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 (get an incoming transaction, write an 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 HwComponent class and how you declare its endpoints (__post_init__ + add_endpoint), walked through simp_fun.
  • Endpoint methods — the master/slave roles and the method you define or call per endpoint type (stream, m_axi, regmap, schema/array transfer).
  • ParameterizationHwParam (per-instance synthesis knobs) vs. HwConst (class-level structural constants), and param_supports variant 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 HwParam becomes C++ template parameters, and main()→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().

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