cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Observer
Observer
1,220 Views
Registered: ‎07-05-2018

Read from various addresses using the same AXI4 master interface

Jump to solution

I know that by doing the following:

 

void example(int *a) {
#pragma HLS INTERFACE m_axi depth=50 port=a
#pragma HLS INTERFACE s_axilite port=a bundle=control
#pragma HLS INTERFACE s_axilite port=return bundle=control
int A[50];
for (int i=0; i<50; i++)
A[i] = a[i]; }

I can assign an address to the register "a" located in the AXI Lite interface and my IP automatically knows the address to read the data from.

 

 

What I would like to do is something like this:

void example(int *a, int64_t addr_a, int64_t addr_b, int64_t addr_c) {
#pragma HLS INTERFACE m_axi depth=150 port=a

#pragma HLS INTERFACE s_axilite port=addr_a bundle=control
#pragma HLS INTERFACE s_axilite port=addr_b bundle=control
#pragma HLS INTERFACE s_axilite port=addr_c bundle=control

#pragma HLS INTERFACE s_axilite port=return bundle=control
int A[50], B[50], C[50];

a = addr_a;
for (int i=0; i<50; i++)
   A[i] = a[i];

a = addr_b;
for (int i=0; i<50; i++)
   B[i] = a[i];

a = addr_c;
for (int i=0; i<50; i++)
   C[i] = a[i];
}

Thus, with a single AXI4 master interface I could read from 3 different addresses (of course this code does not synthesize). Is it possible to do something like this? And how could I test it in my testbench?

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
Highlighted
Xilinx Employee
Xilinx Employee
1,130 Views
Registered: ‎07-18-2014

Hi @ieronym,

Can you try to have multiple memory arguments which are connected to single Master interface using bundle as below?

 

void example(int *a, int *b, int *c) {
#pragma HLS INTERFACE m_axi depth=150 port=a bundle=gmem0
#pragma HLS INTERFACE m_axi depth=150 port=b bundle=gmem0
#pragma HLS INTERFACE m_axi depth=150 port=c bundle=gmem1 #pragma HLS INTERFACE s_axilite port=return bundle=control int A[50], B[50], C[50]; for (int i=0; i<50; i++) A[i] = a[i]; for (int i=0; i<50; i++) B[i] = b[i]; for (int i=0; i<50; i++) C[i] = c[i]; }

If you are using same bundle value for multiple arguments, it is going to create single AXI4 Master interface.

 

-Heera

View solution in original post

0 Kudos
4 Replies
Highlighted
Xilinx Employee
Xilinx Employee
1,160 Views
Registered: ‎09-05-2018

Hey @ieronym

I think that code does not synthesize because of the assignment of int64_t to int*. But also, it's not how I would recommend reading from various addresses. The m_axi INTERFACE directive has an offset parameter, which you can set to 'direct' to tell HLS to create an axilite interface to control the address offset.

I would recommend instead creating IP which only has one s_axilite input, then passing three different address into that top level IP.

Here's the top level function I would use:

void example(volatile int *a, int addr_a[50]){
#pragma HLS INTERFACE m_axi depth=50 port=a offset=direct
#pragma HLS INTERFACE s_axilite port=addr_a bundle=control
#pragma HLS INTERFACE s_axilite port=return bundle=control
int i;
 for(i=0; i < 50; i++){
  a[i] = addr_a[i];
 }
}

And in the testbench, call that function 3 times:

int A_in1[50], A_in2[100], A[150];
//Create data
for(i=0; i < 50; i++) A_in1[i] = i;
for(i=0; i < 100; i++) A_in2[i] = i+50;

// call the function three times with different offsets
example(A,A_in1);
example(&A[50],A_in2);
example(&A[100],&A_in2[50]);

I think this accomplishes what you're looking for, and it should pass C/RTL Co-Sim. However, I think the waveform is confusing. You won't see the address offset change how you expect. Instead, the co-simulation just loads up the appropriate values from the testbench and leaves the address offset alone.

Nicholas Moellers

Xilinx Worldwide Technical Support
0 Kudos
Highlighted
Observer
Observer
1,140 Views
Registered: ‎07-05-2018

This example has the same effect as if in my initial example I had called the example function 3 times. This means that, every time, my accelerator does the same thing and I just have to start/wait for it to stop 3 times. Also the "direct" directive has the same result as the "slave" directive except that it creates an additional port and not a register inside the AXI Lite to control the address.

In my case, my accelerator needs to read from 3 different addresses data of different sizes every time it executes (actually it needs to read 2 arrays of different size and a file). This could easily be done with 3 AXI master interfaces but I think this results to redundant utilization, and it could be convenient if the addresses where stored in 3 registers inside the AXI Lite and the accelerator could choose one of the 3 whenever it likes.

For now I think one solution could be to store the data in 3 addresses relative to the address the axi master reads from, but this makes the software developement less agile. I mean, I could just simply call mmap or malloc 3 times and pass 3 addresses to the accelerator, but now I have to do one big malloc, insert the data in a specific way and pass an address and 3 offsets to it.

 

PS You I right, I should have written a = (int *) addr_a; but this does not synthesize also.

0 Kudos
Highlighted
Xilinx Employee
Xilinx Employee
1,131 Views
Registered: ‎07-18-2014

Hi @ieronym,

Can you try to have multiple memory arguments which are connected to single Master interface using bundle as below?

 

void example(int *a, int *b, int *c) {
#pragma HLS INTERFACE m_axi depth=150 port=a bundle=gmem0
#pragma HLS INTERFACE m_axi depth=150 port=b bundle=gmem0
#pragma HLS INTERFACE m_axi depth=150 port=c bundle=gmem1 #pragma HLS INTERFACE s_axilite port=return bundle=control int A[50], B[50], C[50]; for (int i=0; i<50; i++) A[i] = a[i]; for (int i=0; i<50; i++) B[i] = b[i]; for (int i=0; i<50; i++) C[i] = c[i]; }

If you are using same bundle value for multiple arguments, it is going to create single AXI4 Master interface.

 

-Heera

View solution in original post

0 Kudos
Highlighted
Observer
Observer
1,118 Views
Registered: ‎07-05-2018

You are right. Thank you

0 Kudos