UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor ivars211
Visitor
221 Views
Registered: ‎11-25-2018

Data transfer via m_axi

I am pulling my hair out and cannot figure out why this simple code doesn't work..

Testbench:

#include <iostream>
using namespace std;

void buildSolution(int d_nSources, volatile int* d_prodCap, volatile int* d_dailyOrderLimit);

int main() {

	int prodCap[3];
	prodCap[0] = 10000;
	prodCap[1] = 20000;
	prodCap[2] = 30000;
	int dailyOrderLimit[3];
	dailyOrderLimit[0] = 10;
	dailyOrderLimit[1] = 20;
	dailyOrderLimit[2] = 30;
	int nSources = 3;

	buildSolution(nSources, prodCap, dailyOrderLimit);//,

	cout << endl << "ProdCap:";
	for (int i = 0; i < nSources; i++) {
		cout << prodCap[i] << " ";
	}
	cout << endl << "DailyOrder:";
	for (int i = 0; i < nSources; i++) {
		cout << dailyOrderLimit[i] << " ";
	}

	cout << endl;

	return 0;
}

core:

#include "math.h"
#include <stdio.h>
#include <string.h>

void buildSolution(int d_nSources, volatile int* d_prodCap, volatile int* d_dailyOrderLimit) {
#pragma HLS INTERFACE m_axi port=d_prodCap depth=50
#pragma HLS INTERFACE m_axi port=d_dailyOrderLimit depth=50

#pragma HLS INTERFACE s_axilite port=d_nSources bundle=CTR
#pragma HLS INTERFACE s_axilite port=return bundle=CTR

	int nSources = d_nSources;

int local_prodCap[50]; memcpy(local_prodCap,(const int*)d_prodCap,nSources*sizeof(int));
int local_dailyOrderLimit[50]; memcpy(local_dailyOrderLimit,(const int*)d_dailyOrderLimit,nSources*sizeof(int));

for (int i = 0; i<nSources;i++) {
	local_prodCap[i] = 10+i;
	local_dailyOrderLimit[i] = i*4;
}

memcpy((int *)d_prodCap,local_prodCap,nSources*sizeof(int));
memcpy((int *)d_dailyOrderLimit,local_dailyOrderLimit,nSources*sizeof(int));

}

Outputs I get:

C testbench: 

ProdCap:10 11 12 
DailyOrder:0 4 8 

Cosimulation:

ProdCap:10000 20000 30000 
DailyOrder:0 4 8 

 

Must be something obvious I am doing wrong but I just have not figured it out in past 3 days. 

Windows 10, Vivado HLS 2018.2

0 Kudos
10 Replies
Scholar u4223374
Scholar
167 Views
Registered: ‎04-26-2015

Re: Data transfer via m_axi

I'm confused about why you're declaring the AXI masters as volatile (ie telling the compiler "this data could change while the function runs") and then casting it to const (ie telling the compiler "this data must not change while the function runs").

 

Try just removing all "volatile" and "const" keywords and see what happens.

0 Kudos
Visitor ivars211
Visitor
161 Views
Registered: ‎11-25-2018

Re: Data transfer via m_axi

Thanks for your reply. I was following axi_master example project in Vivado HLS that uses volatile and const keywords.

Removed volatile and const keywords and still having exact same problem with exact same mismatch. 

0 Kudos
Visitor ivars211
Visitor
142 Views
Registered: ‎11-25-2018

Re: Data transfer via m_axi

Little update, I am pretty sure this is a bug of Vivado HLS unless someone can explain:

Wrong result in co-simulation:

