为 AI 引擎设计使用流量生成器 - 2023.2 简体中文

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

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

概述

本节旨在描述如何使用 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 引擎应用时,您可在仿真中单独对其进行测试(x86simulatoraiesimulator),或者在仿真中将其作为系统工程的一部分来进行测试(sw_emuhw_emu)。无论如何,您都需要从预定义的参考文件发送输入数据,并在独立文件中捕获输出数据。此外,如果您的 AI 引擎计算图与位于可编程逻辑(HLS C++ 或 RTL)中的内核交错,那么您还需要处理这些数据流中断。例如,完整的系统设计可能如下图所示:

图 1. AI 引擎 + 可编程逻辑应用
在第一步中,您将 AI 引擎阵列中不包含的所有连接都替换为文本文件以提供输入数据或捕获输出数据:
图 2. 初始仿真框架

为了提升数据生成和验证的灵活性,您可以将文本文件与外部流量生成器进行交换,以便在 PL 与 AI 引擎阵列之间通过连接到 UNIX 套接字的 AXI4‑Stream TLM 来启用动态仿真的通信。这些外部流量生成器的优势在于,它们无需修改即可直接在所有仿真框架内使用:

  • x86 仿真
  • AI 引擎仿真
  • 软件仿真
  • 硬件仿真

整体仿真框架如下图所示:

图 3. 基于外部流量生成器的 AI 引擎仿真流程

每个 AI 引擎块均可使用以 Python、MATLAB 或 C++ 编写的外部测试激励文件来确认。在 GitHub 上的 External-Traffic-Generator-AIE 教程中可找到实现示例。

对于系统工程,通过整合 AI 引擎计算图应用与 PL 内核,将数据移动程序替换为外部流量生成器源端和宿端,而 PL 处理内核则是连接到 AI 引擎内核的串流内核,如下图所示。

图 4. 完整系统仿真

流量生成器也用于将数据馈送并刷新到含 PL 逻辑的完整系统中。您无需对用于将数据写入 DDR 存储器的 PS 代码进行建模,也无需对移入 AI 引擎内核的数据进行建模。此方法会将数据移动程序替换为动态生成数据的外部流量生成器。以下章节逐步描述了将外部流量生成器与 AI 引擎系统对接以执行仿真流程所需的更改。

AI 引擎计算图修改

在计算图中无需进行任何有关内核连接的更改。只需将流量生成器定义为来自 PLIO 端口的数据源即可,如下所示。以下示例基于 AI 引擎内核与计算图编程指南(UG1079)使用 RTL 编程逻辑的设计流程中的代码。

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 声明的第一个参数的重要性在于,它所表示的名称将在流量生成器一侧用于连接到正确的套接字。

x86 仿真和 AI 引擎仿真可启动并搭配流量生成器来工作。启动仿真需与外部流量生成器并行运行 aiesimulatorx86simulator

PL 内核更改

考量 AI 引擎应用及其适用于系统仿真模式(swhw)的环境时,需要对往来可编程逻辑一侧的数据传输进行建模。开始开发时,内核尚未准备就绪,无法在 sw_emuhw_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 引擎计算图。hw_link.cfg 配置文件的创建方式可保证计算单元的名称与您在计算图中为 input_pliooutput_plio 定义的名称相匹配。例如,以下代码与上述示例中的 PLIO 分配相匹配:

[connectivity]

nk=sim_ipc_axis_master_32:1:in_interpolator
nk=sim_ipc_axis_slave_32:1:out_classifier
nk=polar_clip:1:polar_clip

sc=in_interpolator.M00_AXIS:ai_engine_0.in_interpolator
sc=ai_engine_0.out_interpolator:polar_clip.in_sample
sc=polar_clip.out_sample:ai_engine_0.in_classifier
sc=ai_engine_0.out_classifier:out_classifier.S00_AXIS

--connectivity.nk 命令格式为内核名称(如 sim_ipc_axis_master_32)、要创建的内核实例数或计算单元数 (1) 以及每个内核实例的名称 (in_interpolator)。如需了解有关此命令的更多信息,请参阅 --connectivity 选项

--connectivity.sc 命令用于定义 PL 内核之间或者 PL 内核与 AI 引擎计算图之间的串流连接。在以上示例中,流量生成器 in_interpolator.M00_AXIS 的输出端口连接到 ai_engine_0.in_interpolator 的输入端口。

凭借此命名方法,即可确保对多轮仿真使用相同的外部流量生成器。对于软件仿真 (sw_emu) 和硬件仿真 (hw_emu),如果您熟悉 RTL 编码,即可采用 C++、Python、MATLAB 或 HDL 来编写外部流量生成器。

主机代码

主机代码的创建十分简单。由于其中并没有可编程逻辑内核,因此查找和运行 PL 内核的所有阶段以及为所有缓冲器对象分配存储器的部分都可跳过。剩余阶段仅包括:

  • 打开器件
  • 加载 xclbin 文件
  • 寄存 XRT 以连接到设计
  • 运行 AI 引擎计算图

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