Repository navigation
gen-verilog: an entry parameter named clk/rst_n/en is declared once; a void body's last call stays a statement (Closes #5649, Closes #5650, Closes #5651) - #8844
Conversation
…declared once (Closes gHashTag#5649) A parameter of `fn on_comb` / `fn on_clock` named like a boilerplate header port was declared a second time, and iverilog refused the module ("'clk' has already been declared in this scope"). Five corpus specs on master 295b2c5: d_bank13_test, d_direct, led_simple_test, led_test_inv (`on_comb(clk: bool)`) and dsp_probe (`on_clock(cfgmclk, rst_n, en)`). - The decision is specs/compiler/verilog_entry_port_collision.t27 (7 tests), lowered by `t27c gen-rust` to bootstrap/gen/rust/compiler/ and mounted by #[path]. A 1-bit unsigned parameter IS the boilerplate port: the header declares it once and every use keeps the name. A wider or signed one refuses the entry point, in the file and on stderr, as W699 does for an unsized parameter; it is never narrowed. - compiler.rs prints it. The W649 `declares` closure moves up so the parameter loop can read it. FROZEN_HASH updated. - Verilog output changed for 5 of 2227 .t27 files, exactly those five; all five now elaborate under iverilog -g2012 (each failed before). Resealed gen_hash_verilog for the two sealed ones (dsp_probe, led_simple_test) and sealed the new spec, with this tree's t27c. - bootstrap/tests/verilog_entry_port_collision.rs: 7 tests, including the five corpus specs, a refused u8 `clk`, an unchanged non-colliding header, and the generated copy matching gen-rust.
…ent; both rules within Only t27 (Closes gHashTag#5651, Closes gHashTag#5649) gHashTag#5651: gen_verilog_fn_body lowered the final bare expression of a body to `<fn> = <expr>;` (t27#1948) unless the return type was spelled "void". A fn with no return type is a `task` (W705), so `fn reset() { ...; tick(); }` ended in `reset = tick(1'b0);`, and gen_verilog_clocked_fn never set the return type it was judged by, so a void `on_clock` ended in `on_clock <= f(d);`. - The decision is specs/compiler/verilog_void_tail.t27 (4 tests), lowered by `t27c gen-rust` to bootstrap/gen/rust/compiler/ and mounted by #[path]. Both tail sites (the bare tail and the final if/else) read it, so they cannot disagree. on_clock sets its own return type and clears it on exit. - Verilog output changed for 46 of 2227 .t27 files, 88 lines, each exactly `<name> = <expr>;` -> `<expr>;` inside a task. iverilog -g2012 accepts 23 of them now (0 before): the 22 specs/fpga/testbench/*_tb.t27 and specs/tri/t27b/conformance/value_ignored.t27; no file regressed. gHashTag#5649 rework for the Only-t27 gate (owner rules 2026-10-05 and 2026-10-09): - bootstrap/tests/verilog_entry_port_collision.rs is removed: a new hand-written .rs is denied. The rule stays in specs/compiler/verilog_entry_port_collision.t27 and its tests; the output is pinned by the gen_hash_verilog seals of the specs it changes. - compiler.rs reads the rule through one closure; the W699 refusal comment names the collision instead of "no derivable width". compiler.rs is +25/-11, FROZEN_HASH updated, paid for by deleting scripts/gen_w369.py (a one-shot wave-369 generator nothing runs), so hand-written foreign lines shrink. gHashTag#5650's shape gets a fixture, specs/compiler/verilog_on_comb_zero_arg.t27, whose seal pins `assign result = on_comb(1'b0);` (sealed in a later commit).
's fixture with this tree's t27c (Closes gHashTag#5650, Closes gHashTag#5649, Closes gHashTag#5651) Sealed with t27c built from f226c8d (this branch merged with master d01d772). - 44 sealed specs change Verilog output (5 for gHashTag#5649, 46 files / 41 sealed specs for gHashTag#5651, minus the unsealed ones). Each verified MATCH with a master-tip t27c before, and only gen_hash_verilog moves now. Forced seals keep the same failing tests; the primary seal files move to schema 2 as `seal --save` writes it. Every one verifies MATCH with this tree's t27c. - New: compiler_VerilogVoidTail.json, compiler_VerilogOnCombZeroArg.json; compiler_VerilogEntryPortCollision.json resealed. gHashTag#5650's fixture pins `input _unused;` and `assign result = on_comb(1'b0);` (fixed by gHashTag#5955); d_full_path / d_static_one cannot be sealed: module trinity_top already owns openxc7-synth_trinity_top.json (gHashTag#8540). - docs/reports/t27b_expectations.json: specs/compiler/ verilog_entry_port_collision.t27 is `pass`, as the t27b native ratchet measured it on this PR (run 38092422487: UNLISTED, reference pass, t27b pass).
…oses gHashTag#5650, Closes gHashTag#5651) The t27b native ratchet on aca8a31 (run 38094798157) reported both UNLISTED with the reference passing and t27b passing: specs/compiler/verilog_on_comb_zero_arg.t27 and specs/compiler/verilog_void_tail.t27. Listed in sorted order.
|
Updated 2026-10-11 for head What changed since
Local checks with this tree's CI on head
Status: mergeable at Dmitrii Fedorov (@dmitrii-f-t27) |
Closes #5649
Closes #5650
Closes #5651
Description
Three
t27c gen-verilogdefects that made iverilog refuse generated modules.on_comb/on_clockparameter named like a header port (clk,rst_n,en) was declared a second time. Five corpus specs:d_bank13_test,d_direct,led_simple_test,led_test_inv(fn on_comb(clk: bool)),dsp_probe(fn on_clock(cfgmclk: bool, rst_n: bool, en: bool)).<fn> = <expr>;:fn reset() { ...; tick(); }becamereset = tick(1'b0);insidetask reset, and a voidon_clockbecameon_clock <= f(d);. The predicate tested only the spelling"void", andgen_verilog_clocked_fnnever set the return type it was judged by.assign result = on_comb();without the W530 placeholder argument #5650 (assign result = on_comb();) was already fixed on master by fix(gen-verilog): size struct and uN entry ports by one rule (#5904) #5955 (for gen-verilog refuses an on_comb over a struct or u1 although its own functions lower both -- ternary_mac stays at 0 cells #5904). This PR adds the regression pin the issue asks for.Spec
The decisions live in
.t27, lowered byt27c gen-rusttobootstrap/gen/rust/compiler/and mounted by#[path](theverilog_aos_memory.t27pattern, #8151):specs/compiler/verilog_entry_port_collision.t27(7 tests): a 1-bit unsigned parameter IS the header port and is declared once; a wider or signed one refuses the entry point (W699 path, file and stderr), never narrowed; a non-colliding parameter keeps its own port.specs/compiler/verilog_void_tail.t27(4 tests): only a function whose return type is written and is notvoidgets the implicit return. Both tail sites (bare tail, final if/else) read it;on_clocksets its own return type and clears it on exit.specs/compiler/verilog_on_comb_zero_arg.t27(1 test): a fixture withfn on_comb() -> bool; its seal pinsassign result = on_comb(1'b0);. The two corpus specs of gen-verilog: zero-argument on_comb is driven asassign result = on_comb();without the W530 placeholder argument #5650 cannot be sealed: their module nametrinity_topalready owns the seal file in that directory (seal store: two specs derive one seal file name, and seal --save overwrites the other spec's seal #8540).Only t27 (owner rules 2026-10-05 and 2026-10-09)
The issues asked for new
bootstrap/tests/*.rsregression tests. A new hand-written.rsfile is now denied, so the regression guards are the three specs and the resealedgen_hash_verilogof every sealed spec whose output changed (the suite's seal-verify phase reports any drift).compiler.rsis +25/-11 andFROZEN_HASH1/1; paid for by deletingscripts/gen_w369.py(a one-shot wave-369 generator nothing runs, as #8617 and #8667 did withgen_w378.py/gen_w379.py). Localown_language.ccheck_allandcheck_budget: both 0.Measured (master tip vs this branch, merged with master d01d772)
gen-verilogwith a master-tipt27cand with this tree'st27c: 51 of 2230.t27files change. 5 lose exactly the duplicated header line(s) (gen-verilog: an entry-point parameter named clk/rst_n/en is declared twice in the module header #5649); 46 change 88 lines, each exactly<name> = <expr>;-><expr>;(gen-verilog: the tail-expression rule turns the last call in a void fn or on_clock into an assignment to the fn's own name #5651). Nothing else changes; exit codes and stderr are identical.iverilog -g2012: the 5 gen-verilog: an entry-point parameter named clk/rst_n/en is declared twice in the module header #5649 specs fail before and pass after; of the 46 gen-verilog: the tail-expression rule turns the last call in a void fn or on_clock into an assignment to the fn's own name #5651 files, 0 passed before and 23 pass after (the 22specs/fpga/testbench/*_tb.t27andspecs/tri/t27b/conformance/value_ignored.t27). No file regresses.t27c: gen-verilog: an entry-point parameter named clk/rst_n/en is declared twice in the module header #5649 all 10 hold (clkdeclared 1 time in d_bank13_test / led_simple_test / led_test_inv,rst_n|en2 and duplicates 0 in dsp_probe,cfgmclk1,assign result = on_comb(clk);1, ternary_node 8 inputs, 0 duplicates). gen-verilog: the tail-expression rule turns the last call in a void fn or on_clock into an assignment to the fn's own name #5651:reset = tick0 in bridge_tb, dft_tb, memory_tb, spi_tb, apb_bridge_tb;reset = tick_slow0 in clock_domain_tb; bridge_tbtick(1'b0);7,task reset;1; ternary_mac_synthproduct = __mul_noop(1. The twospecs/fpga/uart.t27criteria no longer apply: fix(fpga): elaboration ratchet green -- uart restored, adapter recorded, ternary_isa a named gap #6686 replaced itson_clockwithon_comb; a voidon_clockending in a call was checked with a scratch spec instead (on_clock <=1 -> 0, iverilog fails -> passes). gen-verilog: zero-argument on_comb is driven asassign result = on_comb();without the W530 placeholder argument #5650:d_full_path/d_static_oneon_comb()0,on_comb(1'b0)1,input _unused;1, ternary_node unchanged.t27cbefore, and are resealed with this tree'st27c(onlygen_hash_verilogchanges; forced seals keep the same failing tests). 3 new specs sealed.t27c test-report: the three specs 7/7, 4/4, 1/1 pass, 0 vacuous (zig 0.16.0).cargo test -p t27cforverilog_struct_entry_ports,verilog_branch_context,on_clock_plain_assign,clocked_counter,duplicate_declarations,behavior_sva_v2: all pass. The 16 scenario tests first written asbootstrap/tests/*.rsalso pass locally; they are not committed (Only t27).t27b_expectations.json:verilog_entry_port_collision.t27listed aspass, as this PR's t27b ratchet measured it (run 38092422487: "the reference passes it ... (t27b pass)").verilog_void_tail.t27andverilog_on_comb_zero_arg.t27likewise, from run 38094798157 on aca8a31.Limits
varof that name is not judged here (no corpus spec has one).return <expr>;written in a void fn (e.g.return undefined;) still becomes<fn> = <expr>;: that is the explicit-return path, not the tail rule, and is out of scope (17 files on master).Dmitrii Fedorov (@dmitrii-f-t27)