HLS functions can be directly used in data-flow graphs. The only
extra work is to write a separate header file to declare function signatures and to
specify hls::stream
directions for HLS functions
to be used in data-flow graphs. In this special header file, the function signature
is declared the same as in the HLS function definition, except that the input or
output direction of a hls::stream
data type is
specially qualified using adf::dir::in<T>
and adf::dir::out<T>
, respectively.
For example, given an HLS function
hls_mul
defined in hls_mul.cpp:#include "hls_stream.h"
#include "ap_int.h"
extern "C" void hls_mul(hls::stream<ap_axis<32,0,0,0>>& in, hls::stream<ap_axis<32,0,0,0>>& out, ap_int<32> inputParam, unsigned int loop_count)
{
for (unsigned int n=0; n<loop_count; n++)
{
for (int i=0; i<8; i++)
{
ap_axis<32,0,0,0> value = in.read();
value.data *= inputParam;
out.write(value);
}
}
}
A
separate header file, for example hls_kernels.h should be written as
follows:#ifndef __HLS_KERNELS_H__
#define __HLS_KERNELS_H__
#include "hls_stream.h"
#include "ap_int.h"
#include "adf.h"
void hls_mul(adf::dir::in<hls::stream<ap_axis<32,0,0,0>>&> in, adf::dir::out<hls::stream<ap_axis<32,0,0,0>>&> out, ap_int<32> inputParam, unsigned int loop_count);
#endif
In
this special header file, the data types for parameters in
and out
are specifically changed
to adf::dir::in<hls::stream<ap_axis<32,0,0,0>>&>
and adf::dir::out<hls::stream<ap_axis<32,0,0,0>>&>
respectively to indicate the direction of the hls::stream
. This is because hls::stream
data type does not provide directional information needed
by AI Engine compiler. This header file should be
included in the graph specification for adf::kernel::create
and should not be included in any HLS source file.
To connect a port representing hls::stream
to
another port using adf::connect<S,D>(src,dst)
, the template parameter (S
or D
) for the
hls::stream
port should be specified as
adf::stream
. In other words, the type of a
hls::stream
port is still considered as a
stream and is treated similarly to other
stream ports such as input_stream_int32
or output_stream_int32
. The following code shows how to
create and connect a HLS kernel in a graph specification.#include "hls_kernels.h" //declare hls_mul as shown above
#include "aie_kernels.h" //declare producer and consumer aie kernel functions
#include "adf.h"
using namespace adf;
class mygraph : public graph
{
public:
kernel prd, mul, cns;
mygraph()
{
prd = kernel::create(producer);
cns = kernel::create(consumer);
mul = kernel::create(hls_mul); //create a hls kernel from the declaration in hls_kernels.h
fabric<pl>(mul); //hls kernel runs on programmable logic
source(mul) = "hls_mul.cpp" //specify source file containing hls function definition
adf::connect<window<32>, stream>(prd.out[0], mul.in[0]);
adf::connect<stream, window<32>>(mul.out[0], cns.in[0]);
}
};
Important: Simulation
of the PL components in C++ is not timing accurate because it is only intended for
functional modeling.
Recommended: To verify
correctness and optimize for performance, use Vitis HLS for single HLS C++ kernels. After single-kernel development
and graph System C have successfully completed, the system including the AI Engine kernels, PL kernels, and PS code can be
integrated using the Vitis tools flow.