Skip to content

fpga-synthesis has never once passed: the SIMULATION guard is inverted, and %%0d is emitted literally #2153

Description

@gHashTag

Every run of fpga-build.yml has failed since the workflow was added on 2026-05-30: 600 runs, 598 failure, 2 cancelled, 0 success, and 184 of 184 on master. The failing job is fpga-synthesis, the failing step is FPGA synthesis (Yosys + JSON netlist), and the log line is the same one every time:

/home/runner/work/t27/t27/build/fpga/generated/mac.v:535: ERROR: Failed to evaluate system task `$display' with non-constant argument at position 2.
##[error]Process completed with exit code 1.

This is a generator defect, not an environment problem. Two independent bugs produce it.

1. The SIMULATION guard is inverted for the synthesis path

bootstrap/src/compiler.rs lines 7276, 7330 and 7352 wrap benchmark blocks in:

`ifndef SIMULATION

ifndef includes the block when the macro is not defined. The only place in the tree that defines it is bootstrap/src/suite.rs:859:

read_verilog -sv -DSIMULATION

The synthesis path does not. bootstrap/src/main.rs:4937 and :4962 emit a bare read_verilog {files}. So benchmark code — including $display with a runtime argument, which Yosys cannot evaluate — is fed to the synthesiser on every single synthesis run, and excluded from the one flow that could tolerate it.

Scale: 121 `ifndef SIMULATION occurrences and zero `ifdef occurrences across the generated tree; 31 generated .v files contain $display. mac.v:535 is not special, it is just the first file Yosys reaches.

Either the guard should be `ifdef SIMULATION, or the synthesis path should define the macro. The two must agree; today they are opposites.

2. %%0d is written to the file literally

compiler.rs:7376:

$display("[BENCH] {} : %%0d cycles", var)

The line is built with format!, where the only escape is {{/}}%% is not an escape and passes through verbatim. The generated file contains %%0d 8 times in mac.v and %0d 0 times. In Verilog %% prints a literal %, so the argument is never consumed by a conversion specifier, which is exactly the shape of thing Yosys objects to.

Verification, not by CI

bootstrap/build.rs compares the SHA-256 of compiler.rs against bootstrap/stage0/FROZEN_HASH, so a fix must re-freeze (./scripts/tri freeze). A fix must also be shown not to move any generated file it does not intend to move — ./scripts/tri diffbin over the corpus, zero regressions as the condition.

yosys is not installable via apt in the sandbox (Unable to locate package yosys); yowasp-yosys from pip is the workaround for reproducing locally.

A separate observation on the gate

t27c synth-readiness reports NOT READY with Parse 31/36 and exits with code 0. A gate that never fails does not gate. Five specs are behind that count and belong to a parser issue, not this one:

  • specs/fpga/boards/arty_a7_integration.t27, specs/fpga/boards/qmtech_a100t_integration.t27, specs/fpga/verification/build_verify.t27Unexpected token in expression: KwInvariant
  • specs/fpga/vcd_conformance_compare.t27, specs/fpga/power_analysis.t27unexpected token after expression statement: Ident

What this is not

Nothing here is measured on hardware. This is a text-generation defect found by reading the generator and the CI log. No claim is made about the netlist that would result once it is fixed, and no claim is made about silicon.

Found while diagnosing the red checks on #2151, where the same failure was shown to reproduce byte-identically on the base commit.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions