Files
FPGA-Neural/docs/FPGA-Neural-Datapatch-Benchmark.md
T
2026-09-02 13:09:20 +02:00

15 KiB
Raw Blame History

FPGA-Neural — Analisi datapath e benchmark ECP5

1. Obiettivo

Questa fase del progetto FPGA-Neural ha avuto lo scopo di verificare il comportamento sintetizzabile e le prestazioni del core neurale parametrico sul dispositivo:

Lattice LFE5U-45F-8BG381C

Configurazione FPGA:

  • ECP5-45F
  • Speed grade: -8
  • Package: CABGA381
  • 72 blocchi MULT18X18D
  • circa 43.8k LUT/FF equivalenti

La configurazione funzionale utilizzata nei benchmark è:

DATA_WIDTH  = 8 bit
ACC_WIDTH   = 32 bit
N_INPUTS    = 256
N_NEURONS   = 4
PARALLEL    = variabile

Il datapath implementa:

INT8 × INT8
      ↓
   INT16
      ↓
sign extension
      ↓
   INT32
      ↓
accumulation
      ↓
   + bias
      ↓
    ReLU
      ↓
INT8 saturation

Lo scopo principale del benchmark è stato determinare il compromesso tra:

numero di MAC paralleli;
utilizzo dei DSP;
complessità del datapath;
routing;
frequenza massima;
latenza di elaborazione.
2. Architettura RTL

L'attuale datapath è organizzato gerarchicamente:

                    layer
                      │
             ┌────────┴────────┐
             │                 │
          neuron 0           neuron N
             │                 │
             ▼                 ▼
       neuron_parallel   neuron_parallel
             │                 │
             ▼                 ▼
           mac8              mac8
             │                 │
       MAC × PARALLEL    MAC × PARALLEL

Ogni neurone elabora N_INPUTS ingressi a gruppi di PARALLEL.

Con:

N_INPUTS = 256

il numero di gruppi è:

GROUPS = 256 / PARALLEL

Pertanto:

PARALLEL	Gruppi per neurone
16	16
8	32
4	64
2	128

I quattro neuroni vengono elaborati contemporaneamente.

3. MAC unit

Il modulo mac_unit implementa un singolo prodotto-accumulatore.

Per la configurazione INT8:

x : signed INT8
w : signed INT8

Il prodotto è:

INT8 × INT8 = INT16

Il risultato viene quindi esteso con segno a 32 bit:

INT16 → INT32

e sommato all'accumulatore.

L'operazione fondamentale è quindi:

acc_out = acc_in + (x × w)

L'implementazione è completamente parametrica rispetto a:

DATA_WIDTH
ACC_WIDTH
4. Balanced adder tree

Una modifica importante rispetto alla prima implementazione è stata la sostituzione dell'accumulatore combinazionale lineare con un balanced binary adder tree.

Una riduzione lineare avrebbe prodotto:

((((p0 + p1) + p2) + p3) + ...)

con profondità:

O(PARALLEL)

La nuova implementazione utilizza invece:

             sum
           /     \
        sum       sum
       /   \     /   \
      p0   p1   p2   p3

La profondità diventa:

O(log2(PARALLEL))

Per esempio:

PARALLEL = 8
→ 3 livelli

PARALLEL = 16
→ 4 livelli

PARALLEL = 32
→ 5 livelli

Questa modifica riduce significativamente la profondità combinazionale del datapath.

5. neuron_parallel

neuron_parallel esegue il calcolo di un singolo neurone.

Il funzionamento è:

start
  ↓
group 0
  ↓
group 1
  ↓
...
  ↓
group N
  ↓
+ bias
  ↓
ReLU
  ↓
saturation
  ↓
done

Durante ogni ciclo viene elaborato un gruppo di:

PARALLEL

prodotti.

L'accumulatore mantiene il risultato tra un gruppo e il successivo.

6. Test funzionale

Il testbench sim/parametric_tb.v utilizza:

DATA_WIDTH = 8
N_INPUTS   = 256
N_NEURONS  = 4
PARALLEL   = variabile
ACC_WIDTH  = 32

Sono stati definiti quattro casi di test.

N0 — accumulazione su più gruppi

Input:

x = 1

Pesi:

primi 32 = +1
restanti = 0

Risultato:

32 × 1 × 1 = 32

Output atteso:

32

Questo test verifica soprattutto la corretta gestione dell'accumulatore attraverso più gruppi.

N1 — bias

Pesi:

tutti = 0

Bias:

+10

Output atteso:

10
N2 — ReLU

Pesi:

tutti = -1

Input:

tutti = +1

Il risultato è negativo.

