加速器的异步主机控制 - 2022.1 简体中文

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

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

VSC 模式允许利用包含用户定义的硬件流水线的 CU 对加速器进行编译,如 构建硬件 中所述。此类流水线由通过 AXI4-Stream 彼此相连的 PE 组成,并且也可以连接到平台端口(AXI4 连接),例如,全局存储器或 IO 接口(如以太网 QSFP 端口)。平台将提供 IP 用于将此类接口转换为 AXI4-Stream 端口,这些端口即可连接到用户定义的流水线中的 PE。

通过使用 VSC,即可在运行时从主机 CPU 中运行的应用,将此类硬件流水线轻松配置为动态更改处理行为。以下描述了此类加速器的创建方式。下图中显示了系统组合示例。

图 1. 加速器实现

Eth_RxEth_Tx 模块通常为平台 IP,用于将 AXI4-Stream 码字转换为以太网包。这些模块也可能是含用户定义的 AXI4 接口的定制 IP。

加速器流水线其余部分则是通过 VSC 使用 AXI4-Stream 连接来创建的,如白框中所示。流水线中的 PE 均为用户定义的功能,例如,包处理功能(如互联网协议包筛选器)。在此示例中,有一条创建的流水线包含两项任务,即分别名为 modsmp 的 PE。此外,系统还包含另一个控制 PE,其中具有到这些流水线 PE 的 AXI4-Stream 连接。以下提供的加速器代码示例中,左侧为 .hpp 文件,右侧则是 .cpp 文件。

// -- file: ETH.hpp --
#include "vpp_acc.hpp"
class ETH : public VPP_ACC<ETH,1>
{
public:
    ZERO_COPY(dIn);
    ZERO_COPY(dOut);

    SYS_PORT(dIn,  MEM_BANK0);
    SYS_PORT(dOut, MEM_BANK1);

    FREE_RUNNING(fsk_mod);
    FREE_RUNNING(fsk_smp);
    FREE_RUNNING(eth_rx);
    FREE_RUNNING(eth_tx);
    
    static void compute(int cmd, Pkt* dIn, Pkt* dOut);

    static void control(...
    static void fsk_mod(...
    static void fsk_smp(...
    static void eth_tx(...
    static void eth_rx(...
};
// -- file: ETH.cpp --
void ETH::compute(int cmd, Pkt* dIn, Pkt* dOut)
{
    static IntStream dropS("drop");
    static IntStream addS("add");
    static IntStream reqS("req");
    static PktStream smpS("smp");
    static BitStream getS("get");
    static IntStream sntS("snt");
    static PktStream Ax("Ax", /*post_check=*/false);
    static PktStream Bx("Bx", /*post_check=*/false);
    static PktStream Cx("Cx", /*post_check=*/false);
    
    control(cmd, dIn, dOut,
            dropS, addS, reqS, smpS, getS, sntS);
    eth_rx (Ax);
    fsk_mod(Ax, Bx, dropS, addS);
    fsk_smp(Bx, Cx, reqS, smpS);
    eth_tx (Cx, getS, sntS);
}

在此示例中,定义了 5 个 PE,包括 eth_txeth_rx 用于模仿 AXI4-Stream 中的接收码字和发射码字中的平台 IP 行为。compute() 作用域在这些 PE 之间使用 AXI4-Stream 连接来实现加速器流水线。control PE 可在这些串流上发送命令码字,而任务 PE(fsk_modfsk_smp)则监控这些命令 AXI4-Stream 并通过更改行为来做出响应。fsk_smp PE 的响应方式则是对请求的包数量进行采样并返回给 control PE。fsk_mod PE 的响应方式是给包数据添加值,或者丢弃从 Eth_Rx 传递到 Eth_Tx 的包。

流水线 PE fsk_modfsk_smp, 属于 FREE_RUNNING 的 PE(如 指南宏 中所述),因为这些 PE 永不停止,并按其输入串流中的码字来驱动其操作。

control PE 通过两条 SYS_PORT 连接与主机 CPU 进行沟通,这两条连接分别对应于输入 (dIn) 和输出 (dOut) 的接口实参数据指针,以及标量命令实参 (cmd)。control PE 并非自由运行,且会对来自主机 CPU 的 compute() 调用做出响应。此系统组合完全由用户定义,包括命令的性质以及对应的 PE 功能。

此处显示了主机代码快照,在 GitHub 上还提供了完整示例。

// -- file: host.cpp --
#include "vpp_acc_core.hpp" // required
#include "ETH.hpp"
int config_sample(int sz)
{
    printf("main: sample %d\n", sz);

    Pkt* sample  = (Pkt*)ETH::alloc_buf(sz * sizeof(Pkt), vpp::output);
    Pkt* config  = (Pkt*)ETH::alloc_buf(sizeof(Pkt), vpp::input);
    config[0].dt = sz;

    auto fut = ETH::compute_async(cmd_sample, config, sample);
    fut.get();
    print_sample(sample, sz);
    int pkt_nr = sample[0].nr;
    ETH::free_buf(config);
    ETH::free_buf(sample);
    return pkt_nr;
}

由 VSC 主机代码所发出的作业命令(尤其是使用 compute_async() API 发出的命令)支持控制 PE 转换此命令并通过命令串流将配置码字按序传递到流水线 PE。此快照显示了发出包采样命令的用户定义 API。必需的 szsample 缓冲器是在运行时分配的,compute_async() 调用将触发控制 PE 以捕获包的 sz 数量,并将码字返回到主机。由 compute() 返回的 fut 在主机代码中保持阻塞状态,直至结果可用为止。但 compute_async() 正如其名,表示触发加速器的异步调用。一旦采样的码字返回并经主机处理后,即可清空对应的缓冲器。

在此例中,由于主机控制并非 compute 作业的连续流水线,而只是偶发的非时序关键型作业,因此 send_while/receive_all 线程将不会对其加以管理。改由应用使用 vpp_acc_core.hpp 中定义的 compute_async() API 来管理同步。

重要:vpp_acc_core.hpp 头文件只需包含在主机代码文件内,并置于所包含的任何 vpp_acc.hpp 之前即可。

通过 VSC,即可从主机 CPU 对此类硬件流水线进行组合与异步控制。此类加速器的应用方式之一是 NIC 卡上的包处理加速器。例如,X3 Hybrid 平台可提供以太网发射和接收 IP,通过 MAC 接口将到达 QSFP 端口的以太网数据包转换为 AXI4-Stream。此外,NIC 接口允许加速器通过 PCIe 向已连接的主机 CPU 提供数据,或者可使用主机到存储器的访问通过 PCIe 来直接访问主机 CPU 存储器。通过使用 VSC,集合在 PL 上组合加速器数据包处理流水线,并且可由 CPU 通过 PCIe 来进行异步控制。