The AI Engine architecture uses streaming data extensively for communicating between two AI Engines, and for communicating between the AI Engine and the programmable logic (PL). This raises the potential for a resource deadlock when the data flow graph has reconvergent stream paths. If the pipeline depth of one path is longer than the other, the producer kernel can stall and might not be able to push data into the shorter path because of back pressure. At the same time, the consumer kernel is waiting to receive data on the longer path due to the lack of data. If the order of data production and consumption between two stream paths is different, a deadlock can happen even between two kernels that are directly connected with two stream paths.
Vitis Model Composer supports adding a FIFO_DEPTH between
two AI Engine kernels or between an AI Engine and the programmable logic (PL) using the AIE
FIFO block and automatically generates the graph code with
fifo_depth constraint on a connection.
The AIE FIFO block specifies the FIFO depth on a particular path. Specifying the FIFO depth value can help avoid deadlock or stalling by creating more buffering in the paths. This block does not affect functional simulation and will only impact the generated graph code. You can set location constraints for the FIFO block using the Constraint manager. FIFOs can be either stream FIFOs, DMA FIFOs, or a combination of the two.
- Use this tab to specify FIFO depth.
- Use this tab to set location constraints for the FIFO block using the Constraint manager.
Consider the following example where the AIE FIFO blocks are connected in two stream paths between AI Engine kernel blocks.
The FIFO depth value is are specified as
default and the corresponding information is reflected on the block symbol. For
example, if values
4 are specified as parameters of the two FIFO blocks, the GUI will
update as shown in the following figures.
The stream FIFO values specified using the AIE Signal Spec block are
automatically updated in the generated graph code (graph.h) with
constraints as shown in the following code.
Snippet of graph.h
// create nets to specify connections
adf::connect< adf::stream > net0 (In1, AIE_Kernel.in);
adf::connect< adf::stream > net1 (AIE_Kernel.out, AIE_Kernel1.in);
adf::fifo_depth(net1) = 2;
adf::connect< adf::stream > net2 (AIE_Kernel.out, AIE_Kernel1.in);
adf::fifo_depth(net2) = 4;
adf::connect< adf::stream > net3 (AIE_Kernel1.out, Out1);
Notice the two
fifo_depth constraints corresponding to the
two stream paths in the design. Using this
fifo_depth constraint on a connection is useful as it creates more
buffering in paths with back pressure, and hence avoids any deadlock.