描述
Vitis HLS 会检测循环内的依赖关系:循环的相同迭代内的依赖关系为独立于循环的依赖关系,循环的不同迭代之间的依赖关系则为循环进位依赖关系。DEPENDENCE 编译指示允许您提供额外信息用于定义、抵消循环依赖关系,并允许循环以更低的时间间隔来进行流水打拍。
- 独立于循环的依赖关系
- 在单个循环迭代内访问相同元素。
for (i=1;i<N;i++) { A[i]=x; y=A[i]; }
- 循环进位依赖关系
- 从不同循环迭代内访问相同元素。
for (i=1;i<N;i++) { A[i]=A[i-1]*2; }
这些依赖关系会影响运算的调度时间,尤其是在函数和循环流水打拍期间。
在诸如建立变量相关阵列索引或需强制实施外部要求(例如,2 项输入从不采用相同索引)之类的情况下,依赖关系分析可能过于保守,无法滤除假性依赖关系。DEPENDENCE 编译指示允许您显式定义依赖关系并消除假性依赖关系。
重要: 如果实际上依赖关系并非假性 (false) 关系,那么指定假性依赖关系可能导致硬件错误。指定依赖关系前,请确认它是否正确(true 或 false)。
语法
将编译指示置于函数边界内定义依赖关系的位置。
#pragma HLS dependence variable=<variable> <class> \
<type> <direction> distance=<int> <dependent>
其中:
-
variable=<variable>
- (可选)指定为了确认依赖关系而需要考量的变量。重要: 对于与
m_axi
接口内其他实参捆绑的函数实参,不能指定dependence
。这是函数上的m_axi
接口的默认配置。并且除非结构体已解聚,否则也不能为结构体的元素指定依赖关系。 -
class=[array | pointer]
- (可选)指定需要澄清其中所含依赖关系的变量的类。有效值包括
array
或pointer
。提示:<class>
和variable=
不应一起指定,因为您可以在函数内为某一个变量或者某一类变量指定依赖关系。 -
type=[inter | intra]
- 有效值包括
intra
或inter
。指定依赖关系:-
intra
- 相同循环迭代内的依赖关系。当依赖关系
<type>
指定为intra
并且<dependent>
为 false 时,HLS 工具可在循环内自由移动操作,从而增大其可移动性并潜在改善性能或面积。当<dependent>
指定为 true 时,必须按指定顺序执行操作。 -
inter
- 不同循环迭代间的依赖关系。这是默认
<type>
。如果依赖关系 <type> 指定为inter
,并且<dependent>
为 false,那么它允许 HLS 工具并行执行多项操作,前提是函数或循环采用流水打拍或者循环已展开或部分展开,当<dependent>
指定为 true 时,则阻止此类并发操作。
-
-
direction=[RAW | WAR | WAW]
- 仅与循环进位依赖关系有关,用于指定依赖关系的方向:
-
RAW
(先写后读 - 真性依赖关系) - 写指令使用的值供读指令使用。
-
WAR
(先读后写 - 反依赖关系) - 读指令获取的值被写指令覆盖。
-
WAW
(先写后写 - 输出依赖关系) - 2 条写指令按顺序写入相同位置。
-
-
distance=<int>
- 指定阵列访问的迭代间距离。仅与循环进位依赖关系有关,其中依赖关系设为
true
。 -
<dependent>
- 指定
<dependent>
实参可用于指示依赖关系如为true
则需要强制实施,如为false
则应移除。但如果不指定该实参,则工具将返回警告,称未指定该值,并且假定值为false
。接受的值为true
或false
。
示例 1
在以下示例中,HLS 工具不知晓 cols
的值,并且保守假定在写入 buff_A[1][col]
与读取 buff_A[1][col]
之间始终存在依赖关系。在诸如此类的算法中,cols
几乎不可能为 0,但 HLS 工具无法就数据依赖关系做出任何判断。为了克服这一缺陷,您可使用 DEPENDENCE
编译指示来声明在循环迭代之间(在此示例中,针对 buff_A
和 buff_B
)没有依赖关系。
void foo(int rows, int cols, ...){
for (row = 0; row < rows + 1; row++) {
for (col = 0; col < cols + 1; col++) {
#pragma HLS PIPELINE II=1
#pragma HLS dependence variable=buff_A type=inter false
#pragma HLS dependence variable=buff_B type=inter false
if (col < cols) {
buff_A[2][col] = buff_A[1][col]; // read from buff_A[1][col]
buff_A[1][col] = buff_A[0][col]; // write to buff_A[1][col]
buff_B[1][col] = buff_B[0][col];
}
}
}
}
示例 2
移除 func
函数的 loop_1
的相同迭代中的 Var1
之间的依赖关系。
#pragma HLS dependence variable=Var1 type=intra false
示例 3
在 func
函数的 loop_2
中的所有阵列上定义依赖关系,以便告知 HLS 工具,在相同循环迭代内,所有读操作都必须发生在写操作之后 (RAW)。
#pragma HLS dependence class=array type=intra direction=RAW true