Vectorization
Vectorization is how Waveflow’s functional simulation is fast and bit-exact.
Data lives in NumPy arrays from end to end — operands, intermediates, and results
are all ndarrays — so a whole vector of values flows through one C-level NumPy
call instead of a Python loop over elements. The numbers Waveflow computes match
the Vitis HLS datapath bit-for-bit, and they are computed at NumPy speed.
Outline
We describe how to implement arrays in two sections:
Python — defining NumPy-backed vectors in the Python model and computing on them:
- Numerical operations — the shared model for every element type:
defining vectors, the
.valNumPy escape hatch, and the type-preserving operators (a*b + c, thenquantize). - Integer vectorization — NumPy integer arrays, growth-aware operators, the width-tracking caveat.
- Float vectorization — NumPy passthrough and golden references.
- Fixed-point vectorization — full-precision
a*b + c, one explicitquantize, bit-exact withap_fixed. (The fixed-point type itself is on the FixedField page.) - Complex vectorization — complex arithmetic and the numpy-vs-hardware multiply edge.
HLS — Vectors can also be used in the generated Vitis HLS code using the synthesizable Vitis kernel (the schema-level packing model is in Serialization). These are described in three parts:
- Raw arrays — the flat array, packing factor, lanes, and the throughput lane loop.
- Struct arrays — the generated wrapper struct’s whole-array methods.
- Complex arrays — complex elements end-to-end (the wireless vertical).
Why vectorization is the differentiator
The Waveflow thesis is bit-exact and fast. The speed comes from keeping data
vectorized: a DataArray is numpy-backed, and .val is the underlying
ndarray. FixedField is deliberately integer-backed on a single 64-bit dtype
(not an arbitrary-precision object array) specifically so fixed-point arrays stay
vectorized — every fixed-point op is a NumPy integer op over the whole array.
This is a deliberate abstraction/speed tradeoff, not a claim that other tools are wrong:
- Per-element fixed-point packages (arbitrary-precision Python fixed-point libraries) model each value exactly at any width, but fall back to per-element Python for big widths — correct, but not vectorized, so slower over large arrays.
- RTL / cycle-level Python simulators (e.g. PyMTL) model the design cycle-by-cycle. That is a different abstraction level: they pay per-cycle costs that don’t vectorize over data, in exchange for cycle-accurate timing.
Waveflow sits at the transaction level with vectorized data: it gives fast functional (bit-exact) simulation, and handles timing separately. Pick the level that fits the question you’re asking — for “are my bits right, fast, over a lot of data,” vectorized functional sim is the sweet spot.
See also
- Numerical operations — the two compute paths (
.valvs the type-preserving operators) in depth. - FixedField — the fixed-point type (the
ap_fixedmodel,QMode/OMode, defaults-match-Vitis). examples/basic_vec— the worked front-door: one MAC,y = a*b + c, computed with these operators and checked bit-exact against Vitis for int / float / fixed.- Timing Analysis — where cycle/throughput modeling lives (the separate, non-functional concern).
Table of contents
- Python - The NumPy-backed vectorized value model — integer, float, fixed-point, and complex arrays — for loop-free Python computation that stays bit-exact with the generated hardware.
- HLS - Vectorized arrays in synthesizable Vitis C++ — the packing factor and lanes, the canonical lane loop, read_array_slice, and the raw / struct / complex storage modes.