La ReLU produce:

0
N3 — saturazione

Pesi:

primi 32 = +4
restanti = 0

Input:

tutti = +1

Risultato:

32 × 4 = 128

L'uscita INT8 positiva viene saturata:

128 → 127
7. Risultato simulazione

Il test è passato con PARALLEL=16:

PARALLEL  = 16

PASS N0: 32
PASS N1: 10
PASS N2: 0 (ReLU)
PASS N3: 127 (saturation)

INT8 PARAMETRIC TEST PASSED

È passato anche con PARALLEL=32:

PARALLEL  = 32

PASS N0: 32
PASS N1: 10
PASS N2: 0 (ReLU)
PASS N3: 127 (saturation)

INT8 PARAMETRIC TEST PASSED

La correttezza funzionale del datapath parametrico è quindi confermata.

8. Sintesi e Place & Route

Dopo la simulazione il datapath è stato sintetizzato per ECP5 utilizzando:

Yosys

e successivamente piazzato e instradato con:

nextpnr-ecp5

Target:

LFE5U-45F
CABGA381
Speed grade -8

Il wrapper di benchmark genera internamente:

input;
pesi;
bias;
segnali di test.

In questo modo non vengono portati all'esterno i giganteschi bus del modello neurale.

Il top-level espone solamente:

clk
rst
start
y_bus
busy
done

Questa modifica è stata fondamentale.

Il primo tentativo esponeva infatti direttamente:

x_bus      ≈ 2048 bit
weights    ≈ 8192 bit
bias       ≈ 32 bit

portando a oltre 10.000 I/O fisiche richieste.

Il risultato era:

TRELLIS_IO: 10309/245

e quindi un errore di placement.

Il problema non era la dimensione logica del circuito, ma esclusivamente il numero di I/O.

9. PARALLEL = 16

Risorse sintetizzate:

LUT4 ≈ 2531
DFF  = 186

Risorse FPGA:

MULT18X18D = 64 / 72

quindi:

88% dei DSP

Timing:

Fmax ≈ 52.13 MHz
Tcrit ≈ 19.18 ns

Il percorso critico risultava fortemente influenzato dal routing.

Configurazione:

PARALLEL = 16
N_NEURONS = 4

produce:

16 × 4 = 64 MAC simultanei
10. PARALLEL = 8

Risorse:

MULT18X18D = 32 / 72

quindi:

32 DSP

Con quattro neuroni:

8 × 4 = 32 MAC simultanei

Timing:

Fmax ≈ 61.71 MHz
Tcrit ≈ 16.20 ns

Composizione del percorso critico:

logic   ≈ 6.43 ns
routing ≈ 9.77 ns
total   ≈ 16.20 ns

Questa configurazione è particolarmente importante perché corrisponde esattamente al target originale di:

32 MAC hardware simultanei
11. PARALLEL = 4

Risorse:

LUT4 = 804
DFF  = 194

MULT18X18D = 16 / 72

Quindi:

16 MAC simultanei

Timing:

Fmax ≈ 75.01 MHz
Tcrit ≈ 13.33 ns

Composizione:

logic   ≈ 6.67 ns
routing ≈ 6.66 ns
total   ≈ 13.33 ns

In questa configurazione logica e routing sono quasi perfettamente bilanciati.

12. PARALLEL = 2

Risorse:

LUT4 = 481
DFF  = 198

MULT18X18D = 8 / 72

Quindi:

8 MAC simultanei

Timing finale dopo routing:

Fmax ≈ 87.88 MHz
Tcrit ≈ 11.38 ns

Composizione:

logic   ≈ 6.43 ns
routing ≈ 4.95 ns
total   ≈ 11.38 ns

Il design è stato quindi verificato con target:

80 MHz

ottenendo:

87.88 MHz

e:

PASS

Il margine teorico rispetto a 80 MHz è:

T80MHz = 12.50 ns

12.50 - 11.38 ≈ 1.12 ns
13. Tabella comparativa
PARALLEL	MAC/neurone	Neuroni	MAC totali	DSP	Fmax	Tcrit	80 MHz
16	16	4	64	64	52.13 MHz	19.18 ns	FAIL
8	8	4	32	32	61.71 MHz	16.20 ns	FAIL
4	4	4	16	16	75.01 MHz	13.33 ns	FAIL
2	2	4	8	8	87.88 MHz	11.38 ns	PASS
14. Interpretazione

I risultati mostrano chiaramente il trade-off fondamentale.

Riducendo PARALLEL:

PARALLEL ↓
    ↓
MAC simultanei ↓
    ↓
DSP ↓
    ↓
adder tree ↓
    ↓
