feat(v2): M2 Neural Processor Array, N_PROCESSORS resource sweep
Implements M2 of the V2 roadmap: neural_processor_array.v instantiates
N_PROCESSORS independent neural_processor (M1) units, each with its
own dedicated point-to-point job/operand/result interface -- no shared
bus or mux at this level (arbitration is explicitly the Neural
Director's job, M5).
Verified with Verilator (tb_neural_processor_array.v, N_PROCESSORS=4):
7/7 tests pass, including a same-cycle 4-way concurrent launch with
different tile counts and a staggered-start test where a
later-launched, shorter job completes before an earlier-launched,
longer one -- confirming genuine independent concurrent execution
(§18/§34: a blocked/busy processor must not block the others).
Real resource/timing sweep for N_PROCESSORS in {1,2,4,8} (Yosys +
nextpnr-ecp5, real place&route): Fmax stays above the 80MHz target
throughout (159.11 -> 134.70 MHz), but MULT18X18D usage scales
linearly and reaches 88% of the LFE5U-45F's 72 DSPs at N=8 while
LUT/FF stay under 6% -- DSP, not LUT/FF/routing, is the first hard
ceiling on N_PROCESSORS at P_IN=8 (decisions.log DEC-0005). Measured
via a dedicated synthesis-only timing harness after the array's wide
per-processor buses were found to exhaust the device's TRELLIS_IO pin
budget as a bare top-level module beyond N=1 (errors.log ERR-0005) --
not a logic limit, an artifact of testing the array in isolation
before the Memory Manager/Director (M4/M5) exist to consume those
ports on-chip.
Full log trail (development/experiments/errors/decisions/simulation/
synthesis/timing/benchmark.log) in hardware/v2/logs/ per the project's
logging mandate.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
This commit is contained in:
@@ -18,3 +18,25 @@ stall %, effective MAC/s: not yet meaningful at this milestone (single
|
||||
isolated processor, no streaming benchmark harness yet -- deferred to
|
||||
M2 once neural_processor_array.v exists and a real workload can be
|
||||
timed end-to-end).
|
||||
|
||||
[2026-09-05] M2 Neural Processor Array, N_PROCESSORS sweep (P_IN=8,
|
||||
ACC_WIDTH=32 each; synthesized via the timing harness, see errors.log
|
||||
ERR-0005 for why)
|
||||
|
||||
| N_PROCESSORS | Fmax (POST-P&R) | LUT | FF | DSP (MULT18X18D) | DSP % of 72 |
|
||||
|--------------|------------------|-----|------|-------------------|-------------|
|
||||
| 1 | 159.11 MHz | 59 | 409 | 8 | 11% |
|
||||
| 2 | 149.59 MHz | 106 | 786 | 16 | 22% |
|
||||
| 4 | 151.01 MHz | 207 | 1540 | 32 | 44% |
|
||||
| 8 | 134.70 MHz | 374 | 3048 | 64 | 88% |
|
||||
|
||||
All figures POST-P&R (real nextpnr-ecp5), all PASS at the 80MHz
|
||||
target. LUT4 utilization stays under 6% of the device even at N=8;
|
||||
DSP is the binding resource (see decisions.log DEC-0005), reaching 88%
|
||||
at N=8 -- N_PROCESSORS=9 would already exceed the LFE5U-45F's 72
|
||||
MULT18X18D budget at P_IN=8. Theoretical MAC/cycle (THEORETICAL, not
|
||||
yet measured end-to-end -- no real workload/benchmark harness exists
|
||||
until M9): N_PROCESSORS * P_IN MACs/cycle when all processors are
|
||||
simultaneously streaming tiles (8, 16, 32, 64 for N=1/2/4/8 -- verified
|
||||
achievable in principle by EXP-0003's concurrent/staggered simulation,
|
||||
not yet measured as a sustained throughput number).
|
||||
|
||||
@@ -201,3 +201,50 @@ resolved by picking whichever answer looks more convenient.
|
||||
|
||||
STATUS:
|
||||
ACCEPTED
|
||||
|
||||
---
|
||||
|
||||
DEC-0005
|
||||
|
||||
DATE: 2026-09-05
|
||||
|
||||
DECISION:
|
||||
Treat DSP (MULT18X18D) budget, not LUT/FF/routing, as the primary
|
||||
constraint when exploring the N_PROCESSORS x P_IN trade-off space
|
||||
(§16) going forward.
|
||||
|
||||
WHY:
|
||||
Real place&route measurement (EXP-0003) shows MULT18X18D usage
|
||||
scaling linearly and reaching 88% of the LFE5U-45F-8BG381's 72 total
|
||||
DSPs at N_PROCESSORS=8, P_IN=8 -- while LUT4/FF usage stays under 6%
|
||||
at the SAME configuration and Fmax is still comfortably above the
|
||||
80MHz target (134.70 MHz). This means the naive "just add more
|
||||
processors" scaling (§8/§16) hits a hard DSP ceiling around
|
||||
N_PROCESSORS=9 at P_IN=8, long before LUT/FF/routing/timing become
|
||||
relevant -- the opposite of what LUT/FF utilization alone would
|
||||
suggest if read in isolation.
|
||||
|
||||
EVIDENCE:
|
||||
experiments.log EXP-0003 -- MULT18X18D 8/16/32/64 (11%/22%/44%/88% of
|
||||
72) at N_PROCESSORS 1/2/4/8, LUT4 under 6% throughout, Fmax PASS at
|
||||
80MHz throughout (159.11/149.59/151.01/134.70 MHz).
|
||||
|
||||
ALTERNATIVES:
|
||||
Assume LUT/FF/routing congestion would be the limiting factor (the
|
||||
naive expectation for "more parallel copies of a datapath"). Rejected
|
||||
by direct measurement, not assumed -- §16 explicitly requires
|
||||
choosing the final configuration "sulla base del throughput effettivo
|
||||
... non dell'utilizzo massimo delle risorse", and knowing WHICH
|
||||
resource binds first is a prerequisite for that.
|
||||
|
||||
RESULT:
|
||||
Future N_PROCESSORS x P_IN sweeps (§16, deferred to a dedicated
|
||||
scripts/sweep/ run per §31) should budget MULT18X18D count explicitly
|
||||
(N_PROCESSORS * P_IN <= ~72, minus whatever the rest of the real
|
||||
system needs once M4/PSRAM integration lands) rather than only
|
||||
tracking LUT/FF. A smaller P_IN with more N_PROCESSORS (or vice versa)
|
||||
is a live trade-off worth exploring precisely because of this ceiling,
|
||||
not merely a stylistic choice.
|
||||
|
||||
STATUS:
|
||||
ACCEPTED
|
||||
|
||||
@@ -59,3 +59,32 @@ errors: vedi errors.log ERR-0001, ERR-0002, ERR-0003, ERR-0004.
|
||||
decision: vedi decisions.log DEC-0002, DEC-0003, DEC-0004.
|
||||
next_action: M2 -- neural_processor_array.v, sweep N_PROCESSORS
|
||||
(1,2,4,8), misura timing/risorse/throughput/utilization reali.
|
||||
|
||||
[2026-09-05T14:30:00Z] commit=dc0b331 session=v2-M2-processor-array
|
||||
module: hardware/v2/rtl/neural_processor_array.v + hardware/v2/sim/
|
||||
tb_neural_processor_array.v + hardware/v2/synthesis/
|
||||
harness_neural_processor_array.v
|
||||
action: implementato M2 -- Neural Processor Array, N_PROCESSORS
|
||||
parametrico, ogni processore con interfaccia job/operand/result
|
||||
dedicata (nessun bus condiviso/mux a questo livello, §7). Testato
|
||||
N_PROCESSORS=4 con esecuzione concorrente reale (lancio simultaneo
|
||||
di 4 job diversi, più un test a partenza sfalsata) e con lo sweep
|
||||
reale N_PROCESSORS={1,2,4,8} per sintesi/place&route.
|
||||
reason: roadmap M2.
|
||||
result: 7/7 test PASS (Verilator), confermata esecuzione concorrente e
|
||||
indipendente (un job più corto lanciato dopo completa prima di uno
|
||||
più lungo lanciato prima -- non c'e' serializzazione nascosta).
|
||||
Sintesi/P&R reali per N=1/2/4/8: 0 problemi CHECK, scaling lineare
|
||||
delle risorse, Fmax sempre PASS a 80MHz (159.11/149.59/151.01/134.70
|
||||
MHz). Scoperta reale non assunta: il DSP (MULT18X18D) e' la prima
|
||||
risorsa a saturare (88% a N=8), non LUT/FF (sotto il 6% anche a
|
||||
N=8) -- vedi decisions.log DEC-0005.
|
||||
errors: ERR-0005 (artefatto di sintesi da pin-count, non un bug RTL --
|
||||
workaround con un harness dedicato, vedi errors.log). Un primo
|
||||
tentativo di harness alimentava dati identici a ogni processore/lane
|
||||
MAC, e Yosys deduplicava silenziosamente tutto a 1x indipendentemente
|
||||
da N -- scoperto verificando che lo scaling fosse davvero lineare
|
||||
prima di fidarsi dei numeri.
|
||||
decision: vedi decisions.log DEC-0005.
|
||||
next_action: M3 -- activation_buffer.v / weight_buffer.v /
|
||||
result_buffer.v (profondita' parametrica, valutare BRAM mapping).
|
||||
|
||||
@@ -98,3 +98,29 @@ NOTE: this session's V1 certification campaign (docs/validation/,
|
||||
this V2-kickoff session (V1 is frozen, not to be touched) and was
|
||||
not performed. See decisions.log DEC-0004.
|
||||
STATUS: OPEN CAVEAT, not actioned in this session by design.
|
||||
|
||||
ERR-0005 (synthesis measurement artifact, WORKED AROUND, not an RTL bug)
|
||||
DATE: 2026-09-05
|
||||
MODULE: hardware/v2/rtl/neural_processor_array.v
|
||||
SYMPTOM: synthesizing neural_processor_array as a bare top-level
|
||||
module (every per-processor job/operand/result field exposed as a
|
||||
real TRELLIS_IO pin) works at N_PROCESSORS=1 but fails place&route
|
||||
at N_PROCESSORS=2 with "Unable to place cell ...$tr_io, no BELs
|
||||
remaining to implement cell type 'TRELLIS_IO'".
|
||||
ROOT CAUSE: not a logic/timing limit -- the LFE5U-45F-8BG381 package
|
||||
has 245 TRELLIS_IO pins total; the array's wide per-processor buses
|
||||
(input_data/weight_data alone are DATA_WIDTH*P_IN*N_PROCESSORS bits)
|
||||
exceed that budget once N_PROCESSORS>=2, purely because these ports
|
||||
have no on-chip consumer yet (the Memory Manager/M4 and Neural
|
||||
Director/M5 that will drive them in the real system don't exist
|
||||
yet).
|
||||
WORKAROUND: hardware/v2/synthesis/harness_neural_processor_array.v --
|
||||
a synthesis-only wrapper (NOT part of rtl/, not a functional
|
||||
deliverable) that drives all wide buses from an internal free-
|
||||
running LFSR and reduces outputs to a small checksum, keeping only
|
||||
clk/rst/seed/checksum as real top-level pins. See its own header
|
||||
comment and experiments.log EXP-0003 for the resulting real
|
||||
resource/Fmax numbers.
|
||||
STATUS: WORKED AROUND. Will become moot once M4/M5 exist and the array
|
||||
is synthesized as part of a larger design with on-chip ports instead
|
||||
of a bare top-level module.
|
||||
|
||||
@@ -98,3 +98,64 @@ decision: ACC_WIDTH=32 remains the M1 default (matches V1 exactly for
|
||||
comparison run).
|
||||
next_action: revisit ACC_WIDTH choice during M10 (Optimization) with a
|
||||
real seed sweep, not before.
|
||||
|
||||
EXP-0003
|
||||
timestamp: 2026-09-05T14:30:00Z
|
||||
git_commit: dc0b331 (+ uncommitted M2 work)
|
||||
session: v2-M2-processor-array
|
||||
module: hardware/v2/rtl/neural_processor_array.v
|
||||
configuration: N_PROCESSORS in {1,2,4,8}, P_IN=8, ACC_WIDTH=32 each
|
||||
action: M2 -- functional array + real N_PROCESSORS resource/timing sweep
|
||||
command (sim, Verilator): verilator --binary --timing -j 0 -Wno-fatal
|
||||
--top-module tb -o /tmp/vtb_array hardware/v2/rtl/neural_processor.v
|
||||
hardware/v2/rtl/neural_processor_array.v
|
||||
hardware/v2/sim/tb_neural_processor_array.v && /tmp/vtb_array
|
||||
command (synth/timing): see hardware/v2/synthesis/harness_n{1,2,4,8}/
|
||||
(yosys.log, nextpnr.log) -- synthesized via
|
||||
hardware/v2/synthesis/harness_neural_processor_array.v, a
|
||||
synthesis-only timing harness (see its own header comment and
|
||||
errors.log ERR-0005 for why the array cannot be synthesized as a
|
||||
bare top-level module beyond N_PROCESSORS=1 without it).
|
||||
result:
|
||||
SIMULATED (N_PROCESSORS=4, tb_neural_processor_array.v): 7/7 tests
|
||||
PASS -- single-processor sanity, 4 processors launched the SAME
|
||||
cycle with different tile counts (finish at different times,
|
||||
proving true concurrency), and a staggered-start test (processor 1
|
||||
launched mid-way through processor 0's 6-tile job, both complete
|
||||
correctly and independently, confirming §18/§34's "un processor
|
||||
bloccato non deve bloccare gli altri").
|
||||
SYNTHESIZED (resource scaling, harness): perfectly linear in
|
||||
N_PROCESSORS, confirming no unintended resource sharing:
|
||||
N=1: LUT=59 FF=409 MULT18X18D=8 CCU2C=96
|
||||
N=2: LUT=106 FF=786 MULT18X18D=16 CCU2C=192
|
||||
N=4: LUT=207 FF=1540 MULT18X18D=32 CCU2C=384
|
||||
N=8: LUT=374 FF=3048 MULT18X18D=64 CCU2C=768
|
||||
0 CHECK problems in every configuration.
|
||||
POST-P&R (real nextpnr-ecp5, --45k --package CABGA381 --speed 8
|
||||
--freq 80): Fmax PASS at 80MHz in every configuration:
|
||||
N=1: 159.11 MHz N=2: 149.59 MHz
|
||||
N=4: 151.01 MHz N=8: 134.70 MHz
|
||||
Fmax decreases gently with N (routing congestion), never close to
|
||||
failing the 80MHz target up to N=8.
|
||||
REAL RESOURCE CEILING FOUND (not assumed, measured via nextpnr's own
|
||||
device utilisation report): MULT18X18D usage is 22%/44%/88% of the
|
||||
LFE5U-45F's 72 total DSPs at N=2/4/8 respectively, while LUT4/FF
|
||||
usage stays under 6% even at N=8. **DSP (not LUT/FF/routing) is
|
||||
the first hard ceiling as N_PROCESSORS grows at P_IN=8** --
|
||||
N_PROCESSORS=9 would already exceed the device's 72 MULT18X18D
|
||||
budget at P_IN=8, before accounting for any multipliers the rest
|
||||
of a real system (Memory Manager, PSRAM path, etc.) might need.
|
||||
See decisions.log DEC-0005 and benchmark.log.
|
||||
errors: ERR-0005 (toplevel-pin-count synthesis artifact, worked around
|
||||
with the timing harness -- see errors.log); a first harness attempt
|
||||
fed every processor and every MAC lane identical LFSR-derived data,
|
||||
which Yosys correctly (from pure logic-equivalence) collapsed via
|
||||
CSE down to 1 processor's worth of multipliers regardless of N --
|
||||
fixed by giving each processor AND each of its P_IN MAC lanes a
|
||||
distinct bit-rotated data source, confirmed by the corrected,
|
||||
properly-linear MULT18X18D counts above.
|
||||
decision: see decisions.log DEC-0005 (DSP is the binding constraint,
|
||||
not LUT/FF -- informs how the N_PROCESSORS x P_IN trade-off should
|
||||
be explored going forward).
|
||||
next_action: M3 -- activation_buffer.v / weight_buffer.v /
|
||||
result_buffer.v.
|
||||
|
||||
@@ -15,3 +15,16 @@ PASS/FAIL: 7/7 PASS (ACC_WIDTH=32); 7/7 PASS (ACC_WIDTH=24, EXP-0002)
|
||||
bit-exact result: V1.y === V2.result_data for every case, both widths
|
||||
stall cycles / memory wait / utilization: N/A (no Memory Manager yet,
|
||||
M1 operands fed directly by testbench per the roadmap)
|
||||
|
||||
[2026-09-05] EXP-0003 -- hardware/v2/sim/tb_neural_processor_array.v
|
||||
(N_PROCESSORS=4)
|
||||
test: 7 cases (single-processor sanity; 4-way same-cycle concurrent
|
||||
launch with different tile counts; staggered-start 2-processor test)
|
||||
simulator: Verilator 5.050 (--binary --timing)
|
||||
PASS/FAIL: 7/7 PASS
|
||||
bit-exact result: N/A at this milestone (hand-computed expected
|
||||
values, arithmetic itself already bit-exact-certified vs V1 at M1)
|
||||
concurrency: confirmed genuine -- in the staggered test, the
|
||||
later-launched, shorter job (processor 1) completes BEFORE the
|
||||
earlier-launched, longer job (processor 0), proving independent
|
||||
progress rather than serialization.
|
||||
|
||||
@@ -14,3 +14,16 @@ CHECK: 0 problems. 36 warnings, all "multiple conflicting drivers for
|
||||
LUT: 49 FF: 509 DSP(MULT18X18D): 8 BRAM: 0 CCU2C: 88
|
||||
CHECK: 0 problems, same 36 benign warnings as EXP-0001.
|
||||
Log: hardware/v2/synthesis/neural_processor_p8_acc24/yosys.log
|
||||
|
||||
[2026-09-05] EXP-0003 -- neural_processor_array via
|
||||
harness_neural_processor_array.v (synthesis-only wrapper, see
|
||||
errors.log ERR-0005), N_PROCESSORS in {1,2,4,8}, P_IN=8
|
||||
N=1: LUT=59 FF=409 MULT18X18D=8 CCU2C=96
|
||||
N=2: LUT=106 FF=786 MULT18X18D=16 CCU2C=192
|
||||
N=4: LUT=207 FF=1540 MULT18X18D=32 CCU2C=384
|
||||
N=8: LUT=374 FF=3048 MULT18X18D=64 CCU2C=768
|
||||
CHECK: 0 problems in all 4 configurations. Perfectly linear scaling in
|
||||
N confirms no unintended cross-processor resource sharing (a first,
|
||||
flawed harness attempt fed identical data to every processor/lane
|
||||
and Yosys silently deduplicated down to 1x regardless of N -- caught
|
||||
by checking for exactly this linearity before trusting the numbers).
|
||||
|
||||
@@ -20,3 +20,14 @@ Delta vs ACC_WIDTH=32: -6.91 MHz (-3.8%) despite FEWER resources --
|
||||
(no seed sweep run to confirm either way -- see experiments.log
|
||||
EXP-0002 and benchmark.log). Log: hardware/v2/synthesis/
|
||||
neural_processor_p8_acc24/nextpnr.log
|
||||
|
||||
[2026-09-05] EXP-0003 -- N_PROCESSORS sweep (P_IN=8), real nextpnr-ecp5
|
||||
--45k --package CABGA381 --speed 8 --freq 80 --lpf-allow-unconstrained
|
||||
N=1: Fmax=159.11 MHz PASS MULT18X18D 8/72 (11%)
|
||||
N=2: Fmax=149.59 MHz PASS MULT18X18D 16/72 (22%)
|
||||
N=4: Fmax=151.01 MHz PASS MULT18X18D 32/72 (44%)
|
||||
N=8: Fmax=134.70 MHz PASS MULT18X18D 64/72 (88%)
|
||||
TRELLIS_IO stays at 18/245 (7%) throughout (harness has only
|
||||
clk/rst/seed/checksum as real pins, by design -- see ERR-0005).
|
||||
See decisions.log DEC-0005: DSP, not Fmax or LUT/FF, is the resource
|
||||
that will first prevent scaling N_PROCESSORS further at P_IN=8.
|
||||
|
||||
Reference in New Issue
Block a user