Cosim Deadlock Viewer - 2021.2 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2021-12-15
Version
2021.2 English

A deadlock is a situation in which processes inside a DATAFLOW region share the same channels, effectively preventing each other from writing or reading from it, resulting in both processes getting stuck. This scenario is common when there are either FIFO’s or a mix of PIPOs and FIFOs as channels inside the DATAFLOW.

The deadlock viewer visualizes this deadlock scenario on the static dataflow viewer. It highlights the problematic processes and channels. The viewer also provides a cross-probing capability to link between the problematic dataflow channels and the associated source code. The user can use the information in solving the issue with less time and effort. The viewer automatically opens only after, the co-simulation detects the deadlock situation and the co-sim run has finished.

A small example is shown below. The dataflow region consists of two processes which are communicating through PIPO and FIFO. The first loop in proc_1 writes 10 data items in data_channel1, before writing anything in data_array. Because of the insufficient FIFO depth the data_channel loop does not complete which blocks the rest of the process. Then proc_2 blocks because it cannot read the data from data_channel2 (because it is empty), and cannot remove data from data_channel1. This creates a deadlock that requires increasing the size of data_channel1 to at least 10.

void example(hls::stream<data_t>& A, hls::stream<data_t>& B){
#pragma HLS dataflow
..
..
hls::stream<int> data_channel;
int data_array[10];
#pragma HLS STREAM variable=data_channel depth=8 dim=1
    proc_1(A, data_channel, data_array);
    proc_2(B, data_channel, data_array);
}

void proc_1(hls::stream<data_t>& A, hls::stream<int>& data_channel, int data_array[10]){
  …
  for(i = 0; i < 10; i++){
    tmp = A.read();
    tmp.data = tmp.data.to_int();
    data_channel.write(tmp.data);
  }
  for(i = 0; i < 10; i++){
      data_array[i] = i + tmp.data.to_int();
  }
}

void proc_2(hls::stream<data_t>& B, hls::stream<int>& data_channel, int data_array[10]){
  int i;
  ..
  ..
  for(i = 0; i < 10; i++){
      if (i == 0){
        tmp.data = data_channel.read() + data_array[5];
      }
      else {
        tmp.data = data_channel.read();
      }
    B.write(tmp);
  }
Co-sim Log:
///////////////////////////////////////////////////////////////////////////////////
// Inter-Transaction Progress: Completed Transaction / Total Transaction
// Intra-Transaction Progress: Measured Latency / Latency Estimation * 100%
//
// RTL Simulation : "Inter-Transaction Progress" ["Intra-Transaction Progress"] @ "Simulation Time"
////////////////////////////////////////////////////////////////////////////////////
// RTL Simulation : 0 / 1 [0.00%] @ "105000"
//////////////////////////////////////////////////////////////////////////////
// ERROR!!! DEADLOCK DETECTED at 132000 ns! SIMULATION WILL BE STOPPED! //
//////////////////////////////////////////////////////////////////////////////
/////////////////////////
// Dependence cycle 1:
// (1): Process: example_example.proc_1_U0
//      Channel: example_example.data_channel1_U, FULL
// (2): Process: example_example.proc_2_U0
//      Channel: example_example.data_array_U, EMPTY
////////////////////////////////////////////////////////////////////////
// Totally 1 cycles detected!
////////////////////////////////////////////////////////////////////////
Figure 1. Deadlock Viewer