12-22-2017 09:43 AM
Folks,
I need help on how I can pass an array/pointer to HLS IP in SDK. I know that if it is a scalar value I can use <>_get/set(*Instance) function but how to do it when you want to pass a memory region as array/pointer. I tired the following with no success.
#define DRAM_ADDR 0x00100000 u32 val; u32* DRAM = (u32*)DRAM_ADDR; XSimple_ddr simple_ddr; int* res_hw;
memcpy(DRAM, data, 100*sizeof(int)); //data is an array with 100 elements
for(int i=0; i<100; i++) { xil_printf("\nRead Memory: %d, %d, %d\n", res_hw[i], DRAM[i], DRAM[i+100]); } XSimple_ddr_Set_DRAM(&simple_ddr, DRAM); XSimple_ddr_Set_num(&simple_ddr, 100); if (XSimple_ddr_IsReady(&simple_ddr)) print("HLS peripheral is ready. Starting... "); else { print("!!! HLS peripheral is not ready! Exiting...\n\r"); exit(-1); } XSimple_ddr_Start(&simple_ddr); print("Detected HLS peripheral complete. Result received.\n\r"); do { res_hw = (int*)XSimple_ddr_Get_DRAM(&simple_ddr); } while (!XSimple_ddr_IsReady(&simple_ddr)); xil_printf("------------------Read after IP------------------------\n"); for(int i=0; i<100; i++) { xil_printf("\nRead Memory: %d, %d, %d", (res_hw[i]), DRAM[i], DRAM[i+100]); }
The IP is:
void simple_ddr(int* DRAM, int num) { #pragma HLS INTERFACE m_axi port=DRAM depth=400 offset=slave bundle=DRAMBUS register #pragma HLS INTERFACE s_axilite port=num bundle=CONFIGBUS register #pragma HLS INTERFACE s_axilite port=return bundle=CONFIGBUS register int BRAM[100]; int j; memcpy(BRAM, DRAM, num*sizeof(int)); int val=0; for(j=0; j<num; j++) { BRAM[j]=7 + val; val++; } memcpy(DRAM+num, BRAM, num*sizeof(int)); }
So what I observed is that the following line returns the base address of the DDR and the memory region starting from (base address + num) doesn't have the modifies data from the HLS IP.
res_hw = (int*)XSimple_ddr_Get_DRAM(&simple_ddr);
Cheers!
12-22-2017 11:36 AM - edited 12-22-2017 11:36 AM
@futuristic Use the offset=slave option on the INTERFACE pragma.
See page 129 for an example
Then HLS will generate a AXI-LITE register that you can set the pointer's memory offset from SDK.
12-22-2017 01:29 PM - edited 12-22-2017 01:54 PM
Thanks! Modified the Pragmas to these:
#pragma HLS INTERFACE m_axi port=DRAM depth=400 offset=slave bundle=DRAMBUS register
#pragma HLS INTERFACE s_axilite port=num bundle=CONFIGBUS_1 register
#pragma HLS INTERFACE s_axilite port=return bundle=CONFIGBUS_2 register
#pragma HLS INTERFACE s_axilite port=DRAM bundle=CONFIGBUS_2
Still the (DRAM + num) memory region has garbage data.
Below is the circuit.
12-22-2017 06:16 PM
@futuristic Now you have to replace your IP with the newly generated one. In my experience, you are better deleting simple_ddr_0 and placing it again as upgrading is a pain.
Have a look at the IP folder and look at the generated C sources for SDK.
You should see C-functions related to setting the offset.
12-23-2017 07:07 AM
@hbucher that is actually what I did. I can't tell where the problem is.
I don't know why res_hw = (int*)XSimple_ddr_Get_DRAM(&simple_ddr); is not returning a memory region with the updated data from the IP.
BTW, the IP doesn't pass the Co-simulation with the following error message:
ERROR: System recieved a signal named SIGSEGV and the program has to stop immediately! This signal was generated when a program tries to read or write outside the memory that is allocated for it, or to write memory that can only be read. Possible cause of this problem may be: 1) the depth setting of pointer type argument is much larger than it needed; 2)insufficient depth of array argument; 3)null pointer etc. Current execution stopped during CodeState = ENTER_WRAPC_PC. You can search CodeState variable name in apatb*.cpp file under ./sim/wrapc dir to locate the position. ERROR: [COSIM 212-379] Detected segmentation violation, please check C tb. ERROR: [COSIM 212-362] Aborting co-simulation: C TB post check failed. ERROR: [COSIM 212-4] *** C/RTL co-simulation finished: FAIL ***
I ignored the above message to generate the RTL IP. Would that be something I need to investigate more.
What would be the next effective debugging step, if not?
12-23-2017 10:35 AM
@futuristic What is your main.cpp you used to run simulation?
12-23-2017 02:12 PM
@hbucher Thanks for your help. I have attached both HLS and SDK source files.
12-28-2017 10:23 AM - edited 12-28-2017 10:23 AM
Modified the IP to:
void simple_ddr(int* DRAM, int num, int midResult)
{
...
midResult = 6;
...
}
to check if the IP is really working by checking if midResult changes values after the IP is started. In SDK I did this:
XSimple_ddr_Set_DRAM(&simple_ddr, DRAM);
XSimple_ddr_Set_num(&simple_ddr, 100);
XSimple_ddr_Set_midResult(&simple_ddr, midResult);
XSimple_ddr_Start(&simple_ddr); print("Detected HLS peripheral complete. Result received.\n\r"); do { res_hw = (int*)XSimple_ddr_Get_DRAM(&simple_ddr); midResult = XSimple_ddr_Get_midResult(&simple_ddr); numfromIP = XSimple_ddr_Get_num(&simple_ddr); } while (!XSimple_ddr_IsReady(&simple_ddr));
...
xil_printf("midResult=%d\n", midResult);
which returns midResult=0, not modified to the value in the IP. What does that mean? I am getting the ready signal from the IP yet not the computed results. I feel like the addressing between the PS and the IP is kinda messed up. Where to go from here?
12-28-2017 10:28 AM
@futuristic In the C code, midResult is an input argument. All changes are local so the result is "correct".
12-28-2017 11:08 AM
@hbucher Not so clear. I passed the midResult to the IP and get the value after it is done which makes midResult=6. How would you change the code then to read the modified value from the IP?
Best,
12-28-2017 11:12 AM
@futuristic This is not anything specific to HLS, this is C language.
To make a variable return a value, you have to pass by reference, as in
void simple_ddr(int* DRAM, int num, int& midResult)
12-30-2017 09:20 AM
11-13-2019 03:17 AM
@futuristic were you able to solve the problem ?