routing/congestione ↓
    ↓
Fmax ↑

ma contemporaneamente:

PARALLEL ↓
    ↓
numero gruppi ↑
    ↓
cicli necessari ↑
    ↓
latenza ↑

Quindi la frequenza massima non è sufficiente per scegliere la configurazione.

Occorre considerare il throughput complessivo:

throughput ≈ MAC_per_cycle × clock_frequency

A parità di quattro neuroni:

P2
8 MAC × 87.88 MHz
≈ 703 M MAC/s
P4
16 MAC × 75.01 MHz
≈ 1.20 G MAC/s
P8
32 MAC × 61.71 MHz
≈ 1.97 G MAC/s
P16
64 MAC × 52.13 MHz
≈ 3.34 G MAC/s

Questi valori sono una misura teorica del throughput del datapath MAC, non ancora del throughput end-to-end della rete, perché non includono i limiti della memoria esterna, del trasferimento dei pesi e del controller.

15. Scelta architetturale

Il risultato più importante del benchmark è che PARALLEL=8 rimane il candidato naturale per l'architettura V1 se l'obiettivo iniziale di progetto è mantenere circa:

32 MAC simultanei

Infatti:

PARALLEL = 8
N_NEURONS = 4

→ 32 MAC
→ 32 DSP / 72
→ 61.71 MHz

L'utilizzo DSP è ancora relativamente basso:

44% circa

lasciando risorse per:

controller memoria;
buffer;
interfaccia SPI;
DMA;
gestione layer;
eventuali pipeline;
future funzioni di controllo.

PARALLEL=2 è invece la configurazione più semplice da temporizzare tra quelle testate:

87.88 MHz

e passa il target di 80 MHz.

Tuttavia richiede:

128 gruppi

per elaborare un neurone da 256 ingressi.

Per questo motivo non è opportuno adottarlo automaticamente come configurazione definitiva solo perché raggiunge la frequenza più elevata.

16. Timing a 100 MHz

Il target di:

100 MHz

non viene attualmente raggiunto.

Il miglior risultato è:

87.88 MHz

con PARALLEL=2.

Il percorso critico è ancora:

weight FF
    ↓
MULT18X18D
    ↓
products
    ↓
adder/carry chain
    ↓
acc_next
    ↓
ReLU / saturation
    ↓
output FF

Il problema non è quindi un'elevata occupazione delle risorse FPGA.

Al contrario, con P2 l'FPGA è utilizzato molto poco:

DSP ≈ 11%
LUT ≈ 1%
FF  ≈ 0%

Il limite è principalmente temporale e dipende dal datapath combinazionale.

Per superare 100 MHz sarà probabilmente necessario introdurre una o più pipeline interne.

Questa ottimizzazione non è però ancora necessaria per procedere con la prossima fase architetturale.

17. Vincoli LPF

Durante questi benchmark il file:

synth/ecp5/top.lpf

è stato lasciato senza vincoli di pin.

nextpnr viene eseguito con:

--lpf-allow-unconstrained

Pertanto i numerosi warning relativi a I/O non vincolate sono intenzionali.

Il benchmark verifica quindi:

sintesi
placement
routing
timing

e non:

pin assignment
I/O standard della scheda
signal integrity

I vincoli LPF reali verranno aggiunti quando sarà definito il pinout della scheda FPGA-Neural.

18. Decisione per la prossima fase

Non è utile proseguire con benchmark PARALLEL=1.

Il punto di interesse architetturale è già stato individuato.

La prossima fase deve spostare il progetto dal benchmark sintetico verso l'architettura reale:

                    HOST
                      │
                      │ SPI
                      ▼
              FPGA interface
                      │
                      ▼
               Memory interface
                      │
          ┌───────────┴───────────┐
          ▼                       ▼
      PSRAM 8 MB               FPGA BRAM
          │                       │
          └──────────┬────────────┘
                     ▼
                tile/buffer
                     │
                     ▼
                 MAC engine
                     │
                     ▼
                accumulator
                     │
                     ▼
                 activation
                     │
                     ▼
                  output

Il core layer e neuron_parallel dovrà quindi essere separato dalla memoria fisica attraverso una Memory Interface.

19. Memoria V1

La memoria di lavoro prevista è:

ISSI IS66WVE4M16EBLL-70BLI

Caratteristiche:

64 Mbit
8 MB
4M × 16
parallel PSRAM
asynchronous/page mode
70 ns
2.73.6 V
48-TFBGA
6 × 8 mm

La memoria volatile sarà utilizzata come working memory durante l'inferenza.

La memoria persistente prevista è:

Winbond W25Q128JVS