int main() {
	int prodCap[3];
		prodCap[0] = 10000;
		prodCap[1] = 20000;
		prodCap[2] = 30000;

	int dailyOrderLimit[3];
		dailyOrderLimit[0] = 10;
		dailyOrderLimit[1] = 20;
		dailyOrderLimit[2] = 30;


	int nSources = 3;

	buildSolution(nSources, prodCap, dailyOrderLimit);//,

Correct result in co-simulation:

int main() {
	
	int dailyOrderLimit[3];
		dailyOrderLimit[0] = 10;
		dailyOrderLimit[1] = 20;
		dailyOrderLimit[2] = 30;
			
	int prodCap[3];
		prodCap[0] = 10000;
		prodCap[1] = 20000;
		prodCap[2] = 30000;

	int nSources = 3;

	buildSolution(nSources, prodCap, dailyOrderLimit);//,

Basically swapping the order of array declaration made difference. Any explanation? 

 

Scholar u4223374
Scholar
129 Views
Registered: ‎04-26-2015

Re: Data transfer via m_axi

Yep, that looks like a bug.

 

Do not select any "solution" to this thread; if it's left unsolved eventually a Xilinx employee will have a look at it.

0 Kudos
Explorer
Explorer
123 Views
Registered: ‎08-16-2018

Re: Data transfer via m_axi

 

I think you are using some example in the HLS UG just adding an additional memcpy.

Why memcpy? Why not a for loop? Many sw people seem to think (or code as if) the less they code, the smarter they are.

Or maybe they think they can pass the burden to "the function I haven't written" - but still have the responsibility of having chosen it.

At the end of the day, memcpy is a loop as well. And in HLS, any loop can (and should if possible) be unrolled.

The difference is, if you write your own loop, you directly state what to access, while with memcpy it's indirect.

Memcpy works with memory addresses that have not much meaning in an FPGA. 

 

0 Kudos
Explorer
Explorer
117 Views
Registered: ‎08-16-2018

Re: Data transfer via m_axi

If the order of variable declarations change the implementation, there is a bug, I'm afraid...

Maybe HLS only accepts one memcpy (?). You could bundle your two arrays in one and try a single one.

Anyways, either an issue or a missing note in the UG.

0 Kudos
Visitor ivars211
Visitor
108 Views
Registered: ‎11-25-2018

Re: Data transfer via m_axi


@johnvivm wrote:

 

I think you are using some example in the HLS UG just adding an additional memcpy.

Why memcpy? Why not a for loop? Many sw people seem to think (or code as if) the less they code, the smarter they are.

Or maybe they think they can pass the burden to "the function I haven't written" - but still have the responsibility of having chosen it.

At the end of the day, memcpy is a loop as well. And in HLS, any loop can (and should if possible) be unrolled.

The difference is, if you write your own loop, you directly state what to access, while with memcpy it's indirect.

Memcpy works with memory addresses that have not much meaning in an FPGA. 

 


If it makes you feel better, this core also produces the same wrong result in co-simulation:

#include "math.h"
#include <stdio.h>
#include <string.h>

void buildSolution(int d_nSources, volatile int* d_prodCap, volatile int* d_dailyOrderLimit) {

#pragma HLS INTERFACE m_axi port=d_prodCap depth=50
#pragma HLS INTERFACE m_axi port=d_dailyOrderLimit depth=50

#pragma HLS INTERFACE s_axilite port=d_nSources bundle=CTR
#pragma HLS INTERFACE s_axilite port=return bundle=CTR

	int nSources = d_nSources;
	int local_prodCap[50];
	int local_dailyOrderLimit[50];

	for (int i = 0; i < nSources; i++) {
		local_dailyOrderLimit[i] = d_dailyOrderLimit[i];
		local_prodCap[i] = d_prodCap[i];
	}
	for (int i = 0; i < nSources; i++) {
		local_prodCap[i] = 10 + i;
		local_dailyOrderLimit[i] = i * 4;
	}
	for (int i = 0; i < nSources; i++) {
		d_dailyOrderLimit[i] = local_dailyOrderLimit[i];
		d_prodCap[i] = local_prodCap[i];
	}

}

Co-sim result:

ProdCap:10000 20000 30000 
DailyOrder:0 4 8 

Only way of getting correct result is swapping array declarations in testbench. 

 

Another discovery of mine is to change m_axi depth to 3 (the size of arrays) and both cores work... Can someone confirm that depth always have to match the array size? I thought that it just have to be bigger than the array you are accessing... 

Explorer
Explorer
95 Views
Registered: ‎08-16-2018

Re: Data transfer via m_axi

Sorry for just pointing at possibilities without trying myself, but what if you had all ports (d_prodCap, d_dailyOrderLimit) defined as AXILITE and bundled on the same interface as you do with d_nSources and return (that btw, I wonder if necessary with a void function)?

 

Visitor ivars211
Visitor
90 Views
Registered: ‎11-25-2018

Re: Data transfer via m_axi

Like this? No, same wrong result.

#include "math.h"
#include <stdio.h>
#include <string.h>

void buildSolution(int d_nSources, volatile int* d_prodCap, volatile int* d_dailyOrderLimit) {

#pragma HLS INTERFACE m_axi port=d_prodCap depth=50
#pragma HLS INTERFACE m_axi port=d_dailyOrderLimit depth=50

#pragma HLS INTERFACE s_axilite port=d_prodCap bundle=CTR
#pragma HLS INTERFACE s_axilite port=d_dailyOrderLimit bundle=CTR
#pragma HLS INTERFACE s_axilite port=d_nSources bundle=CTR
#pragma HLS INTERFACE s_axilite port=return bundle=CTR

	int nSources = d_nSources;
	int local_prodCap[50];
	int local_dailyOrderLimit[50];

	for (int i = 0; i < nSources; i++) {
		local_dailyOrderLimit[i] = d_dailyOrderLimit[i];
		local_prodCap[i] = d_prodCap[i];
	}
	for (int i = 0; i < nSources; i++) {
		local_prodCap[i] = 10 + i;
		local_dailyOrderLimit[i] = i * 4;
	}
	for (int i = 0; i < nSources; i++) {
		d_dailyOrderLimit[i] = local_dailyOrderLimit[i];
		d_prodCap[i] = local_prodCap[i];
	}

}

Two things that make pretty much all cores work is either 1) change m_axi depth=3 or 2) swap array declaration order in tesbench.

0 Kudos
Xilinx Employee
Xilinx Employee
67 Views
Registered: ‎09-05-2018

Re: Data transfer via m_axi

@ivars211,

I've filed a bug report for this issue. Thanks for bringing this to our attention.

Nicholas Moellers

Xilinx Worldwide Technical Support