Capitolo 1.   Architettura di un sistema di elaborazione

Il termine architettura riferito ai sistemi di elaborazione indica l'organizzazione logica dei vari componenti interni della macchina ed il modo in cui essi cooperano per eseguire le operazioni richieste dagli utenti. Quindi l'architettura di un elaboratore può essere dedotta dalla conoscenza della sua struttura interna e dal modo in cui è possibile far cooperare i suoi componenti fisici mediante una serie di comandi o istruzioni (linguaggio macchina).

1.1   La macchina di Von Neumann

I moderni elaboratori elettronici, dai piccoli personal computer ai grandi maxi-computer, derivano in buona parte da uno stesso «modello» fondamentale di elaboratore chiamato Macchina di Von Neumann dal nome dello scienziato che nel 1946 pubblicò, insieme ad altri, un progetto per una nuova macchina di calcolo automatico.

Questa macchina è schematizzata in figura 1.1.

Figura 1.1.

figure/sist-vn

Le linee continue rappresentano il flusso di dati, le linee tratteggiate il flusso di controllo, dal quale si capisce che tutte le unità agiscono in base ai segnali inviati da un componente denominato appunto unità di controllo.

Le tre funzioni principali svolte dal sistema di elaborazione sono:

L'elaboratore è un sistema «automatico» in quanto tali funzioni vengono realizzate senza l'intervento diretto dell'uomo.

La cooperazione tra le unità di controllo, esecuzione e memoria permette di eseguire algoritmi opportunamente descritti secondo determinati linguaggi ed inseriti in memoria.

L'elaboratore è un sistema «versatile» in quanto può svolgere compiti molto diversi tra loro variando opportunamente gli algoritmi ad esso forniti.

Uno dei concetti fondamentali introdotti da Von Neumann e che costituì un passo avanti decisivo rispetto ai primi elaboratori dell'epoca, è quello di «programma memorizzato», cioè il fatto che il programma da eseguire (cioè la traduzione dell'algoritmo in una forma comprensibile alla macchina) viene immagazzinato in memoria al pari dei dati su cui esso opera.

L'elaborazione consiste nella esecuzione delle istruzioni del programma, da parte della unità di esecuzione sotto il governo della unità di controllo, una alla volta secondo l'ordine in cui sono contenute nella memoria, fino al completamento dell'intero processo previsto dall'algoritmo. L'uomo interviene solo per dare il comando di avvio dell'esecuzione e per introdurre eventuali dati di input.

Come detto il programma da eseguire deve essere scritto in precedenza in un apposito linguaggio (linguaggio di programmazione), poi tradotto in una forma direttamente eseguibile dalla macchina (linguaggio macchina) e quindi portato nella memoria dell'elaboratore.

Le tre operazioni possono essere così riassunte:

In queste dispense non vengono fornite ulteriori informazioni sui linguaggi di programmazione, eccetto per quelli a basso livello, come il linguaggio macchina o l'«assembly», trattati nel capitolo ##ling-macchina##.

1.2   Funzioni svolte dall'elaboratore

Vediamo più in dettaglio in cosa consistono le operazioni svolte da un elaboratore elettronico:

1.3   Componenti del sistema di elaborazione

Lo schema di Von Neumann introdotto in precedenza, anche se concettualmente ancora valido, deve essere «aggiornato» con quello della figura 1.2.

Figura 1.2.

figure/sist-vn-av

(sono indicate solo le linee di flusso dei dati e di controllo che entrano o escono dalla «Unità centrale»).

Nella figura si possono individuare:

1.3.1   CPU

La CPU (Central Processing Unit) costituisce il cuore dell'elaboratore e il luogo dove avviene l'esecuzione delle istruzioni di un certo programma; è costituita dalla unione della ALU e della unità di controllo CU (Control Unit) nello stesso circuito integrato.

