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 
Note: By default 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.