处理 HLS 内核的功能模型 - 2023.2 简体中文

Vitis 统一软件平台文档 应用加速开发 (UG1393)

Document ID
UG1393
Release Date
2023-12-13
Version
2023.2 简体中文

在硬件仿真期间,AMD Vitis™ HLS 内核的功能模型的使用方法属于高级用例,它支持在功能模式下进行内核编译,使用围绕 C 语言代码的 SystemC 封装文件来生成 XO。每个 IP(无论是否由 HLS 编译器生成)都可包含多种类型的仿真模型,例如,TLM 和 RTL,并由 allowed_sim_models 属性来指明其类型。但 IP 需指明其中哪个模型是当前模型,该模型由 selected_sim_model 属性来定义。此处所述方法支持您可以在 HLS 编译器生成输出 IP 或 XO 时,指定希望选中哪种类型的仿真模型。

HW Emulation 主要用于硬件内核调试,可提供内核活动的周期精确的详细视图。功能 (TLM) 模型能在功能模式下(而不是使用 RTL 代码)编译所需内核,从而加速仿真,并且可在 RTL 尚未可用时用作为早期模型。由于无需完整执行 C 语言到 RTL 综合,因此内核编译时间更短,并且由于对 C 语言代码进行仿真而不是进行 RTL 仿真,因此执行时间也更短。您也可以在硬件仿真中混用 C 语言和 RTL 内核以加速 RTL 块的调试。

该功能模型功能特性支持对 AXI4‑Stream 接口 (axis) 和 AXI4 存储器映射接口 (m_axi) 进行建模,并支持对 AXI4‑Lite 接口 (s_axilite) 进行寄存器读写操作。但不同于周期精确的模型,凭借此方法,内核将成为纯功能内核,无时延信息。

用户 HLS 函数使用 TLM 接口封装到 SystemC 模块内,根据生成的代码创建 IP,这样即可生成兼容 HW_EMU 的 XO,可供在 IP integrator 内用于通过硬件仿真流程来拼接 v++ 链接设计。这样还可支持 Wrapper IP 与其他 RTL 和 SystemC 模型进行交流。因此以功能模式编译的 HLS C/C++ 内核将在仿真期间拥有 TLM 传输事务,用户可在存储器模型(如 DDR 存储器)与 TLM 内核之间看到流量。

提示: 功能模型使用 C 语言代码执行内核的 C 语言仿真。不同于周期精确的模型,内核将成为纯功能内核,无时延信息。但在硬件仿真期间,您仍可通过 TLM 接口看到边界传输事务。

利用功能模型执行 XO 生成

重要: v++ -c --mode hls 命令不支持功能仿真模型,如下所述。要生成 IP 或内核来使用 TLM 模型进行功能仿真,必须使用 v++ -c -t=hw_emu 命令。

v++ -c -t=hw_emu 编译步骤中创建硬件仿真 (hw_emu) XO 文件期间,您可提供选项来为 PL 内核启用功能仿真,这样即可生成 XO 并且在 C 语言代码中包含 SystemC 封装文件。您需要在编译期间提供 --advanced.param compiler.emulationMode=func 选项,如 --advanced 选项 中所述。

此项默认设置为 compiler.emulationMode=rtl。构建 XO 时,您可使用 --advanced.param compiler.emulationMode=rtl 提供默认值,这样即可为特定 XO 轻松切换 RTL 和 TLM 模型;或者,可以在为功能仿真执行构建时,移除 --advanced_param 命令以复原默认值,并重新添加。在上述任一情况下,如果您要在 RTL 与 TLM 之间来回切换模型,都必须使用 v++ -c -t=hw_emu 命令重新编译此 XO。

生成的功能仿真 XO 使用 v++ --link 命令来链接,与常规 XO 一样。如需获取示例,请访问 GitHub 上的 mm_stream_func_mode

功能模型的限制

  1. 在 Windows 操作系统上不支持功能模式。
  2. HLS 中原有的限制在此处同样适用。例如,HLS 不支持双指针,因此功能模型无法识别此类指针。
  3. 如果 HLS 设计从含有单个内核 ap_start(例如,ap_ctrl_chain)的主机对多次数据迭代执行操作,那么从内核代码触发重启时,此设计可能无法正常执行操作。邮箱功能正常。
  4. 更改由于在功能模型 x86 的应用二进制接口 (ABI) 中,FPGA 不可用,因此,ABI 发生了更改。对于使用 ABI 的大部分最优化而言,需在功能编译器中将其禁用。
  5. 通过强制类型转换/过程间使用来限制 DDR 分析:

    1. 将 DDR 存储器指针从标量类型强制转换为其他类型无效。
      kernel void vadd(size_t a_s,size_t b_s,size_t c){
       int* a = (size_t)a;
       int* b = (size_t)b;
       int* c = (size_t)c;
       for(int i=0; i < 64; i++){
       c[i] = a[i] + b[i]; 
       } 
      }
    2. 跨过程上下文进行 DDR 存储器指针高速缓存无效。
      class Cache{
      int* local;
      Cache(int *a) : local(a){}
      int read(){}
      void write(int x){}
      };
      kernel void vadd(int *a,int *b, int *c){
       Cache ca(a);
       for(int i=0; i < 64; i++){
       c[i] = ca.read() + b[i]; 
       } 
      }
  6. 二进制中实现的 HLS 功能特性和耗用 DDR 存储器访问均不受支持,需重写功能。
  7. 在功能模型中不会自动检测突发传输事务。

处理功能模型时的编码准则:对于需在每次迭代内多次运行并且需将静态值复位为 0 的内核计算单元,您必须在进入内核函数时,初始化所有静态变量。以下示例显示了返回错误的代码,并演示了建议的方法:

// User code that errors out 
static int i = 0;
void hls_kernel_logic(...) {
 ...
}
// Recommended 
static int i = 0;
void hls_kernel_logic(...) {
 i = 0;
 ...
}