Fisicamente si tratta di una piastrina di silicio contenente circuiti stampati costituiti da molte migliaia o milioni di semiconduttori che prende anche il nome di microprocessore. La CPU è dotata di un certo numero di celle di memoria «locale» (da non confondere con la memoria centrale) che servono a contenere i dati interessati alle operazioni da svolgere, queste celle di memoria si chiamano registri.

1.3.2   Bus e clock

La CPU deve essere collegata alle altre componenti del sistema di elaborazione alle quali invia segnali di controllo ed in particolare alla memoria centrale con la quale deve avvenire un continuo scambio di segnali binari corrispondenti ad indirizzi di memoria o al contenuto (dati o istruzioni) delle celle di memoria o dei registri. Questo comporta la necessità di collegamenti fisici che vengono chiamati bus.

Esistono tre tipi di bus:

Gli stessi collegamenti devono essere presenti anche all'interno della CPU per assicurare lo scambio di segnali tra le sue componenti interne; in questo caso si parla di bus (dati, indirizzi e di controllo) «interni».

Il motivo per cui si parla di «indirizzi» risiede nella struttura logica e fisica della memoria centrale dell'elaboratore (illustrata più in dettaglio in seguito): essa è costituita da una sequenza di celle o locazioni numerate progressivamente e quindi individuabili tramite il proprio numero d'ordine o indirizzo.

I bus possono essere indipendenti o condivisi; nel secondo caso vengono usate le stesse linee fisiche per trasportare segnali di natura diversa allo scopo di ottenere un risparmio di spazio e di costo, al prezzo di un certo deterioramento delle prestazioni,.

Solitamente ad essere condivisi sono il bus dati e il bus indirizzi e viene usato un opportuno segnale di controllo per «chiarire» la natura degli impulsi trasportati in un certo momento nella linea di comunicazione.

Affinché la CPU possa funzionare correttamente c'è anche l'esigenza di un dispositivo chiamato clock che è un generatore di impulsi di durata costante emessi uno dopo l'altro ad intervalli di tempo regolari; lo scopo di questi impulsi è di sincronizzare tutti i circuiti ed il loro funzionamento all'interno della CPU, in modo che essi funzionino tutti all'unisono.

In altre parole si può dire che gli impulsi generati dal clock innescano le azioni all'interno della CPU; a fronte di una entrata (di segnali) in un certo circuito, si ha la corrispondente uscita solo quando arriva anche un impulso dal clock; maggiore è la sua frequenza, maggiore è la velocità di funzionamento della CPU e quindi la quantità di lavoro da essa svolta in un certo tempo. La velocità del microprocessore (o meglio, del clock) si misura in cicli al secondo (frequenza degli impulsi) cioè in Hertz (Hz); le moderne CPU hanno frequenze di funzionamento dell'ordine dei miliardi di hertz o gigahertz (Ghz).

Nella figura 1.3 viene presentato un possibile schema di unità centrale di elaborazione comprendente i vari bus e il clock.

Figura 1.3.

figure/sist-uc

1.3.3   ALU

La ALU è una rete logica in grado di eseguire operazioni logiche e aritmetiche sui dati; l'insieme delle operazioni che la ALU può eseguire costituisce il livello di dettaglio in cui devono essere espresse le istruzioni di un qualunque algoritmo da far eseguire all'elaboratore.

Naturalmente tale livello di dettaglio non deve essere raggiunto direttamente dal programmatore che, come già accennato, scrive i suoi algoritmi in un linguaggio di programmazione e poi provvede alla loro traduzione in forma comprensibile alla macchina mediante la compilazione.

Le operazioni vengono svolte dai circuiti della ALU con l'ausilio di appositi registri e precisamente:

Tutte queste informazioni sono di tipo binario (si/no, 1/0) e occupano solo un bit ciascuna, quindi RS contiene una sequenza di bit ciascuno associato ad un tipo di informazione.

Un possibile schema della ALU è quello della figura 1.4:

