When the memory tile DMA channel number is limited or the routing resource is limited, you can reuse the memory tile DMA channel to split data to multiple destinations using packet splits.
To use packets for data output from the memory tile, add packet_port_id
to the tiling parameters. Tiling parameters can also be
chained together to support different packet IDs for the same port.
The following is an example of graph code where the packet splits the data from the memory tile to different kernels with different read patterns:
shared_buffer<int32> mtxA;
pktsplit<2> sp;
input_plio in;
output_plio out[2];
......
//in elements, input port=1, output port=1
mtxA = shared_buffer<int32>::create({256}, 1, 1);
sp=pktsplit<2>::create();
in=input_plio::create("Datain0", plio_64_bits, "data/input.txt");
for(int i=0;i<2;i++){
out[i]=output_plio::create("Dataout"+std::to_string(i), plio_64_bits, "data/output"+std::to_string(i)+".txt");
}
......
//connecting from PLIO input to shared buffer, from shared buffer to pktsplit
//from pktsplit to kernels, from kernels to PLIO outputs
connect(in.out[0], mtxA.in[0]);
connect(mtxA.out[0], sp.in[0]);
connect(sp.out[0], first.in[0]);
connect(sp.out[1], second.in[0]);
connect(first.out[0], out[0].in[0]);
connect(second.out[0], out[1].in[0]);
//Write to shared buffer
write_access(mtxA.in[0]) = tiling({.buffer_dimension={256}, .tiling_dimension={256}, .offset={0}, .tile_traversal = {{.dimension=0, .stride=1, .wrap=1}} });
//Read from memory tile to packet ID 0 first, and then packet ID 1,
//With packet split, different packets will route to different destinations.
read_access(mtxA.out[0]) = {
tiling({.buffer_dimension={32,8}, .tiling_dimension={32,1}, .offset={0,0}, .tile_traversal = {{.dimension=1, .stride=1, .wrap=8}}, .packet_port_id=0 }),
tiling({.buffer_dimension={32,8}, .tiling_dimension={1,8}, .offset={0,0}, .tile_traversal = {{.dimension=0, .stride=1, .wrap=32}}, .packet_port_id=1 })
};
The example graph view is as follows:
Figure 1. Memtile Packet Split Graph View
