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_supports below.
  • 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 instantiationcomp = 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 HwParam field 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 each HwParam value as an HwParamValue — an int subclass that remembers the .param_name it 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 a HwParam field 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

Quick reference

  • HwParam[T] = per-instance synthesis knob; int-like in sim, wrapped HwParamValue, 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_supports declares variant kernels (key → HwParam overrides); realization is Templating.

This site uses Just the Docs, a documentation theme for Jekyll.