Detailed studies

From NaplesPU Documentation
Revision as of 00:43, 27 September 2017 by Fabio (talk | contribs) (Replacement Chain)
Jump to: navigation, search

This page contains all the experience from the user that have worked on nu+ architecture and want to share all the acquired experiences

Fused multiply-add inside the microarchitecture

Vincenzo

Replacement L2

Introduction

In questo Capitolo si intende mostrare come si svolge la Replacement Chain relativamente alla cache L2, osservando come il Directory Controller evolve per gestire l’occorrenza di tale casistica. Lo scopo principale è quello di testare tutti i casi in cui si verifica un replacement L2, come descritto in figura:

Replcement - MSI

Memory in Directory Controller

Per poter comprendere al meglio come funziona il meccanismo di replacement è necessario in primis valutare come è strutturata la cache amministrata dal Directory Controller. La seguente descrizione rappresenta la configurazione utilizzata per tutti gli esperimenti. Come possiamo osservare dalla figura la cache è costituita da quattro way e 64 set, ogni way contiene al proprio interno un tag e un dato (64 bit).

Cache

Gli indirizzi gestiti sono di 32 bit e sono organizzati come descritto in figura:

Indirizzo

Ogni directory controller può quindi gestire un numero limitato di indirizzi, ad esempio la Tile 0 può gestire gli indirizzi da 0x00000000 a 0x3fffffff, la Tile 1 da 0x4000000 a 0x7fffffff, e così via. Negli esperimenti trattati vengono utilizzate quattro Tile.

Replacement Chain

Per poter causare un replacement è necessario riempire tutte e quattro le way relative ad un determinato set: all’atto dell’inserimento di una nuova entry nello stesso set viene realizzato il replacement. Per una questione di semplicità è necessario scrivere il codice da eseguire direttamente in Assembly all’interno dei kernel utilizzati, per avere un maggiore controllo sulle operazioni effettuate e sugli indirizzi di memoria utilizzati. Per poter stabilire che si sta verificando un replacement è necessario osservare il segnale do replacement. Tale segnale è alto solo se

do_replacement = dc2_message_valid && ((allocate_cache | | update_cache) && !deallocate_cache) && !is_replacement && !dc2_message_cache_hit && dc2_message_cache_valid;

Quindi se il è stata processata una richiesta diversa da un replacement e che non causi la deallocazione di una linea di cache, se non si è verificato un hit all’interno della cache allora sarà necessario eseguire un replacement. Si può notare che l'operazione di replacement si scatena se non c'è una deallocazione della cache, cosa che potrebbe essere contro-intuitiva. In realtà, l’operazione di replacement è gestita in maniera tale da rimpiazzare direttamente la entry LRU con la nuova linea da inserire senza invalidare la linea di cache su cui effettuare il replacement, demandando le operazioni di invalidazione (verso i cache controller) ad una successiva fase. A seguito dell’asserzione del segnale do_replacement si scatena l’enqueue della richiesta di replacement all’interno della relativa coda attraverso il segnale dc3 replacement enqueue, inserendo in tale coda anche il contenuto della linea di cache su cui effettuare il replacement:

dc3_replacement_enqueue                    	= dc2_message_valid && do_replacement;
assign dc3_replacement_request.source          = dc2_message_source,
dc3_replacement_request.memory_address.tag  	= dc2_message_cache_tag,
dc3_replacement_request.memory_address.index  	= dc2_message_address.index,
dc3_replacement_request.memory_address.offset 	= 0,
dc3_replacement_request.data                 	= dc2_message_cache_data,
dc3_replacement_request.state                 	= dc2_message_cache_state,
dc3_replacement_request.sharers_list          	= dc2_message_cache_sharers_list,
dc3_replacement_request.owner                 	= dc2_message_cache_owner;

Si tenga conto che dc2 message address.index contiene l’indice dell’LRU prelevato dallo stadio 2.

