The repository had accumulated multiple, contradictory "current state" documents for V2 hardware: an old V1 IT/EN datasheet copy nested inside hardware/v2/docs/datasheet/, a stray untracked duplicate at repo root (docs/DatasheetLatex/), and a second, much older documentation track (hardware/v2/docs/*.md: PRE_PCB_VERIFICATION.md, PRE_PCB_CLOSURE_4POINT.md, MEMORY_UPGRADE_64MB_N8.md, and 10 more) describing an earlier PSRAM/ N_SLOTS<=2 milestone alongside the real, current SDRAM/N_SLOTS=4 board. The LaTeX datasheet's own front matter (features/pinout cover pages) and chapter 9 (benchmarks) were themselves still describing that obsolete architecture, contradicting the real, current chapters 5/7/10 elsewhere in the same document. This commit: - Flattens hardware/v2/docs/datasheet/files/docs/datasheet/v2-en/* up to hardware/v2/docs/datasheet/ (was 4 levels of redundant nesting). - Removes the old V1 IT/EN LaTeX copies and the stray root-level duplicate entirely (recoverable from git history, not from disk). - Preserves the real component reference PDFs (ECP5 eval board, ISSI PSRAM, programming cables) under datasheet/references/. - Removes 13 superseded hardware/v2/docs/*.md status documents after folding every real, unique fact they contained into the datasheet: SPI max verified clock (12MHz, exact 12.8MHz CDC edge), SDRAM directed boundary test (21/21 PASS), 16MHz oscillator MPN (ECS-3225MV-160-BN-TR), and the real FPGA<->SDRAM ball mapping cross-check. - Rewrites the datasheet's own front matter, ch.4 (parameters), ch.8 (top-level module -- was documenting the wrong, non-physical top entirely), and ch.9 (benchmarks) to describe the current, real SDRAM/ N_SLOTS=4 production board, while keeping the real PSRAM-era chapters as clearly-labeled history rather than deleting correctly-measured work. - Fixes a title-page tikzpicture that was clipped off the page edge (pre-existing, unrelated to this change) by scaling it to fit. Net: 85 files changed, -8814/+498 lines. hardware/v2/docs/ now contains exactly one current datasheet plus FIRST_POWER_ON.md (a bring-up runbook, not a duplicate spec). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
258 lines
13 KiB
TeX
258 lines
13 KiB
TeX
\chapter[ECP5 implementation \& benchmarks]{ECP5 implementation, real benchmark campaign \& measured results}
|
|
\label{ch:impl2}
|
|
|
|
\section{Flow and verification discipline}
|
|
Every number in this chapter is labelled \textsc{Theoretical},
|
|
\textsc{Simulated}, \textsc{Post-P\&R measured}, or \textsc{Derived}
|
|
(a combination of two real measurements, e.g.\ cycles $\div$ real Fmax).
|
|
No result is invented, approximated to look better, or reported without
|
|
a matching real measurement.
|
|
|
|
\begin{tabularx}{\textwidth}{L{5.0cm} C{3.0cm} Y}
|
|
\toprule
|
|
\rowh \thd{Verification stage} & \thd{Outcome} & \thd{Covers} \\
|
|
\midrule
|
|
RTL simulation (Verilator 5.050) & \PASS & bit-exact correctness vs.\ a software golden model \\
|
|
\rowa ECP5 synthesis (Yosys \code{synth\_ecp5}) & \PASS, 0 problems & synthesizability, resource mapping \\
|
|
Place\&route (real \code{nextpnr-ecp5}) & \PASS at \code{N\_SLOTS}$\le$2 & LUT/FF/DSP, real timing \\
|
|
\rowa Full benchmark campaign & 24/24 bit-exact & 6 workloads $\times$ 4 \code{N\_SLOTS} configurations \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
|
|
\begin{fnnote}[Verilator, not Icarus, for V2]
|
|
Two independent Icarus Verilog v13.0 scheduling defects were found and
|
|
reproduced on minimal repros during V2's own M1 milestone (a
|
|
task/scope-entry desync and a spurious condition evaluation, both
|
|
edge-parity dependent) --- Verilator gives correct results on the same
|
|
repros. V1's own certification (performed separately, with Icarus) was
|
|
unaffected, since its own testbenches already avoided the trigger
|
|
pattern by convention; this is flagged honestly, not glossed over.
|
|
\end{fnnote}
|
|
|
|
\section{V1 vs.\ V2 --- final comparison}
|
|
Both systems full-system (not isolated modules), same
|
|
PARALLEL/P\_IN=8, same real, unmodified V1 PSRAM chain.
|
|
|
|
\begin{tabularx}{\textwidth}{L{3.6cm} C{2.6cm} C{2.6cm} Y}
|
|
\toprule
|
|
\rowh \thd{Metric} & \thd{V1} & \thd{V2 (N\_SLOTS=2)} & \thd{Class} \\
|
|
\midrule
|
|
Fmax & 68.65~MHz (\FAIL) & \textbf{87.72~MHz} (\PASS) & Post-P\&R \\
|
|
\rowa LUT (Total LUT4s) & 8907 & 4359 & Post-P\&R \\
|
|
FF (Total DFFs) & 4900 & 3924 & Post-P\&R \\
|
|
\rowa DSP (MULT18X18D) & 16 & 16 & Post-P\&R \\
|
|
BRAM (DP16KD) & 2 & 0 & Post-P\&R \\
|
|
\rowa cycles/neuron (1 neuron, 8 inputs, real PSRAM) & 209 & 166 & Simulated \\
|
|
Real wall-clock speedup vs.\ V1 & 1.00$\times$ & \textbf{2.6$\times$} & Derived \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
\begin{center}\footnotesize\itshape\color{fnGrey}
|
|
V1's own figures are its already-certified, frozen baseline (not
|
|
re-measured this session); V2's figures are real, current measurements
|
|
including both post-campaign optimizations.\end{center}
|
|
|
|
\begin{fnnote}[Where the win comes from --- and where it does not]
|
|
V2's advantage comes from a faster pipeline and a higher achievable
|
|
clock, \textbf{not} primarily from the multi-processor concurrency the
|
|
architecture was built to add. That concurrency's own real payoff, given
|
|
the single-PSRAM-port memory subsystem, is much smaller than a naive
|
|
\code{N\_SLOTS}$\times$\code{P\_IN} calculation would suggest ---
|
|
\S\ref{sec:scaling}.
|
|
\end{fnnote}
|
|
|
|
\section{Real \texttt{N\_SLOTS} sweep --- Fmax and resources}
|
|
Full system, real place\&route, both memory optimizations active
|
|
(word-burst \S\ref{sec:burstimpl} $+$ activation cache
|
|
\S\ref{sec:cacheimpl}).
|
|
|
|
\begin{tabularx}{\textwidth}{C{1.6cm} C{2.2cm} C{1.6cm} C{1.6cm} C{1.6cm} C{1.6cm} Y}
|
|
\toprule
|
|
\rowh \thd{N\_SLOTS} & \thd{Fmax} & \thd{LUT4} & \thd{FF} & \thd{DSP} & \thd{BRAM} & \thd{80\,MHz} \\
|
|
\midrule
|
|
1 & 131.79~MHz & 2760 & 2405 & 8/72 & 0 & \PASS \\
|
|
\rowa 2 & \textbf{87.72~MHz} & 4359 & 3924 & 16/72 & 0 & \PASS (\textbf{recommended}) \\
|
|
4 & 65.01~MHz & 9158 & 7986 & 32/72 & 0 & \FAIL \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
|
|
\subsection{Fmax versus N\_SLOTS}
|
|
\begin{center}
|
|
\begin{tikzpicture}
|
|
\begin{axis}[
|
|
width=0.68\textwidth,height=6.0cm,
|
|
xlabel={\footnotesize N\_SLOTS}, ylabel={\footnotesize Fmax [MHz]},
|
|
xtick={1,2,4}, ymin=50,ymax=145, ytick={50,65,80,95,110,125,140},
|
|
tick label style={font=\scriptsize}, label style={font=\footnotesize},
|
|
grid=major, grid style={fnRule!40},
|
|
legend style={font=\scriptsize,at={(0.5,-0.28)},anchor=north,legend columns=2}]
|
|
\addplot[fnBlue,mark=square*,thick,mark options={fill=fnBlue}]
|
|
coordinates {(1,152.44)(2,133.58)(4,112.07)};
|
|
\addlegendentry{word-burst only}
|
|
\addplot[fnRed,mark=*,thick,mark options={fill=fnRed}]
|
|
coordinates {(1,131.79)(2,87.72)(4,65.01)};
|
|
\addlegendentry{$+$ activation cache}
|
|
\draw[fnAmber,dashed,thick] (axis cs:1,80)--(axis cs:4,80);
|
|
\node[font=\scriptsize,text=fnAmber] at (axis cs:3.3,74){80 MHz target};
|
|
\end{axis}
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
\begin{center}\footnotesize\itshape\color{fnGrey}
|
|
The activation cache's own real Fmax cost grows much faster with
|
|
N\_SLOTS than the arbiter-widening cost alone --- a single shared
|
|
resource with N\_SLOTS request ports and an unpipelined,
|
|
broadcast-capable hit-check.\end{center}
|
|
|
|
\section{Real parallel scaling}
|
|
\label{sec:scaling}
|
|
Not assumed --- computed from real cycle counts, largest workload
|
|
(256 independent neurons sharing one input vector).
|
|
|
|
\begin{tabularx}{\textwidth}{C{1.6cm} C{2.6cm} C{2.0cm} C{2.6cm} C{2.0cm}}
|
|
\toprule
|
|
\rowh \thd{N\_SLOTS} & \thd{Speedup(N)} & \thd{Efficiency} & \thd{PSRAM utilization} & \thd{Real wall-clock speedup vs.\ N=1} \\
|
|
\midrule
|
|
1 & 1.00$\times$ & 100\% & 55.5--71.8\% & 1.00$\times$ \\
|
|
\rowa 2 & 1.06$\times$ & 53\% & $\approx$90\% & 0.99$\times$ (a wash) \\
|
|
4 & 1.06$\times$ & 27\% & $\approx$90\% & 0.79$\times$ (\emph{slower}) \\
|
|
8 & 1.06$\times$ & 13\% & $\approx$90\% & --- \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
\begin{center}\footnotesize\itshape\color{fnGrey}
|
|
Pre-optimization figures, isolating the real scaling behavior from the
|
|
two memory optimizations' own effect (\S\ref{sec:burstimpl}--\ref{sec:cacheimpl}).\end{center}
|
|
|
|
\begin{fnwarn}[The central, measured finding]
|
|
Real cycle-count speedup from \code{N\_SLOTS}=1 to \code{N\_SLOTS}=8 is
|
|
essentially flat (1.05--1.06$\times$) for sustained, memory-bound
|
|
workloads --- the single shared PSRAM port saturates at
|
|
$\approx$90\% utilization regardless of \code{N\_SLOTS}$\ge$2. Once real
|
|
Fmax degradation is also folded in, \code{N\_SLOTS}=4 measures
|
|
\emph{slower} in real wall-clock time than \code{N\_SLOTS}=1. More
|
|
hardware parallelism made this workload class worse, not better,
|
|
because the bottleneck was never compute.
|
|
\end{fnwarn}
|
|
|
|
\section{Memory optimization \#1 --- word-level burst reads}
|
|
\label{sec:burstimpl}
|
|
See ch.~\ref{ch:mem}, \S\ref{sec:burst}, for the full rationale. Real,
|
|
measured single-job cycle reduction: $-$49\% (1 tile), $-$54\% (3
|
|
tiles), $-$56\% (5 tiles). Combined real wall-clock speedup on the
|
|
256-neuron sustained workload: 2.24--2.37$\times$ across every
|
|
\code{N\_SLOTS} tested, at negligible real Fmax cost.
|
|
|
|
\section{Memory optimization \#2 --- shared activation cache}
|
|
\label{sec:cacheimpl}
|
|
See ch.~\ref{ch:mem}, \S\ref{sec:cache}. A further real 1.66--2.00$\times$
|
|
cycle reduction on top of optimization~\#1, at a real, steep Fmax cost
|
|
that makes \code{N\_SLOTS}=4 fail 80\,MHz outright.
|
|
|
|
\begin{tabularx}{\textwidth}{C{1.6cm} C{2.4cm} C{2.4cm} C{2.4cm}}
|
|
\toprule
|
|
\rowh \thd{N\_SLOTS} & \thd{Wall-clock, baseline} & \thd{Wall-clock, final} & \thd{Total real speedup} \\
|
|
\midrule
|
|
1 & 5118.1~$\mu$s & 1324.9~$\mu$s & \textbf{3.86$\times$} \\
|
|
\rowa 2 & 5169.5~$\mu$s & 2113.9~$\mu$s & \textbf{2.45$\times$} (recommended) \\
|
|
4 & 6498.7~$\mu$s & 2842.6~$\mu$s (Fmax fails) & 2.29$\times$ but a real regression vs.\ \#1 alone \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
|
|
\section{Bottleneck analysis}
|
|
\begin{tabularx}{\textwidth}{L{2.8cm} Y}
|
|
\toprule
|
|
\rowh \thd{Candidate} & \thd{Verdict, with real evidence} \\
|
|
\midrule
|
|
\textbf{Memory (PSRAM port)} & \textbf{The real bottleneck.} $\approx$90\% utilization at N\_SLOTS$\ge$2; real compute-to-memory-wait ratio on the order of 1:170--1:220. \\
|
|
\rowa Compute (Neural Processor) & Not the bottleneck --- the pipeline is idle most of the time waiting for data. \\
|
|
Arbiter overhead & Real but small: a mandatory 1-cycle pending-latch (correctness, not choice) plus modest Fmax cost ($-$6\% at N\_SLOTS=2, word-burst alone). \\
|
|
\rowa Director/dependency logic & Not the bottleneck --- zero lost/duplicated jobs, no queueing backlog observed; a real \emph{fairness} issue exists (\S\ref{ch:sched}) but does not limit throughput. \\
|
|
DSP/LUT/FF availability & Not the bottleneck at N\_SLOTS$\le$4 --- all well under budget; DSP would eventually bind at N\_SLOTS=9 (64/72), never reached in practice since the memory bottleneck dominates first. \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
|
|
\section{Limitations, honestly stated (PSRAM-era campaign above)}
|
|
\begin{itemize}
|
|
\item V1's own memory-utilization/stall figures were not re-measured
|
|
this session (V1 is frozen); only its already-certified numbers
|
|
are used for comparison.
|
|
\item No clean per-cycle split between ``processor computing'' and
|
|
``processor waiting for memory'' exists in the current
|
|
instrumentation --- reported figures use tile-delivery-rate
|
|
proxies, not an exact split.
|
|
\item Power/energy: \textbf{NOT MEASURED} --- no ECP5 power estimator
|
|
(\code{ecppower}, \code{icepower}, or equivalent) is available in
|
|
this project's toolchain; no value is invented in its place.
|
|
\item \code{N\_SLOTS}=8 was not re-measured full-system (real PSRAM
|
|
chain) after either memory optimization --- only
|
|
\code{dataflow\_core.v} alone, pre-optimization (92.63~MHz).
|
|
\end{itemize}
|
|
|
|
\section{SDRAM-era benchmark addendum (2026-09-07) --- current,
|
|
authoritative results}
|
|
\label{sec:impl-sdram-addendum}
|
|
\begin{fnwarn}[Supersedes the PSRAM/\code{N\_SLOTS}$\le$2-era campaign
|
|
above for the current hardware baseline]
|
|
Every section above (V1 vs.\ V2 comparison, \code{N\_SLOTS} sweep,
|
|
parallel scaling, memory optimizations \#1/\#2, bottleneck analysis)
|
|
describes an earlier V2 milestone built on V1's own PSRAM chain,
|
|
recommending \code{N\_SLOTS}=2. The project has since replaced external
|
|
memory with a single SDR SDRAM device (ch.~\ref{ch:mem}
|
|
\S\ref{sec:sdram-mem-addendum}) and closed on
|
|
\textbf{\code{N\_SLOTS}=4 as the production configuration}. This
|
|
section is the current, real, measured state; the PSRAM-era numbers
|
|
above remain real and correctly measured for the architecture they
|
|
describe, but do not apply to the current board.
|
|
\end{fnwarn}
|
|
|
|
\subsection{Real resource utilization (\code{N\_SLOTS}=4, SDRAM
|
|
architecture, post real critical-path fixes)}
|
|
\begin{tabularx}{\textwidth}{L{4.2cm} C{2.4cm} Y}
|
|
\toprule
|
|
\rowh \thd{Resource} & \thd{Count} & \thd{Notes} \\
|
|
\midrule
|
|
TRELLIS\_COMB (LUT4-equiv) & 7,175 / 43,848 (16.4\%) & Real Yosys synthesis, most recent measurement (post-ERR-0029) \\
|
|
\rowa MULT18X18D & 32 / 72 (44.4\%) & Exactly $4\times8$ (\code{N\_SLOTS}$\times$\code{P\_IN}), confirmed --- the ERR-0027 fix removed a spurious 33rd multiplier \\
|
|
DP16KD (block RAM) & 0 / 108 & All small SRAMs synthesize to distributed RAM \\
|
|
\rowa EHXPLLL & 1 & Real \code{EHXPLLL} primitive, \code{ecppll}-derived parameters \\
|
|
TRELLIS\_FF & $\ge$6,322 (last individually re-quoted figure) & Real, same SDRAM architecture, pre-dates the ERR-0027/0028/0029 restructuring; not independently re-synthesized standalone since --- disclosed as a lower-bound reference, not re-invented as exact \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
|
|
\subsection{Real, current clock closure and functional regression}
|
|
See ch.~\ref{ch:hw} \S\ref{sec:clock-closure-current} for the complete
|
|
per-seed Fmax/WNS table (single source of truth, not duplicated here):
|
|
\textbf{\code{N\_SLOTS}=4 @ 64\,MHz, 8/8 seeds PASS} (worst 64.55\,MHz,
|
|
best 72.37\,MHz); \code{N\_SLOTS}=8 deferred (3/8); 80\,MHz confirmed
|
|
NO-GO at either processor count with a genuinely regenerated PLL.
|
|
|
|
D-Stress functional regression (256 neurons, 256/256 bit-exact vs.\
|
|
golden model): \textbf{49,927 cycles} at \code{N\_SLOTS}=4 ---
|
|
\textbf{780\,\textmu s} real wall-clock at the P\&R-verified 64\,MHz
|
|
system clock ($49{,}927 / 64{,}000{,}000$, \textsc{Derived}). SDRAM
|
|
directed boundary verification (ch.~\ref{ch:hw}
|
|
\S\ref{sec:sdram-addendum}): 21/21 PASS, zero bugs found, both 64\,MHz
|
|
and 166\,MHz.
|
|
|
|
\subsection{Real SPI host protocol throughput}
|
|
Board-level smoke test (\code{tb\_fpga\_neural\_v2\_top\_smoke.v}, 11/11
|
|
PASS): single job 99--100 cycles/job; back-to-back 88--100 cycles/job;
|
|
steady-state throughput unaffected by inter-job gap (100\,ns/5\,\textmu
|
|
s/50\,\textmu s tested). Maximum verified SPI host clock: \textbf{12\,MHz
|
|
recommended} (exact deterministic CDC edge at 12.8\,MHz $=$ 64\,MHz/5)
|
|
--- see ch.~\ref{ch:hw} \S\ref{sec:spi-max-verified} for the full sweep.
|
|
|
|
\subsection{Limitations, honestly stated (current SDRAM architecture)}
|
|
\begin{itemize}
|
|
\item Power/energy: \textbf{NOT MEASURED} --- no ECP5 power estimator
|
|
is available in this toolchain (unchanged from the PSRAM-era
|
|
disclosure above).
|
|
\item Hold-time closure: \textbf{OPEN --- tool-chain limitation}, not a
|
|
real defect; see ch.~\ref{ch:hw} \S\ref{sec:hw-open-items} for
|
|
the complete, consolidated open-items list.
|
|
\item \code{N\_SLOTS}=8 is functionally correct but not
|
|
timing-closed on every tested seed --- deferred by explicit
|
|
project direction, not attempted further this pass.
|
|
\item No embedded-host (ESP32-class) physical baseline exists; all
|
|
host-side numbers above are protocol-level simulation, not
|
|
measured on real silicon.
|
|
\end{itemize}
|