Hallo, ich habe ein Spartan3 (XC3S4000FGG676-5C) FPGA Modul mit 48 MHz Quarz. Um einmal zu testen, welche Performance der Microblaze (v7.10d) auf diesem System hat habe ich ein paar Versuche getätigt. Der Microblaze läuft mit einer Frequenz von 80 MHz, die aus den 48MHz des Quarzes durch den DCM generiert werden. Dem Microblaze habe ich so ziemlich alles mitgegeben was geht, FPU, Integer Multiplier, Integer Divider, Barrel Shifter sowie jeweils 2KB Cache auf der Daten und Befehlsseite und 5 Stage Pipeline. Das Programm für die Tests wird von einem Bootloader ins externe SDRam geladen und dort gestartet. Um eine Zeitmessung durchzuführen verwende ich den XPS_Timer. Dieser lüuft mit den vollen 80MHz Systemtakt. Wenn ich den Timerwert zweimal hintereinander auslese, so erhalte ich einen Wert von 125, was ich zunächst einmal als Offset-Takte ansehe. Zwischen beide Timerauslese-Vorgänge mache ich nun verschiedene Operationen und erhalte die Taktzahl des Befehls (den Offset habe ich abgezogen). Folgende Werte sind dabei herausgekommen: Zuweisung "i=1;" 92 Takte SDRam 32Bit schreiben 127 Takte SDRam 32Bit lesen 99 Takte Float multiplizieren 28795 Takte Float dividieren 18091 Takte Diese paar Werte sollen erstmal reichen. Was mir direkt aufgefallen war ist, dass die Werte allgemein doch sehr hoch sind. Wie kommen diese hohen Werte zustande? Vor allem bei den Float-Multiplikation gibt Xilinx an, dass diese in 4 takten, die Division in 28 Takten zu schaffen sei. Da bin ich aber doch sehr weit entfernt, obwohl der Haken bei FPU in den Microblaze Einstellungen vorhanden ist. Aber auch das Lesen und Schreiben vom SDRam müsste doch in 10 Takten zu schaffen sein oder etwa nicht? Mache ich bei der Auswertung etwas falsch? Bei der Opitimiereng die der Compiler vornehmen kann habe ich alle Einstellungen ausprobiert, jedoch ohne großartige Änderungen. Vielleicht hat ja von euch jemand eine Idee, was hier schief geht... Gruß, Christoph
Bei mir dauert das "normale" Lesen von einem BRAM auch schon 10 Takte. Die Stärke des Microblaze scheint damit nicht so sehr in der IO-Performance zu liegen. Duke
SDRAM ist nicht ganz einfach im Zugriff (Bank schliessen, neue öffnen, prefetch,...) , da kann der erste Zugriff schon ne weile dauern. Realistischer (zumal du ja extra cache in deinem System hast) ist das das lesen von 16 Daten am Blöck. Einige Busse am uB sind mit waitstates konfiguriert, vielleicht liegt es daran. i=1 in 10 Takten mag ich wirklich glauben (ist i im Register?). Sind vielleicht die datentypen zu groß (64 bit) und es sind in echt mehrere Zugriffe nötig (da 32 bit system oder 16 bit bus). Schau dir mal die Datenbreite des Busses an. MfG,
Laß das Programm vorallem mal vom internem Ram aus laufen... und ggf mal das ASM listing betrachten. Ich würde auch Stack und Heap erstmal in den internen Ram verfrachten.
Korrektur:
> i=1 in 10 Takten mag ich wirklich glauben (ist i im Register?).
hab mich vertippt, soll heissen:
i=1 in 10 Takten mag ich wirklich NICHT glauben (ist i im Register?).
Soo hab jetzt alles mal ins BRam gemacht, dort gehts deutlich schneller. Hier mal mein Ergebnis fürs SDRam (Die Zahl hinter diff gibt die Anzahl der Takte an): Offset: start: 3694914, end: 3694789, diff: 125 SDRam schreiben ( 8Bit): start: 3307401, end: 3307180, diff: 96 SDRam lesen ( 8Bit): start: 2852301, end: 2852079, diff: 97 SDRam schreiben (16Bit): start: 2420327, end: 2420106, diff: 96 SDRam lesen (16Bit): start: 1962411, end: 1962189, diff: 97 SDRam schreiben (32Bit): start: 1533853, end: 1533601, diff: 127 SDRam lesen (32Bit): start: 1066168, end: 1065946, diff: 97 Zuweisung: start: 666999, end: 666812, diff: 62 U08 add: start: 324233, end: 323885, diff: 223 U08 sub: start: 7989981, end: 7989633, diff: 223 U08 mul: start: 7615069, end: 7613636, diff: 1308 U08 div: start: 7236778, end: 7230341, diff: 6312 U16 add: start: 6864495, end: 6864054, diff: 316 U16 sub: start: 6512587, end: 6512146, diff: 316 U16 mul: start: 6150292, end: 6148549, diff: 1618 U16 div: start: 5774912, end: 5767974, diff: 6813 U32 add: start: 5404223, end: 5403968, diff: 130 U32 sub: start: 5053976, end: 5053721, diff: 130 U32 mul: start: 4693431, end: 4691564, diff: 1742 U32 div: start: 4318054, end: 4310547, diff: 7382 U64 add: start: 3949057, end: 3948672, diff: 260 U64 sub: start: 3601188, end: 3600803, diff: 260 U64 mul: start: 3243774, end: 3232991, diff: 10658 U64 div: start: 2866074, end: 2827091, diff: 38858 F32 add: start: 2482778, end: 2470956, diff: 11697 F32 sub: start: 2117319, end: 2105056, diff: 12138 F32 mul: start: 1748761, end: 1719849, diff: 28787 F32 div: start: 1379891, end: 1361684, diff: 18082 F64 add: start: 1016372, end: 997991, diff: 18256 F64 sub: start: 676799, end: 655104, diff: 21570 F64 mul: start: 329401, end: 233341, diff: 95935 F64 div: start: 7944629, end: 7825620, diff: 118884 Und jetzt das gleiche, wenn das Programm im BRam läuft: Offset: start: 7999922, end: 7999908, diff: 14 SDRam schreiben ( 8Bit): start: 7766009, end: 7765980, diff: 15 SDRam lesen ( 8Bit): start: 7318828, end: 7318777, diff: 37 SDRam schreiben (16Bit): start: 6899140, end: 6899111, diff: 15 SDRam lesen (16Bit): start: 6451944, end: 6451893, diff: 37 SDRam schreiben (32Bit): start: 6032258, end: 6032229, diff: 15 SDRam lesen (32Bit): start: 5585066, end: 5585015, diff: 37 Zuweisung: start: 5165382, end: 5165366, diff: 2 U08 add: start: 4821387, end: 4821362, diff: 11 U08 sub: start: 4484256, end: 4484231, diff: 11 U08 mul: start: 4147140, end: 4147077, diff: 49 U08 div: start: 3810016, end: 3809784, diff: 218 U16 add: start: 3466022, end: 3465996, diff: 12 U16 sub: start: 3128909, end: 3128883, diff: 12 U16 mul: start: 2791785, end: 2791714, diff: 57 U16 div: start: 2454659, end: 2454410, diff: 235 U32 add: start: 2110656, end: 2110636, diff: 6 U32 sub: start: 1780422, end: 1780402, diff: 6 U32 mul: start: 1450177, end: 1450101, diff: 62 U32 div: start: 1113058, end: 1112784, diff: 260 U64 add: start: 3369839, end: 3369815, diff: 10 U64 sub: start: 3032705, end: 3032681, diff: 10 U64 mul: start: 2695590, end: 2695222, diff: 354 U64 div: start: 2351597, end: 2350234, diff: 1349 F32 add: start: 7766136, end: 7765731, diff: 391 F32 sub: start: 7408384, end: 7407962, diff: 408 F32 mul: start: 7050615, end: 7049619, diff: 982 F32 div: start: 6692855, end: 6692249, diff: 592 Man sieht deutlich, dass es ca. um Faktor 8 schneller ist. Aber es drei Sachen verstehe ich nicht: 1. Warum brauchen float Operationen so lange, obwohl ich die FPU aktiviert habe? 2. Was ist der Grund dafür, dass das Programm im SDRam so stark langsamer ist? Klar wird es etwas langsamer sein, aber so einen großen Unterschied hätte ich nicht erwartet. 3. Kann es sein, dass etwas mit den Cache Einstellungen nicht stimmt, so dass der MB den Cache nur fürs BRam verwendet und fürs SDRam garnicht? Oder lässt sich durch Einstellungen des Memory Controllers noch Performance rausholen? Gruß, Christoph
Wie gesagt... schau dir das ASM Listing an... ich glaub eher das der MB viel mehr "machen" muß, als du denkst, gerade aufgrund deiner "Benchmarks". Und bzgl des SRAMs zitier ich mal das MB Datenblatt: >When executing from slower memory, instruction fetches may >take multiple cycles. This additional latency directly >affects the efficiency of the pipeline. Zwar hat der MB nen prefetch buffer, aber dieser muß bei jedem genommen Sprung neu aufgebaut werden! >The MicroBlaze instruction and data caches can be configured >to use 4 or 8 word cache lines. When using a longer cache line, >more bytes are prefetched, which generally improves performance >for software with sequential *access* patterns. >However, for software with a more random *access* pattern the >performance can instead _decrease_ >for a given cache size. This is caused by a reduced cache hit rate >due to fewer available cache lines. Float Operationen können so lange dauern weil diese das ausführen Nachfolgender Befehle verzögern, oder der compiler nicht die HW FP Operationen verwendet, deshalp --> Listing ansehen
Okay, werde mir das ASM Listing mal anschauen, aber wo genau finde ich das? Bisher habe ich nur eine *.elf, eine *.o und eine *.d Datei gesehen, aber dort befindet sich so wie ich das sehe kein ASM Code. Oder muss ich mir den ASM Code selbst erzeugen, bzw. durch Optionen selber erzeugen lassen?
<Oder muss ich <mir den ASM Code selbst erzeugen, bzw. durch Optionen selber erzeugen <lassen? Früher hat man dem gcc die Option -s mitgegegeben, damit er den Assembler-Quellcode ausgibt. MfG,
Rechtsklick auf das Projekt --> Set compile Options --> Path and Options dort bei Other Compiler Options -save-temps eintragen. dann behaält er das erzeugte (.s) file. (http://www.delorie.com/djgpp/v2faq/faq8_20.html)
Ich habe auch gerade mal den Cache ausgeschaltet -> keine Veränderung bei den Takten, ist alles beim Alten geblieben, das kann eigentlich nicht sein oder? @Läubi: Bezüglich deines letzten Posts, Ist denn der externe SDRam wirklich so viel langsamer, so, dass der Microblaze so starke Unterschiede zum internen BRam zeigt? Als externen SDRam verwende ich den " http://www.issi.com/pdf/42S32160A.pdf " So langsam erscheint der mir eigentlich garnicht.
Naja sagen wir mal der braucht 5 Takte für einen Lesezugriff, dann dauern alle Befehle (im mittel) 5 takte länger... Stell doch sonst mal das listing file rein.
< Ist denn der externe SDRam wirklich so viel langsamer Ja SDRAM ist nicht SRAM, vor dem READ muss 3 takte vorher ein AVTIVATE passieren, und nach dem READ dauert es noch die CAS-Latency biss die Daten anliegen. Dann muss man meist noch in die verschiedenen taktdomainen einsynchronisieren. DER SDRAM ist nicht unbedingt langsamer, er hat nur eine lange "Anfahrzeit" (Latenz). Deshalb sollte man Block und keine Einzeltransfer messen um die Durchsatzrate zu bestimmen. Oder mehrmals laufen lassen. MfG
Okay, ich kann ja mal einfach 1KByte ins SDRam schreiben bzw. 1KByte aus dem SDRam lesen und dort die Zeit messen, mal sehen wie die sich im bezug auf einen einfachen ransfer verhält...
Um der ganzen Sache nach und nach auf den Grund zu gehen analysiere ich gerade den generierten ASM-Code Mir ist aufgefallen, dass er aus dem C-Code: i=1; den ASM Code: addik r3,r0,1 # 0x1 swi r3,r19,36 macht. Somit initialisiert er nicht nur ein Register mit 1, sondern speichert dieses auch gleich im SDRam ab, wenn ich das richtig interpretiere. Aus welchem Grund wird das im SDRam gespeichert? Ich verwende diese Variable i im ganzen Progrmam nicht mehr.
Wenn die data area im SDRam liegt wird er das auch dort hinspeichern... Leg mal Stack und Heap in den Bram.. könnte aber auch sein das du ggf ne andere Optimierungsstufe einstellen mußt.
Heap und Stack im Bram wird glaube nicht so einfach glaube ich, oder kann man einfach angeben, wo sich das befinden soll? Starte mein Progeramm ja mit nem Bootloader...
Weiss sowieso im Moment nicht genau was ich machen soll. Im BRAm hab ich momentan meinen Bootloader. Deswegen habe ich das normale Programm im SDRam. Jetzt merk ich, dass es dort doch sehr langsam zu sein scheint, jedoch ist das BRAM eigentlich zu klein für mein Programm (also wenn es fertig ist). Ich kann es so wie ich das gesehen habe bis 64KB einstellen. Das ist shcon etwas arg wenig. Was für eine Möglichkeit habe ich noch? Hat jemand eine Idee?
Ich hab hier gerade etwas im Netz gefunden: http://www1.cs.columbia.edu/~soviani/cs4840hack/Microblaze_timing.html Die müssen irgendwas anders amchen als ich...
Interessant, hat mir doch ein Kolleche erzählt das es in neueren EDK-Versionen einen Ersatz für den OPB-Bus gibt. Unter dem dir genannten steht für Zugriffe über den (neuen) LMB 1 Takt, für den (alten) OPB bis zu 7 Takte. Vielleicht solltest du dein syste neuzusammenklickern und dabei auf den LMB achten ?! Kann man die FPU auch an den LMB (statt OPB) klemmen?
Also der Bram ist am LMB, der SDRam Controller ist am OPB. An welchem Bus jetzt die FPU hängt kann ich dir nicht sagen, aber ich nehme an dass die garnicht extern am Microblaze hängt, sondern intern verdrahtet ist... Was genau soll ich versuchen an den LMB zu hängen? den SDRam Controller? Ich glaube das ist garnicht möglich, aber werde mal gucken ob es geht.
Ich habe jetzt noch einmal etwas mit dem System rumgespielt. Es sieht tatsächlich so aus, als wäre der Cache fürs SDRam nicht eingeschaltet. Wollte diesen jetzt einschalten, jedoch kann ich den Microblaze dann nicht mehr mit 80 MHz betreiben. Woran kann das liegen? Kann man dies umgehen?
Ich habe jetzt nochmal wegen der FPU geguckt. Also eingeschaltet ist diese, der Compiler macht mir aus der float-Multiplikation folgenden ASM Code: lwi r5,r19,44 lwi r6,r19,40 brlid r15,__mulsf3 ## Need to verify this nop # Unfilled delay slot swi r3,r19,36 Ist dieser ASM-Code nun so, dass die FPU angesprochen wird, oder wird die float-Zahl auf üblichem Weg ohne FPU ausgerechnet?
er ruft die Unterfunktion __mulsf3 auf... Ich hätte jezt eher sowas erwartet:
1 | lwi r5,r19,44 |
2 | lwi r6,r19,40 |
3 | fmul r3, r5, r6 |
4 | swi r3,r19,36 |
Spart Platz und Ausführungszeit... sieht für mich eher so aus als ob er entweder die FPU nicht nuzt, oder der Linker dies (je nach vorhandener Hardware) dann umsezt. Kompilier mal die Debuginfos rein und dann mit objdump von der Binary das listfile zu erzeugen.
Kenne mich damit leider nicht so gut aus. Wie kann ich die Debug-Infos mit reincompillieren und wie genau erzeuge ich dann mit objdump das Listfile aus der Binary? Sorry, habe sowas noch nie gemacht... Für mich siehts auch so aus, als würde er die FPU garnicht nutzen, genauso wie das Cache. Es macht nämlich momentan keinen Unterschied, ob ich den Cache einschalte oder auslasse. Das wundert mich sehr. Kann es sein, dass das Xilinx SDK irgendwie nicht mitbekommt, welche Features beim Microblaze aktiv und welche deaktiv sind?
Also ggf mut du mal das Bitfile + die Softwarelibs neu bauen. Die Debuginfos kannst du im Compilersettings Dialog aktivieren, objdum gehört zum gcc --> http://www.linuxjournal.com/article/7269 ziemlich am Ende ist der aufruf von objdump beschrieben: objdump -d test.o
Also selbst wenn ich das Bitfile, die Softwarelibs und mein Programm cleane und neu baue gibt es keine Änderung bei der Anzahl der Takte. Müsste denn irgendwo im SDK sichtbar sein, ob Cache oder die FPU aktiviert sind? Lässt sich dies irgendwo erkennen? Ich probiere jetzt mal das mit dem objdump
Also habe mir jetzt ein Programm geschirbeen, dass einfach nur zwei floats multipliziert: int main (void) { U32 x1=123.45,x2=567.89,x3=0.0; x3=x1*x2; return (int)x3; } wenn ich jetzt objdump -d app.o in der Konsole eingebe, erhalte ich folgendes: 00000000 <main>: 0: 3021ffd4 addik r1, r1, -44 4: f9e10000 swi r15, r1, 0 8: fa610028 swi r19, r1, 40 c: 12610000 addk r19, r1, r0 10: 3060007b addik r3, r0, 123 14: f8730024 swi r3, r19, 36 18: 30600237 addik r3, r0, 567 1c: f8730020 swi r3, r19, 32 20: f813001c swi r0, r19, 28 24: e8b30024 lwi r5, r19, 36 28: e8d30020 lwi r6, r19, 32 2c: b0000000 imm 0 30: b9f40000 brlid r15, 0 34: 80000000 or r0, r0, r0 38: f873001c swi r3, r19, 28 3c: e873001c lwi r3, r19, 28 40: e9e10000 lwi r15, r1, 0 44: 10330000 addk r1, r19, r0 48: ea610028 lwi r19, r1, 40 4c: 3021002c addik r1, r1, 44 50: b60f0008 rtsd r15, 8 54: 80000000 or r0, r0, r0 So wie ich das überschauen kann sehe ich da garnichts von einer Multiplikation oder? Theoreitsch sollte ja jetzt irgendwo FMUL auftauchen.
Ohh sorry, hab ausversehn U32 Variablen erstellt, sollte F32 sein, also nochmal: C-Code: int main (void) { F32 x1=123.45,x2=567.89,x3=0.0; x3=x1*x2; return (int)x3; } ASM-Code: lwi r5,r19,36 lwi r6,r19,32 brlid r15,__mulsf3 ## Need to verify this nop # Unfilled delay slot swi r3,r19,28 Und die Ausgabe des objdump -d app.o : app.o: file format elf32-microblaze Disassembly of section .text: 00000000 <main>: 0: 3021ffd4 addik r1, r1, -44 4: f9e10000 swi r15, r1, 0 8: fa610028 swi r19, r1, 40 c: 12610000 addk r19, r1, r0 10: b00042f6 imm 17142 14: 3060e666 addik r3, r0, -6554 18: f8730024 swi r3, r19, 36 1c: b000440d imm 17421 20: 3060f8f6 addik r3, r0, -1802 24: f8730020 swi r3, r19, 32 28: 10600000 addk r3, r0, r0 2c: f873001c swi r3, r19, 28 30: e8b30024 lwi r5, r19, 36 34: e8d30020 lwi r6, r19, 32 38: b0000000 imm 0 3c: b9f40000 brlid r15, 0 40: 80000000 or r0, r0, r0 44: f873001c swi r3, r19, 28 48: e8b3001c lwi r5, r19, 28 4c: b0000000 imm 0 50: b9f40000 brlid r15, 0 54: 80000000 or r0, r0, r0 58: e9e10000 lwi r15, r1, 0 5c: 10330000 addk r1, r19, r0 60: ea610028 lwi r19, r1, 40 64: 3021002c addik r1, r1, 44 68: b60f0008 rtsd r15, 8 6c: 80000000 or r0, r0, r0 Trotzdem keine Multiplikation oder?
Habe gerade gesehen mit objdump -D app.o Disassembliert er alles. So erhalte ich: app.o: file format elf32-microblaze Disassembly of section .text: 00000000 <main>: 0: 3021ffd4 addik r1, r1, -44 4: f9e10000 swi r15, r1, 0 8: fa610028 swi r19, r1, 40 c: 12610000 addk r19, r1, r0 10: b00042f6 imm 17142 14: 3060e666 addik r3, r0, -6554 18: f8730024 swi r3, r19, 36 1c: b000440d imm 17421 20: 3060f8f6 addik r3, r0, -1802 24: f8730020 swi r3, r19, 32 28: 10600000 addk r3, r0, r0 2c: f873001c swi r3, r19, 28 30: e8b30024 lwi r5, r19, 36 34: e8d30020 lwi r6, r19, 32 38: b0000000 imm 0 3c: b9f40000 brlid r15, 0 40: 80000000 or r0, r0, r0 44: f873001c swi r3, r19, 28 48: e8b3001c lwi r5, r19, 28 4c: b0000000 imm 0 50: b9f40000 brlid r15, 0 54: 80000000 or r0, r0, r0 58: e9e10000 lwi r15, r1, 0 5c: 10330000 addk r1, r19, r0 60: ea610028 lwi r19, r1, 40 64: 3021002c addik r1, r1, 44 68: b60f0008 rtsd r15, 8 6c: 80000000 or r0, r0, r0 Disassembly of section .debug_abbrev: 00000000 <.debug_abbrev>: 0: 01110110 r8, r17, r0 4: 06120111 neg r16, r18 8: 01250813 r9, r5, r1 c: 0b03081b r24, r3, r1 10: 08000002 r0, r0, r0 14: 24000308 rsubi r0, r0, 776 18: 0b0b3e0b r24, r11, r7 1c: 00000324 r0, r0, r0 20: 00030e0b r0, r3, r1 24: 0b3e0b00 r25, r30, r1 28: 00041600 r0, r4, r2 2c: 03083a0b r24, r8, r7 30: 3b0b4913 addikc r24, r11, 18707 34: 0000052e r0, r0, r0 38: 0101133f r8, r1, r2 3c: 0c03083a r0, r3, r1 40: 0b3b0b27 r25, r27, r1 44: 0c491311 r2, r9, r2 48: 01120140 r8, r18, r0 4c: 06000006 neg r16, r0 50: 34000308 rsubik r0, r0, 776 54: 3a0b3b0b addikc r16, r11, 15115 58: 4913020a r8, r19, r0 5c: Address 0x0000005c is out of bounds. Disassembly of section .debug_info: 00000000 <.debug_info>: 0: 0000018a r0, r0, r0 4: 00020000 add r0, r2, r0 8: 00000401 r0, r0, r0 c: Disassembly of section .debug_line: 00000000 <.debug_line>: 0: 0000009c r0, r0, r0 4: 00020000 add r0, r2, r0 8: 00620101 r3, r2, r0 c: f6f50a00 shi r23, r21, 2560 10: 01010101 r8, r1, r0 14: 00000001 r0, r0, r0 18: 2e2e0000 rsubic r17, r14, 0 1c: 74797065 r3, r25, r14 20: 732e6800 r25, r14, r13 24: 01000069 r8, r0, r0 28: 6e74632e ncget r19, rfsl14 2c: 68000100 r0, r0, r0 30: 0074696d r3, r20, r13 34: 65722e68 r11, r18, r5 38: 00010000 add r0, r1, r0 3c: 6770696f bsrli r27, r16, 15 40: 2e680001 rsubic r19, r8, 1 44: 00007370 r0, r0, r14 48: 692e6800 r9, r14, r13 4c: 01000075 r8, r0, r0 50: 6172742e muli r11, r18, 29742 54: 68000100 r0, r0, r0 58: 00693263 r3, r9, r6 5c: 2e680001 rsubic r19, r8, 1 60: 00006170 r0, r0, r12 64: 702e6300 r1, r14, r12 68: 01000000 add r8, r0, r0 6c: 00050200 r0, r5, r0 70: 00000004 r0, r0, r0 74: 083b0005 r1, r27, r0 78: 02000000 add r16, r0, r0 7c: 10150005 r0, r21, r0 80: 02000000 add r16, r0, r0 84: 30150005 addik r0, r21, 5 88: 02000000 add r16, r0, r0 8c: 48270005 r1, r7, r0 90: 02000000 add r16, r0, r0 94: 58150005 r0, r21, r0 98: 02000000 add r16, r0, r0 9c: 70000101 r0, r0, r0 Disassembly of section .debug_frame: 00000000 <.debug_frame>: 0: 0000000c r0, r0, r0 4: ffffffff r31, r31, r31 8: 0100017c r8, r0, r0 c: 0f0c0100 r24, r12, r0 10: 00000018 r0, r0, r0 ... 1c: 00000070 r0, r0, r0 20: 440e2c48 bsll r0, r14, r5 24: 93018f0b r24, r1, r17 28: 440d1300 bsra r0, r13, r2 Disassembly of section .debug_loc: 00000000 <.debug_loc>: 0: Disassembly of section .debug_pubnames: 00000000 <.debug_pubnames>: 0: 00000017 r0, r0, r0 4: 00020000 add r0, r2, r0 8: Disassembly of section .debug_aranges: 00000000 <.debug_aranges>: 0: 0000001c r0, r0, r0 4: 00020000 add r0, r2, r0 8: 00000400 r0, r0, r0 ... 14: 00000070 r0, r0, r0 ... Disassembly of section .debug_str: 00000000 <.debug_str>: 0: 6c6f6e67 necaget r3, rfsl7 4: 20756e73 addi r3, r21, 28275 8: 69676e65 r11, r7, r13 c: 6420696e bsrli r1, r0, 14 10: Address 0x00000010 is out of bounds. Hier finde ich wenigstens muli. Was genau ich mit den verschiedenen Sektionen anfangen soll weiss ich leider nicht. Und warum er muli macht und nicht fmul ist mir auch völlig unklar. Vielleicht weisst du da mehr?
Alo das mit dem Cache hab ich jetzt hinbekommen, der war aus irgendeinem Grund nicht aktiv. Es lag entweder daran, dass der externe SDRam neben dem Cach Link auch über den OPB mit dem Microblaze verbunden war oder dass der Cache im Bootloader vor dem Starten der eigentlichen Application deaktiviert wurde und erst im Programm wieder aktiviert wurde. Jetzt hab ich das so geändert, dass der Cache nach dem Aktivieren im Bootloader garnicht mehr deaktiviert wird, funzt jetzt wunderbar. Siehe folgende Tabelle: Offset: start: 4999528, end: 4999513, diff: 15 SDRam schreiben ( 8Bit): start: 4784092, end: 4784058, diff: 19 SDRam lesen ( 8Bit): start: 4503296, end: 4503253, diff: 28 SDRam schreiben (16Bit): start: 4239792, end: 4239757, diff: 20 SDRam lesen (16Bit): start: 3958992, end: 3958944, diff: 33 SDRam schreiben (32Bit): start: 3695472, end: 3695438, diff: 19 SDRam lesen (32Bit): start: 3414672, end: 3414626, diff: 31 Zuweisung: start: 3151146, end: 3151124, diff: 7 U08 add: start: 2935143, end: 2935103, diff: 25 U08 sub: start: 2723464, end: 2723419, diff: 30 U08 mul: start: 2511766, end: 2511725, diff: 26 U08 div: start: 2300109, end: 2300033, diff: 61 U16 add: start: 2088426, end: 2088379, diff: 32 U16 sub: start: 1876745, end: 1876699, diff: 31 U16 mul: start: 1665074, end: 1665016, diff: 43 U16 div: start: 1453372, end: 1453295, diff: 62 U32 add: start: 1241710, end: 1241683, diff: 12 U32 sub: start: 1030012, end: 1029985, diff: 12 U32 mul: start: 818339, end: 818310, diff: 14 U32 div: start: 615286, end: 615224, diff: 47 U64 add: start: 412249, end: 412203, diff: 31 U64 sub: start: 209222, end: 209180, diff: 27 U64 mul: start: 6183, end: 6112, diff: 56 U64 div: start: 4820419, end: 4819160, diff: 1244 F32 add: start: 4600115, end: 4599307, diff: 793 F32 sub: start: 4384102, end: 4383622, diff: 465 F32 mul: start: 4168096, end: 4167600, diff: 481 F32 div: start: 3952109, end: 3951432, diff: 662 F64 add: start: 3736102, end: 3734842, diff: 1245 F64 sub: start: 3515769, end: 3515123, diff: 631 F64 mul: start: 3299784, end: 3298865, diff: 904 F64 div: start: 3083787, end: 3081715, diff: 2057 Das sieht shcon um eineiges besser aus als vorher, damit kann man auch schon fast leben denk ich. Das einzige Problem was ich jetzt noch habe ist die FPU. Diese scheint immernoch deaktiv sein und ich vermute es liegt am Compiler. Ich muss dies wohl erst irgendwie in den Compiler-Options aktivieren, nur wie?
Habs gerade mal provbiert, mit der Option macht er die HW mul/add. ABER!!:
1 | F32 x1=123.45,x2=567.89,x3=0.0; |
2 | x3=x1*x2; |
3 | return (int)x3; |
Wird er (berechtigterweise) als konstanten Ausdruck auswerten! daher:
1 | volatile F32 x1, x2, x3; |
2 | int main (void) |
3 | {
|
4 | x1=123.45; |
5 | x2=567.89; |
6 | x3=x1*x2; |
7 | return (int)x3; |
8 | }
|
wird bei mir zu:
1 | main: |
2 | addik r3,r0,0x42f6e666 |
3 | addik r4,r0,0x440df8f6 |
4 | addik r1,r1,-28 |
5 | swi r3,r0,x1 |
6 | swi r4,r0,x2 |
7 | lwi r3,r0,x1 |
8 | lwi r4,r0,x2 |
9 | swi r15,r1,0 |
10 | fmul r3,r3,r4 |
11 | swi r3,r0,x3 |
12 | lwi r5,r0,x3 |
13 | brlid r15,__fixsfsi |
14 | nop # Unfilled delay slot |
15 | |
16 | lwi r15,r1,0 |
17 | rtsd r15,8 |
18 | |
19 | addik r1,r1,28 |
20 | |
21 | .end main |
Genau den Link (http://www.xilinx.com/support/answers/31770.htm) hab ich auch gerade gefunden, jetzt funzt es... Aktuelle Werte: Offset: start: 4999540, end: 4999525, diff: 15 SDRam schreiben ( 8Bit): start: 4784076, end: 4784042, diff: 19 SDRam lesen ( 8Bit): start: 4503281, end: 4503238, diff: 28 SDRam schreiben (16Bit): start: 4239779, end: 4239744, diff: 20 SDRam lesen (16Bit): start: 3958967, end: 3958919, diff: 33 SDRam schreiben (32Bit): start: 3695438, end: 3695404, diff: 19 SDRam lesen (32Bit): start: 3414638, end: 3414592, diff: 31 Zuweisung: start: 3151124, end: 3151102, diff: 7 U08 add: start: 2935136, end: 2935096, diff: 25 U08 sub: start: 2723454, end: 2723405, diff: 34 U08 mul: start: 2511759, end: 2511716, diff: 28 U08 div: start: 2300100, end: 2300024, diff: 61 U16 add: start: 2088420, end: 2088373, diff: 32 U16 sub: start: 1876745, end: 1876699, diff: 31 U16 mul: start: 1665060, end: 1665002, diff: 43 U16 div: start: 1453364, end: 1453287, diff: 62 U32 add: start: 1241706, end: 1241679, diff: 12 U32 sub: start: 1030026, end: 1029999, diff: 12 U32 mul: start: 818334, end: 818305, diff: 14 U32 div: start: 615304, end: 615242, diff: 47 U64 add: start: 412261, end: 412215, diff: 31 U64 sub: start: 209217, end: 209175, diff: 27 U64 mul: start: 6178, end: 6107, diff: 56 U64 div: start: 4820387, end: 4819029, diff: 1343 F32 add: start: 4600088, end: 4600050, diff: 23 F32 sub: start: 4388401, end: 4388363, diff: 23 F32 mul: start: 4176730, end: 4176692, diff: 23 F32 div: start: 3965045, end: 3964994, diff: 36 F64 add: start: 3753370, end: 3752155, diff: 1200 F64 sub: start: 3533039, end: 3532359, diff: 665 F64 mul: start: 3317044, end: 3313812, diff: 3217 F64 div: start: 3096724, end: 3094759, diff: 1950 Das sieht doch schonmal nicht schlecht aus. Ich glaube dass er das bei mir nicht als konstanten Ausdruck wertet, sonst hätten sich die Werte nicht so geändert, kann aber auch daran liegen, dass ich momentan die Optimierung auf 0 habe. Das Einzige was mich jetzt noch stört sind die anderen hohen Werte: einmal die U64 Division unddie F64 Operationen. Lässt sich da noch was amchen oder ist das nicht möglich, da es dafür evtl garkeine Hardware Unterstützung gibt?
Achso, das volatile hab ich natürlich auch davor, aber hab die Variablen lokal und nicht global, sollte aber beiden gehn denk ich
U64 und F64 wird in software gemacht... Könnte man aber wenns exessiv genuzt wird in nen Extra core auslagern.
Vielen Dank erstmal für deine Hilfe, hat mich wirklich ein gutes Stück weiter gebracht. Naja, denke das ist vorerst nicht nötig ist U64 und F32 in Hardware zu erledigen, aber wenn, dann würde man das über diesen FSL Link machen oder? Ich lasse den Microblaze im Moment mit 50 MHz laufen, den SDRam Controller mit 100MHz, das geht ganz gut so und ich konnte so auch noch etwas Performance rausholen. Der Microblaze könnte auch noch etwas schneller laufen, aber der SDRam Controller will nicht schneller glaube nicht. Leider muss, so wie ich das sehe, die Frequenz des SDRam Controllers durch die Frequenz des Microblaze teilbar sein, deswegen kann ich den Microblaze im Moment nicht schneller laufen lassen oder ist diese Annahme falsch? Kann man den Microblaze auch mit 75MHz laufen lassen und den SDRam mit 100MHz? Nutzt du die Library die Xilinx für die IPCores mitliefert? Was hälst du von diesen Libraries? Ich finde die irgendwie sehr unpraktisch und unübersichtlich. Ich habe jetzt für die IPCores die ich verwende eigene Libs geschrieben und komme damit sehr viel besser klar, und schneller sind die alle mal...
ChrisB wrote: > Hallo, > ... > Zuweisung "i=1;" 92 Takte > SDRam 32Bit schreiben 127 Takte > SDRam 32Bit lesen 99 Takte > Float multiplizieren 28795 Takte > Float dividieren 18091 Takte > > Diese paar Werte sollen erstmal reichen. > Was mir direkt aufgefallen war ist, dass die Werte allgemein doch sehr > hoch sind. Wie kommen diese hohen Werte zustande? Vor allem bei den > Float-Multiplikation gibt Xilinx an, dass diese in 4 takten, die > Division in 28 Takten zu schaffen sei. Da bin ich aber doch sehr weit > entfernt, obwohl der Haken bei FPU in den Microblaze Einstellungen > vorhanden ist. > Aber auch das Lesen und Schreiben vom SDRam müsste doch in 10 Takten zu > schaffen sein oder etwa nicht? Mache ich bei der Auswertung etwas > falsch? Bei der Opitimiereng die der Compiler vornehmen kann habe ich > alle Einstellungen ausprobiert, jedoch ohne großartige Änderungen. > Vielleicht hat ja von euch jemand eine Idee, was hier schief geht... > Gruß, Christoph scheint mir ja auch wirklich arg lang zu sein... hast du schon den Parameter 'C_AREA_OPTIMIZED = 0' gesetzt? damit sollte die Taktzahl um einiges runtergehen.
Hannes Pauli wrote: > ChrisB wrote: [..] > scheint mir ja auch wirklich arg lang zu sein... > hast du schon den Parameter 'C_AREA_OPTIMIZED = 0' gesetzt? > damit sollte die Taktzahl um einiges runtergehen. Schon längst geklärt wodran es gelegen hat ;) @ChrisB: Sorry ich fürchte da kann ich dir nicht weiterhelfen habe mich mit SDRam bisher noch garnicht beschäftigt. Die IP Cores habe ich bisher entweder in ASM oder direkt über In/Out in C angesprochen, die Libs von Xilinx sind mir da immer etwas zu undurchsichtig gewesen... Ob man das ganze über den FSL Link oder über PLB/OPB macht ist ne Geschmacks und aufwandsfrage... OPB für "langsame" Perepherie wie Timer, UARTs etc, und PLB für die schnellen Sachen wie DMA haben halt den Vorteil das sie Memmory Mapped angesprochen werden können, dafür ist das Interface recht komplex. Beim FSL muß man halt den Zugriff selber regeln, dafür ist das Interface sehr simpel und ich benutz das gerade für meine Diplomarbeit, ist eigentlich wenn man sich ein paar Gedanken macht ne feine Sache.
Ja, ist schon geklärt, aber der C_AREA_OPTIMIZED Parameter ist auf 0. Ich mache mir gerade ein paar Gedanken ob die Performance des Microblaze nun ausreichen wird oder nicht. Mal angenommen der Microblaze muss dauerhaft mit 115200 per Uart kommunizieren (Interrupt-gesteuert mit Ringpuffern) dann hat der, wenn er mit 50MHz läuft und die oben genannten Zeiten benötigt doch so einiges zu tun denk ich... Um dann noch großartig zu rechnen, auf einem Display was darzustellen oder ein RTOS aufzusetzen ist da wahrscheinlich nicht mehr so viel Performance oder? Aber wahrscheinlich kann ich das erst sagen, wenn ich das praktisch mal ausprobiert habe. Im schlimmstne Fall muss ich vom Spartan 3 mit SDRam auf einen Viertex5 mit DDR2 Ram umsteigen, da sollte dann doch einiges mehr drin sein denk ich mal. Ich werde weitere Ergebnisse hier berichten.
Naja, der MicroBlaze ist halt nur ein Softcore, da ist ja einiges etwas beschränkt. Gibts denn da keinen DMA Controller, wie den MPMC beim Virtex 4? Da könntest du die CPU schon recht gut entlasten. Wir arbeiten hier mit dem Virtex 4 FX20, da geht schon gut die Post ab. Einmal eingestellt, streamt der MPMC die Daten vom GbE MAC zur externen Hardware und zurück per DMA, und die CPU langweilt sich. Die UDP/IP Frames werden wo es geht durch den Scatter-Gather DMA zusammengebastelt.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.