Documente Academic
Documente Profesional
Documente Cultură
15
16
StarCore are un set dual de instruciuni pentru operaii aritmetice, cu rezultate diferite n funcie de tipul datelor folosit: fracionar sau ntreg. Setul de instruciuni este echivalent cnd o operaie cu ntregi sau cu fracii conduce la acelai rezultat, neinndu-se cont de tipul operaiei, de exemplu la adunare. Setul de instruciuni este dual (acioneaz diferit) n dou cazuri, situaii n care se realizeaz n mod automat aliniamentul datelor, extensia semnului i completarea cu zero:
Cnd se face transferarea datelor din/n memorie (Figura 2.1). Cnd o operaie cu ntregi sau cu fracii conduce la un rezultat diferit depinznd de tipul operaiei desfurate, de exemplu, o nmulire (Figura 2.2);
-215 214 20 ntreg .
2.1 Operaii aritmetice cu numere ntregi i fracionare 2.1.1 Interpretarea numerelor fracionare i ntregi Unul dintre punctele forte ale arhitecturii StarCore ct i ale compilatorului acestuia o reprezint abilitatea de a rula operaii aritmetice att cu numere ntregi ct i cu numere fracionare. Pentru numere ntregi, punctul binar este considerat ca a fi imediat cel din dreapta LSB (bitului cel mai puin semnificativ). Pentru cazul fracionar, punctul binar este considerat a fi imediat n dreapta MSB (bitului cel mai mult semnificativ). n tabelul 2.1 sunt ilustrate reprezentrile pe 16 bii a diferitelor valori. Tabelul 2.1 Reprezentare n binar
0100 0000 0000 0000 0001 0000 0000 0000 0000 0000 0000 0000 1100 0000 0000 0000 1111 0000 0000 0000
MOVE.W (Rn),Dn
Reprezentare hexazecimal
0x4000 0x1000 0x0000 0xC000 0xF000
Reprezentare ca ntregi
16384 4096 0 -16384 -4096
Reprezentare ca fracionar
0.5 0.125 0.0 -0.5 -0.125
-20 2-1 s. fractie 2-15
-239 s
232 231
20 ntreg
Dn.l
Dn.e
Dn.h
MOVE.F (Rn),Dn
Dup cum se observ, aceeai reprezentare binar poate fi interpretat ca numr ntreg i sau ca numr fracionar f, relaia ntre cele dou reprezentri fiind:
-28 s
21 20 2-1
2-31 0
s.
Dn.e
Dn.l
i = f 2B
B = 15bii
Figura 2.1. Transferul numerelor ntregi i a numerelor fracionare din memorie n registre
17
S
18
S X
. .
S S
Sintaxa funciilor intrinseci este compatibil cu implementrile de referin ETSI sau ITU pentru standardele bit-exact (precizie finit). De exemplu, funcia intrinsec L_mac() este folosit n urmtorul exemplu (figura 2.3). Exemplul ilustreaz cum sunt plasate instruciunile n funcie de tipul operaiei aritmetice cerute. Pentru o operaie aritmetic de tipul celeia n care se vor folosi ntregi, compilatorul genereaz instruciuni de tip ntreg (cum ar fi cea de tip imac), iar pentru operaiile cu numere fracionare genereaz instruciuni fracionare (de exemplu mac). De asemenea instruciunile de tip move sunt generate cu aliniamentul datelor corect
nmulire cu semn
X nmulire cu semn
MSP
. .
2N Bii
LSP
. .
MSP
. .
2N Bii
LSP
Figura 2.3. Pentru a utiliza ntr-un program C operaii pe numere fracionare trebuie inclus fiierul prototype.h unde sunt definite funciile intrinseci. O list complet a funciilor intrinseci pentru aritmetica fracionar poate fi gsit n Manualul de utilizare al compilatorului C pentru SC140 sau n meniul Help. Tabelul 2.3 Funcie
abs_s add div_s extract_h extract_l
Compilatorul C pentru StarCore suport funcii construite intrinsec care asociaz operaiilor aritmetice cu numere fracionare direct instruciunile de asamblare corespunztoare. Deoarece limbajul C nu are o reprezentare pentru tipurile i operaiile cu numere fracionare, funciile intrinseci permit folosirea datelor de tip ntreg pentru a implementa operaii de tip fracionar. Orice valori fracionare sau constante trebuie de aceea s fie definite utilizndu-se echivalentul acestora n ntreg. Relaiile pentru a obine aceste reprezentri n ntreg din cele de tip fracionar sunt:
16 bii: 32 bii: 40 bii:
Sintax Word16 abs_s(Word16 var1) Word16 add(Word16 var1, Word16 var2) Word16 div_s(Word16 var1, Word16 var2); Word16 extract_h(Word32 L_var1); Word16 extract_l(Word32 L_var1);
valoare ntreag = valoare fracionar * 215. valoare ntreag = valoare fracionar * 231. valoare ntreag = valoare fracionar * 239.
19
20
Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2); Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2); Word16 mac_r(Word32 L_var3,Word16 var1, Word16 var2); Word16 max(Word16 var1, Word16 var2); Word16 mult(Word16 var1, Word16 var2); Word16 round(Word32 L_var1); Word16 saturate(Word32 L_var1); Word16 shl(Word16 var1, Word16 var2); Word16 shr(Word16 var1, Word16 var2); Word16 sub(Word16 var1, Word16 var2);
De asemenea, se recomand utilizarea unor tipuri de date n declararea variabilelor echivalente cu formatul fracionar. Tabelul 2.4 Date fracionare
Word16 Word32
Tip echivalent n C
short long/int
Iniializarea variabilelor declarate de tip Word16, Word32 etc. cu valori de tip fracionar se face cu macrourile WORD16() sau WORD32(). De exemplu:
Word16 x = WORD16(0.5);
1. Se creeaz un proiect nou StarCore Stationery (salvat n directorul C:/freescale/apsc/grupa). Proiectul trebuie s fie pentru SC100Simulator de tip C, Big Endian.
21
22
Se deschide (Open) fisierul starcore_main.sl generat dup compilare. Operaia de sum de produse este realizat n asamblare cu instruciunea imac. Codul n asamblare nu este optimizat i este mai greu de urmrit. Se deschide din nou fereastra Settings i la seciunea Optimizations se alege Level 2 de optimizare.
%d
($%x)\n",res,res);
Se compileaz (F7 sau butonul Make) i se ruleaz n Debugger (F5 sau Debug).
2. Pentru a vedea i codul n limbaj de asamblare generat la compilare trebuie setat n fereastra C for SC Settings (butonul cu acelai nume sau Alt+F7), la seciunea pentru Compilator, opiunea Keep .sl Files.
Se recompileaz programul. n fiierul starcore_main.sl apar unele schimbri: reducerea dimensiunii programului i gruparea instruciunilor imac.
3. S se modifice programul anterior astfel ca s se calculeze suma ptratelor a 4 numere fracionare. Se vor considera numerele fracionare care au aceeai reprezentare n binar ca numerele ntregi 10, 20, 30, 40. De exemplu pentru 10 avem: 10 * 2^-15 = 0.00030517578125 etc.
23
24
Exerciiul urmtor arat diferena ntre dou opiuni ale compilatorului C: optimizarea local(predefinit) i optimizarea global. Optimizarea local compileaz fiecare fiier al proiectului individual dup cum e prezentat n Figura 2.5. Optimizarea global se comport ca un combinator global care unete toate fiierele reprezentate intermediar (IR) ntr-un singur fiier intermediar nainte de optimizarea aplicaiei (Figura 2.6). Din moment ce toat informaia codului aplicaiei este disponibil, aceasta aduce o optimizare n plus fa de folosirea unei optimizri separate.
25
26
int main(void) { int i; Word32 result = 0; for(i=0; i<200; i++) { result += Prod(&array1[0],&array2[0]); }
/*apel subrutina*/
prod.c
#include <prototype.h> #define LENGTH 10 Word32 Prod(Word16 a1[], Word16 a2[]) { Word16 j; Word32 res_rout = 0; for(j=0; j<LENGTH; j++) { res_rout += a1[j] * a2[j]; } return res_rout; }
EXERCIIU:
n exemplul urmtor sunt folosite dou fiiere: fiierul principal numit main.c. fiierul funcie numit prod.c. Fiierul principal main.c apeleaz o rutin definit n fiierul funcie prod.c.
main.c
#include <prototype.h> #define LENGTH 10 Word16 array1[LENGTH] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Word16 array2[LENGTH] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; volatile Word32 volatile_result;
Compilarea fr optimizare Se seteaz n fereastra Settings (butonul cu acelai nume sau Alt+F7), la seciunea pentru Compilator, opiunea Keep .sl Files. Se compileaz cu Level 0 optimizare. Se observ apariia a dou fiiere main.sl i prod.sl.
27
28
De obicei, aplicaiile DSP folosesc o mbinare ntre programe scrise n limbajul C i limbajul de asamblare. Acest exercitiu arat cum o funcie scris n limbaj de asamblare poate fi apelat din codul C. Acest exercitiu const n dou fiiere: main.c i addvecs.asm. Programul main.c apeleaz funcia din programul de asamblare, n fiierul addvecs.asm, pentru a suma doi vectori element cu element ntr-un al treilea vector i s se returneze i suma tuturor elementelor vectorului rezultant. addvecs.h
extern Word16 addvecs ( Word16 x[], /* Word16 y[], /* Word16 z[], /* Word16 M /* );
*/ */ */ */
main.c
#include <prototype.h> #include <stdio.h> #include "addvecs.h" /* Prototype for function addvecs() */ #define LENGTH 8 int main(void) { Word16 x[LENGTH] = {1, 2, 3, 4, 5, 6, 7, 8}; Word16 y[LENGTH] = {2, 3, 4, 5, 6, 7, 8, 9}; Word16 z[LENGTH]; Word16 reference[LENGTH] = {3, 5, 7, 9, 11, 13, 15, 17}; Word16 sum; Word16 reference_sum = 80; sum = addvecs (x, y, z, LENGTH); /*** Verify output vector z[] and sum ***/ { Word16 i; for (i=0; i<LENGTH; i++) { if (z[i] != reference[i])
Optimizarea global Se selecteaz opiunea Global Optimization. Dup compilare se observ c fiierul prod.sl dispare iar n fiierul main.sl apare i coninutul funciei prod optimizat n cadrul programului principal.
29
30
; -----------------------------------------------------------------; *** Sum elements of z[] *** ; -----------------------------------------------------------------doensh3 d0 move.l (sp+Z_OFFSET),r0 clr d3 LOOPSTART3 move.w (r0)+,d2 add d2,d3,d3 LOOPEND3 ; Set up loop count and loop flag. ; r0 = &z[0] (Output array). ; d3 (sum) = 0.
; -----------------------------------------------------------------tfr d3,d0 rts ??? ??? GLOBAL F_addvecs_end F_addvecs_end SIZE _addvecs,*-_addvecs ENDSEC END ; Copy d3 into d0 for return.
addvecs.asm
Z_OFFSET M_OFFSET EQU EQU
SECTION .text LOCAL GLOBAL _addvecs ALIGN 16 _addvecs TYPE FUNC move.w (sp+M_OFFSET),d0 ; d0 = M (length of vectors).
; ----------------------------------------------------------------; *** Add vectors together (z[i] = x[i] + y[i]) *** ; ----------------------------------------------------------------doen3 d0 dosetup3 loop1 move.l (sp+Z_OFFSET),r2 FALIGN LOOPSTART3 loop1 move.w (r1)+,d2 add d3,d2,d1 move.w d1,(r2)+ LOOPEND3 move.w (r0)+,d3 ; Load y[i] and x[i] ; d1 = x[i] + y[i]. ; Store d1 as z[i]. ; Set up loop count and loop flag. ; Set up loop start address. ; r2 = &z[0] (Output array).
La apelul funciei sunt pasai ctre addvecs patru parametrii. Primi trei sunt pointeri ctre vectori i de aceea au valori pe 32 de bii (adresele sunt pe 32 de bii n StarCore). Al patrulea parametru const n lungimea vectorilor i este pe 16 bii. Mecanismul prin care parametrii sunt pasai este specificat n interfaa aplicaiei binare (ABI). Vorbind n mod general, acest ABI specific urmtoarea convenie de apelare:
Primul parametru este dus n d0 dac este un scalar numeric sau n r0 dac este o adres. Al doilea parametru este dus n d1 dac este un scalar numeric sau n r1 dac este o adres. Urmtorii parametri sunt plasai n stiv. Valoarea returnat (dac exist) este returnat n funcia de apelare n d0 dac este un scalar numeric sau n r0 dac este o adres.
31
32
Pentru funcii simple cu doi sau mai puini parametrii stiva nu este folosit pentru a pasa parametrii, i este posibil s se scrie ntreaga funcie n limbaj de asamblare, fr s foloseasc deloc implicit stiva. n general, stiva este folosit pentru a pasa parametrii n funcie i a stoca unele variabile locale. Coninutul ei este artat n figura 2.7. Chiar inainte de apelarea funciei, parametrii 3, 4, 5 i aa mai departe sunt mpini n stiva (n ordine inversa) i parametrii 1 i 2 sunt stocai n d0/r1, dup cum a fost descris anterior.
La apelul funciei addvecs se scriu n stiv parametri dup cum este artat n figura 2.8.
Figura 2.8.
EXERCIIU: n addvecs.asm se gsesc dou constante, Z_OFFSET i M_OFFSET ale cror valori nu sunt fixate i care sunt marcate cu semne de ntrebare (????). Aceste offset-uri ndic deplasamentul fa de SP a lui z[] i M din stiva. Calculai valorile lui Z_OFFSET i M_OFFSET. Compilai i rulai programul verificnd rezultatul.
Figura 2.7.
Apoi funcia este apelat, i adresa de revenire i coninutul registrului de stare sunt mpinse n stiva de instruciunile jsr sau bsr. Dac funcia apelat modific registrele d6, d7, r6, r7 ar trebui mai nti s-i salveze n stiva, iar apoi s-i refac nainte sa i returneze. Toate celelalte registre pot fi folosite fr salvarea sau refacerea lor. La ieirea din funcie, coninutul registrului de stare i adresa de revenire n programul principal sunt returnate din stiv (de catre instructiunea rts), i funcia elibereaz stiva de parametriii 3, 4, 5 i aa mai departe.