Pipeline Constraint Violation - 2023.2 English

Vitis HLS Messaging (UG1448)

Document ID
UG1448
Release Date
2023-10-18
Version
2023.2 English

Description

Warning: [200-880] The II Violation in module '%s': Unable to enforce a carried dependence constraint (II = %s, distance = %s, offset = %s) between %s and %s.
This message reports that the design is violating the user-specified constraint.

Explanation

The II violation message is issued when the tool cannot satisfy the user-specified hard constraint. II violation conceptually occurs because of the hardware dependencies generated by the HLS from user code when the function/loop is pipelined with II=1. These dependencies are the same as the processor dependencies as explained in this wiki: https://en.wikipedia.org/wiki/Data_dependency

These dependencies can be categorized into three sections:

Memory dependencies

Memory dependencies arise when there is memory port contention. This contention only occurs if the loop is pipelined with II=1 and the number of access per loop iteration > 2. This limitation of memory ports is a hardware limit of a storage resource - BRAM/URAM.

So if the user tries to perform >2 access per loop iteration the tool won't be able to schedule the operations in one cycle. This can be visualized in Vitis High-Level Synthesis User Guide (UG1399)

Solution: Partition the array with regards to the user code or refactor the array to multiple dimensions.

Data dependencies

A data dependence is a property of the program, where the current instruction uses the value produced by an earlier instruction. There are 3 main scenarios where these dependencies can arise.

  • The current loop iteration uses the value generated by an earlier loop iteration. and this value takes N cycles to be generated by the earlier iteration. This prevents the current iteration starting at the next cycle.
    • The following snippet displays the behavior.
    • In the below example because of the multiplication of a float variable the loop cannot schedule at II=1.
    float a;
    float b;
    for(...)
    {
    #pragma HLS pipeline II=1
    val *= a*b;
     
    }
  • The current loop iteration uses the value generated by an earlier loop iteration but in infrequent terms. and this value takes N cycles to be generated by the earlier iteration. This prevents the current iteration starting at the next cycle.
  • The current loop iteration exit condition uses the value generated by an earlier loop iteration. and this value takes N cycles to be generated by the earlier iteration. This prevents the current iteration starting at the next cycle.

    The following code snippet shows the behavior.

    float a;
    float b;
    for(...)
    {
    #pragma HLS pipeline II=1
    if(val==3.69)
        break;
    val *= a*b;
     
    }

Solution: These dependencies are visualized in the schedule viewer l to help the user understand. Break up these dependencies in the user code.

False dependencies
void histogram(int in[INPUT SIZE], int hist[VALUE SIZE]) {
int acc = 0;
int i, val;
int old = in[0];
#pragma HLS DEPENDENCE variable=hist intra RAW false
for(i = 0; i < INPUT SIZE; i++)
{
#pragma HLS PIPELINE II=1
val = in[i];
if(old == val)
{
acc = acc + 1;
}
else
{
hist[old] = acc;
acc = hist[val] + 1;
}
old = val;
}
hist[old] = acc;