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));
auto host_out=out_bo.map<int*>();
// input memory
auto in_bo = xrt::bo(device, output_size_in_bytes, mm2s.group_id(0));
auto host_in=in_bo.map<int*>();
// 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);
if(handle==event::invalid_handle){
printf("ERROR:Invalid handle. Only two performance counter in a AIE-PL interface tile\n");
return 1;
}
gr.run(iterations);
gr.end();
s2mm_run.wait();
// Wait graph for some cycles
long long cycle_count = event::read_profiling(handle);
std::cout<<"cycle count:"<<cycle_count<<std::endl;
event::stop_profiling(handle);
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;
out_bo.sync(XCL_BO_SYNC_BO_FROM_DEVICE);
//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;
}
}