Forum: Compiler & IDEs Max RAM bei Xilinx SDK gcc Compiler und MicroBlaze Prozessor
Hallo,
ich möchte folgendes Programm auf dem Spartan3E-Starter Board ausführen
und wundere mich, dass bei einem Build bei globalen Variablen die
RAM-Überprüfung korrekt ist - bei lokalen Variablen aber nicht.
Ich benutzte nur BRAM - kein externes SD-RAM.
(Ob dieser Thread eher ins FPGA-Forum gepasst hätte, weiß ich nicht...
;-))
Versuch1 mit globalen Variablen - MIT erwarteter Fehlermeldung: 1 | int testarray[10000000]; //wirft wie erwartet einen Fehler
| 2 |
| 3 | int main() {
| 4 | xil_printf("Hallo Welt!");
| 5 | }
|
--> make 1 | **** Incremental build of configuration Debug for project mb0_default ****
| 2 |
| 3 | make all
| 4 | mb-gcc -c -mno-xl-soft-mul -mxl-pattern-compare -mcpu=v7.10.a -I../../microblaze_0_sw_platform/microblaze_0/include -xl-mode-executable -g -O0 -gstabs -olab2.o ../../../code/lab2.c
| 5 |
| 6 | Building target: mb0_default.elf
| 7 | mb-gcc -o mb0_default.elf lab2.o -mxl-soft-mul -mxl-pattern-compare -mcpu=v7.10.d -L../../microblaze_0_sw_platform/microblaze_0/lib -xl-mode-executable -gstabs
| 8 | Finished building: mb0_default.elf
| 9 |
| 10 | ************** Validating ELF File **************
| 11 |
| 12 | Validating ELF Section Addresses with Hardware Address Map...
| 13 | elfcheck -noheader -mhs C:/Workdir/Xilinx/Tests/Tutorial2/system.mhs -p xc3s500efg320-4 -xmpdir C:/Workdir/Xilinx/Tests/Tutorial2 -pe microblaze_0 mb0_default.elf
| 14 | ERROR:MDT - Section .bss (0x12B0 - 0x2625A33) does not fit completely into
| 15 | memory dlmb_cntlr (0x0 - 0x3FFF).
| 16 | ERROR:MDT - Section .stack located at address 0x2626CE4 does not map to any
| 17 | memory found in the hardware design.
| 18 | ERROR:MDT - elfcheck failed!
| 19 | INFO:MDT - Try using the linker script generation tools to generate an ELF that
| 20 | maps well to your hardware design.
| 21 | make: *** [mb0_default.elf] Error 2
| 22 | Build complete for project mb0_default
|
Versuch2 mit LOKALER Variable - OHNE Fehlermeldung...??? 1 | int main() {
| 2 | int testarray[10000000]; //wirft KEINEN Fehler????
| 3 | xil_printf("Hallo Welt!");
| 4 | }
|
--> make: 1 | **** Incremental build of configuration Debug for project mb0_default ****
| 2 |
| 3 | make all
| 4 | mb-gcc -c -mno-xl-soft-mul -mxl-pattern-compare -mcpu=v7.10.a -I../../microblaze_0_sw_platform/microblaze_0/include -xl-mode-executable -g -O0 -gstabs -olab2.o ../../../code/lab2.c
| 5 |
| 6 | Building target: mb0_default.elf
| 7 | mb-gcc -o mb0_default.elf lab2.o -mxl-soft-mul -mxl-pattern-compare -mcpu=v7.10.d -L../../microblaze_0_sw_platform/microblaze_0/lib -xl-mode-executable -gstabs
| 8 | Finished building: mb0_default.elf
| 9 |
| 10 | ************** Validating ELF File **************
| 11 |
| 12 | Validating ELF Section Addresses with Hardware Address Map...
| 13 | elfcheck -noheader -mhs C:/Workdir/Xilinx/Tests/Tutorial2/system.mhs -p xc3s500efg320-4 -xmpdir C:/Workdir/Xilinx/Tests/Tutorial2 -pe microblaze_0 mb0_default.elf
| 14 | elfcheck passed!
| 15 |
| 16 | ************** Determining Size of ELF File **************
| 17 |
| 18 | mb-size mb0_default.elf
| 19 | text data bss dec hex filename
| 20 | 4418 300 1080 5798 16a6 mb0_default.elf
| 21 |
| 22 | Build complete for project mb0_default
|
Das ganze macht mich etwas "unruhig".
Woher soll ich denn nun wissen, ob der RAM für eine lokal definierte
Variable noch ausreicht - oder nicht?
Hat jemand einen Tip für mich?
Beste Grüße,
Andreas
Hm, naja, im Normalfall wandern lokale Variablen ja auf den Heap,
eventuell überprüft der GCC nicht, wie groß der werden darf?
Hallo Christian,
das ist richtig - die wandern auf den Heap.
Wie es aussieht überprüft der gcc tatsächlich nicht wie groß der wird.
Die dicke Frage ist nur, wie kann ich den gcc dazu bringen, dass er es
tut??
Gruß,
Andreas
Lokale Variablen werden auf dem Stack und nicht auf dem Heap
gespeichert.
>wie kann ich den gcc dazu bringen, dass er es tut??
Wahrscheinlich garnicht, denn lokale Variablen werden erst zur Laufzeit
angelegt. Es müsste aber eine Option geben, die dem Compiler sagt, dass
er nach jedem Funktionsaufruf überprüft, ob der Stack eventuell
übergelaufen ist.
MfG Mark
Das kann der Compiler garnicht pruefen, selbst wenn er wollte. Denn das
haengt von Parametern wie etwa der Rekursionstiefe Deiner Funktionen ab,
die wiederum von etwaigen Eingabewerten abhaengen, die zur Compile-Time
unmoeglich bekannt sein koennen. Ergo musst Du selber dafuer sorgen dass
Dein Programm die verfuegbaren Ressourcen nicht sprengt. Ein guter Weg
ist da z.B., auf Rekursion wenn es geht komplett zu verzichten, dann
bleibt die Sache ueberschaubar.
Michael
Hallo Michael,
wenn man genau darüber nachdenkt hast Du recht.
ABER:
Z.B. der CCS-Compiler für PICs gibt nach dem compilieren die minimale
und maximale RAM-Auslastung aus. Eine Rekursion wird von diesem Compiler
nicht unterstützt.
Bleibt aber die Frage, wie das dieser CCS-Compiler macht - und warum es
der gcc (mit den default-Einstellungen vom Xilinx SDK) nicht macht.
Sicherlich ist es beim CCS-Compiler auch nur eine "Schätzung". So weit
ich aber weiß, "schätzt" er sehr großzügig. Er nimmt also immer den
schlechtesten Fall an.
In meinem obigen Beispiel ist es doch für den Compiler sehr simpel.
Die funktion main() hat eine lokale Variable, die viel zu groß ist - das
würde der CCS-Compiler gut erkennen können.
Schwierig wird es natürlich, wenn in einer Unterfunktion eine weitere
Unterfunktion in Abhängigkeit einer IF-Abfrage oder gar einer
SWITCH-Abfrage aufgerufen wird. Dann kann der Compiler so einfach
natürlich nicht mehr den maximalen Speicherbedarf berechnen...
******************** Lösung gefunden (während dem Schreiben hier...)
*************
Ich habe gerade eine Seite gefunden:
http://www.delorie.com/gnu/docs/gcc/gnat_ug_46.html
Die gcc-Option -fstack-check tut genau das was ich möchte.
Es wird zwar im Fehlerfall nur eine Warnung - kein Fehler geworfen, aber
das reicht mir so...
Danke für die Anregung und beste Grüße,
Andreas
Dir ist klar dass die Dokumentation auf den Ada-GCC bezogen ist. Hier
wird Laufzeit-Code generiert, der prueft, ob noch genug Speicher am
Stack verfuegbar ist. Sicherlich mit der Konsequenz von nicht
unwesentlichen Performance-Verlusten. Ausserdem muss man mit einem
Pragma die Groesse des Stacks angeben. Das funktioniert dann auch nur so
lange gut, wie die Groesse dieses Stacks bekannt und konstant ist. Unter
komplexen Systemen ist das aber nicht der Fall, das steht auch dort:
>For the environment task, the stack size depends on system defaults and is
>unknown to the compiler. The stack may even dynamically grow on somesystems,
>precluding the normal Ada semantics for stack overflow. In the >worst case,
>unbounded stack usage, causes unbounded stack expansion resulting in the
>system running out of virtual memory.
Was Du also pruefen musst ist, ob der C-GCC das ueberhaupt kann und wie
das Feature zu benutzen ist. Und da es sich hier zwangslaeufig um eine
Laufzeitpruefung handelt bringt es Dir nicht besonders viel. Es hilft
Dir, bei einem Stack-Overflow den Fehler besser zu finden da hier eine
spezielle Exception geworfen wird. Ohne diesen Code wuerde Dein Prgramm
halt einfach abschmieren. Das Feature hilft Dir allerdings nicht, zur
Compile-Time irgendwelche Schlussfolgerungen auf die Auslastung des
Stacks zu ziehen.
Ach ja, Ada ist ja "bekannt" fuer solche Dinge. Da wird z.B. auch Code
generiert, der Array-Zugriffe auf ihre Grenzen hin ueberprueft. Sowas
wird in C z.B. auch nicht gemacht. Da rauscht Dir im Zweifelsfall halt
Dein Programm ab.
Michael
Michael G. wrote:
> Dir ist klar dass die Dokumentation auf den Ada-GCC bezogen ist.
Ja, ist mir klar - das war halt die erste Seite, auf der diese
Compileroption beschrieben war...
> Hier wird Laufzeit-Code generiert, der prueft, ob noch genug Speicher am
> Stack verfuegbar ist. Sicherlich mit der Konsequenz von nicht
> unwesentlichen Performance-Verlusten. Ausserdem muss man mit einem
> Pragma die Groesse des Stacks angeben. Das funktioniert dann auch nur so
> lange gut, wie die Groesse dieses Stacks bekannt und konstant ist. Unter
> komplexen Systemen ist das aber nicht der Fall, das steht auch dort:
>>For the environment task, the stack size depends on system defaults and is
>>unknown to the compiler. The stack may even dynamically grow on somesystems,
>>precluding the normal Ada semantics for stack overflow. In the >worst case,
>>unbounded stack usage, causes unbounded stack expansion resulting in the
>>system running out of virtual memory.
>
> Was Du also pruefen musst ist, ob der C-GCC das ueberhaupt kann und wie
> das Feature zu benutzen ist. Und da es sich hier zwangslaeufig um eine
> Laufzeitpruefung handelt bringt es Dir nicht besonders viel. Es hilft
> Dir, bei einem Stack-Overflow den Fehler besser zu finden da hier eine
> spezielle Exception geworfen wird. Ohne diesen Code wuerde Dein Prgramm
> halt einfach abschmieren. Das Feature hilft Dir allerdings nicht, zur
> Compile-Time irgendwelche Schlussfolgerungen auf die Auslastung des
> Stacks zu ziehen.
Ich habe es bereits mit obigem Beispiel ausprobiert.
Im Fehlerfall (also zu große Variable) wird eine Compiler-Warnung
ausgegeben. Die Größe des Stacks habe ich nicht explizit angeben müssen.
Die wird ja dem MicroBlaze mitgeteilt - vor der Synthese (in meinem Fall
die BRAM-Größe - hab ja kein DDR-RAM). Der gcc hat sich anscheinend
automatisch diese Information geholt... Ansonsten hätte er ja auch keine
Fehlermeldung für die globale Variable werfen können...
Gruß,
Andreas
Eine globale Variable kommt nicht auf den Stack, das hat damit garnichts
zu tun. Das ist aber auch einleuchtend, weil es fuer globale Objekte
immer nur genau eine Inkarnation geben kann, die nicht vom Scope
abhaengt. Diese also auf den Laufzeit-Stack zu werfen waere fatal.
Du hast (mal wieder) recht.
Ich sollte mir mal wieder die Begrifflichkeiten Heap, Stack und Co.
anschauen - ist doch schon alles zu lange her...
Bei der globalen Variable kommt die Fehlermeldung tatsächlich nicht vom
gcc, sonder von dem Programm "elfcheck".
Woher nun der gcc die maximale Stackgröße hergenommen hat, weiß ich
gerade auch nicht - werde es mir aber die kommenden Tage nochmal
anschauen...
Danke für die Infos und schönen Feieraben... ;-)
Andreas
Andreas N. wrote:
> Woher nun der gcc die maximale Stackgröße hergenommen hat, weiß ich
> gerade auch nicht - werde es mir aber die kommenden Tage nochmal
> anschauen...
Er ist einfach von einem default-value ausgegangen. Das kann Dir dazu
fuehren dass Dein Programm terminiert, obwohl noch genug Stack zur
Verfuegung stehen wuerde. Da solltest Du etwas vorsichtig mit sein, vor
allem wenn Du nicht weisst, wie dieses default gesetzt ist.
Michael
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|