Was a separate, untracked directory (DataSheet/) outside the repo. Renamed to lowercase and moved in as hardware/v2/docs/datasheet/, with its own .gitignore for LaTeX build byproducts (compiled PDFs stay tracked, .aux/.log/.toc/etc do not). Now versioned and shares this repo's own remote instead of living untracked on disk. Content: IT+EN LaTeX chapter sources, reference manufacturer PDFs, and compiled datasheet PDFs including the 2026-09-07 SDRAM upgrade addendum (AS4C32M16SB-7BIN part/pinout/timing) in the v2-en chapters. Note: hardware/v2/docs/DatasheetLatex/ (and the v1 sibling) is a separate, already-tracked, differently-structured LaTeX document that predates this move -- left untouched, not merged, since its chapter set and content differ and merging was not requested. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
96 lines
4.4 KiB
TeX
96 lines
4.4 KiB
TeX
\chapter{Compute datapath}
|
|
\label{ch:datapath}
|
|
|
|
\section{Bit-exact reuse of V1's arithmetic}
|
|
\code{neural\_processor.v} implements the identical INT8/INT32 arithmetic
|
|
chain as V1's own \code{neuron\_parallel.v}/\code{mac8.v}/\code{mac\_unit.v}
|
|
--- verified bit-exact against V1's own modules, instantiated side-by-side
|
|
in the same testbench, across 7 test cases including extreme INT8 values,
|
|
back-to-back zero-gap tiles, and multi-tile jobs. What changed is the
|
|
\emph{pipelining}, not the math.
|
|
|
|
\begin{center}
|
|
\begin{tikzpicture}[font=\scriptsize,node distance=3mm,start chain=going right,
|
|
every node/.style={fnblock,minimum width=15mm,minimum height=8mm,on chain}]
|
|
\node[fnblockT]{INT8\\$\times$\,INT8};
|
|
\node{INT16\\product};
|
|
\node{sign-ext\\INT32};
|
|
\node[fnblockD]{accumulate\\INT32};
|
|
\node{$+$ bias};
|
|
\node[fnblockA]{activation};
|
|
\node[fnblockT]{sat. INT8};
|
|
\foreach \i [count=\j from 2] in {1,...,6}
|
|
\draw[fnarrow] (chain-\i) -- (chain-\j);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
|
|
\section{8-stage pipeline}
|
|
\code{neural\_processor.v} is fully pipelined, throughput-oriented (one
|
|
new tile accepted per cycle in steady state, given a continuous operand
|
|
stream):
|
|
\begin{center}
|
|
\begin{tikzpicture}[font=\scriptsize,node distance=2.5mm,start chain=going below,
|
|
every node/.style={on chain,fnblock,minimum width=64mm}]
|
|
\node[fnblockA]{Stage 0 --- input alignment / register (\code{x0}, \code{w0})};
|
|
\node{Stage 1 --- per-lane multiply (\code{P\_IN}$\times$\code{MULT18X18D})};
|
|
\node{Stages 2..$(1{+}\log_2\text{P\_IN})$ --- balanced adder tree};
|
|
\node[fnblockD]{accumulate (gated by job state, cleared at job start)};
|
|
\node{$+$bias, activation select};
|
|
\node[fnblockT]{INT8 saturation / output register};
|
|
\foreach \i [count=\j from 2] in {1,...,5}
|
|
\draw[fnarrow] (chain-\i) -- (chain-\j);
|
|
\end{tikzpicture}
|
|
\end{center}
|
|
With \code{P\_IN}=8 the adder tree has 3 levels, giving an 8-stage pipeline
|
|
overall. \code{tile\_last} is gated identically to \code{valid} at every
|
|
stage (\code{last0 <= (operand\_valid \&\& operand\_ready) ? tile\_last :
|
|
1'b0;}) --- an early draft left it ungated, letting a ``last'' tag
|
|
propagate one cycle ahead of its own valid/data pair on jobs where
|
|
\code{tile\_last} was asserted before \code{operand\_ready} rose (legal
|
|
valid-before-ready producer behavior); found and fixed via a
|
|
cycle-by-cycle dump of the pipeline's own internal valid/last signals,
|
|
re-verified against the full 7-test regression.
|
|
|
|
\section{Accumulator width: 24 vs.\ 32 bits}
|
|
A real, 6-seed placement sweep (reusing already-synthesized netlists,
|
|
real \code{nextpnr-ecp5} place\&route only) resolved an earlier
|
|
single-seed measurement that had suggested \code{ACC\_WIDTH}=32 was
|
|
marginally faster:
|
|
|
|
\begin{tabularx}{\textwidth}{L{2.6cm} C{2.0cm} C{2.0cm} C{2.0cm} C{1.6cm}}
|
|
\toprule
|
|
\rowh \thd{ACC\_WIDTH} & \thd{mean Fmax} & \thd{min} & \thd{max} & \thd{stdev} \\
|
|
\midrule
|
|
32 & 170.12~MHz & 145.73 & 183.96 & 14.16 \\
|
|
\rowa 24 & \textbf{180.71~MHz} & 175.16 & 185.49 & \textbf{4.21} \\
|
|
\bottomrule
|
|
\end{tabularx}
|
|
\begin{center}\footnotesize\itshape\color{fnGrey}
|
|
Real place\&route, P\_IN=8, 6 seeds each (default plus 5 explicit).\end{center}
|
|
|
|
\begin{fnnote}[Why a single seed misled]
|
|
Over 6 real placement seeds, \code{ACC\_WIDTH}=24 has both a higher mean
|
|
Fmax ($+$6.2\%) and a much tighter seed-to-seed spread ($\approx$3.4$\times$
|
|
tighter) than \code{ACC\_WIDTH}=32 --- combined with fewer LUT/FF/CCU2C at
|
|
24 bits and identical bit-exact correctness, \code{ACC\_WIDTH}=24 is
|
|
recommended for any new P\_IN=8 INT8 configuration, where product
|
|
magnitudes never need more than 24 bits of accumulator headroom.
|
|
\end{fnnote}
|
|
|
|
\section{Activation and saturation}
|
|
Identical encoding and bit-test logic to V1 (bilateral saturation for
|
|
\code{ACT\_NONE}, positive-only for \code{ACT\_RELU}, both INT8-range).
|
|
Every job dispatched by \code{dataflow\_core.v} currently hardcodes
|
|
\code{job\_bias=0}, \code{job\_activation=ACT\_RELU} --- a documented
|
|
simplification carried through every milestone since M4/M5, not yet
|
|
exposed per-node by the Dependency Manager's own job descriptor.
|
|
|
|
\begin{tabularx}{\textwidth}{L{2.6cm} C{1.4cm} Y}
|
|
\toprule
|
|
\rowh \thd{Encoding} & \thd{Value} & \thd{Behavior} \\
|
|
\midrule
|
|
\code{ACT\_NONE} & \code{2'd0} & Linear: bilateral saturation to $[-128,+127]$. \\
|
|
\rowa \code{ACT\_RELU} & \code{2'd1} & $\max(0,x)$, positive saturation to $+127$ (used by every V2 job today). \\
|
|
\bottomrule
|
|
\end{tabularx}
|