Insegnamenti di
Sistemi Elettronici Dedicati 1
(Corso di Laurea in Ingegneria Elettronica)
Sistemi Elettronici Digitali1
(Corso di Laurea Specialistica in Ingegneria delle Telecomunicaizoni)
DSP
Digital Signal Processors
Edizione 2004
Rodolfo Zunino
1. Introduzione: caratteristiche descrittive dei DSP
L’elaborazione dei segnali digitali rappresenta i segnali analogici del mondo reale con una sequenza
discreta di numeri discreti ed elabora tali numeri per estrarre informazioni od operare
trasformazioni su questi segnali.
La famiglia di processori che realizzano tali operazioni sono noti come DSP (Digital Signal
Processors). Possiamo convertire i segnali analogici in digitali attraverso un processo di
conversione A/D, elaborare i segnali con i DSP e, se questo è necessario, portare i segnali di nuovo
in uscita nel mondo analogico attraverso una conversione D/A.
Rispetto ad un sistema analogico, i sistemi elettronici digitali sono maggiormente insensibili al
rumore provocato da cambiamenti di temperatura, umidità o da altri fattori.
Altri vantaggi rispetto ad un sistema analogico riguardano la facile riprogrammabilità per altre
applicazioni e la predicibilità dei risultati, caratteristiche tipiche dei sistemi digitali.
Nell’ambito del Signal Processing, i DSP offrono il supporto ottimizzato a ben precisi algoritmi di
riferimento; in quanto tali, i DSP possono esser visti come componenti dedicati alla classe di
algoritmi numerici per l’elaborazione di segnali digitali. Un DSP unisce velocità e potenza di
calcolo per elaborare i dati in tempo reale. Questa sua capacità lo rende perfetto per applicazioni
che non possono tollerare ritardi nelle risposte del sistema.
Non è sempre vero che un DSP è meno potente di un microprocessore: infatti, anche se la sua
frequenza di clock (~200MHz) è notevolmente inferiore a quella dei microprocessori classici, il
DSP per le applicazioni per cui è stato pensato si rivela più veloce di microprocessori come il
Pentium.
In generale, si dice che il DSP è un componente dedicato, application dependent, mentre il
microprocessore è un general purpose.
Prestazioni
Infatti un microprocessore general purpose può essere estremamente performante nel processo di
database e nell’elaborazione di fogli elettronici, ma avere invece delle difficoltà nell’elaborare
segnali audio e video in real time. Questo compito può essere svolto efficacemente da un DSP, che
non ripone le sue potenzialità in una frequenza di clock elevata, ma in un’architettura diversa da
quella di un microprocessore.
Criteri di progetto
Dato un progetto possono essere diverse le opzioni di scelta, visto che più di un processore può
implementare le funzioni richieste. Quindi la soluzione progettuale opportuna sta nel scegliere il
migliore DSP fra quelli disponibili. Ciò si ottiene valutando la performance, le dimensioni, la
potenza consumata, le caratteristiche, il software ed i tools che ottimizzano i tempi di sviluppo,
tenendo sotto controllo i costi.
Esiste un tempo di longevità maggiore per i DSP rispetto ai microprocessori. Dopo più di vent'anni
dalla loro comparsa, i DSP continuano ad essere processori competitivi: essi sono al centro
dell'elaborazione digitale dei segnali.
La clock rate di un DSP è limitata dalla potenza che può essere consumata e dall’architettura di
sviluppo: la lunghezza delle linee di bus di una scheda è limitata per non trasformare tali linee in
antenne indesiderate. Viene limitata la frequenza (es. 200MHz → 40MHz). Nel DSP le schede
sono molto compatte: questo può essere facilmente comprensibile, dato il tipo di applicazioni in cui
i DSP sono utilizzati (un esempio per tutti è il telefono cellulare).
Se prevale l’aspetto controllistico e non l’elaborazione si parla di microcontrollori.
2
Ulteriori differenze tra i DSP ed i microprocessori:
•
Sample rate: definisce la massima frequenza di campionamento (ad es. 44KHz del CD),
dipende dal segnale che deve essere elaborato. Assieme alla complessità dell’algoritmo
determina la velocità del DSP.
•
Rappresentazione numerica: a interi (16 bit), oppure a floating point (32 bit). Le operazioni
aritmetiche come addizioni e moltiplicazioni sono il cuore degli algoritmi dei DSP. Di
conseguenza, la scelta della rappresentazione numerica ha una profonda influenza sul
comportamento e sulle prestazioni degli stessi DSP. Esistono DSP che non trattano la
rappresentazione in virgola mobile, ma lavorano solo con grandezze in virgola fissa.
•
I DSP costano in genere qualche decina di dollari: sono spesso inseriti in sistemi per i quali
è determinante avere un prezzo contenuto, come i telefoni cellulari o i modem.
Il costo dei DSP, così come il loro mercato, è molto differenziato. Si parla comunque di lotti
di produzione, come per i microprocessori.
•
D/A :
•
Bisogna pure considerare che un DSP è di solito molto longevo (anche 20 anni), nonché
molto affidabile, grazie al lavoro di testing. Tutt’altro discorso vale per i microprocessori.
capacità di avere un’interfaccia digitale/analogica
1.1
Che cosa fa un DSP: caratteristiche operative
MAC: moltiplicazione + addizione simultaneamente
La maggior parte degli algoritmi per l’elaborazione dei segnali richiede un’operazione di
moltiplicazione ed addizione del tipo:
A = ( B×C )+ D
Questa operazione, multiply and accumulate, in un DSP viene effettuata in un solo ciclo di clock.
L’operazione di MAC è utile in algoritmi che prevedono il calcolo di prodotti fra vettori, come
accade per i filtri digitali e per le trasformate di Fourier. Per poter disporre di questa caratteristica, i
DSP presentano moltiplicatore ed accumulatore integrati nella stessa unità aritmetica, chiamata
datapath.
Accesso multiplo in memoria
Un’altra caratteristica importante dei DSP è la capacità di compiere più accessi in memoria in uno
stesso ciclo di istruzione. Questo permette al processore di caricare simultaneamente un’istruzione
ed i suoi operandi, oppure di salvare in memoria il risultato dell’operazione precedente. Tutto
questo grazie alla presenza di due bus indirizzi e due bus dati: aumenta il throughput, ovvero il
tasso di emissione di dati in uscita rispetto al flusso di dati in ingresso.
3
Set di istruzioni specifico
Per far sì che le operazioni aritmetiche siano calcolate alla massima velocità e che in una singola
istruzione siano specificati più operandi, i DSP fanno ricorso ad un set di istruzioni specifico.
Questo set riguarda i modi di indirizzamento (addressing modes). I DSP incorporano unità di
generazione degli indirizzi, address generation units, che gestiscono la formazione del nuovo
indirizzo in parallelo all’esecuzione delle istruzioni aritmetiche.
Loop control in hardware
Gli algoritmi dei DSP contengono frequentemente istruzioni che devono essere ripetute. Invece di
aggiornare un contatore o di eseguire un salto di istruzione all’inizio del loop, i DSP risolvono
questo problema via hardware. Esistono infatti delle strutture hardware che effettuano il controllo
dei loop: alcune permettono di ripetere per un numero fissato di volte una singola istruzione, altre
ripetono un blocco di istruzioni un certo numero di volte (Single- e Multi-Instruction Hardware
Loops).
I/O interface
Per conseguire gli obiettivi di costi contenuti ed alte performance in I/O, molti DSP incorporano
una o più interfacce seriali o parallele; inoltre essi utilizzano il direct memory access (DMA).
Spesso le interfacce sono direttamente collegate ai convertitori A/D e D/A.
Esistono diversi modi di lavorare con un DSP:
1)
Evaluation board
• Scheda (kit) a basso costo a scopo tutorial
• Si interfaccia di solito via parallela
• Bassa clock rate (comunque apprezzabile: 20-40 MHz)
• Facile da usare (come di solito anche il compilatore fornito insieme ad essa)
Il limite dell’evaluation board non è la clock rate bassa, ma soprattutto la connessione via
parallela che determina un basso throughput.
2)
Scheda professionale
• Interfaccia PCI
• Elevata clock rate
• Facile da usare
• Lavora come un coprocessore
• Da 1000-1500 € in su
Alcune sono espandibili: si può sostituire il DSP o lavorare con multiprocessore.
Deve essere ben interfacciata con il computer, dato che un coprocessore deve rispettare le
esigenze di calcolo dell’unità host..
3)
Scheda custom
• Costo elevatissimo…
Hardware: non nel progetto, ma nel testing, molto impegnativo.
Software: se si passa alla fase 3 vuol dire che il passo 2 non basta.
• Spazio ridotto
La scheda custom serve per realizzare un prototipo: il prodotto finale sarà diverso da questo
(nessuna pista di testing, …).
4
4)
DSP core embedding
• Realizzato su chip e non su scheda
Il DSP core embedding si usa da parte di un’azienda, quando il layout di un DSP è utilizzato
come sottosistema del proprio processore (es. telefoni cellulari).
Una via di mezzo fra 3 e 4 è quella di inserire un DSP in un MultiChip Module (MCM).
I DSP servono all’industria di consumer electronics; queste sono alcune delle applicazioni:
Audio production, audio consumer, wireless communications, motor control, radar, sonar,
biomedical, voice over internet, satellite communications, digital cell phones, digital cameras,
digital TV, speech processing, seismic processing, instruments, music effects, music synthesis.
I maggiori produttori mondiali di DSP sono Texas Instruments, Analog Devices, Motorola.
ST Microelectronics, presente in Italia, produce DSP per un mercato advanced ma in un certo qual
modo di nicchia.
5
2. Rappresentazione Numerica
I processori DSP possono essere raggruppati in due categorie, a seconda della rappresentazione
numerica adottata:
• Virgola fissa (fixed point)
• Virgola mobile (floating point)
I DSP in virgola fissa sono caratterizzati dal rappresentare un numero in un intervallo fissato con
precisione finita. Valori tipici per la rappresentazione ad interi sono 16, 24 e 32 bit.
Le principali caratteristiche di questi processori:
• Minore complessità rispetto ai floating point
• Costo minore dell’hardware
• Maggiore velocità per applicazioni dedicate
I DSP in virgola mobile sono più recenti di quelli in virgola fissa ed esprimono i numeri
impiegando una mantissa combinata con un esponente. Questo metodo di rappresentazione
comporta:
•
•
•
•
•
•
•
Complessità superiore nell’architettura VLSI
Precisione maggiore
Facilità di gestione software
Tempo di sviluppo minore
Si commettono errori proporzionali alla grandezza dei numeri
Alto rapporto signal / noise
Intervallo di rappresentazione dinamico
L’intervallo di rappresentazione varia caso per caso:
•
•
•
16 bit: l’intervallo di rappresentazione va da -32768 a +32767 (per grandezze unsigned, da
0 a +65535 ).
32 bit (fixed point): l’intervallo di rappresentazione va da 0 a 4 × 109.
32 bit (floating point): l’intervallo va da 1.2 × 10-38 a 3.4 × 1038.
Per i DSP a floating point si parla di 32 bit ( 24 per la mantissa e 8 per l’esponente ).
In un DSP non è garantita la coesistenza di ottimizzazione per floating point ed interi.
Si può definire il concetto di precisione:
precisione =
max valore rappresentato
max errore commesso in quantizzazione
Al numeratore c’è il massimo valore rappresentato (diverso da quello rappresentabile). In virgola
mobile tale rapporto è costante, perché i gap fra due numeri consecutivi sono proporzionali alla
grandezza dei numeri in questione: ci sono piccoli gap fra numeri piccoli e grandi gap fra numeri
grandi. Questo effetto è dovuto al fatto che i valori rappresentati in virgola mobile non sono
ugualmente spaziati fra gli estremi dell’intervallo di rappresentazione, come avviene invece per i
6
fixed point. In virgola fissa la precisione cambia, perché non si riesce a sfruttare appieno la
dinamica dei registri.
Il rimedio per curare l’errore di precisione è quello di operare un rescaling: si fa coincidere il
massimo valore rappresentato con il massimo valore rappresentabile.
Spesso le applicazioni DSP trattano segnali analogici, che devono essere convertiti in digitale.
Il segnale analogico, continuo e variabile con precisione infinita, deve essere convertito in una serie
discreta di misure che devono essere a loro volta rappresentate con valori digitali. Questo processo
dà luogo a distorsione nella rappresentazione delle grandezze, chiamata errore di quantizzazione.
Il rumore di quantizzazione
Quando il segnale analogico è convertito in digitale la precisione è limitata dal numero di bit
disponibile. La caratteristica del segnale deve essere rappresentata con una funzione a gradini,
introducendo degli errori non lineari e dipendenti dal segnale. A tutto ciò si devono aggiungere gli
errori dovuti alla precisione limitata nei calcoli aritmetici all’interno del processore. Inoltre si
commettono errori anche nella fase di conversione D/A in uscita.
Un modo di descrivere il problema è considerare un’aggiunta di rumore al segnale, attribuendo gli
errori di quantizzazione alla presenza di random noise.
Valutiamo il signal / noise ratio introdotto dalle due diverse rappresentazioni numeriche; Sia ∆n il
gap percentuale tra l’n-mo numero ed il suo consecutivo.
Nel caso floating-point, lo scarto assoluto tra un numero ed il suo immediato consecutivo e’
proporzionale al valore del numero (i due numeri hanno pari esponente e differiscono per un bit
nella mantissa). Escludiamo gli effetti dovuti a coppie di numeri consecutivi in cui si hanno
transizioni di esponente, quindi possiamo dire che l’effetto della quantizzazione sulla precisione
dipende solo dalla mantissa. Se questa, come vedremo, viene rappresentata tipicamente con 23 bits,
il gap percentuale è costante e vale
1
1
∆( FP ) = 2 − 23 ⇒ 7 < ∆( FP ) < 6
10
10
il che indica che un numero floating-point è rappresentato (mantissa) con una precisione di circa 7
cifre decimali.
Diverso è il caso dei numeri a virgola fissa, in cui lo scarto assoulto tra due numeri consecutivi è
costante (uguale a 1), e quindi il gap percentuale dipende dal valore rappresentato:
∆( INT ) =
1
V
(dove V è il valore rappresentato)
Siamo interessati a studiare l’errore di quantizzazione, εq. In ogni intervallo tra due numeri
consecutivi, il suo andamento nell’intervallo tra due numeri consecutivi è lineare:
½ n∆n
n(1 - ∆/2)
εq
n (1+ ∆/2)
- ½ n∆n
7
e la sua distribuzione statistica sarà uniforme nell’intervallo considerato, con valore 1/n∆n. Il
rumore di quantizzazione, in ogni intervallo considerato ha media nulla: E{εq}= 0. Se ora
calcoliamo la varianza di εq, si può derivare che:
∆n
2
∆n
2
{ } ∫ x p(x )dx = ∆1 ∫ x dx = ∆12 .
{ }
σ q2 = E ε q2 − E 2 {ε q } = E ε 2q =
2
−
2
∆n
2
n
−
2
n
∆n
2
Normalmente si studia la deviazione standard dell’errore di quantizzazione, data dalla radice
quadrata della varianza:
1
σq ≈ ∆n
3
Ne risulta la deviazione standard dell’errore di quantizzazione è proporzionale al gap percentuale.
Nel caso dei numeri floating point, quindi, la deviazione standard dell’errore di quantizzazione è
costante entro ogni intervallo, e vale approssimativamente 1 parte su trenta milioni:
1
σ (qFP ) ≈ 10 − 6 ( numeri a 32 bit )
3
Nel caso dei numeri interi il calcolo e più complesso; per numeri a 16 bit (i più usati nella pratica
attuale) si ottiene:
σ (qINT ) = 10 − 4 ( numeri a 16 bit )
Guardando la deviazione standard ci sono due-tre ordini di grandezza a favore della
rappresentazione floating point.
Esempio:
TAP nei Filtri FIR
Siano x1, x2, … i campioni del segnale, e c1, c2, … i coefficienti pesati: y = x1 c1 + x2 c2 + …
x (n)
x1c1
x
∆
+
C1
x
….
C2
∆
La qualità di un filtro FIR è data dal numero di TAP, ad esempio ce ne possono essere 500: lungo la catena
l’errore si somma ad ogni TAP, per 500 volte.
8
L’errore di quantizzazione in un DSP è un fattore strutturale, quello che si può e si deve fare è tenerne conto
nello sviluppo dell’algoritmo per evitare la propagazione degli errori dovuta ad un’inefficiente
implementazione delle operazioni. Vale infatti la seguente proprietà, dovuta all’aumento nella dinamica
numerica introdotta dalle operazioni (soprattutto dalle moltiplicazioni):
Legge di conservazione dei bit
In generale, quando si moltiplicano due numeri interi di lunghezza n-bit, per rappresentare il
risultato senza introdurre errori occorrono 2n-bit.
Esempio:
Una semplice moltiplicazione che introduce errore può essere:
7-bit × 7-bit → risultato 14-bit → rescaling su 7 → quantizzazione ed errore
Si può ottenere una compensazione dell’errore grazie agli accumulatori a precisione estesa
(extended precision) presenti nel DSP:
•
•
Per gli interi a 16 bit → accumulatore da 32-40 bit
Per i floating point a 32 bit → accumulatore da 80 bit
Il range esteso elimina l’errore di round-off (arrotondamento) quando l’accumulazione è in
svolgimento. L’unico momento in cui permane il round-off noise è quando l’accumulatore viene
scalato e caricato in memoria.
Viene fatto ricorso a tutti questi accorgimenti per mantenere la massima dinamica possibile.
Standard di rappresentazione
Il formato più comune per la rappresentazione dei numeri fixed point è il Qn format. Questo
standard, che incorpora le potenzialità offerte dalla notazione in complemento a 2, è molto utile per
rappresentare le frazioni e i numeri decimali: n indica il numero di bit dopo la virgola, che è
implicita. Per rappresentare i numeri in Q15 sono necessari 16 bit: uno per il segno.
Esempio:
Sia dato il numero binario 10111101 in formato Q7 e si voglia trovare l’equivalente in decimale:
posizione
peso
Bit 7
segno
Bit 6
Bit 5
Bit 4
Bit 3
Bit 2
Bit 1
-1
-2
-3
-4
-5
-6
2
2
2
2
2
2
Bit 0
-7
2
Il numero è negativo, perché il most significant bit, che è il bit del segno, è posto a 1.
10111101
è in complemento a 2
01000010
è in complemento a 1 (si invertono tutti i bit)
01000011
è unsigned (si aggiunge 1)
0(segno) + 1(1/2) + 0(1/4) + 0(1/8) + 0(1/16) + 0(1/32) + 1(1/64) + 1(1/128) = 0.5234375
Dato che il numero è negativo, 10111101 in formato Q7 equivale a –0.5234375 in decimale.
Vi sono diversi standard per i numeri floating point: l’ IEEE 754 , che definisce il formato per la
singola precisione a 32 bit e per la doppia precisione a 64 bit, è il più usato. In un DSP a 32 bit che
segue l’IEEE 754, 23 bit sono usati per la mantissa, 8 bit per l’esponente, un bit è quello di segno.
9
Esempio:
Sia dato il numero a 32-bit IEEE 754: 111000010101011000000000000000
1
bit di segno: il numero è negativo
7
6
1
11000010
esponente = 2 + 2 + 2 = 194
-1
-3
-5
-6
10101100000000000000000 mantissa = 1 + 2 + 2 + 2 + 2 = 1.687
(194 - 127)
20
Il numero decimale equivalente è -1.685 × 2
= -2.49031044995 × 10
Criteri di scelta progettuale fra rappresentazione ad interi e floating point:
1)
La scelta è determinata dalla precisione del segnale di ingresso (data entry),
ovvero dal dato in arrivo dal convertitore A\D,
ovvero dalle specifiche del convertitore date dall’applicazione.
Un buon criterio di scelta è: < 12bit → interi
> 14bit → floating point
Esempio:
segnale TV digitale, 32 bit (RGB + intensità, 8 bit ciascuno) → interi
segnale audio, qualità studio, 20-24 bit → probabilmente floating point
2)
La scelta è determinata dalla complessità dell’algoritmo: se è semplice e non modifica la
statistica del segnale, si pensa ai fixed point
Esempio:
SORT: non c’è modificazione dei dati → semplice
FFT: contiene prodotti, modifica la dinamica dei dati
3)
→ difficile
La scelta è determinata dal costo: i floating point costano circa 2-3 volte più dei fixed point.
Quando viene scelta la rappresentazione ad interi, il costo del prodotto si riduce, ma
probabilmente il costo di sviluppo si incrementa per la complessità maggiore (punto 2). Con
la scelta dei floating point si ha il ragionamento inverso.
Esempio:
Una statistica del 1999 sugli utilizzatori di DSP in applicazioni industriali rappresentava così la situazione:
il 33% hanno già scelto i DSP
il 50% pensano di passare ai DSP
il 17% rimangono sui microprocessori
Di quelli che hanno già scelto i DSP:
il 33% lavorano con i floating point
il 66% lavorano con gli interi
Di quelli che lavorano con gli interi:
il 50% vogliono passare ai floating point
il 50% sono soddisfatti così
10
3. Caratteristiche Hardware
3.1
Architettura classica di un DSP
Tutti i processori digitali sono costituiti da alcuni moduli fondamentali:
• Unità di elaborazione per operazioni aritmetiche e logiche (ALU)
• Memorie per conservare i dati e le istruzioni dei programmi
• Bus per trasferire in modo efficiente i dati e le istruzioni da una memoria
ad una ALU e viceversa.
Le usuali operazioni compiute da un processore sono quelle di prelevare dati ed istruzioni dalla
memoria, elaborarli ed infine ritornare in memoria per salvarvi il risultato dell’elaborazione.
L’equivalente di una ALU in un DSP è il DATAPATH, che può essere definito come il percorso
logico aritmetico compiuto dai dati.
Esempio:
Datapath Fixed point
Legge di conservazione dei bit
Il prodotto di due numeri di dimensione n-bit dà come risultato un numero di dimensione 2n-bit.
Caso 1: virgola implicita a destra
x
7
x
7
virgola
implicita a destra
virgola
implicita a destra
x
x
14
concordi
in segno
mi tengo i 7 bit
meno significativi
(mantengo la precisione)
Se i primi 7 bit non sono concordi in segno dovrò operare un rescaling.
Caso 2: virgola implicita a sinistra
x
7
x
virgola implicita
a sinistra
7
virgola implicita
a sinistra
x
x
14
mi tengo
questi bit
11
Overflow
Operando in fixed point, ad ogni operazione bisogna che il programmatore consideri l’eventualità
che si verifichi il caso di overflow o di underflow. Il tipico strumento per rimediare a questa
eventualità è un accumulatore esteso, ma si deve avere anche dell’hardware dedicato: vi devono
essere unità che gestiscono tutto in hardware.
Tipicamente i DSP non possono permettersi di segnalare overflow senza curarsene e prendere degli
accorgimenti, perché in caso di applicazioni critiche non si può interrompere l’esecuzione di
un’elaborazione.
Nei DSP se un numero va in overflow l’Hardware Saturation Overflow vi sostituisce il massimo
numero rappresentabile.
Esempio:
Dimensione dell’accumulatore = 100; senza overflow saturation
40 +20 + 50 = 115 mod 100 = 15;
di fatto: errore = 100
Esempio:
Dimensione dell’accumulatore = 100; con overflow saturation
40 + 20 + 50 = 115 saturated 100 = 100;
di fatto, errore = 15
Si ha sempre un’approssimazione per difetto: nello scalamento, nella normalizzazione, nella
gestione dell’overflow. Questo fatto comporta l’introduzione di un bias statistico: la media diventa
positiva e non nulla.
Esempio:
Si può pensare al caso dell’offset di un amplificatore, che genera in uscita una rampa che satura a 5 volt: si
ha un errore costante che si amplifica.
Arrotondamento hardware
•
round to nearest:
•
convergent rounding:
Arrotondamento al più vicino in hardware (selezionabile)
[0
0,5) [0,5
1]
si ha offset perché 0.5 Æ 1
Quando il numero che deve essere arrotondato si trova a metà
fra i due estremi, si guarda il bit meno significativo:
0 Æ arrotondamento per difetto
1 Æ arrotondamento per eccesso
Nei datapath floating point scompare tutta una serie di problemi, ad esempio si riducono le
complicanze dovute ad overflow.
12
3.2
Architetture di memoria
Tradizionalmente nei microprocessori è utilizzata un'architettura di tipo Von Neumann. Questo tipo
di architettura contiene una singola memoria ed un singolo bus per il trasferimento dei dati da e
verso la CPU. Lo schema di Von Neumann è abbastanza soddisfacente se bisogna eseguire le
operazioni richieste in modo seriale: questo è il caso più comune nei microprocessori.
Quando però si ha bisogno di incrementare la velocità dei processi, si deve far ricorso ad un altro
tipo di architettura, denominata Harvard. Un'architettura di tipo Harvard dispone sia di memorie che
di bus separati per dati ed istruzioni. Un'istruzione di programma ed un dato possono essere caricati
simultaneamente, incrementando le prestazioni rispetto alla configurazione a singolo bus del caso
Von Neumann. La maggior parte dei DSP odierni implementa questa architettura dual bus:
Il nome di Super Harvard Architecture è associato ad un ulteriore miglioramento in termini di
throughput del'architettura Harvard. Queste maggiori prestazioni si ottengono tipicamente
aggiungendo una cache per le istruzioni nella CPU, il che virtualmente rende disponibili al core del
DSP tre bus; naturalmente il termine Super Harvard si può applicare anche al caso di tre effettivi
bus disponibili.
Nel processore SHARC di Analog Devices le prestazione dell’architettura sono ulteriormente
potenziate inserendo un controller di I/O connesso alla data memory (vedi Figura seguente).
Nell’architettura Harvard l’uso di due memorie, una per i dati ed una per le istruzioni, determina un
incremento dei pin del processore. Si deve infatti indirizzare uno spazio di memoria maggiore. Per
risparmiare pin a bordo di un DSP può essere implementata una memoria, mentre il collegamento
alla memoria esterna è demandato ad un unico bus.
13
Multiple Access Memory
La struttura Harvard permette di compiere accessi multipli in memoria. Questi accessi possono
essere sequenziali: in un ciclo di clock si compiono due fetch. Se il DSP-core accede
simultaneamente a due banchi di memoria usando due bus indipendenti si ottengono quattro accessi
in memoria per ciclo di clock.
Un’altra tecnica per implementare una struttura Harvard, al fine di incrementare il numero di
accessi in memoria, è quella di usare memorie multiporte. Una memoria multiporte dispone di più
set di indirizzi e connessioni indipendenti, in modo da permettere un accesso parallelo in memoria.
Il tipo più comune di memoria multiporte è la dual-port memory, che permette due accessi
simultanei.
Esempio:
Interfaccia di una videocamera
A/D
FPGA
DUAL PORT
RAM
DSP
L’uso di una dual-port RAM consente, durante un ciclo di processo, di digitalizzare tramite FPGA i dati in
ingresso dal sensore mentre si elaborano quelli acquisiti nel ciclo precedente.
Si deve considerare quale tipo di memoria utilizzare se si vuole montarla sulla board insieme al
DSP.
•
Ram dinamica:
•
Ram statica:
Più economica
Più complessa
Con circuito di refresh
Più costosa
Più semplice e veloce
Acceleratori hardware
La memoria è composta da registri e da cache: le cache di programma sono memorie veloci che
contengono le istruzioni più probabili. Esse vengono utilizzate per diminuire il numero di accessi in
memoria. I DSP supportano a livello hardware diversi tipi di cache di programma:
Repeat buffer
• single instruction
• multiple instruction
Il fatto che le istruzioni (for, …) siano implementate in hardware nella cache di programma
fa in modo che si liberi il program bus. Si ha un vantaggio architetturale: è possibile mettere
dei dati nella program memory (usarla come data memory).
Un limite del repeat buffer è che non ci possono essere jump, goto, chiamate a subroutine.
Single-sector cache
Un blocco di memoria che contiene un pezzo di programma (qualunque pezzo, non per forza un
loop: ovviamente un pezzo di programma autoconsistente).
14
Multiple-sector cache
A differenza della single-sector cache, questa cache può memorizzare due o più pezzi indipendenti
di programma. Quando bisogna caricare nella cache un nuovo settore, l’algoritmo utilizzato per
scegliere quale settore sostituire è l’LRU (least-recent-used).
Esempio:
N
Calcolo di
z = ∑ a [ i ]∗ b [ i ]
i
Con un assembler-like:
load CONT N
int a, b
LOOP load *a, *b
mpy r1*r2
sum z=z+r1*r2
a++, b++
CONT-if (CONT>0) GOTO LOOP
Con un repeat buffer:
move #a, r0
move #b, r1
move #N-1, mo
Å registro interno del repeat buffer
CLR a, x : (r0) +, x0 y : (r1) +, y0 Å a e b sono su due bus diversi, in un colpo solo faccio tre cose
rep
mac
mac
#length-1
x0, y0, a
x : (r0) +, x0
y : (r1) +, y0
x0, y0, a
Å il loop viene eseguito in hardware
Å a = a+x+y
Å clean-up finale, fuori dal loop
Nel secondo caso, il loop viene eseguito in hardware, liberando il program bus: non devo aggiornare
un contatore oppure effettuare un salto all’inizio del loop. La prima istruzione MAC viene ripetuta con
la massima efficienza per length-1 volte. La seconda istruzione MAC è esterna al loop: viene
eseguita una volta sola.
Wait states
Gli stati di attesa sono un artificio hardware con cui si ritarda l’esecuzione dei processi di un DSP,
nell’attesa di accedere alla memoria. Quando la memoria è disponibile c’è un messaggio di memory
acknowledgement.
I wait states si possono avere in tre casi:
•
•
•
multiple access: a e b sullo stesso bus;
slow memory;
bus sharing: problema sul bus, che risulta occupato con altre periferiche;
15
Se lo schema architetturale è il seguente:
RAM
RAM
DMA
FPGA
DSP
Gli eventuali conflitti dovranno essere risolti da bus arbiter (semafori): si avranno interrupt, buffer
per time sharing…
Quando si attiva il canale DMA, il DSP utilizza la sua RAM, altrimenti non si ricavano benefici da
questo tipo di schema architetturale.
Nei DSP le cache sono ottimizzate per eseguire le istruzioni, non per fare accesso ai dati.
Modi di indirizzamento
•
•
•
•
•
•
•
•
•
Implicito:
Immediato:
Diretto in memoria:
Diretto a registri:
Indiretto via registro
Indiretto via registro:
Indiretto via registro indice:
Modulo addressing:
Bit reversal:
(non devo specificarlo)
(registro = #)
A = DM(1000)
A=x ∗ y
si legge il dato puntato dall’indirizzo contenuto nel registro
con pre/post incremento/decremento
base + offset
buffer ciclico
00101101 Æ 10110100 usato nel calcolo della FFT
L’ultimo modo di indirizzamento, bit reversal, mostra come possono essere specializzati i
processori DSP. L’indirizzamento bit reversal si ha quando un insieme di valori deve essere
riordinato invertendo l’ordine dei bit dell’indirizzo:
•
•
In ogni indirizzo si inverte l’ordine dei bit
I dati vengono spostati in modo che i corrispondenti nuovi indirizzi abbiano un ordine
crescente
Questa operazione è richiesta nel calcolo della Fast Fourier Transform: è facile vedere come i DSP
siano progettati per calcolare efficientemente questa trasformata.
16
3.3
Pipeline
Una istruzione normalmente non viene eseguita in un ciclo di clock, ma in un processo che viene
generalmente scomposto in quattro fasi:
a)
b)
c)
d)
Fetch
Decode
Fetch
Execute
dell’istruzione
dell’opcode
read / write sui dati
ALU / MAC, parte aritmetica
Queste sono quattro fasi logiche, non necessariamente sequenziali.
Esempio:
Se un’istruzione I1 comporta l’esecuzione di tutte le quattro fasi, l’istruzione seguente I2, secondo lo schema
qui riportato, dovrà attendere quattro cicli di clock prima di andare in fetch.
1
a
2
3
4
I1
b
5
I2
I1
c
I1
d
I1
Il 75% delle risorse è fermo ed inutilizzato: supponendo un clock di 20 ns, si ricava un modesto throughput di
un output ogni 80 ns.
Invece di procedere sequenzialmente si può pensare di compiere più operazioni in modo parallelo.
Le istruzioni sono eseguite concorrenzialmente, ognuna in una diversa fase della pipeline.
Esempio:
a
b
c
d
1
2
3
4
5
I1
I2
I3
I4
I5
I1
I2
I3
I4
I1
I2
I3
I1
I2
Trascurando la parte in basso a sinistra (prologo), in questo esempio si ha un uso massimamente efficiente
delle risorse. Considerando il clock sempre di 20 ns, si ha un throughput a regime di un’uscita ogni 20 ns.
L’efficienza del sistema dipende da quanto sono lunghi prologo ed epilogo rispetto a quanto è lungo il ciclo.
17
Esempio:
Interlock
a
1
2
3
I1
I2
I3
I1
I2
I3
I1
I2
I2
I1
I2
b
c
d
4
5
6
In c5 si verifica un conflitto tra I3 ed I2, che ha bisogno di 2 cicli di clock per completare la propria fase r/w.
Il problema del conflitto si risolve con l’interlocking:
a
1
2
3
4
5
6
7
I1
I2
I3
I4Æ
I4
I5
I6
I1
I2
I3Æ
I3
I4
I5
I1
I2
I2
I3
I4
I1
I2
NOP
I3
b
c
d
L’interlocking risolve il problema, ma è difficile calcolarne l’efficienza: se I3 non avesse avuto bisogno della
fase c non si sarebbe introdotto un nop (no operation code).
Patologie derivanti dall’utilizzo di pipeline
Pipeline Hazard
Quando le stesse risorse hardware vengono richieste contemporaneamente da due diverse istruzioni,
o quando un dato viene modificato da un’istruzione mentre un’altra lo richiede in lettura, si
verificano dei casi di pipeline hazard: rispettivamente si parla di hazard strutturali e di hazard sui
dati. Un hazard è una situazione in cui è impossibile prevedere come evolverà il processo, dato che
le varie fasi appartenenti a diverse istruzioni operano concorrenzialmente.
Esempio:
Le istruzioni sono composte da tre fasi:
a) fetch
b) decode
c) execute
Inizialmente sia:
R0 = 5678
MOV
MOV
#1234, R0
x: (R0), x0
(I1)
(I2)
18
a
1
2
I1
I2
b
I1
c
3
4
I2
I1
I2
Si verifica un caso di hazard, perché l’address generation unit indirizza ancora a 5678, invece del nuovo
valore di indirizzo 1234, nel momento in cui la seconda istruzione va in decode.
Un tipo di soluzione può essere quello di interporre un NOP fra le due istruzioni:
MOV
NOP
MOV
#1234, R0
(I1)
x: (R0), x0
(I2)
Un’altra soluzione è quella di operare un interlock:
a
1
2
3
I1
I2
I2
I1
I1
b
c
4
I1
In questo caso l’interlock viene comunque sempre fatto, rallentando sempre la pipeline: è però un trade-off.
Branching effect
Il branch è un’istruzione che comunica al processore di eseguire un salto ad un nuovo indirizzo, dal
quale iniziare una nuova fase di fetch. Questo provoca un rallentamento nella pipeline, oltre a
problemi di gestione delle istruzioni già “fetchate”.
Esempio:
Quando un’istruzione di branch raggiunge la fase di decode nella pipeline, il processore si accorge di dover
saltare ad un nuovo indirizzo, ma l’istruzione successiva (qui I2) è già stata in fetch.
a
b
c
d
1
2
BR
I2
3
4
5
6
N1
BR
N1
BR
BR
NOP
NOP
19
Bisogna riconoscere i salti il più presto possibile nella pipe. Se un salto è di tipo incondizionato, cioè viene
comunque eseguito, questo avviene in fase di decode. Per un salto di tipo condizionato la situazione è più
difficile, perché deve essere verificata una condizione dopo che l'istruzione è stata decodificata e questo
richiede un tempo maggiore. Si deve poi individuare l'indirizzo di salto e caricarlo. Se l'indirizzo deve essere
calcolato seguendo un qualche metodo di indirizzamento, sarà richiesto un ciclo aggiuntivo.
Quando si incontra un branch la pipeline deve essere svuotata, perché le istruzioni successive che sono già
passate dalla fase fetch non possono terminare il loro ciclo. In questa situazione si ha un pipe-flush.
Se si vogliono sfruttare anche i cicli di clock del branch, bisogna che il programmatore inserisca delle
istruzioni che possano essere eseguite negli “slot” rimasti liberi.
BRD
I2
I3
I4
#ADD…
Con questi inserimenti è come se il branch venisse eseguito in ritardo, si parla di delayed branch.
20
3.4
Architettura VLIW ( Very Long Instruction Word )
Un DSP VLIW ha un’architettura interna di tipo parallelo caratterizzata dalla presenza di più unità
funzionali indipendenti. Si può raggiungere un alto livello di performance utilizzando l’instruction
level parallelism ed il data level parallelism. L’instruction level parallelism permette di processare
più operazioni in un singolo ciclo di clock. Con il data level parallelism una singola unità di
esecuzione è separata in porzioni di dati più piccole. Il parallelismo contribuisce ad avere un
throughput massimo.
Esempio:
Architettura VLIW con unità funzionali (process units) indipendenti
32 bit
opcode 1
opcode 2
P.U.1
P.U.2
opcode N
P.U.N
Process Units
Registri, cache, RAM
Effetti dell’architettura Vliw sulle prestazioni:
Instruction Level Parallelism
L’esecuzione dei programmi può essere velocizzata se le operazioni di tipo RISC, come load, store,
moltiplicazioni ed addizioni vengono eseguite in parallelo su unità funzionali differenti. Ogni
istruzione contiene un operation code per ogni unità funzionale, ed ogni unità riceve il proprio code
simultaneamente
Esempio:
Calcolo di y = a1 x1 + a 2 x 2 + a3 x3
RISC
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
VLIW
fetch
fetch
fetch
fetch
mpy
mpy
fetch
fetch
add
mpy
add
a1
x1
a2
x2
a1x1 = z1
a2x2 = z2
a3
x3
y = z1 + z2
z3 = a3x3
y = y + z3
1.
2.
3.
4.
5.
fetch a1 fetch x1
fetch a2 fetch x2 mpy a1x1
fetch a3 fetch x3 mpy a2x2
add z1, z2 mpy a3x3
add z3, y
Lo speed-up è 11/5 > 2 : con la VLIW si impiega meno della metà dei cicli di clock del caso RISC.
21
Data Level Parallelism
La velocità d’esecuzione dei programmi può essere incrementata anche partizionando le operazioni:
una singola unità aritmetica viene scomposta per poi eseguire la stessa operazione su parti più
piccole di dato.
Esempio:
Partitioned Add
Due array da 64 bit devono essere sommati. Ogni unità da 64 bit viene scomposta in otto piccole unità di 8
bit, per poter eseguire otto operazioni in parallelo. Questo è un caso di partitioned-add, dove si ha la stessa
istruzione , un’addizione, su tanti byte diversi.
D7
D0
B7
B0
D7+B7
Esempio:
D6+B6
Partitioned Add (2)
Si prenda l’operazione da svolgere:
In linguaggio C:
char
int
for
D0+B0
r r r
r r r
c = a + b , con a , b , c ∈ IR128 .
a[128], b[128], c[128];
i;
(i=0; i<128; i++)
c[i]=a[i]+b[i]
Si hanno 3 × 128 cicli di clock.
Lo stesso codice può essere eseguito facendo uso di partitioned_add
long
int
for
a[16], b[16], c[16];
// long da 64 bit
i;
(i=0; i<16; i++)
c[i]=partitioned_add (a[i], b[i])
In questo caso i cicli di clock sono 3 × 16.
In questo esempio la performance è stata incrementata di un fattore 8, grazie al data level parallelism.
Siccome il numero di iterazioni del loop decresce anch’esso di un fattore 8, si ha un ulteriore aumento della
performance.
Il processore può supportare il Data Level Parallelism se dispone di un’architettura adatta. Per poter
sfruttare questo parallelismo si deve utilizzare un apposito set di istruzioni. Il prezzo da pagare
nell’eseguire queste istruzioni è il tempo di latenza (latency), che non è uguale a 1.
22
Set di istruzioni
•
•
SIMD Simple Instruction Multiple Data
Gruppi di istruzioni
a) Partitioned (aritmetico/logiche)
b) Σ instructions (inner-product, SAM-Sum Absolute Module, SAD-Sum Absolute
Difference)
c) partitioned_select (min/max, conditional select)
d) formatting (shuffle)
e) multimedia specific
Esempio: Motion Compensation nel DSP
−1
min
r ∑ p i − pi ( x )
x
i
All’interno del modulo c’è un’operazione di SAD.
23
4. La programmazione dei DSP
La programmazione dei DSP coincide con il mapping di un dispositivo.
Requisiti
• Conoscenza approfondita dell’algoritmo
• Conoscenza dell’architettura del DSP
(A questo punto si può supporre che si sia già scelta la famiglia di DSP adatta)
• Conoscenza del set di istruzioni del DSP
Strumenti tecnologici a disposizione
1. Un ottimale set di istruzioni (Che consenta l’implementazione dell’Instruction Level
Parallelism e del Data Level Parallelism)
2. Pipelining
3. Loop unrolling
4. Evitare istruzioni del tipo if, then, else…
5. Scegliere fra rappresentazione ad interi e floating point
6. Uso della DMA (Direct Access Memory)
Analizziamo voce per voce:
1.
Ottimale set di istruzioni
Esempio:
char
for
Look-Up Table
x[128], y[128];
(i=0; i<128; i++)
y[i]=LUT (x[i])
Supponiamo di avere 3 cicli di clock per ogni campione (3 clock/sample).
Vogliamo utilizzare il parallelismo fornito dal DSP (Il DSP a cui si fa riferimento è
il MAP1000):
load 32
v0
v1
v2
v3
expand 8
v0 16
v1 16
expand 16
v0 32
v1 32
v2 16
v3 16
expand 16
v2 32
v3 32
24
v0 32
v1 32
load 16
v2 32
load 16
lut 32 0
load 16
lut 32 1
load 16
lut 32 2
compress 32
lut 16 0
v3 32
lut 32 3
compress 32
lut 16 1
lut 16 2
lut 16 3
compress 16
lut8
lut8
lut8
lut8
store 32
Si hanno 6 accessi in RAM esterna e 6 accessi ai registri interni. Tutto avviene in 6 cicli di clock:
6 clock / 4 sample = 1.5 clock / sample
2.
Pipelining: vedi pag.16
3.
Loop unrolling
Il loop unrolling sfrutta la pipe per accorciare il tempo di esecuzione del programma.
Esempio:
for
(i=0; i<N; i+=2)
y[i] = x[i] × k;
Non è possibile effettuare l’assegnamento prima di eseguire la moltiplicazione.
Ottimizziamo:
for
(i=0; i<N; i+=2){
y[i] = x[i] × k;
y[i+1] = x[i+1] × k;
}
Se la pipe fosse a tre livelli, nel ciclo for bisogna aggiungere un’istruzione y[i+2], e così via.
4.
Evitare istruzioni del tipo if, then, else…
Esempio:
for
(i-0; i<N; i++)
if
(x[i]>y[i])
s = s+x[i];
else
s = s+y[i];
Supponiamo di programmare in C, altrimenti programmando in Assembler il compilatore deve avere delle
librerie intrinsic.
25
Ottimizziamo:
Load 64 (x)
8 bit
8 bit
8 bit
8 bit
8 bit
8 bit
8 bit
8 bit
8 bit
8 bit
8 bit
8 bit
8 bit
8 bit
8 bit
+
+
+
+
+
+
+
Load 64 (y)
8 bit
Compare (x,y)
+
Registro
Select (Registro, x, y)
Max
(x,y)
S
Sum (S, select)
Si ha parallelismo massimo uguale a 8, dovuto alla VLIW (8 char alla volta). Un altro parallelismo, maggiore
di questo, è dovuto al Data Level Parallelism.
5.
Scegliere fra interi e floating point: vedi pag.9
6.
Uso della DMA: Double-buffering
PERIPHERAL
DSP
I/O
DMA
MEMORY
Ho bisogno di un’architettura DMA e di una memoria dual port, o di due banchi di memoria
indipendenti. A livello software devo implementare il ping-pong del buffer per sincronizzarlo con
l’esterno.
26
Algoritmi: Calcolo della FFT
La Butterfly (farfalla) è l’elemento base del diagramma di flusso che descrive il calcolo di una FFT.
Essa prende in ingresso due numeri complessi e li converte in altri due numeri complessi in questo
modo:
Diagramma corrispondente della butterfly FFT:
L:
A:
M:
S:
load
add/subtract
multiply
store
: negate
L1
Ra
A1
S1
A2
Ia
L2
Rb
A3
M1
A5
S2
Ib
A4
L3
M2
A6
M3
M4
Per eseguire con un calcolatore sequenziale 6 addizioni ( 3N log 2 N ), 4 moltiplicazioni
( 2 N log 2 N ), 6 load, 4 store, occorrono molti cicli di clock.
Invece in un DSP A1 e A2 sono parallelizzabili, così come A5 e A6. Inoltre le operazioni di load si
riducono a 3, mentre le istruzioni store diventano 2, grazie alla lunghezza della instruction word
(es.16bit).
27
Algoritmi: Calcolo della DCT
(blocchetti 8 × 8)
(2 j + 1)π u f  ⋅ cos (2 j + 1)π r
c (r )  7 c(u )
cos
∑
ij 

