Construct Graph with Packet Switching Capability - 2023.2 English

Vitis Tutorials: AI Engine

Document ID
Release Date
2023.2 English

To explicitly control the multiplexing and de-multiplexing of packets, two new templated node classes are added to the ADF graph library: pktsplit<n> and pktmerge<n>. A node instance of class pktmerge<n> is a n:1 multiplexer of n packet streams producing a single packet stream. A node instance of class pktsplit<n> is a 1:n de-multiplexer of a packet stream producing n different packet streams.

Note: The maximum number of allowable packet streams is thirty-two on a single physical channel (n≤32).

The data from the PLIO is first connected to the pktsplit<n> instance, which splits the packet depending on the packet ID. It automatically discards the packet header and fills the buffer input buffers. It automatically discards the TLAST signal of the packet when the buffer data is fully filled.

Each AI Engine kernel works similarly to a non-packet switching kernel. The output data is merged by the pktmerge<n> instance, which automatically inserts the packet headers with packet IDs, and TLAST for the last data of the packet.

Change the working directory to buffer_aie. The example graph code is in aie/graph.h, shown as follows.

	class mygraph: public adf::graph {
	  adf:: kernel core[4];
	  adf:: pktsplit<4> sp;
	  adf:: pktmerge<4> mg;
	  adf::input_plio  in;
	  adf::output_plio  out;
	  mygraph() {
	    core[0] = adf::kernel::create(aie_core1);
	    core[1] = adf::kernel::create(aie_core2);
	    core[2] = adf::kernel::create(aie_core3);
	    core[3] = adf::kernel::create(aie_core4);
	    adf::source(core[0]) = "aie_core1.cpp";
	    adf::source(core[1]) = "aie_core2.cpp";
	    adf::source(core[2]) = "aie_core3.cpp";
	    adf::source(core[3]) = "aie_core4.cpp";
		in=adf::input_plio::create("Datain0", plio_32_bits,  "data/input.txt");
		out=adf::output_plio::create("Dataout0", plio_32_bits,  "data/output.txt");
	    sp = adf::pktsplit<4>::create();
	    mg = adf::pktmerge<4>::create();
	    for(int i=0;i<4;i++){
	    	adf::runtime<ratio>(core[i]) = 0.9;
	    	adf::connect<> (sp.out[i], core[i].in[0]);
	        adf::connect<> (core[i].out[0],[i]);
	    adf::connect<adf::pktstream> (in.out[0],[0]);
	    adf::connect<adf::pktstream> (mg.out[0],[0]);

This is a graph with a 1:4 splitter pktsplit<4> and 1:1 merger pktmerge<4>. Note that the connection type for pktsplit and pktmerge is adf::pktstream. The input port in is first connected to the pktsplit, and pktsplit switches the packets to different AI Engine kernels. The outputs of AI Engine kernels are connected to the pktmerge, and pktmerge generates packet headers for those packets automatically and outputs them through output port, out.

Run the make command make aie to compile the graph. Then open the compiled summary with the AMD Vitis™ analyzer using the command vitis_analyzer ./Work/graph.aiecompile_summary. Then click the Graph tab in the Vitis analyzer. The graph of the design is shown as follows.


It is seen that every sp output has been assigned a unique packet ID. Also, every mg input has been assigned a unique ID. The packet IDs can vary on different implementations. The AI Engine compiler generates a JSON file that contains all the packet ID infomation Work/reports/packet_switching_report.json. It also generates header files that define unique macro variables for the packet IDs. These files are Work/temp/packet_ids_c.h and Work/temp/packet_ids_v.h, which can be directly included in the C or Verilog source code.

For example, in this test case, the Work/temp/packet_ids_c.h file is as follows.

    #define Datain0_0 0
    #define Datain0_1 1
    #define Datain0_2 2
    #define Datain0_3 3
    #define Dataout0_0 3
    #define Dataout0_1 2
    #define Dataout0_2 1
    #define Dataout0_3 0

The macro names Datain0_0, …, Dataout0_3 do not change between different compilations. You can see how these macros are used in the PL kernels in this test case in a later section.