Begins the V2 Neural Multiprocessor / Dataflow architecture per docs/v2-description.md, per explicit user request to freeze V1 and start V2 development, copying from V1 what's needed. Scaffold: - hardware/v1/: byte-exact, read-only copy of the current V1 codebase (rtl, testbenches, tools, constraints, a representative subset of synthesis results, and reference docs) -- verified identical via diff/cmp against the live top-level tree before being made filesystem-read-only. The live top-level tree is untouched and remains the project's "production" V1 (see hardware/v1/README.md and hardware/v2/logs/decisions.log DEC-0001 for why copy-not-move). - hardware/v2/: mandatory structure (rtl/sim/constraints/synthesis/ reports/scripts/logs/docs) plus the full logging system required by the spec (development/architecture/simulation/synthesis/timing/ benchmark/decisions/experiments/errors.log). M1 -- Neural Processor (hardware/v2/rtl/neural_processor.v): - 8-stage pipelined perceptron unit (P_IN=8): input align, 8 multipliers, 3-level adder tree, accumulator, bias+activation, INT8 saturation. Genuine 1-tile/cycle throughput, not just a wider combinational datapath. - 7-state FSM (NP_IDLE..NP_ERROR per docs/v2-description.md §6, with 4 baseline states merged into NP_WAIT_OPERANDS -- see decisions.log DEC-0002); valid/ready/data/last stream interfaces per §7. - Bit-exact vs the frozen hardware/v1/rtl/neuron_parallel.v + mac8.v + mac_unit.v: 7/7 tests pass (hardware/v2/sim/tb_neural_processor.v), covering regular/mixed-sign/extreme-INT8 vectors, both activations, a zero-idle-gap back-to-back-tiles throughput check, and an 8-tile job -- verified with Verilator (see below for why). - Real synthesis + place&route (Yosys + nextpnr-ecp5): 0 CHECK problems, Fmax 183.12 MHz at ACC_WIDTH=32 (PASS at 80MHz, ~3x V1's isolated PARALLEL=8 Fmax of 61.71 MHz) and 176.21 MHz at ACC_WIDTH=24 (a user-requested comparison experiment, also bit-exact-verified; see experiments.log EXP-0001/EXP-0002 and benchmark.log). Three real bugs found and resolved during M1 development (full diagnostic record in errors.log): - Two independent, reproducible Icarus Verilog v13.0 scheduling defects (ERR-0001, ERR-0002) that silently produced wrong simulation results for standard sequential Verilog -- confirmed via Verilator 5.050 giving correct results on the same minimal repros. Verilator is now the trusted simulator for hardware/v2/ (decisions.log DEC-0004); Icarus's affected protocol-violation check was removed from the RTL and deferred architecturally to the Neural Director (DEC-0003) rather than chased further. - One real RTL bug (ERR-0003): last0 wasn't gated like valid0, letting a "last tile" tag leak into the pipeline ahead of its actual valid tile on back-to-back jobs. Fixed and verified. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
1242 lines
22 KiB
Markdown
1242 lines
22 KiB
Markdown
FPGA-Neural V2 — Neural Multiprocessor / Dataflow Architecture
|
||
Obiettivo
|
||
|
||
Progettare e implementare una V2 dell'acceleratore neurale FPGA contenuto nel repository:
|
||
|
||
https://github.com/manvalan/FPGA-Neural
|
||
|
||
La V2 deve evolvere l'architettura V1 trasformandola da un acceleratore principalmente sequenziale a una Neural Multiprocessor / Dataflow Machine, mantenendo V1 come implementazione di riferimento funzionante.
|
||
|
||
L'obiettivo non è semplicemente aumentare PARALLEL.
|
||
|
||
L'obiettivo è costruire un'architettura composta da:
|
||
|
||
molteplici Neural Processor / Perceptron Processor indipendenti;
|
||
un Neural Director / Orchestrator;
|
||
un Dependency Manager;
|
||
un Memory Manager;
|
||
buffer locali e FIFO;
|
||
prefetch;
|
||
forwarding dei risultati;
|
||
pipeline interne ai Neural Processor;
|
||
esecuzione concorrente di più neuroni;
|
||
gestione dinamica delle dipendenze;
|
||
capacità di eseguire reti regolari, DAG, fuzzy network e strutture con dipendenze non strettamente sequenziali.
|
||
|
||
Il sistema deve essere progettato come una piccola macchina dataflow neurale, non come una semplice versione più larga dell'architettura V1.
|
||
|
||
1. Regola fondamentale: V1 è il Golden Reference
|
||
|
||
La V1 funzionante deve essere conservata integralmente.
|
||
|
||
Non modificare, cancellare o degradare la V1 per implementare la V2.
|
||
|
||
Struttura obbligatoria:
|
||
|
||
hardware/
|
||
├── v1/
|
||
│ ├── rtl/
|
||
│ ├── sim/
|
||
│ ├── constraints/
|
||
│ ├── synthesis/
|
||
│ └── ...
|
||
│
|
||
└── v2/
|
||
├── rtl/
|
||
├── sim/
|
||
├── constraints/
|
||
├── synthesis/
|
||
├── reports/
|
||
├── scripts/
|
||
├── logs/
|
||
└── docs/
|
||
|
||
La V1 deve essere utilizzata come:
|
||
|
||
riferimento funzionale;
|
||
riferimento numerico;
|
||
riferimento prestazionale;
|
||
riferimento per i test bit-exact;
|
||
baseline per valutare ogni modifica V2.
|
||
2. Hardware target
|
||
|
||
Target FPGA:
|
||
|
||
Lattice ECP5U LFE5U-45F-8BG381
|
||
|
||
La progettazione deve tenere conto delle caratteristiche reali del dispositivo.
|
||
|
||
Non assumere che una maggiore quantità di DSP/logic implichi automaticamente maggiore prestazione.
|
||
|
||
Il limite può essere:
|
||
|
||
timing;
|
||
routing;
|
||
fanout;
|
||
congestione;
|
||
memoria;
|
||
larghezza dei bus;
|
||
mux;
|
||
distribuzione dei segnali;
|
||
interconnessioni tra blocchi.
|
||
|
||
Ogni scelta importante deve quindi essere verificata con sintesi e place-and-route reali.
|
||
|
||
3. Baseline V1
|
||
|
||
La V1 attuale contiene, tra gli altri:
|
||
|
||
rtl/neuron_parallel.v
|
||
rtl/mac8.v
|
||
rtl/mac_unit.v
|
||
rtl/neuron_memory.v
|
||
rtl/layer_sequencer.v
|
||
rtl/graph_engine.v
|
||
rtl/act_buffer.v
|
||
rtl/psram_controller.v
|
||
rtl/int8_memory_access.v
|
||
rtl/memory_interface.v
|
||
rtl/mem_arbiter.v
|
||
rtl/spi_neuron_top.v
|
||
|
||
La V1 utilizza:
|
||
|
||
INT8;
|
||
accumulazione INT32;
|
||
PARALLEL=8;
|
||
MAC paralleli;
|
||
adder tree bilanciato;
|
||
bias;
|
||
activation;
|
||
saturazione INT8;
|
||
memoria PSRAM/CellularRAM esterna.
|
||
|
||
Dati reali già osservati nella V1:
|
||
|
||
P16 ≈ 52.13 MHz
|
||
P8 ≈ 61.71 MHz
|
||
P4 ≈ 75.01 MHz
|
||
P2 ≈ 87.88 MHz
|
||
|
||
in una configurazione isolata N_INPUTS=256.
|
||
|
||
Nel sistema integrato:
|
||
|
||
P8 ≈ 65.13 MHz
|
||
|
||
con failure rispetto a un target di 80 MHz.
|
||
|
||
Il critical path osservato è principalmente legato alla logica del neuron_parallel e alla sua interconnessione, non al controller PSRAM.
|
||
|
||
Questi dati devono essere considerati misure reali V1, non risultati V2.
|
||
|
||
4. Architettura V2
|
||
|
||
La V2 deve essere organizzata in due piani.
|
||
|
||
Control Plane
|
||
Neural Director
|
||
│
|
||
├── Scheduler
|
||
├── Dependency Manager
|
||
├── Ready Queue
|
||
├── Waiting Queue
|
||
└── Processor State
|
||
Data Plane
|
||
┌─────────────────────┐
|
||
│ Memory Manager │
|
||
└──────────┬──────────┘
|
||
│
|
||
┌────────────┼────────────┐
|
||
│ │ │
|
||
Buffer Buffer Buffer
|
||
Input Weight Result
|
||
│ │ │
|
||
└────────────┼────────────┘
|
||
│
|
||
┌────────────┬───────┴───────┬────────────┐
|
||
│ │ │ │
|
||
NP0 NP1 NP2 NP3
|
||
│ │ │ │
|
||
└────────────┴───────────────┴────────────┘
|
||
│
|
||
Result/Forward
|
||
|
||
Il numero di processor non deve essere deciso a priori.
|
||
|
||
Deve essere determinato tramite sweep di sintesi e timing.
|
||
|
||
5. Neural Processor
|
||
|
||
Il Neural Processor è l'unità fondamentale della V2.
|
||
|
||
Ogni processor deve essere autonomo e indipendente.
|
||
|
||
Un processor esegue un neurone alla volta, ma il datapath interno deve essere pipelineizzato.
|
||
|
||
Configurazione iniziale:
|
||
|
||
P_IN = 8
|
||
|
||
Ogni processor inizialmente deve avere:
|
||
|
||
8 × INT8 multiplier
|
||
balanced adder tree
|
||
INT32 accumulator
|
||
bias
|
||
activation
|
||
INT8 saturation
|
||
local operand registers/FIFO
|
||
job interface
|
||
result interface
|
||
|
||
Pipeline iniziale candidata:
|
||
|
||
Stage 0 input alignment/register
|
||
Stage 1 8 multipliers
|
||
Stage 2 adder tree level 1
|
||
Stage 3 adder tree level 2
|
||
Stage 4 adder tree level 3
|
||
Stage 5 accumulator
|
||
Stage 6 bias / activation
|
||
Stage 7 output / saturation
|
||
|
||
La pipeline può essere modificata se le simulazioni e il timing dimostrano una soluzione migliore.
|
||
|
||
L'obiettivo principale è il throughput, non la minima latenza possibile.
|
||
|
||
6. Neural Processor FSM
|
||
|
||
Ogni Neural Processor deve avere una macchina a stati chiaramente definita.
|
||
|
||
Baseline:
|
||
|
||
NP_IDLE
|
||
NP_LOAD_JOB
|
||
NP_WAIT_OPERANDS
|
||
NP_LOAD_TILE
|
||
NP_MAC
|
||
NP_ACCUM
|
||
NP_NEXT_TILE
|
||
NP_FINISH
|
||
NP_WRITE_RESULT
|
||
NP_DONE
|
||
NP_ERROR
|
||
NP_IDLE
|
||
|
||
Processor libero e disponibile.
|
||
|
||
NP_LOAD_JOB
|
||
|
||
Caricamento del job descriptor.
|
||
|
||
Inizializzazione:
|
||
|
||
node ID;
|
||
numero input;
|
||
indirizzo input;
|
||
indirizzo pesi;
|
||
bias;
|
||
activation;
|
||
tile count;
|
||
accumulator.
|
||
NP_WAIT_OPERANDS
|
||
|
||
Attesa degli operandi.
|
||
|
||
Il processor deve poter rimanere bloccato senza impedire agli altri processor di lavorare.
|
||
|
||
NP_LOAD_TILE
|
||
|
||
Caricamento di un tile locale.
|
||
|
||
NP_MAC
|
||
|
||
Esecuzione del datapath MAC pipeline.
|
||
|
||
NP_ACCUM
|
||
|
||
Aggiornamento dell'accumulatore.
|
||
|
||
NP_NEXT_TILE
|
||
|
||
Richiesta del tile successivo.
|
||
|
||
Il Memory Manager dovrebbe averlo già prefetched.
|
||
|
||
NP_FINISH
|
||
|
||
Bias, activation e saturazione.
|
||
|
||
NP_WRITE_RESULT
|
||
|
||
Handshake con Memory Manager / result path.
|
||
|
||
NP_DONE
|
||
|
||
Il processor ritorna disponibile.
|
||
|
||
NP_ERROR
|
||
|
||
Gestione degli errori senza bloccare globalmente il sistema.
|
||
|
||
7. Interfacce del Neural Processor
|
||
|
||
Evitare grandi mux dinamici come quelli dell'architettura V1.
|
||
|
||
Preferire:
|
||
|
||
valid
|
||
ready
|
||
data
|
||
last
|
||
|
||
per gli stream.
|
||
|
||
Input:
|
||
|
||
operand_valid
|
||
operand_ready
|
||
input_data
|
||
weight_data
|
||
tile_last
|
||
|
||
Output:
|
||
|
||
result_valid
|
||
result_ready
|
||
result_data
|
||
node_id
|
||
|
||
La validità deve essere pipelineizzata insieme ai dati.
|
||
|
||
Non assumere ritardi fissi senza handshake o valid propagation.
|
||
|
||
8. Neural Processor Array
|
||
|
||
Creare:
|
||
|
||
hardware/v2/rtl/neural_processor_array.v
|
||
|
||
Il modulo deve permettere:
|
||
|
||
N_PROCESSORS = parametrico
|
||
P_IN = parametrico
|
||
|
||
Configurazioni iniziali:
|
||
|
||
1 × P8
|
||
2 × P8
|
||
4 × P8
|
||
8 × P8
|
||
|
||
Successivamente esplorare configurazioni maggiori se timing e risorse lo consentono.
|
||
|
||
Esempi teorici:
|
||
|
||
4 × P8 = 32 MAC/cycle
|
||
8 × P8 = 64 MAC/cycle
|
||
|
||
Questi sono solo valori teorici.
|
||
|
||
Non presentarli mai come throughput misurato.
|
||
|
||
9. Neural Director / Orchestrator
|
||
|
||
Creare:
|
||
|
||
hardware/v2/rtl/neural_director.v
|
||
|
||
Il Director controlla l'intero sistema.
|
||
|
||
Responsabilità:
|
||
|
||
ricezione dei job;
|
||
scansione dei job READY;
|
||
scelta del processor libero;
|
||
assegnazione;
|
||
tracking dello stato dei processor;
|
||
gestione delle dipendenze;
|
||
rilevamento dei completamenti;
|
||
wake-up dei job;
|
||
gestione ready queue;
|
||
gestione waiting queue;
|
||
prevenzione dei deadlock;
|
||
massimizzazione dell'utilizzo dei processor.
|
||
|
||
FSM iniziale:
|
||
|
||
DIR_IDLE
|
||
DIR_SCAN_READY
|
||
DIR_ALLOCATE
|
||
DIR_WAIT_DEPENDENCY
|
||
DIR_MONITOR
|
||
DIR_COMPLETE
|
||
DIR_WAKEUP
|
||
DIR_ERROR
|
||
|
||
Scheduling iniziale:
|
||
|
||
first-free
|
||
|
||
Successivamente valutare:
|
||
|
||
round-robin
|
||
least-loaded
|
||
locality-aware
|
||
priority-based
|
||
dependency-aware
|
||
|
||
La politica migliore deve essere determinata sperimentalmente.
|
||
|
||
10. Dependency Manager
|
||
|
||
Creare:
|
||
|
||
hardware/v2/rtl/dependency_manager.v
|
||
|
||
Ogni nodo deve avere almeno:
|
||
|
||
node_id
|
||
state
|
||
required_dependencies
|
||
resolved_dependencies
|
||
producer_information
|
||
|
||
Esempio:
|
||
|
||
node 37
|
||
required = 4
|
||
resolved = 3
|
||
state = WAITING
|
||
|
||
Quando arriva il quarto risultato:
|
||
|
||
resolved = 4
|
||
state = READY
|
||
|
||
Il nodo può quindi essere assegnato dal Director.
|
||
|
||
Il sistema deve supportare:
|
||
|
||
dipendenze multiple;
|
||
risultati condivisi;
|
||
più consumer;
|
||
wake-up;
|
||
forwarding;
|
||
backpressure.
|
||
11. Dataflow e token
|
||
|
||
Il modello concettuale deve supportare token:
|
||
|
||
TOKEN
|
||
├── node_id
|
||
├── value
|
||
└── valid
|
||
|
||
Quando un processor produce un risultato:
|
||
|
||
Producer
|
||
│
|
||
├──→ Consumer FIFO
|
||
│
|
||
└──→ Result Buffer
|
||
|
||
Quando possibile il dato deve essere inoltrato direttamente al consumer senza obbligare il sistema a fare:
|
||
|
||
processor
|
||
→ external memory
|
||
→ memory controller
|
||
→ buffer
|
||
→ processor
|
||
|
||
Il risultato può essere contemporaneamente:
|
||
|
||
forwarded;
|
||
memorizzato;
|
||
utilizzato da più consumer.
|
||
12. Memory Manager
|
||
|
||
Creare:
|
||
|
||
hardware/v2/rtl/memory_manager.v
|
||
|
||
Il Neural Processor non deve accedere direttamente alla PSRAM.
|
||
|
||
Il Memory Manager deve occuparsi di:
|
||
|
||
input activations;
|
||
weights;
|
||
results;
|
||
prefetch;
|
||
buffering;
|
||
FIFO;
|
||
arbitration;
|
||
forwarding;
|
||
gestione latenza;
|
||
double buffering;
|
||
memory request scheduling.
|
||
|
||
Il processor deve vedere principalmente:
|
||
|
||
data available
|
||
|
||
e non:
|
||
|
||
PSRAM latency
|
||
13. Prefetch
|
||
|
||
Creare:
|
||
|
||
hardware/v2/rtl/prefetch_engine.v
|
||
|
||
Usare inizialmente una strategia:
|
||
|
||
compute tile N
|
||
│
|
||
└── concurrently ──→ prefetch tile N+1
|
||
|
||
Con double buffering:
|
||
|
||
Buffer A → COMPUTE
|
||
Buffer B → PREFETCH
|
||
|
||
swap
|
||
|
||
Buffer B → COMPUTE
|
||
Buffer A → PREFETCH
|
||
|
||
Priorità:
|
||
|
||
HIGH operand required now
|
||
MEDIUM next tile
|
||
LOW future tile
|
||
14. Buffer
|
||
|
||
Creare:
|
||
|
||
hardware/v2/rtl/activation_buffer.v
|
||
hardware/v2/rtl/weight_buffer.v
|
||
hardware/v2/rtl/result_buffer.v
|
||
|
||
La profondità deve essere parametrica.
|
||
|
||
Valutare anche:
|
||
|
||
FIFO depth
|
||
buffer depth
|
||
numero porte
|
||
BRAM mapping
|
||
routing
|
||
timing
|
||
|
||
Non assumere che buffer più grandi siano automaticamente migliori.
|
||
|
||
15. Memoria esterna
|
||
|
||
NON iniziare modificando il controller PSRAM.
|
||
|
||
Mantenere inizialmente il backend esistente.
|
||
|
||
Astrarre il Memory Manager dal backend:
|
||
|
||
Memory Manager
|
||
│
|
||
▼
|
||
Memory Backend Interface
|
||
│
|
||
▼
|
||
PSRAM Controller
|
||
|
||
Solo dopo aver misurato il sistema V2 valutare eventuali alternative:
|
||
|
||
SRAM;
|
||
PSRAM;
|
||
SDRAM;
|
||
DDR;
|
||
QSPI;
|
||
altre memorie o risorse esterne.
|
||
|
||
Qualsiasi modifica hardware esterna deve essere motivata da dati reali.
|
||
|
||
16. Parallelismo
|
||
|
||
Due parametri fondamentali:
|
||
|
||
P_IN
|
||
N_PROCESSORS
|
||
|
||
P_IN indica il numero di MAC paralleli dentro un Neural Processor.
|
||
|
||
N_PROCESSORS indica quanti Neural Processor operano contemporaneamente.
|
||
|
||
Eseguire sweep almeno su:
|
||
|
||
P_IN = 2, 4, 8
|
||
|
||
e:
|
||
|
||
N_PROCESSORS = 1, 2, 4, 6, 8, 12, 16...
|
||
|
||
fino al limite imposto da:
|
||
|
||
LUT;
|
||
FF;
|
||
DSP;
|
||
BRAM;
|
||
routing;
|
||
timing.
|
||
|
||
La configurazione finale deve essere scelta sulla base del throughput effettivo, non dell'utilizzo massimo delle risorse.
|
||
|
||
17. Dataflow Core
|
||
|
||
Creare:
|
||
|
||
hardware/v2/rtl/dataflow_core.v
|
||
|
||
Il modulo integra:
|
||
|
||
Neural Director
|
||
Dependency Manager
|
||
Memory Manager
|
||
Prefetch Engine
|
||
Neural Processor Array
|
||
Activation Buffer
|
||
Weight Buffer
|
||
Result Buffer
|
||
|
||
Architettura:
|
||
|
||
JOBS
|
||
│
|
||
▼
|
||
┌─────────────────┐
|
||
│ Neural Director │
|
||
└───────┬─────────┘
|
||
│
|
||
┌───────▼─────────┐
|
||
│ Dependency │
|
||
│ Manager │
|
||
└───────┬─────────┘
|
||
│
|
||
▼
|
||
┌─────────────────┐
|
||
│ Memory Manager │
|
||
└───────┬─────────┘
|
||
│
|
||
┌─────────┼─────────┐
|
||
▼ ▼ ▼
|
||
NP0 NP1 NP...
|
||
│ │ │
|
||
└─────────┼─────────┘
|
||
│
|
||
▼
|
||
RESULTS
|
||
18. Scheduling dinamico
|
||
|
||
Il sistema deve permettere che:
|
||
|
||
NP0 → node A
|
||
NP1 → node B
|
||
NP2 → node C
|
||
NP3 → WAIT
|
||
|
||
Se NP3 attende un risultato:
|
||
|
||
NP3 WAIT
|
||
|
||
non deve bloccare:
|
||
|
||
NP0
|
||
NP1
|
||
NP2
|
||
|
||
Quando il risultato arriva:
|
||
|
||
Producer
|
||
↓
|
||
Dependency Manager
|
||
↓
|
||
dependency resolved
|
||
↓
|
||
job READY
|
||
↓
|
||
Director
|
||
↓
|
||
free processor
|
||
19. Supporto a reti diverse
|
||
|
||
L'architettura deve essere sufficientemente generale per supportare:
|
||
|
||
Layer regolari
|
||
input → layer → layer → output
|
||
DAG
|
||
┌── node B ──┐
|
||
node A ┤ ├→ node E
|
||
└── node C ──┘
|
||
Fuzzy network
|
||
|
||
con dipendenze irregolari e numero variabile di ingressi.
|
||
|
||
Cloud / sparse graph
|
||
|
||
con nodi attivati dinamicamente.
|
||
|
||
Non costruire il sistema assumendo esclusivamente una rete fully-connected regolare.
|
||
|
||
20. Simulazione obbligatoria
|
||
|
||
Ogni componente deve avere un testbench.
|
||
|
||
Creare:
|
||
|
||
hardware/v2/sim/
|
||
├── tb_neural_processor.v
|
||
├── tb_neural_processor_array.v
|
||
├── tb_memory_manager.v
|
||
├── tb_prefetch_engine.v
|
||
├── tb_dependency_manager.v
|
||
├── tb_neural_director.v
|
||
└── tb_dataflow_core.v
|
||
|
||
Test obbligatori:
|
||
|
||
test funzionali;
|
||
random test;
|
||
extreme INT8;
|
||
pipeline;
|
||
stall;
|
||
backpressure;
|
||
dependency;
|
||
wake-up;
|
||
forwarding;
|
||
multi-processor concurrency;
|
||
deadlock detection;
|
||
data-loss detection;
|
||
bit-exact comparison con V1.
|
||
|
||
Valori INT8 da includere:
|
||
|
||
-128
|
||
-127
|
||
-1
|
||
0
|
||
1
|
||
126
|
||
127
|
||
21. Test bit-exact
|
||
|
||
Ogni risultato V2 deve essere confrontabile con V1.
|
||
|
||
Per gli stessi:
|
||
|
||
inputs
|
||
weights
|
||
bias
|
||
activation
|
||
network
|
||
|
||
deve essere verificato:
|
||
|
||
V1 result == V2 result
|
||
|
||
salvo differenze esplicitamente documentate e matematicamente giustificate.
|
||
|
||
22. Performance simulation
|
||
|
||
La simulazione deve misurare almeno:
|
||
|
||
total_cycles
|
||
compute_cycles
|
||
stall_cycles
|
||
memory_wait_cycles
|
||
processor_busy_cycles
|
||
processor_idle_cycles
|
||
completed_neurons
|
||
completed_tiles
|
||
processor_utilization
|
||
memory_utilization
|
||
effective_throughput
|
||
stall_percentage
|
||
|
||
Eseguire anche sweep della latenza memoria:
|
||
|
||
0 cycles
|
||
1 cycle
|
||
2 cycles
|
||
4 cycles
|
||
8 cycles
|
||
16 cycles
|
||
|
||
L'obiettivo è misurare quanto efficacemente il prefetch nasconde la latenza.
|
||
|
||
23. Sintesi e Place & Route
|
||
|
||
Ogni configurazione deve essere realmente verificata con:
|
||
|
||
Icarus / Verilator
|
||
Yosys
|
||
nextpnr-ecp5
|
||
|
||
Non inventare risultati.
|
||
|
||
Non stimare il timing come se fosse una misura.
|
||
|
||
Distinguere sempre:
|
||
|
||
THEORETICAL
|
||
RTL SIMULATION
|
||
SYNTHESIS
|
||
POST-P&R MEASUREMENT
|
||
|
||
Il valore Fmax ufficiale della configurazione deve provenire dal place-and-route reale.
|
||
|
||
24. Benchmark
|
||
|
||
Per ogni configurazione creare:
|
||
|
||
hardware/v2/reports/
|
||
├── simulation/
|
||
├── synthesis/
|
||
├── timing/
|
||
└── experiments/
|
||
|
||
Esempio:
|
||
|
||
hardware/v2/reports/experiments/EXP-0001/
|
||
├── experiment.yaml
|
||
├── simulation.log
|
||
├── synthesis.log
|
||
├── timing.log
|
||
├── results.txt
|
||
└── notes.md
|
||
|
||
Ogni benchmark deve contenere almeno:
|
||
|
||
Fmax
|
||
processors
|
||
P_IN
|
||
MAC/cycle
|
||
LUT
|
||
FF
|
||
DSP
|
||
BRAM
|
||
cycles/neuron
|
||
neurons/s
|
||
stall %
|
||
effective MAC/s
|
||
25. LOGGING OBBLIGATORIO
|
||
Questa è una regola fondamentale del progetto.
|
||
|
||
OGNI attività significativa deve essere registrata.
|
||
|
||
Nessuna modifica, simulazione, sintesi, benchmark, decisione architetturale o errore deve essere perso.
|
||
|
||
Creare:
|
||
|
||
hardware/v2/logs/
|
||
├── development.log
|
||
├── architecture.log
|
||
├── simulation.log
|
||
├── synthesis.log
|
||
├── timing.log
|
||
├── benchmark.log
|
||
├── decisions.log
|
||
├── experiments.log
|
||
└── errors.log
|
||
|
||
Il registro principale deve essere:
|
||
|
||
hardware/v2/logs/experiments.log
|
||
|
||
Ogni esperimento deve avere un identificativo univoco:
|
||
|
||
EXP-0001
|
||
EXP-0002
|
||
EXP-0003
|
||
...
|
||
|
||
Gli ID non devono essere riutilizzati.
|
||
|
||
26. Contenuto minimo di ogni log
|
||
|
||
Ogni evento significativo deve contenere:
|
||
|
||
timestamp
|
||
experiment_id
|
||
git_commit
|
||
session/agent
|
||
module
|
||
configuration
|
||
action
|
||
reason
|
||
command
|
||
result
|
||
errors
|
||
decision
|
||
next_action
|
||
|
||
Per synthesis/timing includere anche:
|
||
|
||
LUT
|
||
FF
|
||
DSP
|
||
BRAM
|
||
Fmax
|
||
critical path
|
||
WNS/TNS se disponibili
|
||
|
||
Per simulazione:
|
||
|
||
test
|
||
vectors
|
||
cycles
|
||
PASS/FAIL
|
||
bit-exact result
|
||
stall cycles
|
||
memory wait
|
||
utilization
|
||
27. Logging delle decisioni
|
||
|
||
Ogni scelta architetturale importante deve essere registrata in:
|
||
|
||
hardware/v2/logs/decisions.log
|
||
|
||
Formato concettuale:
|
||
|
||
DEC-0001
|
||
|
||
DATE:
|
||
...
|
||
|
||
DECISION:
|
||
Use 4 independent P8 Neural Processors.
|
||
|
||
WHY:
|
||
...
|
||
|
||
EVIDENCE:
|
||
EXP-0001
|
||
EXP-0002
|
||
EXP-0003
|
||
|
||
ALTERNATIVES:
|
||
P4 × 8
|
||
P8 × 4
|
||
P16 × 2
|
||
|
||
RESULT:
|
||
...
|
||
|
||
STATUS:
|
||
ACCEPTED
|
||
|
||
Le decisioni devono essere basate su dati quando possibile.
|
||
|
||
28. Nessuna sovrascrittura dei risultati
|
||
|
||
I risultati precedenti non devono essere cancellati o sovrascritti.
|
||
|
||
Se:
|
||
|
||
EXP-0017 = PASS
|
||
EXP-0018 = FAIL
|
||
EXP-0019 = PASS
|
||
|
||
tutti e tre devono rimanere.
|
||
|
||
Un risultato negativo è comunque un risultato utile.
|
||
|
||
Deve essere possibile ricostruire la storia:
|
||
|
||
idea
|
||
↓
|
||
implementazione
|
||
↓
|
||
test
|
||
↓
|
||
fallimento/successo
|
||
↓
|
||
modifica
|
||
↓
|
||
nuovo test
|
||
↓
|
||
decisione
|
||
29. Riproducibilità
|
||
|
||
Ogni esperimento deve essere riproducibile.
|
||
|
||
Il log deve permettere di sapere:
|
||
|
||
quale commit
|
||
quale configurazione
|
||
quali parametri
|
||
quale toolchain
|
||
quale comando
|
||
quale testbench
|
||
quali constraint
|
||
quale risultato
|
||
|
||
Ogni report deve essere associato al commit Git utilizzato.
|
||
|
||
Se il working tree contiene modifiche non committate, questo deve essere esplicitamente registrato.
|
||
|
||
30. Regola contro risultati inventati
|
||
|
||
È vietato presentare dati non misurati come dati reali.
|
||
|
||
Esempio:
|
||
|
||
4 × P8 @ 80 MHz = 2.56 GMAC/s
|
||
|
||
deve essere indicato:
|
||
|
||
THEORETICAL
|
||
|
||
Finché non esiste una misura reale.
|
||
|
||
Un risultato:
|
||
|
||
Fmax = 83.7 MHz
|
||
|
||
può essere dichiarato misurato solo se ottenuto da:
|
||
|
||
nextpnr-ecp5
|
||
|
||
con relativa configurazione e report salvati.
|
||
|
||
31. Sweep automatici
|
||
|
||
Creare:
|
||
|
||
hardware/v2/scripts/sweep/
|
||
|
||
Gli script devono poter eseguire automaticamente combinazioni di:
|
||
|
||
P_IN
|
||
N_PROCESSORS
|
||
FIFO depth
|
||
buffer depth
|
||
pipeline configuration
|
||
|
||
e produrre automaticamente:
|
||
|
||
simulation
|
||
synthesis
|
||
place-and-route
|
||
timing
|
||
resource utilization
|
||
benchmark
|
||
|
||
Ogni configurazione deve generare un proprio:
|
||
|
||
EXP-XXXX
|
||
|
||
e registrarlo nei log.
|
||
|
||
32. Confronto V1 vs V2
|
||
|
||
Il benchmark finale deve produrre una tabella:
|
||
|
||
V1 V2
|
||
------------------------------------
|
||
Fmax
|
||
LUT
|
||
FF
|
||
DSP
|
||
BRAM
|
||
MAC/cycle
|
||
cycles/neuron
|
||
neurons/s
|
||
stall %
|
||
memory utilization
|
||
processor utilization
|
||
effective MAC/s
|
||
|
||
Ogni numero deve essere classificato come:
|
||
|
||
THEORETICAL
|
||
SIMULATED
|
||
SYNTHESIZED
|
||
POST-P&R
|
||
33. Roadmap di implementazione
|
||
M1 — Neural Processor
|
||
|
||
Implementare:
|
||
|
||
hardware/v2/rtl/neural_processor.v
|
||
|
||
P8.
|
||
|
||
Input forniti direttamente dal testbench.
|
||
|
||
Obiettivo:
|
||
|
||
bit-exact V1
|
||
pipeline funzionante
|
||
|
||
Eseguire simulation + synthesis + timing.
|
||
|
||
M2 — Processor Array
|
||
|
||
Implementare:
|
||
|
||
neural_processor_array.v
|
||
|
||
Testare:
|
||
|
||
1
|
||
2
|
||
4
|
||
8
|
||
|
||
processor.
|
||
|
||
Misurare:
|
||
|
||
timing;
|
||
risorse;
|
||
throughput;
|
||
utilization.
|
||
M3 — Buffers
|
||
|
||
Implementare:
|
||
|
||
activation_buffer.v
|
||
weight_buffer.v
|
||
result_buffer.v
|
||
M4 — Memory Manager
|
||
|
||
Implementare:
|
||
|
||
memory_manager.v
|
||
prefetch_engine.v
|
||
|
||
Inizialmente utilizzare il backend PSRAM esistente.
|
||
|
||
M5 — Neural Director
|
||
|
||
Implementare:
|
||
|
||
neural_director.v
|
||
|
||
Scheduling iniziale:
|
||
|
||
first-free
|
||
M6 — Dependency Manager
|
||
|
||
Implementare:
|
||
|
||
dependency_manager.v
|
||
|
||
Aggiungere:
|
||
|
||
ready;
|
||
waiting;
|
||
dependency counters;
|
||
wake-up;
|
||
producer tracking.
|
||
M7 — Dataflow Core
|
||
|
||
Integrare:
|
||
|
||
dataflow_core.v
|
||
M8 — PSRAM integration
|
||
|
||
Integrare il controller V1 senza modificarlo inizialmente.
|
||
|
||
Misurare il comportamento reale.
|
||
|
||
M9 — Full benchmark
|
||
|
||
Confrontare V1/V2.
|
||
|
||
M10 — Optimization
|
||
|
||
Solo sulla base dei dati:
|
||
|
||
pipeline;
|
||
P_IN;
|
||
numero processor;
|
||
buffer;
|
||
FIFO;
|
||
scheduling;
|
||
prefetch;
|
||
routing;
|
||
memoria.
|
||
34. Principi architetturali non negoziabili
|
||
V1 rimane intatta.
|
||
V2 vive esclusivamente sotto hardware/v2/....
|
||
Nessun risultato inventato.
|
||
Ogni misura deve provenire dagli strumenti appropriati.
|
||
Ogni modifica deve essere registrata.
|
||
Ogni esperimento deve avere un ID.
|
||
Nessun risultato precedente deve essere sovrascritto.
|
||
Ogni decisione importante deve avere una motivazione.
|
||
Ogni benchmark deve essere riproducibile.
|
||
Un processor bloccato non deve bloccare gli altri.
|
||
Il Neural Processor non deve conoscere direttamente la memoria esterna.
|
||
Il Director gestisce WHAT deve essere eseguito.
|
||
Il Memory Manager gestisce COME rendere disponibili i dati.
|
||
Il Neural Processor gestisce COME eseguire il calcolo.
|
||
Ottimizzare il throughput effettivo, non il numero di DSP utilizzati.
|
||
Evitare grandi mux e interconnessioni globali quando possibile.
|
||
Favorire località fisica e pipeline.
|
||
Le configurazioni devono essere esplorate sperimentalmente.
|
||
Ogni modifica deve essere confrontata con la baseline.
|
||
Il progetto deve mantenere una cronologia completa e ricostruibile dello sviluppo.
|
||
35. Filosofia finale
|
||
|
||
La V2 deve evolvere FPGA-Neural verso:
|
||
|
||
NEURAL DIRECTOR
|
||
│
|
||
┌────────────┼────────────┐
|
||
│ │ │
|
||
READY WAITING DEPENDENCY
|
||
QUEUE QUEUE MANAGER
|
||
│
|
||
▼
|
||
MEMORY MANAGER
|
||
│
|
||
┌─────────┼─────────┐
|
||
│ │ │
|
||
INPUT WEIGHT RESULT
|
||
BUFFER BUFFER BUFFER
|
||
│ │ │
|
||
└─────────┼─────────┘
|
||
│
|
||
┌──────────────┼──────────────┐
|
||
│ │ │
|
||
NP0 NP1 NP...
|
||
│ │ │
|
||
└──────────────┼──────────────┘
|
||
│
|
||
DATAFLOW / FORWARD
|
||
|
||
Il risultato finale deve essere una macchina neurale parallela e dataflow, capace di mantenere occupati più Neural Processor contemporaneamente, nascondere la latenza della memoria, gestire dipendenze dinamiche e scalare il numero di processor in funzione dei limiti reali dell'ECP5.
|
||
|
||
Il processo di sviluppo deve essere completamente tracciabile:
|
||
|
||
IDEA
|
||
↓
|
||
ARCHITECTURE LOG
|
||
↓
|
||
IMPLEMENTATION
|
||
↓
|
||
SIMULATION
|
||
↓
|
||
SYNTHESIS
|
||
↓
|
||
PLACE & ROUTE
|
||
↓
|
||
MEASUREMENT
|
||
↓
|
||
EXPERIMENT LOG
|
||
↓
|
||
DECISION LOG
|
||
↓
|
||
NEXT EXPERIMENT
|
||
|
||
Non deve esistere una modifica "non registrata", una misura "senza report" o una decisione architetturale "senza motivazione". |