L’Architettura ARM 7

Nel 1983, un gruppo di ingegneri britannici di Acorn, fu sfidato a trovare una soluzione ingegneristicamente valida per la seconda versione di uno degli home computer più diffusi dell’epoca, il BBC Micro. Fu l’inizio di una lunga avventura tecnologica, che avrebbe portato, ai giorni nostri, ARM ad essere il processore  più diffuso al mondo, con quote di mercato superiori al 90% nel settore dei dispositivi mobili phones. In questo articolo descriveremo la sua declinazione  più diffusa: ARM 7.

Acorn è stata un’azienda britannica attiva nel campo degli home computer, che qualcuno ricorderà, per avere prodotto l’Acorn Archimedes, home computer che, sulla carta, avrebbe dovuto essere avversario del predominio dei mitologici Commodore Amiga e Atari ST nel settore home con ambizioni office. La storia dell’architettura ARM inizia, da qui, Acor n Computers, primi anni’80. Acorn era stata la produttrice del primo home computer di gran diffusione nel mercato britannico, il BBC Micro, oggetto commissionato da British Broadcasting Company sull’onda dello stimolo all’alfabetizzazione informatica molto comune all’epoca. Nel 1983 BBC commissionò ad Acorn la realizzazione di una versione migliorata del BBC Micro (questo adottava l’economico 8 bit MOS 6502), in grado di reggere  il confronto con i nuovi computer che si stavano affacciando sul mercato e in grado di far girare applicazioni più complesse. Gli ingegneri di Acorn, nella scelta del core su cui basare il nuovo progetto, puntarono la loro attenzione sui microprocessori a 16/32 bit. Il settore all’epoca era dominato da Motorola con il 68000 - che sarebbe stato poi usato nel best seller Amiga -, e vedeva il rinforzarsi del dominio Intel con il giovane 286, il primo Intel ad avere un embrione di protected mode, cosa che avrebbe permesso nel futuro lo sviluppo di Windows. Il gruppo di progetto ben presto, scoprì che i microprocessori commerciali dell’epoca non soddisfacevano esattamente le loro esigenze. Infatti, questi erano più lenti dei corrispettivi chip di memoria standard disponibili all’epoca, avevano set d’istruzioni complesse che ne comprendevano alcune lunghe centinaia di cicli d’esecuzione, determinando un’enorme latenza potenziale nell’esecuzione degli interrupt di sistema.

La principale causa di queste carenze era, fondamentalmente, che i primi microprocessori integrati erano stati modellati su quelli disegnati per i minicomputer, che tipicamente consistevano di diversi chip cablati insieme ed avevano set di istruzioni molto complesse cablate inter namente in microcodice. Gli ingegneri Acorn, di necessità fecero virtù, e iniziarono a considerare l’idea di progettarsi in proprio un microprocessore; le risorse necessarie per un tale progetto, tuttavia, erano ben al di là di ciò che la compagnia poteva permettersi. Nei primi anni 80, le architetture dei microprocessori erano diventate così complesse che, allo scopo di progettare ex novo un processore, ci volevano molti anni-uomo anche per grandi imprese con significativa esperienza nel campo. Per fortuna, appena due anni prima, l’università’ di Berkeley aveva dimostrato con il progetto RISC1 come fosse effettivamente possibile costruire un processore molto semplice con prestazioni paragonabili a quelle dei più avanzati processori CISC del tempo. Acorn decise di sposare l’approccio Berkeley, e due anni dopo, nel 1985, presentò  il primo processore 26 bit Acorn RISC Machine (ARM), che divenne anche il primo processore RISC commerciale al mondo. Furono usati meno di 25.000 transistor - un numero molto limitato, anche per il 1985- ma le performance furono praticamente le stesse (o in alcuni casi superiori) al 80286 di Intel, nato all’incirca nello stesso periodo.

Famiglie ARM

