Writing Host Applications with XRT API - 2023.2 English

Vitis Unified Software Platform Documentation: Application Acceleration Development (UG1393)

Document ID
UG1393
Release Date
2023-12-13
Version
2023.2 English
The general structure of a host application in the Vitis development flow can be divided into the following steps, with example code provided:
  1. Specify the accelerator device ID and load the .xclbin:
        auto device = xrt::device(device_index);
        auto uuid = device.load_xclbin(binaryFile);
    
  2. Setup the kernel IP, and define the argument buffers:
        auto ip1 = xrt::ip(device, uuid, "Vadd_A_B:{Vadd_A_B_1}");
        // Allocate Buffer in Global Memory
        auto ip1_boA = xrt::bo(device, vector_size_bytes, 1);
        auto ip1_boB = xrt::bo(device, vector_size_bytes, 1);
        // Map the contents of the buffer object into host memory
        auto bo0_map = ip1_boA.map<int*>();
        auto bo1_map = ip1_boB.map<int*>();
    
  3. Transfer data from the host to the device memory, if the kernel is written to access device memory:
    Tip: The kernel can also be written to access host memory directly when the platform supports that ability, as described in Host Memory Access.
        // Get the buffer physical address
        buf_addr[0] = ip1_boA.address();
        buf_addr[1] = ip1_boB.address();
        // Synchronize buffer content with device side
        ip1_boA.sync(XCL_BO_SYNC_BO_TO_DEVICE);
        ip1_boB.sync(XCL_BO_SYNC_BO_TO_DEVICE);
    
        // Setting Register A (Input Address)
        ip1.write_register(A_OFFSET, buf_addr[0]);
        ip1.write_register(A_OFFSET + 4, buf_addr[0] >> 32);
    
        //Setting Register B (Input Address)
        ip1.write_register(B_OFFSET, buf_addr[1]);
        ip1.write_register(B_OFFSET + 4, buf_addr[1] >> 32);
    
    
  4. Run the kernel and returning results:
        // Start Kernel by writing to the Control Register
        uint32_t axi_ctrl = IP_START;
        ip1.write_register(USER_OFFSET, axi_ctrl);
    
        // Wait until the IP is done by reading from the Control Register
        while (axi_ctrl != IP_IDLE) {
            axi_ctrl = ip1.read_register(USER_OFFSET);
        }
    
        // Sync the output buffer back to the Host memory
        ip1_boB.sync(XCL_BO_SYNC_BO_FROM_DEVICE);
    

To support user-managed RTL kernels, you will write your host application using the XRT Native API, defining the RTL kernel as an xrt::ip object as shown above, and accessing the kernel through register read and write commands. Refer to Writing the Software Application for more information.

With the host application written, you can compile it using the standard g++ compiler as described in Compiling and Linking for x86.