Vitis HLS Testbench

The generated schema classes also make the C++ testbench much simpler. Instead of manually decoding binary files and packing AXI4-Stream words by hand, the testbench can operate directly on typed protocol objects.

In this example, the testbench performs five basic tasks:

  • read the coefficients, DATA command header, sample payload, and END command header from binary files generated by Python
  • write the DATA command header + samples + END command header into the AXI4-Stream input ahead of the kernel call (C-sim runs the kernel as a synchronous function, so all inputs must be queued first)
  • invoke the poly kernel with the coefficients passed as an s_axilite argument and the status fields (halted, error_code, tx_id_status) passed as s_axilite references
  • deserialize the output stream back into a typed response header and sample buffer, then write them to binary files
  • write regmap_status.json with the final values of halted, error_code, and tx_id_status so ValidateCSimStep can cross-check them against the Python regmap status

The kernel returns after it consumes the END header (or halts on a TLAST error). In synthesized RTL the return asserts ap_done; in C-simulation it is just “the call completed.”

Testbench responsibilities

The HLS testbench is implemented in examples/poly/poly_tb.cpp.

  1. Load coeffs.bin into a float[4] array (used as the s_axilite coefficient argument).
  2. Load data_cmd_hdr.bin into a PolyCmdHdr and samp_in_data.bin into a float[] sample buffer.
  3. Load end_cmd_hdr.bin into a second PolyCmdHdr.
  4. Push the DATA header, packed samples (with TLAST on the final word), and END header into the input stream.
  5. Declare AXI-Lite output scalars (ap_uint<1> halted, ap_uint<8> error_code, ap_uint<16> tx_id_status) and call poly(in_stream, out_stream, coeffs, halted, error_code, tx_id_status).
  6. Drain resp_hdr and samp_out from the output stream into binary files (resp_hdr_data.bin, samp_out_data.bin).
  7. Write regmap_status.json containing the three AXI-Lite output values.

Because the kernel halts (rather than emitting a per-transaction footer) on framing errors, neither a streamed footer nor any extra TLAST-sync file is produced — ValidateCSimStep instead compares regmap_status.json between the Python and Vitis runs and asserts halted == 0 and error == NO_ERROR for both.

Why this matters

In a conventional HLS testbench, a significant amount of code is often spent on:

  • manually reading packed binary data
  • converting that data into stream words
  • reconstructing typed responses from the output stream
  • keeping the testbench protocol consistent with both the software model and the kernel interface

In this example, those concerns are handled by schema-generated helpers.
As a result, the testbench mostly expresses the transaction flow itself:

  • load inputs
  • stream them into the kernel
  • collect outputs
  • write results for comparison

This reduces boilerplate and makes it easier to keep the Python model, generated headers, kernel, and testbench synchronized.


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