1 La memoria
Con riferimento allo schema di Figura 1 si facciano queste assunzioni:
• La memoria è costituita da parole1 di ampiezza p bit, pari al grado di parallelismo del bus dei dati.
Ad ogni cella è assegnato un indirizzo univoco.
• La lettura/scrittura di una cella richiede la presentazione del suo indirizzo sul bus degli indirizzi.
Se m è il numero delle linee di indirizzo lo spazio di memoria è ampio M = 2m .
Si noti che abbiamo assunto che gli indirizzi siano assegnati alle parole, indipendentemente dal grado di
parallelismo2 . Al Paragrafo 1.1 modificheremo questa assunzione assegnando gli indirizzi ai byte.
Di norma non tutto lo spazio di memoria viene utilizzato e, comunque, si può sempre presentare la
possibilità che occorra costruire un blocco di memoria di una certa dimensione a partire da una posizione
prestabilita.3 Supponiamo di disporre di integrati di memoria con parallelismo p, di dimensione B = 2b
(ovvero con b linee di indirizzo). Assumiamo che gli integrati presentino un piedino di abilitazione CS
(Chip Select). Con n integrati potremo costruire un blocco di memoria di nB parole contigue.
Un indirizzo di memoria può essere sempre considerato come composto da due parti: il numero
di blocco e l’indirizzo entro il blocco. Figura 2 mostra questa schematizzazione. Ne consegue che la
dislocazione naturale di un blocco di B parole all’interno dello spazio di memoria M è quella che lo alloca
ad un indirizzo di partenza multiplo di B (incluso lo 0), come schematizzato a sinistra in Figura 3.
Ciò equivale a immaginare lo spazio di memoria come suddiviso in blocchi della dimensione dell’in-
tegrato. Corrispondentemente l’indirizzo può essere cosı̀ interpretato: le linee di indirizzo Ab−1 − A0
rappresentano l’indirizzo entro il blocco, le linee Am − Ab identificano il blocco. Ne consegue che le linee
Ab−1 − A0 vanno portate ai piedini degli indirizzi dell’integrato, mentre le restanti verranno decodificate
in modo da selezionare l’integrato attraverso il piedino CS.
1A volte si usano anche i termini “celle”,“posizioni” e “locazioni”
2 Da questa convenzione segue che una memoria a 8 bit di ampiezza M contiene M byte, mentre una memoria a 32 bit
di ampiezza M contiene 4M byte.
3 È il caso della memoria ROM contenete il codice di inizializzazione del sistema.
1 LA MEMORIA 2
Vale solo la pena di osservare che, se con integrati di capacità B volessimo costruire un blocco di
memoria a partire da un indirizzo non multiplo di B, saremmo nella situazione schematizzato nella parte
destra di Figura 3, dove si è supposto di allocare l’integrato di capacità B a cavallo tra il blocco 0 e
il blocco 1 nello spazio degli indirizzi. La selezione comporta il riconoscimento del blocco di indirizzi
corrispondente alla dislocazione dell’integrato (si vedano a tale scopo gli Esercizi 10.7, 10.10 e 10.12 del
testo). La soluzione ovvia per costruire un blocco di memoria ampio B a partire da un indirizzo non
multiplo di B consiste nell’usare integrati di taglia inferiore, in modo che essi vengano allocati in modo
“naturale” nello spazio di memoria. Con riferimento all’esempio di Figura 3 si tratta di usare due integrati
di capacità B/2. Ovviamente questi integrati avranno b − 1 linee di indirizzo, mentre il bit b − 1 (che
prima faceva parte dell’indirizzo all’interno dell’integrato) andrà a far parte degli ingressi della logica di
selezione dell’integrato.
2 Parallelismo
2.1 Parallelismo di 1 byte
La forma più semplice di memoria è quella con parallelismo a 8 bit. I microprocessori della prima gene-
razione (8080, Z80, 6800) avevano tipicamente un bus dati a 8 bit. Lo schema della memoria corrisponde
è esattamente a quello di Figura 3 dove si devono assumere parole di 8 bit.
Esempio 1
In una memoria a 8 bit e capacità di 1 MB, i blocchi di 256 KB hanno come posizioni naturali quelle
che iniziano agli indirizzi 0, 256 K, 512 K, 768 K. L’indirizzo entro il blocco è dato attraverso le linee
A17 − A0 , mentre le linee A19 − A18 servono a specificare il blocco. Per esempio, il blocco di memoria 1
(quello che va dall’indirizzo 256 K all’indirizzo 512-1 K) viene selezionato con CS1 = A19 · A18 .
Figura 4: Schematizzazione di una memoria a 32 bit. Si è assunta la convenzione little endian. Tra
parentesi sono indicati i numeri di parola. La parola 1 è all’indirizzo 4, la parola 2 è all’indirizzo 8, ecc.
Con una macchina avente parallelismo pari a k byte, con k potenza del 2, si dice che una parola di
memoria è allineata se il suo byte meno significativo è a un indirizzo multiplo di k (nel caso di figura: 0,
4, 8, 12, ·· ). L’indirizzo di un byte può essere interpretato come il numero d’ordine della parola più lo
scostamento del byte entro la parola, come schematizzato in Figura 5. Seguendo la schematizzazione di
Figura 5, le linee Am−1 − Ak contengono il numero d’ordine della parola5 .
Alternativamente si può guardare la memoria come divisa in k fasce verticali (di parallelismo 1 byte)
e riguardare il numero su Am−1 − Ak come l’indirizzo effettivo del byte nella fascia considerata.
Dal Pentium il parallelismo è passato a 64 bit, anche se per molto tempo i registri interni sono rimasti a 32 bit. Per motivi
storici, Intel e gli altri produttori di Micro di architettura ×86 designano come parola i 16 bit, come doppia parola i 32 bit
e come quadrupla parola i 64 bit.
5 Formalmente si tratta del numero d’ordine della parola, nella pratica si parla di indirizzo di parola. Qui e nel seguito,
quando non c’è rischio di confusione, parleremo di indirizzo di parola intendendo riferirci al numero d’ordine della parola
stessa. In Figura 5 l’effettivo indirizzo di parola sarebbe dato dal numero d’ordine della parola e due “0” alla sua destra.
3 INTERFACCIA CON LA MEMORIA 4
Figura 5: Interpretazione dell’indirizzo di un byte come numero d’ordine del byte entro la parola. A sua
volta la parola è individuata attraverso il suo numero d’ordine entro un blocco.
• Possibilità di leggere/scrivere non solo a parole, ma anche a frazioni (in byte) di parole (con
riferimento alla Figura 4: un byte, una semiparola (16 bit) o una parola).
• Possibilità di trasferire parole (o semiparole) non allineate.
• Possibilità di trasferire la frazione di parola di memoria in/da differenti porzioni di registri di CPU.
In ogni caso, risulta evidente che, quando è possibile il trasferimento di una frazione di parola, in
appoggio al bus degli indirizzi occorrono ulteriori linee di controllo per selezionare gli specifici byte da
leggere/scrivere.
Nel paragrafo 3 vengono esposte differenti soluzioni in riferimento ai tre punti precedenti, .
• LDW: trasferisce in un registro di CPU la parola contenuta nella locazione indirizzata (indirizzo
multiplo di 4); schematicamente: R31−0 ← mW, dove R31−0 rappresenta i 32 bit del (generico) registro
R, mentre mW rappresenta la parola di memoria (allineata) indirizzata.
• LDH: trasferisce nella parte bassa di un registro di CPU la semi parola contenuta nella locazione
indirizzata (indirizzo multiplo di 2); la parte alta del registro viene azzerata; schematicamente:
R31−16 ← 0 e R15−0 ← mH, dove mH rappresenta la semi parola di memoria (allineata) indirizzata.
• LDB: trasferisce negli 8 bit meno significativi di un registro di CPU il byte indirizzato (indirizzo
qualunque); i restanti bit del registro vengono azzerati; schematicamente: R31−8 ← 0 e R7−0 ← mB,
dove mB rappresenta il byte di memoria indirizzato.
(Si noti che, dal punto di vista della memoria, le operazioni di fetch equivalgono a LDW.)
Le istruzioni di scrittura siano cosı̀ schematizzabili:
• STW: trasferisce il contenuto di un registro di CPU nella parola indirizzata (indirizzo multiplo di
4); schematicamente: mW ← R31−0 .
• STH: trasferisce la parte bassa di un registro di CPU nella semi parola indirizzata (indirizzo multiplo
di 2); schematicamente: mH ← R15−0 .
• STB: trasferisce li 8 bit meno significativi di un registro di CPU nel il byte indirizzato (indirizzo
qualunque); schematicamente: mB ← R7−0 .
Qualunque sia l’entità trasferita, alla memoria viene trasmesso l’indirizzo di parola, cioè i bit A31 − A2
e altri segnali di controllo per individuare la dimensione e la specifica entità trasferita.
Si può stabilire che la CPU, in base all’operazione effettuata, generi due segnali, ENW (Enable Word )
e ENH (Enable Halfword ), di cui la Tabella 3.1 specifica la combinazione dei valori in rapporto alla
3 INTERFACCIA CON LA MEMORIA 5
Tabella 1: Codifica dei segnali ENH e ENW in rapporto all’indirizzamento delle differenti entità di
memoria. La combinazione 11 non è consentita. Ovviamente ENW è asserito su le istruzioni LDW e
STW e sulle operazioni di fetch; ENH sulle istruzioni LDH e STH.
dimensione del dato trasferito; il posizionamento dell’entità trasferita è invece determinato dai bit A1 e A0
dell’indirizzo.
La logica per i trasferimenti è schematizzata in Figura 6 e Figura 7. Esse evidenziano il bus interno
e il bus esterno dei dati. Lettura/scrittura da/in memoria richiedono che i dati vengano incanalati dalla
sorgente alla destinazione posizionandoli secondo la precedente convezione circa gli effetti delle specifiche
istruzioni LD/ST. Per non appesantire le due figure si è evitato di riportare i necessari AND di ENW e
ENH con i comandi di lettura della memoria (RDM) e di scrittura della memoria (WRM), generati dalla
CPU, al pari dei segnali ENW e ENH, nell’esecuzione delle istruzioni LD/ST.
La Figura 6 mostra la logica relativa alle operazioni LD. e Si può osservare che un’operazione di lettura
può essere sempre eseguita come lettura dell’intera parola, con selezione della porzione da trasferire e suo
incanalamento verso la parte bassa del registro di destinazione nel passaggio da bus esterno a bus interno.
Per la lettura dell’intera parola basta che il comando di lettura della memoria (RDM) facia asserire tutti
i chip select degli integrati relativi alle 4 fasce.
Nel caso delle operazioni di scrittura (Figura 7), la situazione è più complessa, in quanto, ad esempio,
la scrittura di un byte deve andare a modificare il contenuto dello specifico byte indirizzato e non l’intera
parola di memoria. Ovvero, occorre asserire selettivamente i chip select delle fasce contenenti i byte da
aggiornare. Con riferimento alla Figura 7 sono possibili due diversi tipi di soluzione:
1. Si portano alla memoria le due linee ENW e ENH, ma anche le linee A0 e A1 e si ricostruisce la
rete che asserisce opportunamente i CS relativi alle quattro fasce.
2. Dalla CPU si fanno uscire direttamente quattro segnali di controllo, che denomineremo BE3 , BE2 ,
BE1 , BE0 , che selezionano, rispettivamente, la fascia dalla più significativa alla meno significativa.
Questi segnali di controllo vengono generati da una rete equivalente a quella del punto precedente,
con la differenza che tale rete è parte della CPU.
Nelle macchine di tipo RISC si preferisce la prima soluzione. La seconda soluzione è tipica dell’architettura
×86 e viene utilizzata anche per le operazioni di lettura.
Vale la pena di trovare l’espressione dei BEi in funzione di ENW, ENH, A1 e A0 . A titolo di esempio
consideriamo BE1 , assumendo che i 4 segnali in questione siano coerenti in uscita dalla CPU, ovvero
assumendo che:
In queste ipotesi
BE1 = EN W + EN H · A1 · A0 + EN W · EN H · A1 · A0
= EN W + EN H · A1 · A0 + EN H · A1 · A0
3 INTERFACCIA CON LA MEMORIA 6
Figura 6: Schema per il caricamento dalla memoria di una parola, una semiparola o un byte con ri-
ferimento all’architettura ipotizzata all’inizio del paragrafo 3.1 (la numerazione è little endian). Si fa
l’ipotesi di leggere sempre una parola allineata. Per non appesantire la figura si è evitato di riportare il
comando di lettura (che ovviamente è in AND con ENW e ENH). Il dato viene messo sul bus interno
dopo essere stato selezionato tramite i segnali ENW e ENH (Tabella 3.1). Il segnale di ENW comanda il
trasferimento di un’intera parola. Quando si richiede il trasferimento di una semiparola e asserito ENH,
mentre ENW è disasserito. In tal caso il buffer con uscita a 16 bit mantiene a zero i 16 bit più significativi
sul bus interno, mentre ENH abilita il trasferimento sulla metà bassa del bus interno della semiparola
selezionata tramite A1 . Se ambedue i segnali ENW e ENH sono disasseriti, il byte selezionato in base
al valore di A0 e A1 , viene trasferito sulle linee D7−0 , mentre vengono portati a 0 anche i bit D15−7 .
Ovviamente, la combinazione 11 per ENW, ENH non è consentita: la logica di macchina deve garantire
che tale combinazione non si possa mai manifestare.
3 INTERFACCIA CON LA MEMORIA 8
Figura 7: Schema per la memorizzazione di una parola, una semiparola o un singolo byte (la numerazione
è little endian). Si tratta dello schema duale di quello di Figura 6. Per non appesantire la figura si è
evitato di riportare il comando di scrittura (che è ovviamente sottinteso, ovvero in AND con ENW e
ENH). Per selezionare il dato da scrivere in memoria, si usano gli stessi segnali di controllo usati per
la lettura. I segnale ENW e ENH hanno il significato di Tabella 3.1. A differenza della lettura, nel
caso di scrittura occorre necessariamente trasmettere A0 e A1 , oltre che ENW e ENH, alla memoria per
selezionare la porzione di parola da scrivere.
3 INTERFACCIA CON LA MEMORIA 9
mov rax,m64
Una CPU ×86, ad ogni ciclo di lettura/scrittura della memoria asserisce i segnali che selezionano
la striscia verticale su cui leggere. Nell’8086 e 286, le due fasce erano individuate dal segnale BHE e
dal bit A0 dell’indirizzo. Nel 386 e nel 486 attraverso i 4 segnali BE3 , BE2 , BE1 , BE0 . A partire dal
Pentium il bus dati è diventato a 8 byte, per cui il bus indirizzi è diventato A31 − A3 , mentre le linee di
selezione di fascia sono diventate 8 (BE7 , BE6 , ··, BE0 )8 . Si noti che, diversamente da quanto ipotizzato
al Paragrafo 3.1 e in particolare in Figura 6, i segnali BE sono asseriti anche sulle operazioni di lettura.
Essi identificano le sezioni del bus che, in un trasferimento, contengono dati validi.
Con riferimento alla Figura 4, si supponga di dover leggere la parola (32 bit) non allineata che inizia
all’indirizzo 9, come schematizzato in Figura 8. Cioè supponiamo che si abbia l’istruzione
mov eax, <9>
essa determina due cicli di lettura:
a) nel primo ciclo, sul bus degli indirizzi (A31 −A2 ) viene asserito il numero 2 e vengono asseriti BE3 ,
BE2 e BE1 ;
a) nel secondo ciclo, sul bus degli indirizzi (A31 −A2 ) viene asserito il numero 3 e il solo BE0 .
Figura 8: La parola formata dai byte B3, B2, B1 e B0 non è allineata. L’ipotesi di figura è che la parola
inizi all’indirizzo (di byte) 9. Ovvero, il byte meno significativo (B0) si trova in posizione 1 nella parola
(di indirizzo) 2, mentre il byte più significativo è nella posizione 0 alla parola 3.
In Figura 9 viene schematizzato il meccanismo di posizionamento dei byte in ingresso alla CPU (cioè
per le letture). Nell’architettura ×86 il riordinamento delle porzioni di parola non allineata, lette/scritte
in due fasi, è interamente svolto all’interno della CPU.
In passato sono state costruite macchine che, pur prevedendo l’indirizzamento di parole non allineate,
lasciavano la ricostruzione della parola alla logica esterna (al controllore di memoria)9 .
8 Vale la pena di osservare che fino all’introduzione della modalità di funzionamento a 64 bit, i registri di CPU erano 32
bit, mentre dal Pentium in poi il bus era a 64 bit. Non stupisca la differenza tra parallelismo dei registri e parallelismo del
bus dati. Di fatto la CPU legge/scrive, di norma in cache. Dunque il bus a 64 bit serviva ad aumentare la banda passante
tra memoria e cache. Peraltro la CPU (Pentium e successive), per quanto si riferisce alle operazioni di fetch delle istruzioni,
legge dalla cache parole di 128 bit.
9 La CPU comandava una sola operazione di lettura/scrittura e attendeva che il controllore esterno (al quale spettava il
Tabella 2: Trasferimenti tra CPU e memoria e loro codifica per la CPU 68040.
Oggi i manuali Intel raccomandano vivamente di allineare le parole (quelle di 64 bit a indirizzi multipli
di 8, quelle a 32 a indirizzi multipli di 4, quelle a 16 bit a indirizzi multipli di 2). Vengono forniti numeri
impressionanti (cicli di clock persi) circa il peggioramento delle prestazioni a causa del non allineamento.
• I singoli byte, com’è ovvio, possono essere trasmessi su qualunque corsia del bus dati.
• Le semi parole possono essere trasmessi sulla parte alta o sulla parte bassa.
• La parola occupa le 4 corsie.
Inoltre
• La configurazione SIZ1 = SIZ0 = 1 (per la quale A1 e A0 sono pure irrilevanti) viene impiegata per
comandare il trasferimento di una parola nella lettura di una linea da portare in cache10 .
• Infine si faccia attenzione alle corsie del bus associate alle codifiche di A1 , A0 .
Con la precedente codifica delle abilitazioni se una parola non è allineata a un indirizzo pari, occorrono
tre cicli di lettura/scrittura. Con riferimento all’esempio di Figura 8, occorre:
a) un primo ciclo per trasferire il byte B0;
PowerPC
Per l’esattezza, ci riferiamo al modello 601, ma quanto detto vale per tutte le CPU della famiglia. Si
tratta di una CPU RISC con registri interni a 32 bit, bus indirizzi a 32 bit e bus dati a 64 bit.
Sebbene si tratti di una macchina RISC c’è alta flessibilità nei trasferimenti. A tale scopo la CPU
trasmette all’esterno un indirizzo su 32 bit e tre segnali SIZ2 , SIZ1 e SIZ0 , usati per dare la dimensione del
10 La cache ha linee di 16 byte (4 parole). Il trasferimento di una linea avviene di norma in burst mode, ma ci sono delle
situazioni in cui è possibile che il trasferimento avvenga come una successione di 4 (normali) letture della memoria. Su tali
letture viene asserita la configurazione SIZ1 = SIZ0 = 1
3 INTERFACCIA CON LA MEMORIA 11
dato trasferito. Questi tre segnali, combinati con i tre bit meno significativi del bus indirizzi determinano
esattamente cosa viene trasferito in un ciclo di accesso alla memoria. Sono possibili trasferimenti da 1
a 8 byte. Trasferimenti di 16, 32 o 64 bit non allineati comportano due cicli di lettura/scrittura se la
quantità trasferita attraversa un confine di allineamento a 64 bit.