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

Ap_memory tutorial & ILA tutorial

Accepted Solution Solved
Explorer
Posts: 208
Registered: ‎02-05-2015
Accepted Solution

Ap_memory tutorial & ILA tutorial

[ Edited ]

I really really need some help, I've been around at this for too long an nothing.

 

I have a block from Vivado HLS which receives an array. That array is automatically converted into ap_memory interface and I was trying to connect them to the PS via  GPIO (proper initializing them in SDK) but I failed miserably.

 

What I need is just a tutorial in Vivado that shows you how to deal with ap_memory interfaces (and preferably on how to initialize them after in SDK)

 

Thank you very much


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

Re: Ap_memory tutorial

[ Edited ]

There's no reason you have to express indicies or addresses in hex its often easier to look at if they are expressed that way. For this sort of thing I prefer hex so I use it. There is no signifance to either quantity being represented in decimal vs. hex. 

 

 

So, keep in mind that in your HLS top level function parameters are representing physical interfaces which is very much not like normal C. You use the interface directive to indicate what kind of interface they are, keep that in mind as you develop your designs. So a pointer which we have set to be a master AXI port represents a physical AXI interface. You may want to study some of the AXI signal descriptions at some point since it may communicate more clearly how some of this works. Accesing that pointer translates to accesses on the AXI bus. However accessing that pointer has no implict base address and how could it. It's possible for there to be a variety of memory mapped devices that it could communicate with. There has to be a way to distinguish one from the other which is done by address space mapping. That said I believe it is possible to explicitly set a base address on an instantiation by instantiation basis. The VHDL created supports a "Target Address" generic which is added to all the transaction addresses. It may be possible to configure this in IPI as well. This would work for this application but when you have multiple memories you would have to rethink the scheme. Finally there is an offset for the m_axi directive which may do the same thing, but then you're back to your code needing to know the address. It also means the Zynq Software and your HLS design have slightly different memory maps which I would find undesirable but really is very application specific.  

 

 

I think your point of confusion may be due to the way the simple example I created works. It relies on a shared memry space between the Zynq PS and your HLS design. The memory is accessed by both using the same AXI interface on the AXI interconnect. Going through this thread again I might pick a slightly different example to communicate my point more clearly. For example you could have two different AXI BRAM Controllers connected to the same BRAM. The Zynq PS would talk to one through the interconnect and the HLS design would talk to another one directly. In this case the HLS design would only be accessing the BRAM's memory space and nothing more. As a result it would behave in a way closer to your thought process. Note the reason I'm using Master AXI and not say an ap_memory port is that memcpy requires a master AXI interface to work. 

 

Now your last point, you can't just specify an address because that's not specifying an interface. In normal SW that would work since the CPU only has access to one memory space. However in this case no such limitation exists. You have to explicitly use the pointer. Naturally my previous example code was a lie since it also doesn't specify an interface. It was to try to explain to you what's going on but it wouldn't work since it doesn't specify an interface.

 

 

Note: Learning VHDL is defintely helpful. I don't believe you can do everything in HLS without understanding some of the FPGA side as well. I've found HLS pretty simple to pick up but I have a lot of experience with the hardware side. From a HDL designer pointer of view HLS makes a lot of really annoying tasks substantially easier (far less work to develop/implement). I'm not sure the same is true if one is approaching from a software perspective. That said if you understand a handful of basic concepts you can probably go pretty far.

View solution in original post


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

Re: Ap_memory tutorial

Guys, please help me. I searched all around and literally found 0 examples or tutorials on how to deal with an ap_memory interface from Vivado HLS.

 

Come on Xilinx guys, wtf! Can't you take 1 min of your time to answer a question?

 

I also tried to make sense of this alone but couldn't by any way. With an array of length 4 only I havethese parameteres in the IP block:

In:

-..._q0[31:0] 

-..._q1[31:0]

 

Out

-..._ce_0

-..._we0

-..._ce1

-..._we1

-...._address0[1:0]

-...._d0[31_0]

-...._address1[1:0]

-...._d1[31_0]

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

Re: Ap_memory tutorial

jmales,

 

You're going to need to take a step back. There's a certain amount of assumed experience in the HLS user guide that you don't have yet (which is fine). However it's not a simple "one minute answer" like you'd expect since you're interfacing to the Zynq PS. The way you address this problem has broad implications in your design that you need to understand before you proceed. Now those in/out ports are for the HDL implementation and should be self explainatory. Jjust think of a generic dual port memory; it's two addresses, two write data's, two write enables, two clock enables and two read datas. If you don't understand what those ports mean I'll be happy to explain but that means you probably don't have enough background knowledge to do what you want just yet.

 

Now since you're trying to connect this to the Zynq PS I would reccomend taking a step back. There are a few ways to do this and while GPIO would theoretically work this probably isn't what you would want. Presumably some sort of software/driver would be communicating with your HLS design and maybe other designs on your PL. This is best handled using a memory mapped protocol like AXI (I strongly reccomend you read up on this protocol, it will come up again and again). Once you understand how AXI works you should look at the HP and GP AXI ports available on the zynq and figure out how you want to map PS to PL memory spaces. You can set a pointer from your top level function to be an axi interface. I recognize this is not just a "how do you do it answer" but in these sorts of scenarios that just isn't possible.

 

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

Re: Ap_memory tutorial

@jprice Ty for answering one of my questions once again.

 

 Now those in/out ports are for the HDL implementation and should be self explainatory. 

