pragma HLS dependence
Description
The DEPENDENCE
pragma is used to provide additional information that can
overcome loop-carry dependencies and allow loops to be pipelined (or pipelined with lower
intervals).
Vivado HLS automatically detects dependencies:
- Within loops (loop-independent dependence), or
- Between different iterations of a loop (loop-carry dependence).
These dependencies impact when operations can be scheduled, especially during function and loop pipelining.
- Loop-independent dependence: The same element is accessed in the same loop
iteration.
for (i=0;i<N;i++) { A[i]=x; y=A[i]; }
- Loop-carry dependence: The same element is accessed in a different loop iteration.
for (i=0;i<N;i++) { A[i]=A[i-1]*2; }
Under certain complex scenarios automatic dependence analysis can be too conservative and
fail to filter out false dependencies. Under certain circumstances, such as variable
dependent array indexing, or when an external requirement needs to be enforced (for example,
two inputs are never the same index), the dependence analysis might be too conservative. The
DEPENDENCE
pragma allows you to explicitly specify the dependence and
resolve a false dependence.
Syntax
Place the pragma within the boundaries of the function where the dependence is defined.
#pragma HLS dependence variable=<variable> <class> \
<type> <direction> distance=<int> <dependent>
Where:
variable=<variable>
: Optionally specifies the variable to consider for the dependence.- <class>: Optionally specifies a class of variables in which the
dependence needs clarification. Valid values include array or
pointer. TIP: <class> and
variable=
do not need to be specified together as you can either specify a variable or a class of variables within a function. - <type>: Valid values include
intra
orinter
. Specifies whether the dependence is:intra
: dependence within the same loop iteration. When dependence <type> is specified asintra
, and <dependent> is false, Vivado HLS may move operations freely within a loop, increasing their mobility and potentially improving performance or area. When <dependent> is specified as true, the operations must be performed in the order specified.inter
: dependence between different loop iterations. This is the default <type>. If dependence <type> is specified asinter
, and <dependent> is false, it allows Vivado HLS to perform operations in parallel if the function or loop is pipelined, or the loop is unrolled, or partially unrolled, and prevents such concurrent operation when <dependent> is specified as true.
- <direction>: Valid values include
RAW
,WAR
, orWAW
. This is relevant for loop-carry dependencies only, and specifies the direction for a dependence:- RAW (Read-After-Write - true dependence) The write instruction uses a value used by the read instruction.
- WAR (Write-After-Read - anti dependence) The read instruction gets a value that is overwritten by the write instruction.
- WAW (Write-After-Write - output dependence) Two write instructions write to the same location, in a certain order.
distance=<int>
: Specifies the inter-iteration distance for array access. Relevant only for loop-carry dependencies where dependence is set to true.- <dependent>: Specifies whether a dependence needs to be enforced (true) or removed (false). The default is true.
Example 1
cols
and conservatively assumes that there is always a dependence between
the write to buff_A[1][col]
and the read from
buff_A[1][col]
. In an algorithm such as this, it is unlikely
cols
will ever be zero, but Vivado HLS cannot make assumptions about data
dependencies. To overcome this deficiency, you can use the DEPENDENCE
pragma to state that there is no dependence between loop iterations (in this case, for both
buff_A
and
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 inter false
#pragma HLS dependence variable=buff_B 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];
temp = buff_A[0][col];
}
Example 2
Removes the dependence between Var1
in the same iterations of
loop_1
in function foo
.
#pragma HLS dependence variable=Var1 intra false
Example 3
Defines the dependence on all arrays in loop_2
of function
foo
to inform Vivado HLS that all reads must happen after writes (RAW) in
the same loop iteration.
#pragma HLS dependence array intra RAW true
See Also
- pragma HLS pipeline
- Vivado Design Suite User Guide: High-Level Synthesis (UG902)
- xcl_pipeline_loop
- SDAccel Environment Optimization Guide (UG1207)