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?).
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?
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
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?
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.