Università degli Studi di Napoli Federico II
Sistemi ad Elevate Prestazioni
Prof.re Nicola Mazzocca
Lezione 1
0. Introduzione al corso (prestazioni e affidabilità)
Per capire le finalità del corso e il filo logico che lega le lezioni, strutturiamo schematicamente le
unità didattiche in modo da capire i diversi argomenti affrontati. Il corso di Sistemi ad elevate
prestazioni è basato su due moduli fondamentali:
- Sistemi ad elevate prestazioni;
- Sistemi affidabili;
0.1 Sistemi ad elevate prestazioni
La prima grossa novità di questo modulo è che il modello di Von Neumann, che fino ad ora ci ha
condotto nella trattazione, risulta essere accantonato per lasciare spazio ad architetture reali che non
risultano seguire tale modello. Il modello di Von Neumann assume, quindi, una valenza più logicoastratta che architetturale. Le architetture studiate nei diversi corsi universitari a parte l’MC68000,
non risultano essere architetture reali, almeno per quanto riguarda i processori moderni.
Quindi ci occuperemo di architetture reali, caratterizzate da precisi accorgimenti sul parallelismo
interno e/o sul clock, tali da permettere il miglioramento delle prestazioni. Da un punto di vista
pratico nell’ambito dello studio di sistemi ad elevate prestazioni possiamo delineare due diverse
soluzioni:
- Parallelismo interno: Le architetture che puntano su tale aspetto per incrementare le
prestazioni sono: le architetture SuperScalari, i VLIW (Very Long Instruction Word), e i
DSP;
- Architetture Parallele: caratterizzate dall’aumento del numero di processori presenti nel
sistema, in modo da aumentare le prestazioni. Si passa, quindi, dalla soluzione
monoprocessore (a parallelismo interno) a più processori. Naturalmente è possibile sfruttare
tale soluzione secondo modalità diverse, è possibile avere due processori che collaborano
attraverso memoria condivisa, in tal caso si parla di sistema multiprocessore (il problema
relativo è quello della gestione della memoria condivisa). Altra soluzione è quella dei
sistemi multicomputer, caratterizzata da una comunicazione tra i processori basata su
messaggi. Ogni processore è dotato di un sistema di I/O con cui connettersi agli altri; in tal
caso il problema sarà gestire la comunicazione attraverso link.
Una delle problematiche importanti, che distingue le architetture parallele dalle soluzioni
monoprocessore, è la gestione dello stato che può essere centralizzato o distribuito. Nel caso dei
sistemi a più processori ho certamente uno stato distribuito e la gestione, quindi, risulta sicuramente
più complessa rispetto al caso dei sistemi monoprocessore. In più possiamo allargare maggiormente
il discorso andando a sottolineare che sicuramente la gestione dello stato nei sistemi multicomputer
risulta più critica rispetto al caso dei sistemi multiprocessore.
Per meglio capire quali sono le difficoltà nella gestione dello stato possiamo stilare una breve lista
delle principali difficoltà nella gestione distribuita dello stato:
- Perdita del riferimento temporale, quindi l’ordinamento temporale degli eventi;
- Perdita della mutua esclusione, ogni sistema può elaborare indipendentemente dagli altri
mentre in un sistema centralizzato c’è mutua esclusione;
- Problema di stallo;
- Problema di guasti: devo gestire situazioni in cui solo alcuni delle parti che formano il
sistema risultano non funzionanti, mentre il resto continua a funzionare;
- Problema di programmazione su sistemi distribuiti, con la possibilità di voler realizzare
sistemi single-purpose e multi-purpose.
Tutti questi problemi sono problemi che rientrano nel cosiddetto Software di Base.
Parte esercitativa relativa al primo modulo del corso:
-
Tesine (analisi di un processore alla luce della teoria trattata al corso);
Esercizi sul dimensionamento delle memorie (Tool Dinero);
Programmazione su architetture parallele (Multicomputer).
0.2 Sistemi affidabili
La seconda parte del corso cura il problema dell’affidabilità. Quando consideriamo un sistema
basato su più oggetti replicati lo si fa o per aumentare le prestazioni o per raggiungere una maggiore
affidabilità. In questo caso ci occuperemo di affidabilità nei sistemi ferroviari e nei sistemi avionici.
1. Sistemi ad elevate prestazioni
1.1 Sistemi Monoprocessore
Il più importante parametro fra quelli che riguardano le prestazioni dei sistemi (ma non l’unico) è la
velocità di elaborazione. Per incrementare la velocità di un sistema possiamo agire sia
sull’hardware che sul software, e, per quest’ultimo punto, o sulla fase di programmazione, o su
quella di compilazione. Ricordiamo che il ruolo del compilatore è quello di adattare il linguaggio di
alto livello alle caratteristiche fisiche della macchina.
Se ci limitiamo a considerare architetture a singolo processore, possiamo solo muoverci nella
direzione di massimizzare le prestazioni dell’unico processore presente. Prima o poi però ci si trova
ad avere a che fare con applicazioni e/o requisiti prestazionali che non possono essere in nessun
caso soddisfatti mediante la struttura monoprocessore, e, quand’anche non esistesse questo limite, è
solo naturale pensare di incrementare le prestazioni combinando strutture a nodo singolo per
ottenere strutture più potenti. Quindi si passa a considerare le architetture parallele.
1.1.1 La tecnica del Pipelining
Concentriamoci per ora solo sui sistemi monoprocessore, dove ci sono più unità che evolvono in
parallelo. Per poter effettivamente parlare di unità che evolvono in parallelo bisogna accertarsi che
il processo elaborativo possa essere sviluppato da unità che elaborano in modo disgiunto. Per fare
questo bisogna riferirsi a modelli che possono essere più o meno complessi. Nell’ambito degli studi
abbiamo visto due modelli principali, il modello CISC e quello RISC, che differiscono per:
- Codici Operativi. Avere più (CISC) o meno (RISC) codici operativi corrisponde ad una
maggiore o minore complessità della rete di controllo del processore;
- Operandi ammessi dal processore. Per i processori RISC gli operandi per le operazioni
aritmetiche sono solo di tipo registro, questo significa che per fare una qualsiasi operazione
su di un valore contenuto in memoria bisogna far riferimento al modello load/store, cioè i
dati devono essere caricati prima all’interno dei registri del processore per poi essere oggetto
del calcolo effettivo.
- Modi di indirizzamento. Per i processori RISC abbiamo solo indirizzamento immediato e
indiretto, in quanto attraverso questi due modi riesco a coprire tutte le operazioni.
Naturalmente su questo ha un grosso peso l’attività di compilazione.
Tutto questo ci fa capire che nei processori RISC è meno problematica l’operazione aritmetica
rispetto ad un’operazione di I/O, naturalmente si può dire questo con qualche riserva in quanto già
se ci si pone di fare un’operazione in aritmetica floating point, queste considerazioni possono
cambiare.
Questi sono i presupposti da cui partiamo per costruire un sistema monoprocessore basato su pipe,
cioè vogliamo costruire un sistema con pochi codici operativi, caratterizzato da codici di load e
store, e con pochi modi di indirizzamento. Quindi vogliamo capire ponendoci questi vincoli come
possiamo semplificare l’architettura del nostro sistema, poi passeremo a capire se l’architettura
determinata possa andare bene anche per i processori CISC, quindi processori non caratterizzati
dalle tre proprietà delineate.
Un’architettura che può soddisfare i requisiti espressi rispetta delle fasi principali:
1. IF 2. ID 3. EX 4. MEM 5. WB
(prelievo (Fetch), interpretazione (Decode), esecuzione (Execution), Memorizzazione ed eventuale
Scrittura dei risultati in memoria (Write Back)1) c’è da sottolineare che rispetto alla
schematizzazione fatta nei corsi di Calcolatori I e II dove ci si poneva nell’ottica di poter fare
operazioni coinvolgendo sia i registri del processore sia la memoria, per le ipotesi fatte, prima della
fase di esecuzione non c’è la fase di preparazione degli operandi. Questa fase è mancante perchè gli
operandi saranno disponibili nei registri del processore oppure affinché siano disponibili bisogna
eseguire un’operazione di load.
Le cose più importanti su cui su può agire per migliorare le prestazioni del sistema appena delineato
sono:
- Aumentare il clock;
- Duplicare le risorse hardware (figura 1);
- Implementare il parallelismo (all’interno) del nodo o microparallelismo.
In realtà la frequenza del clock non può essere aumentata indefinitamente, a causa di un limite
massimo dovuto alle proprietà reattive; la seconda soluzione può essere applicata solo per alcuni
componenti del processore, per evidenti motivi economici e di spazio; si preferisce, dunque, la terza
soluzione.
PC
TEMPi2
MAR’
MDR’
MAR
MDR
ID
TEMPi3
ALU
Registro
Stato
RC
Figura 1 : Schema di un processore RISC LIKE.
Come vedremo più avanti il microparallelismo può essere implementato via hardware e/o software
e, in quest’ultimo caso, è possibile agire sulla fase di programmazione, o su quella di compilazione.
Si può partire dall’idea che se le cinque fasi sono eseguite in modo strettamente sequenziale, ogni
unità lavora per una quota parte del
tempo di esecuzione della singola
(1) (2) (3) (4)
(5)
istruzione; ad esempio, quando
i-1
IF ID
EX MEM WB
l’istruzione
è
in
fase
di
i
IF
ID
EX MEM
interpretazione, le unità associate alle
i+1
IF
ID
EX
altre fasi sono inattive; il processore
i+2
IF
ID
non è, quindi, sfruttato al massimo.
 tempo