Questa prima architettura prototipale è ora conosciuta come ARM versione 1. ARM1 fu seguita da un secondo processore, progettato nel 1987. La novità principale introdotta nella versione ARM 2 fu il supporto al coprocessore matematico. In seguito la versione ARM 2 fu implementata con cache on-chip nella versione di ar-chitettura successiva ARM3. Saltando nel tempo, nel 1990 Apple prese la decisione strategica di utilizzare un processore ARM nel suo nuovo PDA Newton, allo scopo fu fondata una joint venture tra Acorn e Apple per la progettazione di un nuovo processore basato su architettura ARM, ma più avanzato. La società in joint-venture fu chiamata ARM Ltd, la sigla, in questo caso, sta per Advanced RISC Machine. La terza versione di architettura ARM fu sviluppata direttamente da questa società, nella quale erano intanto confluiti i  gruppi di progetto di Acorn, e fu la prima ad avere uno spazio di memoria a 32 bit, il supporto MMU ed un’istruzione di moltiplicazione e addizione a 64-bit. Sfogliando la tabella 1 si capisce come vi è differenza tra il tipo d’architettura ARM implementata e il nome commerciale del core che la implementa.

Tabella 1 - le varie famiglie ARM

Tabella 1 - le varie famiglie ARM

Ad esempio, infatti, la citata architettura ARM 3 fu implementata per la prima volta solo nei processori ARM 6 e ARM 7. Il rilascio  di questi processori e del PDA Apple Newton nel 1992 segnò il passaggio di ARM ad un mercato di riferimento ben preciso: il segmento embedded; inoltre il modello di business cambio verso una rotta che avrebbe fatto scuola, l’azienda divento una fabless. Con questo termine s’intende un’azienda che produce soltanto IP (proprietà intellettuali), quindi il cui prodotto è il progetto del core del processore, e non direttamente l’hardware. Sta ai produttori di terze parti implementare nell’hardware il core ARM contornato delle giuste periferiche. Con queste premesse manageriali e con le successive implementazioni, ARM divento un’azienda di successo globale. La quarta generazione di core ARM è uscita nel 1996. La principale innovazione in questa versione di architettura è stato il supporto al set di istruzioni Thumb. Il codice Thumb, è codice compresso a 16 bit, occupa il 40% in meno di spazio rispetto al codice ARM 32-bit standard, ma è leggermente meno efficiente. Un’altra implementazione popolare dell’architettura ARM versione 4 e stato lo StrongArm. Nel 1999, la quinta generazione di architettura ARM ha introdotto nuove istruzioni DSP e estensioni per supportare direttamene in hardware il byte code Java nel set di istruzioni ARM. La più popolare delle implementazioni di questa architettura è il  processore Intel XScale, utilizzato in una varietà di dispositivi embedded, tra cui i processori di rete, smart-phones e PDA. La sesta generazione di architettura ARM è stato rilasciata nel 2001, le principali novità sono l’estensione al set di istruzioni SIMD, un migliore set di istruzioni Thumb, il TrustZone  che è una tecnologia di virtualizzazione, e il supporto multiprocessore. E’ stata recentemente rilasciata ARM v7, ha un set di istruzioni SIMD allargato e un migliorato supporto alle operazioni in virgola mobile. Il rappresentante  più importante per la quarta generazione di ARM (diremo meglio, per l’intera storia di ARM) è stato sicuramente il nucleo ARM7TDMI. Ancora oggi il cosiddetto ARM7 è l’architettura che conta la maggior diffusione nel mondo embedded (con milioni di chip venduti che lo contengono), in particolare, viene usato nella maggior parte dei lettori Apple iPod, compreso l’iPod Video. Anche La descrizione dell’architettura ARM, come si è capito dalle ragioni storiche e un continuum tecnologico, quello che diremo vale in gran parte per tutti gli ARM, ma il focus sarà sul best seller ARM 7.

Introduzione all’architettura ARM 7 TDMI

ARM 7 è un processore a 16/32 bit che implementa nella versione TDMI l’architettura inter na ARM v4 (alcuni modelli implementano la ormai obsoleta ARM v3). Con quest’architettura  il processore è stato implementato dai chip-maker in milioni di pezzi ed è presente nell’80% dei sistemi embedded mobili. L’ARM 7TDMI implementa intorno all’architettura di base versione 4, una struttura senza cache e con accesso diretto alla memoria. La sigla TDMI sta per:

