Salta al contenuto
Note per Studenti Esercizio 21 · cache a due vie FIFO con write-through

Esercizio 21cache a due vie FIFO con write-through

Esame
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: 32/4=832 / 4 = 8; a 2 vie → 8/2=48 / 2 = 4 insiemi → set 2 bit.
  • Etichetta: 12−2−2=812 - 2 - 2 = 8 bit.

L'indirizzo 0001 0000 0100 è quindi etichetta 00010000, set 01, parola 00. Il blocco che inizia a 104 va nell'insieme 0101 (il blocco ha indirizzo 0x104/4=650x104 / 4 = 65 e 65 mod 4=165 \bmod 4 = 1).

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] = byte a ogni s.
  • 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:

python
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 insieme

Errori 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 32/4=832/4 = 8, insiemi 8/2=48/2 = 4 → set 2 bit, etichetta 12−2−2=812 - 2 - 2 = 8 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.

Esercizi su questo argomento

Teoria collegata