STRUTTURA DEI
CALCOLATORI
1 Strutture di interconnessione
1.1 Struttura a singolo bus
1.1.1
1.1.2
1.1.3
1.1.4
1.1.5
1.1.6
Passaggio di controllo del bus
Struttura interna del bus
Lettura e scrittura in memoria ed unità periferiche
Memory mapped I/O
Evoluzione dei bus
Tipi di bus
2 Struttura dei processori
2.1 Il ciclo di istruzione
2.1.1
2.1.2
2.1.3
2.1.4
Diagramma di stato dell’interpretazione di una istruzione
Struttura generale dei processori
Fase fetch
Fasi execute
2.2 Temporizzazione
2.3 Unità di controllo “cablata”
2.3.1 Il clock, il contatore tempi e la rete combinatoria
2.3.2 Funzioni booleane della rete combinatoria della fase fetch
2.4 Unità di controllo microprogrammata
2.4.1
2.4.2
2.4.3
2.4.4
2.4.5
La temporizzazione nelle unità di controllo microprogrammate
Il formato di microistruzione
Decodifica del codice operativo
Diagramma a blocchi dell’unità di controllo microprogrammata
Unità aritmetica e logica
1 Strutture di interconnessione
La struttura del modello di von Neumann si
compone di
a) un processore
b) una memoria
c) un canale di comunicazione (bus)
Per comunicare con il mondo esterno,
il modello di von Neumann deve essere
dotato di un ulteriore canale di
comunicazione: il bus di input/output
Struttura con canale di comunicazione
diretto memoria – unità periferiche
(Direct Memory Access)
1.1 Struttura a singolo bus
Una soluzione più elastica consiste nel collegare tutti i componenti, per esempio i
processori, le memorie e le unità di I/O, ad uno switch centrale, che regola ed
arbitra tutte le comunicazioni.
Una struttura molto più semplice, che conserva le caratteristiche di generalità e
flessibilità dello switch centrale, con la limitazione di permettere soltanto una
comunicazione alla volta, è la struttura a singolo bus.
Il bus è condiviso fra tutte le unità
del sistema. La comunicazione può
avvenire fra due qualsiasi unità,
non soltanto con il processore.
Inoltre, una sola unità alla volta
può trasmettere, mentre più di
una unità possono ricevere.
Il bus deve essere dotato di un
insieme di linee di controllo
sufficientemente generale, che
Struttura a singolo bus
tenga conto della diversa natura
delle unità componenti il sistema.
L’unità che detiene il controllo del bus viene denominata master, tutte le altre slave.
1.1.1 Passaggio di controllo del bus
I segnali per il passaggio del controllo del bus sono, come la maggior parte dei segnali
di controllo, in logica negativa, cioè allo “0” logico è associato il livello di tensione più
alto (es. 5 volt) ed all’”1” logico il livello di tensione più basso (es. 0 volt).
La richiesta del bus, Bus Request, è inviata dall’aspirante master portando questo
segnale da livello alto a livello basso. Il processore risponde, dopo aver portato in alta
impedenza le sue linee di bus in uscita, asserendo (cioè ponendo a livello basso) la
linea di concessione del bus,
Bus Grant. Quando l’unità riceve
questo segnale può diventare master
e, contemporaneamente, invia un
segnale di riconoscimento,
Bus Grant Acknowledgement, che gli
è stato accordato il bus.
Al completamento della sua
operazione, riporterà a livello alto
(cioè negherà) il segnale di
riconoscimento. Tale passaggio,
da basso ad alto del segnale di
Segnali di sincronizzazione richiesti per il
riconoscimento, viene utilizzato dal
passaggio del controllo del bus dal processore
processore come segnale che può
ad un’altra unità del sistema.
riprendere il controllo del bus.
Nel caso più generale, più unità possono essere nella condizione di voler ottenere il
controllo del bus. Le linee di controllo non possono più essere dirette ma debbono
essere comuni a tutte le unità. Inoltre, in caso di richieste simultanee, è necessario
un meccanismo di arbitraggio che risolva il conflitto.
La figura mostra una semplice evoluzione del caso precedentemente presentato,
con le linee Bus Request e Bus Grant Acknowledgement in comune fra tutte le
unità, mentre la linea Bus Grant è utilizzata con modalità daisy-chain. Anche questa
è da considerare una linea comune, ma essa passa attraverso le varie unità per
risolvere i conflitti secondo una
priorità determinata dalla
posizione fisica delle stesse sulla
linea di Bus Grant rispetto al
processore . Se un’unità riceve un
segnale di Bus Grant, ed ha fatto
una Bus Request, essa la utilizza
per prendere il controllo del bus,
altrimenti si limita a propagare
il segnale di Bus Grant.
I meccanismi di arbitraggio possono essere abbastanza più complessi per tener
conto, ad es., di priorità non fisse. Inoltre essi possono essere centralizzati, cioè
incorporati nel processore o demandati ad una apposita unità esterna, oppure
distribuiti fra le varie unità componenti il sistema.
1.1.2 Struttura interna del bus
Il Bus di indirizzi è usato per selezionare
l’unità con la quale deve essere stabilita
la comunicazione. E’ unidirezionale, è
prodotto in uscita dall’unità di calcolo
degli indirizzi interna al master, e va in
input alle unità slave per poterle
selezionare. La larghezza del Bus di
indirizzi fissa la dimensione dello
Componenti di un bus
spazio di indirizzi, cioè il numero delle
celle di memoria e dei registri delle unità di I/O selezionabili.
Il Bus di dati è bidirezionale.
Le Linee di controllo in input al master si riferiscono
a segnali con cui le altre unità del sistema gli
comunicano il verificarsi di particolari condizioni o
eventi, sui quali deve essere sincronizzata
l’elaborazione futura. Le Linee di controllo in output
corrispondono a segnali o comandi che il master
invia alle altre unità per evocarne l’operazione.
Associata ad ogni unità slave esiste una
decodifica degli indirizzi.
Vettore di n bit
2n uscite tutte uguali
a “0” logico eccetto
quella la cui posizione
corrisponde al valore
del dato in ingresso
1.1.3 Lettura e scrittura su una unità di I/O o in memoria
Per poter leggere o scrivere un dato su una unità di I/O o in memoria, molti processori
usano i segnali Read e Write, accompagnati da altri due segnali: Memory Request, se
l’operazione è in memoria centrale, Input Output Request se invece è con unità
periferica.
Linee di bus per la lettura e scrittura in memoria
e nelle unità periferiche
Il segnale di richiesta di memoria, Memory Request, viene usato per selezionare la
memoria in blocco, ma la memoria è di solito implementata come un insieme di
moduli o banchi. Il segnale viene usato per abilitare un decodificatore (input di
Enable). A questo decodificatore vengono inoltre mandati i bit di ordine alto del bus
di indirizzi, per selezionare
uno dei banchi di memoria.
Gli altri bit dell’indirizzo
vengono inviati a tutti i
banchi.
Le uscite del decodificatore
vanno singolarmente agli
input Chip Select di
selezione dei moduli di
memoria, in modo da
selezionare uno ed uno
solo di questi.
Le linee di indirizzo
inviate ad ogni modulo
di memoria verranno
decodificate, a loro volta,
Se ci sono più banchi di memoria
dalla logica di decodifica
che fa parte di ogni modulo.
1.1.4 Memory mapped I/O
Le unità di I/O e la memoria possono suddividersi lo spazio di indirizzi fissato dal bus
di indirizzi. In tal caso, non c’è più bisogno di ulteriori linee, come Memory Request e
Input Output Request, perché è l’indirizzo stesso che viene utilizzato per distinguere
se si tratta di un’operazione di I/O o di memoria.
Memory mapped I/O.
Lo spazio di indirizzi è stato suddiviso in due 2 parti uguali:
la parte superiore (An-1 = 1) è assegnata alle unità periferiche,
mentre la metà inferiore (An-1 = 0) alla memoria centrale
Memory mapped I/O con spazio di indirizzi suddiviso in 16 parti.
Di queste, si può decidere di assegnarne un certo numero
alla memoria e le parti restanti all’I/O.
1.1.5 Evoluzione dei bus
I primi PC usavano la soluzione più semplice. Un
solo insieme di fili percorreva l’intera mainboard. La
CPU, la memoria e tutti gli altri dispositivi di I/O
erano connessi a questi fili, cioè al singolo bus.
I moderni computer combinano tutte le funzioni di
tutti I devices in due chip. Il chip Northbridge
connette alla CPU la memoria (front side bus (FSB)
e il video AGP. Il Northbridge è quindi connesso ad
un chip Southbridge che supporta la keyboard, il
mouse, il floppy, l’hard disk, il CD, la LAN, l’USB, il
FireWire e il PCI. Questi due chip stanno nel
mezzo di quella che può essere considerata una
configurazione a “stella” o ad “hub”. I devices si
connettono o al North o al Southbridge ed i chip
forniscono la funzione di interconnessione o
switching.
Quando tutti i devices erano connessi ad un
singolo insieme di fili (singolo bus), c’era soltanto
una velocità di clock che si applicava alla CPU, alla
memoria ed a tutti I devices di I/O. Ora, invece,
poichè ciascun bus è separato, ciascuno può avere
il suo proprio clock.
La stessa
velocità
Bus di I/O
Bus multipli
FireWare
Un tipico sistema Pentium II
SCSI (Small Computer System Interface) era molto diffusa in passato in ogni
tipologia di computer, mentre attualmente trova un vasto impiego solamente in
workstation, server e periferiche di fascia alta (cioè con elevate prestazioni). I
computer desktop e portatili sono invece di solito equipaggiati con l'
interfaccia
ATA/IDE (Advanced Technology Attachment e Integrated Drive Electronics),
rinominato PATA per distinguerlo da SATA (Serial Advanced Technology
Attachment), per gli hard disk, e con l'
interfaccia USB (Universal Serial Bus) per
altre periferiche di uso comune. Queste ultime interfacce sono più lente della SCSI,
ma anche più economiche. Notare che l'
USB utilizza lo stesso set di comandi dello
SCSI per implementare alcune delle sue funzionalità.
PCI (Peripheral Component Interconnect) è l'
interfaccia sviluppata da Intel intorno
agli anni Novanta per collegare al computer le più svariate periferiche. La larghezza
di banda dell'
interfaccia PCI è rimasta negli anni ancorata a 133 MBytes/s,
generata da una trasmissione dati con frequenza pari a 33MHz a 32bit. Sebbene
l'
interfaccia PCI abbia fatto segnare un notevole passo avanti nell'
evoluzione dei
pc, sia per il costo contenuto sia per le buone (e inizialmente sufficienti) prestazioni
che ne hanno decretato la diffusione di massa rimpiazzando ISA (Industry Standard
Architecture) (o Bus AT), i primi limiti si sono fatti sentire poco dopo in sistemi come
server e workstation, dove vi è bisogno di un enorme larghezza di banda per la
trasmissione dei dati. Fu così che si iniziò a cercare e progettare sostituti per
questa interfaccia: i più fortunati sono stati il PCI a 66MHz, il PCI X (a 3.3v)ed ora il
PCI Express.
1.1.6 Tipi di bus
Bus Sincrono: Include un clock nelle linee di controllo
Un protocollo fisso per la comunicazione che è relativo al clock
Vantaggio: richiede pochissima logica e può essere molto veloce
Svantaggio: Ogni dispositivo sul bus deve andare alla stessa velocità di clock
Bus Asincrono: Non usa un clock
Può servire una grande varietà di dispositivi
Richiede un protocollo di handshaking
Bus Memoria-Processore (specifico del progetto): Corto e ad alta velocità
Ha bisogno solo di accordarsi con il sistema di memoria
Massimizza la banda memoria-processore
Connette direttamente al processore
Ottimizzato per trasferimenti di blocchi di cache
Bus di I/O (standard industriali): Usualmente è lungo e più lento
Ha bisogno di accordarsi con una grande varietà di dispositivi di I/O
Connette al bus Memoria-Processore o al bus di Backplane
Bus di Backplane (standard o proprietari): Una struttura
di interconnessione all’interno del telaio
Permette ai processori, ai dispositivi di memoria
e di I/O di coesistere.
Vantaggio di costo: un bus per tutti i componenti.
2 Struttura dei processori
La struttura interna di un processore deve fornire le funzionalità richieste dal
livello di architettura di calcolatore, e cioè l’elaborazione dei dati, degli indirizzi e
delle istruzioni.
Si può considerare il processore come un interprete di istruzioni che, per ogni
istruzione, effettui delle sequenze di cambiamenti di stato che portino dallo stato
iniziale allo stato finale definiti per quella istruzione. La situazione è analoga a
quella dei livelli superiori, dove un programma specifica, tramite le istruzioni che lo
compongono, una sequenza di cambiamenti di stato che portano da uno stato
iniziale ai risultati finali della risoluzione di un problema. Il problema risolto dal
programma dei livelli superiori è ora sostituito dall’istruzione di macchina che
verrà “risolta” dal processore. Per ogni istruzione, dovrà essere specificata la
sequenza di operazioni elementari che determinano i cambiamenti di stato
richiesti sulla struttura fisica del calcolatore. Tali operazioni elementari sono in
diretta corrispondenza con le unità fisiche componenti il calcolatore.
L’interpretazione di ogni istruzione da parte del processore avviene attraverso un
insieme di fasi che compongono quello che viene chiamato il ciclo di istruzione.
2.1 Il ciclo di istruzione
Il ciclo di istruzione si compone delle seguenti fasi:
1)
2)
3)
4)
5)
6)
7)
8)
estrazione dell’istruzione dalla memoria;
calcolo dell’indirizzo della prossima istruzione tramite l’avanzamento del PC;
decodifica del codice operativo;
calcolo dell’indirizzo dell’eventuale operando;
estrazione dell’operando dalla memoria;
esecuzione;
calcolo dell’indirizzo del risultato;
immagazzinamento del risultato in memoria.
Alcune di queste fasi corrispondono ad operazioni in memoria, altre ad
operazioni del processore.
2.1.1 Diagramma di stato dell’interpretazione di una istruzione
Gli stati controllati dal processore sono a
sinistra, quelli controllati dalla memoria
a destra. Se non vi sono vincoli di
sequenzialità, fasi di tipo diverso
possono sovrapporsi nel tempo.
Alcune delle fasi possono essere
assenti in determinate istruzioni,
o possono essere eseguite
ripetutamente in altre.
La sequenza è ripetutamente
eseguita per tutte le istruzioni di
un programma: essa assume il
nome di ciclo di istruzione.
Occasionalmente si può ritornare
all’interno del ciclo, come accade nella
elaborazione di stringhe.
All’interno del ciclo di istruzione, si usa
fare una suddivisione in fase fetch,
comprendente le fasi (1), (2) e (3), che è la
stessa per ogni istruzione eseguita, e in fase
execute, specifica per ogni tipo d’istruzione.
2.1.2 Struttura generale dei processori
Le unità costituenti un generico
processore sono:
- unità di bus: ha il compito di stabilire
la comunicazione con le unità esterne;
- unità di istruzione: estrae e decodifica
le successive istruzioni del programma
in esecuzione. Il risultato della
decodifica servirà a selezionare la
particolare fase execute corrispondente
al codice operativo dell’istruzione estratta;
MAR
MBR
PC
IR
- unità aritmetica e logica: esegue le
operazioni di elaborazione dati
specificate durante la fase execute
dell’istruzione in corso di interpretazione;
- unità di indirizzo: esegue il calcolo
dell’indirizzo;
- unità di controllo o di governo: riceve gli input dal decodificatore d’istruzione e
genera l’insieme di controlli e di temporizzazioni necessarie all’espletamento della
corrispondente fase execute. L’unità di controllo ha anche il compito di generare la
temporizzazione per la fase fetch e per la gestione delle eccezioni.
2.1.3 Fase fetch
Ogni ciclo di istruzione comincia con l’invio,
sul bus di indirizzi, dell’indirizzo dell’istruzione
da estrarre. Tale indirizzo è contenuto nel PC,
MAR
che è uno dei registri di indirizzo che fanno
parte dell’unità di indirizzi.
L’indirizzo impostato dal PC sul bus di
MBR
indirizzi interno viene “latched” in un registro
di indirizzi, spesso denominato MAR
(Memory Address Register), posto
IR
PC
nell’unità di bus (MAR := PC).
Un’operazione sul bus esterno richiede,
infatti, che l’indirizzo sul bus di indirizzi
sia impostato per un tempo piuttosto lungo
per permettere alle unità esterne,
collegate al bus, di decodificare e, quindi,
riconoscere l’indirizzo.
Solo dopo che è passato questo tempo,
l’unità esterna selezionata potrà impostare o prelevare dal bus dati l’informazione.
Nel caso in questione, l’informazione è l’istruzione che il processore richiede (RD)
ad una unità di memoria. Nel tempo che l’unità di memoria impiega ad inviare
l’istruzione al processore, quest’ultimo può fare altre operazioni (parallelismo fra
processore e memoria). Tale parallelismo è reso possibile dalla presenza, già
menzionata, di un registro buffer quale è il MAR.
Una tipica operazione che può essere
anticipata è l’avanzamento del PC
(PC := PC + 1), in modo che punti alla
prossima istruzione, o alla successiva
parola dell’attuale istruzione, in dipendenza
dal formato d’istruzione.
Per lo stesso motivo, alla fine della fase
fetch, è presente sul bus di dati o l’intera
istruzione o la sua prima parola. In tutti e
due i casi il codice operativo è presente sul
bus di dati e conviene catturarlo nel registro
IR (Instruction Register) dell’unità di
istruzione (IR := MBR). In questo modo, si
libera il bus di dati interno per ulteriori cicli
di bus. Il bus di dati esterno aveva già
provveduto a liberarlo l’unità di bus,
memorizzando l’informazione ivi presente
nel suo registro buffer di dati, generalmente
chiamato MBR (Memory Buffer Register).
Una volta che il codice operativo è nell’IR,
la prossima fase da compiere è quella di
decodifica.
MAR
MBR
PC
IR
2.1.4 Fasi execute
Mentre la fase fetch è condivisa da tutte
le istruzioni, esistono tante fasi execute
quanti sono i codici operativi. Ognuna di
esse rimanda ad un differente interprete.
Per ognuna di esse si tratta di stabilire,
analogamente alla fase fetch,
le operazioni elementari richieste per
eseguire la corrispondente
interpretazione.
Le differenti fasi execute sono
selezionate dal processo di decodifica
del codice operativo.
Sia la fase fetch che le fasi execute
debbono specificare i trasferimenti
fra registri coinvolti, la serie dei comandi
da inviare alle unità interessate e la loro
temporizzazione, cioè la loro durata e
il tempo di inizio.
MAR
MBR
PC
IR
2.2 Temporizzazione
Temporizzazione è la sequenza di comandi da inviare alle varie unità che
concorrono all’espletamento della fase fetch e delle fasi execute.Una volta
individuate le operazioni da compiere per una singola fase, queste vanno tradotte
nelle sequenze di comandi o segnali corrispondenti.
Per la fase fetch, per es., erano state individuate le seguenti operazioni, alcune da
effettuare in sequenza (rappresentate su linee differenti) altre in parallelo
(rappresentate sulla stessa linea, separate da un “;”):
0:
1:
2:
MAR := PC; RD
PC := PC + 1; RD
IR := MBR
Se si conviene che le operazioni su ogni linea abbiano tutte la stessa durata, si
comprende la ragione della ripetizione dell’operazione RD su due linee: si ottiene,
così, di far durare l’operazione di lettura il doppio (se necessario, il triplo o il
quadruplo, ripetendola su più linee) delle altre operazioni.
L’operazione MAR := PC è una tipica operazione
di trasferimento fra registri. Essa è realizzata inviando
un segnale di abilitazione di durata opportuna
all’input Enable del registro di destinazione.
Si suppone di usare logica positiva anche per i segnali di controllo
PC
EN
MAR
Se i registri sorgente dovessero essere
più di uno, si può adoperare a monte del
registro di destinazione un selettore a due
o più vie, in cui l’input Indirizzo sceglie la
direzione di provenienza.
Se l’indirizzo per la provenienza dal PC è “0”,
la temporizzazione per la fase fetch potrebbe
essere quella riportata in figura.
E’ bene cercare di avere segnali
di durata multipla l’uno dell’altro
(come nel caso del segnale di lettura
in memoria la cui durata è un multiplo
di quella del segnale di abilitazione
ai registri). Inoltre, se è possibile,
è meglio usare dei livelli (come nel
caso dell’indirizzo ai selettori),
o riusare dei segnali (come nel caso
dell’incremento del PC che utilizza
lo stesso segnale di EN (MBR)).
La temporizzazione delle fasi
execute è realizzata allo
stesso modo.
MREQ, RD
EN (MAR)
Indirizzo (S) = 0
EN (MBR)
EN (IR)
Incrementa (PC)
Indirizzo
EN
S
MAR
2.3 Unità di controllo “cablata”
Se le istruzioni del livello di macchina sono direttamente interpretate in hardware da
circuiti che hanno il compito di generare la temporizzazione corrispondente alla
fase fetch ed alla fase execute di ogni istruzione, l’unità di controllo è definita come
“cablata”, cioè consistente di reti combinatorie e circuiti sequenziali.
Questo approccio è stato universalmente adottato dai calcolatori delle prime
generazioni, dalle architetture ad alte prestazioni ed, attualmente, da molte
architetture che seguono il cosiddetto modello RISC – Reduced Instruction Set
Computer. A queste si contrappongono le architetture CISC – Complex Instruction
Set Computer – che, per avere istruzioni e metodi di indirizzamento più complessi,
beneficiano, almeno in parte, dei vantaggi della microprogrammazione.
La funzione di un’unità di controllo cablata è quella di produrre temporizzazioni
come quella vista per la fase fetch.
Un metodo per ottenere ciò, è quello di usare gli output degli stadi di un contatore
degli impulsi del clock del processore come input ad un circuito combinatorio.
2.3.1 Il clock, il contatore tempi e la rete combinatoria
Il clock emette un treno di impulsi a frequenza costante molto elevata. Se questi
impulsi entrano nell’input Avanzamento di un contatore, si produrranno alle sue
uscite altri treni di impulsi di frequenza metà, un quarto, ecc., corrispondentemente di
larghezza doppia, quadrupla, ecc., in ordine crescente di stadi del contatore stesso.
Questo è chiaramente illustrato dalla tavola della verità del contatore.
La varietà di impulsi così ottenuta è utilizzata dalla rete combinatoria per produrre la
successione di comandi relativi alla fase fetch o alla fase execute selezionata dalle
linee provenienti dal decodificatore di istruzioni.
La rete combinatoria è una rete multifunzionale, cioè ha molte uscite, ognuna
corrispondente ad una particolare funzione booleana degli ingressi.
2.3.2 Funzioni booleane della rete combinatoria per la fase fetch
In questa figura, sono state ricavate le funzioni booleane relative alla temporizzazione
della fase fetch. Si noti l’accorgimento di utilizzare durate di impulsi uguali o multiple di
semiperiodi dei treni ad onde quadre in uscita dal contatore tempi.
Una volta ottenuta la tavola della verità della rete logica complessiva corispondente
all’intera temporizzazione, essa viene realizzata di solito usando dispositivi logici
strutturati general purpose, quali i PLA – Programmable Logic Array, o le ROM – Read
Only Memory.
2.4 Unità di controllo microprogrammata
Al di là del fatto di esprimere sinteticamente ed elegantemente la sequenza di
operazioni necessarie all’espletamento della fase fetch, la sequenza:
0:
1:
2:
MAR := PC; RD
PC := PC + 1; RD
IR := MBR
ha tutte le caratteristiche di un programma e, se esistesse una macchina in grado di
interpretarlo, ecco che l’insieme dei due ci fornirebbe l’unità di controllo per
l’architettura di calcolatore. Analogamente alla fase fetch, anche le fasi execute, se
scritte come sequenze di istruzioni a livello più basso, potrebbero essere
interpretate da tale macchina.
Ma una macchina siffatta altro non è se non il modello di von Neumann applicato
ad un’altra architettura, sebbene di livello inferiore. Una tale architettura ha lo
stesso tipo di unità funzionali dell’architettura di livello superiore, ed infatti ne
conserva i nomi, con l’aggiunta del prefisso micro.
I microprogrammi che costituiscono un interprete sono ottenuti tramite traduzione
da un linguaggio simbolico del tipo su presentato e debbono essere memorizzati in
una memoria di controllo o di microprogrammazione. Per non degradare le
prestazioni, è necessario che tale memoria sia almeno n volte più veloce della
memoria centrale se n è la somma del numero di microistruzioni della fase fetch e
del numero medio di microistruzioni delle fasi execute. Infatti, le unità di controllo
microprogrammate cominciarono ad essere realizzate solo quando la tecnologia dei
circuiti integrati permise di produrre memorie sufficientemente veloci.
2.4.1 La temporizzazione nelle unità di controllo
microprogrammate
Il problema della temporizzazione di ogni istruzione viene scomposto, con la
microprogrammazione, in sottoproblemi di temporizzazione più elementari. Il ciclo
stesso di microistruzione, coincidente con il ciclo della memoria di controllo, è un
modo semplice e sistematico di introdurre una temporizzazione. In ogni ciclo
possono essere eseguite in parallelo diverse microoperazioni o microordini.
Se questo semplice meccanismo non si dovesse rivelare sufficiente, si può
ricorrere anche a realizzare una temporizzazione interna al ciclo di microistruzione.
Questa consiste nel suddividere il ciclo di microistruzione in due o più sottocicli
identici e nell’abilitare l’esecuzione di alcuni microordini soltanto nel 1° sottociclo, di
altri nel 2° sottociclo, e così via. Se esiste un solo ciclo non suddiviso, si parla di
controllo monofase, altrimenti si usa il termine di controllo polifase.
Per es., come è noto, l’immagazzinamento del risultato di una operazione della
ALU può essere fatto solo dopo aver selezionato gli operandi al suo ingresso. In
una organizzazione bifase, la selezione dei due operandi (dal file di registri
generali, dal bus interno, ecc.) verrebbe abilitata nel 1° sottociclo, mentre
l’immagazzinamento del risultato, con un eventuale shift, verrebbe abilitato nel 2°
sottociclo.
La microarchitettura ha una visibilità delle risorse hardware maggiore di quella
dell’architettura di calcolatore. Per questa ragione, ed anche per poter controllare in
parallelo più risorse, il formato di microistruzione è completamente diverso da
quello di istruzione.
2.4.2 Il formato di microistruzione
A differenza delle istruzioni di macchina, le microistruzioni esibiscono un gran
numero di campi, ognuno controllante una diversa unità.
Alcuni campi sono relativi a comandi. Per es., i campi RD e WR sono campi lunghi
1 bit che, se posti uguali ad “1”, inviano sulle rispettive linee di controllo un comando
di Read o di Write.
Altri campi sono dei codici di funzione, come il campo ALU che rappresenta quale
operazione è richiesta alla unità aritmetica e logica.
Altri campi possono rappresentare degli indirizzi. Per es., un campo può essere il
numero di registro, in un file di registri generali, su cui si intende operare.
Dato che la lunghezza di microistruzione può essere molto grande, si tende a
codificare in un unico campo informazioni espresse in più campi. Per es., se il
risultato di un’operazione può essere memorizzato in 8 registri diversi, si possono
impiegare 8 campi di 1 bit l’uno, oppure un campo di 3 bit. Col primo metodo si può,
in linea di principio, memorizzare il risultato anche in tutti gli 8 registri
contemporaneamente, col secondo, invece, si può memorizzarlo solo in uno degli 8.
La codifica di un campo è un metodo molto utile anche quando due o più campi
risultano avere configurazioni reciprocamente incompatibili. Per es., l’abilitazione di
una dato sul bus di dati da tre diverse sorgenti non può essere data, come è stato
già detto, contemporaneamente. Un modo molto semplice di risolvere il problema di
evitare di incorrere in errori di microprogrammazione in questo caso, è di usare un
campo codificato di 2 bit che, con le sue 4 configurazioni distinte, permette di
selezionare in modo esclusivo una ed una sola delle tre sorgenti, o nessuna di esse.
Una microistruzione con campi
decodificati, in cui ogni bit controlla
direttamente un input ad una unità
di calcolatore, è spesso detta di tipo
orizzontale, mentre una con campi
codificati è di tipo.verticale.
Quest’ultima realizza un notevole
risparmio di memoria di controllo,
ma a spese di una maggiore lentezza, dovuta alla necessità di decodificare i vari
campi. Inoltre, non consente di sfruttare al massimo il parallelismo esistente
nell’hardware. Il formato più usuale è quello misto, con alcuni campi codificati ed altri
no. Inoltre, esistono vari schemi di codifica, ognuno dei quali tende ad adattarsi
meglio a determinate caratteristiche del particolare interprete.
Un’altra differenza con le istruzioni in linguaggio di macchina, sta nel fatto che è
incluso esplicitamente nella microistruzione l’avanzamento o, alternativamente,
l’aggiornamento del MPC (Micro Program Counter).
Esiste, cioè una sezione della microistruzione che è destinata al cosiddetto
sequenziatore, il cui compito è appunto quello di determinare l’indirizzo della prossima
microistruzione da eseguire. Tale campo è formato da 3 sottocampi: un sottocampo
code che contiene il codice operativo di un microjump condizionato, un sottocampo
cond che rappresenta la condizione su cui effettuare il test, un sottocampo addr che
esprime l’indirizzo di memoria di controllo a cui saltare se la condizione è verificata.
2.4.3 Decodifica del codice operativo
La decodifica del codice operativo dell’istruzione di macchina
rimanda, invece che ad un circuito differente per ogni codice
operativo, all’indirizio di inizio di un differente microprogramma.
Essa viene comunemente effettuata tramite una memoria di mapping.
Il codice operativo viene inviato sulle linee di indirizzo di tale
memoria in modo da selezionare una locazione, nella quale
si è andato a porre l’indirizzo di micromemoria in cui comincia
il microprogramma. Se successivamente si vuole spostare il
microprogramma in un’altra area della memoria di controllo, basterà cambiare il
contenuto della corrispondente locazione in memoria di mapping con il nuovo indirizzo.
2.4.4 Diagramma a blocchi dell’unità di controllo
microprogrammata
Una unità di controllo microprogrammata
è dotata di un contatore di microprogramma
MPC e di un registro di microistruzione MIR.
L’unità di controllo riceve l’indirizzo di inizio
del microprogramma da eseguire dalla
memoria di mapping.
L’indirizzo della prossima microistruzione,
oltre che essere fornito dalla memoria di
mapping, può essere dato dall’avanzamento
automatico del MPC, oppure può essere il frutto
di un microjump.
Quale delle tre alternative viene decisa dal controllore
della prossima istruzione in base ai campi codice e
cond della microistruzione. Il campo cond seleziona
per il test uno dei bit di condizione N, Z, V o C,
prodotti dall’unità aritmetica e logica. L’uscita del
controllore seleziona infine la sorgente per il prossimo
indirizzo da caricare in MPC.
La microistruzione, posta alla locazione di memoria
puntata da MPC, viene estratta e caricata nel MIR,
da cui si dipartono le linee dirette alle altre unità.
2.4.5 Unità aritmetica e logica
L’unità aritmetica e logica è formata
essenzialmente da un insieme di registri
generali, una ALU propriamente detta, ed una
unità di shift.
I registri generali sono collegati, in genere,
ad entrambi gli input della ALU. Per questo sono
selezionabili due registri contemporaneamente
nella microistruzione, mediante i due campi di
indirizzo denominati A e B.
Tramite il campo ST di un solo bit, si può decidere
di immagazzinare il risultato nel registro selezionato
dal campo B.
La logica di decodifica degli indirizzi A e B è
costruita dentro quella che viene chiamata una
RAM a due porte.
Il bus di dati interno è collegato ad uno dei
due input della ALU, in multiplexing con una
delle uscite dei registri generali.
I due latch A e B vengono impiegati per presentare dati stabili alla ALU qualora si
utilizzino gli stessi registri come input e come output dell’operazione.
I campi ALU ed SH della microistruzione
specificano, rispettivamente, il tipo di
funzione richiesta alla ALU e se si
desidera effettuare uno shift sul risultato,
ed il tipo di shift.
Un risultato collaterale della ALU è dato
dai bit di condizione N, Z, V e C, il cui
valore può essere interrogato sia dalle
istruzioni della architettura di calcolatore
che dalle microistruzioni. Queste ultime
utilizzano il campo cond per decidere la
prossima microistruzione da eseguire.