» “T” - Thumb, che come abbiamo detto è l’estensione a 16-bit del set di istruzioni di ARM originariamente a 32 bit;

» “D” e “I” riguardano le capacita di debug on-chip presenti nel core ARM. Le lettere stanno per segnali di Debug e embeddedIce logic, rispettivamente.

» “M” - supporto al moltiplicatore a 64-bit L’ARM v4 conserva l’architettura tipica dei primi ARM: struttura tipo Von Neumann con una pipeline a 3 livelli ed implementa  il set d’istruzioni ridotto e orientato a muovere dati fra registri di tipo load-and-store, tipico del mondo RISC, un Register File a 16 registri che può assumere diverse funzioni a seconda della modalità operativa e con il Program Counter che è uno dei registri (in particolare R15) e che quindi può essere trattato come un registro standard. La scelta dell’architettura di tipo Von Neumann (ricordiamo che quest’architettura usa un solo bus misto istruzioni-dati e si contrappone all’architettura Harvard con bus separati per dati e istruzioni) fu fatta nei primi ARM per ridurre il costo del processore. La scelta, oculata per l’epoca in termini di costi/benefici, limita nei fatti le performance complessive del sistema in quanto la tipica operazione di load o di store ha bisogno di due colpi di clock (uno per le istruzioni e uno per i dati) per essere eseguita; questo fa si che la pipeline a tre stadi sia leggermente inefficiente. ARM 7TDMI è l’ultimo processore ARM con architettura Von Neumann e tutte le successive sono architetture Harvard (innegabilmente più di successo nel mondo embedded vedi  Microchip PIC, Atmel AVR, etc.).

L‘ARM® Cortex™-A8 di Texas Instruments.

L‘ARM® Cortex™-A8 di Texas Instruments.

ARM ISA (Instruction Set Architecture) e pipeline

La ISA di ARM è una classica load-andstore, ciò significa che non esistono istruzioni che possano muovere direttamente dati da memoria a memoria, tutte le istruzioni coinvolgono l’uso di (almeno) un registro. L’architettura si distingue da una canonica architettura RISC per alcune scelte ardite per l’epoca in cui furono decise: la prima è la gia citata architettura Von Neumann, questa inficia la regola di “un colpo di clock - un’istruzione” usata nel design RISC, ma abbassa i costi del processore. Per recuperare un colpo di clock nell’indirizzamento della memoria, in ARM è presente il modo d’indirizzamento in auto-addressing che incrementa in automatico il puntatore all’area di memoria che si vuole manipolare. Inoltre ARM supporta sia istruzioni a singolo registro sia istruzioni a registro multiplo, queste ultime sono usate per muovere da e verso la memoria l’intero blocco del register file, in una sola istruzione; questo tipo d’istruzioni è molto utile nei sistemi operativi per effettuare cambi di contesto fra i processi. In ARM una delle proprietà più importanti, e che ne ha decretato il successo, è la semplicità dell’architettura; i progettisti hanno scelto di non implementare tecniche hardware d’ottimizzazione particolarmente raffinate come register window, o register aliasing, esecuzione fuori ordine o branch prediction etc..., questo ha permesso di tenere la implementazione hardware della pipeline semplice e lineare dalle prime versioni di architettura sino alle ultime. La pipeline a 3 stadi è usata per aumentare le performance del sistema eseguendo in parallelo le tre operazioni che un processore deve compiere ad ogni nuova istruzione: Fetch, Decode ed Execute. L’hardware è stato disegnato per rendere ogni operazione completamente indipendente, cosi che, a regime e a pipeline piena, fino a tre istruzioni in sequenza possano essere processate contemporaneamente. In ogni caso, ricordiamo che, stalli del sistema o istruzioni di salto possono invalidare i benefici di avere una pipeline profonda. Il primo stadio della pipeline legge un’istruzione dalla memoria e incrementa  il valore del registro che memorizza  il valore della prossima istruzione da fetchare, e questo valore è memorizzato anche nel Program Counter. La fase successiva decodifica l’istruzione e prepara i segnali di controllo necessari per l’esecuzione. Il terzo stadio fa tutto il  lavoro effettivo: legge gli operandi dal register file, esegue le operazioni ALU, legge o scrive la memoria, se necessario, e muove finalmente i valori modificati nei registri. Nel caso in cui l’istruzione in esecuzione sia un’istruzione di data processing, il risultato generato dalla ALU è scritto direttamente nel register file e la fase di esecuzione si completa in un solo ciclo. Se si tratta di un’istruzione di load o store, l’indirizzo di memoria calcolato dalla ALU è immesso sul bus degli indirizzi e l’accesso in memoria reale è effettuato durante il secondo ciclo della fase di esecuzione.

