|
| 1 | +# Wave Loop 486 Plan — Variant B (default) |
| 2 | + |
| 3 | +**Date:** 2026-07-07 |
| 4 | +**Anchor:** φ² + φ⁻² = 3 | TRINITY |
| 5 | +**Branch:** `wave-loop-486` |
| 6 | +**Issue:** #1456 (to be opened) |
| 7 | + |
| 8 | +## Goal |
| 9 | + |
| 10 | +After W485 closed the next soft-failure classes, W486 continues the Icarus/Verilog |
| 11 | +backend hardening on the remaining reachable gaps: |
| 12 | + |
| 13 | +1. **Bench-local fixed-size arrays crossing function boundaries.** |
| 14 | + A bench declares `let data : [4]u32 = [...];` and calls `fn f(a: [4]u32)`. |
| 15 | + The array-parameter binding pass currently rejects this because bench-local |
| 16 | + arrays are neither module-level consts nor function-local arrays. |
| 17 | +2. **Imported namespace helper erasure.** |
| 18 | + Namespace-qualified helper functions (e.g., `module::helper`) used only in |
| 19 | + host-side contexts are currently emitted as sized-zero placeholders. Extend |
| 20 | + W485 host-only detection to skip them entirely when they are dead to |
| 21 | + synthesizable contexts. |
| 22 | +3. **Module-scope wildcard `_` bindings with array literal initializers.** |
| 23 | + Where the parser already accepts `let _ = [N]T{...};` at module scope, ensure |
| 24 | + the backend does not emit a named `_` identifier. Full struct-literal |
| 25 | + wildcard support is parser-blocked and remains for a future wave. |
| 26 | + |
| 27 | +## Decomposition |
| 28 | + |
| 29 | +### Subtask 1 — Bench-local arrays as array-parameter arguments |
| 30 | + |
| 31 | +**Owner:** backend (`bootstrap/src/compiler.rs`) |
| 32 | + |
| 33 | +1. Pre-collect bench-local array names per bench before the array-parameter |
| 34 | + binding pass. |
| 35 | +2. Change the call-site tuple from `(&Node, Option<&Node>)` to |
| 36 | + `(&Node, Option<&Node>, Option<String>)` where the third element is the |
| 37 | + containing bench name for top-level bench-block calls. |
| 38 | +3. In the signature builder, when a call is inside a bench block and an array |
| 39 | + argument identifier matches that bench's local array set, push `"__local__"` |
| 40 | + instead of the raw name. |
| 41 | +4. The existing local-packed array-parameter path will then: |
| 42 | + - clone the callee with a packed-vector input, |
| 43 | + - pack the hoisted bench-local registers at the call site, and |
| 44 | + - slice the packed vector inside the function body. |
| 45 | +5. Add witness spec `specs/scratch/w486_bench_array_param.t27`. |
| 46 | + |
| 47 | +### Subtask 2 — Namespace-qualified helper erasure |
| 48 | + |
| 49 | +**Owner:** backend (`bootstrap/src/compiler.rs`) |
| 50 | + |
| 51 | +1. In the host-only pre-pass, also collect all imported namespace-qualified |
| 52 | + functions that are referenced in the current module and determine which are |
| 53 | + used only in non-Verilog contexts (invariants, host-only functions, or |
| 54 | + wildcard statements). |
| 55 | +2. Add a map `host_only_namespace_calls: HashSet<String>` of qualified names |
| 56 | + that should be skipped. |
| 57 | +3. In `gen_verilog_expr` `ExprCall`, treat qualified names in this set like |
| 58 | + unqualified host-only functions: statement-context comment no-op, |
| 59 | + expression-context sized-zero placeholder. |
| 60 | +4. Add a witness spec that imports a helper module and uses it only in an |
| 61 | + invariant or wildcard statement. |
| 62 | + |
| 63 | +### Subtask 3 — Module-scope wildcard array literals |
| 64 | + |
| 65 | +**Owner:** backend (`bootstrap/src/compiler.rs`) |
| 66 | + |
| 67 | +1. In `gen_verilog_const`, when `node.name == "_"` and the initializer is an |
| 68 | + `ExprArrayLiteral` or `ExprIdentifier` referring to a module-level array, |
| 69 | + emit an anonymous packed temporary or memory (matching the function-scope |
| 70 | + wildcard logic) instead of discarding it with a comment. |
| 71 | +2. Keep the existing comment-only path for host-only/namespace calls. |
| 72 | +3. Add a regression witness if the parser accepts the construct; otherwise |
| 73 | + document the parser limitation in the close-out report. |
| 74 | + |
| 75 | +### Subtask 4 — Global reseal and verification |
| 76 | + |
| 77 | +1. Run `./scripts/tri test`. |
| 78 | +2. Reseal if needed. |
| 79 | +3. Run `cargo test -p t27c --bin t27c`. |
| 80 | +4. Confirm zero `UNSUPPORTED_ICARUS` placeholders remain. |
| 81 | + |
| 82 | +## Acceptance criteria |
| 83 | + |
| 84 | +- [ ] `specs/scratch/w486_bench_array_param.t27` parses, typechecks, generates |
| 85 | + Verilog, and passes yosys + Icarus smoke. |
| 86 | +- [ ] `./scripts/tri test` reports 661 / 661 non-smoke PASS, 141 / 141 yosys |
| 87 | + smoke PASS, 141 / 141 Icarus smoke PASS, 0 documented baseline failures. |
| 88 | +- [ ] 661 / 661 seal matches. |
| 89 | +- [ ] `cargo test -p t27c --bin t27c` 1525 / 0 / 2. |
| 90 | +- [ ] Zero `UNSUPPORTED_ICARUS` placeholders across all specs. |
| 91 | + |
| 92 | +## Literature context |
| 93 | + |
| 94 | +- **Cambridge VFE synthesizable Verilog subset (V0).** Direct binding of |
| 95 | + module-level memories to function parameters is synthesizable; the backend |
| 96 | + already does this for module const arrays. Bench-local arrays are hoisted to |
| 97 | + module scope, so the same binding mechanism applies once the pre-pass knows |
| 98 | + their names. |
| 99 | +- **FIRRTL/Chisel property types.** Namespace-qualified helpers are analogous to |
| 100 | + non-synthesizable property methods; erasing them before Verilog emission is |
| 101 | + consistent with treating strings and dynamic methods as host-only. |
| 102 | + |
| 103 | +## References |
| 104 | + |
| 105 | +- W485 close-out: `docs/reports/WAVE_LOOP_485_CLOSEOUT.md` |
| 106 | +- W486 cooperation variants: `docs/reports/FPGA_LOOP_COOPERATION_W486_2026-07-07.md` |
| 107 | +- Icarus Verilog quirks: https://steveicarus.github.io/iverilog/usage/icarus_verilog_quirks.html |
| 108 | +- Cambridge VFE V0 paper: https://www.cl.cam.ac.uk/~djg11/pubs/synthesizable_verilog_syntax_and_semantics.pdf |
| 109 | +- FIRRTL spec: https://github.com/chipsalliance/firrtl-spec/blob/main/spec.md |
| 110 | + |
| 111 | +*φ² + φ⁻² = 3 | TRINITY* |
0 commit comments