Working with Nested Loops - Working with Nested Loops - 2026.1 English - UG1399

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2026-06-23
Version
2026.1 English

A loop can be pipelined only if it does not contain any loop (possibly after some inner loop unrolling). A loop containing a pipelined loop is therefore either dataflow or sequential. When it is sequential, its iterations are executed in sequence and, for each iteration, the inner loop is fully executed once. In the RTL implementation, this requires one clock cycle to move from the outer loop to the inner loop, one clock cycle to move back from the inner loop to the outer loop, plus, in between, the whole latency to complete all iterations of the inner loop. To get better performance (lower latency) when working with nested loops, it becomes crucial to create perfectly nested loops and to convert them into a single loop that can be pipelined.

Perfect_nested_loop_1: for (int i = 0; i < N; ++i) {
    Perfect_nested_loop_2: for (int j = 0; j < M; ++j) {
        ...
    }
}
 
Imperfect_nested_loop_0: for (int i = 0; i < N; ++i) {
    Imperfect_nested_loop_2: for (int j = 0; j < M; ++j) {
        ...
    }
    Imperfect_nested_loop_3: for (int j = 0; j < M; ++j) {
        ...
    }
}

Perfect loop nests are nested loops where each outer loop contains only one subloop and nothing else. Almost-perfect loop nests (nested loops where each outer loop can contain, in addition, elementary instructions) can be automatically transformed into perfect loop nest by pushing these instructions into the innermost loop.

The LOOP_FLATTEN pragma or directive is used to allow perfect and almost-perfect nested loops to be flattened. With some additional important flattenability requirements about their tripcount, see the description of the loop_flatten pragma or directive. Removing the need to re-code for optimal hardware performance and reducing the number of cycles it takes to perform the operations in the loop. When the LOOP_FLATTEN optimization is applied to a set of nested loops, it should be applied to the innermost loop that contains the loop body.

When pipelining nested loops, the optimal balance between area and performance is typically found by pipelining the innermost loop. This also results in the fastest runtime.