Component Code Generation
WaveFlow generates Vitis-ready C++ for every HwComponent. You write the
component once in Python — its ports, its parameters, its behavior — and the generator emits a
top-level HLS kernel with the right AXI interfaces, the C++ type lowering, and the build-ready file
set, all from that single source.
This chapter covers what the generator produces automatically: the structure of a generated
component, how each endpoint becomes an HLS port, the execution model it lowers to, what the
HwStmt extractor accepts, and how HwParam parameterizes the output.
A component’s compute body is not always auto-generated. When a datapath needs hand-tuned HLS C++,
you write the kernel body yourself and attach it with @synthesizable(impl_file=…). That
hand-written path — how to author a kernel body, the in-kernel port and loop patterns — is the next
chapter, Custom Hooks. This chapter is the auto-generated structure those hooks
plug into.
In this section
- Component structure — how an
HwComponentbecomes a Vitis HLS top-level function: the kernel entry, the execution model (free-running vs. regmap-launched), and where hooks come from. - Endpoint interfaces — how each declared endpoint (stream / m_axi / regmap) is realized as a Vitis port (
hls::stream/m_axi/s_axilite) and how a slave endpoint’s handler binds. - Extractor — how
HwStmtExtractorparses the synthesizable Python subset into theHwStmtIR, failing fast on unsupported patterns. - Codegen — how
kernel_files_to_stremits the deterministic kernel file set and resolves naming. - Templating — the C++ realization of parameterization: how
HwParamlowers (concrete widths /.tpptemplate params),HwConst(deferred), and howparam_supportsemits variant kernels. - Testbench —
HwTestbenchandis_testbench=Truecodegen mode.
See also
- Hardware Components — the Python
HwComponentthis section generates C++ for. - Custom Hooks — the hand-written synthesizable kernel bodies that plug into a generated component.
- Cosim timing — extracting and validating cycle timing from the generated kernel’s cosim (now under Timing Analysis, where the timeline analysis lives).
- Build System — the
BuildDagthat drives these codegen steps end to end.
Table of contents
- Component structure - The Vitis HLS realization of an HwComponent: each component becomes one top-level kernel function whose arguments are its endpoints; the execution model is a free-running loop (run_proc) or a one-time regmap-launched call (on_start), selected by whether the component carries a VitisRegMapMMIFSlave; the kernel body comes from the @synthesizable methods (auto-extracted or, with impl_file=, hand-written).
-
Endpoint interfaces - How each declared endpoint on an HwComponent is realized as a Vitis HLS port: stream endpoints become hls::stream
>& with #pragma HLS INTERFACE axis; m_axi masters become ap_uint * with m_axi offset=slave bundle=gmem; a VitisRegMapMMIFSlave becomes s_axilite register-field ports plus the ap_start/ap_done control protocol. Also how a slave endpoint's handler binds to the kernel body. - Extractor - How HwStmtExtractor parses the synthesizable subset of a component's Python (on_start / run_proc, or main for a testbench) into the HwStmt IR, failing fast with SynthesisError on unsupported patterns.
-
Codegen - How resolved HwStmt IR is emitted to deterministic kernel files —
.hpp / .cpp plus sticky hook impl files — with C++ type lowering, top-level signatures, namespace-qualified hook calls, and variant naming. -
Templating - The C++ realization of component parameterization: HwParam values lower to concrete literal widths in the top kernel signature and to template parameters in .tpp hooks (HwParamValue carries the param name so the emitter chooses name vs literal); HwConst lowers to static constexpr (currently deferred); and param_supports emits one concrete
_ top per variant from a single class. -
Testbench - The codegen-source testbench path: HwTestbench.main() lowered to a sequential C++ int main() (DUT build, file I/O, stream push/pop, dut.run()), emitted as
_tb.cpp when is_testbench=True.