Figura 1.4.

figure/sist-alu

Il registro AC è collegato al bus dati in quanto può contenere operandi dell'operazione da svolgere e risultati, rispettivamente provenienti e diretti verso altre posizioni di memoria (locale o centrale).

Il registro RS è collegato al bus dati in quanto il suo contenuto può essere richiesto dall'unità di controllo per essere esaminato dopo una certa operazione.

Le operazioni non previste dai circuiti, e quindi non eseguibili direttamente tramite l'hardware dell'elaboratore, devono essere programmate ed eseguite via software; ad esempio per fare il prodotto di due numeri, se non abbiamo un circuito che realizza la moltiplicazione, si deve programmare l'operazione come un ciclo di somme.

In molti casi ciò è realizzato mediante microprogrammi registrati su appositi circuiti di memoria; l'insieme dei microprogrammi prende il nome di firmware.

La memoria dove vengono registrati i microprogrammi è di tipo ROM (Read Only Memory) e prende il nome di memoria di controllo.

Le microistruzioni stanno ad un livello inferiore rispetto alle istruzioni macchina; queste ultime infatti vengono eseguite attivando l'apposito gruppo di microistruzioni (microprogramma).

1.3.4   CU

La CU è ancora una RETE LOGICA progettata per eseguire ciclicamente il seguente processo suddiviso in tre fasi:

  1. fase di FETCH: consiste nel prelevamento (lettura) di una istruzione dalla memoria centrale e nel suo trasferimento in un apposito registro della CPU, l'instruction register (IR) dove viene messa a disposizione per la successiva fase;

  2. fase di DECODE: consiste nell'individuazione, in base all'istruzione trasferita, della operazione da effettuare e su quali eventuali operandi; questa fase viene svolta da una unità di decodificazione a ciò adibita denominata decodificatore di istruzioni;

  3. fase di EXECUTE: in base alle segnalazioni della unità di decodifica, che ha interpretato l'istruzione nella fase precedente, l'unità di controllo vera e propria invia le «direttive» di esecuzione alla ALU che esegue l'operazione richiesta.

Questo ciclo si chiama ciclo istruzione e si compone di diversi cicli macchina con i quali vengono eseguite le varie fasi (fetch, decode, execute).

Un ciclo macchina (o passo elementare di esecuzione) è l'intervallo tra due impulsi consecutivi del clock.

Perché questo processo possa continuare ciclicamente è necessario che, al termine della esecuzione di una istruzione, l'unità di controllo sia in grado di determinare l'indirizzo della istruzione successiva (si ricordi, a questo proposito, che le istruzioni che compongono un programma in esecuzione sono memorizzate in posizioni adiacenti della memoria centrale).

A questo scopo viene utilizzato un registro della CPU, il program counter (PC), che contiene l'indirizzo della prossima istruzione da prelevare e viene aggiornato dopo la fase di decodifica aggiungendo al suo contenuto la lunghezza della istruzione corrente decodificata.

La CU può essere schematizzata come nella figura 1.5:

Figura 1.5.

figure/sist-cu

Il ciclo di esecuzione di un programma da parte della CPU può essere rappresentato con un diagramma di flusso come in figura 1.6:

Figura 1.6.

figure/sist-cicloistr

1.3.5   Memoria centrale

Prima di illustrare la memoria centrale del sistema di elaborazione vengono fornite alcune nozioni sulle memorie in generale.

1.3.5.1   Struttura logica delle memorie

Una memoria può essere rappresentata come un insieme di celle (o locazioni) che possono conservare porzioni elementari di informazione.

Nelle celle sono possibili due tipi di operazione: «lettura» di informazione o «scrittura» di informazione; in generale si parla di «accesso» alla memoria quando si compie una delle due operazioni.

Le memorie devono essere organizzate in modo da permettere la loro individuazione per l'effettuazione degli accessi; devono quindi avere un indirizzo univoco per ogni cella.

