Architettura del repertorio di istruzioni - RISC, CISC, VLIW e indirizzamento
In questa pagina 6
L'architettura di un processore è l'insieme delle risorse che ne permettono la programmazione in linguaggio macchina (la "architetturainsieme delle risorse visibili al programmatore lato utente"). Discutere un'architettura vuol dire valutare tre cose: la struttura delle istruzioni, i modi di indirizzamento dei dati e le funzioni che le istruzioni realizzano. Dietro ogni architettura c'è sempre una precisa organizzazione hardware (Organizzazione del processore - Von Neumann, Harvard, bus, ALU e registriOgni processore ha ALU, memoria e dispositivi di I/O. Nell'organizzazione Von Neumann dati e istruzioni stanno nella stessa memoria e viaggiano su un solo sistema di bus (semplice ed economica, usata nei µC più semplici); nell'organizzazione Harvard memorie e bus sono separati (più accessi per ciclo: tipica di DSP e µC veloci). I bus sono pilotati da porte tri-state; l'ALU lavora su registri (accumulatore o molti registri); il controllo è cablato o microprogrammato; la gerarchia di memoria va dai registri alla RAM interna e a quella esterna.Organizzazione del processore - Von Neumann, Harvard, bus, ALU e registri →); l'architettura incide sul numero di istruzioni di un programma, l'organizzazione su tempo di ciclo e cicli per istruzione (Misura delle prestazioni - tempo di calcolo e indici MIPSLe prestazioni di un processore si misurano col tempo di calcolo di un programma: $T_{cal}=T_{clk}\sum_{i}N_i,NC_i$ (periodo di clock per numero di istruzioni di classe $i$ per cicli medi della classe). Aumentare la velocità vuol dire ridurre $T_{clk}$, i cicli per istruzione (organizzazione) o il numero di istruzioni (architettura). Gli indici MIPS, DMIPS, FLOPS misurano solo un picco e non permettono di confrontare famiglie diverse: si usa il benchmarking (kernel benchmarking per i DSP).Misura delle prestazioni - tempo di calcolo e indici MIPS →).
Qualità di un repertorio di istruzioni
- Simmetria: nessun caso particolare. Se un registro si può caricare dalla memoria, si può anche copiare in memoria; se un dato si sposta da un registro a un altro, vale anche lo spostamento inverso.
- Ortogonalitàtipo di istruzione e modo di indirizzamento sono indipendenti: ogni modo vale per ogni istruzione.
- Regolarità: tutte le instruction wordIW: la parola binaria che codifica una istruzione hanno la stessa lunghezza e i campi (OPCODE, registri) la stessa posizione.
- Compattezza: dimensione del codice macchina; architetture regolari e semplici (RISC) sono in genere più compatte.
- Velocità di esecuzione, facilità di debugging (somiglianza con un linguaggio ad alto livello) e costo.
RISC e CISC
RISC (Reduced Instruction Set Computer): istruzioni poche decine, semplici nel formato e nelle funzioni, tutte della stessa dimensione (per esempio 16 bit). La decodifica quasi sempre cablata è semplice, quindi di norma ogni istruzione dura un solo ciclo macchina. L'area di silicio risparmiata nell'unità di controllo permette banchi di registri e cache: l'organizzazione è quasi sempre "a molti registri". Le prime realizzazioni RISC erano a accumulatoreregistro implicito su cui agiscono le istruzioni a un solo operando o a stack (istruzioni senza operandi), ma generavano troppo traffico con la memoria, che è il collo di bottiglia, e sono state abbandonate.
CISC (Complex Instruction Set Computer): centinaia di istruzioni di struttura variabile e complessa; la decodifica è spesso microprogrammata, l'esecuzione richiede più cicli. Era comune nei processori generici fino ai primi anni '90; tra i µC resta in alcune famiglie datate degli anni '70 (Intel 8XC196, Renesas H8S). Spesso ha un'organizzazione Von Neumann con aggiunte: cache, coprocessori, blocchi di debug.
I processori di nuova concezione per controllo real time sono RISC e hanno caratteristiche prossime a quelle di un DSP a virgola fissa. I DSP seguono la filosofia RISC (molti registri, controllo cablato) ma con istruzioni compatte a molti campi: questo rende il repertorio asimmetrico e non ortogonale, quindi difficile da programmare in assembly e, nelle prime generazioni, con compilatori poco efficienti.
Parallelismo: VLIW, SIMD, processori su misura
Dagli anni '90 la complessità degli algoritmi (telefonia mobile) ha spinto verso architetture più facili da programmare:
- VLIW (Very Long Instruction Word): più istruzioni semplici (4, 8) sono impacchettate in una sola macro-istruzione letta in un solo prelievo e eseguita in parallelo in un ciclo. Il codice occupa più memoria. Non è equivalente al superscalare: solo certe sequenze si impacchettano bene (per esempio una cella di filtro FIR), il parallelismo hardware è ridotto, la pipeline è statica, il bus istruzioni è largo (anche 256 bit).
- Istruzioni a lunghezza variabile: le istruzioni aritmetiche in stile VLIWVery Long Instruction Word: più istruzioni semplici impacchettate in una sola, quelle di controllo o di manipolazione di bit in formato compatto.
- SIMDSingle Instruction Multiple Data: la stessa istruzione su più dati (Single Instruction, Multiple Data): la stessa istruzione su più dati. Nell'ARM Cortex-M4 l'ALU a 32 bit esegue in un ciclo 2 somme a 16 bit o 4 somme a 8 bit, se il compilatore le usa.
- Processori su misura (licensable corenucleo di processore concesso in licenza, di cui l'utente può personalizzare repertorio e hardware): ottimi ma con sviluppo lungo; oggi si usano molto le FPGA.
Istruzioni tipiche di un DSP
- Moltiplicazione sempre a ciclo singolo, spesso in più modalità (intera, frazionaria, con o senza segno), seguita da shift e somma sull'accumulatore nello stesso ciclo: circuito MACmoltiplicatore con accumulatore: somma il prodotto di due operandi all'accumulatore in un solo ciclo, esterno all'ALU. La divisione è rara e quasi mai in hardware.
- Aritmetica saturata: in caso di overflow il risultato è sostituito dal massimo (
0x7FFF) o minimo (0x8000) rappresentabile, evitando l'effetto di avvolgimento (Numeri binari e complemento a dueI processori lavorano con un numero fisso di bit $n$. I naturali vanno da $0$ a $2^n-1$; per i negativi si usa il complemento a due: $C_2(N)=2^n-N=\overline N+1$ (si invertono tutti i bit e si somma 1). Con $n$ bit rappresenta $-2^{n-1}\le N\le2^{n-1}-1$, ha un solo zero e unifica somma e sottrazione. Quando il risultato esce dall'intervallo c'è overflow; gli overflow intermedi si compensano se il risultato finale è rappresentabile. La lunghezza di parola non è l'accuratezza.Numeri binari e complemento a due →). - Shift aritmetici e logici flessibili con il barrel shiftercircuito che sposta una parola di un numero qualsiasi di posizioni in un solo ciclo.
- Riduzione dei bit (per esempio da 8 a 4): troncamento (scarta i bit bassi), arrotondamento (somma il bit più significativo scartato), arrotondamento convergente.
- Radice quadrata e funzioni trigonometriche non sono mai in hardware: conviene approssimarle con polinomi (Realizzare un filtro o un regolatore a virgola fissaRealizzare in C un filtro a virgola fissa vuol dire scegliere per ogni dato il formato (coefficienti $<1$ in 0.16 U, coefficienti $>1$ in 1.15, 4.12, 5.11 S...), moltiplicare con aritmetica a 32 bit ($16\times16\to32$) e riportare il prodotto al formato di arrivo con uno shift a destrascorrimento dei bit verso destra: equivale a dividere per una potenza di 2; per sommare due prodotti con scale diverse si fa lo shift prima di sommare. Con $a+b=2^{16}$ il filtro $y=\big(a,y_{k-1}+b,(u\ll4)\big)\gg16$ non va in overflow in un
uint32_t. Nel codice il formato di ogni variabile va dichiarato in un commento; la funzione $\sin x\approx x-\frac{x^3}6+\frac{x^5}{120}$ mostra come si approssima una funzione con polinomi a coefficienti in virgola fissa.Realizzare un filtro o un regolatore a virgola fissa →). Poi: spostamento dati, confronto, manipolazione di bit, ripetizione di segmenti di codice, salti, emulazione della virgola mobile.
Esempio: arrotondamento da 8 a 4 bit
Sia l'operando a 8 bit e si voglia = i 4 bit alti.
- Troncamento: .
- Arrotondamento: .
- Convergente: come l'arrotondamento, ma se (esattamente a metà) si somma invece di , cioè si arrotonda al pari, eliminando l'errore sistematico. Per : troncamento , arrotondamento , convergente (perché ); per : troncamento , arrotondamento , convergente (perché ).
Struttura delle istruzioni e modi di indirizzamento
Le istruzioni hanno fino a tre operandi: ADD X, Y, Z. Con un solo operando (ADD X) c'è un accumulatore implicito; senza operandi sono le macchine a stack, abbandonate.
Modi di indirizzamentoil modo in cui l'istruzione specifica dove si trova il dato più comuni: immediato (l'operando è nella IW), a registro, diretto o assoluto (la IW contiene l'indirizzo dell'operando), indirettomodo di indirizzamento in cui l'istruzione contiene l'indirizzo dell'indirizzo del dato (la IW contiene l'indirizzo dell'indirizzo, cioè un puntatore). Molto comuni nei µC e nei DSP: indiretto con auto-incremento (al puntatore si somma automaticamente ) e indiretto con offset (indicizzato: puntatore più costante). Le AGUAddress Generation Unit: unità che calcola gli indirizzi in background, fuori dall'ALU rendono possibili modi ancora più efficienti:
- circolare: per gestire vettori di dati (buffer di un filtro), quando un puntatore di lettura o scrittura raggiunge la fine del vettore ripassa da solo all'inizio, senza istruzioni di controllo;
- a bit rovesciati: la lettura con indice a bit invertiti di una sequenza ordinata produce l'ordinamento della uscita della DFTDiscrete Fourier Transform, trasformata di Fourier discreta, calcolata dalla FFT.
Esempio a bit rovesciati con 8 elementi (3 bit): l'indice legge la posizione ; ; . La sequenza di lettura è : è proprio l'ordine in cui la FFT a decimazione in frequenza (ingresso in ordine) produce gli elementi e permette di mettere il vettore in ordine con un solo ciclo. I dsPIC 33F e i DSP Freescale 563xx supportano entrambi i modi ottimizzati.
Errori comuni
- Dire che i RISC sono "più lenti perché hanno meno istruzioni": hanno più istruzioni per programma ma ciascuna dura 1 ciclo.
- Confondere VLIW con superscalare (che replica le unità e gestisce l'ordine a runtime: 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 →).
- Dimenticare che l'arrotondamento convergente riguarda solo il caso "esattamente a metà".
Versione ripasso
- Qualità: simmetria, ortogonalità, regolarità (IW della stessa lunghezza), compattezza, velocità, debug, costo.
- RISC: poche istruzioni semplici, IW uguali, cablato, 1 ciclo, molti registri. CISC: centinaia, microprogrammato, più cicli (µC datati). DSP: RISC con istruzioni a molti campi (asimmetrico).
- Parallelismo: VLIW (4-8 istruzioni in una, parallele, bus 256 bit), SIMD (stessa istruzione su più dati: Cortex-M4 2×16 o 4×8 bit), core su misura.
- DSP: MAC a ciclo singolo, saturazione (
0x7FFF/0x8000), barrel shifter, troncamento/arrotondamento/convergente (, ). - Indirizzamento: immediato, registro, diretto, indiretto, auto-incremento, indicizzato, circolare (buffer), bit rovesciati (FFT: ).
- Errori: RISC "lento", VLIW = superscalare, arrotondamento convergente ovunque (Organizzazione del processore - Von Neumann, Harvard, bus, ALU e registriOgni processore ha ALU, memoria e dispositivi di I/O. Nell'organizzazione Von Neumann dati e istruzioni stanno nella stessa memoria e viaggiano su un solo sistema di bus (semplice ed economica, usata nei µC più semplici); nell'organizzazione Harvard memorie e bus sono separati (più accessi per ciclo: tipica di DSP e µC veloci). I bus sono pilotati da porte tri-state; l'ALU lavora su registri (accumulatore o molti registri); il controllo è cablato o microprogrammato; la gerarchia di memoria va dai registri alla RAM interna e a quella esterna.Organizzazione del processore - Von Neumann, Harvard, bus, ALU e registri →).
Esercizi su questo argomento
Teoria collegata
- Microcontrollori e DSP - definizioni e scelta del dispositivo
- Misura delle prestazioni - tempo di calcolo e indici MIPS
- Numeri binari e complemento a due
- Pipeline - accelerazione e conflitti
- Rappresentare un valore reale in virgola fissa - formato ottimo ed errore
- Realizzare un filtro o un regolatore a virgola fissa
- Unità di controllo - cablata, microprogrammata, singolo ciclo e multiciclo