Replace the serial "last-match-wins" priority-scan hit-index encoder with a flat one-hot compare + single-level priority encode, breaking the serially-dependent PFUMX/OFX cascade real P&R showed dominating the N_SLOTS=8 @ 64MHz critical path (55.84MHz worst, 4/8 seeds PASS). Real nextpnr-ecp5 re-verification (32-run matrix, 4 configs x 8 seeds): N_SLOTS=8 @ 64MHz improves to 5/8 PASS (worst 60.12MHz, up from 55.84MHz). N_SLOTS=4 @ 64MHz stays 8/8 PASS but with reduced worst-case margin (WNS +0.605ns, down from +2.143ns) as the critical path relocates to a different, previously-second-worst path in the same module -- a real, disclosed trade-off, not hidden. 80MHz remains NO-GO at both processor counts (re-confirmed on the fixed RTL). Bit-exact, zero functional regression: isolated tb_sdram_unified_backend.v (40/40) and full D-Stress N=4/N=8 (both 256/256 neurons bit-exact vs golden model). See errors.log ERR-0029 and decisions.log DEC-0040 for full root-cause writeup and MEMORY_UPGRADE_64MB_N8.md section 10 for the complete measured data set and AS4C32M16SB-7BIN pinout tables. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
2278 lines
120 KiB
Plaintext
2278 lines
120 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.
|
|
|
|
DEC-0037
|
|
|
|
DATE: 2026-09-06
|
|
|
|
DECISION:
|
|
ERR-0025 Part B (real, downstream defect blocking the physical SPI
|
|
host interface's own end-to-end correctness) is RESOLVED. The fix
|
|
(combinational reads in nms_weight_packed.v / nms_activation_
|
|
replicated.v, see errors.log's own "ERR-0025 Part B -- RESOLUTION"
|
|
entry for the full root-cause writeup) is verified to introduce ZERO
|
|
regression against the STEP19 baseline (N=2/N=4 D-Stress, identical
|
|
cycle counts, still bit-exact) while making the NEW STEP20 board-level
|
|
integration path (SPI -> dependency_manager -> compute -> SDRAM ->
|
|
result) correct under both tight and realistic-gap job dispatch.
|
|
|
|
This REVISES DEC-0036's own "V2 HARDWARE RELEASE: FAIL" conclusion:
|
|
the single blocking item DEC-0036 identified is now closed. The
|
|
physical SPI host interface is no longer just "protocol-correct in
|
|
isolation" -- it is now verified correct end-to-end, matching the same
|
|
bit-exact standard already established for the raw reg_* interface.
|
|
|
|
NEXT STEP (not yet performed this round, per the governing spec's own
|
|
explicit sequencing -- "prepara il repository per il passo successivo:
|
|
synthesis/P&R del vero fpga_neural_v2_top... NON eseguire benchmark
|
|
finche' ERR-0025 Part B non e' completamente chiuso e la V2 non ha
|
|
superato synthesis/P&R"): real synthesis and P&R of fpga_neural_v2_top.v
|
|
against a real, ball-assigned LPF, to determine the real, achievable
|
|
operating frequency for the board-level top (including the SPI bridge
|
|
and the new host-arb arbitration layer) -- this was deliberately not
|
|
attempted before now, since running the real toolchain against RTL
|
|
known to compute wrong answers would not have been a meaningful
|
|
result. That reason no longer applies.
|
|
|
|
DEC-0038
|
|
|
|
DATE: 2026-09-06
|
|
|
|
DECISION:
|
|
The SDRAM datasheet-parameter audit (PRE-PCB VERIFICATION FREEZE,
|
|
section 8) is CLOSED. Every timing parameter in hardware/v2/nms/rtl/
|
|
sdram_controller.v was cross-checked against the real Alliance Memory
|
|
AS4C4M16SA-6TIN datasheet (Rev 5.0, Table 17) at the real 64MHz target
|
|
frequency, not merely re-cited from a previous, uncross-checked
|
|
baseline. This found and closed ERR-0026 (T_MRD unit mismatch -- see
|
|
errors.log), the only genuine discrepancy found. tRCD, tRP, tRAS,
|
|
tWR, tMRD, tREFI are all now confirmed correct at 64MHz with zero
|
|
regression to the existing bit-exact regression suite. See
|
|
hardware/v2/docs/PRE_PCB_VERIFICATION.md for the full parameter-by-
|
|
parameter table (DATASHEET PARAMETER -> REQUIRED VALUE -> RTL VALUE ->
|
|
STATUS).
|
|
This REVISES CHIP_READINESS.md/OPEN_ITEMS.md's own prior "SDRAM
|
|
datasheet-parameter cross-check: OPEN (sim-level only)" status to
|
|
CLOSED.
|
|
|
|
DEC-0039
|
|
|
|
DATE: 2026-09-07
|
|
|
|
DECISION:
|
|
The single external SDRAM is UPGRADED from Alliance Memory
|
|
AS4C4M16SA-6TIN (64Mbit/8MB, 4 banks x 4096 rows x 256 cols, 12 address
|
|
pins A0-A11) to Alliance Memory AS4C32M16SB-7BIN (54-ball TFBGA
|
|
package, per the user's own explicit package choice -- the TSOP-II
|
|
sibling AS4C32M16SB-7TIN is the same die/organization/timing and was
|
|
also confirmed real/in-stock, should package choice be reconsidered
|
|
during layout) (512Mbit/64MB, 4 banks
|
|
x 8192 rows x 1024 cols, 13 address pins A0-A12 -- one new pin,
|
|
sdram_a[12], real ball F1/bank6, added to v2_board_top.lpf). This
|
|
followed a real, from-datasheet investigation of the whole Alliance
|
|
Memory SDR SDRAM family (AS4C4M16SA/AS4C8M16SA/AS4C16M16SA/
|
|
AS4C32M16SA, all confirmed same package/pinout family via their own
|
|
real datasheets) at the user's own explicit request, after establishing
|
|
that 8MB was not a hard capacity ceiling for this accelerator's actual
|
|
compute throughput (D-Stress: 32,768 weights takes 49,771 cycles/
|
|
777us at 64MHz -- a 24MB weight budget at the same rate would take
|
|
~580ms/inference, already compute-bound long before memory-bound).
|
|
"SA" vs "SB" in the part number is a die-shrink revision (Alliance's
|
|
own standard practice, confirmed via their own datasheet revision
|
|
history), NOT a functional/pinout difference -- "SB" is the currently
|
|
orderable die at real distributors (DigiKey: 568 units in stock,
|
|
$31.12/unit for the frozen BGA package as of this session; "SA" did
|
|
not surface as a current distributor listing for this exact
|
|
package/temp-grade combination).
|
|
Real -7-grade AC timing (144MHz max, `far above our 64MHz target):
|
|
tRCD=15ns, tRP=15ns (both BETTER than the previous part's 18ns), tRAS=
|
|
45ns/100000ns, tRC=65ns, tMRD=2 CLK (fixed, explicit units, no
|
|
ambiguity), tREFI=7.8125us (HALF the previous part's 15.625us, since
|
|
8192 rows must refresh in the same 64ms window).
|
|
|
|
This REQUIRED a real SPI protocol change (spi_host_bridge.v): the
|
|
26-bit byte address (up from 23 bits) no longer fits in 3 bytes (24
|
|
bits) with a spare reserved bit -- every address field (x_base/w_base/
|
|
result_addr in WRITE_JOB, addr in WRITE_MEM/READ_MEM) widened from 3
|
|
to 4 bytes. WRITE_JOB grew from 15 to 18 payload bytes; the WRITE_MEM/
|
|
READ_MEM header grew from 5 to 6 bytes.
|
|
|
|
This ALSO exposed two real, pre-existing timing-scaling issues, found
|
|
via real nextpnr-ecp5 P&R re-verification (not assumed): see errors.log
|
|
ERR-0027 (neural_director.v's own runtime-indexed demux write, fixed,
|
|
N_SLOTS=4 now fully reliable at 64MHz across all 8 tested seeds) and
|
|
ERR-0028 (nms_activation_fill_ctrl_v3.v's own linear N_SLOTS-wide max
|
|
scan, fixed, N_SLOTS=8 significantly improved but not yet fully
|
|
reliable -- 5/8 seeds close timing at 64MHz).
|
|
|
|
Full regression re-verified against BOTH the memory upgrade and both
|
|
RTL fixes with zero functional regression: sdram_controller (461/461,
|
|
18 configs), tb_sdram_boundary (21/21, real+cross-checked 64/166MHz),
|
|
D-Stress N=2/N=4/N=8 (bit-exact, identical cycle counts to the
|
|
pre-upgrade baseline), tb_spi_host_bridge (18/18), board-level SPI
|
|
smoke test (11/11, real 64MHz clk_sys), tb_sdram_unified_backend
|
|
(40/40).
|
|
|
|
STATUS: Memory upgrade CLOSED and verified. N_SLOTS=4 clock closure
|
|
CLOSED (64MHz, all seeds). N_SLOTS=8 clock closure OPEN (64MHz, 5/8
|
|
seeds) -- a real, disclosed, not-yet-fully-resolved finding, not
|
|
silently claimed complete. 80MHz (the user's own stretch preference)
|
|
is NOT achievable with the current architecture at either N_SLOTS
|
|
value -- confirmed via a real 80MHz-targeted PLL regeneration and
|
|
P&R re-run, all seeds failing -- consistent with this project's own
|
|
prior documented conclusion (ecp5_pll_sys_clk.v's own header: "64MHz
|
|
was chosen... the highest frequency at which ALL measured seeds close
|
|
timing with real margin").
|
|
|
|
DEC-0040 -- N_SLOTS=8 @ 64MHz weight-cache hit-index optimization
|
|
(ERR-0029): accepted a measured, disclosed N_SLOTS=4 margin reduction
|
|
in exchange for a measured N_SLOTS=8 pass-rate improvement
|
|
|
|
DATE: 2026-09-07
|
|
CONTEXT: user-mandated root-cause investigation and optimization of
|
|
DEC-0039's own remaining open item (N_SLOTS=8 @ 64MHz not fully
|
|
timing-closed), under an explicit constraint set: N_SLOTS=4 must stay
|
|
8/8 PASS and not "regress into a hardware concern," N_SLOTS=8 must
|
|
measurably improve (by the real routed critical path, not synthesis
|
|
LUT counts), full regression must stay bit-exact, and the complete
|
|
8-seed matrix must be re-run and reported honestly either way.
|
|
DECISION: applied ERR-0029's fix (sdram_unified_backend.v's weight-
|
|
cache hit-index: serial priority-scan -> flat one-hot compare + single-
|
|
level priority encode). Re-ran the full real nextpnr-ecp5 32-run matrix
|
|
(4 configs x 8 seeds) post-fix:
|
|
N_SLOTS=4 @ 64MHz: 8/8 PASS (unchanged pass count), worst-case WNS
|
|
fell from +2.143ns to +0.605ns (worst seed Fmax 74.17->66.58MHz).
|
|
Real cause: the critical path relocated off the (shortened) hit-
|
|
index chain onto a different, previously-second-worst path in the
|
|
same module, which this seed set happens to route less favorably.
|
|
N_SLOTS=8 @ 64MHz: pass count improved 4/8 -> 5/8, worst-case Fmax
|
|
55.84->60.12MHz, worst WNS -2.284ns->-1.009ns.
|
|
N_SLOTS=4/8 @ 80MHz: unchanged, still 0/8 both -- NO-GO confirmed
|
|
again on the fixed RTL.
|
|
ACCEPTED, not rejected: N_SLOTS=4 @ 64MHz remains a real 8/8 PASS
|
|
(all seeds have positive WNS -- no seed fails), which is this project's
|
|
own stated acceptance bar; the margin reduction is disclosed here and
|
|
in errors.log ERR-0029, not hidden. N_SLOTS=8 is a genuine, measured
|
|
improvement toward closure but is explicitly NOT declared fully closed
|
|
(3/8 seeds still fail, now via a still-different critical path -- a
|
|
further iteration, e.g. constraining nextpnr's placement region for
|
|
u_sdram_backend or exploring more seeds, remains a real OPEN item, not
|
|
attempted here).
|
|
Full regression re-verified after this fix: isolated
|
|
tb_sdram_unified_backend.v (40/40, bit-exact), full D-Stress N_SLOTS=4
|
|
(49927 cycles, 256/256 neurons bit-exact vs golden) and N_SLOTS=8
|
|
(49909 cycles, 256/256 neurons bit-exact vs golden) -- zero functional
|
|
regression at either processor count.
|
|
STATUS: N_SLOTS=4 @ 64MHz remains the frozen production baseline (8/8
|
|
PASS, real positive margin on every seed). N_SLOTS=8 @ 64MHz OPEN,
|
|
improved but not closed (5/8 PASS). 80MHz NO-GO at either N_SLOTS,
|
|
reconfirmed on the fixed RTL. File changed: hardware/v2/nms/rtl/
|
|
sdram_unified_backend.v.
|