LA MEMORIA SRAM e D R A M | | static dynamic random access memory SRAM: unità che memorizza un gran numero di parole in un insieme di flip-flop, opportunamente connessi, mediante un sistema di indirizzamento e trasferimento (lettura/scrittura) di parole. I flip-flop della memoria si dividono in 2k gruppi di h flip-flop, ciascuno dei quali memorizza una parola di h bit. Ogni gruppo è sostanzialmente un registro cui è logicamente associato un indirizzo di k bit nell’intervallo 0 .. 2k –1. La configurazione di una SRAM è completamente definita specificando il numero 2k di celle indirizzabili (dimensione verticale o altezza – height) e la dimesione h della cella (dimensione orrizzontale o larghezza – width). k SRAM h 2k × h h k ingressi per l’indirizzo h ingressi per i dati h uscite per i dati 3 ingressi di controllo attivazione/selezione (chip select) abilitazione uscita (output enable) abilitazione scrittura (write enable) La struttura con i multiplexor utilizzata per l’indirizzamento all’interno del banco dei registri non è utilizzabile per memorie a grandi dimensioni. In questo caso si utilizzano porte di collegamento a tre stati che, distribuite tra le celle di memoria, risultano più efficienti di un unico (gigantesco) multiplexor. Per evitare decodificatori troppo grandi si organizza la memoria in modo gerarchico e si usa un metodo di decodifica a due fasi. Esempio. Si consideri una SRAM 32 × 2. Per indirizzare una tale memoria servono 5 bit (25 =32). I dati in input ed in output sono di 2 bit. Si puo’utilizzare prima un indirizzo a 3 bit (bit 4-3-2) per selezionare la memoria di primo livello ed accedere poi ai dati utilizzando i rimanenti 2 bit (bit 1-0). 110 10 000 001 110 111 DRAM Mentre nella memoria statica (SRAM) il bit memorizzato viene mantenuto per un tempo arbitrario (finché c’è alimentazione), nella memoria dinamica (DRAM) un bit viene espresso sotto forma di stato di carica di un transistor, non è stabile e quindi va “rinfrescato” periodicamente. Questo può essere fatto direttamente con un circuito di controllo integrato sul componente di memoria liberando il processore dall’operazione di rinfresco. Usando meno transistor, la densità di bit memorizzati in una DRAM è molto più alta rispetto ad una SRAM e quindi la DRAM ha, a parità di capacità, un costo inferiore. Nella DRAM la decodifica dell’indirizzo è un processo a due fasi, simile a quello visto per la SRAM ma generalmente più lento. Desiderio … .. irrealizzabile: avere tanta memoria (potenzialmente infinita) ad accesso molto veloce. Soluzione … più realistica: •avere tanta memoria (potenzialmente infinita) strutturata gerarchicamete, •con quella che ha più alta probabilità di servire subito ad accesso più veloce; •le altre, scendendo nella gerarchia, ad accesso sempre più lento. CACHE Le memorie più veloci (SRAM) saranno fisicamente più vicine alla CPU al livello più alto, e manterranno i dati usati più di recente, le altre (DRAM e dischi) formeranno i livelli più bassi. La memoria più vicina al processore viene detta cache. (cache = nascondiglio, luogo sicuro) CPU Cache più veloce più piccola più costosa RAM Dischi, etc. più lenta più grande meno costosa Lo scambio di informazione avvene solo tra due livelli adiacenti. L’unità di informazione che viene scambiata si dice blocco. Quando arriva la richiesta di un dato ad un livello (livello superiore) ci sono ovviamente due possibilità: •il dato è presente a quel livello, e quindi la richiesta ha successo (hit); •il dato non è presente a quel livello, e quindi la richiesta non ha successo (miss) e deve essere inoltrata al livello inferiore. hit ratio: frequenza dei successi miss ratio: frequenza dei fallimenti (1.0 – hit ratio) hit time: è il tempo necessario per cercare il dato al livello superiore. Nota: anche quando il dato non è presente al livello superiore, viene speso del tempo per cercare il dato in quel livello prima di inoltrare la richiesta al livello inferiore. miss penality: è il tempo necessario per passare l’informazione (il blocco che contiene il dato cercato) da un livello inferiore ad un livello superiore. Principio di località: •Località temporale: è probabile che un dato già utilizzato venga riutilizzato dopo breve tempo. •Località spaziale: è probabile che i dati utilizzati in un breve intervallo di tempo siano memorizzati in zone vicine della memoria. Le memorie (memoria istruzioni e memoria dati) indicate nella descrizione del processore sono cache. • come si fa a sapere se un dato è presente nella cache? • come si recupera un dato presente nella cache? L’hit time chiaramente dipende dalla risposta a queste due domande. La risposta alla prima domanda diventa facile quando ogni blocco può essere memorizzato in un solo posto della cache, ovvero se ad ogni locazione di memoria corrisponde esattamente una locazione della cache: indirizzamento diretto. Sia M il numero di blocchi che possono essere contenuti nella cache. Un semplice metodo di indirizzamento diretto consiste nel prendere come indirizzo nella cache l’indirizzo del blocco modulo M. Se M = 2m allora l’indirizzo del blocco modulo M è dato dagli m (=log2 (M)) bit meno significativi dell’indirizzo. 0 0 1 1 0 1 M = 8 = 23 0 0 0 0 1 0 0 1 0 1 0 1 0 0 1 0 1 1 0 1 1 0 0 0 1 1 0 1 0 1 1 1 0 0 1 0 1 5 9 13 17 21 25 1 1 1 0 1 29 31 Supponiamo di cercare il dato all’indirizzo 21 = 101012. Dobbiamo prima sapere se la posizione 101 della cache contiene un dato reale o no (cioè se è gia’stata caricata o no): aggiungiamo un bit di validità. Inoltre, dobbiamo sapere se la posizione 101 della cache contiene il dato cercato oppure quello ad uno degli altri indirizzi che vengono mappati in 101: aggiungiamo un insieme di tag. Memorizzando un bit di validità ed un insieme di (etichette) tag che contengono i bit più significativi dell’indirizzo (non usati per l’indirizzamento nella cache) si può dare una risposta veloce alle domande precedenti. Esempio. Supponiamo di cercare i dati ai seguenti indirizzi in una cache inizialmente vuota. ind10 ind2 cache hit/miss 22 26 22 26 6 3 18 10 110 11 010 10 110 11 010 00 110 00 011 10 010 110 010 110 010 110 011 010 miss miss hit hit miss miss miss Indirizzo cache 000 001 010 011 100 101 110 111 bit di validità tag N N Y N N N Y N blocco 11 Mem(11010) 10 Mem(10110) Osservazione. Nell’architettura MIPS, i due bit meno significativi di ogni indirizzo servono per individuare il byte all’interno della parola. Se ogni blocco della cache contiene una parola (4 byte), i due bit meno significativi dell’indirizzo non servono per indirizzare all’interno della cache e l’indirizzo nella cache si forma considerando i bit da 2 in poi. Tag Byte offset Indice Bit di validita' Tag = Le memorie (memoria istruzioni e memoria dati) indicate nella descrizione del processore sono cache. In caso di miss la soluzione più semplice e’che l’unità di controllo del processore sospenda (ponendosi in una situazione di stallo) ogni operazione finchè, utilizzando un controllo separato, la memoria non sia stata aggiornata. Alcuni accorgimenti possono essere presi per diminuire i tempi di stallo (e quindi di esecuzione). Primo tipo di implementazione cache: blocchi di una parola (DECStation 3100 - con processore MIPS2000) La gestione delle richieste di lettura (sia di dato che di istruzione) è quella più ovvia: - L’indirizzo viene inviato alla memoria appropriata. - Viene effettuato il controllo per la presenza nella cache. In caso di hit si procede con l’esecuzione. In caso di miss la richiesta viene inviata alla memoria principale. Appena disponibile, il dato (o l’istruzione) viene scritto nella cache e l’esecuzione riprende. La gestione delle richieste di scrittura è un po’meno ovvia. Problema dell' inconsistenza tra cache e memoria principale. Se eseguendo una store il dato viene registrato solo nella cache e non viene riportato anche nella memoria principale, due posizioni corrispondenti (indirizzo + tag) potrebbero contenere dati diversi. Richieste di scrittura Per mantenere la memoria principale e la cache sempre consistenti, ogni modifica alla cache dovrebbe essere subito riportata nella memoria principale. Questa soluzione è detta di write-through. Questa scelta ha chiaramente un costo (attesa che l’operazione di scrittura in memoria principale sia completata) che, per programmi con frequenti operazioni di memorizzazione, puo’ diventare molto elevato. Per ridurre i costi si puo' utilizzare una memoria tampone (write buffer): il processore scrive il dato nella cache e nel buffer e poi prosegue l’esecuzione. Il processo di scrittura nella memoria principale avviene in parallelo prelevando un dato alla volta dal write buffer (liberando man mano spazio per memorizzazioni successive). In caso di frequenti operazioni di scrittura, il processore può ugualmente dover entrare in una situazione di stallo aspettando che il buffer si liberi. Un'altra tecnica utilizzata prevede la scrittura in memoria solo nel momento in cui il dato nella cache deve venir riscritto (write back).