But isn't Vivado HLS intendend to not be necessary that you write and manage HDL code? From what I can understand, Vivado HLS is a tool to transform "automatically" C code into IP blocks. However they have 0 tutorials or examples on how to deal with various interfaces, e.g. ap_memory...

 

This is best handled using a memory mapped protocol like AXI (I strongly reccomend you read up on this protocol, it will come up again and again). Once you understand how AXI works you should look at the HP and GP AXI ports available on the zynq and figure out how you want to map PS to PL memory spaces. You can set a pointer from your top level function to be an axi interface. I recognize this is not just a "how do you do it answer" but in these sorts of scenarios that just isn't possible.

I know about AXI protocol, HP and GP already, and I've used them in some examples that I made. The problem is that I can't convert the array into s_axilite since it is automatically converted into ap_memory... That's why I'm having this problem.

 

Note: See this post to see how the structure of the parameter of entrance that I'm talking about is: http://forums.xilinx.com/t5/Embedded-Development-Tools/S-Axilite-from-Vivado-HLS/td-p/593566

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

Re: Ap_memory tutorial

jmales,

 

    HLS will greatly help to reduce the amount of HDL you have to write yourself, however the nature/maturity of the tool and the C language is that it will not completely eliminate it (although in my experience it reduces a ton of work, very much still worth while).  Now, if you're willing to use AXI I can take a guess as to why it's using an ap_memory port instead. AXI itself is just a bus and your enterance structure doesn't directly map to that. Instead have a pointer (say a uint32 *mem) and specify that as a master AXI port (or a slave AXI lite). You should be able to read/write to it and grab the values you desire so long as you know where the data is in memory. This can work (this is exactly what I'm doing in my current design) assuming it meets your needs. I'm reasonably certain there is a way with IPI to use AP_Memory port as well but it would likely involve chaining a few cores together to make it work (and I have not yet had the occassion to do it myself).

 

Hope that helps!

 

 

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

Re: Ap_memory tutorial

[ Edited ]

I'm sorrry, I haven't understood your solution. Making it a pointer doesn't solve it... The array is still declared as ap_memory

 

I tried to find a workaround. Can you check the picture in attachement to see if everything is correct?

 

What I did was separate the array parameters from the structure, and then I tried to connect it to DDR via an AXI DMA.

Everything seems well connected but when I export from SDK to the Zedboard, the result is not correct, which brings me to ask you if the following procedure is correct:

 

1-With one GPIO I set ap_start to 1 (question here is on whether I should set ap_start to 1 here or after MM2S has passed the values to the block)

 

2-With interrupts and AXI DMA initialized I pass the array to the IP block - MM2S transfer (my main doubt is here. As a stream, where is it being keep within the block? I mean, if I pass 10 values from the DDR to an IP block, where are they being kept before using in the IP block? Or are they used as they are received? )

 

3-I try reading the ap_done and ap_ready ports though the GPIO 1 (which I have set for "all inputs" ) but their values is always 0 -_-

 

Please, please help me understand what I'm doing worng.This is critical and I can't find information on how to deal with this anywhere.

Screenshot from 2015-04-28 17:03:10.png
Scholar
Posts: 335
Registered: ‎01-28-2014

Re: Ap_memory tutorial

No problem, I wasn't very explicit so I'll try again. Your GPIO example I don't believe will work although could be made to eventually work. However it would be very difficult to follow and hard to maintain. Below is a snippet of code that more clearly shows what I mean with regards to the AXI interface.

 

void axiTest(uint32 *DDR)
{
   //DDR should be a m_axi port that you would probably
   //connect to one of the Zynq's HP_AXI ports or an
   //interconnect that does.
   #pragma HLS INTERFACE m_axi port=DDR
   MembershipFunction input;
   memcpy(&input,&DDR[physical_address],sizeof(MembershipFunction));
}

The only unknown is how you would acquire the physical address.

 

 

However I looked at the user guide regarding the AXI Lite Slave Interface option and I suspuect this is what you really want. You can read up at it here: 2014.1 Vivado HLS User Guide.The section in question starts on page 170. The part you'll be most interested in is that it claims to automatically generate some driver code for you (I have not tested this). There is some setup invovled but it appears to go into detail on how to do so.

 

float axiTest(MembershipFunction *input)
{
   #pragma HLS INTERFACE s_axilite port=input bundle=BUS_A
   //do stuff
   return input.bound_Min;
}

This seems to compile and generates an axi lite interface for me.

 

 

 

 

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

Re: Ap_memory tutorial

There is some setup invovled but it appears to go into detail on how to do so.

 

float axiTest(MembershipFunction *input)
{
   #pragma HLS INTERFACE s_axilite port=input bundle=BUS_A
   //do stuff
   return input.bound_Min;
}

This seems to compile and generates an axi lite interface for me.

With Membership function having the array parameters??

Which version of Vivado HLS are you using? I'm using 2014.2 and doind that generates an axi lite interface and also ap_memory interface for mf_parameters...

 

The manual you sent said in page 153 that for structures I can use the DATA_PACK directive. However I don't have it available in Vivado HLS 2014.2 don't know why.

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

Re: Ap_memory tutorial

Good point, for the record I'm using 2014.4. I know changing versions mid-project might be unpleasant but you may want to try to see if that AXI issue goes away. But for me it worked even with the array called parameters in the structure, I simply had to apply the correct directive. One thing you could try is to put an array_partition directive on it and see if your version is able to handle it better with that guidance.

 

 

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

Re: Ap_memory tutorial

To be clear, I do not get an ap_memory interface at all, just the AXI lite interface.