Testbed for connecting an IP generated by Vivado HLS to the network interfaces of the host. The IP is expected to exchange etherent frames with the host (or other IPs on the FPGA) using AXI4 Streams of Packet Units (PUs, see Notes).
This testbed forwards all raw ethernet frames from all specified interfaces to the IP, and vice versa.
- Make sure Xilinx's
xsim
,xvlog
,xsc
andxelab
can be found in your path. Also requiresmake
for automatic building and both Python 2 (for Mininet) and 3 (for IP unpacking script). - Copy your HLS-generated IP to the directory where
Makefile
is in, and fill the filename of the zip archive into theIP_ZIP
variable of theMakefile
. - Run
make
here. The testbed framework should generate a top-level modulesim_top.sv
here for you, and proceed to compilation. You should check the generated code insim_top.sv
. The generator scripttestbed/tbgen.py
assumes input and output PU AXI Streams are in pairs (each for a network interface). If not, you may need to manually write the rest of them. Also check if the interface names ("s1-eth1 ...") are what you need (especially when not using Mininet). - If
make
successes, modifymn-run.py
for desired Mininet setup and runsudo ./mn-run.py
here to start. It should bring up the Mininet console. The simulator's output is written to the filexsim-mn-out.log
. Do experiments in the console as required. - If need to run on host (with machine's physical interfaces) instead,
check the interface names as per step 3,
make
andsudo make run
. The simulation will run continuously until receiving interrput (Ctrl^C
). - Alternatively,
sudo make run_gui
starts the Vivado GUI for simulation. Or you may runsudo make run_wave
to have some signals logged. Choose the signals by modifyingtestbed/dump_wave.tcl
. - After a
sudo make run_wave
execution, view the waveforms withmake view_wave
.
The IP archive xilinx_com_hls_EtherSwitch_Top_1_0.zip
is provided as
an example. It acts as a 3-port ethernet bridge that allows the 3 hosts
in the Mininet topology to communicate with each other.
make
may need to run twice ifsim_top.sv
is not yet generated.- Once
sim_top.sv
is generated, it will not be overwritten bymake
. - Root privilege is requried for opening raw socket, hence the
sudo
. - The raw socket works in sniffer mode, which means the OS kernel
will still receive the packets. Outgoing packets from OS kernel
will also be sniffed. To prevent this, run
sudo iptables -A INPUT -i your_if_name -j DROP
to block the OS kernel, andsudo iptables -D INPUT -i your_if_name -j DROP
to restore. make view_wave
requires write permission tobuild/.Xil/
. May need tochown
the directory if it belongs to root due tosudo
.
In this example, HDL modules pktunit_axis_feeder
and
pktunit_axis_poller
calls the DPI socket functions defined in
rawsock.c
, puts data onto or polls them from an AXI Stream. The
format of such an stream ("Packet Unit" AXI Stream) is defined as:
- data: Data bus of
DATA_BYTES
parallel bytes. 8*8=64 bits in this example. Carries the packet data, bytes of smaller offsets are at the LSB. Bit order in a byte is the same as the bus. - flags: Optional flags associated with a packet unit. Reserved for processing inside the HDL design, not used in this example.
- eop: End-of-packet indication bit, width of
DATA_BYTES
. Each bit corresponds to a byte in data. If the bit is set to 1, the corresponding byte is or is beyond the last byte in a packet.
The C++ (HLS) definition is given as follows:
template <short W>
struct PktUnit { // Note that the struct should not be packed
// Packet/Frame data chunk
ap_uint<W*8> data;
// User-defined flags
ap_uint<8> flags;
// End-of-packet bits, set to 1 for the last byte and thereafter
ap_uint<W> eop;
};
// ...
hls::stream<PktUnit<PU_WIDTH> > inStream[NUM_PORT]
#pragma HLS INTERFACE axis register port=inStream
#pragma HLS ARRAY_PARTITION variable=inStream complete dim=1