Hardware Components
A HwComponent is Waveflow’s representation of a
synthesizable hardware module. You write it once in Python, and that one class is the source for
both the SimPy simulation and the generated C++ kernel.
A component is defined by three things, and this chapter is organized around them:
- Its interface endpoints — the typed ports it talks to the outside world through (a stream input, a memory-mapped master, an AXI-Lite register map). You declare them on the class.
- How it is wired — a component does not call other components directly; its endpoints are bound to interfaces, which carry transactions to the endpoints of other components.
- What it does — its behavior is expressed as the methods on those endpoints (
getan incoming transaction,writean outgoing one), driven from its lifecycle methods.
This section is Python-only by design — the model you simulate. The same component’s synthesizable C++ realization (the generated kernel function, its ports, parameterization) is the Component Code Generation chapter; each page below cross-links its codegen dual.
In this section
- Defining a component — the
HwComponentclass and how you declare its endpoints (__post_init__+add_endpoint), walked throughsimp_fun. - Endpoint methods — the master/slave roles and the method you define or call per endpoint type (stream, m_axi, regmap, schema/array transfer).
- Parameterization —
HwParam(per-instance synthesis knobs) vs.HwConst(class-level structural constants), andparam_supportsvariant kernels. - HwTestbench — a component subclass whose
main()is a Python test sequence.
See also
Prerequisites — a component is built from these:
- Interfaces — the typed ports (stream / MM / regmap endpoints) a component declares, and their transaction-method signatures.
- Data Schemas — the payloads those ports carry.
The synthesizable side (the C++ realization of a component):
- Component Code Generation — what a full component generates: the kernel structure, how
HwParambecomes C++ template parameters, andmain()→testbench emission. - Custom Hooks — the hand-written synthesizable kernel bodies that plug into a generated component.
Table of contents
- Defining a component - How you define a HwComponent: subclass HwComponent, declare its typed interface endpoints in __post_init__ and register each with add_endpoint, and mark compute methods @synthesizable — walked through the regmap simp_fun example. The same class is the source for the generated C++ kernel.
- Endpoint methods - The master/slave roles and the endpoint methods a component's behavior is built from: a master initiates transactions (write/push on a stream, read/write/read_array/write_array on an m_axi); a slave responds — a launch handler (on_start), a get/pop pulled in the body (stream/transfer slave), or a passive memory target. A table maps each endpoint type to the method you define or call and the interface page with its signature.
- Parameterization - Parameterizing a HwComponent: HwParam[T] for per-instance, configurable synthesis knobs (bus widths, datapath sizing — vary per instance and per generated kernel variant) and HwConst[T] for class-level, fixed structural constants (static array extents). The crux is per-instance-configurable vs class-level-fixed. param_supports declares a set of HwParam values to emit as kernel variants; its C++ realization is comp_codegen/templating.
- HwTestbench - HwTestbench — a HwComponent subclass whose sequential main() (stream push/pop, dut.run()) defines a test sequence in Python; the codegen source for a C++ testbench main().