feat: MILESTONE - real activation-fetch engine, full N=2 system verified on real DDR3 (EXP-0079)
Closes the last major disclosed functional gap: packed_slot.v's activation data was read through a combinational stand-in since EXP-0062. New act_tile_fetch.v reads activation tiles directly from DDR3 (no on-chip buffering needed, unlike weights -- activation data has no reuse), sharing each slot's existing ctrl port with its own weight-prefetch engine. Real memory layout: one full BURST_LEN=8-word burst per tile, deliberately avoiding any runtime-indexed part-select given this project's thin P&R timing margin (EXP-0078). Verified at three levels: act_tile_fetch.v alone (6/6), packed_slot.v with real preloaded activation data (9/9), and the full N=2 system against real DDR3 via xsim (8/8, 0 errors) -- the first time this project's compute path has been verified end-to-end with real DDR3 for both weights and activations. Retired hardware/v3/rtl/n2_system_top.v and its testbench (pre-DDR3 SDR-placeholder era, fully superseded by n2_system_ddr3_top.v). Also: docs/PHYSICAL_REALIZATION.md (real pinout/parts/timing/protocol reference for the physical board) and CLAUDE.md (persistent project instructions for future Claude Code sessions). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
This commit is contained in:
@@ -4933,3 +4933,101 @@ checkpoint. Remaining open work (scaling past N=2, a real activation-
|
||||
fetch engine, PCB-specific pin constraints once the board layout is
|
||||
underway, ESP32-side JTAG bootstrap firmware) is all disclosed and
|
||||
outside this experiment's own scope.
|
||||
|
||||
EXP-0079 -- MILESTONE: real activation-fetch engine built, closing
|
||||
the last major disclosed functional gap; full N=2 system re-verified
|
||||
end-to-end with REAL DDR3 for BOTH weights and activations
|
||||
(2026-09-20, same autonomous continuation, user's own explicit
|
||||
request: "completiamo quello che manca per avere un codice ready to
|
||||
use nell'hardware fisico")
|
||||
|
||||
CONTEXT: packed_slot.v's own header had disclosed, since EXP-0062,
|
||||
that activation data was read through a combinational stand-in port
|
||||
(act_tile_addr_a/b -> act_tile_data_a/b), with a real fetch engine
|
||||
explicitly deferred. This was the single largest remaining gap between
|
||||
"a verified compute architecture" and "a system that can actually run
|
||||
on real data in real DDR3".
|
||||
|
||||
DESIGN: new hardware/v3/rtl/act_tile_fetch.v -- unlike the weight path
|
||||
(prefetched once into an on-chip buffer, reused across many read-outs
|
||||
per job), activation data has NO reuse (read exactly once per
|
||||
position), so this engine reads DIRECTLY from DDR3 per tile, no
|
||||
on-chip buffering. Reuses the SAME per-slot ctrl_req/addr/etc port
|
||||
layer_prefetch_ctrl.v already owns (mutually exclusive in time by FSM
|
||||
construction -- weight prefetch always fully completes before the
|
||||
tile loop that needs activation data starts), muxed inside packed_slot.v
|
||||
on a new act_mem_active signal. Two sequential burst reads per tile
|
||||
request (lane A then lane B), with an explicit ctrl_busy wait between
|
||||
them (mig_native_adapter.v's own S_DONE tail can keep busy asserted
|
||||
one cycle past ready -- checked explicitly, not assumed safe).
|
||||
|
||||
MEMORY LAYOUT (a new, real, disclosed requirement): each tile occupies
|
||||
its own full BURST_LEN=8-word burst slot (P_IN=8 bytes in the low 64
|
||||
bits, upper 64 bits padding) -- deliberately 2x wasteful of DDR3
|
||||
capacity, in exchange for needing ZERO runtime-indexed part-select in
|
||||
the fetch logic (weight_tile_gather.v, EXP-0061, already flagged that
|
||||
pattern as a real Fmax risk, and this project's P&R margin is
|
||||
currently thin, EXP-0078 WNS +0.013ns -- not the moment to introduce a
|
||||
new critical path). Documented in the new hardware/v3/constraints
|
||||
physical doc for whoever prepares host-side data layout.
|
||||
|
||||
packed_slot.v's own S_TILEWAIT state was restructured into a real
|
||||
two-source JOIN: latches (tile_seen/act_seen) independently track
|
||||
whether the (fast, on-chip) weight tile and the (real-DDR3-latency)
|
||||
activation tile have each arrived, proceeding to S_OPERAND only once
|
||||
BOTH have been seen, correctly handling either arrival order (not just
|
||||
the expected common case of weight-first).
|
||||
|
||||
VERIFICATION (three levels, matching this project's own "one variable
|
||||
at a time" discipline):
|
||||
1. hardware/v3/sim/tb_act_tile_fetch.v -- act_tile_fetch.v alone
|
||||
against the SDR SDRAM placeholder: 6/6 PASS on the first real run
|
||||
(no bugs found -- the nonblocking-assignment stimulus idiom,
|
||||
already standard practice since EXP-0073/0075/0077, avoided the
|
||||
testbench-race class that has bitten every PREVIOUS new module's
|
||||
first draft in this project).
|
||||
2. hardware/v3/sim/tb_packed_slot.v -- rewritten to preload REAL
|
||||
activation data into the SDR placeholder (same technique already
|
||||
used for weights) instead of a combinational lookup stand-in;
|
||||
the OLD decimal-encoded x_base convention (li*100000+pos*1000)
|
||||
was replaced by the new real word-address convention. 9/9 PASS,
|
||||
0 errors, on the first real run after fixing one Verilog syntax
|
||||
issue (can't part-select a function call's return value inline
|
||||
in this dialect -- assign to a temp variable first).
|
||||
3. hardware/v3/sim/tb_n2_system_ddr3.v -- the full real N=2 system
|
||||
(Director + 2 packed_slot + arbiter + MIG + real ddr3_model.sv),
|
||||
same update pattern, re-run via real xsim. **8/8 tests, 0 errors,
|
||||
8/8 positions completed, bit-exact against the golden model --
|
||||
the first time this project's compute path has been verified
|
||||
end-to-end against REAL DDR3 for BOTH weights and activations,
|
||||
not just weights.**
|
||||
|
||||
INTEGRATION: n2_system_ddr3_top.v (the real synthesis target) updated
|
||||
to remove the old activation-stub top-level wiring entirely (the
|
||||
free-running-counter stand-in from EXP-0074, itself a fix for an
|
||||
earlier mistake of exposing act_addr/data as literal chip pins) --
|
||||
activation fetch is now fully internal to each packed_slot instance,
|
||||
using ports that already existed for other reasons. Net effect: FEWER
|
||||
top-level signals than before, not more.
|
||||
|
||||
RETIRED (superseded, not fixed-in-place): hardware/v3/rtl/n2_system_top.v
|
||||
and hardware/v3/sim/tb_np_director_n2_system.v (the pre-DDR3, SDR-
|
||||
placeholder-era N=2 top/test, EXP-0066/0067) -- fully superseded by
|
||||
n2_system_ddr3_top.v/tb_n2_system_ddr3.v, would have needed the exact
|
||||
same class of update for zero forward benefit. Removed via `git rm`,
|
||||
fully recoverable from git history if ever needed.
|
||||
|
||||
DECISION: this closes the last major disclosed FUNCTIONAL gap in the
|
||||
V3 compute pipeline -- real DSP-packed cores, real weight-reuse
|
||||
scheduling, real N-way arbitration, real DDR3 for BOTH weights and
|
||||
activations, real host SPI protocol (jobs/registers/raw memory/config-
|
||||
flash), all verified together end to end. What remains open (scaling
|
||||
past N=2, PCB-specific pin finalization, ESP32 firmware) is genuinely
|
||||
separate, disclosed, non-blocking work -- not a hidden correctness gap.
|
||||
|
||||
next_action: real in-context P&R re-verification (the activation
|
||||
engine adds real logic on a path that matters -- EXP-0078's own margin
|
||||
was already thin, +0.013ns, before this addition) -- must re-confirm
|
||||
timing still closes before calling this "ready to use in physical
|
||||
hardware". Also: finalize and commit docs/PHYSICAL_REALIZATION.md
|
||||
(drafted this session, real pin/part/protocol/layout data).
|
||||
|
||||
Reference in New Issue
Block a user