10.1. Task Functions
Task Function Interfaces
- You cannot use Avalon® MM Host interfaces (ihc::mm_host) defined at global or file scope in a component or its tasks.
- Pointer or reference data types cannot be passed to task functions as arguments unless they are a pointer or reference to an explicit Avalon® MM Host interface.
Task Invocation Interface
You can invoke a function as a task with the ihc::launch<>() and ihc::collect<>() API.
An ihc::launch<task_function>() call in your code produces a call interface for the specified task with the top-level component as the source and the task as the sink. The top-level component invokes the call interface of a task by asserting the start signal to start a new execution of the task.
An ihc::collect<task_function>() call in your code produces a return interface for the specified task with the task as the source and the top-level component as the sink. This return interface has a done signal that is asserted by the task when it has completed a single execution. When the top-level component invokes the return interface it consumes this donesignal and retrieves any returned values.
In the High Level Design Reports (report.html), the ihc::launch and ihc::collect calls appear as blocking streaming write and streaming read operations.
Scalar Parameters and Return Values
Like HLS components, the scalar parameters and return value for an HLS task are implemented as conduits and the hand-shaking is implemented as a simple stall/valid handshake. The ihc::launch and ihc::collect calls connect directly to the HLS task function do and return streams.
In the High Level Design Report (report.html), the ihc::launch and ihc::collect calls appear as blocking streaming write and streaming read operations.
Interaction with External Systems
Task functions can use a global instance of the ihc::stream_in class to take an input from the external system, or a global instance of the ihc::stream_out class to provide output to the external system.
The global ihc::stream_in and ihc::stream_out streams must be declared outside of any struct variables, and they cannot be declared in arrays.
Communication Between HLS Task Functions
For two task functions to communicate with each other, connect them with a global ihc::stream object (instead of the ihc::stream_in and ihc::stream_out objects).
The global ihc::stream object must be declared outside of any struct variables, and it cannot be declared in an array.
The ihc::stream object has an API very similar to the ihc::stream_in and ihc::stream_out classes. However, since these streams always require handshaking, the API does not support the parameters ihc::usesReady or ihc::usesValid. They do support tryRead and tryWrite API functions.
HLS Task Function Restrictions
- Task functions cannot be shared between multiple components.
- All read sites and write sites for a stream must be within the same function (component or task).
- If you implement a class member function as a task function, the member function must be static. If you want to parameterize the function behavior, use function parameters or template parameters. You cannot use instance variables of an object.
- A task function can be launched (with ihc::launch) only from one component function or task function. The launching function and the collecting function can be different functions but they must part of the same component system of tasks.
- A task function can be collected (with ihc::collect) only from one component or task function. The collecting function and the launching function can be different functions but they must part of the same component system of tasks.
- No guarantee of execution order is provided between independent I/O instructions, even at the task level.
The ihc::launch and ihc::collect calls to a particular task function are executed in order.
Any stream accesses to that task from the current function are executed in instruction order only with respect to ihc::launch and ihc::collect calls to the corresponding function.
In addition to these function attributes, you can use any HLS attributes and pragmas within your HLS task functions. For example, you can use attributes and pragmas like #pragma ii, #pragma ivdep, hls_memory, and hls_register.
You cannot use component macros or component invocation interface control attributes when you define HLS task functions. For example, you cannot use hls_avalon_agent_register_argument, hls_conduit_argument, hls_stall_free_return, or hls_avalon_streaming_component
The compiler schedules launches and collects in the top-level component or caller datapath.
If you schedule multiple tasks with different latencies, you might need to add capacity to ihc::launch and ihc::collect calls.
Similarly, setting the capacity parameter in an ihc::launch call inserts a buffer that allows the caller to push work onto the task function which is then free to pull work off that queue when it can.
Setting the capacity parameter in an ihc::collect call inserts a buffer that can hold the return values as they are computed by the task function. The caller function is free to pull the return values from the buffer at a convenient later time without causing backpressure on the task function.
For more information on how and when to use the capacity parameter with your ihc::launch and ihc::collect calls, refer to "Explicitly Add Buffer Capacity to Your Design When Needed" in the Intel HLS Compiler Best Practices Guide