Come abbiamo visto nei precedenti articoli che hanno parlato di quest’arcinota famiglia di CPU, il progetto originale era stato pensato per semplificare l’implementazione, favorendo efficienza, compattezza del codice e minor spreco di spazio, anche se a spese dello spazio d’indirizzamento della memoria (limitato a 64MB).
Questo limite è stato rimosso dalla versione 3 dell’architettura, ponendo delle solide basi per il suo futuro, che l’ha vista protagonista di innumerevoli modifiche, indice anche questo dell’apprezzamento di questa ISA molto versatile.
Data la naturale predisposizione per l’impiego nei sistemi embedded (ricordo che il core al completo della v3 conta soltanto 35mila transistor, con consumi ridottissimi), alcune di esse sono state orientate verso l‘integrazione di funzionalità DSP, particolarmente importanti e utilizzate in questo settore / mercato.
DSP è un acronimo che sta per Digital Signal Processor, ed esplicita il compito per cui nasce un processore di questo tipo: l’elaborazione digitale dei segnali, la quale avviene tramite l’applicazione di algoritmi che in genere fanno massiciamente uso di operazioni di somma, sottrazione, e moltiplicazione fra interi.
La trasformata veloce di Fourier (FFT), la trasformata discreta del coseno (DCT), i filtri FIR, di convoluzione, ecc. sono operazioni molto comuni utilizzate nell’elaborazione dei segnali, e le loro implementazioni sono tipici esempi di ampio utilizzo delle istruzioni sopra citate.
In particolare sono molto comuni operazioni di tipo accumulazione e saturazione. Per le prime si tratta di moltiplicazioni di interi (generalmente a 16 bit) a cui viene sommata una certa quantità che viene successivamente conservata per essere riutilizzata nuovamente nel processo (rappresenta l’accumulatore, appunto).
Le seconde sono addizioni e sottrazioni in cui eventuali overflow o underflow non comportano la tradizionale applicazione del modulo (ad esempio 28 lavorando a 8 bit), ma il valore eccedente il limite consentito viene sostituito col limite stesso.
Quindi se, ad esempio, facciamo uso di quantità a 8 bit con segno e sommiamo i valori 100 e 50, il risultato che verrà fuori non sarà -106 (150 se lavorassimo senza segno), ma 127 (che è il limite superiore per gli interi positivi).
Questo tipo di operazioni è estremamente importante perché consente, come si è visto, di mantenere i valori entro i limiti dell’intervallo numerico utilizzato, evitando che si passi da un estremo all’altro e che, quindi, si producano fastidiosi sbalzi nel segnale elaborato che porterebbero, per citare qualche caso ben noto, a rilevabili imperfezioni grafiche oppure a click/pop dell’audio.
Per realizzare ciò ARM ha presentato, con la versione 5 dell’architettura, apposite estensioni chiamate Enhanced DSP Extension (i modelli che le implementano si riconoscono dalla lettera E appesa al nome) che introducono diverse caratteristiche:
- numerose istruzioni di moltiplicazione e accumulazione (con valori sia a 16 che a 32 bit per il moltiplicando, e a 32 e 64 bit per l’accumulatore)
- altre istruzioni di moltiplicazione (16×16 e 32×16)
- istruzioni per la somma e la sottrazione “saturate” (con apposite varianti per raddoppiare il valore a un operando prima di effettuare l’operazione; utile in alcuni algoritmi per risparmiare un’altra istruzione)
- nuovo flag nel registro di stato (Q, utilizzato per controllare se una catena di operazioni abbia prodotto almeno una volta un valore oltre i limiti numerici stabiliti)
- istruzioni di load & store in grado di prelevare 64 bit dalla memoria (per caricare più dati, ottimizzando i trasferimenti con la memoria, ma col vincolo dell’allineamento a 64 bit)
- istruzioni di trasferimento di due registri fra il core e un coprocessore (anche qui per risparmiare un’istruzione, ottimizzando i trasferimenti interni)
- un’istruzione di hint, cioé “suggerimento”, al memory controller (per precaricare dati che serviranno più avanti, in modo da ritrovarli già nella cache)
Non siamo in presenza di stravolgimenti dell’architettura, perché a conti fatti ci ritroviamo con appena 14 istruzioni aggiunte all’ISA, e un bit nel registro di flag (che aveva parecchio spazio non utilizzato, essendo a 32 bit). Inoltre le istruzioni di moltiplicazione fanno uso dell’apposita sezione già presente nel microprocessore (infatti non sono stati aggiunti altri moltiplicatori; elementi, questi, che richiedono un bel po’ di transistor).
Con poche e mirate modifiche ci ritroviamo con un’architettura in grado di assolvere discretamente a funzionalità tipiche di un DSP (la cui “emulazione” avrebbe altrimenti richiesto l’impiego di numerose istruzioni, aumentando considerevolmente i tempi di calcolo), senza richiedere coprocessori dedicati o cambiamenti radicali.