1
Alcune istruzioni non necessitano di alcune fasi, ad esempio, ADD R2, R1 non necessita della fase WB.
Quindi per rendere il sistema più veloce è possibile prelevare una nuova istruzione, mentre la
precedente è ancora in esecuzione (tecnica del prefetching). Più in generale, è possibile
parallelizzare le tutte fasi, implementando la tecnica del pipelining.
La tecnica del pipelining permette di diminuire il tempo di esecuzione di un programma, anche se il
tempo di attraversamento della singola istruzione non varia.
Tempo di attraversamento  TA = TIF + TID + TEX + TMEM + TWB
Tempo di risposta  TR = max {TIF,TID,TEX,TMEM,TWB}
In particolare se N sono le fasi, in condizioni ottimali, il tempo di esecuzione del programma
diventa pari ad 1/N del tempo di esecuzione dello stesso programma, in caso di esecuzione
sequenziale; ovvero il throughput (produttività), diventa N volte maggiore rispetto all’esecuzione
sequenziale.
1.1.2. I limiti del pipeling
1° Limite. (Vincolo di tempo) Queste fasi dette ‘in PIPE’ funzionano bene se tutte le unità
funzionali impiegano più o meno lo stesso tempo. Quindi la prima ipotesi da fare per garantire un
buon funzionamento del pipeling è:
ti  cost
Infatti, se il tempo necessario per una delle unità è significativamente maggiore di quello delle altre,
l’intero processore risulterà condizionato dalle prestazioni di tale unità più lenta (come indicato
nell’espressione precedente del tempo di risposta): la produttività è legata al tempo massimo. Ora, è
naturale che ciò può avvenire solo se le istruzioni eseguibili sono relativamente semplici. Come si
vede tale condizione tipica dei sistemi Risc è non, come siamo abituati a pensare, una premessa
progettuale, ma una conseguenza architetturale.
Un’istruzione singola processata da un sistema di questo genere impiegherebbe naturalmente lo
stesso tempo che sarebbe necessario per eseguirla in un sistema tradizionale. La velocizzazione
risiede nella possibilità di eseguire più istruzioni in parallelo nel modo che si è spiegato: migliora il
throughput (produttività). Ad ogni colpo di clock, difatti, sarà sempre disponibile una istruzione
nella fase di esecuzione. Se ad esempio il tempo di risposta (o di ‘fuoriuscita’ dal blocco
elaborativo) di una istruzione in un sistema tradizionale è 5*ti, qui diventa ti. ti sarà il tempo
impiegato da ciascuna unità funzionale, supposto costante; tale parametro evidentemente può essere
migliorato per via elettronica. L’unico inconveniente è far andare a regime la pipe (problema dello
startup), solo dopo una fase transitoria che dura 5*ti possiamo dire che il tempo di risposta diviene ti.
Il parallelismo ottenuto è a livello di istruzione: fino a 5 istruzioni dello stesso programma,
prelevate in tempi successivi, vengono eseguite in parallelo. Fino a questo momento il
miglioramento è solo di tipo hardware: programmatore
e compilatore sembrano non entrare in gioco.
2° Limite. (Vincolo tecnologico) Dobbiamo imporre
che tra le diverse fasi ci debba essere uno stesso clock,
quindi questo segnale dovrà viaggiare attraverso un filo,
sorgono quindi problemi di natura elettronica, e
principalmente il problema dello skew (allungamento)
del clock.
Quando la frequenza diviene molto elevata, il clock
comincia a deformarsi, e la deformazione è tanto
maggiore quanto più lunga è la linea di trasmissione. La
linea di trasmissione è un circuito induttivo/capacitivo
che tende a filtrare le alte frequenze, ovvero quelle che
sono responsabili delle variazioni rapide (transizioni
Figura 2: Circuito induttivo/capacitivo.
Figura 3: Lo skew del segnale di clock.
01 e 10) del segnale. Per conseguenza il segnale di clock si ‘addolcisce’ in corrispondenza
delle transizioni. Poiché l’impedenza vale C, maggiore è la frequenza, maggiore è l’impedenza di
filtro e più evidente è la deformazione; al limite, il clock si deforma fino a divenire una linea, e gli
ultimi elementi della catena delle 5 unità funzionali, che ricevono tutte lo stesso segnale di clock,
finiscono col non percepire nulla. Il problema è acuito dalla presenza inevitabile del rumore
induttivo. Nelle comunicazioni a grandi distanza si sovracampiona il segnale e si inseriscono bit di
controllo per sapere se il segnale è corretto o meno.
Per poter quantomeno limitare questo problema, si fa in modo da avere una linea di trasmissione su
cui far viaggiare il clock che sia priva di fenomeni capacitivi (problema di tecnologia elettronica), in
più è possibile aggiungere tra ogni coppia di unità dello schema uno stabilizzatore, in termini
informatici un registro, che sia in grado di acquisire il dato e di mantenerlo stabile durante
l’elaborazione.
3° Limite. (Problema di gestione delle istruzioni di salto) Le istruzioni di salto sono utilizzate per
cambiare il flusso di esecuzione di un programma; quando si incontra una istruzione di salto
bisogna eseguirla completamente (fine fase EX), prima di sapere se il salto deve essere effettuato o
meno e, quindi, prima di conoscere l’indirizzo della prossima istruzione da prelevare.
La pipe, intanto, continua a caricare le istruzioni in modo sequenziale. Tali istruzioni potrebbero
essere esatte o meno; se non lo sono bisogna eliminarle dalla pipe (flush della pipe) e caricare le
istruzioni esatte, si ha, quindi, un ritardo.
Tale ritardo detto branch penality è molto rilevante se si pensa che in un programma si ha un salto
ogni volta che si ha un ciclo o un costrutto condizionale (if-then-else/do-while…ecc); i salti
costituiscono, quindi, il 25% circa delle istruzioni eseguite.
Le soluzioni adottate per risolvere questo problema sono varie e saranno affrontate in seguito.
Questo problema della gestione delle istruzioni di salto è presente sia nei processori CISC che nei
processori RISC, però per i RISC il problema è meno rilevante perché i RISC hanno pochi modi di
indirizzamento ed operandi quindi fa operazioni più semplici arrivando prima a capire cosa può
accadere, mentre nei CISC c’è una maggiore complessità anche nei salti, arrivando dopo a capire il
salto.
4° Limite. (Problema di conflitto sui dati) Spesso accade che due istruzioni consecutive cercano
di leggere e scrivere contemporaneamente lo stesso registro; ciò potrebbe causare gravi errori. Nei
processori CISC i conflitti sui dati sono più probabili, siccome quest’ultimi possono utilizzare come
operandi per tutte le istruzioni sia registri del processore che le locazioni di memoria. Il conflitto sui
dati è confinato alle ultime tre fasi: EX, MEM e WB.
5° Limite (Problema della gestione delle interruzioni) In un sistema parallelo sono in esecuzione
più istruzioni contemporaneamente diventa, quindi, difficile gestire le interruzioni esterne e
garantire che le interruzioni interne siano eseguite in ordine.
6° Limite (Problema di conflitti per l’accesso in memoria) ovvero più fasi possono tentare di
accedere contemporaneamente alla memoria, per eseguire operazioni di lettura delle istruzioni o
scrittura dei dati.
La cosa fondamentale sarebbe risolvere ognuno dei problemi elencati nell’ambito della singola fase
senza coinvolgere le altre fasi, quindi limitando gli effetti negativi alla singola fase isolandola dalle
altre.
Torniamo ai due modelli CISC e RISC. Possiamo dire che quanto spiegato fino ad ora è relativo al
modello RISC, se cerchiamo di applicare gli stessi concetti al modello CISC ci rendiamo conto che
nei CISC quanto descritto per funzionare deve subire delle aggiunte, sicuramente bisogna
aggiungere la fase di operand assembly alle 5 già presenti, ma altro inconveniente che capita nei
CISC è la variabilità dei tempi che occorre impiegare nelle diverse fasi, cosa che certamente non va
a porre rimedio al primo limite evidenziato, quindi nei processori CISC avremo una suddivisione
ulteriore di ogni singola fase più lunga, in fasi, in modo da ottenere una pipe più lunga ma con un
tempo di esecuzione di ogni fase approssimativamente costante.
Naturalmente allungare la pipe non risulta un vantaggio a causa dello startup che si allunga e a
causa del maggior numero di informazioni da gestire in caso di errori. Anche da un punto di vista
elettronico si ha, a parità di circuiti che realizzano un pezzo della pipe, una diversa occupazione nei
processori RISC e CISC, questo porta alla possibilità di avere più registri nei processori RISC in
quanto c’è da realizzare meno stadi rispetto ad un processore CISC.
1.1.3. Cache dati e cache istruzioni
Il processore lavora ad una frequenza che è fino a 5 volte più elevata di quella di una macchina
tradizionale. Le fasi critiche dal punto di vista del tempo di esecuzione sono evidentemente quelle
che si interfacciano con la memoria, cioè quelle che abbiamo indicato con WB e IF. Le memorie,
rigorosamente sincrone, devono essere dunque molto veloci. Le memorie più veloci che
conosciamo sono le memorie cache.
CACHE
P
Si comprende però come, nel momento in cui si esegue una fase di WB per un’istruzione e una IF
per un’altra, si verifichi un conflitto (contemporaneità di una operazione di lettura e di una di
scrittura in memoria).
IF ID EX MEM
IF ID EX
IF ID
IF
WB
MEM . . .
EX . . .
ID . . .
IF . . .
Se quindi utilizziamo una sola cache il modello non funziona perché c’è un conflitto sulla 5° fase.
Osserviamo tuttavia che la fase WB riguarda la scrittura di dati, mentre la fase IF il prelievo di
istruzioni. Possiamo pensare allora di impiegare due cache: una per le istruzioni e una per i dati.
Tale limite quindi viene superato mediante una duplicazione architetturale.
Delle due cache, quella dei dati è più critica; infatti le
istruzioni sono statiche: possono essere solo lette.
Invece i dati sono acceduti in lettura e scrittura, e quindi
tutte le tecniche di write back, write through ecc.
Processore
considerate nel corso di Calcolatori 2 riguardano
principalmente la cache dati.
Si noti che la cosa si complica enormemente in presenza
CACHEist CACHEdati
di un processore CISC, le cui istruzioni consentono di
operare direttamente su dati all’interno della memoria:
ci sarà una ulteriore fase tra le fasi 2 e 3 la quale,
consistendo di operazioni di lettura e scrittura in
Figura 4 : Le memorie cache per i dati e
memoria, provocherà ulteriori potenziali conflitti con le
per le istruzioni.
altre fasi che accedono alla memoria.
A tutto quanto detto bisogna aggiungere che senza pipelining si accedeva alla memoria ogni 5*ti,
con la pipe si accede in memoria ogni ti ,quindi le tecnologie su cui si basano le memorie risultano
essere molto importanti nell’economia del sistema.
1.1.4. Le Memorie
Cerchiamo di capire ora come sono strutturate le memorie e come interfacciamo le memorie ai
processori. Lo schema generale da cui partiamo è:
R
A
M
Pbus
Pbus
Ci
Cj
mA
M
M
U
P
mA
Fra la cache primaria e l’eventuale cache secondaria, e fra quest’ultima e la RAM ci saranno
opportuni protocolli di bus. La memoria virtuale con la sua unità di gestione (MMU) risiede nel
processore. La MMU converte gli indirizzi logici, con i quali ha a che fare il processore, negli
indirizzi fisici di memoria. MMU lavora come è noto secondo un criterio di memoria associativa,
producendo un indirizzo fisico a partire da una etichetta.
Apriamo una parentesi su di un argomento che vedremo in futuro: Virtual cache. È da notare che in
molti casi anche le cache moderne lavorano con un
criterio di associatività (virtual cache). Sfruttando il
vantaggio di avere la cache primaria integrata sullo
Processore
stesso blocco del processore, in tale configurazione si fa
in modo che la MMU indichi direttamente dove si trova
il dato all’interno della cache (se vi è presente). Si
Cachedati Primaria
fondono cioè le due tabelle associative in una sola,
mediante la quale la MMU determina la posizione del
Buffer
dato nella cache. Ovviamente nel caso in cui il dato non
Figura
si trovi in cache sarà necessario propagare normalmente
Cachedati Secondaria
26(b):
l’indirizzo fino alla cache secondaria, o, alla peggio,
Esempio 1 fino alla memoria fisica.
Tabella di
I sistemi moderni, come rappresentato nello schema ad
ibernazione
Figura 5: Le cache dei
dati di primo e
inizio paragrafo, prevedono generalmente un doppio
secondo livello.
.
livello di cache dati: la cache primaria (Cj), che risiede
sullo stesso chip del processore, al fine di ridurre le
distorsioni (skew) e migliorare la propagazione dei segnali, e la cache secondaria (Ci), più lontana
dal processore e più capiente, ma meno veloce della primaria.
Tra le due cache dati potrebbe nascere un problema di disallineamento dei dati; per evitarlo si
utilizza un bus dedicato che, attraverso una politica di Write Through, garantisce sempre il perfetto
allineamento tra le informazioni.
Il bus dedicato non causa rallentamento del sistema, siccome il trasferimento dei dati tra le due
cache è effettuato utilizzando un buffer: il dato, scritto su Cj, è prima bufferizzato e,
successivamente, scritto in Ci.
Riepilogando, i dati vengono scritti nella cache primaria Cj, che è quella più vicina al processore,
dunque è più veloce e, fra l’altro, non presenta problemi di skew; la coerenza con la cache
secondaria viene garantita dalla politica di write through, ma le due scritture possono essere
differite grazie all’impiego di un buffer. In nessun caso si ha conflitto con il prelievo di istruzioni,
che sono contenute in una cache distinta.
La velocità di esecuzione di un sistema di calcolo dipende dalla velocità con cui si effettuano gli
scambi tra la CPU e la Memoria Principale, in cui dati e programmi sono memorizzati durante
l’esecuzione. Le memorie dovrebbero essere veloci, grandi e poco costose, ma ottenere queste tre
caratteristiche contemporaneamente è impossibile, perciò i moderni sistemi di calcolo utilizzano più
memorie ciascuna con caratteristiche e compiti diversi.
Processore
Cache Primaria
Cacheist.
Cache Secondaria
Memoria Principale
Memoria di massa
Figura 6 : La gerarchia delle memorie.
La memoria di massa (o Memoria Secondaria) è ad accesso sequenziale o parzialmente sequenziale,
quindi, il tempo di accesso alla memoria dipende dalla locazione a cui si deve accedere. Le
memorie cache e la Memoria Principale sono RAM (Random Access Memory); in particolare la
Memoria Principale è una RAM dinamica (DRAM), capace di mantenere i dati solo per un breve
intervallo di tempo, mentre le cache sono RAM statiche (SRAM), capaci di mantenere i dati finchè
sono alimentate.
Una memoria dinamica può essere immaginata come una matrice nella quale ciascun elemento è
individuato dalla coppia di indici (i,j). Ogni riga costituisce una parola della memoria e tutte le celle
di una riga sono collegate alla linea di parola , pilotata dal decodificatore di riga. Le celle di ogni
colonna sono collegate ad un circuito Sense/Write, tramite 2 linee di bit. I circuiti Sense/Write sono
collegati al decodificatore di colonna ed al bus dei dati.
Durante un’operazione di lettura/scrittura l’indirizzo, proveniente dal processore, è diviso in 2 parti,
la prima utilizzata per selezionare la riga, la seconda utilizzata per selezionare la colonna.
linee di
bit


