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
92 lines
4.5 KiB
Markdown
92 lines
4.5 KiB
Markdown
# NMS Weight Datapath Scaling (STEP14 Part A)
|
||
|
||
Status: architectural requirement established and proven (simulation),
|
||
**not realizable on real hardware today** (fixed 16-bit physical
|
||
PSRAM). Full data: `hardware/v2/reports/step14_weight_scaling.csv`.
|
||
Full narrative: `hardware/v2/logs/experiments.log` (EXP-0032, EXP-0033),
|
||
`decisions.log` (DEC-0028).
|
||
|
||
## Question answered
|
||
|
||
*At what weight-path width does the processor stop being fundamentally
|
||
starved by weight delivery?* **64 bits** — exactly `P_IN × DATA_WIDTH`
|
||
(8 × 8). Proven by direct cycle-exact simulation, not assumed.
|
||
|
||
## What was built
|
||
|
||
`weight_prefetch_engine_wide.v` — a parameterized (`MEM_DATA_WIDTH`)
|
||
generalization of the real `weight_prefetch_engine.v`'s continuous
|
||
cross-tile-boundary streaming design, simulation-only/exploratory
|
||
(same status as `ideal_memory_model.v`). `WORDS_PER_TILE =
|
||
ceil(P_IN*DATA_WIDTH / MEM_DATA_WIDTH)`, clamped to a minimum of 1.
|
||
`nms_memory_manager_stream_wide.v` pairs it with STEP13's own streaming
|
||
memory manager unchanged (A2's requirement), on a *separate* logical
|
||
wide port from the real 16-bit result-write-back port.
|
||
|
||
A real bug was found and fixed during development: address stepping
|
||
initially used `WORDS_PER_TILE × BYTES_PER_WORD` as the inter-tile
|
||
byte stride, which over-counts whenever the bus is wider than one full
|
||
tile (the 128-bit case, `WORDS_PER_TILE=1` but `BYTES_PER_WORD=16`
|
||
while the tile itself is only 8 bytes) — this skips over the next
|
||
tile's actual data in the packed backing store. Fixed by defining
|
||
`TILE_BYTES = TILE_BITS/8` as the canonical, width-independent stride.
|
||
|
||
## Results (bit-exact + ideal-memory cycle count)
|
||
|
||
| Width | Words/tile | Steady-state cycles/tile | 16-tile job total |
|
||
|---|---|---|---|
|
||
| 16-bit | 4 | 4 | 80 |
|
||
| 32-bit | 2 | 2 | 48 |
|
||
| **64-bit** | **1** | **1** | **32** |
|
||
| 128-bit | 1 | 1 | 32 |
|
||
|
||
All four widths pass bit-exact correctness (9/9 tests each, including
|
||
under injected extra memory latency). 64-bit achieves a clean,
|
||
cycle-exact **1 cycle/tile** — 100% of `neural_processor.v`'s own
|
||
theoretical per-tile acceptance rate, exactly matching the streaming
|
||
memory manager's own ceiling (EXP-0027, STEP13). 128-bit gives **zero**
|
||
further benefit: a bus wider than one full tile still delivers exactly
|
||
one tile per transaction in this single-tile-per-request design (no
|
||
multi-tile bursting was attempted).
|
||
|
||
## The critical distinction: logical vs. physical bandwidth (A5)
|
||
|
||
STEP14 explicitly warned against assuming a wider logical interface
|
||
means the real memory can deliver it. It cannot, here: **the real V1
|
||
PSRAM chain is fixed at 16 bits** — a real chip
|
||
(ISSI IS66WVE4M16EBLL-70BLI, x16), not an RTL parameter. The
|
||
already-existing, already-verified `weight_prefetch_engine.v` (real,
|
||
used throughout STEP11-13) *is* exactly what a "64-bit logical / 16-bit
|
||
physical" packing adapter would produce: it assembles one 64-bit
|
||
logical tile from 4 real sequential 16-bit word transactions. Its real,
|
||
repeatedly-measured result is 4 cycles/tile — identical to the ideal
|
||
16-bit row above, because the real transaction count is unchanged
|
||
regardless of what the logical interface upstream claims. **A logical
|
||
wide interface backed by a physically-narrow bus delivers exactly the
|
||
narrow bus's own throughput.** No new "packing adapter" module was
|
||
built for this reason — the real engine already demonstrates the
|
||
answer, conclusively, without further RTL.
|
||
|
||
## Answer to the primary research questions
|
||
|
||
- **Is 16-bit weight delivery fundamentally insufficient for P_IN=8?**
|
||
Yes — it costs 4 cycles/tile, 4× the achievable minimum.
|
||
- **Is 32-bit enough?** No — still 2× the achievable minimum (2
|
||
cycles/tile).
|
||
- **Is 64-bit the natural architectural point?** Yes, exactly — proven
|
||
cycle-exact, not approximate.
|
||
- **Does wider logical delivery actually improve real throughput?**
|
||
**Not on this hardware.** Realizing the 64-bit ideal requires a
|
||
matching *physical* bandwidth increase (a real 64-bit-wide external
|
||
bus, or multiple parallel 16-bit PSRAM chips banked together) — a
|
||
board/silicon-level change, outside this project's own RTL scope.
|
||
|
||
## Recommendation
|
||
|
||
The 64-bit requirement is now precisely quantified and should inform
|
||
any future hardware revision (wider PSRAM, multiple banks). No RTL
|
||
change is warranted on the current board: `weight_prefetch_engine.v`
|
||
(real, 16-bit) remains the correct, already-optimal implementation
|
||
given the fixed physical bus width — STEP13's streaming-manager fix
|
||
already extracts everything available from the real interface.
|