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 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.t27 — Unexpected token in expression: KwInvariant
specs/fpga/vcd_conformance_compare.t27, specs/fpga/power_analysis.t27 — unexpected 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.
Every run of
fpga-build.ymlhas failed since the workflow was added on 2026-05-30: 600 runs, 598 failure, 2 cancelled, 0 success, and 184 of 184 onmaster. The failing job isfpga-synthesis, the failing step isFPGA synthesis (Yosys + JSON netlist), and the log line is the same one every time:This is a generator defect, not an environment problem. Two independent bugs produce it.
1. The
SIMULATIONguard is inverted for the synthesis pathbootstrap/src/compiler.rslines 7276, 7330 and 7352 wrap benchmark blocks in:ifndefincludes the block when the macro is not defined. The only place in the tree that defines it isbootstrap/src/suite.rs:859:The synthesis path does not.
bootstrap/src/main.rs:4937and:4962emit a bareread_verilog {files}. So benchmark code — including$displaywith 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 SIMULATIONoccurrences and zero`ifdefoccurrences across the generated tree; 31 generated.vfiles contain$display.mac.v:535is 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.
%%0dis written to the file literallycompiler.rs:7376:The line is built with
format!, where the only escape is{{/}}—%%is not an escape and passes through verbatim. The generated file contains%%0d8 times inmac.vand%0d0 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.rscompares the SHA-256 ofcompiler.rsagainstbootstrap/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 diffbinover the corpus, zero regressions as the condition.yosysis not installable viaaptin the sandbox (Unable to locate package yosys);yowasp-yosysfrom pip is the workaround for reproducing locally.A separate observation on the gate
t27c synth-readinessreportsNOT READYwithParse 31/36and 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.t27—Unexpected token in expression: KwInvariantspecs/fpga/vcd_conformance_compare.t27,specs/fpga/power_analysis.t27—unexpected token after expression statement: IdentWhat 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.