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
280 lines
14 KiB
TeX
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}
|