Using High-Level Synthesis IP in Data Flow Graphs - 2020.2 English

Versal ACAP AI Engine Programming Environment User Guide (UG1076)

Document ID
UG1076
Release Date
2020-11-24
Version
2020.2 English

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.