文档目录

10.1. 任务函数

Intel® HLS Compiler Pro Edition以类似于HLS组件函数的方式实现任务函数,但会有一些其他的限制。

任务函数接口

您可以通过下列方式将数据传入和传出任务函数:
任务函数接口有以下限制:
  • 您不能将以全局或文件范围定义的 Avalon® MM Host接口(ihc::mm_host)用于组件及其任务中。
  • 指针或引用数据类型不能作为参数被传递给任务函数,除非它们是指向显式 Avalon® MM Host接口。
更多任务函数接口的详细信息和实例,请参考以下教程:

<quartus_installdir>/hls/examples/tutorials/system_of_tasks/interfaces_sot

任务调用接口

您可以通过ihc::launch<>()ihc::collect<>() API将函数作为任务来调用。

您代码中的ihc::launch<task_function>()调用会产生一个call接口,该接口用于以顶层组件为源,以任务为接收器(sink)的指定任务。顶层组件通过置位start信号调用任务的调用接口来开始新一轮任务执行。

您代码中的ihc::collect<task_function>()调用会产生一个return接口,该接口用于以任务为源,以顶层组件为接收器(sink)的指定任务。该返回接口具有done信号,在其完成单个执行时由任务将其置位。当顶层组件调用返回接口时,它会使用此done信号并读取任何返回的值。

在High Level Design Reports (report.html)中,ihc::launchihc::collect调用表现为阻塞流写入和流读取操作。

标量参数和返回值

与HLS组件一样,HLS任务的标量参数和返回值被实现为管道,而握手则被实现为简单的stall/valid握手。ihc::launchihc::collect调用直接连接到HLS任务函数 doreturn流。

在High Level Design Reports (report.html)中,ihc::launchihc::collect调用表现为阻塞流写入和流读取操作。

与外部系统的交互

任务函数可以使用ihc::stream_in类从外部系统获取输入,或者获取ihc::stream_out类全局实例以便向外部系统提供输出。

必须在任何结构变量之外声明全局ihc::stream_inihc::stream_out流,并且也不能在数组中进行声明。

HLS任务函数之间的通信

为了使两个任务函数相互通信,需要将它们与全局函数ihc::stream目标对象连接起来(而不是ihc::stream_inihc::stream_out对象)。

必须在任何结构变量之外声明全局ihc::stream目标对象,并且也不能在数组中进行声明。

ihc::stream对象有一个与ihc::stream_inihc::stream_out类极为相似的API。但是,由于这些流始终需要握手,因此API不支持参数ihc::usesReady或者ihc::usesValid。但是确定支持tryReadtryWriteAPI函数。

ihc::stream对象可以在任务系统中拥有两个端点。也包括在同一函数中。例如,在单个函数中将ihc::stream作为FIFO使用,请参阅以下教程:
<quartus_installdir>/hls/examples/tutorials/system_of_tasks/internal_stream
如果ihc::stream类实例在任务系统中只有一个端点,就会根据其在系统内的用途来将其作为ihc::stream_in或者ihc::stream_out,因而可以将其与ihc::stream_in或者ihc::stream_out互换使用(前提是这些限制不会影响设计)。ihc::stream目标对象可用于多个任务相互通信。请参阅以下教程:
<quartus_installdir>/hls/examples/tutorials/system_of_tasks/parallel_loops
下图展示了如何使用ihc::stream目标对象在任务函数之间进行通信:
图 13. 使用内部流的任务系统实例


HLS任务函数限制

HLS任务函数受到以下限制:
  • 任务函数不能在多个组件之间共享。
  • 流的所有读站点和写站点必须位于同一函数(组件或任务)内。
  • 如果将类成员函数实现为任务函数,则该成员函数必须为静态。如果要参数化函数行为,则请使用函数参数或模板参数。不能使用对象的实例变量。
  • 只能从一个组件函数或任务函数启动任务函数(通过ihc::launch)。启动函数和收集函数可以是不同的函数,但他们必须属于同一任务组件系统。
  • 只能从一个组件或任务函数收集任务函数(通过ihc::collect)。收集函数和启动函数可以是不同的函数,但他们必须属于同一任务组件系统。
  • 即使在任务级别,也不保证独立I/O指令之间的执行顺序。

    对特定任务函数的ihc::launchihc::collect调用按顺序执行。

    从当前函数对该任务的任何流访问都仅按照与相应函数的ihc::launchihc::collect调用相关的指令顺序执行。

图 14. 实例1—有效的ihc::launch/ihc::collect顺序
图 15. 实例2—有效的ihc::launch/ihc::collect顺序
图 16. 实例3—有效的ihc::launch/ihc::collect顺序
图 17. 实例—无效的ihc::launch/ihc::collect顺序

任务属性

您可以在HLS任务函数上使用以下函数级属性:
  • hls_max_concurrency
  • hls_component_ii
  • hls_scheduler_target_fmax_mhz
  • hls_disable_component_pipelining

除了这些函数属性之外,您还可以在HLS任务函数中使用任何HLS属性和指令。例如,您可以使用以下属性和指令,#pragma ii, #pragma ivdephls_memoryhls_register

在您定义HLS任务函数时,不能使用组件宏功能或组件调用接口控制属性。例如,不能使用hls_avalon_agent_register_argumenthls_conduit_argumenthls_stall_free_returnhls_avalon_streaming_component

任务容量

编译器调度启动并在顶层组件或调用者数据路径中进行收集。

如果您安排了具有不同延迟的多个任务,则可能需要将capacity添加到ihc::launchihc::collect调用。

同样地,设置ihc::launch调用中的capacity参数可插入一个缓冲,从而允许调用程序将工作推送到任务函数上,然后可自由地从队列中提取工作。

设置ihc::collect调用指令的capacity参数插入一个缓冲区,该缓冲区可保存由任务函数计算的返回值。调用指令程序函数可在稍后方便的时间自由地从缓冲区中获取返回值,但不会对任务函数造成背压。

有关如何以及何时通过ihc::launchihc::collect调用 使用capacity参数,请参阅Intel HLS编译器最佳实践指南中的 “在需要时明确地向您的设计添加缓冲容量”

您也可以查看以下教程:
<quartus_installdir>/hls/examples/tutorials/system_of_tasks/launch_and_collect_capacity