pragma HLS unroll
Description
Unroll loops to create multiple independent operations rather than a single collection of
operations. The UNROLL
pragma transforms loops by creating multiples copies
of the loop body in the RTL design, which allows some or all loop iterations to occur in
parallel.
Loops in the C/C++ functions are kept rolled by default. When loops are rolled, synthesis
creates the logic for one iteration of the loop, and the RTL design executes this logic for
each iteration of the loop in sequence. A loop is executed for the number of iterations
specified by the loop induction variable. The number of iterations might also be impacted by
logic inside the loop body (for example, break
conditions or modifications
to a loop exit variable). Using the UNROLL
pragma you can unroll loops to
increase data access and throughput.
The UNROLL
pragma allows the loop to be fully or partially unrolled. Fully
unrolling the loop creates a copy of the loop body in the RTL for each loop iteration, so
the entire loop can be run concurrently. Partially unrolling a loop lets you specify a
factor N, to create N copies of the loop body and
reduce the loop iterations accordingly. To unroll a loop completely, the loop bounds must be
known at compile time. This is not required for partial unrolling.
for(int i = 0; i < X; i++) {
pragma HLS unroll factor=2
a[i] = b[i] + c[i];
}
break
construct is used to ensure the functionality remains
the same, and the loop exits at the appropriate point:
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];
}
Because the maximum iteration count X is a variable, Vivado HLS may not
be able to determine its value and so adds an exit check and control logic to partially
unrolled loops. However, if you know that the specified unrolling factor, 2 in this example,
is an integer factor of the maximum iteration count X, the
skip_exit_check
option lets you remove the exit check and associated
logic. This helps minimize the area and simplify the control logic.
config_unroll
command. See config_unroll
in the Vivado
Design Suite User Guide: High-Level Synthesis (UG902) for more information.Syntax
Place the pragma in the C/C++ source within the body of the loop to unroll.
#pragma HLS unroll factor=<N> region skip_exit_check
Where:
factor=<N>
: Specifies a non-zero integer indicating that partial unrolling is requested. The loop body is repeated the specified number of times, and the iteration information is adjusted accordingly. Iffactor=
is not specified, the loop is fully unrolled.region
: An optional keyword that unrolls all loops within the body (region) of the specified loop, without unrolling the enclosing loop itself.skip_exit_check
: An optional keyword that applies only if partial unrolling is specified withfactor=
. The elimination of the exit check is dependent on whether the loop iteration count is known or unknown:- Fixed (known) bounds: No exit condition check is performed if the iteration count is
a multiple of the factor. If the iteration count is not an integer multiple of the
factor, the tool:
- Prevents unrolling.
- Issues a warning that the exit check must be performed to proceed.
- Variable (unknown) bounds: The exit condition check is removed as requested. You
must ensure that:
- The variable bounds is an integer multiple of the specified unroll factor.
- No exit check is in fact required.
- Fixed (known) bounds: No exit condition check is performed if the iteration count is
a multiple of the factor. If the iteration count is not an integer multiple of the
factor, the tool:
Example 1
loop_1
in function foo
.
Place the pragma in the body of loop_1
as shown:
loop_1: for(int i = 0; i < N; i++) {
#pragma HLS unroll
a[i] = b[i] + c[i];
}
Example 2
loop_2
of
function foo
, and removes the exit check:
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] = ...;
...
}
...
}
Example 3
loop_1
in function
foo
, but not loop_1
itself due to the presence of the
region
keyword:
void foo(int data_in[N], int scale, int data_out1[N], int data_out2[N]) {
int temp1[N];
loop_1: for(int i = 0; i < N; i++) {
#pragma HLS unroll region
temp1[i] = data_in[i] * scale;
loop_2: for(int j = 0; j < N; j++) {
data_out1[j] = temp1[j] * 123;
}
loop_3: for(int k = 0; k < N; k++) {
data_out2[k] = temp1[k] * 456;
}
}
}
See Also
- pragma HLS loop_flatten
- pragma HLS loop_merge
- pragma HLS loop_tripcount
- Vivado Design Suite User Guide: High-Level Synthesis (UG902)
- opencl_unroll_hint
- SDAccel Environment Optimization Guide (UG1207)