Esercizio 21cache a due vie FIFO con write-through
In questa pagina 7
Testo (esempio di compito di Architettura degli Elaboratori, UniPD, a.a. 2014-15, e variante dell'esempio di compitino a.a. 2015-16). Sia data la seguente sequenza di indirizzi in lettura (l) o scrittura (s) emessi dalla CPU e la memoria abbia il contenuto esadecimale indicato.
| # | indirizzo (binario) | l/s | byte scritto (hex) |
|---|---|---|---|
| 1 | 0001 0000 0100 |
l | |
| 2 | 0001 0000 1100 |
s | 3F |
| 3 | 0001 0000 1111 |
l | |
| 4 | 0001 0000 1101 |
s | A9 |
| 5 | 0001 0001 0100 |
l | |
| 6 | 0001 0001 1111 |
s | 5E |
| 7 | 0001 0000 0111 |
s | 66 |
| 8 | 0001 0010 0110 |
l |
| indirizzo | byte | byte | byte | byte |
|---|---|---|---|---|
| 100 | 08 | D0 | 07 | 02 |
| 104 | 00 | 00 | 00 | 00 |
| 108 | AE | 13 | A1 | 23 |
| 10C | A1 | 42 | 90 | 75 |
| 110 | BB | 16 | 00 | 00 |
| 114 | 0A | 87 | 03 | 71 |
| 118 | 3E | 13 | A1 | 23 |
| 11C | A1 | 82 | 90 | 15 |
| 120 | F9 | 86 | A0 | 00 |
| 124 | E9 | 16 | 05 | 00 |
Si assuma che la dimensione di parola coincida con un byte e la presenza di una cache di ampiezza 32 B, dimensione di blocco 4 B, inizialmente vuota, ad associazione a 2 vie, con politica di rimpiazzo FIFO, politica di scrittura write-through e gestione dei miss in scrittura con write allocate. Si indichino i campi in cui sono suddivisi gli indirizzi e il numero di insiemi, e si mostri come cambiano il contenuto della cache e della memoria.
Teoria: Memoria cacheBlocchi, linee ed etichette; scomposizione dell'indirizzo; associazione diretta, completamente associativa e associativa a insiemi con calcolo dei campi; politiche di rimpiazzo (LRU, FIFO, casuale); politiche di scrittura (write-through, write-back con bit sporco, write-allocate); dimensione del blocco; cache multilivello e separate; come ridurre i miss; quesiti sui campi dell'indirizzo.Memoria cache →. Esercizi analoghi: Esercizio 11 · cache a due vie con rimpiazzo FIFO, Esercizio 12 · campi dell'indirizzo per cache a due vie.
Campi dell'indirizzo e struttura della cache
- Indirizzi di 12 bit (i 12 bit del testo).
- Blocco di 4 B → parola 2 bit.
- Linee: ; a 2 vie → insiemi → set 2 bit.
- Etichetta: bit.
L'indirizzo 0001 0000 0100 è quindi etichetta 00010000, set 01, parola 00. Il blocco che inizia a 104 va nell'insieme (il blocco ha indirizzo e ).
Regole applicate
- FIFO: in un insieme pieno esce la linea caricata per prima, a prescindere dagli accessi successivi (diverso da LRU).
- Write-through: ogni scrittura (hit o miss) scrive anche in memoria: la colonna "memoria" riporta
M[indirizzo] = bytea ognis. - Write allocate: su miss in scrittura prima si carica il blocco dalla memoria (con i valori vecchi), poi si scrive il byte sia nella linea sia in memoria.
- La lettura di un blocco carica tutte e 4 le parole; in tabella si scrivono i 4 byte della linea dopo l'accesso.
Evoluzione
| # | indirizzo | accesso | etichetta | set | parola | esito | linea | contenuto della linea dopo l'accesso | memoria / note |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 104 |
l | 10 | 01 | 0 | miss | 0 | 00 00 00 00 | |
| 2 | 10C |
s 3F | 10 | 11 | 0 | miss | 0 | 3F 42 90 75 | M[10C] = 3F (write allocate: carica A1 42 90 75, scrive 3F) |
| 3 | 10F |
l | 10 | 11 | 3 | hit | 0 | 3F 42 90 75 | stesso blocco di 10C |
| 4 | 10D |
s A9 | 10 | 11 | 1 | hit | 0 | 3F A9 90 75 | M[10D] = A9 |
| 5 | 114 |
l | 11 | 01 | 0 | miss | 1 | 0A 87 03 71 | l'insieme 01 ha ora due linee |
| 6 | 11F |
s 5E | 11 | 11 | 3 | miss | 1 | A1 82 90 5E | M[11F] = 5E (carica A1 82 90 15) |
| 7 | 107 |
s 66 | 10 | 01 | 3 | hit | 0 | 00 00 00 66 | M[107] = 66 |
| 8 | 126 |
l | 12 | 01 | 2 | miss | 0 | E9 16 05 00 | insieme 01 pieno: esce la linea 0 (etichetta 10), la prima caricata |
Esito: 3 hit (accessi 3, 4, 7) e 5 miss.
Dettaglio dell'accesso 8. Nell'insieme 01 ci sono la linea 0 (blocco 104, caricata al passo 1) e la linea 1 (blocco 114, passo 5). Con FIFO esce la linea 0 anche se è stata usata al passo 7: con LRU sarebbe uscita la linea 1. Poiché la politica è write-through, la linea uscente non va riscritta in memoria (la memoria è già aggiornata: M[107] = 66).
Stato finale
| insieme | linea 0 | linea 1 |
|---|---|---|
| 00 | vuota | vuota |
| 01 | etichetta 12: E9 16 05 00 |
etichetta 11: 0A 87 03 71 |
| 10 | vuota | vuota |
| 11 | etichetta 10: 3F A9 90 75 |
etichetta 11: A1 82 90 5E |
Memoria modificata: M[10C] = 3F, M[10D] = A9, M[11F] = 5E, M[107] = 66.
Variante dell'esempio di compitino a.a. 2015-16
Stessa cache (32 B, blocchi da 4 B, 2 vie, FIFO, write-through, write allocate), sequenza 108 l, 10C l, 10F s C9, 10D l, 118 s DD, 11F l, 10B s 67, 125 l e memoria con contenuti leggermente diversi. Con lo stesso procedimento: 3 hit (accessi 3, 4 e 7) e 5 miss (accessi 1, 2, 5, 6 e 8); le scritture portano M[10F] = C9, M[118] = DD, M[10B] = 67. Al passo 8 l'insieme 01 è ancora vuoto, quindi non c'è rimpiazzo.
Verifica con un simulatore
La tabella è stata ottenuta con un breve simulatore che applica le regole sopra (indirizzo, etichetta/insieme/parola, FIFO o LRU, write-through o write-back, write allocate) e riprodotta anche a mano. Ecco il nucleo, per chi vuole rifare la prova su altre sequenze:
def cache(accessi, memoria, byte_cache, blocco, vie, bit_ind=12):
"""Cache write-through con write allocate e rimpiazzo FIFO; accessi = [(indirizzo, 'l'|'s', valore)]."""
insiemi = byte_cache // blocco // vie
righe = {i: [] for i in range(insiemi)} # per ogni insieme: lista in ordine di caricamento (la prima esce)
esiti = []
for a, op, val in accessi:
s, base = (a // blocco) % insiemi, a - a % blocco
et = a // blocco // insiemi
linea = next((l for l in righe[s] if l["et"] == et), None)
hit = linea is not None
if not hit:
if len(righe[s]) == vie:
righe[s].pop(0) # FIFO: esce la più vecchia
linea = {"et": et, "dati": [memoria.get(base + k, 0) for k in range(blocco)]}
righe[s].append(linea)
if op == "s":
linea["dati"][a % blocco] = val
memoria[a] = val # write-through
esiti.append("hit" if hit else "miss")
return esiti, righe
memoria = {}
for ind, byte4 in [(0x100, "08 D0 07 02"), (0x104, "00 00 00 00"), (0x108, "AE 13 A1 23"), (0x10C, "A1 42 90 75"),
(0x110, "BB 16 00 00"), (0x114, "0A 87 03 71"), (0x118, "3E 13 A1 23"), (0x11C, "A1 82 90 15"),
(0x120, "F9 86 A0 00"), (0x124, "E9 16 05 00")]:
for k, b in enumerate(byte4.split()):
memoria[ind + k] = int(b, 16)
accessi = [(0x104, "l", None), (0x10C, "s", 0x3F), (0x10F, "l", None), (0x10D, "s", 0xA9),
(0x114, "l", None), (0x11F, "s", 0x5E), (0x107, "s", 0x66), (0x126, "l", None)]
esiti, righe = cache(accessi, memoria, 32, 4, 2)
print(esiti) # ['miss', 'miss', 'hit', 'hit', 'miss', 'miss', 'hit', 'miss']
print({hex(a): hex(memoria[a]) for a in (0x10C, 0x10D, 0x11F, 0x107)}) # le quattro scritture in memoria
print([[(hex(l["et"]), l["dati"]) for l in righe[s]] for s in range(4)]) # stato finale per insiemeErrori comuni
- Usare LRU invece di FIFO: la linea usata di recente non si salva dal rimpiazzo.
- Dimenticare che il write-through scrive in memoria a ogni
s, anche sugli hit; oppure dimenticare il write allocate (sui miss in scrittura il blocco va prima caricato). - Caricare nella linea soltanto il byte e non tutto il blocco di 4 byte.
- Calcolare l'insieme con i bit sbagliati: i due bit del set sono quelli subito sopra i due bit della parola.
Versione ripasso
Esempio di compito a.a. 2014-15 (e variante a.a. 2015-16): cache da 32 B, blocchi da 4 B, 2 vie, FIFO, write-through, write allocate, indirizzi di 12 bit. Teoria: Memoria cacheBlocchi, linee ed etichette; scomposizione dell'indirizzo; associazione diretta, completamente associativa e associativa a insiemi con calcolo dei campi; politiche di rimpiazzo (LRU, FIFO, casuale); politiche di scrittura (write-through, write-back con bit sporco, write-allocate); dimensione del blocco; cache multilivello e separate; come ridurre i miss; quesiti sui campi dell'indirizzo.Memoria cache →.
Campi: parola 2 bit, linee , insiemi → set 2 bit, etichetta bit.
Regole: FIFO = esce la linea caricata per prima; write-through = ogni s scrive anche in memoria; write allocate = su miss in scrittura si carica il blocco e poi si scrive; si carica sempre l'intero blocco.
Risultati per 104 l, 10C s 3F, 10F l, 10D s A9, 114 l, 11F s 5E, 107 s 66, 126 l:
| # | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|---|
| esito | miss | miss | hit | hit | miss | miss | hit | miss |
3 hit e 5 miss; memoria: M[10C] = 3F, M[10D] = A9, M[11F] = 5E, M[107] = 66. All'accesso 8 l'insieme 01 è pieno e con FIFO esce la linea 0 (blocco 104, la prima caricata) anche se è stata usata di recente; nessuna riscrittura (write-through).
Errori comuni: LRU al posto di FIFO; write-through non applicato agli hit; write allocate dimenticato; solo il byte caricato invece del blocco.