Never-ending kernels have the following coding requirements for top-level function arguments:
- The kernel implements the
ap_ctrl_chain
block control protocol to enable theauto_restart
bit. - The kernel supports AXI4-Stream
interfaces (
axis
) and has no AXI4 memory mapped (m_axi
) interface, and interacts with other kernels only through streams.
Modeling designs that use the streaming paradigm can be difficult in C.
The approach of using pointers to perform multiple read and/or write accesses can
introduce issues because there are implications for the type qualifier. Vitis HLS provides a C++ template class hls::stream<ap_axis<N>>
for modeling streaming
data structures. On the hardware, the hls::stream
is
implemented as an axis
interface.
template <typename T, size_t WUser, size_t WId, size_t WDest> struct axis { .. };
Where:
-
T
is the stream data type -
WUser
is the width of the TUSER signal -
WId
is the width of the TID signal -
WDest
is the width of the TDest signal
When the stream data type (T
) are
simple integer types, there are two predefined types of AXI4-Stream implementations available:
- A signed implementation of the AXI4-Stream class:
hls::axis<ap_int<WData>, WUser, WId, WDest>
- An unsigned implementation:
hls::axis<ap_uint<WData>, WUser, WId, WDest>
TVALID
, TREADY
, and TLAST
are required control
signals for the AXI4-Stream protocol. Side-channel
signals TKEEP
, TSTRB
, TUSER
, TID
, and TDEST
are special signals that
can be used to pass around additional bookkeeping data. The values specified for the
template parameters WUser
, WId
, and WDest
define the use of
side-channel signals in the interface as explained in AXI4-Stream Interfaces in the
Vitis
High-Level Synthesis User Guide (UG1399).
The following example shows a programming model for a data-driven, never-ending kernel using AXI4-Stream:
#include "ap_axi_sdata.h"
#include "hls_stream.h"
typedef ap_axis<32, 0, 0, 0> pkt;
extern "C" {
10 void krnl_stream_vdatamover(hls::stream<pkt> &in,
11 hls::stream<pkt> &out // Internal Stream
12 ) {
13 #pragma HLS interface ap_ctrl_chain port=return
14 bool eos = false;
15 vdatamover:
16 do {
17 // Reading a and b streaming into packets
18 pkt t1 = in.read();
19
20 // Packet for output
21 pkt t_out;
22
23 // Reading data from input packet
24 ap_uint<DWIDTH> in1 = t1.data;
25
26 // Vadd operation
27 ap_uint<DWIDTH> tmpOut = in1;
28
29 // Setting data and configuration to output packet
30 t_out.data = tmpOut;
31 t_out.last = t1.last;
32 t_out.keep = -1; // Enabling all bytes
33
34 // Writing packet to output stream
35 out.write(t_out);
36
37 if (t1.last) {
38 eos = true;
39 }
40 } while (eos == false);
while(1)
loop
around the kernel. Therefore, you should not explicitly specify a while(1)
loop in your source code to prevent
non-deterministic behavior.