con:

128 Mbit
16 MB
SPI NOR Flash

La divisione dei ruoli è:

W25Q128JVS
    ↓
persistent storage
    ↓
weights
biases
network metadata
FPGA/network configuration

e:

IS66WVE4M16EBLL
    ↓
runtime working memory
    ↓
input/output tensors
intermediate data
weight tiles

Infine:

FPGA BRAM
    ↓
local working buffers
tiles
accumulators
20. Conclusioni

La fase di caratterizzazione del datapath ha prodotto i seguenti risultati:

Il datapath INT8/INT32 è funzionalmente corretto.
Il test parametrico è passato.
Il balanced adder tree ha sostituito con successo la precedente riduzione lineare.
Il design è sintetizzabile per LFE5U-45F.
Il placement e routing sono stati completati correttamente.
Il problema iniziale delle migliaia di I/O è stato eliminato spostando i test vector all'interno del wrapper.
PARALLEL=8 implementa esattamente 32 MAC simultanei con quattro neuroni.
PARALLEL=2 raggiunge 87.88 MHz e supera il target di 80 MHz.
Il limite attuale a 100 MHz è dovuto al percorso combinazionale, non alla saturazione delle risorse FPGA.
Non è necessario continuare il benchmark verso PARALLEL=1.

La baseline architetturale rimane quindi:

LFE5U-45F-8BG381C
INT8 / INT32
256 inputs
4 neurons
PARALLEL parametrico

con:

PARALLEL = 8

come candidato principale per la configurazione orientata al throughput e:

PARALLEL = 2

come riferimento per la configurazione orientata alla frequenza.

La prossima attività significativa è l'integrazione della Memory Interface con la PSRAM esterna, mantenendo PARALLEL come parametro del motore computazionale.

Appendice A — Toolchain
Yosys

Yosys è il tool di sintesi RTL.

Flusso:

Verilog RTL
    ↓
elaborazione
    ↓
ottimizzazione
    ↓
mapping ECP5
    ↓
JSON netlist

Versione utilizzata:

Yosys 0.68+post

Binary:

/opt/homebrew/bin/yosys
Project Trellis

Project Trellis fornisce il database open-source dell'architettura ECP5 e gli strumenti necessari all'implementazione.

Tra gli strumenti disponibili:

ecppack
ecppll
ecpbram
ecpunpack

Installazione utilizzata:

/tmp/prjtrellis/install
nextpnr-ecp5

nextpnr-ecp5 esegue:

placement
routing
timing analysis

Versione:

nextpnr-0.11.1-19-g8dbcee5

Binary:

/tmp/nextpnr/build/nextpnr-ecp5

Parametri principali:

--45k

seleziona LFE5U-45F.

--package CABGA381

seleziona il package.

--speed 8

seleziona speed grade -8.

--json

carica la netlist generata da Yosys.

--lpf

carica i vincoli di pin.

--lpf-allow-unconstrained

permette I/O non vincolate.

--freq 80

richiede un timing target di 80 MHz.

Icarus Verilog

Icarus Verilog viene utilizzato per la simulazione RTL.

Esempio:

iverilog -g2012 \
  -Ptb.PARALLEL=16 \
  -o sim/parametric_256x4_p16 \
  sim/parametric_tb.v \
  rtl/mac_unit.v \
  rtl/mac8.v \
  rtl/neuron_parallel.v \
  rtl/layer.v

Esecuzione:

vvp sim/parametric_256x4_p16

Icarus verifica principalmente la correttezza funzionale del RTL.

Appendice B — Differenza tra simulazione e implementazione
Simulazione
Icarus Verilog

verifica:

algebra signed;
prodotti;
accumulazione;
gruppi;
bias;
ReLU;
saturazione;
segnali busy e done.
Implementazione
Yosys
+
nextpnr-ecp5

verifica:

sintetizzabilità;
mapping FPGA;
LUT;
FF;
DSP;
placement;
routing;
timing;
Fmax.

Le due verifiche sono complementari.
 r
Appendice C — Stato attuale
RTL funzionale              PASS
Simulazione parametrica     PASS
Sintesi ECP5                PASS
Placement                   PASS
Routing                     PASS

PARALLEL=16                 52.13 MHz
PARALLEL=8                  61.71 MHz
PARALLEL=4                  75.01 MHz
PARALLEL=2                  87.88 MHz

Target 80 MHz, P2           PASS
Target 100 MHz              FAIL

Memory Interface            DA IMPLEMENTARE
PSRAM controller            DA IMPLEMENTARE
Host SPI interface          DA IMPLEMENTARE
Layer engine reale          PROSSIMA FASE