Files
FPGA-Neural/hardware/v2/docs/architecture/activation_fabric_timing.md
T
micheleandClaude Sonnet 5 81a9619214 chore: remove root-level V1 duplicates, superseded by hardware/v1/ freeze
hardware/v1/ was created (dc0b331) as a frozen snapshot of the V1
project that then lived at the repo root (rtl/, sim/, synth/, tools/,
docs/). Root received zero further commits to those files after the
freeze -- confirmed byte-identical to the hardware/v1/ copy for every
file removed here. Root was the "before", hardware/v1/ is the
curated, canonical "after".

Removed (all verified exact-hash duplicates of hardware/v1/ content):
  - rtl/ (20 files, 100% covered by hardware/v1/rtl/)
  - tools/{netasm,pinout,run_regression.py,flash_catalog,validation,
    fpga_benchmark.py} (19 files, 100% covered by hardware/v1/tools/;
    tools/neural_sim/ kept -- unique, post-freeze, no counterpart)
  - sim/*.v (47 testbenches, 100% covered by hardware/v1/sim/; the
    ~38 remaining sim/ entries are compiled binaries and .vcd
    waveform dumps, left as a separate cleanup decision)
  - synth/ecp5/{p2,p4,p8,post_fix_verify} (25 files, exact duplicates
    of hardware/v1/synthesis/; the other ~84 synth/ecp5/* experiment
    build directories are historical artifacts never carried into the
    freeze, left as a separate decision)
  - WORKLOG.md (duplicate of hardware/v1/docs/WORKLOG.md)
  - docs/{FPGA-Neural-Datapatch-Benchmark,FPGA-Neural-Hardware-Design,
    FPGA-NeuralNetwork-Engine}.md, docs/validation/*.md (18 files),
    docs/FPGA-Neural-Datasheet-{EN,IT}.pdf -- all exact duplicates of
    hardware/v1/docs/ content
  - hardware/v1/docs/DatasheetLatex/ (24 files) -- exact duplicate of
    hardware/v2/docs/datasheet/files/docs/datasheet/en/ (discovered
    during this audit; not the same DatasheetLatex already removed
    from hardware/v2/docs/ in an earlier commit)

Moved (genuine, unique, post-freeze V2 content -- not duplicated
anywhere, just living in the wrong/legacy root docs/ location):
  - docs/architecture/*.md -> hardware/v2/docs/architecture/
  - docs/pinouts.md, docs/FPGA_NEURAL_V2_DATASHEET.md,
    docs/FPGA_NEURAL_V2_SCHEMATIC.md,
    docs/FPGA-Neural-V2-Datasheet-EN.pdf -> hardware/v2/docs/

Left untouched (separate decisions, not part of this cleanup):
  - docs/FPGA-Neural-Flash-Subsystem-Verification.md, docs/
    v2-description.md -- orphaned root-only content, no duplicate
    found anywhere, but also not part of the reviewed plan
  - synth/ecp5/* experiment dirs and sim/*_sim + sim/*.vcd build
    artifacts -- not literal duplicates, flagged as candidates for a
    future, separate cleanup pass

Verified no functional breakage: grepped all remaining scripts/docs
for references to every removed path -- only prose/comment mentions
found, no executable imports or build-script paths broken.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2026-09-07 05:30:17 +02:00

93 lines
4.3 KiB
Markdown

# NMS Activation Fill Controller Timing (STEP14 Part B)
Status: fixed, real post-P&R verified, bit-exact, adopted. Full data:
`hardware/v2/reports/step14_activation_timing.csv`. Full narrative:
`hardware/v2/logs/experiments.log` (EXP-0029, 0030, 0031),
`decisions.log` (DEC-0026, DEC-0027).
## B1 — Exact critical path (not assumed)
Mined directly from the real nextpnr-ecp5 P&R report for
`nms_neural_multiprocessor_stream.v` at N_SLOTS=4
(Fmax=55.22 MHz, FAIL @ 80 MHz). Full path, 18.11 ns total (6.25 ns
logic + 11.85 ns routing):
```
SOURCE: u_act_fill.resident_tag[11] (register Q)
-> COMBINATIONAL, chained, NO register in between:
(1) max_n_tiles computation, nms_activation_fill_ctrl.v:92
(N_SLOTS-wide running-max fold, each iteration gated by a
23-bit tag-equality check) -- long CCU2C carry chain
(2) resident_count < max_n_tiles comparison, line 165
(the ST_IDLE refill/continue decision) -- ANOTHER 16-bit
magnitude-comparison carry chain, feeding directly off (1)
in the SAME cycle
(3) into pf_start's own next-state logic
DESTINATION: u_act_fill.pf_addr's clock-enable (CE) pin
```
Two full 16-bit magnitude comparisons sit in **one** combinational
cone across **one** clock edge. This confirms, at the exact RTL-line
level, the failure class DEC-0016/EXP-0022 predicted analytically
("O(N_SLOTS) unpipelined combinational scan feeding directly into a
control decision") — but precisely localizes it to the comparison
logic (lines 92 and 165), *not* the priority-encoder
(`desired_valid`/`desired_x_base`, lines 77-86), which does not appear
in this critical path at all.
## B2 — Scaling behavior
The bottleneck is the `max_n_tiles` running-max fold: an imperative
`for` loop creates a data dependency between iterations (`max_n_tiles`
after iteration *i* depends on iteration *i-1*), which Yosys
synthesizes as a sequentially-chained carry structure — inherently
O(N_SLOTS) deep, not O(log N_SLOTS). At N_SLOTS=4 the chain reached
6.25 ns logic + 11.85 ns routing; at N_SLOTS=8 it doubles again (see
below).
## B3 — Minimum fix (two iterations, evidence-driven)
**v2** (one pipeline stage: register `max_n_tiles` before its use in
the `resident_count` comparison): Fmax 55.22 → 72.78 MHz (+31.8%) —
real improvement, still fails 80 MHz. Re-tracing showed the *remaining*
critical path was entirely inside `max_n_tiles`'s own computation
(now feeding its own register), confirming the fix needed to go one
level deeper.
**v3** (second stage: register each slot's tag-equality/masking result
first — independent per-slot work, no N_SLOTS-dependent chain — *then*
fold the already-registered, already-masked values): Fmax 55.22 →
**106.81 MHz** (+93.4%). **PASSES** 80 MHz with real margin. Resource
cost: LUT4 -5.5%, FF +1.4% (2 added pipeline registers), CCU2C
unchanged.
## B4 — No serialization reintroduced
Verified directly: N_SLOTS=2 bit-exact regression test (D-Stress, real
V1 PSRAM chain) gives **numerically identical** cycle count and
sustained MAC/cycle before and after the fix (185270/185270 cycles,
0.1769/0.1769 MAC/cycle). The 3 total cycles of added latency apply
only to the rare, tile-refill-boundary-only decision — never to the
real-time per-tile consumption path (already fully decoupled by
STEP13's own streaming manager). Higher Fmax, zero throughput cost —
satisfying B4's explicit requirement.
## N=8 (exploratory)
`nms_activation_fill_ctrl_v3.v` at N_SLOTS=8: DSP=64/72 (89%, FEASIBLE),
LUT4=4653, FF=10855 (both comfortably FEASIBLE). **Fmax=52.25 MHz,
FAILS 80 MHz** — the v3 fix's second stage (the max-fold itself) is
still O(N_SLOTS)-deep; at N=8 it is twice as deep as at N=4 and becomes
dominant again. This is expected: v3 shifted the crossover point, it
did not eliminate the underlying dependency. A genuine balanced-tree
reduction (or a pipeline scaling with log₂(N_SLOTS) rather than a flat
2-stage split) would be required for N=8 — not undertaken this round
(N=8 is explicitly exploratory; the limiting resource (Fmax, not
DSP/LUT/FF/BRAM) is precisely identified and quantified, per spec).
## Adoption
`nms_activation_fill_ctrl_v3.v` is adopted as the reference activation
fill controller for N_SLOTS≥4 configurations (DEC-0027). The original
and the insufficient v2 are preserved for reference.