feat: real first step of 4x4 hybrid systolic architecture (EXP-0089)

Adds packed_pe.v (packed_slot.v's compute+activation-fetch+writeback
subsystem, reusing ddr_prefetch_mgr.v/neural_processor_packed.v/
result_writeback.v completely unmodified, with its own private
weight-fetch removed) and systolic_group.v (one real layer_prefetch_
ctrl.v+layer_weight_buffer.v+weight_tile_gather.v shared by 4x
packed_pe.v via a real, barrier-synchronized broadcast bus).

Real design choice confirmed with the user before writing any RTL
(AskUserQuestion, concrete topology preview): shared-weight broadcast,
not a literal PE-to-PE systolic shift register -- achieves the real,
quantified rationale (4x reduction in redundant weight-fetch DDR3
traffic per group of 4 PEs) with much lower real risk than genuine
inter-PE pipeline fill/drain.

The real new design is the barrier: each PE's own tcnt is the join key
against the group's broadcast tcnt, self-synchronizing regardless of
which PE is momentarily ahead/behind (e.g. a real DDR3 row-switch
stall on one PE's own activation fetch). Found and fixed a real bug
during verification (not by inspection): the first full test run
reported every result as undefined despite every control-flow signal
tracing correctly -- root-caused via real signal tracing down to a
5-way test arbiter bus mis-sliced at the wrong slot offset (single-bit
handshake buses happened to use a correct range and masked it from the
control-flow trace; only the wide, byte-offset buses were wrong).

Verified in isolation (tb_systolic_group.v, real Icarus xsim, real
sdram_arbiter_n.v generalized to NUM_REQ=5 with zero changes): 8/8
PASS across 2 consecutive group jobs (exercising the barrier's own
per-job reset path, not just cold start).

Deliberately scoped to the isolated mechanism only, per this project's
"one variable at a time" discipline -- Director/SPI job dispatch for
group jobs, a real N=16 top-level, and real P&R are real, disclosed
next steps, not done here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
This commit is contained in:
2026-09-20 22:54:52 +02:00
co-authored by Claude Sonnet 5
parent 7f9ece12dc
commit 932aec2490
5 changed files with 1104 additions and 25 deletions
+36 -25
View File
@@ -659,12 +659,18 @@ specifically to document where/how it breaks rather than to succeed):
---
### 5.6 [EXPLORATORY — captured, not decided, not built] Hybrid systolic scaling: 4 groups × 4-PE weight-stationary chains
### 5.6 [First step DONE, EXP-0089] Hybrid systolic scaling: 4 groups × 4-PE weight-stationary chains
Captured from a 2026-09-20 brainstorming session (same continuation), before
any N=4/8/16 scaling work starts, so the direction isn't lost. **Nothing in
this subsection is implemented or committed to — it's a working hypothesis
for a future architecture, explicitly not yet an RTL task.**
Captured from a 2026-09-20 brainstorming session as a purely exploratory
idea; the same day, per the user's own explicit reprioritization, the real
open design question below (shared-weight broadcast vs. a literal PE-to-PE
systolic shift register) was resolved with the user directly (not guessed),
and the **first real, isolated step is now built and verified**:
`systolic_group.v` + `packed_pe.v` (EXP-0089) — one real group of 4 PEs
sharing a single broadcast weight fetch, real barrier-synchronized, real
xsim-verified (8/8 PASS across 2 consecutive group jobs). **Not yet done**:
Director/SPI-level job dispatch for group jobs, a real N=16 (4-group)
top-level, and any real P&R for this — see EXP-0089's own `next_action`.
**The problem it targets**: plain N=16 independent cores (§5.5's own
"documentary, expected to break" framing) means 16 independent DDR3
@@ -701,27 +707,32 @@ flagged explicitly as a projection):
naive flat-N=16 baseline — a real, meaningful, but NOT a full solve by
itself; still needs real measurement once anything is built.
**Real open questions, not resolved yet** (deliberately not designed
further until the current in-flight work — §5.4's channel widening, N=2/4/8
real testing — lands first, per this project's own "one variable at a time"
discipline):
- Intra-chain dataflow RTL (result propagation between adjacent PEs,
pipeline drain/fill at chain boundaries) is a real, new design, not a
trivial extension — needs its own isolated verification before wiring
into anything real, same as every other module in this project.
- Result collection actually gets SIMPLER under this model versus flat
N=16 (4 chain-output events instead of 16 independent ones) — relevant
to §5.3's result-writeback engine, worth designing writeback with this
in mind rather than for flat N=16 if this direction is pursued.
- Arbitration simplifies too: 4 group-level requesters instead of 16,
though `sdram_arbiter_n.v`'s own NUM_REQ parameter already generalizes to
either case without changes.
**Real open question, RESOLVED (EXP-0089)**: intra-chain dataflow — the
user was asked directly (`AskUserQuestion`, concrete side-by-side preview
of both real topologies) rather than guessed, given how different their
real risk/complexity profiles are. Chosen: **shared-weight broadcast** (one
real weight fetch per group of 4 PEs, no inter-PE result/data propagation,
each PE computes its own independent activation positions in parallel) —
**not** a literal PE-to-PE systolic shift register. This achieves the real,
quantified rationale above (4× reduction in redundant weight-fetch DDR3
traffic per group) without the real complexity/risk of genuine pipeline
fill/drain at chain boundaries, which the literal-systolic alternative
would have required. Real result-writeback stays exactly as §5.3 already
built it — `packed_pe.v` reuses `result_writeback.v` completely unmodified,
one real DDR3 write per PE, not a new "4 chain-output events" model (that
framing, from the original brainstorm, doesn't apply to the broadcast
design actually built). Arbitration: confirmed real — `sdram_arbiter_n.v`'s
own `NUM_REQ` parameter generalized to a 5-way arbiter (1 group weight-fetch
+ 4 PE activation/writeback) in `tb_systolic_group.v` with zero changes to
that module.
**Decision**: not decided. Revisit after §5.4 (32-bit widening) and the
real N=2/4/8 flat-core scaling tests produce real numbers — those numbers
will tell us whether flat scaling is "good enough" up to some N, making
this restructuring unnecessary, or whether the real congestion at N=8/16
justifies it.
**Decision**: first real step DONE (EXP-0089) — build and verify the
isolated group mechanism before any Director/SPI/top-level integration,
per this project's own "one variable at a time" discipline. Full N=16
integration (Director-level group job dispatch, SPI protocol extension,
real top-level, real P&R) is real, disclosed, deliberately deferred work,
not yet done — see EXP-0089's own `next_action` in
`hardware/v2/logs/experiments.log`.
#### 5.6.1 [EXPLORATORY] Opportunistic BRAM cache for activation tiles