Vitis HLS 会尽早调度逻辑和函数,以减少时延,同时使估算的时钟周期保持在用户指定的周期之下。为此,它会将尽可能多的逻辑运算和函数调度为并行运行。但它并不会将循环也调度为并行执行。
如果对以下代码示例进行综合,则先调度 SUM_X
循环,然后调度 SUM_Y
循环,即使 SUM_Y
循环无需等待 SUM_X
循环完成后再开始运算,也仍调度为在 SUM_X
之后运行。
#include "loop_sequential.h"
void loop_sequential(din_t A[N], din_t B[N], dout_t X[N], dout_t Y[N],
dsel_t xlimit, dsel_t ylimit) {
dout_t X_accum=0;
dout_t Y_accum=0;
int i,j;
SUM_X:for (i=0;i<xlimit; i++) {
X_accum += A[i];
X[i] = X_accum;
}
SUM_Y:for (i=0;i<ylimit; i++) {
Y_accum += B[i];
Y[i] = Y_accum;
}
}
由于循环边界(xlimit
和 ylimit
)不同,因此无法合并。通过将循环置于不同函数内(如以下代码示例所示),即可实现相同功能,并且可并行调度这 2 个循环(在函数内部)。
#include "loop_functions.h"
void sub_func(din_t I[N], dout_t O[N], dsel_t limit) {
int i;
dout_t accum=0;
SUM:for (i=0;i<limit; i++) {
accum += I[i];
O[i] = accum;
}
}
void loop_functions(din_t A[N], din_t B[N], dout_t X[N], dout_t Y[N],
dsel_t xlimit, dsel_t ylimit) {
sub_func(A,X,xlimit);
sub_func(B,Y,ylimit);
}
如果对前述示例进行综合,则时延为顺序循环示例的一半,因为现在这些循环(作为函数)可并行执行。
dataflow
最优化同样可在顺序循环示例中使用。此处演示了在函数中捕获循环以发挥其并行性的原理,在此处示例中无法使用 dataflow
最优化。例如,在较大的示例中,对位于顶层的所有循环和函数应用 dataflow
最优化,存储器置于每个顶层循环和函数之间。