概述
本节描述了如何将外部流量生成器与 AI 引擎组件对接。并行启动仿真器与流量生成器即可使用外部流量生成器运行仿真。流量生成器可以 Python、MATLAB 或 C++ 来编写,并且可使用这些语言的多线程功能。随后,必须将 AI 引擎编写为在仿真期间搭配流量生成器来运行。以下步骤描述了如何将流量生成器对接到 AI 引擎计算图内以便单独执行 AI 引擎仿真或完整系统仿真流程 (hw_emu/sw_emu)。
为了将外部流量生成器与 AI 引擎组件对接,您需要在以 Python、MATLAB 或 C++ 编写的外部脚本或源代码中使用某些 API:
使用 Python 或 Matlab API
您必须使用专用 API 来编写 Python 脚本,以便将外部流量生成器与运行 AI 引擎计算图的 AI 引擎仿真进程对接。
# Mandatory
import os, sys
import multiprocessing as mp
import threading
import struct
from aie_input_plio import aie_input_plio
from aie_output_plio import aie_output_plio
# Optional for ease of use
import numpy as np
import logging
Python 流量生成器使用 编写 Python 流量生成器 中所述的 API。如需了解 MATLAB API 描述,请参阅 以 MATLAB 编写流量生成器。
使用以下步骤将外部流量生成器数据集成到计算图中:
- 修改计算图代码以声明 PLIO,但在 PLIO 构造函数中不指定基于 PLIO 的数据文本文件。这是外部流量生成器正常工作所必需的。记录 PLIO 构造函数的名称(第一个实参)。这些名称将用于连接外部流量生成器,应使用同样的名称在外部流量生成器中创建端口:
plin = input_plio::create("DataIn1",adf::plio_32_bits); plout = output_plio::create("DataOut1",adf::plio_32_bits);
- 在 Python 脚本中例化对应的 AXI 主接口与从接口连接。这将确立到计算图的 PLIO 端口的连接:
pl_in = aie_input_plio("DataIn1", 'int16') pl_out = aie_output_plio("DataOut1", 'int16')
提示: 您需要在对象创建期间指定 PLIO 数据类型。 - 向 AI 引擎发送数据。
在 Python 脚本中必须设置要发送到 AI 引擎计算图中的 PLIO 端口的数据。您可使用
send_data()
API 以列表格式发送数据。plin.send_data send_data(<data_list>, tlast)
-
接收来自 AI 引擎的数据。
使用
receive_data_with_size()
API 接收来自 AI 引擎的数据。此 API 会返回recv_data
中接收到的来自以下示例的值。这是阻塞 API,将等待直至接收到所期望的数据字节数为止。如需了解更多信息,请参阅 编写 Python 流量生成器。recv_data = plout.receive_data_with_size(<expected_bytes>)
使用 C++ 流量生成器 API
使用 C++ 语言来实现外部流量生成器时,需要各种头文件才能在外部流量生成器源代码中使用某些库。适用于处理这些库的头文件包括:
# For the traffic generator
#include "xtlm_ipc.h"
#include <thread>
此外,C++ 流量生成器还会使用 xtlm_ipc
源文件中提供的 API。如需获取 API 及其对应用法的列表,请参阅 以 C++ 编写流量生成器。
Makefile 依赖关系如下所述:
# Libraries directories
PROTO_PATH=$(XILINX_VIVADO)/data/simmodels/xsim/2023.1/lnx64/6.2.0/ext/protobuf/
IPC_XTLM= $(XILINX_VIVADO)/data/emulation/ip_utils/xtlm_ipc/xtlm_ipc_v1_0/cpp/src/
IPC_XTLM_INC= $(XILINX_VIVADO)/data/emulation/ip_utils/xtlm_ipc/xtlm_ipc_v1_0/cpp/inc/
LOCAL_IPC= $(IPC_XTLM)../
LD_LIBRARY_PATH:=$(XILINX_VIVADO)/data/simmodels/xsim/2023.1/lnx64/6.2.0/ext/protobuf/:$(XILINX_VIVADO)/lib/lnx64.o/Default:$(XILINX_VIVADO)/lib/lnx64.o/:$(LD_LIBRARY_PATH)
# Kernel directories
PLKERNELS_DIR := ../../pl_kernels
PLKERNELS := $(PLKERNELS_DIR)/polar_clip.cpp
PLHEADERS := $(PLKERNELS_DIR)/polar_clip.hpp $(PLKERNELS_DIR)/s2mm.hpp $(PLKERNELS_DIR)/mm2s.hpp
# XTLM source files
IPC_SRC := $(LOCAL_IPC)/src/axis/*.cpp $(LOCAL_IPC)/src/common/*.cpp $(LOCAL_IPC)/src/common/*.cc
# Compiler/linker flags
INC_FLAGS := -I$(LOCAL_IPC)/inc -I$(LOCAL_IPC)/inc/axis/ -I$(LOCAL_IPC)/inc/common/ -I$(PROTO_PATH)/include/ -I$(PLKERNELS_DIR) -I$(XILINX_HLS)/include
LIB_FLAGS := -L$(PROTO_PATH)/ -lprotobuf -L$(XILINX_VIVADO)/lib/lnx64.o/ -lrdizlib -L$(GCC)/../../lib64/ -lstdc++ -lpthread
# Compilation
compile: main.cpp $(PLHEADERS) $(PLKERNELS)
$(GCC) -g main.cpp $(PLKERNELS) $(IPC_SRC) $(INC_FLAGS) $(LIB_FLAGS) -o chain
在 AI 引擎组件中使用 C++ API 集成外部流量生成器的步骤如下所述:
- 在计算图代码中声明外部 PLIO,如下所示:
plin = input_plio::create("DataIn1",adf::plio_32_bits); plout = output_plio::create("DataOut1",adf::plio_32_bits);
- 例化 AXI 主接口和发送器。
xtlm_ipc::axis_master plin("DataIn1"); xtlm_ipc::axis_slave plout("DataOut1");
- 准备数据。这是用户逻辑。
- 发送数据。
如果您倾向于不对数据发送加以精细控制,则可使用一个简单的 API。
std::vector<char> data; // The sender API expects data to be in the form of vector of char
C++ XTLM 库提供了实用工具转换 API,以便将用户可读的数据类型轻松转换为字节阵列:
std::vector<char> type std::vector<char> byte_array = plin.uInt8ToByteArray(user_list)
此处
uint8
是用户数据类型,包含uint8
类型的用户列表/阵列,例如,std::vector<uint8> user_list;
。如需了解有关转换 API 的更多详情,请查阅 以 C++ 编写流量生成器。// Write a user logic to fill in the data // Send the data using send_data() API call plin.send_data(byte_array, tlast)
对于需要对 AXI4‑Stream 进行细粒度控制的高级用户,请参阅 高级 C++ 流量生成器 API。
- 接收数据。
如果您无需精细控制,有一个简单的 API 可供您使用。它会以字节阵列格式 (
std::vector<char>
) 返回数据,并等待直至接收到期望的data_size
为止。std::vector<char> data; // create empty vector of char plout.receive_data_with_size(data, data_size);
C++ 库提供了另一组实用工具转换 API,以便将接收到的字节阵列转换为用户可读的数据格式。例如:
std::vector<int8> recv_data; recv_data = plout .byteArrayTouInt8(data)
对于需要对 AXI4‑Stream 进行高精度控制的高级用户,请参阅 高级 C++ 流量生成器 API。
如需了解外部流量生成器 CPP 代码中的 API 及其用法的更多详情,请参阅以 C++ 编写流量生成器。
C++ 流量生成器的有趣之处在于,HLS 内核一旦创建完成,即可立即使用和测试,无需在 .xo
文件内进行综合。这样您无需重新创建 .xclbin
文件即可给自己的仿真添加更多真实性和灵活性。
使用 SystemVerilog 流量生成器 API
您还可将流量生成器从外部 SystemVerilog/Verilog 流量生成器和测试激励文件驱动到 aiesimulator
或 x86simulator
。
在集成流量生成器模块前,请在计算图中声明外部 PLIO。
pl_in0 = adf::input_plio::create("in_classifier",adf::plio_32_bits);
out0 = adf::output_plio::create("out_interpolator",adf::plio_32_bits);
要在 SystemVerilog/Verilog 流量生成器与 AI 引擎计算图的外部 PLIO 之间建立连接,xtlm_ipc
SystemC 模块不可或缺。外部 AI 引擎封装文件是基于 ADF 计算图中的外部 PLIO 声明来生成的。请遵循以下步骤来为 AI 引擎生成此封装文件模块。
-
以下命令可用于执行 ADF 计算图编译,以生成
scsim_config.json
文件,此文件驻留在work/config/scsim_config.json
目录中。此配置文件包含有关计算图中声明的 PLIO 的信息。aiecompiler --platform=$(PLATFORM) -v -log-level=3 --pl-freq=500 -include=./aie --output=graph.json aie/graph.cpp
- 此配置文件作为实参传递给 ${XILINX_VITIS}/data/emulation/scripts/gen_aie_wrapper.py 中可用的 Python 脚本,以生成基于 Verilog 的 AI 引擎封装文件模块。如需了解有关如何生成 AI 引擎封装文件模块的更多详情,请参阅 外部 RTL 流量生成器和 AI 引擎仿真。
- 生成 AI 引擎封装文件模块后,您需要在外部测试激励文件中将其例化,以在 SystemVerilog/Verilog 流量生成器与 AI 引擎计算图 PLIO 之间建立连接。如需了解有关如何将封装文件模块集成到外部 RTL 测试激励文件中的详情,请参阅 在测试激励文件中例化 AI 引擎封装文件。
建立连接后,即可与 AI 引擎仿真或 x86 仿真器并行启动 HDL 仿真。如需了解有关如何启动 HDL 仿真的详情,请参阅 将 RTL 流量生成器与 AI 引擎仿真一起运行。