自由运行的 PE - 2022.1 简体中文

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

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

流水线中的 PE 对流经的各项传输事务同步执行操作。对于每次 compute() 调用,PE 都将显式启动和停止一次。但当 PE 标记为 FREE_RUNNING 时(如 指南宏 中所述),它将具有如下硬件语义:

  • PE 不会根据传输事务或 compute() 调用来启动、停止或复位。它属于 HLS 内核,并具有 ap_none 控制接口,如块级控制协议中所述
  • 此接口只能包含 AXI4-Stream 实参或标量输入
  • PE 执行数据驱动的操作,并且仅对输入串流码字进行操作,而无法察觉传输事务的有效载荷大小
  • 在硬件比特流编程到器件中后,PE 立即开始执行
图 1. 自由运行

上图显示了自由运行的 PE 的图示。此加速器包含 2 个 PE,LdStr PE 包含全局存储器访问,fsk_incr 则是自由运行的 PE。在 compute() 作用域内,这些 PE 均通过下列两个 AXI4-Stream 接口来连接:AS 用于将码字从 LdStr 移至 fsk_incrXS 则为反馈路径。

此示例的代码如下所示。

class fsk_acc : public VPP_ACC<fsk_acc, NCU>
{
    ZERO_COPY(A);
    ZERO_COPY(X);
    SYS_PORT(A, DDR[0]);
    SYS_PORT(X, DDR[0]);
    FREE_RUNNING (fsk_incr);
public:
    static void compute(DT* A, DT* X, int sz);
    static void loadstore(DT* A, DT* X, hls::stream<DT>& AS, 
                          hls::stream<DT>& XS);
    static void fsk_incr(hls::stream<DT>& AS, hls::stream<DT>& XS);
};
Void fsk_acc::compute(DT* A, DT* X, int sz)
{
    static vpp::stream<DT> AS, XS;
    ldst(A, X, sz, AS, XS);
    fsk_incr(AS, XS);
}
void fsk_acc::ldst(DT* A, DT* X, int sz, hls::stream<DT>& AS, 
                   hls::stream<DT>& XS)
{
    for (int i = 0; i < sz; i++) {
        AS.write(A[i]);
    }
    for (int i = 0; i < sz; i++) {
        XS.read(X[i]);
    }
}
void fsk_acc::fsk_incr(hls::stream<DT>& AS, hls::stream<DT>& XS)
{
    DT val;
    AS.read(val);
    XS.write(val + 1);
}

LdSt PE 对 sz 码字执行操作,它可对全局存储器端口 A 和 X 分别执行读取和写入。而自由运行的 PE fsk_incr 则对 sz 不可知,仅对传入 AS 串流上的码字予以响应。

前文所述自由运行的语义能够显著简化自由运行的 PE 的实现,通常这样即可简化 FPGA 的使用和所需的布线资源。它串流流水线设计,其中所含中间 PE 可作为自由运行的 PE,从而仅对输入 AXI4-Stream 进行操作。

凭借任一流水线组合,只要启用硬件复制(NCU 大于 1),硬件即可包含任意数量的复制流水线,并且 compute() 作业可在可用流水线时隙上运行。这样应用层即可保持简单,并自动运行数据,使其穿过硬件中的多个流水线。