From 7e6b57ec21f8ee3abb048e7ec6e136f62a4cb893 Mon Sep 17 00:00:00 2001 From: Vasilev Dmitrii Date: Sat, 8 Aug 2026 01:05:24 +0700 Subject: [PATCH] test: CI quantifies 'size costs TIME (microcode steps), not AREA' The emit-bitexact gate now prints, per topology, the microcode step count next to the one-shared-multiplier datapath invariant: (2,2,1)=32 steps -> (2,4,2)=88 -> deep [3,4,4,2,1]=216, while the synth area report shows cells stay ~constant (13945 -> 17468). So the whitepaper's headline claim -- network size costs TIME (microcode steps), not AREA (one shared multiply/add) -- is measured on every PR, not just asserted in prose. The step count also predicts on-silicon timing-marginality (more steps per frame = more chances for a glitch on the timing-relaxed shared-core path), tying the CI metric to the silicon reality from cycles 86-89. Also added [N steps / N regs] to each per-topology bit-exact OK line. Refs #1764 Co-Authored-By: Claude Opus 4.8 --- docs/NOW.md | 8 +++++++- tools/verify_emit_bitexact.py | 11 ++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/docs/NOW.md b/docs/NOW.md index 2d73f509e..b5706b0dc 100644 --- a/docs/NOW.md +++ b/docs/NOW.md @@ -1,7 +1,13 @@ -# NOW — feat: emit_verilog custom init -> GENERATED trainer TRAINS XOR ON SILICON (2026-08-08) +# NOW — test: CI quantifies "size costs TIME (steps), not AREA" (2026-08-08) Last updated: 2026-08-08 +## test: the emit gate now reports microcode step count per topology (Refs #1764) + +- Quantified the whitepaper's headline claim IN CI. The emit-bitexact gate now prints, per topology, the microcode STEP count next to the one-shared-multiplier datapath invariant: (2,2,1)=32 steps -> (2,4,2)=88 -> deep [3,4,4,2,1]=216 steps, while the synth area report shows cell counts stay ~constant (13945 -> 17468). So "network size costs TIME (microcode steps), not AREA (one shared multiply/add)" is now measured on every PR, not just asserted in prose +- Bonus: the step count also PREDICTS on-silicon timing-marginality -- more steps per frame = more chances for a glitch on the timing-relaxed shared-core path (why the generated trainer with trainable biases, 32+ steps, needed more seed-search than a leaner design). This ties the CI metric to the silicon reality found in cycles 86-89 +- Also added [N steps / N regs] to each per-topology bit-exact OK line. Tool-only; Refs #1764 + ## feat: emit_verilog `init=` + closed the verified-generator -> hardware loop (Refs #1764) - `emit_verilog` now takes an optional `init` dict (default None) that overrides the random weight init. With an XOR near-solution init, the CI-verified generator emits a microsequencer that trains XOR (29/30 epochs in the model) diff --git a/tools/verify_emit_bitexact.py b/tools/verify_emit_bitexact.py index 5811a25ef..2d3d8dbed 100644 --- a/tools/verify_emit_bitexact.py +++ b/tools/verify_emit_bitexact.py @@ -132,7 +132,8 @@ def check(g, arch, workdir): if mism: print(f"FAIL {arch}: {len(mism)}/{len(py)}; first step {mism[0][0]} py={mism[0][1]} rtl={mism[0][2]}") return False - print(f"OK {arch}: RTL == model BIT-EXACT over {len(py)} training steps, all {n_out} output(s) (final yout={py[-1]})") + print(f"OK {arch}: RTL == model BIT-EXACT over {len(py)} training steps, all {n_out} output(s) " + f"[{len(steps)} microcode steps / {len(reg)} regs] (final yout={py[-1]})") return True @@ -198,6 +199,14 @@ def main(): print("--- datapath invariant (one shared smul + one shared sadd) ---") ok = all(datapath_check(g, a) for a in ARCHS) print("ALL ONE-MULTIPLIER" if ok else "DATAPATH FAIL") + if ok: + # quantify the core claim: bigger nets grow the microcode (TIME), not the + # one-shared-multiplier datapath (AREA). (Step count also predicts on-silicon + # timing-marginality: more steps per frame -> more chances for a glitch.) + print("--- size costs TIME (microcode steps), not AREA (1 shared multiplier) ---") + for a in ARCHS: + reg2, steps2 = (g.gen_deep(a) if isinstance(a, list) else g.gen(*a)) + print(f" {str(a):<16} {len(steps2):>4} steps {len(reg2):>3} regs -- same 1-smul+1-sadd datapath") if ok and shutil.which("yosys"): print("--- synthesizability + area (yosys synth_xilinx) ---") results = [synth_check(g, a, wd) for a in SYNTH_ARCHS]