Unable to Schedule - 2023.2 English

Vitis HLS Messaging (UG1448)

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

Description

Warning: [200-885] Unable to schedule.

This message indicates that the user-specified optimization is in violation. The resource is being accessed multiple times in a single cycle, resulting in a resource conflict and performance degradation.

Explanation

In the below code, the resource conflict shows two scenarios:

  • At the interface:

    In the sfunc1, the inputs - a and b are mapped to the same bundle - gmem which maps to a single AXI Interface port. When both the inputs a and b are accessed at the same time, this results in a resource conflict and results in performance degradation. You would see the below warning message:

    Message
     
    WARNING: [HLS 200-885] Unable to schedule bus request on port 'gmem' (./kernel.c:26) due to limited memory ports. Please consider using a memory core with more ports or partitioning the array.
  • In the local array - AuxBuffer:

    The same resource conflict issue is seen with the array. Here would be the below warning message:

    Message
    WARNING: [HLS 200-885] Unable to schedule 'load' operation ('AuxBuffer1_load_7', ./kernel.c:39) on array 'AuxBuffer1', ./kernel.c:59 due to limited memory ports. Please consider using a memory core with more ports or partitioning the array 'AuxBuffer1'.
Code
#include "top.h"
 
void sfunc2(int *vec1,const int sIter, int *ovec)
{
    int aux[N];
    int i;
    int sq_sIter;
    for (i = 0; i < N; ++i) {
        if(i<N/2)    aux[i] = (vec1[i])/sIter;
        else aux[i] = (vec1[i]);
    }
    sq_sIter = aux[0]*aux[N-1]/sIter;
 
    for (i = 0; i < N; ++i) {
        ovec[i] = aux[i]+sq_sIter;
    }
 
}
 
void sfunc1( const int cIter, int *a, int *b, int *res)
{
#pragma HLS PIPELINE
    int i;
    int res1[N];
    for (i=0;i<N; i++) {
        res1[i]= b[i] + a[i] + cIter;
    }
    if (cIter > 3)   sfunc2(res1, cIter, res);
    else sfunc2(res1, 3, res);
 
}
 
 
void sfunc3(const int cIter, int *inrun, int *oval)
{
    int i;
    int sum = 0;
    for (i = 0; i < N; ++i) {
        sum = (inrun[i]*inrun[cIter])/(i+1);
        oval[i] = sum;
    }
}
 
void accel ( int *in1,  int *in2, const int Iter, int *output)
{
    #pragma HLS INTERFACE m_axi depth=10    port=in1    offset=slave    bundle=gmem num_write_outstanding=300
    #pragma HLS INTERFACE m_axi depth=10    port=in2    offset=slave    bundle=gmem num_write_outstanding =300
    #pragma HLS INTERFACE m_axi depth=10    port=output offset=slave    bundle=gmem2 num_write_outstanding=300
    #pragma HLS INTERFACE s_axilite         port=in1                    bundle=control
    #pragma HLS INTERFACE s_axilite         port=in2                    bundle=control
    #pragma HLS INTERFACE s_axilite         port=Iter                   bundle=control
    #pragma HLS INTERFACE s_axilite         port=output                 bundle=control
    #pragma HLS INTERFACE s_axilite         port=return                 bundle=control
 
 
  accel_label0:for (int i=0;i<N;i++) {
#pragma HLS pipeline II=1
      int AuxBuffer1[N];
      sfunc1(Iter, in1, in2, AuxBuffer1);
      sfunc3(Iter, AuxBuffer1, output);
  }
 
 
  return;
}

Solution

When there are resource conflict issues because of multiple loads and store, increase the number of ports or other resources.

#pragma HLS INTERFACE m_axi depth=10    port=in1    offset=slave    bundle=gmem1 num_write_outstanding=300
    #pragma HLS INTERFACE m_axi depth=10    port=in2    offset=slave    bundle=gmem0 num_write_outstanding =300
A solution to the array is to increase the number of ports that can be accessed in one cycle. You can either:
  • Partition the array as shown in the following code.
  • Refactor the code to use multiple data in one signle cycle.
  accel_label0:for (int i=0;i<N;i++) {
#pragma HLS pipeline II=1
      int AuxBuffer1[N];
#pragma HLS array_partition complete
      sfunc1(Iter, in1, in2, AuxBuffer1);
      sfunc3(Iter, AuxBuffer1, output);
  }