What we’re building
VMAC is a complex vector-MAC accelerator: a small ALU over complex fixed-point matrices, driven by commands the host leaves in shared memory. This page sets up what it computes and how the host talks to it; the later pages build each layer.
The motivating computation
The worked scenario is a host-driven complex correlation. The host has two
complex matrices A and B in memory and wants a normalized correlation
rho = abcorr / anorm, where
anormis the auto-correlation energyA · conj(A), reduced to one row, andabcorris the cross-correlationA · conj(B), reduced to one row.
The split between hardware and host is deliberate:
- The host writes
AandBinto their memory regions. - It enqueues two commands — both
inner_prodwithreduceset: one withBaimed atA(givinganorm), one withBaimed atB(givingabcorr) — then anendsentinel. - VMAC dequeues each command, reads the operands over
m_axi, computes the reduced inner product, and writes the resultYback to memory. - The host reads both
Yregions back and computes the divisionrho = abcorr / anormitself.
The division stays on the host on purpose: it is the one step that is awkward to
synthesize (a complex/real reciprocal), so it is an explicit hardware/host split
— the accelerator does the bandwidth-heavy multiply-accumulate, the host does the
single scalar divide. This is modeled in
examples/vmac/vmac_host.py.
The operation set
VMAC is not single-purpose; the correlation above uses one of its three element-wise operations plus an optional reduce. Presented as a general complex vector ALU:
op |
computes (per element i,j) |
second operand | scalar |
|---|---|---|---|
scalar_mult |
α[i] · A[i,j] |
— | α (immediate or per-row) |
inner_prod |
A[i,j] · conj(B[i,j]) |
B |
— |
sum |
A[i,j] + B[i,j] |
B |
— |
The reduce flag, when set, sums each result down its rows to a single output row
(Y[j] = Σ_i R[i,j]). A fourth opcode, end, carries no computation — it is the
sentinel that breaks the accelerator’s run loop. The correlation example uses
inner_prod + reduce; the conformance suite exercises all three ops with and
without reduce. The opcodes and the command that carries them are the subject of the
data types page.
The system
One host, one accelerator, one shared memory, over a single m_axi master:
host ──AXI-MM command queue──▶ VMAC ──m_axi (gmem)──▶ shared memory
(vmac_host.py) (vmac.py) A | B | Y regions
What makes VMAC distinctive among the examples is that the host does not
push commands down a dedicated control stream. It appends them to a ring buffer in
the same shared memory the operands live in, and a free-running accelerator
dequeues them. That ring is the
AXI-MM command queue interface; here it carries
VmacCmds. Control and data share one interconnect.
Roadmap
The remaining pages build VMAC bottom-up:
- Data types and arithmetic — the command, its element/format types, and the fixed-point datapath.
- The Python model and Python simulation — the one author-written golden, the synthesizable shell, and the SimPy queue sim.
- Code generation and the kernel hook — the generated synthesizable top and the hand-written complex datapath.
- C and RTL simulation and timing — Vitis conformance and the loosely-timed-model calibration that is this example’s headline.