HLS 任务库 - 2023.2 简体中文

Vitis 高层次综合用户指南 (UG1399)

Document ID
UG1399
Release Date
2023-12-18
Version
2023.2 简体中文
重要: 要在代码中使用 hls::task 对象,请包含头文件 hls_task.h

hls::task 库提供了一种简单的方法用来对数据驱动的进程进行建模,此方法支持对仅含串流 I/O(hls::streamhls::stream_of_blocks)的任务进行静态例化,这样就不必检查对 C++ 中的并发进程进行建模所必需的空串流。

提示: hls::task 还支持为 s_axilite 接口上的标量值提供稳定的输入,或者为 m_axi 接口上的阵列提供稳定的指针,如 数据驱动的 TLP 中未同步的 I/O 中所述。

GitHub 上的 simple_data_driven 提供了如下所示简单示例:

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);
}

请注意,顶层函数 odds_and_evens 使用串流输入和输出接口。这是纯串流内核。顶层函数包含:

  • s1 和 s2 均为线程本地的串流 (hls_thread_local),并且均用于连接任务通道任务 t1 和 t2。这些串流需作为线程本地的串流,这样在多次顶层调用之间才能保持处于活动状态。
  • t1、t2 和 t3 均为线程本地的 hls::task,分别用于执行 splitter 函数、odds 函数和 evens 函数。这些任务无限运行,用于处理其输入串流上的数据。无需同步。

但这类仅限串流的模型存在一些限制,如:

  • 您无法访问非本地存储器
  • 非串流数据(如标量、阵列和指针)可以作为参数来传入,前提是这些端口已通过 STABLE 编译指示声明为稳定端口。当前含 m_axi 接口的顶层指针只能使用 offset=off 选项来传递
    重要: 由于与 hls::task 之间不存在同步,因此标量、阵列和指针的读取时间间隔未知。所以编写代码时,需确保代码不依赖于这些端口的读取时机。
  • 您必须按并行任务规范来显式描述设计中的并行度
  • hls::task 必须始终在并行上下文中例化,不得嵌套在顺序上下文中
    • 如果您的顶层函数中使用 hls::task,那么该顶层函数就会成为并行上下文
    • 由于数据流区域是并行上下文,因此您可在其中例化 hls::task
    • 在顺序上下文中,如果您调用函数来例化任务,那么:
      • 该函数必须是并行上下文关联,如数据流区域
      • 必须由并行上下文中的常规数据流进程来生产和耗用任务输入串流和输出串流
    • 控制驱动的 TLP 可位于顶层、位于另一个任务驱动的 TLP 内或者位于顺序区域内
    • 数据驱动的 TLP 可位于顶层、位于另一个数据驱动的 TLP 内或者嵌套在两个控制驱动的任务之间
    • 控制驱动的 TLP 不得位于流水线内,也不得直接位于数据驱动的 TLP 内。在后一种情况下,它必须位于由数据驱动的任务所执行的顺序区域内
    • 数据驱动的 TLP 不得直接位于顺序、流水线或控制驱动的 TLP 内
    • 顺序区域或流水线只能位于控制或数据驱动的任务主体(而非控制或数据驱动的区域)内

hls::task 对象可与标准数据流样式的函数调用自由混用,这些函数调用可将数据移入和移出存储器(DRAM 和 BRAM)。任务还支持拆分通道 (hls::split) 与合并通道 (hls::merge),拆分通道支持一对多数据分发,用于构建工作程序池来处理数据串流,合并通道则支持多对一数据聚集。