docs: sync physical/architecture docs with EXP-0081/0082 reality, add 32-bit vs dual-channel analysis
- PHYSICAL_REALIZATION.md: replace stale "1 tile = 1 burst" layout description with the real EXP-0081/0082 "2 tiles = 1 burst" convention; add EXP-0082 signoff row and history table. - ARCHITECTURE_ANALYSIS.md: mark §5.1 (denser activation packing) DONE with real re-measured numbers (bandwidth ceiling fraction 25%->50%, WNS +0.030->+0.068ns); add §5.4, the real device-data-backed comparison of 32-bit single-channel widening vs a second independent DDR3 channel (decided: 32-bit widening, per real DQS/bank pin-conflict analysis); update scaling-path recommendation to reflect the user's final directive (widen channel -> build DDRManager -> N=2/4/8/16 tests, N=8 target, N=16 documentary). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
This commit is contained in:
@@ -118,7 +118,7 @@ these from an ESP32 doing real JTAG bit-banging (TAP state machine, IR/DR
|
||||
shifting) rather than a bench programmer — that firmware is separate,
|
||||
software-side work, not covered here.
|
||||
|
||||
## 3. Real timing signoff (EXP-0078, the current, trustworthy number)
|
||||
## 3. Real timing signoff (EXP-0082, the current, trustworthy number)
|
||||
|
||||
Real in-context Vivado place-and-route (not out-of-context, not estimated):
|
||||
|
||||
@@ -126,14 +126,23 @@ Real in-context Vivado place-and-route (not out-of-context, not estimated):
|
||||
|---|---|
|
||||
| DDR3 PHY clock (sys_clk_i) | **310.078 MHz** (3.225ns period) |
|
||||
| Compute domain clock (ui_clk, PLL-derived 2:1 from sys_clk_i) | **155.039 MHz** |
|
||||
| WNS (setup slack) | **+0.013 ns** — real, but very thin. Re-verify with a fresh P&R after ANY further logic addition. |
|
||||
| WHS (hold slack) | +0.032 ns |
|
||||
| Failing endpoints | 0 / 17473 (setup), 0 / 17470 (hold) |
|
||||
| LUTs used | 5213 / 63400 (8.22%) |
|
||||
| DSP48E1 used | 16 / 240 (6.67%) — 8 per compute core × 2 cores |
|
||||
| WNS (setup slack) | **+0.068 ns** — real, still thin but improved vs EXP-0078/0079. Re-verify with a fresh P&R after ANY further logic addition. |
|
||||
| Failing endpoints | 0 (setup), 0 (hold) |
|
||||
| LUTs used | 5437 / 63400 (8.58%) |
|
||||
| DSP48E1 used | 16 / 240 (6.67%) — 8 per compute core × 2 cores, unchanged since EXP-0059 |
|
||||
| Block RAM used | 0 |
|
||||
| STARTUPE2 used | 1 / 1 (100%) — the config-flash bridge |
|
||||
|
||||
Signoff history (every real change, same target, in-context P&R):
|
||||
|
||||
| EXP | WNS (ns) | LUTs | DSP48E1 |
|
||||
|---|---|---|---|
|
||||
| 0074 (first real DDR3 + pins) | +0.040 | 5140 | 16 |
|
||||
| 0076 (+regfile, +pins, +SPI fix) | +0.056 | 5173 | 16 |
|
||||
| 0078 (+flash bridge, STARTUPE2) | +0.013 | 5213 | 16 |
|
||||
| 0079 (+real activation engine) | +0.030 | 5379 | 16 |
|
||||
| 0082 (+denser activation packing) | **+0.068** | 5437 | 16 |
|
||||
|
||||
## 4. Real DDR3 memory layout convention
|
||||
|
||||
Both weight data and activation data share the same DDR3 address space
|
||||
@@ -143,17 +152,36 @@ Both weight data and activation data share the same DDR3 address space
|
||||
WORDS_PER_LAYER` (`WORDS_PER_LAYER = LAYER_BYTES/2`). Densely packed —
|
||||
`layer_prefetch_ctrl.v` reads full bursts sequentially into the on-chip
|
||||
weight buffer once per job.
|
||||
- **Activations** (real engine since EXP-0079, `act_tile_fetch.v`): **each
|
||||
tile (P_IN=8 INT8 values) occupies its own full `BURST_LEN=8`-word
|
||||
(128-bit) burst slot** — the 8 useful bytes sit in the low 64 bits, the
|
||||
upper 64 bits are unused padding. This is deliberately 2× wasteful of DDR3
|
||||
capacity, in exchange for needing zero runtime-indexed bit-selects in the
|
||||
fetch logic (a real Fmax risk this project's thin P&R margin, §3, can't
|
||||
currently afford). Tile `t`'s word address is `base + t*BURST_LEN`, always
|
||||
burst-aligned by construction.
|
||||
- **Activations** (real engine, `act_tile_fetch.v`; current layout is the
|
||||
**v2 convention, EXP-0081/0082**): **two consecutive tiles (P_IN=8 INT8
|
||||
values each) share ONE full `BURST_LEN=8`-word (128-bit) burst** — the
|
||||
even-indexed tile occupies the low 64 bits, the odd-indexed tile occupies
|
||||
the high 64 bits. Tile `t`'s burst address is `base + (t>>1)*BURST_LEN`
|
||||
(integer division — two tiles per burst), always burst-aligned by
|
||||
construction. This **halves** real DDR3 bytes-moved-per-useful-byte versus
|
||||
the original EXP-0079 "1 tile = 1 burst" layout, which wasted the upper 64
|
||||
bits of every burst as padding.
|
||||
- **Why this is timing-safe despite selecting a sub-burst half at read
|
||||
time**: the tile index's LSB (which half of the burst a given tile
|
||||
lives in) is known at *request* time, not at response time. It's
|
||||
latched into a register (`sel_lat`) the same cycle the request is
|
||||
accepted — many `ui_clk` cycles before the real DDR3 round-trip
|
||||
completes and `ctrl_rdata` becomes valid. The eventual data-select mux
|
||||
therefore always selects on an already-long-stable registered bit,
|
||||
never a bit racing live read data — this is NOT the runtime-indexed-
|
||||
part-select-on-the-critical-path pattern flagged as a real Fmax risk in
|
||||
EXP-0061 (that pattern is about a select signal arriving *late*,
|
||||
simultaneously with the data it gates). Confirmed timing-safe by real
|
||||
P&R (EXP-0082): margin *improved* from +0.030ns to +0.068ns, not
|
||||
degraded.
|
||||
- Real measured effect: back-to-back same-row DDR3 throughput is a fixed
|
||||
1.24 GB/s (measured, EXP-0080) regardless of packing — this convention
|
||||
doesn't change that ceiling, it changes how much of it is *wasted* on
|
||||
padding, doubling the real achievable useful fraction (see
|
||||
`docs/ARCHITECTURE_ANALYSIS.md` §3 and §5.1).
|
||||
- `base` (a job's own `x_base_a`/`x_base_b`) is chosen freely by whoever
|
||||
submits jobs (the SPI host) — just keep each position's own activation
|
||||
array in its own non-overlapping `N_TILES * BURST_LEN`-word region.
|
||||
array in its own non-overlapping `(N_TILES/2) * BURST_LEN`-word region.
|
||||
|
||||
## 5. FPGA configuration (boot) procedure
|
||||
|
||||
|
||||
Reference in New Issue
Block a user