Così come descritto all’interno della documentazione del Directory Controller, lo Stage 1 contiene uno scheduler a priorità fissa che comporta la processazione con massima priorità delle replacement request se la condizione can issue replacement request è verificata. Oltre ai soliti segnali lo Stage 1 trasmette allo Stage 2 i segnali:

dc1_replacement_state <= output_replacement_state;
dc1_replacement_sharers_list <= output_replacement_sharers_list;
dc1_replacement_owner <= output_replacement_owner;

Tali segnali vengono inoltrati dallo Stage 2 allo Stage 3. Nello Stato 3, in cui avviene l’effettiva processazione della richiesta, viene effettuato il replacement, così come definito all’interno della Protocol ROM a seconda dello stato in cui ci si trova.

Replacement di una linea nello Stato M

Per poter testare il replacement di un blocco nello stato M e valutare i segnali principali descritti nella relativa documentazione, per quanto rigurda il Directory Controller, è stato costruito il seguente kernel:

if(tile_id==0){	
 asm( 	
  "moveih s20, 0x0000"
  "moveil s20, 0x0000"
  "store32 s21, (s20)"
		
  "moveil s20, 0x1000"
  "store32 s21, (s20)"
  
  "moveil s20, 0x2000"
  "store32 s21, (s20)"	
 );
}else if(tile_id==1){
 asm( 	
  "moveih s20, 0x0000"
  "moveil s20, 0x4000"
  "store32 s21, (s20)"
  
  "moveil s20, 0x8000"
  "store32 s21, (s20)"
 );
}

In questo caso la Tile 0 esegue tre store e la Tile 1 ne esegue 2. Per poter distinguere le diverse richieste si osservi il segnale dc1 message valid in figura, tale segnale è asserito quando lo scheduler a priorità fissa preleva una delle richieste dalla rispettiva coda.

Richieste

Come si può evincere dalla simulazione i messaggi vengono processati dal Directory Controller nel seguente ordine:

  • 1. store della Tile 1 all’indirizzo 0x00004000
  • 2. store della Tile 0 all’indirizzo 0x00000000
  • 3. store della Tile 1 all’indirizzo 0x00008000
  • 4. store della Tile 0 all’indirizzo 0x00001000
  • 5. store della Tile 0 all’indirizzo 0x00002000

Le richieste sono state effettuate in modo tale da appartenere allo stesso set, così da scatenare il replacement.

Date le richieste, la cache è allocata nel seguente modo:

Tabella M

Per ottenere le precedenti informazioni è stato valutato il segnale dc3_update_cache_way, che abilita la scrittura della entry nella L2. Tale segnale dipende direttamente da selected_way, che in caso di hit contiene l’hit_index, in caso contrario l’lru_way (si faccia riferimento alla sezione relativa alla Pseudo LRU).

assign selected way = hit ? hit idx : lru_way;

In alternativa è possibile osservare come evolve il segnale dc1_message_cache_state. Osserviamo in dettaglio cosa succede nel caso di una semplice richiesta:

Dettaglio richiesta 1

Il caricamento nella cache avviene per mezzo del segnale dc3_update_cache_state. Dalla seguente figura è possibile verificare come la entry venga allocata nella way 0, così come descritto in precedenza.

Allocazione nella cache

All’atto della quinta store si ha che la cache L2 si riempie e parte il meccanismo di replacement. Per comprenderne il funzionamento possiamo osservare quali sono i messaggi che dovrebbero essere scambiati in via teorica, per poi ottenere un riscontro pratico:

Scambio messaggi

Dalla successiva figura è possibile osservare che la richiesta viene eseguita e la linea di cache viene inserita al posto della entry indicata dal segnale lru way; possiamo quindi rilevare il segnale do_replacement alto e di conseguenza anche il segnale do_replacement_enqueue), che comporta l’inserimento della richiesta all’interno della replacement queue.

Dettaglio replacement

A questo punto è interessante verificare come si svolge l’operazione di replace all’interno della pipe osservando l’evoluzione dei segnali negli Stage in ordine crescente, quindi:

  • Stage 1: in figura possiamo osservare che la condizione can_issue_replacement_request è soddifatta, quindi viene prelevata la richiesta dalla relativa coda. Tale richiesta è di tipo ’c’, ovvero Replace.

