Parameterization
Why parameterize
A HwComponent is a template for hardware, not a single fixed block. Parameterizing
it lets one class describe a family of hardware: the same datapath sized for a 32-bit bus or a
64-bit bus, an accelerator built for 8-bit or 16-bit operands, a coefficient bank with 4 or 8 taps.
That buys three things:
- One source, many concrete kernels. A single class emits several Vitis tops at build time, one
per configuration — see
param_supportsbelow. - Sizing the datapath. Bus widths and lane counts ripple through the generated port signatures and the lane geometry, so the parameter is the hardware size.
- Reusable IP. A component parameterized on its widths/shapes is reusable across designs without editing its body.
Waveflow has two parameter markers, and choosing between them is the crux: HwParam is
per-instance and configurable; HwConst is class-level and fixed.
HwParam[T] — per-instance synthesis parameters
HwParam[T] marks a dataclass field as a synthesis parameter
bound at instantiation — comp = MyComp(in_bw=64) — and potentially varied per generated kernel
variant. From examples/stream_inband/poly.py:
in_bw: HwParam[int] = 32
out_bw: HwParam[int] = 32
aximm_bw: HwParam[int] = 32
(VMAC parameterizes its operand / accumulator / output widths the same way.) Three properties matter:
- Int-like in simulation. A
HwParamfield behaves as a normal Python integer — arithmetic, comparison, indexing all work — so the SimPy model runs with the concrete value. - Identity-preserving for codegen.
HwComponent.__post_init__wraps eachHwParamvalue as anHwParamValue— anintsubclass that remembers the.param_nameit came from. That lets the emitter decide between a C++ template parameter name and a literal value (the realization page). - Immutable after construction.
HwComponent.__setattr__raises if you reassign aHwParamfield once__post_init__has finished — the value is frozen for the instance’s hardware identity.
HwConst[T] — class-level structural constants
HwConst[T] marks a class attribute that is fixed for the
class — the same for every instance — typically a structural extent like a static array size. From its
docstring:
class CoeffArray(DataArray):
ncoeff: HwConst[int] = 4
max_shape = (ncoeff,)
In Python simulation a HwConst is just a regular class attribute (the framework does not enforce
immutability — the marker signals intent). discover_hw_const(cls)
walks the MRO and returns every HwConst field so codegen can find them.
HwParam vs. HwConst — the distinction
HwParam[T] |
HwConst[T] |
|
|---|---|---|
| Scope | per-instance field | class-level attribute |
| Set when | at instantiation (MyComp(in_bw=64)) |
at class definition |
| Varies | per instance, and per kernel variant | never — fixed for the class |
| In simulation | int-like value (wrapped HwParamValue) |
plain class attribute |
| Use for | configurable knobs: bus widths, datapath sizing | fixed structure: static array extents |
Rule of thumb: if a value should be dialable per instance / per generated variant, it is a
HwParam; if it is a fixed structural fact of the class, it is a HwConst.
param_supports — declaring kernel variants
To emit more than one concrete kernel from a class, declare
param_supports: a map of variant key → HwParam overrides.
class MyKernel(HwComponent):
cpp_kernel_name = "my_kernel"
in_bw: HwParam[int] = 32
param_supports = {
"bw64": {"in_bw": 64},
"bw128": {"in_bw": 128},
}
This declares that the build should emit my_kernel (defaults), my_kernel_bw64, and
my_kernel_bw128. validate_param_supports checks the keys
(valid C identifiers) and that every override names a real HwParam field. How those variants are
generated — concrete top functions per key — is the realization page:
Component Code Generation: Templating.
See also
- Component Code Generation: Templating — the C++ realization: how
HwParamlowers into kernel signatures,HwConstintostatic constexpr, andparam_supportsinto variant kernels. - Defining a component — where these fields are declared on the class.
- Component structure — the generated kernel these parameters shape.
Quick reference
HwParam[T]= per-instance synthesis knob; int-like in sim, wrappedHwParamValue, immutable after construction.HwConst[T]= class-level fixed structural constant; a plain class attribute in sim.- Per-instance-configurable →
HwParam; class-level-fixed →HwConst. param_supportsdeclares variant kernels (key →HwParamoverrides); realization is Templating.