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!

Reply
Accepted Solution

Ap_memory tutorial & ILA tutorial

Explorer
Posts: 208
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Ty for the answers @jprice

 

Well, unfortunately my Vivado HLS 2014.4 license is finished and I can't even synthesize...

 

So, I'm left with 2014.2 version and I guess I'll try to get it working by setting the parameters to port axis with the use of an AXI DMA block.

 

Tell me something though:

-When I send a stream through an AXI DMA to a custom IP block, what happens to that stream? I mean, I defined the entrance as:

float parameters[4];

and then I use them within the function. So, when I send the stream of 4*4=16 bytes to the IP block what happens? Where is it being kept? I think the reason my previous block wasn't working is due to me not understanding this properly.

Scholar
Posts: 335
Registered: ‎01-28-2014

Re: Ap_memory tutorial

If possible try to get 2014.4 working would be my reccomendation. To answer your question, I'm not clear on how stream interfaces work with HLS. My guess is that HLS takes the incoming stream and interprets the bytes based on your inputs. In your example the first 4 bytes would be the first float, the second 4 bytes would be the second and so forth.The parameters are likely being kept in an internal memory (internal to your HLS design).  The AXI DMA core to a streaming interface in HLS should work just fine for this application.

Explorer
Posts: 208
Registered: ‎02-05-2015

Re: Ap_memory tutorial

[ Edited ]

Yes, you are correct, it should work easily. However the results being given are not correct.

 

Can I ask for one last thing that is for you to check the printscreens (and SDK code if necessary) to see what I'm doing wrong? I won't ask for anything more and I'm even willing to pay you something if you want.

 

I guess the problem is in the MM2S transfer. I managed to do a S2MM transfer already but not a MM2S.

 

Note: The files dma.c and isr.c you probably won't need to check, they are adapted from other example code

Observer
Posts: 17
Registered: ‎07-17-2014

Re: Ap_memory tutorial

just out of curiosity, is it possible to bundle the control signals as another axi. presumably, it is easier??

Scholar
Posts: 335
Registered: ‎01-28-2014

Re: Ap_memory tutorial

To help you more in depth will require more context. I haven't directly worked with the SW side of Xilinx generated code. What I've done in the past was more custom (I wrote some HDL to interface to the SW side). For example I configured a memory region on the GP0 axi port and setup a small dual port memory that the PS could write directly into. I worked with a SW engineer who wrote the Linux driver that handled the SW side so I'm not familiar with how that worked. The HDL would poll certain addresses for control and then stream the necessary data out to the appropiate logic. It's certainly not necessary but I'm not familiar with the IPI flow you're using (which I agree should be possible to make work) so I'm not able to pin-point the likely small detail you've gotten wrong.  

 

