Pipeline Scheduling - Pipeline Scheduling - 2026.1 English - UG1448

Vitis HLS Messaging (UG1448)

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

When scheduling a pipeline, Vitis HLS must also satisfy an additional set of constraints:

  1. Cyclic data dependence constraints, due to loop-carried dependences. These dependences mean that the write of a scalar or array element at one iteration affects a read of the same scalar or element N iterations of the pipeline later. Dependences with N=0 (that is to say, within the same loop iteration) are called intradependences, while those with N>0 are called interdependences.

    This N is called the “dependence distance” of a cyclic dependence. This code example contains a distance-1 loop-carried dependence, because the write of a at iteration i affects the read of a at iteration i+1:

    int a = 1; 
    for (int i=0; i<N; i++) { 
    #pragma HLS pipeline
      a *= ...;
    }

    This code example contains a distance 2 loop-carried dependence, because the write of A[i+2] at iteration i affects the read of A[i] at iteration i+2.

    int A[N];
    for (int i=0; i<N-2; i++) {
    #pragma HLS pipeline
      A[i+2] = A[i] * ...; 
    }

    The scheduler must schedule every operation involved in a dependence cycle – the read, multiply, and write operations in the preceding examples – within II cycles.

  2. Top argument synchronization constraints. Operations that read and write any input or inout scalar or array argument of the enclosing design top function must occur within the first II clock cycles. These constraints force all operations that write an output top argument to be executed in the last II.

    If the output operations for an inout top argument have a large delay before them, for example because they depend on operations with latency>1 to meet the required clock frequency, the II might increase.

    Note: Sometimes inout top ports are created due to read, modify, write, and partial-write accesses to top scalar arguments, or to elements of a top array or structure argument.

    For example, assume that the chosen clock frequency implies the use of a floating point multiplier with a total latency of four clock cycles before the accesses to the input argument inout of the top function of this design. The dependence pragma is used to avoid II issues due to dependencies.

    void top(int i, double in, double inout[8]) { 
    #pragma HLS pipeline
    #pragma HLS dependence inter false variable=inout 
      inout[i] *= in;
    }

    The II of the function must be at least 6 to enable the write of inout within the first II cycles (1 for the read of inout, 4 for the multiply, and 1 for the write of inout).

  3. Loop exit condition operation constraints. Operations that determine the exit from a loop must be scheduled within the first II clock cycles. If they depend on operations with latency>1, the II might increase.

    This can happen frequently if the loop bound includes the multiplication of several variables (for example, when manually or automatically flattening loops). For example, in the following case, where the floating point multiplication and comparison take several clock cycles to compute, the II of the loop is increased to allow that computation in the first II cycles.

    void top(hls::stream<double> &in, double &out) {
      double t;
      do {
    #pragma HLS pipeline 
        t = in.read();
        out = t;
      } while (t * 24. > -27.);
    }