As discussed in Blocking API, the blocking API can have both deterministic and non-deterministic behavior as shown in the following code example:
func1()
{
while(!s.empty()) {
s.read();
}
}
During C-simulation the data to the stream is always available so the
while
loop runs through to completion. However, if the data stream
has a single bubble when running in hardware the while
loop will exit,
and func1
will return prematurely. This will lead to non-deterministic
behavior between C-simulation and RTL execution.
The proper way to implement this loop is to use the side-channel signal
tlast
, as shown in the following example. Refer to AXI4-Stream Interfaces with Side-Channels for more information.
func1()
{
while(!tlast) {
s1.read()
}
}
- Case 1 - Simple read/write to the FIFO
-
int data = in.read(); if (data >= 10) out1.write(data); else out2.write(data);
- Case 2 - FULL and EMPTY check using blocking API
-
This case does not perform any computation with side effects, i.e. read or write a stream, memory, or static variable is still considered to use only blocking stream accesses.
void df(hls::stream<...> &s1, hls::stream<...> &s2, ...) { #pragma HLS dataflow p1(s1, ...); p2(s2, ...); ... } void p1(hls::stream<...> &s1, ...) { if (s1.empty()) return; ... = s1.read(); ... } void p2(hls::stream<...> &s2, ...) { if (s2.full()) return; ... s2.write(...); }