Skip to content

fpga-build's yosys loop could never have passed as written, and four emitter bugs hid behind it #2215

Description

@gHashTag

#2214 documented fpga-build.yml red on master since 2026-08-08. Root-caused: as written, its yosys loop could never have passed — and behind it sat four real emitter bugs.

The workflow (two defects in one loop, one in a Rust step)

Measured locally, same loop as CI: 1 of 32 modules passed.

  1. Top derived from the filenamemac.v holds module ZeroDSP_MAC, so hierarchy -top mac fails for 31 of 32. The top is now read from the file itself.
  2. Missing -sv -DSIMULATION — the repo's own convention (suite.rs:859, verify_emit_bitexact.py:184): -sv because the emitter uses SV static casts; -DSIMULATION strips ifndef SIMULATION bench blocks whose $display carries non-constant args synthesis cannot evaluate (mac.v:535).
  3. The fpga-synthesis step calls yosys from Rust (t27c fpga-build --synth-only) with the same missing flags — fixed in both script templates.

Four emitter bugs the fixed loop then exposed

bug symptom fix
escape-before-flattening \cross _data_width — the space terminating an escaped identifier split the flattened name (clock_domain.v:221) escape applied to the flattened name, 2 sites
assertion keywords missing function [31:0] assume; — TOK_ASSUME under -sv (formal.v:187) assert assume cover restrict added to the keyword list
call site unescaped declaration emits \assume but the call emits assume(...) — two different identifiers call site uses the same escape
fn-return lvalue unescaped a Verilog function returns by assigning to its own name: assume = 0; (formal.v:195) both return paths escape

Progression, measured at each step

as written on master:            pass= 1 / 32
+ module name from file:         pass=13 / 32
+ -sv -DSIMULATION:              pass=30 / 32
+ four emitter fixes:            pass=32 / 32

t27c fpga-build --docker false --synth-only — the exact step that failed in CI — now exits 0 locally, producing a 9.4 MB synth.json.

Zero regression, by the repository's own gates

verify_emit_bitexact (Verilog == model, iverilog): ALL SYNTHESIZE, exit 0. verify_exhaustive: 8 primitives, model == C == Rust exhaustively, Verilog agrees everywhere it runs. verify_igla_race: exhaustive ternary_mul intact. check_specs_generate: 768/346, unchanged. M5 ceremony performed for the compiler.rs change.

And the ceiling

Every job in fpga-build.yml (8) and emit-bitexact-gate.yml now carries timeout-minutes: 45 — on 2026-08-18 a hung apt step ran 6h0m16s to the GitHub ceiling and read as a red PR whose own steps were all skipped.

Not fixed here, still open in #2214: fpga-formal's pip install sby (packaging).

Closes #2214

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