From 6b4fad282b88d7d1f880447fe2ded7bab4529c30 Mon Sep 17 00:00:00 2001 From: Vasilev Dmitrii Date: Sun, 9 Aug 2026 04:49:22 +0700 Subject: [PATCH] fix(gen-verilog): declare the tuple-destructure temp in test blocks Refs #1948 A test-block `let (a, b) = call()` slices a packed temp (__tup_l{line}), but that temp and its element regs are declared only in emit_local's Decl phase -- the testbench Init-only path skipped it, so the temp was referenced undeclared ("Could not find variable __tup_l242"). The top-of-block declaration pass now emits the tuple-destructure declarations for empty-name/extra_field locals. tri-net corpus: icarus 96 -> 97 (cross_layer_optimizer). bridge.v regenerated; unit suite at the single pre-existing red. FROZEN_HASH resealed. Co-Authored-By: Claude Fable 5 --- NOW.md | 7 +++++++ bootstrap/src/compiler.rs | 11 +++++++++++ bootstrap/stage0/FROZEN_HASH | 2 +- docs/NOW.md | 7 +++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/NOW.md b/NOW.md index d0bf13f07..dd653a317 100644 --- a/NOW.md +++ b/NOW.md @@ -2,6 +2,13 @@ Last updated: 2026-08-08 +## gen-verilog: tuple-destructure temp declared in test blocks (Refs #1948) + +- A test-block `let (a, b) = call()` slices a packed temp `__tup_l{line}`, but that temp (and the element regs) are declared only in emit_local's Decl phase, which the TB Init-only path skips -- the temp was referenced undeclared ("Could not find variable __tup_l242") +- The top-of-block declaration pass now emits the tuple-destructure decls (emit_local Decl) for empty-name/extra_field locals +- tri-net corpus: icarus 96 -> 97 (cross_layer_optimizer) +- FROZEN_HASH resealed + ## gen-verilog: `_` discard in tuple destructure gets a throwaway reg (Refs #1948) - `(link1, _) = create_2node_mesh(50)` emitted `{_, link1} = call()` -- Verilog has no `_` wildcard, so iverilog could not find the variable diff --git a/bootstrap/src/compiler.rs b/bootstrap/src/compiler.rs index 4ac4b6dee..6d875df46 100644 --- a/bootstrap/src/compiler.rs +++ b/bootstrap/src/compiler.rs @@ -8479,6 +8479,17 @@ impl VerilogCodegen { self.write_indent(); self.emit_local(child, LocalEmitPhase::Decl); } + // Tuple-destructure local `let (a, b) = call()`: the packed temp + // (__tup_l{line}) and the element regs are declared only in the + // Decl phase, which the TB Init-only path skips -- so the temp + // was referenced undeclared ("Could not find variable + // __tup_l242"). Declare them at the top of the block here. + if child.kind == NodeKind::StmtLocal + && child.name.is_empty() + && !child.extra_field.is_empty() + { + self.emit_local(child, LocalEmitPhase::Decl); + } // Pre-declare a probe for every assert_eq in the block. let stmt = if child.kind == NodeKind::StmtExpr { child.children.first() diff --git a/bootstrap/stage0/FROZEN_HASH b/bootstrap/stage0/FROZEN_HASH index 43c3dc2c4..3cd74de07 100644 --- a/bootstrap/stage0/FROZEN_HASH +++ b/bootstrap/stage0/FROZEN_HASH @@ -1 +1 @@ -fbbe3e1568e833b001e94be2d4cb612011d41d1e38fb5b57bca42e91ca510fb4 +df2991ce372f7f3ecb9de196116662a7a40f2490cdeeb75ca77b2df18dfbb5fd diff --git a/docs/NOW.md b/docs/NOW.md index 107fef24a..9b6d91a20 100644 --- a/docs/NOW.md +++ b/docs/NOW.md @@ -2,6 +2,13 @@ Last updated: 2026-08-08 +## gen-verilog: tuple-destructure temp declared in test blocks (Refs #1948) + +- A test-block `let (a, b) = call()` slices a packed temp `__tup_l{line}`, but that temp (and the element regs) are declared only in emit_local's Decl phase, which the TB Init-only path skips -- the temp was referenced undeclared ("Could not find variable __tup_l242") +- The top-of-block declaration pass now emits the tuple-destructure decls (emit_local Decl) for empty-name/extra_field locals +- tri-net corpus: icarus 96 -> 97 (cross_layer_optimizer) +- FROZEN_HASH resealed + ## gen-verilog: `_` discard in tuple destructure gets a throwaway reg (Refs #1948) - `(link1, _) = create_2node_mesh(50)` emitted `{_, link1} = call()` -- Verilog has no `_` wildcard, so iverilog could not find the variable