生成流量用于软硬件仿真 - 2022.1 简体中文

Versal ACAP AI 引擎编程环境 用户指南 (UG1076)

Document ID
UG1076
Release Date
2022-05-25
Version
2022.1 简体中文

概述

本节旨在描述如何使用 AXI Traffic Generator 在所有仿真模式下对 AI 引擎阵列提供输入并从中捕获输出。在 AI 引擎仿真器中,输入数据激励是使用 PLIO 对象提供的,此对象用于指定包含数据的文本文件:

input_plio plin = input_plio::create("DataIn", adf::plio_32_bits, "data/input.txt");

虽然这样可使您的首次仿真快速就位,但此方法的主要限制在于,如果您要更改输入文件名用于其它仿真,就必须重新编译整个应用。因此可通过如下方法来避免文件名规范并依靠外部流量生成器在 PLIO 上生成数据流量:

input_plio plin = input_plio::create("DataIn", adf::plio_32_bits);

对于软硬件仿真,存在一项等效的功能特性可用于对此 PLIO 和 AXI4-Stream 接口的行为进行仿真。为此提供了 Python 和 C++ API 用于创建外部流量生成器,这些流量生成器将在任意仿真模式下无缝连接。

AI 引擎阵列的主要外部数据接口是 AXI4-Stream 接口。这些接口称为 PLIO,允许 AI 引擎检索数据、对数据进行操作并通过独立 AXI4-Stream 接口发回数据。AI 引擎的输入接口是 AXI4-Stream 使用者接口,输出则是 AXI4-Stream 生产者接口。为了在软硬件仿真期间与这些顶层接口进行交互,另外提供了补充性的 AXI4-Stream 模块。这些补充性模块称为 AXI Traffic Generator。

注释: PLIO 接口的宽度是一项重要的系统级别设计决策。此接口越宽,每个 PL 时钟周期内可发送的数据就越多。

标准用例

如果您开发 AI 引擎应用并且希望通过仿真(x86sim、aiesim、sw_emu 或 hw_emu)对其进行测试,那么您需要提供输入数据并收集输出数据,以便将这些数据与部分预定义的参考文件进行比较。此外,如果您的 AI 引擎 graph 与位于可编程逻辑(HLS C++ 或 RTL)中的内核交错,那么您还需要处理这些数据流中断。一般应用如下所示:

图 1. 一般 AI 引擎 + 可编程逻辑应用
在第一步中,您将 AI 引擎阵列中不包含的所有连接都替换为文本文件以生成流量:
图 2. 初始仿真框架
为了提升数据生成和验证的灵活性,您可以将必须通过流量生成器来独立管理的所有文本文件进行交换,从而在 PL 与 AI 引擎阵列之间通过连接到 Unix 套接字的 AXI4-Stream TLM 来达成动态仿真的通信。这些外部流量生成器的优势在于,它们无需修改即可直接在所有仿真框架内使用:
  • X86 仿真
  • AI 引擎仿真
  • 软件仿真
  • 硬件仿真
整体仿真框架如下:
图 3. 基于外部流量生成器的仿真

AI 引擎 graph 修改

在 graph 中无需进行任何有关内核连接的更改。外部流量生成器的调整是在 graph 的 I/O 处完成的,一般文本文件形式中只需将如下部分:
plin = input_plio::create("DataIn1",adf::plio_32_bits,"data/mm2s.txt");
clip_in = output_plio::create("clip_in",adf::plio_32_bits, "data/polar_clip_in.txt");
clip_out = input_plio::create("clip_out",adf::plio_32_bits,"data/polar_clip_out.txt");
plout = output_plio::create("DataOut1",adf::plio_32_bits, "data/s2mm.txt");
更改为如下避免文本文件名声明的编写方式即可:
plin = input_plio::create("DataIn1",adf::plio_32_bits);
clip_in = output_plio::create("clip_in",adf::plio_32_bits);
clip_out = input_plio::create("clip_out",adf::plio_32_bits);
plout = output_plio::create("DataOut1",adf::plio_32_bits);

输入/输出 plio 声明的第一个参数的重要性在于,它所表示的名称将在流量生成器一侧用于连接到正确的套接字。

一旦以 Python 或 C++ 编写完流量生成器之后,即可立即启动 X86 仿真和 AI 引擎仿真。

启动仿真包括将 aiesimulatorx86simulator 与外部流量生成器并行运行。

PL 内核更改

在思考 AI 引擎应用及其适用于系统仿真模式(软件和硬件)的环境时,需要对往来可编程逻辑一侧的数据传输进行建模。开始开发时,内核尚未准备就绪,无法在 sw_emu 或 hw_emu 框架内使用,因此无法创建赛灵思对象 (.xo) 文件以供在 Vitis 链接阶段中使用。我们必须在可编程逻辑内引入挂钩,以便将外部流量生成器连接到这些挂钩。赛灵思提供了一整套预编译的 .xo 文件,可用于满足此目的:
  • $(XILINX_VITIS)/data/emulation/XO/sim_ipc_axis_slave_32.xo, $(XILINX_VITIS)/data/emulation/XO/sim_ipc_axis_master_32.xo
  • $(XILINX_VITIS)/data/emulation/XO/sim_ipc_axis_slave_64.xo, $(XILINX_VITIS)/data/emulation/XO/sim_ipc_axis_master_64.xo
  • $(XILINX_VITIS)/data/emulation/XO/sim_ipc_axis_slave_128.xo, $(XILINX_VITIS)/data/emulation/XO/sim_ipc_axis_master_128.xo

您应将一组正确的 .xo 文件复制到工程上的正确位置,以便在 Vitis 链接阶段内,将其用于您的配置文件中。

链接阶段

在 Vitis 链接阶段 (v++ -l),先前定义的 .xo 文件将用于把相关计算单元连接到 AI 引擎 graph。system.cfg 配置文件的创建方式可保证计算单元的名称与您在 graph 中为 input_pliooutput_plio 定义的名称相匹配:
[connectivity]
nk=sim_ipc_axis_master:2:DataIn1.clip_out
nk=sim_ipc_axis_slave:2:DataOut1.clip_in


sc=DataIn1.M00_AXIS:ai_engine_0.DataIn1
sc=ai_engine_0.clip_in:clip_in.S00_AXIS
sc=clip_out.M00_AXIS:ai_engine_0.clip_out
sc=ai_engine_0.DataOut1:DataOut1.S00_AXIS

凭借此命名措施,即可确保所有仿真都使用同一个流量生成器。

对于软件仿真 (sw_emu) 和硬件仿真 (hw_emu),如果您熟悉 RTL 编码,即可采用 C++、Python 或 HDL 来编写外部流量生成器。

主机代码

主机代码的创建十分简单。由于其中并没有可编程逻辑内核,因此查找和运行 PL 内核的所有阶段以及为所有缓冲器对象分配存储器的部分都可跳过。剩余阶段仅包括:
  • 打开器件
  • 加载 xclbin 文件
  • 寄存 XRT 以连接到设计
  • 运行 AI 引擎 graph

编译主机代码后,即可对整个工程进行封装。运行仿真包括并行运行外部流量生成器和标准仿真启动。