Overview
This section describes how to provide input and capture the output from the AI Engine array in all simulation and emulation modes using AXI traffic generators. In the AI Engine simulator the input data stimulus is provided using the PLIO object which specifies a text file containing the data:
input_plio plin = input_plio::create("DataIn", adf::plio_32_bits, "data/input.txt");
While this is really fast to get your first simulation in place, the main limitation of this approach is that if you want to change the input file name for another simulation, you have to recompile the entire application. That's why there is a possibility to avoid file name specification and rely on independent External Traffic Generator to generate data traffic on the PLIO:
input_plio plin = input_plio::create("DataIn", adf::plio_32_bits);
For hardware and software emulation an equivalent feature exists that emulates the behavior of this PLIO and AXI4-Stream interface. Both Python and C++ APIs are provided to create these External Traffic Generators that will be connected seamlessly on any of these simulation or emulation modes.
The primary external data interfaces for the AI Engine array are AXI4-Stream interfaces. These are known as PLIOs and allow the AI Engine to receive data, operate on the data, and send data back on a separate AXI4-Stream interface. The input interface to the AI Engine is an AXI4-Stream consumer and the output is an AXI4-Stream producer. To interact with these top level interfaces during hardware and software emulation complementary AXI4-Stream modules are provided. These complementary modules are referred to as the AXI traffic generators.
Standard Use Case
When you develop an AI Engine application and you want to test it either in simulation (x86sim, aiesim) or emulation (sw_emu, hw_emu) you need to provide data at the input and gather the output data to compare them with some predefined reference files. Further more, if your AI Engine graph is intertwined with kernels which are located in the Programmable Logic (HLS C++ or RTL) then you also have to deal with these data flow interruptions. A generic application might look like this:
- X86 Simulation
- AI Engine simulation
- SW Emulation
- HW Emulation
AI Engine Graph Modifications
plin = input_plio::create("DataIn1",adf::plio_32_bits,"data/mm2s.txt");
clip_in = output_plio::create("clip_in",adf::plio_32_bits, "data/polar_clip_in.txt");
clip_out = input_plio::create("clip_out",adf::plio_32_bits,"data/polar_clip_out.txt");
plout = output_plio::create("DataOut1",adf::plio_32_bits, "data/s2mm.txt");
to
the new written way that avoids text file name
declaration:plin = input_plio::create("DataIn1",adf::plio_32_bits);
clip_in = output_plio::create("clip_in",adf::plio_32_bits);
clip_out = input_plio::create("clip_out",adf::plio_32_bits);
plout = output_plio::create("DataOut1",adf::plio_32_bits);
The first parameter of the input/output plio declaration is important as this is the name that will be used on the traffic generator side to connect to the right socket.
X86 simulation and AI Engine simulation can then be launched as soon as the traffic generators will be written in Python or in C++.
Launching the simulation will consists in running in parallel the
aiesimulator
or the x86simulator
in parallel with the external traffic generator.
PL Kernels Change
.xo
) files cannot be created to be used
in the Vitis link stage. We must introduce hooks in the programmable logic so that
we can connect external traffic generators to them. Xilinx provides a complete set
of pre-compiled .xo
files that can be used for
that purpose:-
$(XILINX_VITIS)/data/emulation/XO/sim_ipc_axis_slave_32.xo, $(XILINX_VITIS)/data/emulation/XO/sim_ipc_axis_master_32.xo
-
$(XILINX_VITIS)/data/emulation/XO/sim_ipc_axis_slave_64.xo, $(XILINX_VITIS)/data/emulation/XO/sim_ipc_axis_master_64.xo
-
$(XILINX_VITIS)/data/emulation/XO/sim_ipc_axis_slave_128.xo, $(XILINX_VITIS)/data/emulation/XO/sim_ipc_axis_master_128.xo
The right set of .xo
files
should be copied to the right location on your project in order to use them in your
configuration file during the Vitis link stage.
Link Stage
v++ -l
) the
previously defined .xo
files will be used to
connect the related compute units to the AI Engine graph. The
system.cfg
configuration file is created in
such a way that the compute unit names matches the names you defined in the graph
for the input_plio
and the output_plio
:[connectivity]
nk=sim_ipc_axis_master:2:DataIn1.clip_out
nk=sim_ipc_axis_slave:2:DataOut1.clip_in
sc=DataIn1.M00_AXIS:ai_engine_0.DataIn1
sc=ai_engine_0.clip_in:clip_in.S00_AXIS
sc=clip_out.M00_AXIS:ai_engine_0.clip_out
sc=ai_engine_0.DataOut1:DataOut1.S00_AXIS
With this naming precaution, the exact same external traffic generator will be used for any simulation or emulation.
In the case of software emulation (sw_emu
) and hardware emulation (hw_emu
), you can write the external traffic generator in C++, Python,
or HDL, if familiar with RTL coding.
Host Code
- Open the device
- Load the
xclbin
file - Register XRT to connect to the design
- Run the AI Engine graph
After compiling the host code you can package the whole project. Running the emulation consists in running the external traffic generator in parallel with the standard emulation launch.