es ist ein Befehlssatz und die Anordnung ist nicht zwingend Sortiert oder in irgend einer Art fortlaufend, im Moment habe ich versucht den Worst-Case zu unterdrücken indem ich die Befehle in der Initialisierungstabelle einfach nach Aufruf-Häufigkeit und nachfolgendem Rechenaufwand sortiert habe(Rechenaufwand = "decodierung" von Parametern <kurzwierig> oder instant-response <langwierig>, z.B.), aber das kann nicht das Maß der Dinge sein dass ich an der Datenbasis tunen muss! Ich tune lieber die Verarbeitung.
Einen Teilerfolg habe ich ja schonmal mittels 108Byte RAM erkauft indem ich eine LookUp dort hinterlegt habe und einfach den Index synchron halte mit der Tabelle was aber nicht Failsafe ist! Und die 108Byte RAM schmerzen gewaltig wenn ich mir das alle so ansehe. Und es werden noch einige Befehle hinzukommen was wieder jeweils 2 Byte weniger RAM bedeutet.
Die Hardware ist im übrigen bereits ausgereizt, da gibt es keine Luft mehr. Aber ich habe mir vorgenommen, wenn ich mal meine eigenen Vorstellungen umsetzen darf, dass ich das EBI Interface des XMega zu meinem Vorteil nutzen werde! 64MHz Bustakt und Memory Mapping sollten mit einem guten Framework-Design die Möglichkeiten erweitern ... aber auch die Platinengröße :<
[NACHTRAG]
okay in meinem disassembly ist mir ein feines aber BÖSES detail entgangen, ich habe eine "CALL" answeisung ignoriert welche mir überraschenderweise bei memcpy und memcmp zusätzliche 28 zyklen serviert ... ich denke mit der ersparnis durch pgm_read_word() sollte sich die Lage schon einmal gewaltig entspannen. Statt 32+28 bzw. 28+28 nur 25 Zyklen scheint mir schon ausreichend und würde auch erklären warum die Zyklen Anzahl sich im Praxistest als nicht nachvollziehbar darstellte, jetzt ergeben meine Zeitmessungen auch wesentlich mehr sinn! Mittlerweilen bin ich mir auch ziemlich sicher dass bei allen 3 Varianten mit progmem die Endianess mir einen Strich durch die Rechnung macht oder wie kann man folgendes Disassembly sinnvoll erklären ?
Code:
000010C9 1 MOVW R24,R16 Copy register pair
000010CA 1 MOVW R22,R24 Copy register pair
000010CB 1 LSL R22 Logical Shift Left
000010CC 1 ROL R23 Rotate Left Through Carry
000010CD 1 LSL R24 Logical Shift Left
000010CE 1 ROL R25 Rotate Left Through Carry
000010CF 1 LSL R24 Logical Shift Left
000010D0 1 ROL R25 Rotate Left Through Carry
000010D1 1 LSL R24 Logical Shift Left
000010D2 1 ROL R25 Rotate Left Through Carry
000010D3 1 ADD R22,R24 Add without carry
000010D4 1 ADC R23,R25 Add with carry
000010D5 1 SUBI R22,0x5F Subtract immediate
000010D6 1 SBCI R23,0xFD Subtract immediate with carry
000010D7 1 MOVW R30,R22 Copy register pair
000010D8 3 LPM R24,Z+ Load program memory and postincrement
000010D9 3 LPM R25,Z Load program memory
000010DA 1 CP R24,R10 Compare
000010DB 1 CPC R25,R11 Compare with carry
000010DC 2 BRNE PC-0x1A Branch if not equal
[FACEPALMMODE]
ja jetzt wird mir einiges klarer
Code:
if(pgm_read_word(&table[i].someval) == input)
er muss ja erst den offset der Variable im Struct umrechnen bzw. den Offset im Array ... ich sollte manchmal nicht einfach das übernehmen was mir vorgegeben wurde
Code:
uint16_t *ptr = &table[i].someval;
if(pgm_read_word(ptr) == input)
das sollte auch unnötige Takte bei der späteren Verarbeitung sparen!
[/FACEPALMMODE]
[NACHTRAG]
Code:
const uin16_t ptr= &progmemtable[i].someval;
000010C8 MOVW R24,R16 Copy register pair
000010C9 MOVW R30,R24 Copy register pair
000010CA LSL R30 Logical Shift Left
000010CB ROL R31 Rotate Left Through Carry
000010CC LSL R24 Logical Shift Left
000010CD ROL R25 Rotate Left Through Carry
000010CE LSL R24 Logical Shift Left
000010CF ROL R25 Rotate Left Through Carry
000010D0 LSL R24 Logical Shift Left
000010D1 ROL R25 Rotate Left Through Carry
000010D2 ADD R30,R24 Add without carry
000010D3 ADC R31,R25 Add with carry
000010D4 SUBI R30,0x5F Subtract immediate
000010D5 SBCI R31,0xFD Subtract immediate with carry
if(pgm_read_word(ptr) == input)
000010D6 LPM R24,Z+ Load program memory and postincrement
000010D7 LPM R25,Z Load program memory
000010D8 CP R24,R10 Compare
000010D9 CPC R25,R11 Compare with carry
000010DA BRNE PC-0x18 Branch if not equal
und schon spare ich mir runde 14Takte bei folgeaufrufen auf die Variable ... leider muss ich mir jeden Wert einzeln pointern
Frage: gib es einen weg die Adresse eines Wertes innerhalb eines Structs auf Basis eine Pointers auf den Anfang selbigen Structs zu ermitteln?
Code:
tyble_t *ptr = &table[i];
if(pgm_read_word(ptr+offset(someval)) == input)
Antwort: JA und es ist optimiert sich quasi von allein weg!
Code:
table_t *pt = &progmemtable[i];
000010C8 MOVW R22,R16 Copy register pair
000010C9 LSL R22 Logical Shift Left
000010CA ROL R23 Rotate Left Through Carry
000010CB MOVW R24,R16 Copy register pair
000010CC LSL R24 Logical Shift Left
000010CD ROL R25 Rotate Left Through Carry
000010CE LSL R24 Logical Shift Left
000010CF ROL R25 Rotate Left Through Carry
000010D0 LSL R24 Logical Shift Left
000010D1 ROL R25 Rotate Left Through Carry
000010D2 ADD R22,R24 Add without carry
000010D3 ADC R23,R25 Add with carry
000010D4 MOVW R30,R22 Copy register pair
000010D5 SUBI R30,0x5F Subtract immediate
000010D6 SBCI R31,0xFD Subtract immediate with carry
if(pgm_read_word(pt+offsetof(table_t,someval)) == input)
000010D7 LPM R24,Z+ Load program memory and postincrement
000010D8 LPM R25,Z Load program memory
000010D9 CP R24,R10 Compare
000010DA CPC R25,R11 Compare with carry
000010DB BRNE PC-0x19 Branch if not equal
und bevor hier jetzt sowas kommt von wegen "das hätte ich auch gewusst, ist ja teil von stdlib" ... zeige mir den nicht autistischen menschen der aus dem stehgreif die ganze stdlib ohne nachschlagen oder google herbeten kann da gibt es mehr zu wissen als man wieder vergessen kann und was man nicht alltäglich verwendet vergisst man nach der schule ganz schnell wieder ... ich hab meinen post bewusst so gelassen damit jemand der etwas ähnliches sucht den gedankengang später nachvollziehen kann ...
und zum thema Design .... Design ist ne Frage der Sicht auf die Bäume ... mal sieht man den Wald mal nicht, kommt drauf an wie tief man drinsteckt
Schade ... gerade eben habe ich erfahren dass offsetof() laut misra verboten ist weil unzuverlässig ... bleibt wohl doch nur das redesign
Lesezeichen