Compiling and Linking Host Code with ADF API - 2023.2 English

AI Engine Tools and Flows User Guide (UG1076)

Document ID
Release Date
2023.2 English
When adaptive data flow (ADF) APIs or event profile APIs are used in the host code, you must:
  • Use the registerXRT() API before using the ADF APIs or the event profile APIs in the host code.
  • Compile and link the host code with Work/ps/c_rts/aie_control_xrt.cpp.
The following are example commands for compiling and linking the PS application:
//Compiling host.cpp
$CXX -std=c++17 -O0 -g -Wall -c -I$SDKTARGETSYSROOT/usr/include/xrt/ --sysroot=$SDKTARGETSYSROOT -I./ -I./src -I$XILINX_HLS/include/ -I$XILINX_VITIS/aietools/include -o sw/host.o sw/host.cpp

//Compiling aie_control_xrt.cpp
-std=c++17 -O0 -g -Wall -c -I$SDKTARGETSYSROOT/usr/include/xrt/ --sysroot=$SDKTARGETSYSROOT -I./ -I./src -I$XILINX_HLS/include/ -I$XILINX_VITIS/aietools/include -o sw/aie_control_xrt.o Work/ps/c_rts/aie_control_xrt.cpp

//Linking the host application
$CXX -ladf_api_xrt -lgcc -lc -lpthread -lrt -ldl -lcrypt -lstdc++ -lxrt_coreutil -L$SDKTARGETSYSROOT/usr/lib/ --sysroot=$SDKTARGETSYSROOT -L$XILINX_VITIS/aietools/lib/aarch64.o -o sw/host.exe sw/host.o sw/aie_control_xrt.o
Where -ladf_api_xrt is the required library for the ADF API in Linux.
The following is an example that uses ADF API and event profile API in the host code:
#include "adf/adf_api/XRTConfig.h"
#include "xrt/xrt_kernel.h"

#include "graph.cpp"

int run(int argc, char* argv[]){
	char* xclbinFilename = argv[1];
	int ret=0;
	// Open xclbin
	auto device = xrt::device(0); //device index=0
	auto uuid = device.load_xclbin(xclbinFilename);
	auto dhdl = xrtDeviceOpenFromXcl(device);

	// s2mm & mm2s kernel handle
	auto s2mm = xrt::kernel(device, uuid, "s2mm");
	auto mm2s = xrt::kernel(device, uuid, "mm2s");

	// output memory
	auto out_bo = xrt::bo(device, output_size_in_bytes, s2mm.group_id(0));

	// input memory
	auto in_bo = xrt::bo(device, output_size_in_bytes, mm2s.group_id(0));

	// Initialization input memory

	//kernel run
	auto s2mm_run = s2mm(out_bo, nullptr, OUTPUT_SIZE);//1st run for s2mm has started
	auto mm2s_run = mm2s(in_bo, nullptr, OUTPUT_SIZE);

	// Use registerXRT before ADF API
	adf::registerXRT(dhdl, uuid.get());
	std::cout<<"Register XRT"<<std::endl;

	event::handle handle = event::start_profiling(gr.dataout, event::io_stream_start_to_bytes_transferred_cycles, output_size_in_bytes);
		printf("ERROR:Invalid handle. Only two performance counter in a AIE-PL interface tile\n");
		return 1;
	// Wait graph for some cycles
	long long cycle_count = event::read_profiling(handle);
	std::cout<<"cycle count:"<<cycle_count<<std::endl;
	double throughput = (double)output_size_in_bytes / (cycle_count *0.8 * 1e-3); //Every AIE cycle is 0.8ns in production board
	std::cout<<"Throughput of the graph: "<<throughput<<" MB/s"<<std::endl;

	//post processing

	return ret;

int main(int argc, char* argv[])
	try {
		auto match = run(argc, argv);
		std::cout << "TEST " << (match ? "FAILED" : "PASSED") << "\n";
		return (match ? EXIT_FAILURE :  EXIT_SUCCESS);
		catch (std::exception const& e) {
		std::cout << "Exception: " << e.what() << "\n";
		std::cout << "FAILED TEST\n";
		return 1;