HLS Task Library - 2023.1 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2023-07-17
Version
2023.1 English
Important: To use hls::task objects in your code include the header file hls_task.h.

The hls::task library provides a simpler way of modeling purely streaming kernels, allowing static instantiation of tasks with only streaming I/O (hls::stream or hls::stream_of_blocks). This reduces the need for checks for empty stream needed to model concurrent processes in C++.

The following is a simple example that can be found at simple_data_driven on GitHub:

void odds_and_evens(hls::stream<int> &in, hls::stream<int> &out1, hls::stream<int> &out2) {
    hls_thread_local hls::stream<int> s1; // channel connecting t1 and t2      
    hls_thread_local hls::stream<int> s2; // channel connecting t1 and t3

    // t1 infinitely runs splitter, with input in and outputs s1 and s2
    hls_thread_local hls::task t1(splitter, in, s1, s2);
    // t2 infinitely runs function odds, with input s1 and output out1    
    hls_thread_local hls::task t2(odds, s1, out1);       
    // t3 infinitely runs function evens, with input s2 and output
    hls_thread_local hls::task t3(evens, s2, out2);
}

Notice the top-level function, odds_and_evens uses streaming input and output interfaces. This is a purely streaming kernel. The top-level function includes the following:

  • s1 and s2 are thread-local streams (hls_thread_local) and are used to connect the task-channel tasks t1 and t2. These streams need to be thread-local so that they can be kept alive across top-level calls.
  • t1, t2, and t3 are the thread-local hls::task that execute the functions (splitter, odds, and evens respectively). The tasks run infinitely and just process data on their input streams. No synchronization is needed.

However, this type of model does have some restrictions such as:

  • You cannot access non-local memory
  • Non-stream data, such as scalar and array variables, must all be local to the processes and cannot be passed as arguments
  • A task cannot be nested inside a sequential region
  • You must explicitly describe the parallelism in the design by the specification of parallel tasks

The hls::task objects can be mixed freely with standard dataflow-style function calls, which can move data in and out of memories (DRAM and BRAM). Tasks also support splitting channels (hls::split) to support one-to-many data distributions to build pools of workers that process streams of data, and merging channels (hls::merge) to support many-to-one data aggregation.