Setting up the Kernel and Kernel Arguments - 2023.1 English

Vitis Tutorials: Hardware Acceleration (XD099)

Document ID
Release Date
2023.1 English

For XRT-managed kernels, the kernel is identified as an xrt::kernel object. However, for user-managed RTL kernels the host application uses the xrt::ip object to identify the kernel in the xclbin, as shown in the code example below. In addition, the host application identifies any compute units (CUs) of the kernel in the xclbin. The CU is an instance of the kernel, as described in Creating Multiple Instances of a Kernel. In the following code example, there are three user-managed kernels identified by the host application: ip1, ip2, and ip3. This enables the host to run multiple instances of the kernel at the same time when available in the xclbin.

NOTE: ip2 and ip3 are added for example purposes, and are not actually used in the host application.

auto ip1 = xrt::ip(device, uuid, "Vadd_A_B:{Vadd_A_B_1}");
auto ip2 = xrt::ip(device, uuid, "Vadd_A_B:{Vadd_A_B_2}");
auto ip3 = xrt::ip(device, uuid, "Vadd_A_B:{Vadd_A_B_3}");

std::cout << "Allocate Buffer in Global Memory\n";
//auto boA = xrt::bo(device, vector_size_bytes, krnl.group_id(1)); //Match kernel arguments to RTL kernel
//auto boB = xrt::bo(device, vector_size_bytes, krnl.group_id(2));
auto ip1_boA = xrt::bo(device, vector_size_bytes, 0);
auto ip1_boB = xrt::bo(device, vector_size_bytes, 1);
 //auto ip2_boA = xrt::bo(device, vector_size_bytes, 0);
//auto ip2_boB = xrt::bo(device, vector_size_bytes, 1);
//auto ip3_boA = xrt::bo(device, vector_size_bytes, 0);
//auto ip3_boB = xrt::bo(device, vector_size_bytes, 1);

In XRT-managed kernels, the XRT API can create a buffer for the memory bank used by a specific argument. This is done using the krnl.group_id(1) as shown for buffer objects boA and boB in the example above. Just as with the XRT managed kernels, the xrt::bo object is used to create buffers for the function arguments, or ports of the RTL kernel. However, unlike XRT managed kernels, the memory that the kernel argument is mapped to must be manually specified as shown for buffer objects ip1_boA and ip1_boB in the code example above.

For user-managed kernels, there is no equivalent method to map the kernel argument to the memory bank it uses. However, you either know this information because you built the user-managed kernel, or you can determine the information by examining the file produced by the xclbinutil command as described in the Vitis Commands and Utilities.

TIP: The report is generated by the Vitis compiler while linking the kernels and generating the xclbin file.

You must determine the memory bank used for specific arguments in the kernel, and create a buffer for the argument associated with that memory bank. Then you must use that buffer for the specified kernel argument when performing a read_register or write_register command for the kernel, as follows:

ip.write_register(register offset for argument A, address of buffer for argument A)`  

This information is hard-coded in this user-host.cpp application. However, there are examples of different coding techniques demonstrated in the Vitis_Accel_Examples.