描述
您可展开循环以创建多个独立操作而非单个操作集。UNROLL 编译指示会通过在 RTL 设计中创建循环主体的多个副本来变换循环,从而允许部分或全部循环迭代并行发生。
C/C++ 语言函数中的循环默认情况下全部保持收起状态。收起循环时,综合会为循环的单次迭代创建逻辑,RTL 设计会为序列中循环的每次迭代都执行此逻辑。循环的迭代执行次数由循环归纳变量来指定。迭代次数也可能受到循环主体内的逻辑影响(例如,对循环出口变量条件应用 break
条件或修改)。您可使用 UNROLL 编译指示展开循环以便增加数据访问和吞吐量。
UNROLL 编译指示支持将循环完全展开或部分展开。完全展开循环会在 RTL 内为每个循环迭代创建一份循环主体副本,因此整个循环可并发运行。部分展开循环允许您指定因子 N 以创建 N 份循环主体副本,并相应减少循环迭代。
部分循环展开不要求 N 为最大循环迭代计数的整数因子。Vitis HLS 工具会添加出口检查以确保部分展开的循环的功能与原始循环相同。例如,给定以下代码:
for(int i = 0; i < X; i++) {
pragma HLS unroll factor=2
a[i] = b[i] + c[i];
}
break
构造函数用于确保功能保持不变,并且循环会在相应的点退出。for(int i = 0; i < X; i += 2) {
a[i] = b[i] + c[i];
if (i+1 >= X) break;
a[i+1] = b[i+1] + c[i+1];
}
在以上示例中,由于最大迭代计数 X
可用,因此 HLS 工具可能无法判定其值,故而它给部分展开的循环添加了出口检查和控制逻辑。但如果您已知指定的展开因子(在此示例中为 2)是最大迭代计数 X
的整数因子,那么 skip_exit_check
选项允许您移除出口检查和关联的逻辑。这有助于最大限度降低面积并简化控制逻辑。
config_unroll
命令来控制。语法
将 C 语言源代码中的编译指示置于要展开的循环主体内。
#pragma HLS unroll factor=<N> skip_exit_check off=true
其中:
-
factor=<N>
- 指定非零整数,表示已请求部分展开。循环主体将重复指定次数,迭代信息将进行相应的调整。如不指定
factor=
,则循环将完全展开。 -
skip_exit_check
- 可选关键字,仅当使用
factor=
指定部分展开时才适用。根据循环迭代计数为已知还是未知来判断是否消除出口检查:- 固定边界
如果迭代计数为因数的倍数,则不执行出口条件检查。
如果迭代计数并非因数的整数倍,则该工具将执行以下操作:
- 阻止展开。
- 发出警告,称必须执行出口检查后才能继续。
- 变量边界
移除出口条件检查。您必须确保:
- 变量边界为因数的整数倍。
- 实际上无需出口检查。
- 固定边界
-
off=true
- 为指定循环禁用展开。
示例 1
以下示例在 foo
函数内完全展开 loop_1
。将编译指示置于 loop_1
主体内,如图所示。
loop_1: for(int i = 0; i < N; i++) {
#pragma HLS unroll
a[i] = b[i] + c[i];
}
示例 2
此示例指定展开因子为 4,以部分展开 foo
函数的 loop_2
,并移除出口检查。
void foo (...) {
int8 array1[M];
int12 array2[N];
...
loop_2: for(i=0;i<M;i++) {
#pragma HLS unroll skip_exit_check factor=4
array1[i] = ...;
array2[i] = ...;
...
}
...
}