DECODIFICATORE
DI RIGA
linea di parola



   
Sense/Write



Sense/Write
DECODIFICATORE DI COLONNA
 
dati
Figura 7 : Organizzazione delle celle di memoria.
Prima è applicato l’indirizzo di riga, seguito dall’impulso del segnale RAS (Row Address Strobe),
che seleziona la riga; poco dopo è caricato l’indirizzo di colonna, seguito dall’impulso del segnale
CAS (Column Address Strobe), che seleziona il circuito Sense/Write interessato. Se l’operazione è
di lettura, l’uscita del circuito selezionato è trasferita sul bus dei dati; se, invece, è di scrittura i dati
presenti sul bus dati vengono trasferiti nel circuito selezionato.
Quando si accede a locazioni di memoria successive, l’indirizzo di riga è caricato una sola volta,
mentre gli indirizzi di colonna nei cicli di memoria successivi; la frequenza, quindi, aumenta
rispetto agli accessi a locazioni casuali. Questo mi porta ad avere tempi di accesso più lunghi tipo 4
volte il tempo di secondo accesso ad un elemento della stessa riga, cioè il tempo per accedere al
primo elemento di una riga risulta essere 4 volte il tempo di accesso per avere gli elementi
successivi di una stessa riga.
Si è detto che le DRAM sono capaci di mantenere i dati solo per un breve intervallo di tempo è,
quindi, necessario riscrivere periodicamente (ogni 216 ms) il contenuto delle celle, prima che esso
venga perso definitivamente; questa operazione è detta refresh.
1K
1K
1K
1K
BUFFER (1K)
BUFFER (1K)
carica
(a)
Figura 8 : L’operazione di refresh.
BUFFER (1K)
(b)
In realtà il refresh fatto sulla singola cella richiederebbe un tempo enorme, risulta perciò
conveniente rinfrescare un’intera riga per volta. Supponiamo, ad esempio, di avere un indirizzo
lungo 20 bit, diviso in due gruppi da 10 bit; ci saranno, quindi 220 celle, divise in 210 righe e 210
colonne (figura 8). Il refresh consiste nel copiare la riga in un buffer e ricopiarla nella posizione
iniziale; il tempo di refresh sarà, quindi, proporzionale a 210, non più a 220. Il buffer può essere
realizzato con la tecnologia statica, essendo relativamente piccolo. Una naturale evoluzione del
modello consiste nel duplicare i buffer, in modo che mentre una riga caricata nel buffer (o scaricata
dal buffer), l’altro buffer possa scaricare nella cache (o caricare dalla cache) il suo contenuto.
Quando si applica un indirizzo di riga, sia durante un’operazione di lettura che di scrittura, l’intera
riga è rinfrescata.
Il circuito di refresh e la CPU sono in competizione per l’accesso in memoria; il circuito di refresh
ha, però, priorità maggiore. L’esecuzione del programma subirà, quindi, un ritardo, che dipende
dalla modalità di rinfresco: è possibile rinfrescare tutte le righe e poi far tornare la memoria allo
stato di funzionamento normale, oppure rinfrescarle un gruppo per volta, in modo da avere tempi di
rinfresco più brevi ma, più frequenti. Il rinfresco provoca degrado delle prestazioni della DRAM,
che risultano più lente ( 10 volte in più) delle SRAM, che non necessitano dell’operazione di
refresh.
Alcuni chip incorporano al loro interno il circuito di refresh e perciò sono dette memorie
pseudostatiche.