16
16
r =0 2
 n =0 2

7
ω ij = ∑
ω ij
i, j = 0,...,7
valore nello spazio trasformato
c (r ), c (u )
 2

 2
1

r, u = 0
else
Per implementare questa DCT è necessario eseguire 16 somme, 26 moltiplicazioni, 16 load, 8 write.
La versione ottimizzata sul C80 della Texas Instruments costa 104 cicli di clock: è un buon
risultato, visto che solo per leggere i dati in ingresso si spendono 64 cicli di clock.
Algoritmi: Filtro FIR
Un filtro FIR è un’altra implementazione tipica dei DSP, come si è visto finore, dato che il calcolo
richiesto in un filtro FIR consiste banalmente in prodotti scalari.
Algoritmi: Calcolo dell’inversa della radice quadrata mediante Newton-Raphson
L’uso di librerie matematiche agevola ilcompito del programmatore ma talvolta può rendere
estremamente inefficiente il codice. Questo di solito accade quando la funzione che si vuole
calcolare non è direttamente rappresentata in termini di semlici potenze delle grandeze di ingresso.
Un esempio tipico è la funzione
y(x ) =
1
x
Questo calcolo è in effetti assai frequente in applicazioni di signal processing, perché per esempio
compare nelle FFT inverse ed in molte operazioni di normalizzazione.
In prima istanza, uno potrebbe implementare la y(x) in linguaggio C con le seguenti istruzioni:
#include <math.h>
.
.
double y, x;
.
.
y=1./sqrt(x) ;
Tuttavia un’analisi computazionale del codice di cui sopra mostra che esso richiede una chiamata a
funzione di libreria matematica (il cui costo può essere ignoto a priori, salvo approfondite ricerche
nella documentazione, con la conclusione che risulta molto elevato), ed una divisione, operazione di
solito invisa ai progettisti hardware perché onerosa e fonte di errori.
28
Esiste in effetti un metodo iterativo per calcolare la y(x) con solo somme e prodotti (e quindi,
estremamente DSP-friendly). L’algoritmo definisce una funzione costo di approssimazione:
1
g(y) = x − 2
y
Se si esclude il caso banale x=0 y=0 facilmente verificabile ed evitabile a priori, lo zero della
funzione g(y) (ovvero il valore di y per cui g si annulla) è la soluzione al problema in esame.
Si applica a tal fine il metodo iterativo di Newton-Raphson (NR), che ad ogni iterazione scende
verso lo zero secondo la derivata prima della funzione stessa. Si ha che:
dg 2
=
dy y 3
Per applicare NR, si inizia in un punto di tentativo y0; ad ogni iterazione yn, si intercetta l’asse y con
la retta tracciata dal gradiente in yn, il nuovo punto yn+1 così trovato diventa il punto di partenza della
prossima iterazione.
0 − g ( yn )
2
= g ′( y n ) = 3
y n+1 − y n
yn
risolvendo per yn+1 si ottiene:
y n+1 =
(
1
y n 3 − y n2 x
2
)
che come richiesto contiene solo somme e moltiplicazioni.
A meno di casi patologici, se il punto iniziale y0 non è troppo distante dalla soluzione l’algoritmo
converge in meno di una decina di passi.
Algoritmi: Calcolo dell’inversa della radice quadrata medinate Look-Up Tables
Un altro sistema per calcolare 1/√x prevede di scomporre l’intervallo di interesse (nel nostro caso,
per semplicità si considera il range [0,1]) e calcolare la funzione non lineare nei punti di confine fra
le diverse regioni.
I valori intermedi potranno essere calcolati come interpolazione lineare lungo la retta che connette
tali estremi. A tal finesarà sufficiente il valore dell’intercetta della retta sull’asse x e la pendenza
(coefficiente angolare) della retta stessa. Pertanto per ogni intervallo dovremo momorizzare due
valori.
Nel caso particolare della funzione x-½ , il trucco consiste nel dividere il range [0,1] in intervalli non
uniformi ma ripartiti secondo una scala logaritmica, ovvero dicotomica. La figura seguente illustra
la strategia di scomposizione.
29
f(x)
0
1/16 1/8
1/4
1/2
1
x
Per implementare la funzione non lineare si utilizza quindi una LUT (look-up table), che memorizza
i dati relativi agli intervalli spaziati logaritmicamente.
Come anticipato sopra, per ogni intervallino si prendono pendenza e intercetta delle rette
y = mx + n
Nela scomposizione di cui sopra in quattro intervalli, otteniamo dunque questa tabella:
Intervallo
1
1
÷ 3
4
2
2
1 1
÷
8 4
1 1
÷
4 2
1
÷1
2
m
4( 2 − 1)
n
(2 − 2 ) / 4
2( 2 − 2 )
( 2 − 1) / 2
2( 2 − 1)
(2 − 2 ) / 2
(2 − 2 )
( 2 − 1)
Il notevole vantaggio di questa tecnica è il fatto che la tabella memorizza di fatto solo due valori:
•
(2 − 2 )
•
( 2 − 1)
oportunamente moltiplicati o divisi. Ma tali moltiplicazioni o divisioni riguardano solamente
potenze di 2, e sono quindi facilmente implementabili da banali ed operazioni aritmetiche. La LUT
diventa quattro volte più piccola ed è virtualmente indipendente dalla precisione nella
rappresentazione dei valori contenuti.
30
Algoritmi: Calcolo dell’inversa
Con lo stesso procedimento mostrato sopra si può anche calcolare l’inversa y(x) = 1/x di un numero
con solo somme e prodotti.
La funzione costo da definire e la sua derivata sono:
g(y) = x −
g ′( y ) =
1
;
y
1
;
y2
Applicando Newton-Raphson come visto in precedenza la formula iterativa di somme/prodotti
diventa:
y n+1 = 2 y n (1 − y n x ) .
Questo metodo consente dunque di calcolare un rapporto fra due numeri attraverso solo
moltiplicazioni e somme iterate:
a
1
= a⋅
b
b
Vva detto tuttavia che le considerazioni fatte a suo tempo a proposito dell’intervallo di convergenza
sono in questo caso più stringenti. In altre parole è assai più critica, in questo caso, la scelta del
punto iniziale da cui far partire le iterazioni di Newton-Raphson.
Tecniche di programmazione dei DSP: C versus Assembler
In un DSP tutte le istruzioni possono essere condizionabili, quando il problema si complica è
necessaria una particolare cura nella programmazione. Se si lavora in assembler bisogna che il
programmatore conosca molto approfonditamente l’architettura sulla quale il suo algoritmo dovrà
essere implementato. Lavorando invece in C++ si può sperare, con buoni motivi, nella efficienza
del compilatore: il C++ disaccoppia la persona che si preoccupa di sviluppare l’algoritmo da quella
che deve pensare all’architettura del DSP.
Mostriamo come lo stesso problema può essere risolto nei diversi linguaggi e a diverso livello.
Esempio:
Prodotto scalare (Dot product)
s = ∑ xi y i
i
1)
Programma in C per DSP:
#define L 20
float dm x[L];
float pm y[L];
float s;
main( )
{ int n ; for ( n=d; n<L; n++)
s += x[n] ∗ y[n];
}
31
2)
Traduzione in assembler del programma 1 per il DSP SHARC (Analog Devices):
il2 = _y
i4 = _x
lcntr = 20 do (pc, 4) until lce
f2 = dm (i4, m6)
f4 = pm (il2, ml4)
f8 = f2 ∗ f4
fl2 = fl2 + f8
Legenda:
lcntr:
lce:
f2,f4,…:
20 do ( ):
(pc, 4):
repeat buffer;
l counter entità;
registri interni;
ripeti 20 volte;
sono 4 istruzioni;
Il costo del programma è di 20 ∗ 4 = 80 cicli di clock.
3)
Traduzione ottimizzata in assembler dello stesso programma:
il2 = _y
i4 = _x
f2 = dm (i4), f4 = pm (il2)
f8 = f2 ∗ f4, f2 = dm (i4)
lcntr = 18 do (pc, 1)
fl2 = fl2 + f8, f8 = f2 ∗ f4, f2 = dm (i4), f4 = pm(il2)
fl2 = fl2 + f8, f8 = f2 ∗ f4
fl2 = fl2 + f8
1
1
18
1
1
Il costo del programma ottimizzato è di 1+1+18+1+1 = 22 cicli di clock.
I DSP, come altre applicazioni scientifiche ed ingegneristiche, sono programmati in linguaggio
assembler oppure in C/C++. I programmi scritti in assembler possono essere eseguiti più
velocemente, mentre i programmi in C sono più facili da sviluppare.
Criteri di scelta progettuale fra linguaggio C e Assembler
1)
Quanto è complicato il programma?
Se il programma è articolato e complesso, bisognerà probabilmente usare il C.
Se invece il programma è piccolo e non presenta particolari complessità, la scelta
migliore sarà l’assembler.
2)
Serve massimizzare la velocità del DSP?
Se la risposta è sì, la migliore performance si potrà ottenere solo facendo uso
dell’assembler.
Quando la velocità non è determinante, si può considerare l’uso del linguaggio C.
3)
Quanti programmatori lavorano al progetto?
Se il progetto deve essere condiviso da più di due programmatori, probabilmente la
scelta si orienterà verso il C.
4)
Incide di più il costo del prodotto oppure il costo di sviluppo?
Se pesa maggiormente il costo del prodotto si sceglierà l’assembler. Si opterà invece per
il C se il costo di sviluppo si rivela critico.
32
5)
Esperienza del programmatore software.
Se il programmatore software è molto esperto in assembler, lo sceglierà per il suo lavoro
con i DSP.
6)
Consigli della casa produttrice.
Questo punto è molto importante. Infatti le indicazioni della casa produttrice possono già
da sole determinare la nostra scelta.
Un buon compromesso è quello di costruire l’architettura software in C, mentre nelle situazioni
critiche utilizzare l’assembler.
Esempio: C versus Assembler
1)
Chi programma i microprocessori...
Nel 90% dei casi utilizza il C, nel rimanente10% si serve dell’assembler.
2)
Chi programma i DSP...
Nel 55% dei casi utilizza il C, mentre nel 45% lavora con l’assembler
3)
Nelle applicazioni che generano un guadagno netto molto alto...
Solo il 30% si serve del C, mentre ben il 70% dei programmatori lavora con il linguaggio
assembler.
33
5. Misura delle prestazioni di un DSP
Quando si tratta di misurare le prestazioni di un microprocessore, spesso si citano termini come
MIPS, MFLOPS, MMACS. Dal punto di vista dell’utilizzatore bisogna tenere in considerazione il
contesto delle applicazioni che vengono utilizzate e per le quali il DSP è stato realizzato.
MIPS:
Milioni di istruzioni al secondo
Forse fra tutti gli indici è il meno utile: viene misurato contando il numero di
istruzioni eseguite da un certo insieme di programmi. Il risultato viene poi diviso per
il tempo di esecuzione. Sfortunatamente il valore che viene riportato sui vari data
sheets si riferisce ad un MIPS di picco.
MFLOPS:
Milioni di floating point operations al secondo
Il numero di operazioni floating point che un DSP può eseguire al secondo fornisce
un’indicazione sulla potenza di elaborazione del dispositivo. Questa è
un’informazione interessante: il problema sta nel modo di calcolare questo valore.
Infatti un’operazione MAC esegue tre operazioni diverse in un solo ciclo di clock:
quando viene considerata tre volte invece di una sola, le prestazioni risultano
migliori, ma è solo un’apparenza.
MMACS:
Milioni di operazioni MAC al secondo
Questo valore è abbastanza utile, anche se non fornisce indicazioni sulle applicazioni
associate al DSP. Però si trova raramente sui data sheets.
Application Cube
Dimensione codice
MIPS
Power
(Potenza dissipata)
Un altro modo di valutare le performance di un DSP è costruire un application cube come quello
mostrato qui sopra. Nell’esempio vengono posti a confronto diversi parametri da ottimizzare, come
MIPS, dimensione del codice e potenza dissipata. L’aspetto più utile di questo tipo di
rappresentazione è quello di rendere visiva la collocazione di un DSP nello spazio tridimensionale
determinato dalle misure dei parametri scelti.
Benchmarking
La strategia migliore da adottare quando si utilizzano i benchmark è quella di testare i DSP
eseguendo le applicazioni per le quali è stato progettato. Le indicazioni che si possono trarre da
queste analisi, per quanto accurate, non forniscono comunque informazioni su quelle che saranno le
prestazioni in caso di processo di segnali in tempo reale, quando il flusso di dati fra DSP e
componenti esterni diventerà un problema.
34
Esempio:
Funzione
Complex FFT a 1024 campioni
FIR (per TAP): delay + mpy + add
IIR (per biquad)
Divide (x/y)
Inverse square root ( 1 x )
Tempi
Cicli di clock
0.46 ms
25 ns
100 ns
150 ns
225 ns
18.221
1
4
6
9
In generale con i benchmark non si possono confrontare adeguatamente due DSP, ma si può operare
una scelta fra diverse famiglie di DSP. Naturalmente bisogna innanzitutto considerare quali sono i
specifici ambiti di utilizzo indicati dal produttore per ciascun DSP o famiglia di DSP.
Esempio:
Benchmark di un DSP SHARC, di Analog Devices
Il throughput di un particolare algoritmo di un DSP può essere ricavato dividendo la frequenza di clock, in
questo esempio 40 MHz, per il numero richiesto di cicli di clock per campione.
I DSP appartenenti alla famiglia SHARC possono eseguire un’operazione MAC in un singolo ciclo di clock.
Siccome molti filtri FIR utilizzano fra 25 e 400 coefficienti, sono necessari da 25 a 400 cicli di clock perché
ogni campione sia processato. Per ottenere il throughput del filtro dividiamo la frequenza di clock, 40 MHz,
per questi valori: otteniamo una data rate massima compresa fra 100K e 1.6M sample/secondo.
In caso di fitri IIR, i coefficienti sono da 5 a 17. Siccome questi loop sono relativamente brevi, dobbiamo
sommare un piccolo overhead, circa tre cicli per campione. I cicli di clock necessari diventano compresi fra
8 e 20, sempre perché sia processato un singolo campione. Il throughput massimo corrispondente varia fra
1.8M e 3.1M sample/secondo.
Il calcolo di una FFT a 1024 campioni richiede in questo DSP 18221 cicli di clock, circa 0.46 ms a 40 MHZ.
Per calcolare il throghput è comodo considerare questo dato in termini di 17.8 cicli di clock per campione.
Una FFT a 256 campioni richiede 14.2 cicli di clock per campione, mentre una FFT a 4096 campioni ne
richiede 21.4. In generale possiamo considerare un range che varia fra 10 e 22 cicli di clock per campione. Il
corrispondente throughput risulta essere fra 1.8M e 3.3M sample/secondo.
La convoluzione della FFT è un modo veloce per calcolare i filtri FIR. In un caso tipico essa richiede 60 cicli
di clock per essere eseguita, determinando un throughput dei dati di circa 660k sample/secondo.
La convoluzione della FFT in 2 dimensioni, richiesta nell’elaborazione delle immagini, in un caso tipico è
associata ad un throughput di 260k sample/secondo.
35
6.
Un’introduzione ai DSP TMS320C6000
In questo capitolo introduciamo alcune caratteristiche dei processori appartenenti alla famiglia di
DSP TMS320C6000, ed in particolare del C62 (fixed point) e del C67 (floating point).
Questi DSP della Texas Instruments sono attualmente fra i più veloci in commercio: con 8
istruzioni da 32 bit per ciclo raggiungono i 4800 MIPS di picco. I clock variano fra 150 e 250Mhz.
Presentano un’architettura chiamata VelociTi Advanced Very Long Instruction Word, o Advanced
VLIW, composta di otto unità funzionali indipendenti:
•
•
•
4 ALU in virgola fissa e mobile
2 ALU in virgola fissa
2 Moltiplicatori in virgola fissa e mobile
Il DSP core è costituito da 32 registri general purpose di 32 bit , mentre la compattazione delle
istruzioni permette di ridurre la dimensione del codice.
Sono supportati i dati ad 8, 16, 32 bit, mentre le moltiplicazioni ad interi 32bit × 32bit possono
restituire il risultato a 32 bit oppure a 64 bit. L’hardware support è in grado di elaborare operazioni
floating point in singola (32 bit) oppure doppia precisione (64 bit)
Altre caratteristiche sono la presenza di 1M bit di SRAM on-chip, 512 Kb di cache interna per il
codice (16K per 32 bit per istruzione), 512 Kb di dual access memory interna per i dati.
L’interfaccia con la memoria esterna è a 32 bit: la memoria è indirizzabile a 32 bit, circa 4 Giga.
Nel caso del ‘6201 e del ‘6701 la memoria on-chip consiste di blocchi di 64 Kb configurabili dal
programmatore come cache oppure come spazio mappato in memoria.
36
Il fetch delle istruzioni prevede la generazione fino ad 8 istruzioni a 32 bit: grazie all’architettura
VLIW il fetch avviene realizzato a 256 bit, grandezza del bus della program memory interna al
DSP. Il pacchetto di fetch ha dimensione fissa, a differenza del pacchetto di esecuzione che può
avere dimensione variabile. Il bit meno significativo di ogni istruzione viene utilizzato per indicare
se la prossima istruzione da eseguire fa parte o meno del pacchetto di esecuzione corrente, o se
invece deve essere eseguita nel ciclo di clock successivo. Se il pacchetto di esecuzione supera il
confine di fetch, il pacchetto di fetch successivi è riempito di NOP (interlock).
Architettura del DSP core
Le unità funzionali del DSP core sono suddivise in due datapath, ognuno dei quali contiene quattro
unità ed un register file. Il primo datapath contiene le unità .L1, .S1, .M1 e .D1, mentre il secondo
contiene le unità .D2, .M2, .S2, .L2. I due register file contengono ciascuno sedici registri general
purpose a 32 bit. Le quattro unità funzionali di ogni datapath possono essere suddivise a scelta del
programmatore fra i corrispondenti sedici registri. Inoltre ogni datapath dispone di un bus dati
attraverso il quale può connettersi con i registri dell’altro datapath, dai quali può ad esempio leggere
un operando. I 32 registri general purpose sono a 32 bit, ma possono supportare dati fino a 40 bit.
37
Indice
1. Introduzione: caratteristiche descrittive dei DSP
1.1 Che cosa fa un DSP: caratteristiche operative
2
3
2. Rappresentazione Numerica
6
3. Caratteristiche Hardware
10
3.1 Architettura classica di un DSP
10
3.2 Architetture di memoria
12
3.3 Pipeline
16
3.4 Architettura VLIW ( Very Long Instruction Word )
20
4. La programmazione dei DSP
23
5. Misura delle prestazioni di un DSP
32
6. Un’introduzione ai DSP TMS320C6000
34
38