下图显示的单路径流水线示例包含 3 个 PE,分别为 AccLoad
、AccMul
和 AccStore
。PE AccLoad
和 AccStore
用于访问通过 M_AXI 通道存储在全局存储器内的数据。请注意,加速器类头文件会将 inputData
和 outputData
端口绑定到 DDR[0]。在此情况下,这些 PE 使用 ZERO_COPY
代码来直接访问全局存储器。
图 1. 单路径流水线
此图的代码示例如下所示。
typedef vpp::stream<DT> STREAM;
class Acc : public VPP_ACC<Acc, NCU>
{
ZERO_COPY(inputData);
ZERO_COPY(outputData);
SYS_PORT(inputData, DDR[0]);
SYS_PORT(outputData, DDR[0]);
public:
static void compute(DT* inputData, DT* outputData);
static void AccLoad(DT* inputData, STREAM& aStr,
STREAM& bStr, STREAM& iStr);
static void AccMul(STREAM& aStr, STREAM& bStr,
STREAM& cStr);
static void AccStore(STREAM& iStr, STREAM& cStr,
DT* outputData);
}
void Acc::compute(DT* inputData, DT* outputData)
{
static STREAM aStr, bStr, cStr, iStr;
AccLoad (inputData, aStr, bStr, iStr);
AccMul (aStr, bStr, cStr);
AccStore(iStr, cStr, outputData);
}
void Acc::AccMul(STREAM& aStr, STREAM& bStr, STREAM& cStr)
{
for (int i = 0 ; i < N_WORDS ; i ++) {
int res = aStr.read() * bStr().read();
cStr.write(res);
}
}
compute()
函数体表示硬件流水线。有 3 个对应于 PE 的函数调用,并且声明了 4 个局部串流变量: -
AccLoad
用于提取inputData
并写入 3 条串流 -
AccMul
用于处理输入串流aStr
和bStr
中的固定数量的码字,并将结果写入cStr
-
AccStore
函数将进一步处理iStr
和cStr
中的传入数据,以在连接到 DDR[0] 端口的outputData
上写入结果。
此系统中的 PE 将以同步方式执行,这样数据流将以流水打拍方式传递。每次调用 compute()
都将加载 inputData
并为新传输事务触发所有 PE。每次调用 compute()
都要求每个 PE 完成仅一次(起始和停止)。此示例显示的是含 3 个阶段的流水线或者单路径内的链式 PE。因此用户只需采用简单的 C++ 编码样式即可创建硬件流水线。
请注意,VPP_ACC
类允许使用 NCU 参数来复制此类流水线。如果 NCU 大于 1,那么硬件即可包含任意数量的已复制的流水线。在下一个可用的流水线时隙内,会自动加载对 compute()
的调用。这样应用层即可保持简单且便于维护,并自动运行数据,使其穿过硬件中的多个流水线。