What I would do is try something simpler to gain more familiarity (you likely have more experience with this flow than I do). For now take out everything and setup an AXI interconnect (two ports), then connect aa master AXI GP port to the inteconnect. I would connect a BRAM with to the interconnect along with a modified version of your design. Your design should contain a master AXI port. You need to know where in BRAM your SW writes your structure but thats a detail I believe you can figure out. If you can make this work (I think this is simpler than the method you're using) I believe that would be an excellent start (and might even get you fully there). Hopefully my thoughts here make sense. 

 

 

Explorer
Posts: 208
Registered: ‎02-05-2015

Re: Ap_memory tutorial

The thing is..I really need to learn this MM2S transfer because I will need it in the future to read maps from the DDR memories.

 

But about what you said: yes it makes sense. Let's just discuss the flow oof this please:

-So, I make a BRAM block (which has just a Slave AXI port) and connect it via an interconnect to a port of the kind Master AXI that I'll make in my custom IP block. That's it? If so, problem is (again) that I can't establish the mf struct with m_axi interface. It doesn't let me and says that for example mf.bound_Min is a calara and m_axi can't be specified for scalars.

 

I can't thank you enough for the knowledge and tips you've been giving me. THANK YOU mate!

Scholar
Posts: 335
Registered: ‎01-28-2014

Re: Ap_memory tutorial

I don't have your version of the tool and don't have the time to directly figure this out myself. I'd certainly like to know how to use the MM2S and S2MM but I'm starting with something more familiar and hopefully we can work towards what you need.

 

To continue, don't use your structure as a parameter in your top level function. Instead create a pointer, say of an unsigned integer. Set that to a m_axi interface and and read (using memcpy) from the memory space. An example is given below. The key thing is you don't use your Membership function as an input. Instead you create an instance of it inside your design and copy from memory to it. Let me know what your version of the tool does with this but this should work. What this doesn't help you with is how to start your particular IP but I think you already have a method in place to do this.

 

void axiTest(uint32 *mem)
{
    #pragma HLS INTERFACE m_axi port=mem
    Membership_Function input;
    memcpy(&input, mem, sizeof(Membership_Function));
    process(input); 
}

 

Explorer
Posts: 208
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Ok, let's forget about the MM2S for now then.

 

Help me understand this well and I'll be on my way. I understand what you are saying and there's also a small example here  on page 178/179. However I'm missing something to fully understand the flow of this. Here's 2 ways of how my noob experience can understand this:

 

1-So, I connect the M_Axi output port via an interconnect to the Slave AXI port of a BRAM controller, the S_AXI of this block to a GP port from Zynq PS and then within this function (axiTest) I define the MembershipFunction? If so, then in SDK I just need to initialize the BRAM controller, start the axiTest block and we're ok to go?

 

My question at this point is: what if I want to use mf->parameters[0] inside that axiTest function, how will that work if I'm only defining it now? Or is this just an example on how to pass a MembershipFunction to RAM memory and then I need to use another (or maybe the same) BRAM controller to use that RAM memory in other IP blocks?

 

OR

 

2- I connect the M_Axi output port via an interconnect to the Slave AXI port of a BRAM controller which gives the address of RAM memory in which MembershipFunction bytes are defined (if so, how do I define them in the 1st place to the RAM memory?) and the S_AXI of this block to a GP port from Zynq PS.

 

Which option is coorect when we are doing a m_axi transfer to BRAM?

 

Sorry if the post is confusing. I'm confused as hell myself, and because of that I couldn't make it clearer than this.

 

I have no more time today, but I'll try this tomorrow first thing in the morning and I'll give you some feeedback.

Highlighted
Scholar
Posts: 335
Registered: ‎01-28-2014

Re: Ap_memory tutorial

No problem, it's confusing especially at first. One thing that has worked to my advantage is working at an HDL level instrinically means that you have to work at a lower level and understand low level details (which Xilinx is trying to abstract away from you with the IPI flow). It might benefit you to do some experiments in HDL if you're able. Understanding the signals might go a long way towards helping you develop a deeper understanding.

 

Now to clarify. You have the Zynq PS, which we desire to be a master, and we have your design which we also desire to be a master. We'll have a BRAM controller which we desire to be a slave. The AXI Interconnect will have two slave interfaces which you connect to masters (The Zynq PS, presumably on M_GP0 and your block). The master port of the AXI interconnect should connect to the BRAM controller. This allows the Zynq PS and your logic to both directly read/write to the BRAM controller. Now what would be desirable is if you could map a memory space from the M_GP0 port to the BRAM controller. I can not find any documentation in the BRAM controller regarding how you would do it. See if IPI gives you any options here. I just wrote custom HDL to filter the address space in the past but there must be an option to do this in IPI. For now, if yuo make a 32 by 1k deep memory it would be sufficent to keep the 15 LSBs of the address space mapped to the M_AXI_GP0 to 0. For example could map the  address space of the Zynq PS M_AXI_GP0 port to to 0xC000_0000 to 0xC000_FFFF. Writing to this address in SW will result in transactions taking place in the PL. The BRAM controller will see them and should handle them accordingly. Your software should write to the BRAM controller the necessary values in the correct byte order. Now your HLS code will know that your SW will write values starting at say BRAM Address 0 (arbitary). This should happen before your block is "called". Then your block may be called (one method is using the GPIO method you've connected to the ap_start port). When your block is called it copies data (raw bytes) into an instance of the membership function using the memcpy call. Since your block is a master like the Zynq PS, it can initiate requests. The block RAM is a slave to both the Zynq PS and your block in this example configuration.

Explorer
Posts: 208
Registered: ‎02-05-2015

Re: Ap_memory tutorial

[ Edited ]

I think I finally understood the AXI BRAM flow, all thanks to you :D

 

Here's the simple function that I made to try this and in attachment the printscreen of the block design.

 

void bram_func(float    *mem, float *result_out){
#pragma HLS INTERFACE m_axi port=mem
#pragma HLS INTERFACE s_axilite port=result_out bundle=BUS_A

    float parameters[4];

    memcpy(&parameters,mem, sizeof(parameters));

    *result_out=parameters[2]+parameters[3];

} 

 

After the bitstream is ready I'll try to proper initialize the BRAM and GPIO in the SDK and I'll post the results

Screenshot from 2015-04-30 12:35:53.png