Il nuovo microcontrollore SAM7x256 di Atmel con architettura ARM.

Il nuovo microcontrollore SAM7x256 di Atmel con architettura ARM.

Registri  ARM

Il modello di programmazione di ARM7 consiste di, come gia detto, consiste di 16 registri; uno di questi è usato con funzioni di Program Counter (R15), in aggiunta anche R14 e R13 hanno funzioni speciali. R13 è di solito usato come Stack Pointer anche se questa e soltanto una convenzione di programmazione, più che un vincolo architetturale. In maniera abbastanza inusuale ARM non ha istruzione di POP e PUSH, ma fa uso, al momento della chiamata di funzione, di istruzioni che hanno il compito di fare copie complete dell’intero register file da e verso la memoria. R14 ha un uso abbastanza particolare ed è chiamato link register: quando si ha una chiamata a funzione l’indirizzo di ritorno viene conservato nel link register piuttosto che essere pushato sullo stack come di solito. è ovvio capire che ogni return di una funzione non è nient’altro che la  copia  di  R14(link  register)  verso R15(Program Counter). Questo accelera in maniera consistente la gestione delle chiamate a funzione singole senza parametri; nel caso di chiamate a funzioni innestate o con molti parametri si deve comunque ricorrere all’uso dello stack, nonostante ciò i moderni compilatori, attenti alle peculiarità tecniche di ARM, riescono a trarre grande vantaggio da questo. Oltre ai 16 registri principali è presente un registro di Flag che prende il nome di Current Program Status Register (CPSR), contenente nei 4 bit di maggior peso informazioni di stato sull’esecuzione dell’ultima istruzione e negli 8 di minor perso dei flag per cambiare lo stato operativo della macchina, disabilitare gli interrupt ed impostare la modalità THUMB.

Modalità operative

L’architettura ARM 7 ha un totale di 6 modalità operative, che dipendono dalle eccezioni e dagli interrupt che il sistema riceve; ogni modalità operativa condivide con le altre parte dei registri, ma alcuni registri sono peculiari del modo corrente, rendendo così più facile l’esecuzione di linee di processazione separate in funzioni degli eventi. Distinguiamo:

» USER  Mode: questa e; la modalità base che viene usata per far girare l’applicazione utente; quando ARM è in questa modalità il registro CPSR non può essere modificato e si può cambiare stato solo attraverso un’eccezione;

» FIQ (Fast Interrupt reQuest) Mode: supporto all’esecuzione di un interrupt da gestire senza il ricordo alla gestione di un Vectorized Interrupt Controller, di solito viene lasciato alla sorgente di interrupt più critica del sistema;

» IRQ (Interrupt reQuest) mode: tutte le altre sorgenti di interrupt nel sistema;

» Supervisor Mode: modalità di esecuzione protetta usata per gestire le trap del sistema operativo (software interrupt) e usata subito dopo il reset;

» Abort e Undefined mode: modalità di recovery da situazioni inattesi (istruzioni non riconosciute o accesso ad aree di memoria non valide).

