Description
The tool is informing the user that the user-specified optimization is violating.
Explanation
This message informs that the resource is being accessed multiple times in a single cycle which results in a resource conflict and performance degradation.
In the below code, the resource conflict is showing in 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. For more information, see Using AXI4-Stream Interfaces. 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. Resolution: For help on HLS 200-885 see www.xilinx.com/html_docs/xilinx2020_1/hls-guidance/200-885.html
- 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'. Resolution: For help on HLS 200-885 see www.xilinx.com/html_docs/xilinx2020_1/hls-guidance/200-885.html
#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. The user needs to increase the number of ports or a different resource.
#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
- 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);
}