Antonio Daril Crispino

Heap and Stack sizes problem

Recommended Posts

Hi,

I have a problem setting heap and stack sizes for my application on a CMOD A7 35T. Briefly, through the linker script, I set heap and stack sizes to be placed into the axi_emc_0_S_AXI_MEM0_BASEADDR (64 MB), the emc controller of the onboard SRAM. So a bootloader copies the program from flash to this memory. 

First of all, I set the emc to 64 MB in the VIvado address editor, but the size of the onboard SRAM is 512kB. What does it mean? Is the actual available size of the memory 64MB or 512KB?

Moreover, if I increase the two sizes, heap and stack, from 800kB to 1 or 2 or 4 MB the program doesn't work anymore (even if the "axi_emc_0_S_AXI_MEM0_BASEADDR" memory is set to 64MB). How can it be explained? How can I solve it?

Thank you in advance,

Antonio

Share this post


Link to post
Share on other sites

Hi Antonio,

The tools will allow you to set the available memory to 64MB but if you exceed the 512KB you will run into runtime errors and your design will not work.  Are you using a digilent design? Have you also changed the sizes in the lscript.ld?

cheers,

Jon

Share this post


Link to post
Share on other sites

Hi Jon,

First of all, thank you for your answer. Yes, I was having runtime errors, hence my question. Yes, I set the heap and stack sizes with the linker script. Now, the fact is that I want to put my application .elf, the heap and the stack memories in a secondary memory, not in the brams that constitute the microblaze local memory (whose maximum size is 128k). The problem is that, having only 512k, all this stuff will not fit. So I thought to use the Distributed  Memory Generator Xilinx IPcore (that use sclices LUTs to create RAM) to this purpose. But I'm not able to find any way to properly connect it to the microblaze. Can you help me?

Share this post


Link to post
Share on other sites

Antonio,

You can add a axi bram controller and run connection automation and that will allow you to instantiate bram in your microblaze design.

cheers,

Jon

Share this post


Link to post
Share on other sites

Ahm ... yeah ... that distributed RAM doesn't nearly work as nicely as you'd like.  It really works better as RAM support for various distributed parts of your design, rather than as a global RAM.  You might find yourself stuck with the block RAM you have.  I mean, sure, you might be able to get that distributed RAM to work for you, but be aware--it might kill your timing and force you to lower your clock rate.

Is there any way you can get your block RAM needs ... smaller?  I know when I was working with my S6 SoC, one of the struggles I had was to specify which parts of my program needed to be in RAM and which parts flash.  Might you do the same thing here?  Put parts of your memory needs in block RAM and another part in the secondary memory?

Another solution is to use the block RAM as a cache of sorts.  I'm not sure how well the Xilinx tools support this, but I'd be disappointed in them if they didn't.  That way you can treat all of your memory as one piece, and the FPGA will just quietly move RAM from secondary to block and back again.

Just a thought, or two,

Dan

Share this post


Link to post
Share on other sites

Thank you Jon, but having only 10k LUTs, I can only create a 80KB RAM (one 6-inputs LUTs can implement one 64bit-ram). Moreover, as Dan suggest, I don't think LUT-based Ram is perfect for stack and heap memories. 

Now I have a very small RAM, related to the particular application. I was wondering if I can manage memory accesses to it through a MMU or enabling stack protection exception, increasing time, but solving runtime memory problems. Which of them do you suggest?

I already use BRAM as cache. Enabling "use cache for all memory accesses" will make me treat the memory as one piace, as you said?

I use a bootloader for moving the program from flash to the 512KB-SRAM. About putting some parts of my program in RAM and others in FLASH, I don't know how to do it through the linker script. It only "sees" the MB local memory controller (max128kB) and the EMC base address (512KB). How can I put, and leave, some parts of the program in the flash, even after the bootloader ends its elaboration? Can the microblaze access to those parts in the flash during the execution of the program?

Thank you both for your help,
Antonio

Share this post


Link to post
Share on other sites

Okay, I just looked up the linker script format you are using.  It looks like MicroBlaze uses the GNU linker, and hence the GNU linker format.  What I don't know is how to integrate a generic GNU linker script with what microBlaze, and specifically the bootloader, needs.

When I built my last linker script, I found that it was possible to specify which source files were left in which piece of memory.  From there, you'll notice how some objects were placed into > flash, and some into > blkram AT> flash.  The AT keyword was big for me: by using it, I could specify that some things would be stored in the flash, and then copied to RAM by the bootloader.  The next critical piece, for me at least, was to place any and all set up code or code that otherwise didn't need speed into the flash.  Everything that needed speed I placed into the block RAM.  (If I ran everything from flash, I couldn't play audio in real time --- so I *had* to use the block RAM)

Hope this heps,

Dan

Share this post


Link to post
Share on other sites

Hi Dan,

Sorry for the late response, but I wanted to thank you for your help. I solved the problem doing a thorough study of the allocated heap and the stack memories then setting their sizes properly. So a application-specific solution, as you suggested.

Have a good day,
Antonio

Share this post


Link to post
Share on other sites

Variables allocated on the stack are stored directly to the memory and access to this memory is very fast, and it's allocation is dealt with when the program is compiled. When a function or a method calls another function which in turns calls another function etc., the execution of all those functions remains suspended until the very last function returns its value. The stack is always reserved in a LIFO order, the most recently reserved block is always the next block to be freed. This makes it really simple to keep track of the stack, freeing a block from the stack is nothing more than adjusting one pointer. More about....Stack and Heap

Macin

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now