Page 1 of 1
RAM overflow on ZX24n
Posted: 13 July 2008, 15:28 PM
by mikep
I compiled some code for the ZX-24n and received the following result which looks wrong to me:
Code: Select all
No errors. Target device: ZX24n, Code: 18590 bytes, RAM: 4206 bytes, Persistent memory: 32 bytes
Re: RAM overflow on ZX24n
Posted: 13 July 2008, 15:48 PM
by dkinzer
mikep wrote:I compiled some code for the ZX-24n and received the following result which looks wrong to me
Is it that you believe there were errors?
Seriously, though, which part do you think is incorrect. Note that all three memory size values include "system" contributions. For example, the Persistent size will always be at least 32 bytes because that's the size of the Persistent system data. Similarly, the RAM value includes system data items.
Re: RAM overflow on ZX24n
Posted: 13 July 2008, 15:53 PM
by dkinzer
mikep wrote:the following result [...] looks wrong to me
I just realized that the RAM value that you showed exceeds the mega644P's RAM size of 4096. I'll look into whether there is no check performed or if it's being done incorrectly.
Posted: 13 July 2008, 16:16 PM
by dkinzer
The compiler currently does not compare the size of the statically allocated RAM to the RAM size. If I recall correctly, it is that way because simply comparing it to the RAM size of the device isn't particularly helpful. Clearly, if the size of statically allocated RAM exceeds the device's RAM size it's going to be a problem. However, the fact that the size of statically allocated RAM is less than RAM size is not sufficient to guarantee proper execution because additional space is needed for the Main() task stack and for the heap, both of which are unknown at compile time.
The best we can do at present is to add a directive similar to Option.CodeLimit which, if present, will result in a warning if the size of statically allocated RAM exceeds the value specified.
Posted: 15 July 2008, 11:35 AM
by mikep
dkinzer wrote:However, the fact that the size of statically allocated RAM is less than RAM size is not sufficient to guarantee proper execution because additional space is needed for the Main() task stack and for the heap, both of which are unknown at compile time.
We should be able to estimate the size of the Main() task stack just like we do for all tasks.
One of the things missing from even the ZVM output is the size of this stack. You get the total RAM estimate for everything else but you don't know how much headroom is left unless you read the MAP file. I don't know quite the best way to display this. Perhaps something like:
Code: Select all
No errors. Target device: ZX24, Code: 4020 bytes, Allocated RAM: 1186 bytes, Main() RAM: 147 bytes, RAM Left: 203 bytes, Persistent memory: 0 bytes
dkinzer wrote:The best we can do at present is to add a directive similar to Option.CodeLimit which, if present, will result in a warning if the size of statically allocated RAM exceeds the value specified.
This may help but we already have the HeapSize option to bound the variable part of the RAM.
Posted: 15 July 2008, 14:57 PM
by dkinzer
mikep wrote:This may help but we already have the HeapSize option to bound the variable part of the RAM.
For native mode devices, RAM is partitioned into three blocks as depicted in the
ZBasic Reference Manual. The first, lowest addressed, block contains all of the statically allocated variables (with contributions from both system and user code). Immediately following that is the Main() task stack and finally the heap.
The directives Option.HeapSize, Option.HeapLimit and Option.MainTaskStackSize allow you to control how the RAM for the second two blocks is partitioned.
The question is, at what point should the size of the first block be declared "too large" and an error message issued? Clearly, if it is larger than the available RAM, it is too large. However, it is also too large unless there is sufficient space for both the Main() task stack and the heap. For the VM targets, the compiler produces an estimate of the necessary task stack size using static analysis. This is not done currently for native mode but it may be possible to do so. I don't think that it is feasible to estimate heap requirements using static analysis.
If we had an estimate of minimum task stack size, we could issue an error/warning message if the sum of the statically allocate variables, the minimum task stack, and the default (or specified) heap size exceeds the RAM size.
Posted: 15 July 2008, 15:16 PM
by mikep
dkinzer wrote: The first, lowest addressed, block contains all of the statically allocated variables (with contributions from both system and user code). Immediately following that is the Main() task stack and finally the heap.
I though the following error message was intelligent when I used the same size stack as the ZVM version.
Code: Select all
FooBar.bas:117: Warning(13): task stack is too small, at least 60 bytes is needed
Now I understand that it is a standard message for all native mode stacks under 60 bytes. I will go back and follow the instructions in section 4.6 of the manual.
So there is not much to do here other than your original suggestion. The rest is up to the native mode device programmer.
Posted: 15 July 2008, 19:26 PM
by dkinzer
mikep wrote:Now I understand that it is a standard message for all native mode stacks under 60 bytes.
Yes, given the number of bytes required for saving the task's context, it seems that 60 bytes or so constitutes an absolute minimum for almost any task. That is the rationale behind that message.
I have some ideas about how to perform a static stack use analysis for native mode by examining AVR opcodes and following all possible execution paths. The main problem is recognizing the opcode sequences that the gcc compiler uses to allocate local stack space. Usually, it looks like this:
Code: Select all
in r28, 0x3d
in r29, 0x3e
sbiw r28, 0x0c
But there is one case that looks like this:
Code: Select all
in r28, 0x3d
in r29, 0x3e
sub r28, r26
sbc r29, r27
Clearly, in order to determine the effect of this sequence you'd need to track the contents of the registers.