Le memorie si possono classificare in base a varie caratteristiche; una classificazione molto importante viene effettuata in base alla modalità di accesso:

1.3.5.2   Memoria centrale del sistema di elaborazione

La memoria centrale RAM (Random Access Memory) è una memoria ad accesso uniforme; anche essa è una rete logica i cui circuiti sono progettati per conservare informazione in codifica binaria.

La codifica binaria dell'informazione consiste nella rappresentazione di un simbolo alfanumerico mediante un gruppo di bit; la memoria allora viene organizzata in una sequenza di «gruppi di bit», o posizioni, o parole (word) ognuna delle quali è individuata da un indirizzo.

La grandezza della parola dipende dalla macchina ed è sempre un multiplo di 8 bit (1 byte); in certi casi la parola è 2 byte, in altri casi è 4 byte e talvolta si usano anche la mezza parola (half word) e la doppia parola (double word).

La capacità della memoria centrale è molto importante in quanto, come si è detto, tutti i programmi che devono essere eseguiti devono esservi memorizzati; la grandezza della memoria è quindi un indice di potenza dell'elaboratore. L'unità di misura della memoria è il byte con i suoi multipli: Kappabyte (1 KB=1.024 byte), Megabyte (1 MB=1.048.576 byte), Gigabyte (1 GB= 1.073.741.824 byte), Terabyte (1 TB= 1.099.511.627.776 byte).

Per quanto riguarda i circuiti per l'accesso alla memoria centrale si hanno:

Il tutto si può schematizzare come in figura 1.7:

Figura 1.7.

figure/sist-mem

1.3.5.3   Ordinamento big endian e little endian dei dati in memoria

Nel caso di posizioni di memoria costituite da più byte (ad esempio di 16 bit) l'ordine con cui i diversi byte di una stessa posizione sono memorizzati dipende dall'architettura del computer.

I due ordinamenti più diffusi sono:

Da quanto detto emerge che nel caso di big endian il byte più significativo (MSB Most Significant Byte) ha l'indirizzo di memoria più piccolo, mentre nel caso di little endian è il byte meno significativo (LSB Least Significant Byte) ad avere l'indirizzo più piccolo.

Ad esempio se si deve memorizzare il dato 'AB' a partire dall'indirizzo 100, avremo, nel caso di big endian:

indirizzo 100: A
indirizzo 101: B

invece, nel caso di little endian:

indirizzo 100: B
indirizzo 101: A

I termini big endian e little endian derivano dai Lillipuziani dei "Viaggi di Gulliver", il cui problema principale era se le uova debbano essere aperte dal lato grande (big endian) o da quello piccolo (little endian); il significato di questa analogia è ovvio: nessuno dei due metodi è migliore dell'altro.

Esiste comunque un problema di compatibilità noto come NUXI problem dovuto al fatto che i processori Intel usano il metodo little endian e quelli Motorola il metodo big endian, si dice anche che hanno endianess diverse.

Il termine NUXI deriva dall'aspetto che avrebbe la parola UNIX se memorizzata in due posizioni consecutive di due byte in little endian.

1.3.5.4   Ciclo di memoria

Si chiama ciclo di memoria la sequenza di azioni che il sistema compie per leggere o scrivere un dato in memoria.

Ipotizzando che il metodo di ordinamento dei dati in memoria sia il big endian, abbiamo, nel caso della lettura:

  1. L'indirizzo del dato viene posto nel MAR.

  2. Il decodificatore di indirizzi accede alla posizione di memoria indirizzata.

  3. Se viene letta una parola, il byte indirizzato dal MAR viene posto nella metà più significativa del MBR e il byte successivo viene posto nella metà meno significativa.

  4. Se viene letto un byte viene posto nella metà meno significativa del MBR e l'altra metà viene riempita con copie del bit più significativo presente nel byte (meccanismo di estensione del segno).

