Salta al contenuto
Note per Studenti Esercizio 32 · istruzioni ARM7 con barrel shifter e realizzazione in assembly di y = a·x + b (prove d'esame del 2004 e del 2014)

Esercizio 32istruzioni ARM7 con barrel shifter e realizzazione in assembly di y = a·x + b (prove d'esame del 2004 e del 2014)

Esame
In questa pagina 5

Testo (prove d'esame del 2004 e del 2014, problemi 5-9 e 9-10).

(i) Si danno le istruzioni ARM7 e i valori iniziali dei registri; indicare in esadecimale il valore finale del registro r1r_1.

  • MOV r1, r2, LSR #2 seguita da MOV r1, r1, LSL r1, con r1=0x00007FFFr_1=\texttt{0x00007FFF}, r2=0x00000008r_2=\texttt{0x00000008};
  • MVN r1, r2, LSR #3, con r1=0x0000FFFFr_1=\texttt{0x0000FFFF}, r2=0x00000008r_2=\texttt{0x00000008};
  • SUB r1, r2, r2, LSR #1, con r1=0x0000FFFFr_1=\texttt{0x0000FFFF}, r2=0x00000008r_2=\texttt{0x00000008}. (ii) Un'istruzione LDR r0, [PC, #0x0050] si trova alla locazione 0x0024\texttt{0x0024}. A quale locazione si trova il dato caricato in r0r_0? (iii) Il convertitore A/D di un DSP lavora a 8 bit con FSR=4,5FSR=4{,}5 V e i dati sono elaborati da un processore a 8 bit con y(k)=a x(k)+by(k)=a\,x(k)+b, a=0,15a=0{,}15, b=1,5b=1{,}5. Determinare, con arrotondamento: (a) la rappresentazione Q7 di aa in esadecimale; (b) la rappresentazione 2.6 di bb; (c) il tipo e l'ampiezza dello shift da eseguire sul prodotto prima della somma con bb (il prodotto è eseguito automaticamente in modalità frazionaria e xx è in Q7); (d) y(2)y(2) in esadecimale se x(2)x(2) si ottiene convertendo 3 V. (iv) Stesso algoritmo con ADC a 10 bit (FSR=4,5FSR=4{,}5 V) e ALU a 32 bit: a=2,125a=2{,}125, b=1,57b=1{,}57. Determinare: (a) aa e bb in formato 2.14 su 16 bit (esadecimale); (b) il tipo e l'ampiezza dello shift se xx è in modalità 0.16 e il prodotto è frazionario automatico; (c) y(2)y(2) per x(2)x(2) da 3 V. (d) Scrivere la sequenza ARM7 che realizza l'algoritmo se x(k)x(k) è in r0r_0 come 0x0000XXY0\texttt{0x0000XXY0} (Y=0,4,8,CY=0,4,8,C).

Teoria usata: Architettura del repertorio di istruzioni - RISC, CISC, VLIW e indirizzamentoL'architettura è l'insieme delle risorse visibili al programmatore (istruzioni, modi di indirizzamento). RISC: poche istruzioni semplici, di uguale lunghezza, decodifica cablata, quasi tutte a 1 ciclo; CISC: molte istruzioni complesse, decodifica microprogrammata, più cicli. I DSP sono RISC "potenziati" (MAC, saturazione, barrel shifter, arrotondamento, VLIW, SIMD); i modi di indirizzamento tipici sono immediato, a registro, diretto, indiretto, con auto-incremento, circolare e a bit rovesciati (per la FFT).Architettura del repertorio di istruzioni - RISC, CISC, VLIW e indirizzamento →, Operazioni in virgola fissa - somma, prodotto e riallineamentoIn virgola fissa il processore opera sugli interi e non sa dov'è la virgola: tocca al programmatore. Regola 1: si sommano solo dati con lo stesso formato (stesso $m$). Regola 2: il prodotto di $n_1.m_1$ per $n_2.m_2$ ha $m_1+m_2$ bit frazionari e il doppio dei bit: va riallineato con uno shift a destra di $m_2$ posizioni (per riportarlo a $m_1$) o preso dalla parte alta. Con la normalizzazione frazionaria $1.15$ il prodotto è $2.30$ e basta uno shift a sinistra di 1 prima di prendere la parte alta. I fattori di scala si scelgono per evitare overflow e perdita di risoluzione.Operazioni in virgola fissa - somma, prodotto e riallineamento →, Pipeline - accelerazione e conflittiLa pipeline divide l'esecuzione in $n$ stadi (fetch, decodifica, lettura, esecuzione, scrittura) che lavorano contemporaneamente su istruzioni diverse. Il clock è dettato dallo stadio più lento; a regime si completa un'istruzione per ciclo. Per $N$ istruzioni servono $(n+N-1),T_{clk}$: l'accelerazione rispetto al multiciclo tende a $n$ ma è sempre minore (riempimento, conflitti). I conflitti sono strutturali (stessa risorsa), sui dati (RAW...) e di controllo (salti): si risolvono con stalli (interlocking), bypass, sovrapposizione, riordino, salti ritardati. La latenza di una singola istruzione non diminuisce.Pipeline - accelerazione e conflitti →.

(i) Istruzioni ARM con shift

Nell'ARM7 il secondo operando passa per il barrel shifter (LSL logico a sinistra, LSR logico a destra, ASR aritmetico a destra) in un solo ciclo.

  • MOV r1, r2, LSR #2: r1=0x8≫2=0x2r_1=\texttt{0x8}\gg2=\texttt{0x2}. Poi MOV r1, r1, LSL r1: lo shift è di r1r_1 posizioni (il registro stesso, valore 2): 2≪2=0x82\ll2=\texttt{0x8}. Risultato 0x00000008\texttt{0x00000008} (il valore iniziale 0x00007FFF\texttt{0x00007FFF} è sovrascritto: MOV non lo usa).
  • MVN r1, r2, LSR #3: MVN carica il complemento a 1 dell'operando: 0x8≫3=0x1\texttt{0x8}\gg3=\texttt{0x1}; ∼0x00000001=0xFFFFFFFE\sim\texttt{0x00000001}=\textbf{0xFFFFFFFE}.
  • SUB r1, r2, r2, LSR #1: r1=r2−(r2≫1)=8−4=0x00000004r_1=r_2-(r_2\gg1)=8-4=\textbf{0x00000004}.

(ii) LDR con PC

Nell'ARM7 con pipeline a 3 stadi il PC letto da un'istruzione punta 8 byte oltre l'istruzione stessa (due istruzioni avanti: fetch e decode già avanzati). L'indirizzo del dato è quindi 0x24+8+0x50=0x7C\texttt{0x24}+8+\texttt{0x50}=\textbf{0x7C} (con 4 byte per istruzione).

(iii) y=0,15 x+1,5y=0{,}15\,x+1{,}5 a 8 bit

(a) Q7 (1.7 S): 0,15⋅128=19,2→19=0x130{,}15\cdot128=19{,}2\to19=\textbf{0x13}. (b) 2.6 (segno + 1 bit intero + 6 frazionari): 1,5⋅64=96=0x601{,}5\cdot64=96=\textbf{0x60} (esatto). (c) Il prodotto a⋅xa\cdot x è fatto in modalità frazionaria 1.15: il byte alto (parte alta) ha 7 bit frazionari (m=7m=7, formato Q7); bb è in 2.6 (m=6m=6): per sommare serve portare il prodotto a m=6m=6 con uno shift aritmetico a destra di 1 bit (ASR 1). (d) x(2)x(2): 3 V/4,5 V=0,66673\ \text{V}/4{,}5\ \text{V}=0{,}6667; in Q7: 0,6667⋅128=85,3→85=0x550{,}6667\cdot128=85{,}3\to85=\texttt{0x55}. Prodotto: 19⋅85=161519\cdot85=1615 (intero a 16 bit), modalità frazionaria: ×2=3230\times2=3230; parte alta ⌊3230/256⌋=12\lfloor3230/256\rfloor=12 (m=7m=7); ASR 1: 66 (m=6m=6, vale 0,094≈0,15⋅0,667=0,10{,}094\approx0{,}15\cdot0{,}667=0{,}1). Somma con bb: 6+96=102=0x666+96=102=\textbf{0x66} (in 2.6 vale 1,591{,}59 contro 0,15⋅0,667+1,5=1,60{,}15\cdot0{,}667+1{,}5=1{,}6 ✓).

(iv) y=2,125 x+1,57y=2{,}125\,x+1{,}57 a 32 bit

(a) 2.14 (positivi, <4<4): a=2,125⋅16384=34816=0x8800a=2{,}125\cdot16384=34816=\textbf{0x8800} (esatto); b=round(1,57⋅16384)=round(25722,9)=25723=0x647Bb=\mathrm{round}(1{,}57\cdot16384)=\mathrm{round}(25722{,}9)=25723=\textbf{0x647B}. (b) xx in 0.16 U (m=16m=16) va portato in 2.14 (m=14m=14) con LSR 2 (stesso valore, C216=C/4214\frac{C}{2^{16}}=\frac{C/4}{2^{14}}); il prodotto 2.14×2.142.14\times2.14 ha 28 bit frazionari e per sommare bb (14 bit frazionari) serve uno ASR di 14 posizioni. In generale si conta sempre il numero di bit frazionari di ciascun prodotto: se il moltiplicatore fosse frazionario automatico (DSP) il prodotto sarebbe già raddoppiato e la quantità da scartare cambierebbe di un bit. (c) y(2)y(2) con x=34,5=0,6667x=\frac3{4{,}5}=0{,}6667 in 2.14: 0,6667⋅16384=10922,7→10923=0x2AAB0{,}6667\cdot16384=10922{,}7\to10923=\texttt{0x2AAB}. a⋅x=34816⋅10923=380 305 …a\cdot x=34816\cdot10923=380\,305\,\ldots; ≫14=23211\gg14=23211; +b=23211+25723=48934=0xBF26+b=23211+25723=48934=\textbf{0xBF26}, cioè 4893416384=2,987\frac{48934}{16384}=2{,}987 (valore atteso 2,125⋅0,6667+1,57=2,98672{,}125\cdot0{,}6667+1{,}57=2{,}9867 ✓). (Se xx è il codice dell'ADC a 10 bit, 683=0x2AB683=\texttt{0x2AB} allineato a sinistra 0xAAC0\texttt{0xAAC0}, si ottiene 0xBF31\texttt{0xBF31}: differenza di 11 LSB per la quantizzazione dell'ingresso.) (d) Codice ARM7 (r0r_0 contiene il dato convertito nel formato 0x0000XXY0\texttt{0x0000XXY0}: 10 bit allineati a sinistra su 16 bit, cioè formato 0.16):

Aa  .equ 0x8800            ; a in 2.14
Bb  .equ 0x647B            ; b in 2.14
    LDR  r4, =Aa           ; carico la costante a
    LDR  r5, =Bb           ; carico la costante b
    MOV  r0, r0, LSR #2    ; passo x(k) da 0.16 a 2.14
    MUL  r1, r4, r0        ; moltiplico a*x (prodotto intero a 32 bit, 28 bit frazionari)
    ADD  r1, r5, r1, ASR #14   ; riporto il prodotto a 14 bit frazionari e sommo b

La moltiplicazione dell'ARM7 è intera: lo shift ASR #14 si fa nell'ADD sfruttando il barrel shifter (nessun ciclo in più). Il risultato in r1r_1 è yy in formato 2.14 (valore massimo a⋅1+b=3,7<4a\cdot1+b=3{,}7<4: nessun overflow). I cicli sono 5, di cui MUL più lunga; con pipeline a 3 stadi a regime (Pipeline - accelerazione e conflittiLa pipeline divide l'esecuzione in $n$ stadi (fetch, decodifica, lettura, esecuzione, scrittura) che lavorano contemporaneamente su istruzioni diverse. Il clock è dettato dallo stadio più lento; a regime si completa un'istruzione per ciclo. Per $N$ istruzioni servono $(n+N-1),T_{clk}$: l'accelerazione rispetto al multiciclo tende a $n$ ma è sempre minore (riempimento, conflitti). I conflitti sono strutturali (stessa risorsa), sui dati (RAW...) e di controllo (salti): si risolvono con stalli (interlocking), bypass, sovrapposizione, riordino, salti ritardati. La latenza di una singola istruzione non diminuisce.Pipeline - accelerazione e conflitti →).

Errori comuni

  • Dimenticare che MVN complementa tutti i 32 bit (non solo il byte basso).
  • Usare il valore iniziale di r1r_1 in MOV (il contenuto viene sovrascritto).
  • Dimenticare che PCPC è 8 byte in avanti rispetto all'istruzione corrente.
  • Non allineare i due addendi: a⋅xa\cdot x ha 28 bit frazionari e bb ne ha 14.

Versione ripasso

Testo. ARM7 con barrel shifter (MOV/MVN/SUB), LDR [PC,#0x50], y=ax+by=ax+b a 8 bit (Q7, 2.6) e a 32 bit (2.14) con codice ARM (2004, 2014).

Teoria collegata