From e6341a7d7a7826b0146cd5c10545b35221486a58 Mon Sep 17 00:00:00 2001 From: Vasilev Dmitrii Date: Sat, 8 Aug 2026 01:50:27 +0700 Subject: [PATCH] test: synth gate asserts zero transparent latches in the netlist Motivated by a root-cause hunt for the on-silicon seed-lottery marginality. Finding: the gen-verilog GF-T cores infer dozens of latches during yosys proc (function locals conditionally assigned), but synth_xilinx optimizes them all away -> 0 latch cells in the final netlist. So latches are NOT the marginality cause here (nor setup nor hold -- all three killed board-independently). But a latch that survived synthesis would be a level-sensitive/placement-sensitive silicon-reliability hazard iverilog verification never catches. The synth phase now asserts 0 transparent latch cells (LD*/*LATCH*) and reports '0 latches' per topology -- passes today, catches a future gen-verilog regression that leaves a real latch on silicon. Refs #1764 Co-Authored-By: Claude Opus 4.8 --- docs/NOW.md | 8 +++++++- tools/verify_emit_bitexact.py | 12 +++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/NOW.md b/docs/NOW.md index 23a72e883..5327d705e 100644 --- a/docs/NOW.md +++ b/docs/NOW.md @@ -1,7 +1,13 @@ -# NOW — docs: workshop-grade silicon-training methodology write-up (2026-08-08) +# NOW — test: synth gate asserts ZERO transparent latches (2026-08-08) Last updated: 2026-08-08 +## test: catch gen-verilog latch inference that reaches silicon (Refs #1764) + +- Motivated by a root-cause hunt for the on-silicon seed-lottery marginality. Finding: the gen-verilog GF-T cores (GftSmul/GftSadd) infer dozens of latches during yosys `proc` (function locals conditionally assigned), but `synth_xilinx` optimizes them ALL away -> the final netlist has 0 latch cells. So latches are NOT the marginality cause here (nor were setup or hold -- all three hypotheses killed board-independently). But a latch that SURVIVED synthesis would be a level-sensitive / placement-sensitive silicon-reliability hazard that iverilog verification never catches +- Added a permanent guard: the synth phase now asserts **0 transparent latch cells** in the synthesized netlist (LD*/`*LATCH*`), and reports "0 latches" per topology. Passes today; catches a future gen-verilog regression that leaves a real latch on silicon +- Tool-only; still ALL SYNTHESIZE. Refs #1764 + ## docs: reproducible methodology paper for on-chip training (Refs #1764) - New `docs/SILICON_TRAINING_METHODOLOGY.md`: a workshop-grade write-up of the full result -- a NN training loop written as a .t27 spec, compiled by t27c, verified bit-exact across FOUR targets (Verilog/C/Rust/model), and trained on a real Artix-7 through a fully open toolchain (yosys->nextpnr-xilinx->prjxray, native macOS arm64, no Vivado/Docker) diff --git a/tools/verify_emit_bitexact.py b/tools/verify_emit_bitexact.py index 2d3d8dbed..376139817 100644 --- a/tools/verify_emit_bitexact.py +++ b/tools/verify_emit_bitexact.py @@ -176,7 +176,17 @@ def synth_check(g, arch, workdir): return False ff = sum(int(n) for n, _ in re.findall(r"(\d+)\s+(FD\w+)", log)) lut = sum(int(n) for n, _ in re.findall(r"(\d+)\s+(LUT\w*)", log)) - extra = f" ({ff} FF + {lut} LUT)" if ff and lut else "" + # ZERO transparent latches: gen-verilog function locals can infer latches + # (yosys warns), and synth_xilinx normally optimizes them back to combinational + # (0 in the final netlist). A latch that SURVIVES to silicon is level-sensitive / + # placement-sensitive -- a real reliability hazard that iverilog verification never + # catches. Assert the synthesized netlist has none. + latch = sum(int(n) for n, _ in re.findall(r"(\d+)\s+(LD\w*|\S*LATCH\w*)", log)) + if latch: + print(f"FAIL {arch}: {latch} transparent latch cells in the synthesized netlist " + f"(silicon-reliability hazard; make the gen-verilog function locals fully assigned)") + return False + extra = f" ({ff} FF + {lut} LUT, 0 latches)" if ff and lut else "" print(f"OK {arch}: yosys synth_xilinx -> {total} cells{extra} (maps to real hardware)") return {"arch": str(arch), "cells": total, "ff": ff, "lut": lut}