STEP20 work toward the V2 hardware release gate. Adds real new RTL
implementing the three pieces the previous freeze (V2.0.0) explicitly
left open, plus real, disclosed verification findings. Does NOT
declare hardware release complete -- see below.
New RTL:
- spi_host_bridge.v: real SPI slave protocol engine (WRITE_JOB/
WRITE_MEM/READ_MEM/STATUS/RESET opcodes), replacing the 110-pin
reg_* testbench bus as the intended physical host interface.
Isolated regression 18/18 PASS (tb_spi_host_bridge.v); two real
MISO-timing bugs found and fixed during its own development (see
the module's header for the root-cause writeup).
- ecp5_pll_sys_clk.v: real, tool-generated (Project Trellis ecppll)
EHXPLLL wrapper, 16MHz oscillator -> 64MHz system clock, with a
declared (not fabricated) simulation-only PLL bypass.
- reset_sync.v: standard async-assert/sync-deassert reset bridge
gating on external POR and PLL lock.
- fpga_neural_v2_top.v: board-level top wiring the above around the
STEP19 compute+memory design's own already-frozen submodules
(zero modification to neural_processor.v, dependency_manager.v,
sdram_unified_backend.v, or any other previously-frozen file).
Real findings from this step's own re-verification (both logged in
full in hardware/v2/logs/errors.log):
- ERR-0024: the current Icarus Verilog v13.0 install (updated since
the last freeze) gives WRONG bit-exact results for the
already-committed STEP19 regression. Cross-checked against
Verilator per this project's own standing protocol (DEC-0004) --
the STEP19 baseline (single SDRAM, N=2/N=4, raw reg_* interface) IS
bit-exact correct, reconfirmed today, matching the historical cycle
counts exactly. Two provably-zero-behavior-change declaration-order
fixes were required just to get the current toolchain to elaborate
the already-shipped STEP19 files at all.
- ERR-0025: a real SPI-bridge protocol race (fixed) plus a SEPARATE,
real, UNRESOLVED defect -- two jobs dispatched through the real SPI
path with realistic pacing produce wrong compute results, even
though job registration itself is confirmed correct at the
handshake. Root cause not yet isolated. Committed as a known-failing
regression (tb_fpga_neural_v2_top_smoke.v) documenting the gap
honestly rather than hiding it.
Given ERR-0025 Part B is real and unresolved, synthesis/P&R of the new
board-level top was deliberately not attempted this round, and V2
hardware release is NOT declared complete. See decisions.log DEC-0036
and hardware/v2/docs/{CHIP_READINESS,OPEN_ITEMS}.md for the full,
itemized status.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2110 lines
111 KiB
Plaintext
2110 lines
111 KiB
Plaintext
# V2 decisions log -- formato DEC-XXXX, mai sovrascritto (vedi README.md)
|
|
|
|
DEC-0001
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
Congelare V1 come copia separata in hardware/v1/ (sola lettura a livello
|
|
filesystem) invece di spostare (git mv) l'albero top-level esistente
|
|
(rtl/, sim/, synth/, tools/) dentro hardware/v1/.
|
|
|
|
WHY:
|
|
docs/v2-description.md §1/§34 impone una "struttura obbligatoria"
|
|
hardware/v1/ + hardware/v2/ e vieta di modificare/degradare V1. Due
|
|
strade possibili: (a) spostare fisicamente rtl/sim/synth/tools
|
|
nell'albero hardware/v1/, oppure (b) copiarli lasciando l'albero
|
|
top-level esattamente come e' oggi. Lo spostamento romperebbe tutti i
|
|
riferimenti a percorso in WORKLOG.md, docs/validation/*.md,
|
|
docs/FPGA-NeuralNetwork-Engine.md (centinaia di citazioni tipo
|
|
"rtl/neuron_parallel.v:127") e negli script (tools/run_regression.py
|
|
resta funzionante per costruzione relativa, ma altri riferimenti
|
|
documentali no) -- un costo reale senza benefico funzionale, dato che
|
|
l'obiettivo della regola e' *non perdere/alterare* V1, non *dove* vive
|
|
fisicamente. La copia raggiunge lo stesso obiettivo (baseline
|
|
funzionale/numerica/bit-exact per V2, mai modificabile) senza il
|
|
rischio di rompere la cronologia documentale esistente.
|
|
|
|
EVIDENCE:
|
|
- `diff -rq rtl/ hardware/v1/rtl/` e confronto file-per-file su
|
|
sim/*.v: 0 differenze (copia bit-esatta verificata, non assunta).
|
|
- hardware/v1/ reso sola lettura (`chmod -R a-w`) subito dopo la copia,
|
|
prima di qualunque lavoro V2.
|
|
|
|
ALTERNATIVES:
|
|
- git mv dell'intero albero rtl/sim/synth/tools sotto hardware/v1/,
|
|
poi aggiornamento di tutti i riferimenti di percorso nella
|
|
documentazione. Scartata: costo/rischio alto, beneficio nullo
|
|
rispetto all'obiettivo dichiarato della regola.
|
|
- Symlink hardware/v1/ -> ../../rtl ecc. Scartata: non garantisce
|
|
l'immutabilita' (un simlink non protegge dalla modifica dell'originale
|
|
ed e' fragile rispetto a `chmod -R a-w`).
|
|
|
|
RESULT:
|
|
hardware/v1/ creato come copia bit-esatta e sola-lettura. L'albero
|
|
top-level del repository resta la "produzione" V1 corrente, invariata,
|
|
usata anche dal resto del progetto (WORKLOG.md, docs/) esattamente come
|
|
prima di questa sessione.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
DEC-0002
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
Collapse §6's baseline Neural Processor FSM states NP_LOAD_TILE,
|
|
NP_MAC, NP_ACCUM, NP_NEXT_TILE into the single NP_WAIT_OPERANDS state
|
|
in the actual implementation (hardware/v2/rtl/neural_processor.v),
|
|
rather than implementing them as four separate one-cycle-gated states.
|
|
|
|
WHY:
|
|
§5 explicitly states the internal datapath must be pipelined and the
|
|
goal is throughput, not minimal latency -- accepting a new P_IN-wide
|
|
tile every cycle. Gating tile acceptance behind four sequential FSM
|
|
states (each holding for exactly one cycle per tile) would recreate a
|
|
non-pipelined, one-tile-per-4-cycles controller, directly
|
|
contradicting §5/§34 ("ottimizzare il throughput effettivo"). The four
|
|
states from §6's baseline list describe what the ORIGINAL (pre-M1)
|
|
sketch assumed before the pipeline design in §5 was fully worked out;
|
|
once the datapath is genuinely pipelined, tile acceptance becomes a
|
|
single steady-state condition (operand_valid && operand_ready), and
|
|
per-tile progress is tracked by the valid/last tags flowing through
|
|
the pipeline registers, not by the outer FSM.
|
|
|
|
EVIDENCE:
|
|
EXP-0001 (bit-exact vs V1, 7/7 tests incl. a deliberate zero-idle-gap
|
|
back-to-back-tiles case, TEST 5 in tb_neural_processor.v) -- confirms
|
|
tiles are genuinely accepted one per cycle with no outer-FSM stall
|
|
between them.
|
|
|
|
ALTERNATIVES:
|
|
Literal 11-state FSM per §6's baseline list, with LOAD_TILE/MAC/
|
|
ACCUM/NEXT_TILE each a real one-cycle state gating acceptance.
|
|
Rejected: would cap throughput at 1 tile per 4 cycles, defeating the
|
|
pipeline's own purpose.
|
|
|
|
RESULT:
|
|
7-state FSM (NP_IDLE, NP_LOAD_JOB, NP_WAIT_OPERANDS, NP_FINISH,
|
|
NP_WRITE_RESULT, NP_DONE, NP_ERROR) implemented and verified.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
---
|
|
|
|
DEC-0003
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
Remove the operand-arrival protocol-violation guard from
|
|
neural_processor.v (the check that would raise NP_ERROR if
|
|
operand_valid arrived while the processor could not consume it) rather
|
|
than continue debugging it. Defer this responsibility to the Neural
|
|
Director (M5).
|
|
|
|
WHY:
|
|
The guard's own evaluation triggered ERR-0002 (docs/v2-description.md
|
|
mandate §25-29 requires documenting this, not hiding it) -- a
|
|
reproducible Icarus Verilog v13.0 bug where the guard's condition
|
|
evaluated true despite operand_valid being independently confirmed 0.
|
|
Root cause was bisected down to a minimal FSM transition unrelated to
|
|
this specific expression (see errors.log ERR-0002), meaning the bug is
|
|
in the toolchain's scheduling, not fixable by rewording the condition.
|
|
Architecturally, a standalone Neural Processor policing its OWN
|
|
issuer's protocol is also arguably the wrong owner of that
|
|
responsibility: per §34's own division of labor ("Il Director gestisce
|
|
WHAT deve essere eseguito"), arbitrating/validating operand issuance
|
|
across possibly-multiple Neural Processors is the Director's job, not
|
|
each processor's.
|
|
|
|
EVIDENCE:
|
|
ERR-0002 (errors.log) -- the guard, and several simplified variants of
|
|
it, all misevaluated under Icarus v13.0; disabling it entirely (and
|
|
only it) restored correct behavior in every case, confirmed via
|
|
Verilator that the underlying pipeline logic was already correct.
|
|
|
|
ALTERNATIVES:
|
|
1. Keep chasing the exact Icarus root cause. Rejected for this
|
|
session: already bisected to a toolchain-level scheduling issue
|
|
independent of this specific code, further chasing would not
|
|
change the architectural need for this check to live in the
|
|
Director eventually anyway.
|
|
2. Reimplement the same check with different Verilog phrasing.
|
|
Rejected: multiple independent phrasings all reproduced the bug.
|
|
|
|
RESULT:
|
|
NP_ERROR is now reachable only via the `default:` case branch (a
|
|
genuine np_state encoding corruption) -- a real safety net, just not
|
|
exercised by operand-arrival timing. The corresponding negative test
|
|
(TEST 7) was removed from tb_neural_processor.v; the scenario is
|
|
deferred to M5's testbench (tb_neural_director.v), where the Director
|
|
is the actual issuer under test.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
---
|
|
|
|
DEC-0004
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
Adopt Verilator 5.050 (`verilator --binary --timing`) as the primary/
|
|
trusted simulator for hardware/v2/ testbenches going forward, in
|
|
addition to (not instead of) Icarus Verilog. Cross-check any Icarus
|
|
result that looks anomalous against Verilator before concluding it is
|
|
an RTL bug.
|
|
|
|
WHY:
|
|
ERR-0001/ERR-0002 (errors.log) are two independently-reproduced Icarus
|
|
Verilog v13.0 defects that produced WRONG simulation results (not
|
|
compile errors) for straightforward, standard sequential Verilog, with
|
|
no workaround available at the RTL/testbench level for ERR-0002 short
|
|
of removing the affected logic. Verilator gave the CORRECT result for
|
|
every one of these repros. §30's rule against invented results cuts
|
|
both ways: a simulator that silently gives a WRONG "measured" result is
|
|
just as dangerous as inventing one outright -- cross-checking against
|
|
a second, architecturally different simulator (Verilator compiles to
|
|
C++, Icarus interprets bytecode -- unlikely to share the same
|
|
scheduling bug) is now mandatory whenever a hardware/v2/ testbench
|
|
shows unexpected behavior.
|
|
|
|
EVIDENCE:
|
|
- Minimal FSM repro (`if (go) st<=B;`, no tasks, no other logic):
|
|
Icarus v13.0 fails to transition on specific testbench edge-count
|
|
parities; Verilator 5.050 gives the correct result every time.
|
|
- Full hardware/v2/sim/tb_neural_processor.v: Icarus v13.0 hangs/
|
|
misbehaves even after every known-real RTL bug (ERR-0003) was fixed;
|
|
the SAME unmodified file under Verilator gives 7/7 PASS, bit-exact
|
|
vs the frozen V1 reference.
|
|
|
|
ALTERNATIVES:
|
|
1. Downgrade Icarus to an older release. Rejected: no older bottle was
|
|
cached on this machine (`brew list --versions icarus-verilog` shows
|
|
only 13.0) and fetching a specific historical formula version was
|
|
not attempted this session (time-boxed decision, revisit if it
|
|
becomes a recurring blocker).
|
|
2. Keep using only Icarus and manually work around each new defect as
|
|
found. Rejected: not sustainable across the dozens of testbenches
|
|
the full V2 roadmap requires (§20).
|
|
|
|
RESULT:
|
|
Verilator installed (`brew install verilator`, 5.050). hardware/v2/
|
|
testbenches are compiled/run with both simulators when convenient;
|
|
Verilator's result is authoritative when the two disagree, and any
|
|
such disagreement is logged here / in errors.log, not silently
|
|
resolved by picking whichever answer looks more convenient.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
---
|
|
|
|
DEC-0005
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
Treat DSP (MULT18X18D) budget, not LUT/FF/routing, as the primary
|
|
constraint when exploring the N_PROCESSORS x P_IN trade-off space
|
|
(§16) going forward.
|
|
|
|
WHY:
|
|
Real place&route measurement (EXP-0003) shows MULT18X18D usage
|
|
scaling linearly and reaching 88% of the LFE5U-45F-8BG381's 72 total
|
|
DSPs at N_PROCESSORS=8, P_IN=8 -- while LUT4/FF usage stays under 6%
|
|
at the SAME configuration and Fmax is still comfortably above the
|
|
80MHz target (134.70 MHz). This means the naive "just add more
|
|
processors" scaling (§8/§16) hits a hard DSP ceiling around
|
|
N_PROCESSORS=9 at P_IN=8, long before LUT/FF/routing/timing become
|
|
relevant -- the opposite of what LUT/FF utilization alone would
|
|
suggest if read in isolation.
|
|
|
|
EVIDENCE:
|
|
experiments.log EXP-0003 -- MULT18X18D 8/16/32/64 (11%/22%/44%/88% of
|
|
72) at N_PROCESSORS 1/2/4/8, LUT4 under 6% throughout, Fmax PASS at
|
|
80MHz throughout (159.11/149.59/151.01/134.70 MHz).
|
|
|
|
ALTERNATIVES:
|
|
Assume LUT/FF/routing congestion would be the limiting factor (the
|
|
naive expectation for "more parallel copies of a datapath"). Rejected
|
|
by direct measurement, not assumed -- §16 explicitly requires
|
|
choosing the final configuration "sulla base del throughput effettivo
|
|
... non dell'utilizzo massimo delle risorse", and knowing WHICH
|
|
resource binds first is a prerequisite for that.
|
|
|
|
RESULT:
|
|
Future N_PROCESSORS x P_IN sweeps (§16, deferred to a dedicated
|
|
scripts/sweep/ run per §31) should budget MULT18X18D count explicitly
|
|
(N_PROCESSORS * P_IN <= ~72, minus whatever the rest of the real
|
|
system needs once M4/PSRAM integration lands) rather than only
|
|
tracking LUT/FF. A smaller P_IN with more N_PROCESSORS (or vice versa)
|
|
is a live trade-off worth exploring precisely because of this ceiling,
|
|
not merely a stylistic choice.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
---
|
|
|
|
DEC-0006
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
memory_manager.v (M4) uses a SINGLE prefetch_engine instance,
|
|
retargeted per bank via a depth-1 pending-request register, rather
|
|
than multiple engines or a general request queue. The result
|
|
write-back (one byte per job, after the last tile) shares the same
|
|
backend port via a simple state-based mux, not a general arbiter --
|
|
because prefetch and write-back are temporally disjoint by
|
|
construction (the write only happens after prefetch_engine has
|
|
nothing left to fetch for that job).
|
|
|
|
WHY:
|
|
§13's double-buffering strategy needs at most ONE fetch "in flight"
|
|
and at most ONE fetch "queued" at any time for a SINGLE Neural
|
|
Processor consuming tiles sequentially (proven by construction: a new
|
|
prefetch is only ever queued on a tile handoff, and at most one
|
|
handoff can be pending completion of the previous prefetch before the
|
|
next one is even requested). A general multi-entry queue or a second
|
|
engine would add complexity with no present benefit. Likewise,
|
|
because this Memory Manager currently serves exactly one Neural
|
|
Processor and one job at a time, no concurrent second requester can
|
|
ever contend for the backend port with prefetch reads -- a real
|
|
mem_arbiter-style arbiter (as V1 uses for ITS OWN multi-master case)
|
|
is deferred until a scenario that actually needs it exists (multiple
|
|
Neural Processors or overlapping jobs sharing one memory_manager,
|
|
not yet built).
|
|
|
|
EVIDENCE:
|
|
errors.log ERR-0006 -- the single-entry pending register, once
|
|
correctly gated (see ERR-0006 items 1-2), handled 1-tile, 3-tile, and
|
|
5-tile jobs correctly with no queue overflow in
|
|
hardware/v2/sim/tb_memory_manager.v.
|
|
|
|
ALTERNATIVES:
|
|
1. Multiple prefetch_engine instances (one per bank), letting both
|
|
banks fetch fully in parallel. Rejected for M4: doubles DSP-free
|
|
logic for a benefit only realized when compute-tile time is
|
|
SHORTER than 2x fetch-tile time for a single engine -- not yet
|
|
measured to be the case (§22, deferred to M9), and the single-
|
|
engine design already fully hides fetch latency behind neural_
|
|
processor's own per-tile compute time in the cases tested (see
|
|
experiments.log EXP-0005 cycle counts).
|
|
2. General N-entry FIFO for pending requests. Rejected: no scenario
|
|
in the current single-processor, single-job design can ever
|
|
generate more than one pending request before the in-flight one
|
|
completes -- an N-entry queue would be complexity with no
|
|
reachable use.
|
|
3. Reuse V1's mem_arbiter.v as-is for the prefetch-vs-writeback
|
|
sharing. Rejected: mem_arbiter.v's four ports are hardcoded to
|
|
specific V1 module names/priorities (§1 already established this
|
|
pattern in DEC-0001 for the broader V1-freeze decision) -- and
|
|
prefetch/write-back are provably never simultaneous here anyway,
|
|
so even a generic 2-port arbiter would be unexercised complexity.
|
|
|
|
RESULT:
|
|
memory_manager.v as implemented. A NOTED, NOT-YET-OPTIMIZED
|
|
characteristic (documented in the module's own header comment): the
|
|
bank-swap-and-check control path costs a minimum 1 idle cycle per
|
|
tile handoff even when the next bank was already prefetched in time,
|
|
unlike neural_processor.v's own zero-gap tile acceptance -- left for
|
|
M10 (Optimization) to revisit using real stall-percentage data (§22)
|
|
rather than optimized blindly now.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
---
|
|
|
|
DEC-0007
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
neural_director.v (M5) implements a reduced FSM (DIR_IDLE,
|
|
DIR_SCAN_READY, DIR_ALLOCATE, DIR_ERROR) instead of §9's full 8-state
|
|
baseline list (which also includes DIR_WAIT_DEPENDENCY, DIR_MONITOR,
|
|
DIR_COMPLETE, DIR_WAKEUP). Dependency tracking/waiting/wake-up are
|
|
entirely deferred to the Dependency Manager (M6, not yet built); slot
|
|
completion detection (§9's "rilevamento dei completamenti",
|
|
DIR_MONITOR's job) is handled by an always-active per-slot busy
|
|
tracker running independently of whatever state the allocate/scan
|
|
loop happens to be in, not a dedicated state the loop must visit.
|
|
|
|
WHY:
|
|
§10 explicitly assigns dependency counters/ready-vs-waiting
|
|
tracking/wake-up/producer-tracking to the Dependency Manager, not the
|
|
Director -- building DIR_WAIT_DEPENDENCY/DIR_WAKEUP now, before M6
|
|
exists, would mean inventing a dependency model here that M6 would
|
|
then have to either reuse or replace, backwards from the roadmap's own
|
|
milestone order. For DIR_MONITOR: gating "did any slot just finish"
|
|
detection behind a specific FSM state would force the SAME state to be
|
|
revisited every cycle for every one of N_SLOTS independently-running
|
|
jobs, which is exactly the throughput-killing pattern DEC-0002 already
|
|
rejected for the Neural Processor's own FSM -- the same reasoning
|
|
applies one level up here.
|
|
|
|
EVIDENCE:
|
|
hardware/v2/sim/tb_neural_director.v -- 4/4 tests pass with 2 slots
|
|
running genuinely concurrent, independently-timed jobs (a 3rd job
|
|
correctly queued until whichever slot freed first, and a
|
|
deliberately-slow 2-job burst used to force real ready-queue
|
|
backpressure) -- confirms slot-completion detection and first-free
|
|
allocation both work without a dedicated FSM state gating either.
|
|
|
|
Separately: this milestone's testbench gives each (memory_manager,
|
|
neural_processor) slot its OWN independent behavioral byte memory
|
|
(sim_byte_mem, not the real V1 PSRAM chain) rather than sharing one
|
|
PSRAM port across N_SLOTS. M4 (EXP-0005) already proved the real PSRAM
|
|
path end-to-end for ONE slot; M5's own concern is scheduling/dispatch
|
|
across MULTIPLE slots, which this isolates. Multiple slots genuinely
|
|
sharing one physical PSRAM port is a backend-arbitration problem
|
|
already explicitly deferred (DEC-0006), not solved here either.
|
|
|
|
ALTERNATIVES:
|
|
1. Implement the literal 8-state FSM now, with DIR_WAIT_DEPENDENCY/
|
|
DIR_WAKEUP as real states that simply never get exercised until
|
|
M6 wires something into them. Rejected: dead states with no real
|
|
behavior are not simpler or safer than documenting the deferral
|
|
explicitly, and risk baking in an ad-hoc dependency model that
|
|
conflicts with M6's actual design once built.
|
|
2. Share one real PSRAM backend across N_SLOTS now, forcing the
|
|
arbiter-design question into M5. Rejected: out of this milestone's
|
|
scope (§9 is about scheduling, not memory arbitration) and would
|
|
duplicate work once M6/M8 need a real answer to backend sharing
|
|
anyway.
|
|
|
|
RESULT:
|
|
neural_director.v as implemented: 4-state FSM, always-active slot-busy
|
|
tracking, ready-queue backpressure via a plain parametric-depth
|
|
circular FIFO. First-free scheduling only (§9's initial policy);
|
|
round-robin/least-loaded/etc are explicitly deferred to a later,
|
|
experimentally-driven milestone per §9's own text.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
---
|
|
|
|
DEC-0008
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
dependency_manager.v (M6) does NOT implement §11's direct producer-
|
|
to-consumer VALUE forwarding (bypassing the Result Buffer/external-
|
|
memory round-trip). It tracks dependency COUNTS and READINESS only --
|
|
"has this node's data become available", resolved via a
|
|
producer_done_node_id tag matched against each waiting node's own
|
|
producer_ids list. A ready node's job descriptor still points at
|
|
result_addr (wherever the Memory Manager, M4, wrote the producer's
|
|
actual result), which is how a consumer finds its real input data
|
|
today. Additionally, node table slots are NOT reclaimed after
|
|
dispatch (ST_DISPATCHED is terminal) -- a full graph run allocates its
|
|
N_NODES once, not a reusable pool.
|
|
|
|
WHY:
|
|
§11 itself frames forwarding as an optimization ("quando possibile"),
|
|
not a correctness requirement -- the dependency-COUNTING mechanism
|
|
(§10's actual explicit field list: node_id/state/required_dependencies/
|
|
resolved_dependencies/producer_information) is what gates correct
|
|
scheduling; forwarding is a bandwidth/latency optimization on top of
|
|
an already-correct base. Implementing real value forwarding would
|
|
require reworking the Neural Processor's operand path (M1) and Memory
|
|
Manager's fetch path (M4) to support a bypass source in addition to
|
|
PSRAM -- a bigger change that should be justified by real measured
|
|
data (§22/§30: no invented results) showing memory bandwidth is
|
|
actually the bottleneck, not assumed now. Slot non-reclamation is
|
|
similarly a scope choice: reclaiming/reusing node table entries mid-run
|
|
only matters for graphs that run longer than N_NODES distinct node
|
|
launches, or that need dynamic re-registration -- not exercised by
|
|
this milestone's own test (a bounded DAG, registered once, run once).
|
|
|
|
EVIDENCE:
|
|
hardware/v2/sim/tb_dependency_manager.v -- 4/4 tests pass demonstrating
|
|
multi-dependency (node2 needs both node0 AND node1) and shared-
|
|
producer/multi-consumer wake-up (node0's single completion correctly
|
|
satisfies both node3 fully and node2 partially) using ONLY the
|
|
counting mechanism, no forwarded values -- confirming the counting-
|
|
only design is sufficient for correct scheduling.
|
|
|
|
ALTERNATIVES:
|
|
1. Implement value forwarding now (Producer -> Consumer FIFO directly,
|
|
per §11's diagram). Rejected: no measured evidence yet that the
|
|
PSRAM round-trip is a real bottleneck (§22 measurements are M9's
|
|
job); adding it now would be exactly the kind of unmeasured,
|
|
assumption-driven change §30 warns against.
|
|
2. Reclaim/reuse node table slots after dispatch. Rejected: adds
|
|
real complexity (a free-list, or requiring producer_done for a
|
|
DISPATCHED node to also clear it) for a scenario (graphs needing
|
|
more distinct node launches than N_NODES, or dynamic re-
|
|
registration) this milestone's test doesn't exercise -- revisit if
|
|
a real M7+ integration scenario needs it.
|
|
|
|
RESULT:
|
|
dependency_manager.v as implemented: pure dependency-count tracking,
|
|
first-found-ready dispatch to the Director (M5), no value forwarding,
|
|
no slot reclamation. Both explicitly noted as deferred, not silently
|
|
missing.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
DEC-0009
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
dataflow_core.v (M7) integrates dependency_manager (M6) -> neural_director
|
|
(M5) -> N_SLOTS x (memory_manager (M4) + neural_processor (M1)), closing
|
|
the wake-up loop end-to-end for the first time. Two things are
|
|
deliberately NOT done in this module: (1) M3's BRAM-backed buffers
|
|
(activation_buffer/weight_buffer/result_buffer) are not instantiated
|
|
anywhere inside it; (2) each slot's byte-level Memory Backend Interface
|
|
is exposed as its own SEPARATE port (slot_mem_req/wr/addr/wdata/rdata/
|
|
ready, arrayed by N_SLOTS) rather than arbitrated down to one shared
|
|
PSRAM master.
|
|
|
|
WHY:
|
|
(1) §15's own diagram places the Memory Manager -> Memory Backend
|
|
Interface -> PSRAM Controller path on one side, with M3's buffers
|
|
belonging as an on-chip cache concept, not a mandatory pass-through --
|
|
each memory_manager instance already owns its own prefetch double
|
|
buffer (M4) for the fast path it actually needs, and no measured
|
|
benchmark yet shows a real need for an additional shared cache layer
|
|
(§22/§30: no invented results/optimizations). (2) real PSRAM has
|
|
exactly ONE physical port; N_SLOTS>1 memory_manager instances wanting
|
|
concurrent access is fundamentally an arbitration problem, and building
|
|
an arbiter now, before M8's real-toolchain measurement of what
|
|
contention actually looks like end-to-end with the real (unmodified)
|
|
V1 PSRAM chain, risks designing to a guess instead of to data.
|
|
|
|
EVIDENCE:
|
|
hardware/v2/sim/tb_dataflow_core.v -- 4/4 tests PASS on a 3-node DAG
|
|
run through the full stack with each slot backed by its own
|
|
independent behavioral memory (deliberately NOT the real shared V1
|
|
PSRAM chain, for exactly the reason above): node0 and node1 (no
|
|
dependencies) both complete correctly via real neural_processor
|
|
computation, and node2 (depends on BOTH) is only dispatched after
|
|
BOTH genuinely finish -- continuously polled every cycle, not just
|
|
checked at the end -- proving the producer_done wake-up loop closes
|
|
correctly with real M1/M4/M5/M6 hardware in between, not just
|
|
between M5 and M6 in isolation (already proven separately by their
|
|
own testbenches).
|
|
|
|
ALTERNATIVES:
|
|
1. Wire a naive round-robin N-port arbiter in front of one shared
|
|
PSRAM master now. Rejected: M8's own roadmap text is explicit
|
|
("Integrare il controller V1 senza modificarlo inizialmente.
|
|
Misurare il comportamento reale.") -- arbitration design should
|
|
follow a real measurement of contention under the real PSRAM
|
|
latency model, not be guessed at during M7's own scope (proving
|
|
the dependency/scheduling loop closes, not memory sharing).
|
|
2. Instantiate M3's buffers as a shared cache in front of each slot's
|
|
Memory Backend Interface now. Rejected: no benchmark yet shows
|
|
PSRAM bandwidth or latency is actually a bottleneck for the
|
|
dependency-graph workloads this module targets -- premature
|
|
without measured justification.
|
|
|
|
RESULT:
|
|
dataflow_core.v as implemented: N_SLOTS independent Memory Backend
|
|
Interface ports, no M3 buffers wired in. Both explicitly deferred to
|
|
M8 (shared PSRAM integration/arbitration) and a future
|
|
measurement-driven decision (M3 buffer reuse), not missing by
|
|
oversight.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
DEC-0010
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
slot_mem_arbiter.v (M8) arbitrates dataflow_core's N_SLOTS independent
|
|
Memory Backend Interface ports down to the ONE real PSRAM port using
|
|
FIXED, lowest-port-index priority (not round-robin/least-loaded/
|
|
fair-share), with a per-port single-entry pending-request latch (see
|
|
errors.log ERR-0008) so a fire-and-forget request pulse arriving
|
|
during contention is queued, never dropped.
|
|
|
|
WHY:
|
|
Fixed lowest-index priority is the same "first-found, simplest
|
|
correct policy first" starting point already chosen for
|
|
neural_director's first-free slot scheduling (decisions.log DEC-0007)
|
|
and dependency_manager's first-ready dispatch -- consistent with this
|
|
whole roadmap's own pattern of shipping the simplest policy that is
|
|
provably correct, then revisiting fairness/throughput ONLY once real
|
|
measured data (M9) shows it actually matters for a real workload.
|
|
Under sustained heavy contention a low-index slot COULD in principle
|
|
starve a higher-index one (an unfair, but not incorrect, outcome);
|
|
this is an honestly-acknowledged limitation of a first cut, not an
|
|
oversight. The pending-latch discipline (ERR-0008) is not a policy
|
|
choice but a correctness requirement -- discovered empirically via
|
|
real concurrent-slot simulation, not designed in from the start (an
|
|
example of the mandate's own point, §22/§30: real measurement finds
|
|
real problems that a purely theoretical design would not).
|
|
|
|
EVIDENCE:
|
|
hardware/v2/sim/tb_neural_multiprocessor.v -- 4/4 PASS with N_SLOTS=2
|
|
genuinely concurrent slots (node0/node1, no dependencies, dispatched
|
|
back-to-back) contending for the one real PSRAM port through the real
|
|
V1 backend chain; both complete correctly and node2 (depends on both)
|
|
dispatches only once they genuinely do. No starvation observed in this
|
|
small a test (2 slots, one short job each) -- a real starvation
|
|
measurement would need a longer-running, higher-N_SLOTS workload,
|
|
deferred to M9's own benchmark.
|
|
|
|
ALTERNATIVES:
|
|
1. Round-robin or least-recently-served fairness now. Rejected: no
|
|
measured evidence yet (M9 not run) that fixed-priority starvation
|
|
is a real problem for the graph workloads this system targets --
|
|
adding fairness logic before a measured need is speculative
|
|
complexity, the same reasoning DEC-0007 already applied to
|
|
neural_director's own scheduling policy.
|
|
2. Give each slot its own dedicated PSRAM port (no arbitration at
|
|
all). Rejected: real PSRAM hardware has exactly one physical port
|
|
(the whole reason this module exists) -- not an option on real
|
|
hardware, only in simulation.
|
|
|
|
RESULT:
|
|
slot_mem_arbiter.v as implemented: fixed lowest-index priority,
|
|
single-entry pending-request latch per port (mandatory for
|
|
correctness, not a policy choice). Fairness/throughput-aware
|
|
scheduling explicitly deferred to a future measurement-driven
|
|
decision, not missing by oversight.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
DEC-0011
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
M9's §32 comparison table reports "stall %", "memory utilization" and
|
|
"processor utilization" as NOT INDEPENDENTLY MEASURED this milestone,
|
|
rather than computing a number for them. All other rows (Fmax, LUT,
|
|
FF, DSP, BRAM, MAC/cycle, cycles/neuron, neurons/s, effective MAC/s)
|
|
are filled with real, sourced numbers (see benchmark.log's M9 entry).
|
|
|
|
WHY:
|
|
Computing a real, honest stall %/utilization figure requires isolating
|
|
"real compute cycles" from "real memory-wait cycles" for BOTH V1 and
|
|
V2 on an equal footing -- V1's own docs give a real end-to-end cycle
|
|
count (209 cycles, 1 neuron/8 inputs, real PSRAM) but not a
|
|
correspondingly measured ISOLATED (no-PSRAM) compute-only cycle count
|
|
for the exact same configuration; V2 has the isolated pipeline latency
|
|
(8-stage neural_processor, known from M1) but computing a precise,
|
|
honest stall % still means dedicated per-cycle instrumentation of a
|
|
real run, not something to approximate from numbers already at hand
|
|
without effectively inventing the missing half of the ratio. §30's own
|
|
rule ("nessun risultato inventato") applies exactly here: an
|
|
approximated/guessed percentage would look precise while not being a
|
|
real measurement.
|
|
|
|
EVIDENCE:
|
|
benchmark.log/timing.log/simulation.log already contain the REAL
|
|
numbers this table draws from (V1: hardware/v1/docs/
|
|
FPGA-NeuralNetwork-Engine.md's own already-certified 209-cycle
|
|
measurement, PARALLEL=8/N_INPUTS=8, real PSRAM; V2: EXP-0005's 166-
|
|
cycle measurement, P_IN=8, real V1 PSRAM chain, plus EXP-0009's 444-
|
|
cycle real 2-slot-concurrent run). The qualitative finding is already
|
|
documented (simulation.log EXP-0005: "real PSRAM latency dominates,
|
|
not memory_manager's own control overhead") -- both systems are
|
|
memory-latency-bound for a single small job, but a precise percentage
|
|
needs dedicated instrumentation neither system has had built for it
|
|
yet.
|
|
|
|
ALTERNATIVES:
|
|
1. Approximate stall % from the neural_processor pipeline's known
|
|
8-stage latency vs total real cycles (rough mental arithmetic).
|
|
Rejected: this is exactly the kind of "looks-measured-but-isn't"
|
|
number §30 prohibits -- pipeline latency and PSRAM real access
|
|
latency are not the same thing as "non-stalled cycles" once
|
|
overlap/pipelining across tiles is accounted for (M4's own
|
|
double-buffered prefetch specifically overlaps compute with the
|
|
NEXT tile's fetch), so a naive subtraction would misrepresent real
|
|
behavior, not measure it.
|
|
2. Skip the whole M9 table until full instrumentation exists.
|
|
Rejected: 9 of the table's 12 rows already have solid real data
|
|
sitting in the logs from M1-M8 -- withholding the whole table would
|
|
throw away real, useful, already-measured information for the sake
|
|
of 3 rows that genuinely need new instrumentation.
|
|
|
|
RESULT:
|
|
M9's table ships with 9/12 rows filled from real measured data
|
|
(labeled THEORETICAL/SIMULATED/SYNTHESIZED/POST-P&R per row) and 3
|
|
rows (stall %, memory utilization, processor utilization) explicitly
|
|
marked NOT MEASURED, deferred to M10 -- which itself explicitly needs
|
|
real utilization data to decide what to optimize, making dedicated
|
|
cycle-accounting instrumentation a natural M10 prerequisite rather
|
|
than M9 scope creep.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
DEC-0012
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
For the LFE5U-45F-8BG381 target at P_IN=8, N_SLOTS=8 is the
|
|
recommended practical ceiling for dataflow_core's processor count (the
|
|
"numero processor" axis of M10). Beyond N_SLOTS=8, DSP usage would
|
|
exceed the chip's 72 total MULT18X18D (N_SLOTS=8 already uses 64/72 =
|
|
88.9%; N_SLOTS=9 would need 72/72 = 100%, leaving zero margin for any
|
|
other DSP use and very likely failing placement given routing
|
|
congestion already visibly eating into Fmax margin well before that
|
|
point).
|
|
|
|
WHY:
|
|
Real P&R data across the full N_SLOTS sweep now run (EXP-0003 at the
|
|
neural_processor_array level for M2, EXP-0008/EXP-0011 at the
|
|
dataflow_core level for M7/M10) shows TWO real, independent trends
|
|
converging on the same conclusion: (1) DSP usage scales exactly
|
|
linearly at 8 per slot (matches P_IN=8), hitting 88.9% at N_SLOTS=8 --
|
|
consistent with DEC-0005's original finding that DSP, not LUT/FF, is
|
|
the first resource to saturate; (2) Fmax falls monotonically and
|
|
non-linearly as N_SLOTS grows (165.15 -> 133.19 -> 92.63 MHz for
|
|
N_SLOTS=2/4/8), meaning routing congestion around the shared
|
|
neural_director/dependency_manager hub is ALREADY compounding with DSP
|
|
pressure well before the hard resource ceiling is reached. N_SLOTS=8
|
|
is therefore not merely "the largest N_SLOTS that fits" but close to
|
|
where BOTH constraints (DSP budget and real routing congestion)
|
|
become simultaneously binding -- a genuinely data-driven ceiling, not
|
|
an assumed one.
|
|
|
|
EVIDENCE:
|
|
timing.log/synthesis.log EXP-0008 (N_SLOTS=2: 165.15 MHz, 16/72 DSP;
|
|
N_SLOTS=4: 133.19 MHz, 32/72 DSP) and EXP-0011 (N_SLOTS=8: 92.63 MHz,
|
|
PASS at 80MHz but with a much thinner margin, 64/72 DSP) -- all real
|
|
nextpnr-ecp5 place&route measurements via harness_dataflow_core.v.
|
|
|
|
ALTERNATIVES:
|
|
1. Recommend a smaller N_SLOTS (e.g. 4) for a larger Fmax safety
|
|
margin. Rejected as a BLANKET recommendation: whether 133.19 MHz's
|
|
larger margin over 133.19 vs 92.63 MHz's thinner one actually
|
|
matters depends on the target application's own real timing needs,
|
|
which M9's benchmark did not fix to a specific number beyond
|
|
"PASS at 80MHz" -- both configurations real-measure as passing.
|
|
N_SLOTS=8 remains the data-driven CEILING; choosing a smaller
|
|
N_SLOTS for a specific deployment is a downstream product decision,
|
|
not something this session can make on the target's behalf.
|
|
2. Reduce P_IN below 8 to allow more slots within the same DSP budget
|
|
(e.g. P_IN=4, N_SLOTS=16 -> still 64 DSP). Rejected as untested:
|
|
no real data exists yet on Fmax/throughput for P_IN=4 slots at any
|
|
N_SLOTS -- this is a real, open experiment for a FUTURE session,
|
|
not something to recommend without having actually measured it
|
|
(§30).
|
|
|
|
RESULT:
|
|
N_SLOTS=8 (P_IN=8) is the data-driven practical ceiling on the
|
|
LFE5U-45F-8BG381 for dataflow_core/neural_multiprocessor. Smaller
|
|
N_SLOTS values remain valid, real-measured configurations trading
|
|
Fmax margin for less concurrency; a P_IN<8 exploration for even higher
|
|
N_SLOTS is explicitly flagged as untested future work, not assumed.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
DEC-0013
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
ACC_WIDTH=24 is the recommended default for neural_processor.v's
|
|
accumulator width (the "pipeline" axis of M10), replacing EXP-0002's
|
|
original single-seed, inconclusive finding.
|
|
|
|
WHY:
|
|
A 6-seed real placement sweep (EXP-0012: default seed plus 5 explicit
|
|
--seed values, same two already-synthesized netlists, real
|
|
nextpnr-ecp5 P&R only -- no re-synthesis needed) shows ACC_WIDTH=24
|
|
has a HIGHER mean Fmax (180.71 vs 170.12 MHz, +6.2%) AND a much
|
|
tighter seed-to-seed spread (stdev 4.21 vs 14.16 MHz) than
|
|
ACC_WIDTH=32. EXP-0002's original single-seed result (176.21 <
|
|
183.12 MHz, suggesting ACC=24 was WORSE) is now understood as
|
|
placement-seed noise, not a real trend -- exactly the kind of mistake
|
|
a single-seed measurement risks, which is why §30/§31 call for
|
|
experimentally exploring configurations rather than trusting one
|
|
placement run. Combined with EXP-0001/EXP-0002's already-known
|
|
resource advantage (ACC_WIDTH=24: LUT=49/FF=509/CCU2C=88 vs
|
|
ACC_WIDTH=32: LUT=55/FF=533/CCU2C=96 -- fewer of every resource) and
|
|
both being bit-exact-correct against the same 7-test regression
|
|
(EXP-0001/EXP-0002), ACC_WIDTH=24 dominates ACC_WIDTH=32 on every real
|
|
axis measured for a plain INT8 perceptron whose products/partial sums
|
|
never need more than 24 bits of headroom for P_IN=8 (8 x int8 x int8
|
|
products, worst case magnitude fits well under 2^24).
|
|
|
|
EVIDENCE:
|
|
timing.log EXP-0012 (6-seed Fmax data for both configs, computed
|
|
mean/min/max/stdev); synthesis.log EXP-0001/EXP-0002 (resource
|
|
counts, already logged); simulation.log EXP-0001/EXP-0002 (both
|
|
configs bit-exact-correct against V1, 7/7 PASS).
|
|
|
|
ALTERNATIVES:
|
|
1. Keep ACC_WIDTH=32 as the default (matches V1's own mac_unit.v
|
|
accumulator width, "when in doubt, match the frozen baseline").
|
|
Rejected: real multi-seed data now shows ACC_WIDTH=24 is strictly
|
|
better on Fmax, resource usage, AND correctness for this specific
|
|
P_IN=8 INT8 configuration -- there is no real axis left on which
|
|
ACC_WIDTH=32 wins for THIS workload. V1 itself is a separate, frozen
|
|
baseline (§1/§34) and is not required to match V2's own internal
|
|
width choices.
|
|
2. Run more than 6 seeds per config for a tighter confidence interval.
|
|
Deferred, not rejected: 6 seeds already show a clear, consistent
|
|
direction (ACC=24 wins on both mean and variance) -- diminishing
|
|
returns for this decision's purposes; a future session could extend
|
|
the sweep if ACC_WIDTH ever becomes a live bottleneck again.
|
|
|
|
RESULT:
|
|
ACC_WIDTH default changed to 24 going forward for any NEW V2 module
|
|
instantiating neural_processor.v at P_IN=8 (no existing committed
|
|
module needs to be edited retroactively purely for this -- M1-M9's own
|
|
modules already default to ACC_WIDTH=32 via their own parameter
|
|
defaults and remain correct either way, since both widths are
|
|
bit-exact verified; this is a recommendation for future configuration
|
|
choices, not a mandate to re-synthesize already-logged results).
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
DEC-0014
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
N_SLOTS=2 is the recommended default/shipped configuration for
|
|
neural_multiprocessor.v, superseding DEC-0012's earlier "N_SLOTS=8 is
|
|
the practical ceiling" framing for general use. N_SLOTS=8 remains a
|
|
REAL, valid, synthesizable configuration (DEC-0012's DSP-budget
|
|
ceiling finding stands), but the final benchmark campaign (EXP-0014)
|
|
shows it is not a good DEFAULT given the system's real bottleneck.
|
|
|
|
WHY:
|
|
EXP-0014's real, measured parallel-scaling data (6 workloads x 4
|
|
configs, real V1 PSRAM chain, real slot_mem_arbiter, real POST-P&R
|
|
Fmax) shows conclusively that the shared PSRAM port -- not slot count
|
|
-- is this system's real bottleneck: memory-bound workloads
|
|
(C-Large/D-Stress) get only 1.05-1.06x real cycle-count speedup from
|
|
N_SLOTS=1 all the way to N_SLOTS=8 (PSRAM port utilization pegged at
|
|
~91% regardless), and once real Fmax degradation from added slots is
|
|
also factored in (152.46 -> 142.45 -> 113.38 MHz for N=1/2/4), the
|
|
REAL WALL-CLOCK time for the Stress workload is actually 21% WORSE at
|
|
N_SLOTS=4 than at N_SLOTS=1. More hardware parallelism made this
|
|
workload class slower, not faster -- adding slots has a real Fmax cost
|
|
with no compensating real throughput benefit once the shared PSRAM
|
|
port saturates.
|
|
|
|
Small/bursty workloads (A-Small, E-Multilayer, F-DAG) DO show a real,
|
|
if modest, benefit from N_SLOTS=2 (~1.2-1.3x real wall-clock speedup,
|
|
from better overlap of per-job registration/scheduling latency across
|
|
two independently-progressing jobs) -- this benefit already exists at
|
|
N=2 and does not meaningfully grow at N=4/8 (see EXP-0014's efficiency
|
|
table: efficiency collapses from 66% at N=2 to 15% at N=8 for exactly
|
|
this workload class). N_SLOTS=2 is therefore the point that captures
|
|
essentially all of the real, measured benefit this architecture can
|
|
deliver from concurrency, without paying N=4/8's real Fmax tax for a
|
|
benefit that does not materialize.
|
|
|
|
EVIDENCE:
|
|
benchmark.log's EXP-0014 entry: the full 6-workload x 4-config real
|
|
cycle-count table, the derived speedup/efficiency table, the real
|
|
wall-clock (cycles / real POST-P&R Fmax) comparison for D-Stress, and
|
|
the real per-slot tile-delivery imbalance data (slot 0/1 doing ~98% of
|
|
C-Large's real work at N_SLOTS=4, slot 2/3 essentially idle until the
|
|
tail) -- all real, Verilator-simulated + nextpnr-ecp5-measured, not
|
|
assumed.
|
|
|
|
ALTERNATIVES:
|
|
1. Recommend N_SLOTS=8 (DEC-0012's original framing, "practical DSP
|
|
ceiling"). Rejected as a DEFAULT: DEC-0012 was correct that
|
|
N_SLOTS=8 is the largest configuration that FITS the chip's DSP
|
|
budget, but EXP-0014 shows fitting is not the same as being
|
|
beneficial -- 8 slots deliver essentially the same real throughput
|
|
as 1 slot for memory-bound work, at a real Fmax cost (92.63 MHz for
|
|
dataflow_core-only, even lower once the real PSRAM chain is added).
|
|
N_SLOTS=8 remains available/valid for a FUTURE system that also
|
|
widens real memory bandwidth (see Alternative 2 below and the final
|
|
report's Bottleneck Analysis/Limitations sections) but is not the
|
|
right choice for THIS system as built.
|
|
2. Solve the real bottleneck (widen/parallelize PSRAM bandwidth --
|
|
e.g. multiple physical PSRAM banks, one per pair of slots) so that
|
|
N_SLOTS=4/8 would actually deliver real throughput gains. Rejected
|
|
for THIS decision: real hardware/board redesign, well beyond a
|
|
measurement-driven RTL parameter choice -- flagged as the correct
|
|
FUTURE direction if higher real concurrency is ever needed, not
|
|
attempted here (§30: no invented results, no un-measured redesigns
|
|
presented as decided).
|
|
|
|
RESULT:
|
|
N_SLOTS=2 is the recommended default configuration, used as the
|
|
reference configuration in the final benchmark report and (pending
|
|
user confirmation) the datasheet. N_SLOTS=1 remains a real,
|
|
competitive alternative for deployments that are purely large/
|
|
sustained/memory-bound (equal or better real wall-clock throughput,
|
|
lower resource cost, highest real Fmax). N_SLOTS=4/8 remain valid,
|
|
synthesizable, functionally-correct configurations (all bit-exact
|
|
verified in EXP-0014) but are NOT recommended as a default without a
|
|
future memory-bandwidth-scaling architecture change.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
DEC-0015
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
prefetch_engine.v/memory_manager.v's own Memory Backend Interface is
|
|
changed from byte-level (matching hardware/v1/rtl/int8_memory_access.v's
|
|
contract, one 8-bit logical transaction per real backend round-trip)
|
|
to WORD-level (matching hardware/v1/rtl/memory_interface.v's own
|
|
16-bit contract directly, one transaction moving 2 consecutive bytes).
|
|
neural_multiprocessor.v no longer instantiates int8_memory_access.v --
|
|
the arbiter's master port connects directly to memory_interface.v.
|
|
slot_mem_arbiter.v's own per-port data width and lb_n/ub_n signals are
|
|
widened to match.
|
|
|
|
WHY (user-requested, directly following the M9/M10 benchmark
|
|
campaign's own finding that the system is memory-bound -- see the
|
|
final-benchmark.md report's recommendation #1): int8_memory_access.v
|
|
ALREADY converts every 8-bit logical request into a FULL 16-bit
|
|
PSRAM word access internally (`mem_addr <= addr >> 1`, one byte lane
|
|
selected via lb_n/ub_n) -- so fetching X/W tile arrays one byte at a
|
|
time was ALREADY paying for two bytes of real PSRAM bandwidth per
|
|
transaction while discarding half of it, and paying int8_memory_access's
|
|
own STATE_IDLE/STATE_WAIT round-trip TWICE for every 2 real bytes
|
|
instead of once. hardware/v1/rtl/psram_controller.v's own real
|
|
page-mode support (already implemented, unmodified, confirmed present
|
|
by direct inspection) then has fewer, more effective opportunities to
|
|
serve consecutive words fast once transactions are batched this way.
|
|
int8_memory_access.v/memory_interface.v/psram_controller.v are all
|
|
frozen V1 files and remain byte-for-byte unmodified (§1/§34) --
|
|
V2 simply chooses to reuse the lower (word-level) layer of that same
|
|
frozen chain directly instead of the byte-splitting layer on top of
|
|
it, the same "reuse what fits" precedent slot_mem_arbiter.v already
|
|
set by not reusing hardware/v1/rtl/mem_arbiter.v verbatim.
|
|
|
|
EVIDENCE (real, measured, before/after -- see experiments.log EXP-0015
|
|
for full detail): hardware/v2/sim/tb_memory_manager.v (M4, real V1
|
|
PSRAM chain): 3-tile job 446->204 cycles (-54%), 1-tile 166->84
|
|
(-49%), 5-tile 728->322 (-56%), all still bit-exact. Full campaign
|
|
(tb_benchmark_suite.v, EXP-0014's own workloads) re-run at N_SLOTS=
|
|
1/2/4/8: D-Stress real wall-clock (cycles / real POST-P&R Fmax)
|
|
improves 2.24-2.37x across every N_SLOTS tested, all 24/24 workload/
|
|
config combinations still bit-exact. Real Fmax cost is small (N=1:
|
|
152.46->152.44 MHz, unchanged; N=2: 142.45->133.58 MHz, -6.2%; N=4:
|
|
113.38->112.07 MHz, -1.2%) -- overwhelmingly a net win in real
|
|
wall-clock terms at every N_SLOTS.
|
|
|
|
CONSTRAINT introduced: P_IN must be even (already true, P_IN=8), and
|
|
tile base addresses (x_base/w_base, and therefore every x_base +
|
|
tile_idx*P_IN the system ever computes) must be word-aligned (even
|
|
byte addresses) -- true of every address this project's own
|
|
testbenches already use, and a trivial constraint for any real
|
|
loader/host to satisfy (place tile arrays at even byte offsets).
|
|
|
|
ALTERNATIVES:
|
|
1. Modify int8_memory_access.v itself to return/accept 2 bytes per
|
|
logical transaction. Rejected: that file is frozen V1 (§1/§34) --
|
|
never modified, regardless of how small the change would be.
|
|
2. Build a NEW byte-level burst wrapper on top of int8_memory_access.v
|
|
(queue N byte requests, pipeline them). Rejected: int8_memory_access's
|
|
own STATE_IDLE only samples a new req once back in STATE_IDLE after
|
|
the previous transaction's mem_ready -- it fundamentally does not
|
|
support pipelining/overlapped requests, so no wrapper on TOP of it
|
|
can avoid paying its full per-byte round-trip cost twice per word.
|
|
Only bypassing it (going one layer lower, to memory_interface.v's
|
|
own native word interface) actually eliminates the redundant
|
|
round-trip.
|
|
|
|
RESULT:
|
|
prefetch_engine.v/memory_manager.v/slot_mem_arbiter.v/
|
|
neural_multiprocessor.v now speak a word-level (16-bit + lb_n/ub_n)
|
|
Memory Backend Interface, bypassing int8_memory_access.v entirely
|
|
(still frozen, still reused unmodified -- just one layer lower in the
|
|
same frozen stack). Real, measured 2.24-2.37x wall-clock improvement
|
|
at every N_SLOTS tested, negligible real Fmax cost, all functional
|
|
correctness preserved (24/24 bit-exact).
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
DEC-0016
|
|
|
|
DATE: 2026-09-05
|
|
|
|
DECISION:
|
|
A new shared module, activation_cache.v, is added inside dataflow_core.v
|
|
alongside the N_SLOTS memory_managers. It fetches a given ACTIVATION
|
|
(X) vector from PSRAM once (tile by tile, on first use) and serves
|
|
every subsequent request for the same x_base/tile directly from an
|
|
on-chip buffer -- no PSRAM access on a hit. Each memory_manager's own
|
|
prefetch_engine now fetches WEIGHTS only (X is no longer duplicated
|
|
per-slot). Single-tag design (one active cached x_base at a time,
|
|
correct but can thrash under interleaved different-x_base concurrent
|
|
traffic -- never incorrect, see the "Alternatives"/"Result" sections
|
|
below for the honest limitation).
|
|
|
|
WHY (user-requested optimization #2, following the final-benchmark.md
|
|
report's own recommendation): in the realistic dense-layer workloads
|
|
this project benchmarks, many neurons share the exact same X vector --
|
|
each of dataflow_core's N_SLOTS memory_manager instances re-fetching
|
|
that identical vector from PSRAM independently was real, measured,
|
|
redundant traffic on the one shared PSRAM port.
|
|
|
|
EVIDENCE -- REAL BENEFIT (cycles, SIMULATED, full campaign,
|
|
tb_benchmark_suite.v, D-Stress the largest/most representative
|
|
workload): combined with DEC-0015's word-level burst rewrite, total
|
|
cycle count for D-Stress falls from the ORIGINAL byte-level baseline
|
|
(EXP-0014) by 3.97x-4.47x across every N_SLOTS tested (N=1: 780298 ->
|
|
174610; N=2: 736402 -> 185428; N=4: 736823 -> 184795; N=8: 738751 ->
|
|
184797) -- the activation_cache's OWN incremental contribution on top
|
|
of DEC-0015 alone is a further 1.66x-2.00x cycle reduction. All 24/24
|
|
workload/config combinations remain bit-exact.
|
|
|
|
EVIDENCE -- REAL COST (Fmax, POST-P&R MEASURED, full
|
|
neural_multiprocessor including the real V1 PSRAM chain): the shared
|
|
cache's real Fmax cost is substantially STEEPER than DEC-0015's own
|
|
(which cost only 0-6% Fmax). Real POST-P&R Fmax after adding the
|
|
cache: N=1: 152.44 -> 131.79 MHz (-13.5%); N=2: 133.58 -> 87.72 MHz
|
|
(-34.3%); N=4: 112.07 -> 65.01 MHz (-42.0%, and this configuration NOW
|
|
FAILS the 80MHz target it previously passed). This is a real,
|
|
structural cost: activation_cache is a single shared resource with
|
|
N_SLOTS request ports, a broadcast-capable hit-check evaluated for
|
|
every port every cycle, and a shared tile_store array -- a genuine
|
|
routing/fan-in hot spot that gets worse as N_SLOTS grows, more
|
|
severely than the arbiter-only widening DEC-0015 introduced.
|
|
|
|
Combined REAL WALL-CLOCK effect (cycles / real POST-P&R Fmax,
|
|
D-Stress, vs the ORIGINAL byte-level baseline): N=1: 3.86x faster
|
|
(the clear win case -- low Fmax cost, full cycle benefit); N=2: 2.45x
|
|
faster (still a solid net win -- this is the recommended default,
|
|
DEC-0014, and it still comfortably beats the baseline, though its
|
|
Fmax safety margin over 80MHz shrank from +78% to +9.7%); N=4: 2.29x
|
|
faster THAN THE ORIGINAL baseline, but WORSE than DEC-0015-alone
|
|
(2742.4us -> 2842.6us) once its own real (now failing) Fmax is used --
|
|
adding the cache is a net REGRESSION specifically at N=4, and N=4 is
|
|
no longer even a valid passing 80MHz design point.
|
|
|
|
ALTERNATIVES:
|
|
1. Pipeline the cache's hit-detection/broadcast logic (register the
|
|
hit[] comparison one extra stage before driving tile_x_out) to
|
|
recover some of the lost Fmax margin. Rejected FOR NOW: a real,
|
|
promising follow-up, but a genuine RTL redesign of the cache's own
|
|
timing, not attempted in this pass -- flagged as real, concrete
|
|
future work rather than attempted blindly without first measuring
|
|
whether N_SLOTS=2 (the actual recommended default, DEC-0014) still
|
|
needs it (it does not fail timing at N=2, it just has a thinner
|
|
margin than before).
|
|
2. Give up on the cache entirely given N=4's regression. Rejected:
|
|
N=1 and N=2 (the actually-recommended range per DEC-0014) both show
|
|
a clear, real net win, and N=4 was never the recommended default
|
|
to begin with -- discarding a real 2.45-3.86x win over the range
|
|
that matters to avoid a regression in a range that was already
|
|
deprioritized would be the wrong trade.
|
|
3. Make MAX_TILES smaller (currently 16, sized for the largest
|
|
workload's shared vector) to shrink the cache's own storage/compare
|
|
width and recover some Fmax. Rejected for THIS round: would need
|
|
re-verifying against every workload's own real tile count
|
|
requirements (Large/Stress use exactly 16) -- a real, bounded
|
|
follow-up, not attempted here to avoid conflating multiple
|
|
variables in one measurement.
|
|
|
|
RESULT:
|
|
activation_cache.v is added, real net win confirmed at N_SLOTS=1 and
|
|
N_SLOTS=2 (the recommended default, DEC-0014), real regression to a
|
|
failing timing state confirmed at N_SLOTS=4 -- reported honestly, not
|
|
hidden. N_SLOTS=2 remains the recommended default (DEC-0014's own
|
|
conclusion is unaffected, since N=4 was never recommended), now with a
|
|
thinner but still real Fmax margin (87.72 MHz vs the 80MHz target).
|
|
Cache pipelining (Alternative 1) is flagged as real, concrete follow-up
|
|
work if N_SLOTS>2 configurations are ever needed with this cache
|
|
active.
|
|
|
|
STATUS:
|
|
ACCEPTED
|
|
|
|
|
|
DEC-0017
|
|
timestamp: 2026-09-05T21:55:00Z
|
|
git_commit: 63cac6a7e5e0126bb13bea89dfe21966d5c9a1a5 (+ uncommitted NMS STEP1 work)
|
|
DECISION: Adopt EXP-0017's measured bandwidth/prefetch-depth floors as
|
|
the NMS (Neural Memory System) design target for STEP3 onward,
|
|
instead of assuming any bank count/SRAM width/prefetch policy a
|
|
priori (per the user's own explicit STEP ordering).
|
|
WHY: EXP-0017 shows the real, unmodified neural_processor.v's own
|
|
demand is exactly 16 bytes/cycle/slot (2*P_IN) once latency is
|
|
hidden -- a hard, derivable floor, not a guess -- and that
|
|
PREFETCH_DEPTH (not bandwidth) is what determines whether that floor
|
|
is actually reachable under nonzero round-trip latency. Designing
|
|
the NMS's SRAM/bank width and prefetch queue depth against these
|
|
measured numbers, rather than an arbitrarily "large" local memory,
|
|
directly follows the user's own stated final rule (optimize for
|
|
sustained compute throughput, not for maximum RAM capacity).
|
|
EVIDENCE: EXP-0017 (768-point real Verilator sweep, N_SLOTS x
|
|
PREFETCH_DEPTH x LATENCY x BANDWIDTH).
|
|
ALTERNATIVES CONSIDERED:
|
|
1. Skip the bandwidth study and directly size the NMS off the V1/V2
|
|
PSRAM controller's own already-measured page-mode timing. Rejected
|
|
for this step: the user explicitly asked for an idealized,
|
|
architecture-agnostic study FIRST (STEP1), to avoid anchoring the
|
|
NMS's own internal SRAM/banking design on the existing PSRAM
|
|
controller's specific timing before knowing what the compute
|
|
fabric actually needs -- the real PSRAM's own achievable bandwidth
|
|
is a separate, still-pending measurement (real page-mode
|
|
byte/cycle rate from psram_controller.v) that determines whether
|
|
16*N_SLOTS bytes/cycle is even reachable from the real backing
|
|
store, but does not change what the compute fabric NEEDS.
|
|
2. Design PREFETCH_DEPTH generously oversized (e.g. always 16) rather
|
|
than latency-dependent. Rejected: EXP-0017 shows PREFETCH_DEPTH=16
|
|
is NOT enough at latency=16 (83.4%, not 90%+) -- an oversized-but-
|
|
fixed prefetch depth is not obviously safe either; the real design
|
|
parameter is PREFETCH_DEPTH scaled to the REAL, separately-measured
|
|
round-trip latency of whatever backing-store interface the NMS
|
|
ends up using, not a single fixed guess.
|
|
RESULT: STEP1 (bandwidth requirement study) is closed. Minimum
|
|
aggregate bandwidth floor = 16*N_SLOTS bytes/cycle (hard, derived
|
|
from real P_IN=8 compute rate). PREFETCH_DEPTH must be sized against
|
|
the REAL round-trip latency of whatever backing store STEP3-STEP7
|
|
eventually select, not fixed independently of it.
|
|
STATUS: ACCEPTED
|
|
|
|
DEC-0018
|
|
timestamp: 2026-09-05T22:20:00Z
|
|
git_commit: 63cac6a7e5e0126bb13bea89dfe21966d5c9a1a5 (+ uncommitted NMS STEP1/STEP3 work)
|
|
DECISION: Adopt "banked Activation SRAM, N_BANKS = N_SLOTS, with
|
|
broadcast-on-same-address and round-robin arbitration on conflict"
|
|
as the STEP4 candidate architecture for the NMS's shared activation
|
|
memory, to replace hardware/v2/rtl/activation_cache.v's single-tag
|
|
design. Weight memory: private per-slot bank (no sharing, no
|
|
arbitration needed at all), per STEP2's own analytical conclusion.
|
|
WHY: EXP-0018 shows this specific combination is the ONLY tested
|
|
configuration that keeps utilization high (~98-99%) across every
|
|
N_SLOTS and every realistic dispatch stagger tested -- it is the
|
|
first real, measured evidence in this whole project that N_SLOTS=2
|
|
can genuinely beat N_SLOTS=1, and N_SLOTS=4 beat N_SLOTS=2, without
|
|
the shared memory nullifying the parallelism (the user's own stated
|
|
success criterion, NMS spec §18).
|
|
EVIDENCE: EXP-0018 (80-point real Verilator sweep).
|
|
ALTERNATIVES CONSIDERED:
|
|
1. Keep N_BANKS=1 (today's single shared activation port/cache).
|
|
Rejected: EXP-0018 reproduces V2's own real bottleneck exactly
|
|
(49.8% utilization loss from a single cycle of stagger at
|
|
N_SLOTS=2) -- this is the architecture being replaced, not a
|
|
candidate.
|
|
2. N_BANKS fixed at some value smaller than N_SLOTS (e.g. always 2 or
|
|
4, to save BRAM). Rejected as the DEFAULT: EXP-0018 shows graceful
|
|
but real degradation once stagger exceeds what N_BANKS<N_SLOTS can
|
|
absorb (e.g. N_SLOTS=8/N_BANKS=4/stagger=8: 49.8%) -- a smaller,
|
|
fixed bank count is a real, legitimate STEP4 candidate to compare
|
|
against N_BANKS=N_SLOTS on real BRAM/Fmax cost (a smaller N_BANKS
|
|
might still be the right trade for large N_SLOTS if DP16KD cost
|
|
dominates), but is not adopted as the default without that real
|
|
synthesis data.
|
|
3. Skip banking, rely purely on broadcast at N_BANKS=1 and force
|
|
perfectly synchronized (zero-stagger) dispatch. Rejected: requires
|
|
redesigning the Neural Director's own dispatch timing to guarantee
|
|
lockstep across all N_SLOTS, a much larger and more fragile change
|
|
than banking the memory, and still fails the instant any slot
|
|
stalls elsewhere in the pipeline (a stall breaks lockstep exactly
|
|
like stagger does).
|
|
RESULT: STEP3's core question (does ANY tested memory organization let
|
|
N_SLOTS actually scale) is answered YES, in simulation, for banked
|
|
activation with N_BANKS=N_SLOTS. This is a SIMULATION-level result
|
|
only -- real Fmax/DP16KD/LUT cost of the broadcast/bank-select logic
|
|
at each N_SLOTS is NOT yet measured (STEP4 candidate selection, then
|
|
STEP5/6 real synthesis, still pending).
|
|
STATUS: ACCEPTED (as the leading STEP4 candidate, not yet as a final
|
|
architecture -- real synthesis data required before STEP7 selection)
|
|
|
|
DEC-0019
|
|
timestamp: 2026-09-06T00:00:00Z
|
|
git_commit: 5c9ec61 (+ uncommitted NMS STEP4/5/6 work)
|
|
DECISION: Select Candidate A ("replicated" -- N_SLOTS private full-
|
|
vector activation copies, broadcast-write fill, zero-contention
|
|
private reads, hardware/v2/nms/rtl/nms_activation_replicated.v) as
|
|
the NMS's Activation SRAM architecture, over Candidate B (banked +
|
|
round-robin arbiter + broadcast crossbar).
|
|
WHY: EXP-0019's real synthesis+PnR data shows Candidate A strictly
|
|
dominates Candidate B on every measured axis at every tested
|
|
N_SLOTS: 2-4x higher real Fmax, ~24x fewer LUTs at N_SLOTS=8
|
|
(MAX_TILES=16), and structurally starvation-free correctness (no
|
|
arbiter exists to get wrong). The real BRAM cost of replication (8
|
|
DP16KD at N_SLOTS=8/MAX_TILES=256, 7% of the chip) is small and
|
|
honestly acceptable for this project's own realistic workload sizes.
|
|
Both candidates already achieved the SAME real cycle-level throughput
|
|
in simulation (EXP-0018, since both implement the identical logical
|
|
broadcast-when-shared / fair-when-contended semantics) -- so once
|
|
cycle-level behavior is equal, the real hardware cost comparison
|
|
(this experiment) is the only thing left to decide between them, and
|
|
it is not close.
|
|
EVIDENCE: EXP-0019 (7 real synthesis+PnR runs), cross-referenced
|
|
against EXP-0018's own cycle-level equivalence.
|
|
ALTERNATIVES CONSIDERED:
|
|
1. Candidate B (banked+broadcast) at N_BANKS=N_SLOTS. Rejected: real,
|
|
measured Fmax/LUT cost is far worse at every N_SLOTS with no
|
|
throughput benefit over Candidate A (EXP-0018 already showed both
|
|
reach the same ~99% utilization ceiling) -- banking only pays off
|
|
over replication if replication's BRAM cost becomes the binding
|
|
constraint, which it does not at this project's own realistic
|
|
vector lengths (MAX_TILES<=256 uses <=8 DP16KD at N_SLOTS=8, 7% of
|
|
chip).
|
|
2. Candidate B with a smaller fixed N_BANKS (e.g. 4) to save further
|
|
BRAM at higher N_SLOTS. Rejected: EXP-0019 shows this variant costs
|
|
MORE LUTs than N_BANKS=N_SLOTS (1667 vs 3348 COMB is fewer in
|
|
absolute terms, but still ~12x Candidate A's 138 at the same
|
|
N_SLOTS=8) for LOWER Fmax AND (per EXP-0018) a real cycle-count
|
|
regression from contention -- worse on every axis simultaneously,
|
|
not a genuine trade.
|
|
3. Skip replication concerns and just always use Candidate A
|
|
regardless of vector length, without measuring larger MAX_TILES.
|
|
Rejected implicitly: EXP-0019 deliberately measured MAX_TILES=256
|
|
(not just 16) specifically because the user's own NMS spec (§6)
|
|
warned against exactly this kind of unverified assumption (M3's own
|
|
"shallower depth = less BRAM" lesson) -- the real DP16KD cost at a
|
|
realistic depth needed to be confirmed acceptable, not assumed.
|
|
RESULT: NMS Activation SRAM = Candidate A (replicated). Real,
|
|
synthesis-confirmed cost at N_SLOTS=8/MAX_TILES=256: 8 DP16KD (7% of
|
|
chip), 137 LUT4-equivalent COMB cells, Fmax=130.70 MHz in isolation
|
|
(component-level, not yet the full-system integrated number).
|
|
CAVEAT, stated honestly: replication's BRAM cost scales with
|
|
N_SLOTS x vector depth -- if a future workload needs a MUCH longer
|
|
shared activation vector (MAX_TILES in the thousands) at N_SLOTS=8,
|
|
this cost should be re-measured before assuming it stays cheap; not
|
|
re-tested this round since it exceeds this project's own current
|
|
realistic workload sizes (largest tested workload uses MAX_TILES=16,
|
|
ch. "Large/Stress" workloads in the frozen V2 final benchmark).
|
|
STATUS: ACCEPTED
|
|
|
|
DEC-0020
|
|
timestamp: 2026-09-06T01:10:00Z
|
|
git_commit: 5c9ec61 (+ uncommitted NMS work)
|
|
DECISION: Select Candidate W2 "packed" (per-MAC-lane narrow memories,
|
|
hardware/v2/nms/rtl/nms_weight_packed.v) as the NMS's Weight SRAM
|
|
architecture, over Candidate W1 "direct" (one wide native-width
|
|
memory per slot, mirroring weight_buffer.v's own M3-era structure).
|
|
WHY: EXP-0020's real synthesis+PnR data shows packed uses the IDENTICAL
|
|
real DP16KD count as direct at every N_SLOTS and every tested depth
|
|
(BRAM cost is unaffected by this choice), while using ~1.9x fewer
|
|
LUTs and ~2x fewer FFs at N_SLOTS=8/MAX_TILES=256, for comparable
|
|
Fmax. There is no real axis on which direct wins meaningfully; at
|
|
the shallow depth this project's current workloads actually use
|
|
(MAX_TILES=16) the two candidates are identical, so packed is never
|
|
worse and sometimes meaningfully cheaper.
|
|
EVIDENCE: EXP-0020 (12 real synthesis+PnR runs).
|
|
ALTERNATIVES CONSIDERED:
|
|
1. Candidate W1 (direct), matching the already-existing
|
|
weight_buffer.v structure for continuity/familiarity. Rejected:
|
|
"already exists elsewhere in the codebase" is not, by this
|
|
project's own stated discipline, a reason to prefer a real,
|
|
measured LUT/FF cost regression with no offsetting benefit.
|
|
2. Skip re-measuring at MAX_TILES=256 since M3 already established
|
|
weight_buffer's DP16KD count is depth-insensitive. Rejected: M3's
|
|
own finding was about DEPTH insensitivity for ONE fixed width/
|
|
packing; this decision is specifically about WIDTH/PACKING choice,
|
|
a different variable, and the user's own NMS spec (S6) explicitly
|
|
asked this not be assumed by analogy.
|
|
RESULT: NMS Weight SRAM = Candidate W2 (packed, per-lane). Combined
|
|
with DEC-0019's Activation SRAM (replicated) selection: at
|
|
N_SLOTS=8/MAX_TILES=256 (a realistic deep shared vector), the
|
|
combined real BRAM cost of BOTH memories is 8 (activation) + 8
|
|
(weight) = 16 DP16KD, 14.8% of the LFE5U-45F's 108 total -- an
|
|
honestly affordable real cost for this project's own realistic
|
|
workload sizes.
|
|
STATUS: ACCEPTED
|
|
|
|
DEC-0021
|
|
timestamp: 2026-09-06T01:55:00Z
|
|
git_commit: 5c9ec61 (+ uncommitted NMS STEP8 work)
|
|
DECISION: Accept nms_dataflow_core.v (Dependency Manager + Neural
|
|
Director reused verbatim + N_SLOTS x nms_memory_manager/
|
|
neural_processor + shared nms_activation_fill_ctrl, backed by
|
|
nms_activation_replicated.v/nms_weight_packed.v) as the STEP8 NMS
|
|
integration, now bit-exact verified end-to-end.
|
|
WHY: EXP-0021 confirms the two independently-decided memory pieces
|
|
(DEC-0019 Activation SRAM replicated, DEC-0020 Weight SRAM packed)
|
|
compose correctly into the full real dependency-wake-up loop,
|
|
including the specific shared-activation-broadcast and multi-tile
|
|
scenarios this new architecture must handle that the OLD memory_
|
|
manager.v + activation_cache.v design already handled differently.
|
|
Both real bugs found (ERR-0013) were caught by DELIBERATELY testing
|
|
scenarios the OLD design's own testbenches never needed to cover
|
|
(multi-tile jobs interacting with the NEW private-fetch-restart
|
|
logic) -- consistent with this project's own standing practice of
|
|
writing tests that specifically target what changed, not just
|
|
reusing old tests unchanged.
|
|
EVIDENCE: EXP-0021 (7/7 bit-exact tests, 2 real bugs found and fixed).
|
|
ALTERNATIVES CONSIDERED:
|
|
1. Trust the two memory pieces' own isolated verification (EXP-0018/
|
|
0019/0020's own testbenches) as sufficient, skip a dedicated full-
|
|
integration test. Rejected: EXP-0021 found 2 real bugs that existed
|
|
ONLY in the glue logic (nms_memory_manager.v) connecting the two
|
|
already-verified pieces together -- isolated correctness of each
|
|
piece does not imply correctness of their composition, the same
|
|
lesson this project already learned at M4/M7/M8 (dataflow_core.v's
|
|
own real integration bugs, ERR-0006/0008).
|
|
RESULT: STEP8 (full NMS integration) is functionally complete and
|
|
bit-exact verified at N_SLOTS=2. Real Fmax/resource cost of the FULL
|
|
integrated system (not just the isolated Activation/Weight SRAM
|
|
candidates from EXP-0019/0020) is NOT yet measured -- that is STEP9's
|
|
own job, alongside a real cycle-count benchmark comparable to V2's
|
|
own frozen final-benchmark campaign.
|
|
STATUS: ACCEPTED
|
|
|
|
DEC-0022
|
|
timestamp: 2026-09-06T03:20:00Z
|
|
git_commit: 5c9ec61 (+ uncommitted NMS STEP9/STEP10 work)
|
|
DECISION: Recommend the NMS (nms_neural_multiprocessor.v) at
|
|
N_SLOTS=2 as a real, measured upgrade over Current V2
|
|
(neural_multiprocessor.v) at its own recommended N_SLOTS=2 (DEC-0014):
|
|
+6.0% real wall-clock throughput, -55.3% LUT4, -10.2% FF, higher
|
|
real Fmax margin (93.10 vs 87.72 MHz), for the SAME DSP/BRAM cost,
|
|
on the IDENTICAL D-Stress workload, bit-exact. Do NOT recommend NMS
|
|
at N_SLOTS=4/8 yet -- Current V2 is REALLY faster there (12.9% at
|
|
N=4) until nms_activation_fill_ctrl.v's own priority-scan is
|
|
pipelined (EXP-0022's own identified, concrete, not-yet-attempted
|
|
fix).
|
|
WHY: This is the first NMS number that is directly, apples-to-apples
|
|
comparable to V2's own already-logged real numbers (same workload,
|
|
same golden-model verification, same real V1 PSRAM chain, same real
|
|
synthesis toolchain) -- every earlier NMS decision (DEC-0019/0020/
|
|
0021) was internally consistent but never checked against V2's own
|
|
real baseline until now. The result confirms the entire NMS
|
|
redesign's own central thesis (EXP-0018: banked/replicated on-chip
|
|
organization removes the SAME-cycle contention that both
|
|
activation_cache.v, DEC-0016, and now nms_activation_fill_ctrl.v's
|
|
OWN priority-scan can reintroduce in a different form) while also
|
|
HONESTLY surfacing that the redesign is not uniformly better --
|
|
N_SLOTS=4/8's real Fmax regression is a genuine, measured cost, not
|
|
glossed over.
|
|
EVIDENCE: EXP-0022 (real synthesis+PnR for N_SLOTS=1/2/4/8, real
|
|
256-neuron D-Stress benchmark for N_SLOTS=2/4 through the real V1
|
|
PSRAM chain, cross-referenced against V2's own already-logged
|
|
D-Stress numbers, benchmark.log EXP-0016).
|
|
ALTERNATIVES CONSIDERED:
|
|
1. Recommend NMS unconditionally (all N_SLOTS). Rejected: EXP-0022's
|
|
own real N=4 data shows Current V2 winning there (0.871x) -- an
|
|
unconditional recommendation would contradict this project's own
|
|
central discipline (never round a real regression up to a win).
|
|
2. Withhold any recommendation until the fill-controller pipelining
|
|
fix is implemented and re-measured at N=4/8. Rejected: N_SLOTS=2 is
|
|
ALREADY the project's own standing recommended default (DEC-0014),
|
|
confirmed unaffected by either DEC-0019/0020's own memory redesign
|
|
or this session's own findings -- there is no reason to withhold a
|
|
real, measured win in the range that already matters while a
|
|
separate, clearly-scoped follow-up (N=4/8 Fmax) remains open.
|
|
RESULT: NMS is a real, net improvement at N_SLOTS<=2 (the range this
|
|
project actually recommends); N_SLOTS=4/8 remain a real, open,
|
|
honestly-flagged regression pending the fill-controller pipelining
|
|
fix identified in EXP-0022. This closes the NMS roadmap (STEP1-
|
|
STEP10) for the current round.
|
|
STATUS: ACCEPTED (N_SLOTS<=2 recommendation); N_SLOTS=4/8 status
|
|
REMAINS OPEN, not resolved this round.
|
|
|
|
DEC-0023
|
|
timestamp: 2026-09-05T23:41:08Z
|
|
topic: NMS STEP11 (real weight prefetch & latency hiding) -- final
|
|
outcome and PREFETCH_DISTANCE recommendation.
|
|
context: STEP11 was commissioned specifically because EXP-0022 found
|
|
prefetch_effectiveness~=0% and weight-related stall~=92.5% at
|
|
N_SLOTS=2, and demanded a REAL weight prefetch engine that
|
|
demonstrably solves it, with an explicit A/B/C outcome framework
|
|
(A=success, sustained MAC/cycle>=90% of theoretical + utilization
|
|
>=90% + Fmax>=80MHz; B=partial, latency solved but bandwidth
|
|
insufficient; C=failure, prefetch cannot materially reduce stalls).
|
|
options_considered:
|
|
1. Declare Outcome A (success) -- REJECTED: not supported by any
|
|
real measurement. Sustained MAC/cycle reaches only 2.8% (N=1) /
|
|
1.2% (N=2) of the required 90%-of-theoretical target (EXP-0024).
|
|
2. Declare Outcome C (failure) uniformly across all N_SLOTS --
|
|
REJECTED as too coarse: N_SLOTS=1 DOES show a real, reproducible,
|
|
bit-exact-verified ~10.3% cycle reduction (181489->162876 cycles)
|
|
directly attributable to the new engine eliminating the old
|
|
per-tile-boundary control-plane restart gap -- a genuine, if
|
|
small, causal effect that must not be erased by an overly blunt
|
|
verdict.
|
|
3. Declare Outcome B for N_SLOTS=1 (real latency-hiding effect
|
|
proven, remaining gap is bandwidth) + Outcome C for N_SLOTS=2
|
|
(zero measured effect, port already saturated by cross-slot
|
|
contention before any lookahead scheme can act) -- SELECTED.
|
|
This is the only framing that matches EXP-0024's own actual,
|
|
dis-aggregated numbers rather than averaging away the real
|
|
N_SLOTS=1-vs-2 divergence STEP11's own experiment discovered.
|
|
decision: STEP11 outcome is B(N_SLOTS=1) / C(N_SLOTS=2), NOT A.
|
|
- N_SLOTS=1: PARTIAL SUCCESS. The real weight_prefetch_engine.v
|
|
mechanism WORKS AS DESIGNED (continuous cross-tile-boundary word
|
|
streaming against the real single-outstanding-transaction PSRAM
|
|
protocol, verified bit-exact in tb_weight_prefetch.v and in the
|
|
real D-Stress integration) and delivers a real, reproducible
|
|
-10.3% cycle-count improvement. It falls far short of the 90%-
|
|
utilization target (achieves 2.8% of the required sustained
|
|
MAC/cycle) because the real, physical PSRAM bandwidth itself
|
|
(not latency) is now the dominant remaining limiter -- quantified
|
|
at EXP-0024: a ~35.8x real bandwidth increase would be needed to
|
|
reach the target.
|
|
- N_SLOTS=2 (this project's own primary reference configuration):
|
|
FAILURE against the "materially reduce stalls" criterion. Every
|
|
PREFETCH_DISTANCE from 1 to 16 produces a statistically
|
|
indistinguishable cycle count (185390-185410, 0.011% spread), and
|
|
the result is functionally identical to the pre-STEP11 "Current
|
|
NMS" baseline (185645 cycles, EXP-0022) -- a -0.13% difference,
|
|
i.e. no real effect. Root cause: the single physical PSRAM port
|
|
is ALREADY saturated (90.5% utilization, unchanged from the
|
|
baseline) by the natural interleaving of two slots' own real
|
|
traffic through slot_mem_arbiter's round-robin arbitration, before
|
|
any lookahead/buffering scheme ever gets a chance to hide latency
|
|
-- there is no idle port time left to hide INTO. This is a real,
|
|
external, physical bandwidth ceiling (the single real
|
|
ISSI IS66WVE4M16EBLL-70BLI PSRAM chip's own access timing,
|
|
contended by N_SLOTS clients), not an RTL-scheduling defect.
|
|
Explicit answer to STEP11's own mandated architectural question
|
|
("is the current PSRAM bandwidth sufficient once latency is
|
|
hidden?"): NO. It was never primarily a latency problem at
|
|
N_SLOTS=2 (the port has no idle time to begin with); it is, and
|
|
remains, a bandwidth problem, requiring more real physical PSRAM
|
|
throughput (wider bus, multiple independent banks/ports, or a
|
|
faster backing technology) to progress further -- outside this
|
|
STEP's own RTL-scheduling scope, and NOT something a "next
|
|
redesign" of the on-chip scheduler alone can fix (per this STEP's
|
|
own explicit "do NOT proceed to another major redesign without
|
|
evidence" instruction).
|
|
PREFETCH_DISTANCE recommendation: PFD=2. Every PFD>=2 tested (2, 4, 8,
|
|
16) is measurement-identical to PFD=2 at BOTH N_SLOTS=1 and
|
|
N_SLOTS=2 -- there is zero additional measured benefit from any
|
|
deeper buffering, so per this STEP's own explicit "a deeper prefetch
|
|
buffer is NOT automatically better; find the smallest implementation
|
|
that achieves the required utilization" instruction, PFD=2 is the
|
|
Pareto-optimal choice among the values that show any benefit at all
|
|
(PFD=1 is measurably worse at N_SLOTS=1; PFD=1..16 are indistinguish-
|
|
able at N_SLOTS=2, so PFD=2 costs nothing extra there either).
|
|
Resource cost at PFD=2 is also equal-to-slightly-cheaper than PFD=8
|
|
(N=1: LUT4 1333 vs 1464, -9.0%; N=2: LUT4 1941 vs 1908, +1.7% --
|
|
a wash) with comparable Fmax (N=1: 132.26 vs 137.76MHz; N=2: 97.16
|
|
vs 95.25MHz).
|
|
production_recommendation: do NOT adopt nms_neural_multiprocessor_pf
|
|
(weight_prefetch_engine.v) as the default NMS configuration at
|
|
N_SLOTS>=2 -- it is resource/Fmax-neutral versus the existing
|
|
Current NMS baseline (nms_neural_multiprocessor.v) but provides no
|
|
real throughput benefit there, so switching adds real design/
|
|
verification surface (a new module, a new testbench, a new failure
|
|
mode class already found once as ERR-0015) for zero measured gain.
|
|
At N_SLOTS=1 specifically, where a real ~10% win exists, it MAY be
|
|
worth adopting once a real workload exists where N_SLOTS=1's own
|
|
per-slot bandwidth is not already the bottleneck -- not the case
|
|
for D-Stress's own dense-layer, non-reusable-weight access pattern.
|
|
Both nms_neural_multiprocessor.v (Current NMS baseline) and
|
|
nms_neural_multiprocessor_pf.v (weight-prefetch variant) are
|
|
PRESERVED side-by-side in the repository per this STEP's own
|
|
explicit "keep the current working configuration available for A/B
|
|
comparison" constraint -- neither supersedes the other.
|
|
future_work: the real, evidence-backed next architectural question is
|
|
real PSRAM bandwidth itself (wider data bus, multiple independent
|
|
PSRAM banks/ports, or a different/faster backing memory technology)
|
|
-- explicitly flagged as future work, NOT undertaken this round per
|
|
this STEP's own "do not proceed to another major redesign without
|
|
evidence" instruction; STEP11's own evidence base (EXP-0024) is
|
|
exactly the evidence such a future redesign would need to start
|
|
from.
|
|
STATUS: STEP11 CLOSED. Outcome B (N_SLOTS=1, partial) / C (N_SLOTS=2,
|
|
failure against the 90% target). PFD=2 recommended if the engine is
|
|
used at all. NMS baseline (nms_neural_multiprocessor.v) remains the
|
|
project's own default reference configuration, unchanged.
|
|
|
|
DEC-0024
|
|
timestamp: 2026-09-06T01:00:00Z
|
|
topic: NMS STEP13 (batch/continuous processor) -- architectural
|
|
direction, chosen based on EXP-0025's own RTL trace rather than the
|
|
governing spec's own initial conceptual framing.
|
|
context: STEP13's own spec asked for a "batch/continuous neuron
|
|
execution model" (multiple neurons per dispatch, or a continuous
|
|
neuron stream) to amortize per-neuron control overhead, framed
|
|
around EXP-0024's ~68.5-cycles/neuron non-memory floor. Step 1 of
|
|
that spec explicitly required tracing the REAL RTL before assuming
|
|
where those cycles go, rather than accepting "dispatch overhead" as
|
|
a given label.
|
|
options_considered:
|
|
1. Batch/pipeline job dispatch (Model B/C from the governing spec:
|
|
amortize per-neuron dispatch overhead across K neurons or a
|
|
continuous neuron stream) -- REJECTED as the PRIMARY fix (though
|
|
still worth a secondary pass): EXP-0025's own cycle-exact trace
|
|
shows job-dispatch/drain overhead is only ~4.5 of the 68.5
|
|
cycles/neuron floor (6.6%). Batching neurons would leave 93.4% of
|
|
the real floor completely untouched.
|
|
2. Redesign neural_processor.v's own datapath/pipeline (Outcome C
|
|
from the governing spec) -- REJECTED: EXP-0025 shows NP's own
|
|
interface (operand_ready held continuously high through
|
|
NP_WAIT_OPERANDS) is ALREADY capable of accepting a new tile
|
|
every cycle; it is not the bottleneck and does not need to change
|
|
(consistent with STEP11's own established "do not modify
|
|
neural_processor.v unless absolutely necessary" precedent, which
|
|
continues to hold).
|
|
3. Pipeline the per-TILE operand-delivery logic inside the memory
|
|
manager (a NEW execution granularity: continuous tile streaming
|
|
within a job, via a read-ahead pipeline + skid buffer, decoupling
|
|
"issue the next tile's SRAM read" from "wait for the current tile
|
|
to be fully consumed") -- SELECTED. This directly targets the
|
|
93.4%-of-the-floor component EXP-0025 traced to
|
|
nms_memory_manager_pf.v's own un-pipelined
|
|
read_issued->read_ready->present->consumed chain (4 cycles/tile,
|
|
zero overlap between tiles, despite both the local SRAMs'
|
|
1-cycle read latency and NP's own continuous-acceptance capability
|
|
allowing a true 1-cycle/tile steady state).
|
|
decision: implement `nms_memory_manager_stream.v` as a NEW A/B variant
|
|
(nms_memory_manager_pf.v itself left UNTOUCHED, per this project's
|
|
own established "preserve the working baseline" discipline) that
|
|
replaces ST_RUN's sequential 4-state-per-tile chain with a pipelined
|
|
read-ahead design: a `rd_ptr` (read-issue pointer, independent of the
|
|
consumption pointer) that issues a new SRAM read every cycle it is
|
|
legal to do so (bounded by n_tiles/wgt_ready_count/usable_act, same
|
|
gating semantics as the old `can_present`), landing in a 1-deep skid
|
|
buffer that presents `operand_valid` to NP; NP's own continuous
|
|
operand_ready drains the skid buffer every cycle it is full, freeing
|
|
it for the next read's arrival the same cycle. Target: ~1 cycle/tile
|
|
steady state (down from 4), i.e. up to a real, RTL-level ~4x
|
|
reduction in the dominant floor component. weight_prefetch_engine.v
|
|
and the outer job FSM (ST_IDLE/ST_WAIT_RESULT/ST_WRITE_RES/ST_DONE)
|
|
are unchanged; only ST_RUN's internal operand-delivery logic differs.
|
|
Job-dispatch batching (Model B/C) is deferred as a SECONDARY,
|
|
smaller-impact follow-up, only worth pursuing once the dominant
|
|
93.4% component has been addressed and its own new ceiling measured.
|
|
STATUS: DIRECTION SET. Implementation, bit-exact verification, and
|
|
ideal-memory/real-memory re-benchmarking follow in EXP-0026+.
|
|
|
|
DEC-0025
|
|
timestamp: 2026-09-06T02:30:00Z
|
|
topic: NMS STEP13 (batch/continuous processor) -- final outcome and
|
|
adoption decision.
|
|
context: STEP13 asked whether changing execution granularity removes
|
|
the ~11.674%-utilization ceiling EXP-0024 found for N_SLOTS=2, and
|
|
demanded an experimentally-proven (not assumed) answer, with an
|
|
explicit A/B/C/D outcome framework.
|
|
evidence_summary:
|
|
- EXP-0025 (RTL trace, zero real memory latency): traced the ACTUAL
|
|
RTL rather than assuming -- found the dominant real floor (93.4%
|
|
of EXP-0024's measured "non-memory" cycles) is NOT per-job dispatch
|
|
overhead but a 4-cycles/tile FSM-serialization bug in
|
|
nms_memory_manager_pf.v's own ST_RUN state (read_issued->
|
|
read_ready->present->consumed, strictly sequential, zero overlap
|
|
between tiles), despite neither the local SRAMs (1-cycle latency)
|
|
nor neural_processor.v (designed for continuous 1-tile/cycle
|
|
acceptance) requiring this.
|
|
- This redirected the architecture AWAY from the governing spec's
|
|
own initial framing ("batch K neurons per dispatch") and TOWARD a
|
|
pipelined, continuous per-TILE operand-delivery redesign within
|
|
the memory manager -- a genuine example of evidence overriding an
|
|
initial conceptual hypothesis, exactly as the spec's own Step1
|
|
demanded ("do not assume the architecture from filenames/specs;
|
|
trace the actual RTL").
|
|
- nms_memory_manager_stream.v (NEW, DEC-0024) implements this fix: a
|
|
read-ahead pointer (rd_ptr) + 1-deep skid buffer, decoupling
|
|
"issue next tile's SRAM read" from "current tile consumed".
|
|
- EXP-0026 (isolated, real weight_prefetch_engine active): the fix
|
|
works exactly as designed, but immediately exposed a SECOND, freshly
|
|
discovered bottleneck at the SAME numeric value (4 cycles/tile):
|
|
weight_prefetch_engine.v's own word-fetch rate, capped by the real
|
|
16-bit PSRAM bus width (P_IN=8 bytes / 2 bytes-per-word = 4 word-
|
|
transactions/tile, 1 cycle/word minimum even at zero real latency).
|
|
Net real-system benefit at TODAY's bandwidth: ~0% (confirmed by
|
|
EXP-0028's real D-Stress re-benchmark: 185270 vs 185398 cycles,
|
|
-0.07%, noise-level).
|
|
- EXP-0027 (control experiment, weight-fetch bypassed -- the Step6
|
|
k->infinity endpoint): PROVES the fix removes a real, structural,
|
|
4x ceiling: with the weight-fetch bottleneck removed, the NEW
|
|
design achieves genuine 1-cycle/tile sustained throughput (100% of
|
|
P_IN=8's own theoretical per-tile acceptance rate), where the OLD
|
|
design (nms_memory_manager_pf.v, confirmed via EXP-0025's own
|
|
trace) is HARD-CAPPED at 4 cycles/tile (25%) regardless of
|
|
bandwidth -- it cannot benefit from ANY future bandwidth increase
|
|
without also fixing this same FSM-serialization bug.
|
|
- EXP-0028: bit-exact PASS (256/256 neurons), resource/Fmax
|
|
real-measured: both N=1 and N=2 PASS the 80MHz target
|
|
(142.92MHz/92.57MHz respectively), resource cost within +/-6% of
|
|
the "_pf" baseline -- no combinational-controller blowup.
|
|
decision: this is an Outcome B (STEP13's own framework: "batching/
|
|
continuous execution helps, but another bottleneck appears") --
|
|
SPECIFICALLY: the executed fix (continuous per-tile streaming, NOT
|
|
neuron-batching) is real, correct, bit-exact, and REMOVES a genuine,
|
|
previously-hidden, hard architectural ceiling in the memory manager
|
|
(proven via EXP-0027's direct control experiment). But it delivers
|
|
ZERO measurable improvement TODAY because a second, independent,
|
|
currently-co-dominant bottleneck (weight-fetch word-granularity,
|
|
tied to the real 16-bit PSRAM bus) already caps the system at
|
|
exactly the same rate -- this second bottleneck is a hardware
|
|
bandwidth-width constraint, NOT something any further on-chip
|
|
scheduling redesign (memory-manager pipelining, neuron batching, or
|
|
otherwise) can fix without ALSO widening the real external memory
|
|
interface.
|
|
ADOPT nms_memory_manager_stream.v / nms_dataflow_core_stream.v /
|
|
nms_neural_multiprocessor_stream.v as the NEW reference NMS
|
|
configuration going forward (strict improvement: same bit-exact
|
|
correctness, same resource/Fmax class, REQUIRED groundwork for any
|
|
future bandwidth increase to actually translate into a throughput
|
|
gain -- without this fix, a future wider/faster PSRAM would
|
|
immediately hit the OLD 4-cycles/tile FSM ceiling and deliver at
|
|
most 25% of the bandwidth improvement's potential benefit).
|
|
nms_memory_manager_pf.v and nms_memory_manager.v are BOTH preserved,
|
|
unmodified, for historical A/B/C reference, per this project's own
|
|
established discipline.
|
|
Neuron-batching (the spec's OWN original Model B/C) is NOT pursued
|
|
further: EXP-0025 already showed job-dispatch overhead is only ~4.5
|
|
of the ~68.5-cycle/neuron floor (6.6%) -- a much smaller opportunity
|
|
than the ~64-cycle/neuron (93.4%) tile-serialization bug just fixed,
|
|
and would deliver no benefit at today's bandwidth for the same
|
|
reason (weight-fetch-rate-bound).
|
|
STATUS: STEP13 CLOSED. Outcome B. Fix adopted (real, bit-exact,
|
|
resource-neutral, structurally necessary for any future bandwidth
|
|
gain), but the immediate, measurable N=2 utilization number is
|
|
UNCHANGED from EXP-0024's own baseline -- the honest answer to
|
|
"does N=4/N=8 become viable" is NOT YET: viability now depends
|
|
entirely on real external memory bandwidth (see the STEP13 summary
|
|
report's own final decision section for the precise quantification).
|
|
|
|
DEC-0026
|
|
timestamp: 2026-09-06T03:05:00Z
|
|
topic: NMS STEP14 Part B -- minimum fix for the N_SLOTS=4
|
|
activation-fill-controller Fmax regression.
|
|
context: EXP-0029's exact post-P&R critical-path trace located the
|
|
N=4 failure (55.22 MHz vs 80 MHz target) to two chained, un-
|
|
pipelined 16-bit magnitude comparisons inside
|
|
nms_activation_fill_ctrl.v: max_n_tiles's own computation (line 92,
|
|
an N_SLOTS-wide running-max over per-slot n_tiles) feeding DIRECTLY,
|
|
same-cycle, into the resident_count < max_n_tiles refill/continue
|
|
decision (line 165).
|
|
options_considered:
|
|
1. Redesign the whole fill controller (e.g. per-slot distributed
|
|
fill engines) -- REJECTED as disproportionate: the measured
|
|
critical path is two specific comparisons, not a structural
|
|
issue with the single-tag/shared-controller design itself
|
|
(DEC-0016's own choice, still valid).
|
|
2. Register max_n_tiles one cycle before its use in the
|
|
resident_count comparison -- SELECTED. This is the smallest
|
|
change that breaks the two chained comparisons into separate
|
|
clock edges, directly targeting the exact two RTL lines EXP-0029
|
|
identified. The refill-decision path is evaluated only once per
|
|
tile-fill-trigger boundary (not every per-tile-consumption cycle,
|
|
which STEP13's streaming fix already fully decoupled from this
|
|
controller) -- one added cycle of latency here has no measurable
|
|
effect on steady-state throughput.
|
|
decision: implement nms_activation_fill_ctrl_v2.v: identical external
|
|
interface and behavior to nms_activation_fill_ctrl.v, except
|
|
max_n_tiles is registered (max_n_tiles_reg <= max_n_tiles every
|
|
cycle, same combinational computation as before) and the ST_IDLE
|
|
refill/continue condition compares resident_count against
|
|
max_n_tiles_reg (the one-cycle-old, REGISTERED value) instead of the
|
|
same-cycle combinational max_n_tiles. nms_activation_fill_ctrl.v
|
|
itself is left UNTOUCHED (A/B preservation, same discipline as every
|
|
prior STEP). Verify: (1) real re-synthesis+P&R at N=4 reaches
|
|
>=80MHz, (2) bit-exact correctness unchanged (the one-cycle-later
|
|
refill decision cannot change WHAT gets fetched, only WHEN the
|
|
decision is made, and only at fill-trigger boundaries already
|
|
gated by pf_busy/state==ST_IDLE), (3) steady-state per-tile cycle
|
|
count unchanged (no new serialization introduced, per STEP14's own
|
|
explicit B4 requirement).
|
|
STATUS: implementation + verification follow in EXP-0030.
|
|
|
|
DEC-0027
|
|
timestamp: 2026-09-06T03:45:00Z
|
|
topic: NMS STEP14 Part B -- final decision on the activation-fill
|
|
controller timing fix.
|
|
evidence: EXP-0029 (exact critical path trace), EXP-0030 (2-stage fix,
|
|
N=4 Fmax 55.22->106.81MHz, +93.4%, bit-exact PASS, zero N=2
|
|
regression), EXP-0031 (N=8 exploratory: DSP/LUT/FF feasible, Fmax
|
|
still fails at 52.25MHz -- same O(N_SLOTS) fold, not yet addressed).
|
|
decision: ADOPT nms_activation_fill_ctrl_v3.v as the reference
|
|
activation-fill controller for N_SLOTS>=4 configurations. It is a
|
|
strict improvement (real Fmax +93.4% at N=4, bit-exact, resource-
|
|
neutral-to-slightly-cheaper, zero throughput regression at N=2) that
|
|
directly satisfies STEP14's own B4 requirement (higher Fmax +
|
|
preserved parallelism, not Fmax via serialization -- verified: N=2
|
|
cycle count and sustained MAC/cycle are numerically IDENTICAL
|
|
before/after this fix). nms_activation_fill_ctrl.v (original) and
|
|
nms_activation_fill_ctrl_v2.v (insufficient 1-stage fix) are
|
|
preserved for reference; v3 supersedes v2 as the working candidate.
|
|
N=8 remains NOT timing-feasible with this fix alone (Fmax=52.25MHz)
|
|
-- the underlying O(N_SLOTS) max-fold chain was shifted, not
|
|
eliminated. This is flagged as concrete future work (a genuine
|
|
balanced-tree or log2(N_SLOTS)-scaling pipeline for the fold stage)
|
|
and NOT undertaken this round, consistent with N=8's own explicit
|
|
"exploratory, does not need to pass" scope.
|
|
STATUS: Part B closed. N=4 acceptance criterion #3 (Fmax>=80MHz) is
|
|
MET (106.81MHz). Criteria #1/#2 (bit-exact, no deadlock) MET.
|
|
Criteria #4/#5 (throughput improvement, parallel efficiency) are
|
|
addressed jointly with Part A/C below, since Part B alone does not
|
|
change memory bandwidth -- see the STEP14 combined summary.
|
|
|
|
DEC-0028
|
|
timestamp: 2026-09-06T04:15:00Z
|
|
topic: NMS STEP14 Part A5 -- logical weight-path width vs. real
|
|
physical PSRAM bandwidth.
|
|
context: EXP-0032 established that a LOGICAL 64-bit weight interface
|
|
(weight_prefetch_engine_wide.v, simulation-only) removes the
|
|
weight-fetch bottleneck entirely (1 cycle/tile, matching the
|
|
streaming memory manager's own ceiling). STEP14's own explicit A5
|
|
instruction: do NOT assume a wider logical interface automatically
|
|
means the real physical memory can deliver that bandwidth --
|
|
measure the difference between logical and physical bandwidth
|
|
explicitly.
|
|
analysis (no new RTL/synthesis needed -- a direct consequence of
|
|
already-measured real data from STEP11-13): the REAL, physical V1
|
|
PSRAM chain (memory_interface.v -> psram_controller.v -> the real
|
|
ISSI IS66WVE4M16EBLL-70BLI x16 chip) is FIXED at a 16-bit physical
|
|
data bus -- this is real hardware, not an RTL parameter. The
|
|
ALREADY-EXISTING weight_prefetch_engine.v (real, 16-bit, used
|
|
throughout STEP11-13 and re-verified unchanged in STEP14 Part B) IS
|
|
PRECISELY what a "64-bit logical / 16-bit physical" packing adapter
|
|
would produce: it already assembles one 64-bit logical tile from
|
|
4 sequential real 16-bit word transactions -- exactly the packing
|
|
behavior A5 asks to explore. Its own real, repeatedly-measured
|
|
result (EXP-0025/26/28, real V1 PSRAM chain): 4 cycles/tile in
|
|
steady state, IDENTICAL to the MEM_DATA_WIDTH=16 ideal-memory result
|
|
from EXP-0032 -- because the REAL transaction count (4 sequential
|
|
16-bit word fetches) is unchanged regardless of what the LOGICAL
|
|
interface upstream claims its width is. A logical 64-bit (or wider)
|
|
interface, if backed by ONLY a real 16-bit physical bus, delivers
|
|
EXACTLY the same real throughput as a native 16-bit design -- the
|
|
logical width is not itself a source of real bandwidth; it is only
|
|
useful if the PHYSICAL interface is ALSO widened to match.
|
|
decision: no new "packing adapter" RTL module was built, since the
|
|
real, already-verified weight_prefetch_engine.v IS that adapter in
|
|
effect (logically requesting a 64-bit tile, physically issuing 4
|
|
real 16-bit transactions) and its real measured behavior already
|
|
answers A5 directly and conclusively: LOGICAL width alone provides
|
|
ZERO real throughput benefit without a matching PHYSICAL bandwidth
|
|
increase. To realize EXP-0032's ideal 64-bit ceiling (1 cycle/tile)
|
|
on real hardware would require the PHYSICAL PSRAM interface itself
|
|
to widen (e.g. a real 64-bit-wide external memory bus, or 4 parallel
|
|
16-bit PSRAM chips banked together) -- a board/silicon-level change,
|
|
explicitly outside this STEP's own RTL-scheduling scope, and NOT
|
|
something achievable by ANY further RTL redesign of
|
|
weight_prefetch_engine.v/nms_memory_manager_stream.v alone.
|
|
STATUS: Part A closed. The 64-bit architectural requirement is
|
|
precisely established (EXP-0032); its real-hardware realization is
|
|
explicitly a future hardware (not RTL) dependency.
|
|
|
|
DEC-0029
|
|
timestamp: 2026-09-06T05:45:00Z
|
|
topic: STEP15 -- physical memory bandwidth recommendation for the
|
|
next board revision.
|
|
evidence: EXP-0034 (real 16-bit baseline, 17.0 cycles/tile single-
|
|
slot), EXP-0035 (RTL-validated page-mode model, 32/64/128-bit:
|
|
9.0/5.0/5.0 cycles/tile, 128-bit confirmed a genuine plateau not a
|
|
regression), EXP-0036 (DERIVED full N=2/4/8 system projection:
|
|
16->32 bit gives 1.889x real speedup, 32->64 gives a further 1.80x,
|
|
64->128 gives none; utilization stays at 0.55%/1.05%/1.88%/1.88% of
|
|
theoretical throughout -- memory-bound at every width tested, no
|
|
crossover to compute-bound reached).
|
|
decision: recommend a 32-bit physical weight-fetch interface,
|
|
implemented as TWO parallel instances of the EXISTING, already-
|
|
qualified ISSI IS66WVE4M16EBLL-70BLI (16-bit each, shared address/
|
|
control bus, independent DQ), for the next board revision.
|
|
Rationale: (1) real, substantial ~1.9x end-to-end speedup, the
|
|
largest single real gain available from ANY bus-width change
|
|
investigated; (2) LOW risk -- reuses an already-qualified, already-
|
|
characterized part and controller family (psram_controller.v's own
|
|
timing model needs only straightforward duplication, not a new
|
|
protocol); (3) LOW-moderate PCB/pin cost (+~16 I/O pins over today's
|
|
45, one additional chip footprint) vs. 64-bit's +~48 pins and 3
|
|
additional footprints. 64-bit is NOT recommended for the immediate
|
|
next revision: its own additional ~1.8x gain is real but arrives at
|
|
much higher pin/PCB/power/routing cost, and the system remains
|
|
overwhelmingly memory-bound (1.88% utilization) even at 64-bit --
|
|
i.e. 64-bit is not "wasted" but is also nowhere near sufficient to
|
|
reach a genuinely compute-bound regime, making its extra cost harder
|
|
to justify as a STANDALONE next step. 128-bit is explicitly NOT
|
|
recommended -- confirmed (EXP-0035) to provide zero additional
|
|
benefit over 64-bit in this single-tile-per-request architecture.
|
|
Alternative technology flagged for a LONGER-TERM, more ambitious
|
|
future revision (not this one): HyperRAM/HyperBus or Octal-SPI
|
|
(xSPI) class memories offer a fundamentally different pin/bandwidth
|
|
trade-off (typically ~11-13 pins total, vs. today's 45 for 16-bit
|
|
parallel, or ~61/93 for 32/64-bit parallel) and could plausibly
|
|
exceed even a 64-bit parallel option's bandwidth at LOWER pin cost
|
|
-- but require an entirely new controller (different, DDR-based
|
|
protocol) and are a genuinely separate engineering initiative, not
|
|
a simple bus-width bump. Recommended as the direction to pursue IF
|
|
a future revision needs to seriously chase a much-higher utilization
|
|
target rather than the incremental (though real) gains a wider
|
|
parallel bus provides.
|
|
EXPLICIT CAVEAT carried forward from EXP-0036: the ~1.9x/1.8x real
|
|
speedup projections are DERIVED (calibrated against the real 16-bit
|
|
measurement, not independently re-measured in a full new multi-slot
|
|
RTL campaign at 32/64-bit) and could be optimistic if per-transaction
|
|
arbitration overhead does not scale down proportionally with
|
|
transaction duration -- flagged explicitly as the next concrete
|
|
experiment (see the STEP15 report's own final recommendation) before
|
|
committing board layout resources.
|
|
STATUS: STEP15 CLOSED. Recommendation stands pending the flagged
|
|
follow-up validation (full multi-slot RTL resynthesis at 32-bit) to
|
|
de-risk the DERIVED projection before committing to PCB layout.
|
|
|
|
DEC-0030
|
|
timestamp: 2026-09-06T07:00:00Z
|
|
topic: STEP15 continuation -- full RTL+synthesis+P&R validation of
|
|
the real dual-chip 32-bit PSRAM architecture (DEC-0029's own
|
|
recommendation), and reassessment of 64-bit given the validated
|
|
32-bit result.
|
|
evidence: EXP-0037 (dual-chip controller: 3 real bugs found and
|
|
fixed -- address-space mismatch, mem_ready timing misalignment,
|
|
testbench DEPTH-too-small -- bit-exact PASS post-fix, real cycles/
|
|
tile=8.5488, single-slot uncontended), EXP-0038 (full N=2/4 real
|
|
system, bit-exact PASS 256/256, REAL speedup 2.496x @ N=4 --
|
|
substantially exceeding the STEP15-prior-round DERIVED 1.89x
|
|
projection, traced to the separate-physical-port architecture
|
|
eliminating weight/activation/writeback cross-traffic contention,
|
|
not merely widening the bus), EXP-0039 (real synthesis+P&R for the
|
|
ACTUAL target LFE5U-45F-8CABGA381: a real I/O infeasibility found
|
|
and fixed -- 245 total TRELLIS_IO, 157 already committed, 88 free,
|
|
the first-draft separate-pin-per-chip interface needed 90 [2 over
|
|
budget]; fixed by sharing address/control between the two chips
|
|
[a real, valid PCB technique, not a synthesis trick] down to 61
|
|
pins; final: Fmax=110.28MHz PASS [actually EXCEEDING the STEP14
|
|
baseline's 106.81MHz], TRELLIS_IO=218/245 [88.9%, 27 spare],
|
|
resources +4-5% over baseline, bit-exact re-confirmed unchanged).
|
|
decision: EXECUTIVE CONCLUSION -- **YES WITH CONDITIONS**. The 32-bit
|
|
dual-chip PSRAM architecture is VALIDATED at RTL+synthesis+P&R
|
|
level: real 2.496x end-to-end speedup, real Fmax IMPROVEMENT
|
|
(110.28 vs 106.81MHz), real bit-exact correctness, real (if tight)
|
|
I/O feasibility on the actual target package. CONDITIONS: (1) the
|
|
design now consumes 88.9% of the package's total I/O (218/245) --
|
|
any FUTURE interface addition (e.g. a real host/SPI command
|
|
interface to replace the current wide parallel test-harness
|
|
registration port, which alone commits 181 of the 157 "existing"
|
|
pins) must be planned with this headroom in mind; (2) the address/
|
|
control-sharing pin optimization is a REQUIRED part of the
|
|
recommended architecture, not optional -- the naive "fully separate
|
|
per-chip pins" version does not fit this package at all.
|
|
64-bit REASSESSMENT: NOT PIN-FEASIBLE on this exact package as
|
|
currently architected -- a 4-chip 64-bit weight interface (same
|
|
address/control-sharing technique) needs 93 pins; combined with the
|
|
existing 157-pin commitment, this totals 250, exceeding the
|
|
package's own 245-pin budget by 5 pins, BEFORE even considering
|
|
Fmax/LUT/FF cost or the incremental-speedup-per-pin question Part 8
|
|
asked for. 64-bit is therefore NOT evaluated further as a real
|
|
option for this board revision without ALSO redesigning the
|
|
existing registration/host interface to free up pins -- a separate,
|
|
larger initiative outside this validation's own scope.
|
|
Full bandwidth breakdown (single-slot real, EXP-0037): nominal
|
|
320MB/s (32-bit@80MHz) -> usable 74.86MB/s (23.4% of nominal, 76.6%
|
|
lost to real per-transaction controller overhead -- NOT primarily
|
|
page-transitions specifically, which cost only ~1.6% of nominal;
|
|
the dominant loss is the fundamentally non-bursting, one-
|
|
transaction-at-a-time protocol) -> effective system-level (N=4,
|
|
real arbitration contention across 4 slots) 35.41MB/s (11.1% of
|
|
nominal). Compute utilization: 1.383% of the N=4 theoretical
|
|
32 MAC/cycle ceiling -- the architecture remains firmly memory-
|
|
bound, exactly as STEP15's own prior round predicted, now with a
|
|
real, independently-measured number rather than a projection.
|
|
STATUS: STEP15 continuation CLOSED. 32-bit dual-chip architecture
|
|
recommended for the next board revision, WITH the stated I/O-budget
|
|
conditions. 64-bit is off the table for THIS board without a
|
|
separate host-interface redesign. Full report:
|
|
hardware/v2/reports/step15_32bit_validation.md.
|
|
|
|
DEC-0031
|
|
timestamp: 2026-09-06T06:08:18Z
|
|
context: STEP16 -- definitive validation of a single Alliance Memory
|
|
AS4C4M16SA-6TIN SDR SDRAM chip against the already-validated
|
|
dual-PSRAM 32-bit architecture (DEC-0030), per the governing spec's
|
|
own explicit, binding closure instruction: reach ONE of A (adopt
|
|
SDRAM) / B (keep dual-PSRAM) / C (SDRAM superior but not worth it),
|
|
supported entirely by real RTL simulation, real synthesis, real
|
|
place & route, and real measured cycles -- never estimated -- and
|
|
treat the memory-exploration phase as closed afterward.
|
|
evidence: a real, isolated-and-validated sdram_controller.v (BURST_LEN
|
|
=4, matching the natural P_IN*DATA_WIDTH/16=4-word tile size) passed
|
|
9/9 real Verilator regressions (100/133/166MHz x burst 1/4/8,
|
|
460/460 tests each) after 5 real protocol bugs were found and fixed
|
|
via simulation (ERR-0016 through ERR-0020 -- an A10 address-bit
|
|
mis-position, two model-side one-cycle-late data-capture bugs, and
|
|
two variants of a real req/refresh arbitration race, the second only
|
|
exposed by the full-system Phase 5 integration benchmark, not the
|
|
isolated regression). Integrated into the real FPGA-Neural datapath
|
|
(nms_neural_multiprocessor_sdram.v, forked from the dual32 baseline
|
|
with ONLY the wide weight-fetch backend replaced) and benchmarked
|
|
with the real D-Stress workload (256 neurons, bit-exact vs golden)
|
|
at both N=2 (52161 cycles, 3.552x vs the original 16-bit baseline,
|
|
1.451x vs dual32) and N=4 (49430 cycles, 3.738x vs original, 1.498x
|
|
vs dual32). Real Yosys synthesis + nextpnr-ecp5 P&R for the actual
|
|
LFE5U-45F-8CABGA381 target succeeded at both N_SLOTS, with real I/O
|
|
headroom improved over the baseline (194/245 vs dual32's own 218/245
|
|
TRELLIS_IO) but real Fmax lower (81.55MHz best-of-3-seeds at N=4 vs
|
|
the baseline's own reported 110.28MHz, root cause of the gap not
|
|
conclusively isolated -- the limiting critical path traces entirely
|
|
to dependency_manager.v, unchanged shared logic, not the new SDRAM
|
|
design itself).
|
|
decision: A -- ADOPT SDRAM. The governing spec's own explicit decisive
|
|
test (does SDRAM's real N=4 speedup clearly exceed dual-PSRAM's own
|
|
2.496x?) is satisfied with real margin (3.738x, +49.7% relative),
|
|
not a marginal difference. SDRAM also wins real, measured PCB
|
|
simplicity (1 chip vs 2, ~38 pins vs 61, real 24-pin I/O saving) and
|
|
real N=4 effective bandwidth (53.04 vs 35.41 MB/s) despite HALF the
|
|
nominal raw bus width (160 vs 320 MB/s @80MHz) -- a genuine "measure,
|
|
don't assume nominal bandwidth wins" result. It loses on real Fmax
|
|
(81.55 vs 110.28MHz) and required more debugging (5 bugs vs 3),
|
|
both real, disclosed risks -- but both designs independently close
|
|
real timing at the actual 80MHz operating point the whole comparison
|
|
is built on, and the spec's own priority order does not make a
|
|
lower-priority shortfall (timing headroom) override a clear win on
|
|
the criterion it itself designated as decisive (performance vs the
|
|
2.496x reference, item 4, following correctness/reliability/timing
|
|
which neither design fails outright).
|
|
confidence: MEDIUM (not HIGH) -- the real, unresolved Fmax gap and the
|
|
larger real protocol surface (more bugs found, all now fixed and
|
|
reverified) are genuine, disclosed reasons for caution, even though
|
|
they do not change the decision itself.
|
|
STATUS: STEP16 CLOSED. Hardware memory architecture for V2: single-
|
|
chip SDR SDRAM (Alliance Memory AS4C4M16SA-6TIN), BURST_LEN=4
|
|
controller. Per the governing spec's own explicit, binding
|
|
instruction, the memory-exploration phase is now closed -- no
|
|
further alternative memory technologies will be proposed for V2
|
|
unless a technical violation makes this validation impossible to
|
|
stand on as written. Full report:
|
|
hardware/v2/reports/step16_sdram_validation.md.
|
|
|
|
DEC-0032
|
|
timestamp: 2026-09-06T10:22:22Z
|
|
context: STEP17 -- real N=4 timing-closure investigation and
|
|
throughput decomposition for the SDRAM architecture adopted in
|
|
DEC-0031. Explicitly NOT reopening the SDRAM-vs-dual-PSRAM decision;
|
|
scope is understanding and (if safely possible) improving the N=4
|
|
Fmax margin, and characterizing where the 49,430 D-Stress cycles are
|
|
actually spent.
|
|
evidence: real post-P&R critical-path tracing (EXP-0044) shows the
|
|
N=4 Fmax ceiling (81.55MHz best-of-3-seeds) is dominated by
|
|
dependency_manager.v's own first_ready_idx priority-encoder scan --
|
|
a module completely unchanged from the dual-PSRAM baseline. Re-
|
|
synthesizing that SAME unmodified baseline at N=4 with the identical
|
|
toolchain gives only 87.26MHz best-of-3-seeds, NOT the originally
|
|
reported 110.28MHz -- meaning the real, apples-to-apples SDRAM-vs-
|
|
dual-PSRAM Fmax gap at N=4 is ~7%, not ~26%. Both architectures show
|
|
a large, shared N=2->N=4 Fmax drop, confirming N-scaling (not SDRAM
|
|
integration) as the primary driver. A candidate minimal fix
|
|
(pipelining the priority-encoder scan by one cycle) was implemented
|
|
and found to introduce a real double-dispatch correctness bug
|
|
(ERR-0021) on a second, more careful attempt too -- reverted in
|
|
full. Separately, real cycle-decomposition and SDRAM-controller
|
|
instrumentation (EXP-0045) shows the N=4 system is memory-bandwidth-
|
|
bound (SDRAM controller busy 99.92% of the run, request latency at
|
|
its own fixed minimum), with real processors delivering a useful
|
|
tile only ~2.06% of the available slot-cycle budget.
|
|
decision: KEEP the STEP16 SDRAM RTL and architecture EXACTLY as
|
|
validated, with NO changes. N=4 already meets the governing spec's
|
|
own hard minimum (Fmax >= 80MHz: 81.55MHz, POST-P&R, best-of-3-
|
|
seeds) without any modification. Do not ship the attempted
|
|
dependency_manager.v pipeline fix (reverted, real correctness risk
|
|
in a heavily-reused shared module, for a Fmax gain that further
|
|
analysis shows was based on a non-reproducible baseline comparison
|
|
anyway). Do not pursue N=8 this round (memory-bandwidth-bound
|
|
behavior at N=4 already, confirmed by real controller-busy
|
|
measurements, means N=8 would need an external-memory-bandwidth
|
|
improvement first to pay off, not merely more parallelism).
|
|
rationale: per the governing spec's own FINAL RULE ("preserve the
|
|
working architecture... the objective is not the prettiest Fmax
|
|
number"), a real, measured, hard-minimum-satisfying result that
|
|
requires no RTL change is preferred over an unproven timing
|
|
optimization with a demonstrated correctness failure mode, especially
|
|
once the underlying comparison motivating the optimization (110.28
|
|
vs 81.55MHz) was itself shown to not be apples-to-apples.
|
|
STATUS: STEP17 CLOSED. N=4 SDRAM architecture (STEP16, DEC-0031)
|
|
stands, unmodified, as the validated V2 baseline: Fmax 81.55MHz
|
|
(POST-P&R, best-of-3-seeds, >=80MHz hard minimum met), 49430 D-Stress
|
|
cycles, bit-exact PASS, real bottleneck for further throughput
|
|
identified as external SDRAM bandwidth (not compute, not Fmax, not
|
|
arbitration). Full report:
|
|
hardware/v2/reports/step17_n4_timing_throughput.md.
|
|
|
|
DEC-0033
|
|
timestamp: 2026-09-06T10:45:21Z
|
|
context: STEP18 -- SDRAM transaction efficiency and weight-path
|
|
scaling. Explicitly NOT reopening the SDRAM device choice (DEC-0031/
|
|
0032 remain closed). Scope: extract maximum useful throughput from
|
|
the already-adopted single-chip AS4C4M16SA-6TIN SDRAM architecture
|
|
via transaction/packing/burst/buffer changes only.
|
|
evidence: real measurement (EXP-0047) refutes the governing spec's own
|
|
stated working hypothesis (multiple transactions per tile) --
|
|
STEP16 already achieves exactly 1 transaction/tile via MEM_DATA_
|
|
WIDTH=64. The real inefficiency is fixed per-transaction always-
|
|
precharge overhead (6 of 10 cycles at BURST_LEN=4). A new memory-
|
|
side-only module, sdram_weight_backend_pack128.v (BURST_LEN=8, 2
|
|
tiles/real transaction, N_ENTRIES=4 address-tagged cache), was
|
|
built, and after fixing a real single-entry-cache regression found
|
|
via full-system benchmarking (ERR-0022), delivers a real, validated,
|
|
bit-exact 9.1% D-Stress cycle reduction at BOTH N=2 and N=4
|
|
(EXP-0046), with N=4 Fmax essentially unchanged (81.47 vs 81.55MHz,
|
|
POST-P&R, best-of-3-seeds) and a modest resource increase (TRELLIS_
|
|
FF +4.3%, TRELLIS_COMB +10.7%, no new I/O pins).
|
|
decision: ADOPT sdram_weight_backend_pack128.v (BURST_LEN=8,
|
|
N_ENTRIES=4) as the new N=4 (and N=2) V2 weight-fetch backend,
|
|
replacing STEP16's sdram_weight_backend.v (BURST_LEN=4, no cache).
|
|
weight_prefetch_engine_wide.v, neural_processor.v, dependency_
|
|
manager.v, and the STEP13 streaming tile-delivery architecture are
|
|
all UNCHANGED -- this is a pure memory-side substitution. All ten
|
|
of the governing spec's own decision criteria are satisfied: bit-
|
|
exact, no deadlock/timeout/dropped-or-duplicated jobs, SDRAM
|
|
protocol correct (reuses the already-validated sdram_controller.v
|
|
unmodified, just at BURST_LEN=8), N=4 Fmax>=80MHz (81.47MHz),
|
|
D-Stress cycles improve (-9.1%), sustained MAC/cycle improves
|
|
(+10.0%), memory efficiency improves (33.2%->36.5% of nominal
|
|
bandwidth), no hidden processor serialization.
|
|
Also decided: do NOT attempt a true multi-outstanding-request
|
|
controller redesign or a page-mode/keep-row-open controller rewrite
|
|
this round -- both are real, correctly-identified further
|
|
opportunities (the row-open/close overhead specifically IS now the
|
|
next bottleneck), but are materially larger changes than this
|
|
round's "smallest possible" mandate; deferred as explicit future
|
|
work, not silently dropped.
|
|
STATUS: STEP18 CLOSED. New V2 baseline: N=4 SDRAM with the pack128
|
|
weight-fetch backend -- 44,935 D-Stress cycles (vs 49,430 before),
|
|
Fmax 81.47MHz (POST-P&R, best-of-3-seeds, >=80MHz met), bit-exact
|
|
PASS, 194/245 I/O (unchanged). Next bottleneck identified as the
|
|
SDRAM controller's own fixed always-precharge transaction overhead,
|
|
not physical bandwidth, burst organization, Memory Manager,
|
|
activation traffic, or compute. Full report:
|
|
hardware/v2/reports/step18_sdram_transaction_efficiency.md.
|
|
|
|
DEC-0034
|
|
timestamp: 2026-09-06T11:26:46Z
|
|
context: FPGA-Neural V2 FASE #1 hardware freeze -- the user's own
|
|
explicit, binding requirement: the physical V2 board must have
|
|
EXACTLY ONE external memory device (SDRAM), serving weights,
|
|
activations, AND results. The prior architecture (STEP16-18) still
|
|
physically depended on hardware/v1/rtl/psram_controller.v for
|
|
activation-fill and result-writeback -- a real, disqualifying gap
|
|
the audit surfaced, not a cosmetic detail (it meant the V2 board, as
|
|
validated through STEP18, would have needed TWO physical memory
|
|
chips, not one).
|
|
evidence: built sdram_unified_backend.v (EXP-0048), a new memory-side-
|
|
only module presenting the same external contracts weight_prefetch_
|
|
engine_wide.v, nms_activation_fill_ctrl_v3.v, and nms_memory_
|
|
manager_stream_wide.v already used -- none of those modules, nor
|
|
neural_processor.v, nor dependency_manager.v, changed at all. Real
|
|
SDR SDRAM DQM per-byte write masking (a genuine, tested extension to
|
|
sdram_controller.v, zero regression across 461/461 tests at all 9
|
|
existing frequency/burst configs) makes single-byte result writes
|
|
correct inside a shared 128-bit burst with no read-modify-write.
|
|
After fixing a real deadlock and a real off-by-one data-corruption
|
|
bug found via full-system (not isolated) testing (ERR-0023), the
|
|
full N=4 AND N=2 D-Stress benchmark passes bit-exact (256/256),
|
|
with real sustained operation across 40 real AUTO REFRESH events.
|
|
Real post-P&R synthesis confirms a real 45-pin I/O reduction
|
|
(194->149/245 TRELLIS_IO) exactly matching the removed PSRAM
|
|
interface's own pin count, and comparable-or-better LUT/FF resource
|
|
usage. Real timing, however, REGRESSED: only 1/8 P&R seeds reach
|
|
>=80MHz (66.97-81.84MHz range) vs the STEP18 dual-memory baseline's
|
|
own 5/8 -- a real, disclosed, unresolved CRITICAL finding, not
|
|
hidden by citing only the best seed. The critical path itself is
|
|
unchanged (still dependency_manager.v's own pre-existing first_
|
|
ready_idx/reg_ready chain, confirmed by direct P&R critical-path
|
|
tracing on the best seed) -- the regression is attributed to overall
|
|
added die/routing pressure squeezing an already-marginal, shared,
|
|
pre-existing bottleneck, not a new defect in the new RTL.
|
|
decision: ADOPT the single-SDRAM architecture (nms_neural_
|
|
multiprocessor_sdram_unified.v) as the V2 FASE #1 hardware-freeze
|
|
reference, per the user's own explicit, binding mandate -- this
|
|
decision is NOT contingent on matching or beating STEP18's own
|
|
Fmax, since the governing spec explicitly prioritizes the single-
|
|
external-memory architectural constraint over Fmax margin ("prima
|
|
rendi il sistema CORRECT... poi misura... NON introdurre una
|
|
seconda memoria per risolvere il problema"). hardware/v1/rtl/
|
|
psram_controller.v and memory_interface.v are REMOVED from the V2
|
|
physical instantiation path (not modified -- V1 itself remains
|
|
fully intact and untouched, still the golden reference, still real,
|
|
synthesizable, and still used by nothing in the frozen V2
|
|
hierarchy). The real memory map (weights @0x010000, activations
|
|
@0x200000, results @0x300000, all within the single 8MB SDRAM) is
|
|
now the official V2 addressing convention -- see MEMORY_ARCHITECTURE
|
|
.md.
|
|
Explicitly NOT resolved this round (real, disclosed OPEN/CRITICAL
|
|
items, not silently dropped): the MARGINAL (1/8 seed) timing result
|
|
itself; a true ball-level V2 pinout (still blocked on the real
|
|
Lattice CABGA381 pin-map data source, unavailable this session); the
|
|
16MHz-oscillator-vs-80MHz-system-clock gap (no PLL exists in the
|
|
RTL); a physical (non-parallel-bus) host interface (the 110-pin
|
|
raw reg_* bus is a test-harness convenience, not a real board
|
|
interface); power/configuration-flash component selection.
|
|
STATUS: FASE #1 (hardware freeze scope) CLOSED for the architectural
|
|
decision itself -- single external SDRAM is the definitive V2
|
|
memory architecture, PSRAM dependency is REMOVED from the V2
|
|
physical path. CHIP READINESS remains NO overall (see CHIP_
|
|
READINESS.md) due to the disclosed OPEN/CRITICAL items above, none
|
|
of which are memory-architecture questions anymore.
|
|
|
|
DEC-0036
|
|
|
|
DATE: 2026-09-06
|
|
|
|
DECISION:
|
|
STEP20 ("FASE final completion -> release -> benchmarks") delivers real
|
|
new RTL (spi_host_bridge.v, ecp5_pll_sys_clk.v, reset_sync.v, the
|
|
board-level fpga_neural_v2_top.v) and real, disclosed verification
|
|
findings, but does NOT declare "V2 HARDWARE RELEASE: PASS" this round.
|
|
Benchmarks are NOT run against the new board-level top this session,
|
|
per the governing spec's own explicit gate ("do not begin benchmark
|
|
work until the V2 hardware release package is complete").
|
|
|
|
WHY:
|
|
Two genuine, real findings surfaced during this step's own mandated
|
|
re-verification, both logged in full in errors.log:
|
|
- ERR-0024: the CURRENT Icarus Verilog v13.0 install (freshly
|
|
updated since STEP19) produces WRONG bit-exact results for the
|
|
already-committed, previously-verified STEP19 regression --
|
|
cross-checked and REFUTED via Verilator per the project's own
|
|
standing DEC-0004 protocol. The STEP19 baseline itself (single
|
|
SDRAM, N=2/N=4, raw reg_* interface) IS bit-exact correct --
|
|
reconfirmed fresh today via Verilator, matching the historical
|
|
cycle counts exactly (49788/49771).
|
|
- ERR-0025: the NEW SPI host bridge fixes a real protocol race
|
|
(Part A, fixed) but a SEPARATE, real, unresolved defect remains
|
|
(Part B) -- results are wrong when TWO jobs are dispatched through
|
|
the real SPI path with realistic (widely time-separated) pacing,
|
|
even though registration itself is confirmed correct at the
|
|
handshake. Root cause NOT yet isolated to a specific module.
|
|
|
|
Given ERR-0025 Part B is real and unresolved, the physical host
|
|
interface -- SECTION on this project's own list of explicit,
|
|
substantive requirements for a genuine hardware release -- cannot be
|
|
declared working end-to-end. Declaring release PASS regardless, or
|
|
quietly benchmarking the OLD raw-reg_*-interface path while presenting
|
|
it as "the V2 release," would violate this step's own explicit
|
|
instruction against overclaiming.
|
|
|
|
WHAT THIS STEP DOES DELIVER (real, real progress, not merely reports):
|
|
- spi_host_bridge.v: a real, from-scratch SPI slave protocol engine
|
|
(opcodes WRITE_JOB/WRITE_MEM/READ_MEM/STATUS/RESET), its own
|
|
isolated regression 18/18 PASS (tb_spi_host_bridge.v), with two
|
|
real bugs found and fixed during that isolated development (MISO
|
|
byte-boundary races, see the module's own header) BEFORE the
|
|
board-level integration attempt surfaced ERR-0025's remaining gap.
|
|
- ecp5_pll_sys_clk.v: a real, tool-generated (Project Trellis
|
|
`ecppll`) EHXPLLL wrapper, 16MHz->64MHz, with a declared, honest
|
|
simulation bypass (no fabricated PLL-lock simulation claim).
|
|
- reset_sync.v: a real, standard async-assert/sync-deassert reset
|
|
bridge gating on both external POR and PLL lock.
|
|
- fpga_neural_v2_top.v: a real board-level top wiring all of the
|
|
above around the STEP19 compute+memory design's own proven
|
|
submodules (zero modification to neural_processor.v,
|
|
dependency_manager.v, sdram_unified_backend.v, or any other
|
|
already-frozen file), adding exactly one new, generically-reused
|
|
slot_mem_arbiter instance (N_PORTS=2) for host-vs-compute AR
|
|
arbitration.
|
|
- Two tooling-compatibility fixes (nms_memory_manager_stream_wide.v
|
|
declaration-order, tb_nms_dstress_sdram_unified.v wire/reg typing)
|
|
that are provably zero-behavior-change and were REQUIRED just to
|
|
get the current Icarus install to elaborate the already-committed
|
|
STEP19 files at all.
|
|
|
|
STATUS: V2 HARDWARE RELEASE: FAIL (not yet). ERR-0025 Part B is the
|
|
single blocking item. Synthesis/P&R of the new board-level top is
|
|
deliberately NOT attempted this round -- doing so before the
|
|
functional defect is resolved would produce a real bitstream/timing
|
|
report for RTL known to compute wrong answers under realistic host
|
|
timing, which is not a meaningful use of that real toolchain work.
|