Files
FPGA-Neural/docs/latex/tests_timing.tex
T
micheleandClaude Sonnet 5 cc6cfe168e docs: update LaTeX docs for N16 real timing closure + honest ESP32-S3 projection (EXP-0097)
architecture.tex: document the real MAC-pipeline fix (Stage 1a/1b
split) and its real result on both N8 (WNS 0.000ns -> +0.108ns) and
N16 (now closed, WNS=+0.269ns) -- N16 is a real, verified candidate
for a future board revision, N8 remains the configuration in current
physical fabrication.

tests_timing.tex: extended P&R history table, real N8/N16 signoff
tables (post-fix), the new N16 critical path (Director queue logic,
still route-dominated) and the negative result of a second directive
attempt (confirms current result is the best found). Added a new,
clearly-labeled PROJECTION (not a measurement) for N16 vs ESP32-S3 --
30-68x range, built from real measured scaling factors (same core
count as the original ECP5 comparison, real clock ratio, real 2x INT8
packing factor) -- more grounded than the old, superseded ~55-85x
figure, with the same DDR3-bandwidth-bound honest caveat carried
forward.

datasheet.tex: N8/N16 side-by-side timing/utilization/performance
tables, open items and revision history updated to reflect physical
fabrication status and the N16 candidate decision.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
2026-09-22 00:59:46 +02:00

280 lines
14 KiB
TeX

