Hallo allerseits, ich beschäftige mich gerade damit, Elm Chans FFT-Code zu verstehen, und den in C nachzubauen. (Bevor jetzt gleich wieder die ASM-Prediger sich berufen fühlen zu predigen: Bitte nicht....) Leider bin ich ziemlich schwach in Assembler, aber das wird schon... Nachdem meine ersten Versuche allein mit dem preprocessing (Windowing) dauernd falsche Ergebnisse geliefert haben, bin ich draufgekommen, dass dort intensiv mit der AVR-eigenen Festkomma-Arithmetik (sprich: FMULS) gearbeitet wird. Damit hatte ich noch nie zu tun, glaube aber die grundlegend verstanden zu haben. Nun frage ich mich, wie man das in C macht. Dabei bin ich draufgekommen, dass der GCC ja eh (zumindest rudimentär) Festkomma-Arithemtik kann (mit dem Datentyp _Fract), allerdings bin ich noch nicht dahintergestiegen ob und wie das zusammenpasst... Weiss jemand wie gut und effizient die Festkomma-Arithemtik am AVR arbeitet? In ein paar einfachen (und konfusen) Beispielen ist mir jedenfalls noch keine FMUL-Instruktion untergekommen. nebenbei gibts im avr-gcc ja ein paar builtins für fmul. Hilft mir das weiter?
Michael Reinelt schrieb: > Nachdem meine ersten Versuche allein mit dem preprocessing (Windowing) > dauernd falsche Ergebnisse geliefert haben, bin ich draufgekommen, dass > dort intensiv mit der AVR-eigenen Festkomma-Arithmetik (sprich: FMULS) > gearbeitet wird. Damit hatte ich noch nie zu tun, glaube aber die > grundlegend verstanden zu haben. > > Nun frage ich mich, wie man das in C macht. Genau wie in Assembler. Der Algorithmus bleibt ja der gleiche. > Dabei bin ich draufgekommen, dass der GCC ja eh (zumindest > rudimentär) Festkomma-Arithemtik kann (mit dem Datentyp _Fract), Es gibt { fract, accum } * { short, /**/, long, long long } * {signed, unsigned } * { /**/, sat } = 2 * 4 * 2 * 2 = 32 unterschiedliche Fixed-Point Typen. > allerdings bin ich noch nicht dahintergestiegen ob und wie das > zusammenpasst... > > Weiss jemand wie gut und effizient die Festkomma-Arithemtik am > AVR arbeitet? So gut oder schlecht wie GCC / avr-gcc / libc diese unterstützen. Unterstützung von Seiten der libc: Momentan keine. Dies wären vor allem Erweiterungen von printf / scanf etc, die mangels Bedarf noch niemand beigetragen hat. Unterstützung avr-gcc / avr-libgcc: Für die meisten nicht-saturierenden Typen <= 32 Bit sind Grundarithmetik (+, -, *, /, Vergleiche, Typ-Umwandlung) in Assembler implementiert. In manchen Fällen nativ inline, ansonsten per Assembler in der libgcc. Dies gilt auch für einige oder alle saturierende Typen für +, -, Vergleiche. Elementare Funktionen aus stdfix.h sind per Built-in Funktionen implementiert und werden durch stdfix.h darauf abgebildet; dies sind abs?, round?, countls?, ?bits und bits?. Die Typ-generischen Funktionen absfx, roundfx und counlsfx sind überladen und bilden auf die entsprechende Built-in Funktion ab. > In ein paar einfachen (und konfusen) Beispielen ist mir > jedenfalls noch keine FMUL-Instruktion untergekommen. fmul[s[u]] sind für Fixed-Point Arithmetik i.W. nutzlos und werden daher auch nur in sehr wenigen Fällen erzeugt, etwa bei short fract Multiplikation. Aber bereits bei unsigned short fract, short sat fract oder short accum oder unsigned short accum kann man nix mehr damit anfangen. > nebenbei gibts im avr-gcc ja ein paar builtins für fmul. Hilft mir das > weiter? Je nachdem, was du machen willst und brauchst (oder glaubst zu brauchen). Die o.g. 32 Fixed Typen im Verbund mit den 9 Standard-Typen (float + { signed, unsigned } * { char, int, long, long long } = 1 + 2 * 4 ergeben bereits 41 unterschiedliche Typen, die man z.B. ineinander umwandeln (casten) kann. Bei t = 41 Typen und s = 9 Standard-Typen sind das bereits t * t - s * s - (t - s) = 1568 mögliche Typ-Casts, wobei triviale Casts und solche zwischen Standard-Typen bereits außen vor sind. In Anbetracht der Fülle an Typen und Operationen ist es kaum möglich sinnvoll auf deine Frage zu Antworten und auf jede mögliche Kombination von Typen und Operation einzugehen. An einfachsten schaust du dir also die entsprechenden Header und Quellen des avr-gcc an. Jeder, der ein bisschen programmieren, AVR-Assembler und abstrakt denken kann, sollte nach einigen Minuten die Transferleistung erbringen können, zu beurteilen, ob die von ihm / ihr benötigten Funktionen mit der gewünschten Effizienz und / oder Rundungsgenauigkeit zur Verfügung stehen. stdfix.h: http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/avr/stdfix.h?view=markup avr-libgcc (fixed) http://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/avr/lib1funcs-fixed.S?view=markup Einiges davon verwendet den nicht-fixed Teil: http://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/avr/lib1funcs.S?view=markup Was in der avr-libgcc in Assembler steht kann auch daraus entnommen werden, was alles aus dem Umfang der default libgcc entfernt wird. Make-Schnippel: http://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/avr/t-avr?revision=216525&view=markup#l212 Was nativ inline expandiert, ist Teil der Maschinenbeschreibung. "define_insn" liest sich wie Inline-Assembler, nur dass es zusätzlich eine algebraische Umschreibung davon enthält: Fixed-Teil der Maschinenbeschreibung (<= 32 Bits): http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/avr/avr-fixed.md?view=markup http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/avr/avr.md?view=markup Falls für 64-Bit Operationen spezieller Code erzeugt wird, dann ist der in: http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/avr/avr-dimode.md?view=markup Falls define_insn kein asm-Template hat, dann ist es ein C/C++-Schnippel, der i.d.R. Support-Funktionen aus dem C/C++-Teil verwendet (z.B. avr_out_fract, avr_out_plus, avr_out_round, avr_out_compare, avr_out_compare64, avr_out_bitop, ...): http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/avr/avr.c?view=markup
:
Bearbeitet durch User
Johann L. schrieb: > In Anbetracht der Fülle an Typen und Operationen ist es kaum möglich > sinnvoll auf deine Frage zu Antworten und auf jede mögliche Kombination > von Typen und Operation einzugehen. Wow, und ob die Antwort sinnvoll war! Danke! Da bin ich jetzt erstmal beschäftigt mit Lesen... (wenn nur der Sch*ss Beruf nicht wäre...) die stdfix.h hab ich mittlerweile auch gefunden, ich hab nur falsch gesucht (die gehört ja zum gcc, nicht zur libc) In der Zwischenzeit versuche ich intensiv, den originalen asm-Code zu verstehen, da komm ich langsam voran. Dann schau'mer mal wie sich das in C umsetzen lässt. ich fürchte nur das wird ein unfairer Vergleich, weil Elm-Chans asm schonmal von Haus aus nicht der Schlechteste ist, und er natürlich auf viele Sonderfälle (Überlauf bei -1*-1 etc) erst gar nicht reagiert, weil er das schon vorab ausschließt. Aber ich finde die Fract-Unterstützung extrem spannend! An der Stelle einen ganz herzlichen Dank für deinen Einsatz, Johann!
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.