I registri  da R0 a R7 sono comuni a tutte le modalità operative, ma nel caso di FIQ altri 8 registri autonomi sono presenti (R8-R14). Inoltre tutte le modalità operative hanno i loro R13 e R14 in modo che ognuna possa avere il suo Link Resister e Stack Pointer. Il  Program Counter, ovviamente, è uno per tutti, esistono però dei particolari registri di flag (SPSR) nel numero di uno per modalità operativa che vengono usati per avere uno stato dei flag privato. L’ingresso in uno degli Exception Mode, avviene alla ricezione di una delle eccezioni possibili (interrupt hw, interrupt sw, eventi imprevisti), l’accesso alla routine di gestione dell’eccezione avviene attraverso una tabella di vettori che contiene gli indirizzi di tutte le routines. La sequenza delle operazioni è sempre la stessa. Alla ricezione dell’evento il processore passa nella corrispondente modalità privilegiata, l’indirizzo contenuto nel Program Counter + 4 (32 bit) viene salvato nel Link Register  (R14), il contenuto del CPSR viene salvato nel SPSR corrispondente all’eccezione avvenuta. Gli interrupt sono diabilitati, nel caso fosse accettato un FIQ anche il FIQ è disabilitato. Alla fine nel Program Counter viene caricato con l’indirizzo corrispondente alla ISR e contenuto nella tabella dei vettori. Le prime istruzioni di ogni routine di gestione ovviamente saranno dedicate a salvare sullo stack i dati contenuti nei registri. Una volta che l’esecuzione è finita, il processore può ritornare a operare in user mode, dopo che la ruotine di gestione avrà ripristinato lo stato dei registri pullando i dati fuori dallo stack. L’ultimo passo e ripristinare lo stato precedente del Program Counter e del registro dei flag in modo che il flusso di processo interrotto possa riprendere.

Tipi di dato

L’architettura ARM 7 supporta 6 tipi di d to: 8 bit con segno e senza, 16 bit con segno e senza e, ovviamente, 32 bit con segno e senza. L’architettura ARM è stata disegnata per supportare questo tipo di dati sia in formato Little Endian che Big Endian (bi-endianess), anche se la maggior parte dell’implementazioni di ARM usa il Little Endian. Particolare attenzione va posta nella architettura ARM v4 ai dati multi byte e quindi anche a strutture e unioni, in quanto l’architettura ARM prevede l’accesso in memoria per le sue istruzioni da singolo ciclo operanti su word e long word in maniera corretta solo se i  dati sono allineati. Ciò significa che tutte le long word debbono essere posizionate in indirizzi multipli di 4 e le word in indirizzi multipli di 2. In ogni caso anche se l’accesso a strutture non allineate e sempre possibile usando accessi multipli allineati e operazioni di shift e mascheratura, può risultare complicato avere il controllo dell’allineamento usando un linguaggio d’alto livello compilato.

Flusso di programma

In tutti i processori esistono un gruppo di istruzioni la cui esecuzione è condizionata dallo stato interno dei flag del processore. Sono le cosiddette istruzioni di salto assoluto o con una condizione. Nell’architettura ARM tutte le istruzioni sono condizionali, nel senso che tutte le istruzioni ARM possiedono nella parte alte dell’opcode (i primi 4 bit) delle condizioni che debbono essere verificate perche l’istruzione sia veramente eseguita. Riflettendo su questa caratteristica delle istruzioni, ci si accorge come si possa pensare che questo sia uno dei punti di forza del successo di ARM. IN effetti l’uso delle istruzioni condizionali, fa sì che piccoli branch nel codice in posizioni distante nella memoria siano praticamente assenti. L’eliminazione dei mini branch, tipicamente molto frequenti nel codice compilato, rende meno probabili gli svuotamenti forzati della pipeline, e quindi migliora enormemente le performance. Come regola pratica quindi, se si dovesse scrivere direttamente codice in assembler, per piccoli salti di tre istruzioni o meno si dovrebbero usare solo le istruzioni condizionali, per salti grandi solo le vere istruzioni di salto.

 

 

 

3 Commenti

  1. Giovanni Di Maria Giovanni Di Maria 27 dicembre 2018
  2. Andrea Garrapa Andrea Garrapa 27 dicembre 2018
    • Stefano Lovati Stefano Lovati 28 dicembre 2018

Scrivi un commento

EOS-Academy