Nel caso della scrittura:

  1. L'indirizzo della cella di memoria di destinazione viene posto nel MAR.

  2. Il dato da memorizzare viene collocato nel MBR.

  3. Se viene scritta una parola, il byte più significativo del MBR viene trasferito nella cella indirizzata dal MAR e il byte meno significativo viene posto nella cella successiva.

  4. Se viene scritto un byte, la metà meno significativa del MBR viene trasferita nella cella di memoria indirizzata dal MAR.

1.3.5.5   Struttura fisica della memoria centrale

La memoria centrale viene realizzata con materiale semiconduttore; ogni unità elementare di informazione o bit è di solito un multivibratore bistabile (o flip-flop), cioè un circuito che può assumere uno di due diversi stati possibili in modo stabile finché un certo impulso non lo fa passare nell'altro stato.

La lettura e la scrittura in memoria consistono nel rilevare lo stato del flip-flop e nell'inviargli impulsi per cambiarlo. Tali operazioni avvengono con la stessa velocità per tutti i circuiti della memoria ed in maniera indipendente dalla loro posizione; quindi la memoria centrale è una memoria ad accesso «casuale» (random) o «uniforme».

Le tecnologie con cui vengono realizzati i circuiti di memoria sono però due e quella basata sui flip-flop non è, come vedremo, la più utilizzata:

La RAM statica è più veloce ma anche molto più costosa; per questo motivo la memoria centrale di un computer è realizzata con RAM dinamica mentre la RAM statica viene utilizzata per la memoria cache.

1.3.5.6   Memoria cache

La cache è una memoria più piccola della memoria centrale ma anche più veloce.

Nei moderni personal troviamo almeno due memorie cache: quella di primo livello (L1) grande alcuni KB, inglobata all'interno della CPU e veloce quanto la CPU e quella di secondo livello, grande qualche MB, situata esternamente alla CPU, meno veloce ma comunque più veloce della memoria centrale.

Il loro ruolo è quello di interporsi tra CPU e RAM allo scopo di immagazzinare dati e istruzioni che si ritiene possano servire alla CPU per le operazioni immediatamente successive, onde evitare che debbano essere letti nella più lenta memoria centrale.

Per questo la CPU cerca dati e istruzioni prima nella memoria cache L1 e poi nella L2 e solo in caso di insuccesso accede alla memoria centrale; inoltre quando una cella viene letta dalla RAM, il suo contenuto viene portato, oltre che alla CPU, anche nelle memorie cache, insieme a quello delle celle limitrofe.

Prima di proseguire nell'esame dei principi di funzionamento della cache presente nell'unità centrale, soffermiamoci brevemente sul concetto più generale di «cache» che incontriamo anche in altri ambiti informatici.

In generale una cache è una memoria tampone che si colloca (logicamente) fra due entità informatiche fra cui avviene uno scambio di dati e che sono notevolmente diverse dal punto di vista della velocità; il suo ruolo è quello di sopperire alla lentezza dell'entità meno veloce ospitando parte dei dati che da questa devono essere trasferiti all'entità più veloce riducendone quindi i tempi di attesa.

Vediamo un paio di esempi in ambiti diversi da quello dell'unità centrale:

Tornando alla cache dell'unità centrale notiamo che la sua utilità è giustificata dalla validità, verificata sperimentalmente, dei seguenti due principi:

La presenza della memoria cache permette di velocizzare gli accessi in lettura alla RAM; non c'è invece alcun miglioramento per gli accessi in scrittura.

A tale proposito ci sono due metodologie di gestione della cache:

1.3.5.7   Memorie ROM

Sia le memorie SRAM che le DRAM sono «volatili» cioè perdono il loro contenuto se viene a mancare l'alimentazione elettrica.

Esistono anche memorie non volatili come le ROM citate in precedenza; più in dettaglio abbiamo: