Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion docs/NOW.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# NOW — docs: a slower clock is not the fix; pipelining is (2026-08-08)
# NOW — docs: localized the shared-core deep path (GftSadd=54, GftSmul=44) (2026-08-08)

Last updated: 2026-08-08

## docs: localized the shared-core critical depth — pipeline the normalize/round cascade, not the multiplier (Refs #1764)

- Measured where the deep combinational path actually is, so the pipeline cut lands in the right place. `GftSmul` is purely combinational (`assign result = smul(a,b)`; clk/en/ready unused → no read-before-ready bug). Yosys `ltp` puts the shared-core critical depth at `GftSadd` = 54 and `GftSmul` = 44
- The depth is NOT the multiplier width: `magmul`'s `*` lowers to a 32-iteration shift-add, but operands are `512+mant ∈ [512,1023]` (10-bit), so yosys already prunes the dead upper iterations — hand-narrowing the loop to 10 leaves depth unchanged (44→45) and area flat. Tested this BEFORE touching the verified spec (observe-before-mutate); narrowing the multiply is a dead end
- The real depth is the dependent normalize/round cascade: `magsub`'s 4-stage priority-shift + `<<14` fixed-point + RNE in `GftSadd`, and `magmul`'s post-product RNE carry in `GftSmul`. Concrete pipeline cut: split each cascade into TWO registered stages (~27 / ~22 deep), which both halves the path and resynchronises it (kills the placement hazard); the microsequencer then waits a fixed 2-cycle latency instead of a settle counter
- Reinforces why neither slow-clock nor path-shortening fixes it: the ~47 ns nominal path is already ~100× under the µs settle window, so the glitch is a placement hazard invisible to static timing — only a mid-cascade register addresses it. Documented in `docs/SILICON_TRAINING_METHODOLOGY.md`. Docs only. Refs #1764

## 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
Expand Down
17 changes: 17 additions & 0 deletions docs/SILICON_TRAINING_METHODOLOGY.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,23 @@ no Docker, native macOS arm64.
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).
- **Where the depth actually is (measured, so we pipeline the right place).** `GftSmul`
is purely combinational (`assign result = smul(a,b)`; the `clk`/`en`/`ready` ports are
unused, so there is no read-before-ready bug). Yosys `ltp` (longest topological path)
puts the shared-core critical depth at **`GftSadd` = 54** and **`GftSmul` = 44**. The
depth is *not* the multiplier width: the `*` in `magmul` lowers to a 32-iteration
shift-add, but its operands are `512+mant ∈ [512,1023]` (10-bit), so yosys prunes the
dead upper iterations — hand-narrowing the loop to 10 leaves the depth unchanged (44 →
45) and the area flat, so **narrowing the multiply is a dead end** (tested before
touching the verified spec). The real depth is the *dependent normalize/round cascade*:
`magsub`'s 4-stage priority-shift + `<<14` fixed-point + round-to-nearest-even in
`GftSadd`, and `magmul`'s post-product RNE carry in `GftSmul`. So the pipeline cut is
concrete: split each of those cascades into **two registered stages** (~27 and ~22 deep),
which both halves the path *and* resynchronises it — the microsequencer then waits the
fixed 2-cycle latency instead of a `settle` counter. Note the ~47 ns nominal path is
already ~100× under the µs settle window, which is why the glitch is a *placement hazard*
a static-timing fix cannot see, and only a mid-cascade register (resynchronisation)
addresses.

## Reproducibility

Expand Down
Loading