3.5.1.12 Data Flow Parallelism

Data Flow or "dataflow" parallelism is another commonly used technique to improve hardware throughout. In dataflow parallelism, a succession of computational tasks which process continuous streams of data can execute in parallel. These tasks are called dataflow sub-functions. A function is declared as a dataflow function using the pragma #pragma HLS function dataflow (see Dataflow ). Within this dataflow function, the called functions, or sub-functions, will execute with dataflow parallelism. If the dataflow function contains loops or control-flow, each top-level loop nest or control-flow region will be extracted into a new sub-function.

In a dataflow circuit, synchronization will be required for passing intermediate data between the sub-functions that can run in parallel. For instance, a producer sub-function can write to an array for another consumer sub-function to read. In this case, the consumer sub-function needs to "know" that the producer has finished writing the array in order to start. SmartHLS can convert such intermediate data into double/shared buffer or FIFOs. By default, intermediate data is converted into double buffer. see Dataflow Channel pragma.

Important: Dataflow functions and sub-functions have the following restrictions or properties:
  1. The dataflow function and all its sub-functions must have void return type, with output data passed by pointer or by reference.
  2. Nested dataflow functions must have the parent dataflow function directly calling the child dataflow function. That is, it is supported for a dataflow function to call another dataflow function; however it is not allowed to have a dataflow function, calling a non-dataflow function, which further calls a dataflow function.
  3. Sub-functions cannot contain SmartHLS Threads (to use SmartHLS Threads, see Multi-threading with SmartHLS Threads).
  4. When a dataflow function is called from within a loop, the loop body can only contain that call in order for SmartHLS to overlap the invocations of the dataflow function; otherwise the dataflow function will still run in a non-overlapped manner.

  5. Data external to the dataflow function (declared outside of the dataflow function and its sub-functions) can only be accessed by 1 sub-function, unless the data is of FIFO type.
  6. All intermediate data should have exactly one producer and one consumer sub-function.
  7. When configuring an intermediate data variable, that is, an array or single-element memory to be implemented as a FIFO channel using the Dataflow Channel pragma, it is only correct to use the fifo type when:
    • The producer function only writes to the variable in a sequential manner.
    • The consumer function only reads from the variable in a sequential manner.
  8. If a sub-function calls another synthesizable sub-sub-function, the sub-sub-function will be automatically inlined by SmartHLS.
  9. If a sub-function is called in more than one location inside a dataflow function, the sub-function will be automatically replicated by SmartHLS.
Important: If a dataflow function contains conditionally executed tasks, the generated circuit may mismatch with the software and may need to be free-running on hardware for the circuit to work properly. To make the generated circuit free-running, tie the start signal to 1. For more information, see COSIM_FREE_RUNNING_DATAFLOW_TOP for how to keep the start signal at 1 during simulation.

Dataflow parallelism can be used to overlap sub-functions which run in sequence, or to run independent sub-functions in parallel.