Modeling Feedback in Dataflow Regions - 2023.1 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2023-07-17
Version
2023.1 English

One main limitation of PIPO buffers is that they can flow only forward with respect to the function call sequence in C++. In other words, the following connection is not supported with PIPOs, while it can be supported with hls::stream_of_blocks:

void top(...) {
  int b[N];
  for (int i = 0; i < M; i++) {
#pragma HLS dataflow
#pragma HLS stream off variable=b
    consumer(b, ...); // reads b
    producer(b, ...); // writes b
  }
}

The following code example is contrived to demonstrate the concept:

#include "hls_streamofblocks.h"
typedef int buf[N];
void producer (hls::stream_of_blocks<buf> &out, ...) {
  for (int i = 0; i < M; i++) {
    hls::write_lock<buf> arr(out);
    for (int j = 0; j < N; j++)
      arr[f(j)] = ...;
  }
}
 
void consumer(hls::stream_of_blocks<buf> &in, ...) {
  if (in.empty()) // execute only when producer has already generated some meaningful data
    return;
 
  for (int i = 0; i < M; i++) {
    hls::read_lock<buf> arr(in);
    for (int j = 0; j < N; j++)
      ... = arr[g(j)];
    ...
  }
}
 
void top(...) {
  // Note the large non-default depth.
  // The producer must complete execution before the consumer can start again, due to ap_ctrl_chain.
  // A smaller depth would require ap_ctrl_none
  hls::stream_of_blocks<buf, M+2> backward;
 
  for (int i = 0; i < M; i++) {
#pragma HLS dataflow
    consumer(backward, ...); // reads backward
    producer(backward, ...); // writes backward
}