Dettaglio replacement Stage 1

  • Stage 2: la richiesta viene inoltrata allo stage 3, è possibile verificare come la selected_way è proprio pari all’lru_way dato il miss, anche se non verrà utilizzata nello stage 3, perchè viene prelevata la way che accompagna la richiesta;
  • Stage 3: il segnale is_replacement è alto, quindi si tratta effettivamente di un replacement.

I messaggi che vengono inviati a questo punto dipendono dalla Protocol ROM, così come si può osservare dal seguente estratto di codice:

{STATE_M, REPLACEMENT, 1'b?, 1'b?}   : begin // Replacement
 // Send BACKINV To Owner
	
 dpr_output.message_forwarded_send         = 1'b1;
	
 dpr_output.message_forwarded_type         = MESSAGE_BACKINV;
	
 dpr_output.message_forwarded_to_owner     = 1'b1;
	
	
 // Next State MN_A
	
 dpr_output.next_state                     = STATE_MN_A;
	
 dpr_output.next_state_is_stable           = 1'b0;

E` quindi necessario generare i messaggi di invalidation da inviare all’owner della linea di cache rimossa (si osservi il messaggio BACK_INV in figura).

Invio dei messaggi di Invalidation

Un altro modo per valutare i segnali consiste nel porsi ad un più alto livello di dettaglio, analizzando le transazioni attarverso lo scambio di messaggi, raccolti all’interno del log (rappresentato dal file display_coherence.txt).

=======================
Directory Controller - [Time 12810] [TILE 0] - Message Sent
Forwarded Destinations: 0010
Source:       0
Address:      00004000
Requestor:    DCACHE
Packet Type:  BACK_INV
Uncoherent:   0
=======================
Cache Controller - [Time 12890] [TILE 1] [Core 0]
Source:       0
Address:      00004000
Requestor:    DCACHE
Packet Type:  BACK_INV
Uncoherent:   0

Una volta processata tale richiesta viene aggiunta una entry nel TSHR (vedi figura seguente), indicando che il blocco di cache rimosso si trova nello stato 5 (MNA), ovvero in attesa degli INV_ACK.

Allocazione e invalidazione dell’entry nel TSHR

Così come ci si aspetta dall’evoluzione del protocollo negli altri controllori, prima o poi ritroveremo in ingresso allo Stage 1 messaggi di response del tipo ’b’, Last_INV_ACK (dato che si tratta dell’unico owner). Il messaggio Last_INV_ACK corrisponde al WB inviato al Directory Controller, così come visto nella rappresentazione teorica dello scambio messaggi. Una volta ricevuto l’ACK il bit della validità della relativa entry TSHR si abbassa.

Replacement di una linea nello Stato S

Caso 1: Singolo Sharer

Per poter testare il replacement di un blocco nello stato S con un singolo Sharer e valutare i segnali principali descritti nella relativa documentazione, per quanto rigurda il Directory Controller, è stato costruito il seguente kernel:

if(tile_id==0){	
 asm( 	
  "moveih s20, 0x0000"
  "moveil s20, 0x0000"
  "store32 s21, (s20)"

  "moveil s20, 0x1000"
  "store32 s21, (s20)"

  "moveil s20, 0x2000"
  "store32 s21, (s20)"	
 );
}else if(tile_id==1){
 asm( 	
  "moveih s20, 0x0000"
  "moveil s20, 0x4000"
  "load32 s22, (s20)"

  "moveil s20, 0x8000"
  "store32 s21, (s20)"
 );
}

In questo caso la Tile 0 esegue tre store e la Tile 1 esegue una load e una store.

Richieste

Per poter distinguere le diverse richieste si osservi il segnale dc2_message_valid, tale segnale è asserito quando lo scheduler a priorità fissa preleva una delle richieste dalla rispettiva coda. A differenza dell’esempio precendente è stato considerato il segnale dc2_message_valid piuttosto che dc1_message_valid: la scelta di uno dei due segnali è indifferente, dato che il primo è ottenuto direttamente dal secondo attraverso l’utilizzo di un flip-flop. Come si può evincere dalla simulazione i messaggi vengono processati dal Directory Controller nel seguente ordine:

  • 1. load della Tile 1 all’indirizzo 0x00004000
  • 2. store della Tile 0 all’indirizzo 0x00000000
  • 3. store della Tile 1 all’indirizzo 0x00008000
  • 4. store della Tile 0 all’indirizzo 0x00001000
  • 5. store della Tile 0 all’indirizzo 0x00002000

Con la conseguente allocazione all’interno della cache:

Tabella S

Le richieste sono state effettuate in modo tale da appartenere allo stesso set, così da scatenare il replacement. In questo particolare caso può essere interessante osservare come viene gestita la richiesta di load: valutando le seguenti, in cui l’elaborazione della richiesta causa l’allocazione all’interno del TSHR di un’entry (si osservi il segnale tshr_allocate), dato lo stato instabile NSD. Tale stato instabile è necessario per attendere la ricezione dei dati, che comporta il passaggio allo stato S e la deallocazione della relativa entry all’interno del TSHR (si osservi il segnale tshr_deallocate).

Load

Data from Owner

Alla ricezione dell'ultima delle 5 richieste si verifica il replacement: dal punto di vista teorico è possibile osservare in figura il relativo scambio di messaggi.

Scambio messaggi

A questo punto è interessante verificare come si svolge l'operazione di replace, dal punto di vista pratico, all'interno della pipe osservando l'evoluzione dei segnali negli Stage in ordine crescente, quindi:

  • Stage 1: la condizione can_issue_replacement_request è soddifatta, quindi viene prelevata la richiesta dalla relativa coda. Tale richiesta è di tipo 'c', ovvero Replace.

Dettaglio replacement Stage 1

  • Stage 2: la richiesta viene inoltrata allo stage 3, è possibile verificare come la selected way è proprio pari all'lru_way dato il miss, anche se non verrà utilizzata nello stage 3, perché viene prelevata la way che accompagna la richiesta.
  • Stage 3: il segnale is_replacement è alto, quindi si tratta effettivamente di un replacement.

Si osservi in figura il dettaglio della richiesta scatenante il Replacement e il Replacement stesso:

Dettaglio replacement

I messaggi che vengono inviati a questo punto dipendono dalla Protocol ROM, così come si può osservare dal seguente estratto di codice:

{STATE_S, REPLACEMENT, 1'b?, 1'b?}   : begin // Replacement 


// Send BACKINV To Sharers

dpr_output.message_forwarded_send         = 1'b1;

dpr_output.message_forwarded_type         = MESSAGE_BACKINV;

dpr_output.message_forwarded_to_sharers   = 1'b1;


// Send WB To Memory Controller

dpr_output.message_response_send          = 1'b1;

dpr_output.message_response_type          = MESSAGE_WB;

dpr_output.message_response_has_data      = 1'b1;

dpr_output.message_response_to_memory     = 1'b1;


// Next State N

dpr_output.next_state                     = STATE_N;


end

In prima istanza è necessario inviare il messaggio di BACK_INV allo Sharer e il messaggio di WB al Memory Controller:

=======================
Directory Controller - [Time 12810] [TILE 0] - Message Sent
Forwarded Destinations: 0010
Source:       0
Address:      00004000
Requestor:    DCACHE
Packet Type:  BACK_INV
Uncoherent:   0
Response Destinations: 1000
Source:       0
From DC:      1
Address:      00004000
Requestor:    DCACHE
Packet Type:  WB
Data: 		 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Uncoherent:   0
Sharer Count: 1
=======================
Cache Controller - [Time 12890] [TILE 1] [Core 0]
Source:       0
Address:      00004000
Requestor:    DCACHE
Packet Type:  BACK_INV
Uncoherent:   0

A differenza dell'esempio precedente si ha direttamente il passaggio dallo stato S allo stato N.

Caso 2: Multiple Sharers

Per poter testare il replacement di un blocco nello stato S con un singolo Sharer e valutare i segnali principali descritti nella relativa documentazione, per quanto rigurda il Directory Controller, è stato costruito il seguente kernel:

if(tile_id==0){	
 asm( 	"moveih s20, 0x0000"
  "moveil s20, 0x4000"
  "load32 s22, (s20)"
	
  "moveil s20, 0x0000"
  "store32 s21, (s20)"

  "moveil s20, 0x1000"
  "store32 s21, (s20)"

  "moveil s20, 0x2000"
  "store32 s21, (s20)"

 );
}else if(tile_id==1){
 asm( 	"moveih s20, 0x0000"
  "moveil s20, 0x4000"
  "load32 s22, (s20)"

  "moveil s20, 0x8000"
  "store32 s21, (s20)"
 );
}


In questo caso la Tile 0 esegue una load e tre store e la Tile 1 esegue una load e una store.


Richieste

Per poter distinguere le diverse richieste si osservi il segnale dc2_message_valid, tale segnale è asserito quando lo scheduler a priorità fissa preleva una delle richieste dalla rispettiva coda.

Come si può evincere dalla simulazione i messaggi vengono processati dal Directory Controller nel seguente ordine:

  • 1. load della Tile 1 all'indirizzo 0x00004000
  • 2. load della Tile 0 all'indirizzo 0x00004000
  • 3. store della Tile 1 all'indirizzo 0x00008000
  • 4. store della Tile 0 all'indirizzo 0x00000000
  • 5. store della Tile 0 all'indirizzo 0x00001000
  • 6. store della Tile 0 all'indirizzo 0x00002000

Con la conseguente allocazione all'interno della cache:

Tabella S

Le richieste sono state effettuate in modo tale da appartenere allo stesso set, così da scatenare il replacement.

Per i dettagli delle richieste si faccia riferimento all'esempio precedente, dato che l' esempio corrente non aggiunge molto al caso Single Sharer.

Dal punto di vista teorico è interessante osservare i messaggi di BACK_INV destinati ai diversi Sharers:

Scambio messaggi

Ciò è riscontrabile alzando il livello di dettaglio, facendo riferimento al log dei messaggi, rappresentato dal file display_coherence.txt:

=======================
Directory Controller - [Time 13980] [TILE 0] - Message Sent
Forwarded Destinations: 0011
Source:       0
Address:      00004000
Requestor:    DCACHE
Packet Type:  BACK_INV
Uncoherent:   0
Response Destinations: 1000
Source:       0
From DC:      1
Address:      00004000
Requestor:    DCACHE
Packet Type:  WB
Data: 		 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Uncoherent:   0
Sharer Count: 2
=======================
Cache Controller - [Time 14080] [TILE 1] [Core 0]
Source:       0
Address:      00004000
Requestor:    DCACHE
Packet Type:  BACK_INV
Uncoherent:   0
=======================
Cache Controller - [Time 15860] [TILE 0] [Core 0]
Source:       0
Address:      00004000
Requestor:    DCACHE
Packet Type:  BACK_INV
Uncoherent:   0

La differenza principale con il caso Single Sharer si evince nella necessità di dover inviare i messaggi di Invalidation a tutti gli Sharer della linea di cache rimpiazzata.

Replacement di una linea nello Stato I

Per poter testare il replacement di una entry nello stato I contenuto nella cache L2 è stato necessario utilizzare un kernel più complesso, a causa del fatto che la dimensione della cache L1 è uguale a quella della cache L2, per cui è stato necessario utilizzare due diversi Directory Controller.

Utilizzare questo tipo di esperimento, piuttosto che aumentare la dimensione della cache L2, risulta essere più formativo, in quanto è possibile osservare l'utilizzo di due diversi DC per l'elaborazione delle richieste, oltre alla sperimentazione e comprensione dell'algoritmo di PLRU utilizzato. Inoltre, è necessario, come definito nell'introduzione, mantenere la stessa configurazione per tutti gli esperimenti.

Di seguito è riportato il codice utilizzato:

"moveih s20, 0x0000"
"moveil s20, 0x0000"
"store32 s21, (s20)"

"moveil s20, 0x1000"
"load32 s22, (s20)"

"moveil s20, 0x2000"
"load32 s22, (s20)"

"moveil s20, 0x4000"
"load32 s22, (s20)"

"moveih s20, 0x4000"
"moveil s20, 0x0000"
"store32 s21, (s20)"

"moveih s20, 0x0000"
"moveil s20, 0x1000"
"store32 s21, (s20)"

"moveil s20, 0x2000"
"store32 s21, (s20)"

"moveil s20, 0x4000"
"store32 s21, (s20)"

"moveil s20, 0x8000"
"store32 s21, (s20)"

Come si può osservare è stata utilizzata una singola Tile, in quanto si desidera avere il completo controllo relativamente alle richieste giunte al Directory Controller. Questo perché il sistema utilizza un instradamento deterministico ed implica che le richieste arriveranno a destinazione così come sono inviate dal mittente.

Richieste parte 1

Dal codice è possibile notare che vengono generate 9 richieste dalla Tile 0:

  • 1. store all'indirizzo 0x00000000
  • 2. load all'indirizzo 0x00001000
  • 3. load all'indirizzo 0x00002000
  • 4. load all'indirizzo 0x00004000
  • 5. store all'indirizzo 0x4000000
  • 6. store all'indirizzo 0x00001000
  • 7. store all'indirizzo 0x00002000
  • 8. store all'indirizzo 0x00004000
  • 9. store all'indirizzo 0x00008000

Si noti, come definito nella sezione Memory in Directory Controller, che la richiesta 5 è destinata al Directory Controller della Tile 1.

Le prime 4 richieste sono necessarie per riempire la cache L2, così come segue:

Tabella I


Per ottenere un'entry nello stato I è necessario che il Cache Controller, owner della suddetta linea di cache, ne effettui il replacement (L1). Un'ulteriore richiesta al DC causerebbe il replacement di una delle linee a livello L2, allora per poter scatenare il tutto il Cache Controller della Tile 0 effettuerà una richiesta al Directory Controller della Tile 1 (richiesta 5).

Per poter verificare la richiesta 5 possiamo passare ad un più alto livello di astrazione consultando il message log:

=======================
Cache Controller - [Time 13700] [TILE 0] [Core 0] - Message Request Sent
Directory Destinations: 1
Source:       0
Address:      40000000
Packet Type:  GETM
Data: 		 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
=======================
Directory Controller - [Time 13780] [TILE 1] - Message Received
Source:       0
Address:      40000000
Packet Type:  GETM
Data: 		 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000


Si osservi anche la relativa PUTM (richiesta di tipo 3) ricevuta dal Directory Controller della Tile 0 in seguito al replacement a livello L1, sia in figura \ref{fig:putm}, che nell'estratto del message log.

Ricezione della PUT M

=======================
Cache Controller - [Time 14470] [TILE 0] [Core 0] - Message Request Sent
Directory Destinations: 0
Source:       0
Address:      00000000
Packet Type:  PUTM
Data: 		 44618020820180007600001411018640606403206164000060600330616000007608006820f3d00082f40000040000c04b0c2010600002e061000000xxxxxxxx
=======================
Directory Controller - [Time 14610] [TILE 0] - Message Received
Source:       0
Address:      00000000
Packet Type:  PUTM
Data: 		 44618020820180007600001411018640606403206164000060600330616000007608006820f3d00082f40000040000c04b0c2010600002e061000000xxxxxxxx
=======================
Directory Controller - [Time 14630] [TILE 0] - Message Sent
Response Destinations: 0001
Source:       0
From DC:      1
Address:      00000000
Requestor:    DCACHE
Packet Type:  PUT_ACK
Data: 		 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Uncoherent:   0
Sharer Count: 0

Dall'immagine seguente possiamo osservare mediante il segnale dc1_message_cache_state (contenente lo stato delle linee di cache) come evolve lo stato della cache, si noti che con lo stato 3 si intende lo stato "I":

Cambiamento di stato relativo alla PUT M

Le richieste 6, 7, 8, rappresentate in figura sono necessarie al fine di far coincidere la selected_way con la way contenente le linea di cache nello stato I, dato che essa non è più la lru.

Richieste parte 2

Le richieste modificano lo stato della entry LRU così come segue:

Tabella lru

Nella seguente figura è riportato un esempio di come avviene il cambiamento di stato da S (2) a M (1) a seguito di una richiesta per la relativa entry, con la conseguente evoluzione del segnale lru_way:

Esempio di cambiamento di stato nella Cache L2

A questo punto la richiesta 9 genera il replacement:

Tabella I2

Dal punto di vista teorico è possibile osservare il scambio di messaggi (vedi figura seguente), che in questo caso risulta essere molto più semplice, dato che il blocco è posseduto dal solo Directory Controller.

Scambio messaggi


A questo punto è interessante verificare come si svolge l'operazione di replace, nel dettaglio, all'interno della pipe osservando l'evoluzione dei segnali negli Stage in ordine crescente, quindi:

  • Stage 1: nella figura riportata di seguito, si può osservare che la condizione can_issue_replacement_request è soddifatta, quindi viene prelevata la richiesta dalla relativa coda. Tale richiesta è di tipo 'c', ovvero Replace.

Dettaglio Replacement Stage1

  • Stage 2: la richiesta viene inoltrata allo stage 3, è possibile verificare come la selected way è proprio pari all'lru_way dato il miss, anche se non verrà utilizzata nello stage 3, perché viene prelevata la way che accompagna la richiesta.
  • Stage 3: il segnale is_replacement è alto, quindi si tratta effettivamente di un replacement.

Si osservi in figura il dettaglio della richiesta scatenante il Replacement e del Replacement stesso:

Richiesta causa del replacement

Nella figura riportata di seguito è possibile osservare in dettaglio il cambiamento di stato relativo alla entry nello stato I nello Stage 1.

elaborazione della richiesta di replacement

Così come specificato dalla protocol ROM essa genera una WB al Memory controller:


{STATE_I, REPLACEMENT, 1'b?, 1'b?}   : begin // Replacement


// Send WB To Memory Controller

dpr_output.message_response_send          = 1'b1;

dpr_output.message_response_type          = MESSAGE_WB;

dpr_output.message_response_has_data      = 1'b1;

dpr_output.message_response_to_memory     = 1'b1;


// Next State N

dpr_output.next_state                     = STATE_N;

end

Ciò è riscontrabile anche alzando il livello di dettaglio, facendo riferimento al log dei messaggi, rappresentato dal file display_coherence.txt:

=======================
Directory Controller - [Time 15940] [TILE 0] - Message Sent
Response Destinations: 1000
Source:       0
From DC:      1
Address:      00000000
Requestor:    DCACHE
Packet Type:  WB
Data: 		 618020820180007600001411018640606403206164000060600330616000007608006820f3d00082f40000040000c04b0c2010600002e061000000xxxxxxxx
Uncoherent:   0
Sharer Count: 0
=======================
Memory Controller - [Time 16360] [TILE 3] - Message Received
Source:       0
From DC:      1
Address:      00000000
Requestor:    DCACHE
Packet Type:  WB
Data: 		 618020820180007600001411018640606403206164000060600330616000007608006820f3d00082f40000040000c04b0c2010600002e061000000xxxxxxxx
Uncoherent:   0
Sharer Count: 0

Replacement negli stati instabili

È importante notare che non è possibile testare gli stati instabili. Questo è dovuto alla osservazione della struttura del directory controller. Per poter evadere un replacement, la richiesta deve essere portata in ingresso al controllore tramite un buffer di riciclo, ma dato che nella cache sono conservati solo stati stabili (a parte N) è impossibile valutare stati diversi da quelli stabili.