Description
Explanation
Imperfect loop nests cannot be flattened by the tool. This results in additional clock cycles to enter and exit the loops.
- The innermost loop has a variable bound.
- The loop body is not exclusively inside the inner loop
The following example shows an imperfect loop nest. It will take one cycle to enter the loop and one cycle to exit the loop copy_A. This creates an additional n_elements * 2 clock cycles.
#define BUFFER_SIZE 256
void foo(int *a, int *b) {
// n_elements: variables
outCopyA: for (int i = 0 ; i < n_elements ; i += BUFFER_SIZE) {
int size = BUFFER_SIZE;
copyA: for (int j = 0 ; j < size/2 ; ++j) // 1 cycle to enter the loop
{
b[j*2] = a[i+j*2]; // even index for b
b[(j*2)|1] = a[i+((j*2)|1)]; // odd index for b
}
}
Bursting: At times bursting optimization may result in introducing code in between the loops which may cause this warning. This is a limitation in the current version of the tool and will be addressed in a future releases.
Solution
The solution is to convert the imperfect loop to a perfect loop or a semi-perfect loop nest.
HLS provides the loop_flatten constraint to allow labeled perfect and semi-perfect nested loops to be flattened. This removes the need to re-code for optimal hardware performance and reduces the number of cycles it takes to perform the operations in the loop.
Perfect loop nest: Only the innermost loop has loop body content, there is no logic specified between the loop statements and all the loop bounds are constant. The following is an example:
void foo_top { a, b, c, d} {
...
Outer: while(j<100)
Inner: while(i<6) // 1 cycle to enter inner
...
LOOP_BODY
...
} // 1 cycle to exit inner
}
...
}
Semi-perfect loop nest: Only the innermost loop has loop body content, there is no logic specified between the loop statements but the outermost loop bound can be a variable.