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);
}
///////////////////////////////////////////////////////////////////////////////////
// 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!
////////////////////////////////////////////////////////////////////////