\chapter{Verifica funzionale, timing e confronti}
\label{chap:tests}
\section{Metodologia di verifica}
Il progetto segue una disciplina di verifica a due livelli, applicata
sistematicamente a ogni modulo nuovo prima di fidarsi di un risultato
di sintesi o di place-and-route:
\begin{enumerate}
\item \textbf{Verifica isolata} (Icarus Verilog / \texttt{iverilog}):
ogni modulo nuovo \`e verificato da solo, con un modello di memoria
comportamentale semplificato, prima di essere collegato al resto
del sistema (``one variable at a time'').
\item \textbf{Verifica funzionale reale su DDR3} (Vivado \texttt{xsim}):
il sistema completo (o una sua configurazione reale, es. N=8) \`e
simulato contro il modello DDR3 \emph{reale} fornito da Xilinx
(\texttt{ddr3\_model.sv}, lo stesso modello usato per la
certificazione del MIG), con calibrazione realistica e tracce di
comando JEDEC reali --- non un modello di memoria semplificato.
\end{enumerate}
Solo dopo che entrambi i livelli passano si procede a un vero
place-and-route in contesto (\texttt{synth\_design} + \texttt{opt\_design}
+ \texttt{place\_design} + \texttt{route\_design}), sulla parte reale
XC7A100T-CSG324-2, mai fuori contesto e mai stimato.
\section{Risultati della verifica funzionale (reali, non stimati)}
\begin{table}[h]
\centering
\begin{tabular}{lll}
\toprule
\textbf{Modulo / testbench} & \textbf{Risultato} & \textbf{Note} \\
\midrule
\texttt{tb\_mig\_native\_adapter.v} & 12/12 PASS & adattatore DDR3 nativo, contro il modello DDR3 reale \\
\texttt{tb\_n2\_system\_ddr3.v} & 8/8 PASS & sistema N=2 completo su DDR3 reale \\
\texttt{tb\_packed\_slot.v} & 9/9 PASS & include verifica read-after-write reale in DDR3 \\
\texttt{tb\_spi\_host\_bridge\_v3.v} & 49/49 PASS & protocollo SPI di gestione completo \\
\texttt{tb\_host\_mem\_bridge.v} & 16/16 PASS & percorso di accesso raw DDR3 dell'host \\
\texttt{tb\_systolic\_group.v} & 8/8 PASS & un gruppo sistolico isolato, 2 job consecutivi \\
\texttt{tb\_neural\_director\_grouped.v} & 4/4 PASS & dispatch a ottetti, stallo su mismatch, wraparound \\
\texttt{tb\_sdram\_arbiter\_hier.v} & 23/23 PASS & arbitro gerarchico, contesa cross-gruppo e host \\
\texttt{tb\_n16\_system\_ddr3.v} & 32/32 PASS & sistema N=16 completo, su DDR3 reale \\
\texttt{tb\_n8\_system\_ddr3.v} & \textbf{16/16 PASS} & \textbf{sistema N=8 completo, su DDR3 reale (target definitivo)} \\
\bottomrule
\end{tabular}
\caption{Sottoinsieme rappresentativo dei test funzionali reali eseguiti nel progetto. Ogni riga \`e un vero risultato di simulazione, non una stima.}
\end{table}
\section{Cronologia reale dei segni di timing (place-and-route)}
\label{sec:pnr-history}
Ogni riga della tabella seguente \`e un vero risultato di
\texttt{report\_timing\_summary} dopo un vero \texttt{route\_design},
sulla stessa parte fisica (XC7A100T-CSG324-2) e sullo stesso dominio
di clock reale (155.039\,MHz, \texttt{clk\_pll\_i}) --- mai una stima
di sintesi fuori contesto.
\begin{longtable}{p{1.3cm}p{3.7cm}p{0.9cm}p{2.1cm}p{1.3cm}p{1.3cm}}
\toprule
\textbf{Exp.} & \textbf{Cosa \`e cambiato} & \textbf{N} & \textbf{WNS (ns)} & \textbf{LUT} & \textbf{DSP48E1} \\
\midrule
\endhead
0074 & prima vera P\&R in contesto: DDR3 + pin & 2 & +0.040 & 5140 & 16 \\
0076 & + registri, + pin, + fix SPI & 2 & +0.056 & 5173 & 16 \\
0078 & + bridge flash (STARTUPE2 reale) & 2 & +0.013 & 5213 & 16 \\
0079 & + motore attivazioni reale & 2 & +0.030 & 5379 & 16 \\
0082 & + packing attivazioni pi\`u denso & 2 & +0.068 & 5437 & 16 \\
0083 & + DDRManager fase 1, canale 16 bit & 2 & +0.073 & 5644 & 16 \\
0084 & canale DDR3 a 32 bit + clock pi\`u veloce (172.4\,MHz) & 2 & $-0.618$ \textbf{(FALLITO)} & 6418 & 16 \\
0086 & canale a 32 bit, clock ripristinato a 155.039\,MHz & 2 & +0.096 \textbf{(CHIUSO)} & 6382 & 16 \\
0088 & + motore di scrittura risultati in DDR3 & 2 & +0.100 \textbf{(CHIUSO)} & 6642 & 16 \\
0093 & architettura sistolica, arbitro piatto a 21 vie & 16 & $-0.913$ \textbf{(FALLITO)} & 19751 & 128 \\
0094 & + arbitro gerarchico a 2 livelli & 16 & $-0.646$ (ancora fallito) & 19936 & 128 \\
0094 & + tuning delle direttive P\&R & 16 & $-0.338$ (ancora fallito) & 19936 & 128 \\
0095 & curva N=4 (1 gruppo) & 4 & $-0.005$ (2 endpoint falliti) & 8794 & 32 \\
0095/0096 & \texttt{n8\_system\_ddr3\_top.v}, in fabbricazione fisica & 8 & 0.000 (CHIUSO) & 12535 & 64 \\
0097 & + pipeline MAC aggiuntiva (branch \texttt{n16-timing-closure}) & 8 & +0.108 (CHIUSO, migliorato) & 12536 & 64 \\
\textbf{0097} & \textbf{+ pipeline MAC aggiuntiva} & \textbf{16} & \textbf{+0.269 (CHIUSO)} & \textbf{19903} & \textbf{128} \\
\bottomrule
\caption{Cronologia reale dei segni di place-and-route, dal primo P\&R in contesto fino ai risultati pi\`u recenti su entrambe le configurazioni N=8 e N=16.}
\end{longtable}
\subsection{Il segno in fabbricazione fisica: N=8}
\begin{table}[h]
\centering
\begin{tabular}{ll}
\toprule
\textbf{Metrica} & \textbf{Valore reale} \\
\midrule
Clock PHY DDR3 (sys\_clk\_p/n) & 310.078\,MHz (periodo 3.225\,ns) \\
Clock di calcolo (ui\_clk/clk\_pll\_i) & 155.039\,MHz \\
WNS (setup slack) & \textbf{+0.108\,ns} --- chiuso, con la correzione pipeline MAC (EXP-0097) \\
WHS (hold slack) & +0.036\,ns \\
Endpoint falliti & 0 (setup e hold) \\
LUT utilizzate & 12536 / 63400 (19.77\%) \\
Registri utilizzati & 19910 / 126800 (15.70\%) \\
DSP48E1 utilizzati & 64 / 240 (26.7\%) \\
Parallelismo reale & 8 elementi di elaborazione paralleli \\
\bottomrule
\end{tabular}
\caption{Segno di temporizzazione reale per \texttt{n8\_system\_ddr3\_top.v} con la correzione pipeline MAC (EXP-0097) --- la configurazione fisicamente in fabbricazione. Il segno originale (pre-correzione, EXP-0095/0096) chiudeva a WNS=0.000\,ns esatto, senza margine di riserva; questa correzione lo migliora senza alcuna regressione funzionale.}
\end{table}
\subsection{Il nuovo segno reale: N=16 ORA CHIUDE}
\label{sec:n16-closed}
Il percorso critico che inizialmente impediva la chiusura del timing a
N=16 \`e stato tracciato realmente (non ipotizzato) fino all'interno
del datapath MAC di \texttt{neural\_processor\_packed.v} --- lo stesso
nucleo di calcolo descritto nel Capitolo~\ref{chap:architecture},
invariato dalla prima versione del progetto, che a N=2 chiudeva gi\`a
con un margine estremamente sottile (+0.0999\,ns). A N=16 la maggiore
occupazione complessiva del die (31\% LUT) aumentava la congestione di
piazzamento a sufficienza da erodere quel margine gi\`a minimo.
\textbf{Questo collo di bottiglia \`e stato risolto} (\S\ref{sec:mac-pipeline}
del Capitolo~\ref{chap:architecture}) aggiungendo un vero stadio di
pipeline nel datapath MAC. Risultato reale, su un branch di sviluppo
dedicato (\texttt{n16-timing-closure}), isolato dalla scheda fisica in
produzione:
\begin{table}[h]
\centering
\begin{tabular}{ll}
\toprule
\textbf{Metrica} & \textbf{Valore reale} \\
\midrule
WNS (setup slack) & \textbf{+0.269\,ns} --- \textbf{CHIUSO} \\
WHS (hold slack) & +0.026\,ns \\
Endpoint falliti & 0 su 106087 (setup), 0 su 106084 (hold) \\
LUT utilizzate & 19903 / 63400 (31.39\%) \\
Registri utilizzati & 35409 / 126800 (27.93\%) \\
DSP48E1 utilizzati & 128 / 240 (53.33\%) \\
Parallelismo reale & 16 elementi di elaborazione paralleli \\
Verifica funzionale & 32/32 PASS su DDR3 reale (\texttt{tb\_n16\_system\_ddr3.v}) \\
\bottomrule
\end{tabular}
\caption{Segno di temporizzazione reale per \texttt{n16\_system\_ddr3\_top.v} con la correzione pipeline MAC (EXP-0097). Margine reale migliore di quello storico originale di N=2 (+0.0999\,ns).}
\end{table}
Dopo questa correzione, il percorso critico si \`e spostato di nuovo
(prova reale che la correzione ha effettivamente risolto il proprio
problema specifico): ora si trova nella logica di aggiornamento della
coda del Director (\texttt{neural\_director\_grouped.v}), ancora
dominato dal routing fisico (73\%) pi\`u che dalla profondit\`a
logica. Un secondo tentativo reale con direttive di place-and-route
alternative ha dato un risultato \emph{peggiore} (+0.168\,ns), confermando
che il margine attuale (+0.269\,ns) \`e gi\`a il migliore risultato
reale ottenuto con il solo tuning delle direttive, senza ulteriori
modifiche RTL.
\textbf{Stato reale onesto}: N=16 non \`e pi\`u limitato da un vincolo
tecnico di temporizzazione. La sua adozione come scheda fisica \`e ora
una decisione dell'utente, non un problema RTL ancora aperto. La
scheda fisica attualmente in fabbricazione resta N=8 (fabbricazione
gi\`a avviata al momento di questa correzione); N=16 \`e un candidato
reale, verificato, per una futura revisione.
\section{Confronto con un riferimento reale: ESP32-S3}
\label{sec:esp32-comparison}
Un confronto quantitativo con un microcontrollore ESP32-S3 esiste,
ma va presentato con la dovuta cautela storica, per non presentare
come attuale un dato ormai superato.
\begin{itemize}
\item \textbf{Dato reale, misurato (architettura precedente, ECP5)}:
la versione precedente del progetto (v2, su FPGA Lattice ECP5,
ora archiviata) ha misurato realmente uno speedup di
\textbf{$\sim$9.5--14$\times$ rispetto a ESP32-S3} (baseline
misurata) per un carico di lavoro tipo riconoscimento facciale
(classe MobileFaceNet), con 16 core paralleli a 64--97\,MHz.
\item \textbf{Proiezione non verificata (superata)}: da quel dato
era stata derivata una proiezione di $\sim$55--85$\times$ su
ESP32-S3 per l'architettura Artix-7, basata su un'ipotesi di
\textbf{30 core paralleli} limitati solo dal conteggio dei DSP
disponibili. Questa proiezione \textbf{non \`e mai stata verificata}
con una misura reale a livello di sistema completo, ed \`e oggi
superata dalla scoperta successiva (\S~\ref{sec:bottleneck}) che il
sistema \`e limitato dalla banda DDR3, non dal conteggio dei DSP ---
l'ipotesi dei 30 core non \`e pi\`u realistica alla luce di questo
vincolo.
\end{itemize}
\textbf{Stato onesto attuale}: non esiste ancora una misura reale,
diretta, di throughput aggregato (inferenze al secondo, o MAC/s
sostenuti) di nessuna configurazione (N=8 o N=16) confrontata con un
benchmark ESP32-S3 aggiornato. Il picco teorico calcolabile,
puramente computazionale, \`e:
\[
8~\text{PE} \times 16~\text{MAC/ciclo} \times 155.039\times10^6~\text{cicli/s} = 19.84~\text{GMAC/s di picco teorico aggregato (N=8)}
\]
\[
16~\text{PE} \times 16~\text{MAC/ciclo} \times 155.039\times10^6~\text{cicli/s} = 39.69~\text{GMAC/s di picco teorico aggregato (N=16)}
\]
ma questo \`e un limite superiore puramente computazionale: dato il
vincolo reale di banda DDR3 (2.48\,GB/s fisici, condivisi tra tutti i
PE attivi), il throughput realmente sostenibile in un carico di lavoro
reale sar\`a inferiore, nella stessa misura gi\`a documentata a N=1/2
(\S~\ref{sec:bottleneck}) --- e la condivisione dello stesso canale
DDR3 tra il doppio dei PE a N=16 rende questo vincolo ANCORA PI\`U
stringente rispetto a N=8, non meno.
\subsection{Una nuova stima onesta per N=16 (proiezione, non misura)}
Su richiesta esplicita, ecco una stima reale --- costruita da dati
reali gi\`a misurati, ma essa stessa \textbf{una proiezione, non una
nuova misura diretta} --- pi\`u solida della vecchia proiezione
$\sim$55--85$\times$ ormai superata (sopra), perch\'e confronta lo
\textbf{stesso numero di core} (16 vs 16) invece di ipotizzare 30 core
limitati solo dai DSP:
\begin{table}[h]
\centering
\begin{tabular}{lll}
\toprule
\textbf{Fattore di scala reale} & \textbf{Base} & \textbf{Valore} \\
\midrule
Numero di core & 16 (ECP5) vs 16 (Artix-7 N=16) & $1\times$ (confronto diretto) \\
Rapporto di clock & 155.039\,MHz vs 64--97\,MHz (reale, ECP5) & $1.60\times$--$2.42\times$ \\
Packing INT8 per DSP & 2 MAC/DSP (Artix-7) vs 1 MAC/DSP (ECP5, non impacchettato) & $2\times$ \\
\midrule
\textbf{Fattore di scala combinato} & & \textbf{$3.20\times$--$4.85\times$} \\
\bottomrule
\end{tabular}
\caption{Fattori di scala reali (misurati) tra l'architettura ECP5 (v2) e Artix-7 N=16 (v3), a parit\`a di numero di core.}
\end{table}
Applicando questo fattore di scala al dato reale, misurato,
$\sim$9.5--14$\times$ su ESP32-S3 (stesso workload MobileFaceNet-class):
\[
9.5\times3.20 \approx \mathbf{30\times} \qquad\qquad 14\times4.85 \approx \mathbf{68\times}
\]
\textbf{Stima onesta}: N=16, su un carico di lavoro simile a quello
del confronto originale, \`e plausibilmente nell'ordine di
\textbf{30--68$\times$ ESP32-S3} (punto centrale $\sim$45$\times$) ---
una proiezione di puro throughput di calcolo, costruita da fattori di
scala reali, \textbf{non una misura diretta}. Il dato esatto reale
richiede un vero benchmark end-to-end (stesso workload, hardware
reale o simulazione a livello di sistema completo) --- non ancora
eseguito. Come per N=8, il vincolo reale di banda DDR3
(\S~\ref{sec:bottleneck}) former\`a probabilmente un tetto reale
inferiore a questa proiezione puramente computazionale su un carico
di lavoro reale, specialmente a N=16 dove pi\`u PE condividono lo
stesso canale fisico.
\section{Lezioni reali dal processo di verifica}
Alcuni bug reali, trovati e corretti durante la verifica di questo
progetto, meritano di essere documentati perch\'e generalizzabili:
\begin{itemize}
\item \textbf{Impulsi a colpo singolo persi al confine
dell'arbitraggio}: un richiedente che genera un impulso di
richiesta di un solo ciclo pu\`o essere perso se l'elemento che lo
riceve non \`e ancora pronto a elaborarlo nello stesso ciclo ---
causa originaria di un bug reale gi\`a nella primissima versione
dell'arbitro, e riemerso (in una forma nuova, al confine tra i due
livelli dell'arbitro gerarchico) durante lo sviluppo di N=16/N=8;
risolto con un'aggancio (\emph{latch}) persistente per richiesta,
non con un semplice registro.
\item \textbf{Corse (race condition) nei testbench}: pilotare gli
stimoli sullo stesso fronte di clock campionato dal modulo sotto
test, specialmente in chiamate ravvicinate senza un ciclo di
margine naturale, pu\`o causare doppie registrazioni silenziose ---
risolto pilotando gli stimoli sul fronte opposto.
\item \textbf{Casi limite di larghezza di bus}: espressioni come
$\log_2(N)$ diventano zero (e quindi un intervallo di bit non
valido) quando $N=1$, un caso non testato fino all'esplorazione
della curva N=4/8/16 --- risolto con un valore minimo di 1 bit
esplicito.
\end{itemize}