Migrating the Hardware Function
When migrating a hardware function from the SDSoC™ environment for use in the Vitis environment, there are few items to remember.
For execution in the PL, the hardware function is now compiled separately
as an .xo file, so it is not included in the main() function and does not require a
specific header file for function definition as it does in the SDSoC environment. Before discarding the header file, you must copy the
BUFFER_SIZE declaration into the mmult function. You can also comment or remove the
#include statement.
#include "mmult.h"
As the host code and the kernel code are developed and compiled
independently, there could be a name mangling issue if one is written in C and another
in C++. To avoid this issue, you must wrap the kernel function declaration with the
extern "C" linkage.
extern "C" {...}
In addition, while the sds++ compiler
infers certain features of the dataflow between the embedded processor and the
programmable logic region, the Vitis compiler
requires explicit instructions for defining the interface protocol used to move data
from the host to the kernel.
Specifying the INTERFACE pragma
Use the HLS INTERFACE pragma to define the interface protocol as shown in the following code snippet.
#pragma HLS INTERFACE m_axi port=matA offset=slave bundle=gmem0
#pragma HLS INTERFACE m_axi port=matB offset=slave bundle=gmem1
#pragma HLS INTERFACE m_axi port=matC offset=slave bundle=gmem2
#pragma HLS INTERFACE s_axilite port=matA bundle=control
#pragma HLS INTERFACE s_axilite port=matB bundle=control
#pragma HLS INTERFACE s_axilite port=matC bundle=control
#pragma HLS INTERFACE s_axilite port=col bundle=control
#pragma HLS INTERFACE s_axilite port=row bundle=control
#pragma HLS INTERFACE s_axilite port=return bundle=control
sds++ compiler would infer the m_axi to
each have individual bundles for performance. For the Vitis
compiler, you will have to explicitly set each bundle to a new gmem to keep same
behavior. If reducing the number of interfaces is desired, use the same bundle name for
different interfaces.The code above defines the interfaces for the three matrix parameters, matA, matB, and matC, as high-performance memory-mapped AXI interfaces
(m_axi) for data transfer to and from the
accelerator. Scalar parameters are also mapped to the s_axilite interface in the kernel function and function parameters, such
as col and row, as
well as the base addresses for the memory mapped interfaces and kernel function returns.
Define the kernel interfaces through the HLS INTERFACE pragma. The compiler will use these parameters when defining the specified kernel interface ports. For more information on this topic, refer to "Interface Synthesis" in the Vivado Design Suite User Guide: High-Level Synthesis (UG902) and Methodology for Accelerating Applications with the Vitis Software Platform.
The Vitis environment requires that the
function parameters (scalars, pointers, and return control signals) should be
consolidated into a single s_axilite interface port,
including the function return. In the example above, the bundle=control keyword consolidates all the s_axilite ports into an interface port called control.
Beyond the elimination of the hardware function header, and the addition of the HLS INTERFACE pragma, the function is largely unchanged. Generally, HLS pragmas that are used inside the function can be left as is. These pragmas would be PIPELINE, UNROLL, ARRAY_PARTITION, and so on.