feat: real result-writeback engine, removes the last hard N-scaling pin blocker (EXP-0088)
Adds result_writeback.v, one instance per packed_slot.v, writing each completed job's result directly into DDR3 at the job's own result_addr_a/b instead of driving literal top-level pins -- the same architectural shape as the weight-fetch path, in reverse. job_done now means "durably in DDR3", not "captured in a register only a pin could see". n2_system_ddr3_top.v's own s0_result_data_a/b, s1_result_data_a/b top-level package pins are removed (and the now-dangling XDC constraint for them), closing the real, hard scaling blocker docs/ARCHITECTURE_ ANALYSIS.md flagged since EXP-0074/0079 (8 bits x 2 lanes x N cores -> 256 pins at N=16). Addressing reuses the exact same JOB_ADDR_WIDTH->ctrl-bus-word truncation x_base_a/w_base already use (verified against act_tile_ fetch.v's/layer_prefetch_ctrl.v's own real code, not guessed). The host reads results back via the already-existing READ_MEM (0x02) SPI opcode -- no new protocol. A real EXP-0066-class bug (issuing ctrl_req before mem_grant) was caught and fixed before ever compiling, by re-deriving the design against act_tile_fetch.v's own proven S_MEMWAIT/S_GAP sequencing. Verified two ways: tb_packed_slot.v extended with a real DDR3 read-after-write check (9/9 PASS, confirms the write actually landed, not just that job_done pulsed); tb_n2_system_ddr3.v re-run via real xsim to confirm correct behavior under real 2-slot shared-bus arbitration (8/8 PASS, 0 errors, consistent timing with EXP-0087's own baseline for this workload). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
This commit is contained in:
@@ -98,13 +98,17 @@ module n2_system_ddr3_top #(
|
||||
output wire flash_mosi,
|
||||
input wire flash_miso,
|
||||
|
||||
// ---- results (small enough to keep as real top-level pins for
|
||||
// observation; NOT part of the activation-interface pin-count
|
||||
// problem described below) ----
|
||||
output wire signed [DATA_WIDTH-1:0] s0_result_data_a,
|
||||
output wire signed [DATA_WIDTH-1:0] s0_result_data_b,
|
||||
output wire signed [DATA_WIDTH-1:0] s1_result_data_a,
|
||||
output wire signed [DATA_WIDTH-1:0] s1_result_data_b,
|
||||
// ---- results: EXP-0088 REMOVES the literal per-slot top-level
|
||||
// result pins that used to live here (s0_result_data_a/b,
|
||||
// s1_result_data_a/b) -- they were flagged (docs/ARCHITECTURE_
|
||||
// ANALYSIS.md S4.6/S5.3) as the exact same class of scaling mistake
|
||||
// already caught once for activation data (EXP-0074): fine at N=2
|
||||
// (4 pins), a hard blocker at N=16 (8 bits x 2 lanes x 16 cores =
|
||||
// 256 pins on this port alone). Each packed_slot.v instance now
|
||||
// writes its own result directly into DDR3 via its own internal
|
||||
// result_writeback.v (see packed_slot.v's own header) -- the host
|
||||
// reads results back via the already-existing READ_MEM (0x02) SPI
|
||||
// opcode, no new top-level port needed at any N.
|
||||
|
||||
// ---- status ----
|
||||
output wire ui_clk_o,
|
||||
@@ -283,6 +287,12 @@ module n2_system_ddr3_top #(
|
||||
|
||||
wire [15:0] s0_nid_a, s0_nid_b, s1_nid_a, s1_nid_b;
|
||||
wire [JOB_ADDR_WIDTH-1:0] s0_raddr_a, s0_raddr_b, s1_raddr_a, s1_raddr_b;
|
||||
// EXP-0088: plain internal debug wires now (no longer top-level
|
||||
// pins) -- the real result is written to DDR3 by each slot's own
|
||||
// internal result_writeback.v; these remain wired from packed_
|
||||
// slot.v's own output ports purely for internal observability.
|
||||
wire signed [DATA_WIDTH-1:0] s0_result_data_a, s0_result_data_b;
|
||||
wire signed [DATA_WIDTH-1:0] s1_result_data_a, s1_result_data_b;
|
||||
|
||||
// ---- activation fetch: REAL now (EXP-0079) -- each packed_slot
|
||||
// instance owns its own act_tile_fetch.v internally, sharing that
|
||||
|
||||
Reference in New Issue
Block a user