refactor(kg): split polymem into 3 banks {a, se, t} (async, stage 2a)

Replace the single async-read polymem[0:28*256-1] with 3 polynomial-indexed
banks (bank_a A_hat / bank_se s_hat||e_hat / bank_t t_hat), addressed by
abs_slot - base_slot. Still async-read here -- a pure refactor that validates
bank sizing and base-relative addressing with zero timing change before
stage 2b converts them to registered sd_bram + read-ahead pipelines.

11/11 KAT PASS, byte-exact, 0 file-not-found.
This commit is contained in:
2026-06-28 15:55:26 +08:00
parent 4f46c1cd02
commit 4d3adc6b57
2 changed files with 103 additions and 15 deletions

View File

@@ -0,0 +1,47 @@
# Phase 2: polymem -> BRAM banks
## Goal
Replace the single multi-port async-read `reg [11:0] polymem [0:28*256-1]` with
registered-read `sd_bram` banks that infer real BRAM (ASIC: compiled SRAM).
## Bank split (all sd_bram, W=12, 1R+1W registered)
- bank_a : A_hat[i][j], slots 0..K^2-1 -> D=4096 (KMAX^2*256), A=12
- bank_se: s_hat[i] then e_hat[i] -> D=2048 (2*KMAX*256), A=11
relative slot = abs_slot - slot_s_rt (s: 0..K-1, e: K..2K-1)
- bank_t : t_hat[i], slots slot_t_rt.. -> D=1024 (KMAX*256), A=10
relative slot = abs_slot - slot_t_rt
## Port budget (verified disjoint)
- poly_mul LOAD vs ACCUMULATE never overlap; ST_N/ST_M/ST_E are disjoint
top-states. => each bank needs only 1R+1W. sd_bram fits.
- bank_t ST_M-acc reads t_hat[idx] (j>0 source) and writes t_hat[idx] result
same cycle: 1R+1W, read-old/write-new. Prefetch keeps read AHEAD of write
(monotonic idx), so no same-pass RAW hazard.
## Read sites (all need 1-cycle read-ahead vs async today)
- ntt_in (ST_N load) <- bank_se[n_slot]
- e_c0,e_c1 (ST_E) <- bank_se (dk) or bank_t (ek); SERIALIZE the
two reads across the 3-byte/pair window
- pm_a_in (ST_M load) <- bank_a[m_aslot]
- pm_b_in (ST_M load) <- bank_se[m_j]
- m_acc_src (ST_M acc) <- bank_se[K+m_i] (j==0) or bank_t[m_i] (j>0)
- dbg_coeff_o (not on KAT path) <- route by slot range (compile-only)
## Write sites
- ST_A: bank_a[a_slot] <= snt_coeff
- ST_C: bank_se[c_slot-slot_s] <= cbd_modq
- ST_N: bank_se[n_slot] <= ntt_coeff (write-back, same slot)
- ST_M-acc: bank_t[m_i] <= m_accq
## Read-ahead strategy
Cores hold ready_o high through entire LOAD (no mid-stream backpressure) =>
fixed 1-cycle skew. Pattern: advance a read-address pointer 1 cycle ahead of
the consumer index; delay the consumer's valid by 1 cycle ("prime the pipe").
For ST_M-acc (irregular pm_vo cadence 0,1,1): 2-entry prefetch skid buffer,
read pointer runs monotonically ahead of write pointer.
## Checkpoints (KAT-gated: 11 cases, byte-exact, 0 file-not-found)
- 2a: split polymem -> 4 ASYNC-read banks (pure refactor, zero timing change).
Validates bank sizing + base-relative addressing + debug mux. COMMIT.
- 2b: convert banks to registered sd_bram + add read-ahead pipelines to every
consumer FSM (ST_N, ST_E, ST_M load, ST_M acc). COMMIT.