Skip to content

Enable -stable-verilog by default; testsuite regen check and regolds - #61

Open
nanavati wants to merge 2 commits into
sv/4-featurefrom
stable-verilog-7
Open

Enable -stable-verilog by default; testsuite regen check and regolds#61
nanavati wants to merge 2 commits into
sv/4-featurefrom
stable-verilog-7

Conversation

@nanavati

@nanavati nanavati commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Enable -stable-verilog by default; testsuite regen check and regolds

Last of the 5-PR series, stacked on the feature PR. One commit: the flip, the enforcement, and the fallout.

The flip

-stable-verilog turns on by default (and becomes visible in -help); -no-stable-verilog restores the historical names and orderings.

Enforcement

check_verilog_regen (unix.exp), applied at the point of generation: bsc_compile_verilog — the choke point every Verilog-compile proc uses — regenerates each .v its compile just produced (read off the compile log, immune to stale files in shared dirs) from the always-written .ba with -c into a scratch dir and byte-compares. The regen runs in a fresh bsc process, which is what makes the check meaningful: a same-process regen would see the same interning history and could not fail for interning-order reasons. Skips: -no-stable-verilog, -elab-only/-no-elab, relocated outputs, -verilog-filter, pending setup_xfail (a result emitted mid-proc would consume the arm meant for the caller's verdict), and it forwards a test's +RTS … -RTS budget to the regen (the normal build bakes -K10m; the perf-blowup designs need their declared caps). 2,934 regen checks per full run, all passing.

Two battery divergence pins prove the flag is not vacuous: under -no-stable-verilog the direct and regenerated .v of the trigger designs MUST diverge.

Regolds (all verified against the final compiler)

  • 8 .v goldens + 1 schedule dump (signal numbering / def order).
  • bsc.options: -help gains the flag line; the -print-flags family (incl. the two messages/flag-test dumps) lists -stable-verilog; print-flags-raw stableVerilog = True.
  • method_conditions/impcondof: minted ___dN names renumber to first-use order. The rest of method_conditions passes unchanged — the COND collapse the flag first exposed is fixed by the joinDefs NoCSE PR below this stack, not regolded away.
  • perf-creg-blowup: CregMemBlowup's stack cap recalibrated to -K40m (>2x the ~18M stable-path peak vs ~6M intern-ordered; constant factor, structurally identical output — 2562 wires / 46848 assigns both ways).

Docs: user guide flag entry; DEVELOP.md -c section and determinism-contract description.

Testing

Full testsuite (fullparallel, SystemC enabled) at this tip: 23,871 PASS / 0 FAIL / 134 XFAIL / 0 XPASS / 0 ERROR, with the regen check active on every Verilog compile. Targeted: method_conditions 152/0, impcondof 194/0, battery 37/0, perf-creg-blowup 9/0, bsc.options 71/0 + messages 41/0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NRVtTNugutAyrTED4qHnrt

The flag flips on (and becomes visible in -help): generated Verilog
is now a pure function of the elaborated design by default, and
-no-stable-verilog restores the historical behavior.

The testsuite enforces the contract at the point of generation: since
a -verilog compile writes the .ba by default, check_verilog_regen
(called from bsc_compile_verilog, so every Verilog-compile proc gets
it) regenerates each .v the compile just produced -- read off the
compile log, so stale files in shared test directories are never
picked up -- from its .ba with the -c codegen mode, and requires a
byte-identical result.  The regeneration runs in a fresh bsc process,
which is what makes the check meaningful: in the process that wrote
the .v every string is already interned, so a same-process regen
would see the same interning history and could not fail for
interning-order reasons.  Skipped when the invocation's options make
the comparison meaningless (-no-stable-verilog, -elab-only/-no-elab,
relocated outputs, -verilog-filter); a test that raises the RTS
limits for its design gets the same budget for the regen (the normal
build bakes -K10m, below the perf-blowup designs' peaks).  Two new
battery designs pin that the flag is not vacuous: under
-no-stable-verilog the direct and regenerated .v of the trigger
designs MUST diverge.

Regolds, all verified against the final compiler:

  * 8 .v goldens and 1 -dschedule golden whose signal numbering or
    def order legitimately changes (bsc.evaluator/undefined Reg3D
    family, scheduler/disjoint, bsc.doc GCD, b262/b293/b302/b378/
    b1354).
  * bsc.options: -help gains the flag line; the -print-flags family
    now lists -stable-verilog (and print-flags-raw stableVerilog =
    True), including the two flag-test dumps under bsc.options/
    messages.
  * method_conditions/impcondof: compiler-minted ___dN names
    renumber to first-use order.  (The rest of method_conditions
    passes unchanged -- the COND collapse the flag first exposed is
    fixed in the joinDefs NoCSE commit, not regolded away.)
  * perf-creg-blowup: CregMemBlowup's stack cap recalibrated to
    -K40m (>2x the ~18M stable-path peak; was 2x the ~6M
    intern-order peak).  Constant factor, structurally identical
    output.

User guide: -stable-verilog documented in the Verilog back-end flags.
DEVELOP.md: the -c section reflects codegen flags coming from the .ba
(with the options pragma applied), and describes the determinism
contract and its testsuite enforcement.

Co-authored-by: Ravi Nanavati <ravi@matx.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NRVtTNugutAyrTED4qHnrt
@nanavati nanavati changed the title -stable-verilog: deterministic Verilog emission, on by default Enable -stable-verilog by default; testsuite regen check and regolds Aug 4, 2026
@nanavati
nanavati changed the base branch from staged-flow/6-portprops-caveat to sv/4-feature August 4, 2026 03:26
nanavati pushed a commit that referenced this pull request Aug 23, 2026
Link-rung instrumentation (task #61): the ir-passes phase is the
dominant slice of a Toooba-scale link (23-25 of ~52 minutes under the
default<O1> size tier) and was a single opaque timer. inkwell exposes
no TimePasses API, so inject LLVM's own -time-passes flag once via
LLVMParseCommandLineOptions when TRS_JIT_TIME_PASSES=1 — the new-PM
StandardInstrumentations honor the cl::opt and print the per-pass
report to stderr. Diagnostic-only, off by default.

Witness: fixture link under the flag prints the timing table
(EarlyCSEPass / InstCombinePass / GVNPass named with times); build
clean; behavior unchanged without the flag.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CerPH99xuDTaGhaBQ3wwqS
Make stableRenumberVProgram cheaper.  The renumbering is unchanged.

  * Walk the module body with explicit per-constructor traversals rather
    than SYB generic ones.  Pruning becomes structural: the walk simply
    never descends into a String, Id or Position, where SYB otherwise
    crosses every character of every identifier and comment.
  * Collect in one walk instead of four: identifier occurrences, foreign
    function names and system task names come back from a single
    traversal as a sum.
  * Pass the collection accumulator explicitly, so every call is
    saturated and each hit is consed exactly once.  Written point-free
    with (.), each node instead allocates a partial application per
    child and a closure per composition.
  * Match a name's family from its tail, rather than reversing the whole
    name and re-splitting it once per family.
  * Key the sets and the rename map on (hash, name), so comparisons
    resolve on the hash instead of a long shared prefix.

Constructors are matched without a wildcard, so a new one -- or a new
field in an existing one -- is a compile error here rather than an
identifier that silently escapes the walk.

Measured on the MatX monorepo, 2371 actions, 1846 of which emit Verilog:

  | Metric                   | Before   | After    |       |
  |--------------------------|----------|----------|-------|
  | verilogDollar allocation | 0.889 TB | 0.020 TB | 45x   |
  | verilogDollar CPU        | 593 s    | 84 s     | -86%  |
  | Whole-build allocation   | 49.40 TB | 48.67 TB | -1.5% |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants