diff --git a/docs/NOW.md b/docs/NOW.md index db7fe1967..2b27acaa2 100644 --- a/docs/NOW.md +++ b/docs/NOW.md @@ -1,7 +1,14 @@ -# NOW — docs: seed-lottery marginality is placement-level, Heisenbug-confirmed (2026-08-08) +# NOW — docs: a slower clock is not the fix; pipelining is (2026-08-08) Last updated: 2026-08-08 +## docs: a slower clock cannot fix the seed-lottery — pipelining the shared core is the only structural fix (Refs #1764) + +- Investigated the "just run the deep path on a slower clock" remedy and ruled it out on TWO independent grounds. (a) NOT buildable on openXC7: a fabric-counter divided clock needs a clock buffer, and nextpnr-xilinx cannot place one driven from fabric — both `BUFG` and `BUFR` fed by a divider bit fail with "Unable to find legal placement" (7-series clock-buffer inputs come from clock-capable pins / the CMT, not general routing). Only an MMCM/PLL could make a real divided clock +- (b) Even if buildable, it would not help: a divided clock with the same microcode `settle` gives the SAME real settle window (~µs) as the working `/N` clock-enable, and more settle does not cure the glitch — silicon behaviour is non-monotonic in settle (`/128` glitched worse than `/64`, cycle 93). The fault is a placement HAZARD, not a settle shortage +- Also re-confirmed: `create_clock` on the differential `clk_p` port does not propagate through `IBUFDS`; the internal clock net defaults to a loose 12 MHz target and always "passes", so `--timing-allow-fail` was effectively a no-op. Constraining `[get_nets clk]` tighter reports the true fmax (~21 MHz) but does not change the silicon hazard +- CONCLUSION (re-prioritises the roadmap): the one viable structural fix is to PIPELINE the shared `GftSmul`/`GftSadd` (a spec-level `on_clock` pipelined multiply/add) so each microcode step reads a registered value and the deep combinational hazard is broken. This is the prerequisite for on-silicon training beyond XOR (seed-search runs out at 62 steps). Documented in `docs/SILICON_TRAINING_METHODOLOGY.md` "Honest limits". Docs only. Refs #1764 + ## docs: record that seed-lottery marginality is a PLACEMENT property, not a register bug (Refs #1764) - Ran the last diagnostic for the on-silicon seed-lottery: on-chip observability. Widened the UART result dump from 4B (y) to 12B `{z1, z0, y}` so a glitching seed would reveal WHICH register diverges first (hidden pre-activations vs output). The instrumented design output ALL-ZERO on every seed tried — adding the probe re-placed the shared core past its (unconstrained) timing edge diff --git a/docs/SILICON_TRAINING_METHODOLOGY.md b/docs/SILICON_TRAINING_METHODOLOGY.md index 0ec562d93..302728855 100644 --- a/docs/SILICON_TRAINING_METHODOLOGY.md +++ b/docs/SILICON_TRAINING_METHODOLOGY.md @@ -78,7 +78,30 @@ no Docker, native macOS arm64. core past its (unconstrained) timing edge. This is a genuine Heisenbug: the deep path is marginal enough that instrumenting it *moves* the result, which is itself the evidence that the fault lives in the timing/placement of the whole path, not in one microcode - step. The fix is a real timing constraint (commercial P&R), not a code change. + step. +- **A slower clock is NOT the fix — on two independent grounds.** The intuitive remedy + ("just run the deep path at a slower clock so it settles") fails twice on this flow. + *(a) It is not buildable.* A fabric-counter divided clock needs a clock buffer, and + nextpnr-xilinx cannot place one driven from fabric: both `BUFG` and `BUFR` fed by a + divider bit fail with *"Unable to find legal placement"* (a 7-series clock buffer input + comes from a clock-capable pin or the CMT, not general routing). Only an MMCM/PLL could + synthesize a real divided clock. *(b) Even if it built, it would not help.* A divided + clock with the same microcode `settle` count delivers the **same real settle window** + (~µs) as the working `/N` clock-enable — no new mechanism. And more settle does not cure + the glitch: the on-silicon behaviour is **non-monotonic in settle** (a `/128` enable + glitched *worse* than `/64`), so the fault is a placement **hazard**, not a shortage of + settle time. Note too that `create_clock` on the differential `clk_p` port does **not** + propagate through the `IBUFDS`; the internal clock net defaults to a loose 12 MHz target + and always "passes", so `--timing-allow-fail` was effectively a no-op — the path was + never actually being closed, just loosely met. Constraining the internal net tighter + reports the true fmax (~21 MHz) but does not change the silicon hazard. +- **Therefore the one viable structural fix is to PIPELINE the shared core** — register + the intermediate stages of `GftSmul`/`GftSadd` (a spec-level `on_clock` pipelined + multiply/add) so every microcode step reads a clean, registered value and the deep + combinational hazard is broken, letting nextpnr close each short stage at the real + 200 MHz. This is a code/spec change, not a clock or constraint change. It is the + prerequisite for training nets larger than XOR on this open flow (where seed-search + runs out — a 62-step net does not stabilise in any seed). ## Reproducibility