Progetto di Calcolatori Elettronici M Prof. Giovanni Neri Prof. Stefano Mattoccia Progetto di Calcolatori Elettronici M Realizzato da: Simone Berardi Daniele Di Donato Isabella Gottardi Stefano Poli
Introduzione Lo Scenario Il Protocollo MESI Protocollo di contesa a bus Uno sguardo al Progetto
Introduzione L’obbiettivo presentato all’inizio del progetto era la creazione si un controllore di memoria tramite l’utilizzo di FPGA opportunamente programmate tramite software Xilinx. Questo componente doveva garantire l’integrità di dati presenti in una memoria centrale comune a più processori muniti di diversi livelli di cache.
Lo Scenario Nel dettaglio il nostro progetto si basava su di una visione ben specifica di sistema. L’ambiente comprendeva due processori in grado di lavorare contemporaneamente con una stessa memoria centrale comune entrambi dotati di due livelli di memoria cache. Tutte le ipotesi formulate sono state virtualizzate tramite ambiente Xilinx.
Lo Scenario
Un interfaccia verso il bus Partendo dall’idea di riutilizzare alcuni componenti che lavorano in sistemi con singolo master, abbiamo definito un interfaccia tramite la quale questi componenti potessero accedere alle risorse senza “accorgersi” della natura condivisa di quest’ultime. Abbiamo quindi definito un interfaccia che si connettesse in modo naturale ai componenti già presenti come la cache e il DLX.
Un interfaccia verso il bus
Un interfaccia verso il bus La CPU e le Cache accedono in modo trasparente alle risorse come se fossero a loro dedicate. Il Controller della cpu fornisce un interfaccia tramite cui i componenti accedono come se stessero accedendo al bus ed alla memoria. Inoltre il controller controlla e gestisce la coerenza all’interno delle cache presenti.
La Coerenza Un aspetto fondamentale di tutto il progetto era incapsulato dal concetto di coerenza interna ai due processori nonché di coerenza a livello di sistema multiprocessore. La soluzione adottato fin dalla fase di progetto è stata quella di un protocollo MESI per garantire tale proprietà all’intero sistema virtuale.
Il Protocollo Mesi Il protocollo sfruttato all’interno del progetto si basa sulla discriminazione della validità, in termini di aggiornamenti disponibili, dei dati presenti nelle cache dei due processori. Ogni dato è pertanto etichettato con uno stato che identifica il suo livello di “freschezza” riferita all’intero sistema multiprocessore.
Il Protocollo Mesi Gli stati possibili sono quattro: Modified: indica l’avvenuta modifica della linea di cache in una sua parte; Exclusive: legato al concetto di livelli multipli di memoria cache indica nello specifico la concordanza tra la linea corrente e quella presente nel livello inferiore (verso la memoria centrale) che può a sua volta risultare modificata rispetto ad un livello successivo; Shared: in parte sfruttato nel contesto di livelli multipli di cache ma soprattutto utilizzato nel caso di processori multipli garantisce la coerenza tra la linea corrente e quella nel livello successivo, nel caso in cui la linea si trovi subito sopra alla memoria centrale (RAM) questo stato garantisce la coerenza dei dati con tutte le linee identiche caricate da parte di altri processori nello stesso sistema; Invalid: utilizzato in presenza di processori multipli indica la presenza di dati non più aggiornati poiché modificati da una cpu presente nel sistema; in caso la linea sia necessaria in un secondo momento al processore, la cache dovrà provvedere a reperirli nuovamente aggiornati dalla memoria centrale.
Il Protocollo Mesi – Caso Di Studio Il progetto nello specifico interessa una particolare configurazione di riferimento del protocollo MESI in presenza, per l’appunto, di processori multipli.
Il Protocollo Mesi – Caso Di Studio Il progetto nello specifico interessa una particolare configurazione di riferimento del protocollo MESI in presenza, per l’appunto, di processori multipli. In figura sono presenti tutte le possibili configurazioni dello stato allegato a due eventuali linee di cache. Queste linee sono presenti in livelli differenti della stessa cache presupponendo la presenza di un altri processori. L1 identifica il primo livello di cache mentre L2 identifica il secondo livello di cache (a valle).
Il Protocollo Mesi – Visione Generale Le transizioni previste dal protocollo MESI implementato a qualunque livello, mono o multi processore prevede il seguente “grafo delle transizioni”. L’immagine evidenzia tutte i passaggi corretti fra gli stati possibili delle linee presenti in una qualunque delle cache.
Protocollo di Contesa a Bus Gestisce l’accesso contemporaneo della risorsa bus Il protocollo utilizzato è di tipo request- grant, implementato modificando la modalità base del Pentium in configurazione master-slave
Dominare La Complessità L’approccio adottato nella soluzione è stato rappresentato in una divisione in parti di ambiente virtuale (due processori con doppio livello di cache) e soluzione alla problematica (controllore di memoria). Questa soluzione offre il vantaggio della modularità e della ridotta complessità delle parti singolarmente esaminate e sintetizzate.
Le Cache Uno degli obbiettivi secondari è stato rappresentato dalla resa modulare di un componente prelevato da una presentazione di alcuni nostri colleghi : la “Cache DLK”. Aggiungere un secondo livello di cache e rendere i due moduli interagenti ha comportatolo smussamento di alcuni punti principali. Le attività di “re-factoring” hanno portato sostanzialmente all’aggiunta di alcuni segnali di comodo per la gestione multilivello della cache.
Le Cache Nello specifico si sono rese necessarie due attività di re-factoring: È stato installato un segnale aggiuntivo in grado di indicare la fine di una risposta ad un’operazione di snoop così da poter sequenzializzare più operazioni di questo tipo; È stato esplicitato il protocollo adottato dalla cache di secondo livello per effettuare un caricamento dalla memoria principale per adeguare così anche il primo livello di cache alle stesse convenzioni.
Il Sequencer In presenza di una cache di secondo livello si è subito posta la problematica di effettuare letture multiple atte al caricamento di una linea dalla memoria centrale. Il componente effettua una serie di letture allineate alla dimensione delle linee della cache di primo livello in modo da caricare completamente la parte di memoria necessaria alla cache di secondo livello.
I Controller Componente principe del lavoro svolto che racchiude in se tutta la logica di applicazione del protocollo MESI per rendere coerente tutto l’ambiente di lavoro. La progettazione di questo componente ha richiesto una ulteriore suddivisione in sottoparti: due nello specifico.
Cpu Controller La prima funge da substrato per la ogni cpu che diventa capace di gestire in modo formale le richieste del bus condiviso di dati, effettuare richieste di snoop ad una terza parte per suo conto in lettura e scrittura ed infine di garantire una risposta efficace allo snoop stesso effettuato a suo carico.
Memory Controller La seconda parte è carica di tutta la logica necessaria alla risoluzione di conflitti in operazioni in lettura e scrittura veri e propri; la dicotomia tra meccanismi e politiche assume in questa scelta la sua valenza più ampia separando la parte di substrato alla cpu dalla parte del componente incaricato di gestire i conflitti tra le diverse richieste dei processori.
Una Visione Panoramica Nel complesso l’intuizione alla base della soluzione implementata è racchiusa nella divisione modulare dei componenti in grado di interfacciarsi per ottenere un risultato finale perfettamente sincronizzato e coerente.
Descrizione dei componenti RandomNumberGenerator_32Bit Sequencer Dummymemory Cpucontroller Memorycontroller Cache_cmp _2 Cache_2_livelli Cache_with_Sequencer Cpu
RandomNumberGenerator_32Bit Genera numeri casuali a 32 bit con lo scopo di simulare dati letti e scritti dal processore da e verso le cache e la memoria. Utilizzato all’interno del componente DummyMemory Registro a scorrimento retroazionato con xor modulo 2
RNGenerator_32Bit : Segnali RESET : in std_logic ⇒ segnale di reset del componente ENABLE : in STD_LOGIC ⇒ segnale di attivazione del componente CLK : in STD_LOGIC ⇒ clock signal sr: std_logic_vector(31 downto 0) := x”1045ACE1” ⇒ registro a scorrimento inizializzato con un seme scelto a caso signal sr_in: std_logic ⇒ bit inserito nel registro a scorrimento U : out std_logic_vector(31 downto 0) ⇒ bus a 32 bit che consente di trasferire il dato generato
RNGenerator_32Bit: Processo Unico processo del componente Se il componente è abilitato (ENABLE=1), ad ogni fronte di salita del clock: shift del registro (sr) immissione del nuovo bit nel registro abilitazione dell’uscita collegandovi sr
RNGenerator_32Bit : Calcolo del bit da reinserire Concorrentemente al precedente processo viene calcolato il bit da inserire nel registro tramite la formula sr_in <= sr(9) xor (sr(29) xor (sr(30) xor sr(31)))
Sequencer: Schema architettura Linee da 128 byte Sequenzializza le operazioni di read/write da e verso le cache Bus a 128 byte Bus a 4 byte 32 cicli di bus per operazioni di lettura/scrittura
Segnali di Input/Output Wr_in : in STD_LOGIC ⇒ segnale di scrittura dei dati fornita dalla cache per trasferimenti cache => memoria DataLineIn : in data_line_2 ⇒ dati in ingresso dalla cache di dimensione pari ad una linea di cache di livello 2 (128 byte) Rd_in : in STD_LOGIC ⇒ segnale di lettura dei dati fornita dalla cache per trasferimenti memoria-cache Ready_from_2_level : in STD_LOGIC ⇒ segnale di ready ricevuto dalla memoria, utilizzato per sequenzializzare le operazioni DataIn_2_level : in STD_LOGIC_VECTOR (dataOutParallelism-1 downto 0) ⇒ dati in ingresso dalla memoria con parallelismo a 32 bit Reset : in STD_LOGIC ⇒ segnale di reset del componente AddressIn : in STD_LOGIC_VECTOR (PARALLELISM-1 downto 0) ⇒ indirizzo da sequenzializzare Enable : in STD_LOGIC ⇒ segnale di abilitazione del componente AddressOut_2_level : out std_logic_vector(PARALLELISM-1 downto 0) ⇒ indirizzo in uscita per la memoria Ready : out std_logic ⇒ segnale di ready verso la cache di secondo livello DataLineOut : out data_line_2 ⇒ linea di cache in uscita per la cache di secondo livello (una volta caricata) Wr_out_2_level : out std_logic ⇒ segnale di write in uscita verso la memoria DataOut_2_level : out std_logic_vector(dataParallelism-1 downto 0) ⇒ dati in uscita per la memoria con parallelismo a 32 bit Rd_out_2_level : out std_logic ⇒ segnale di read in uscita verso la memoria
Processi Processi “accessori” inizializza variabili interne per la sincronizzazione delle operazioni aggiorna il segnale di ready ad ogni clock Operazione di scrittura (cache - memoria) inizializza le variabili interne necessarie al trasferimento cache - memoria effettua i cicli di scrittura per trasferire l’intera linea di cache in memoria Operazione di lettura (memoria - cache) inizializza le variabili interne necessarie al trasferimento memoria - cache effettua cicli di lettura per trasferire l’intera linea di cache dalla memoria
Operazioni e processi Write (cache => memoria), processi in gioco: SplitProcess_Write WriteLoop Read (memoria => cache), processi in gioco: SplitProcess_Read ReadLoop
SplitProcess_Write “Prepara” il componente all’esecuzione della reale operazione di trasferimento dell’intera linea dalla cache alla memoria Attivato al variare dei segnali Enable, Wr_in, Rd_in o Reset Disattiva il ready Setta variabili e segnali interni (loopEnabled_var, loopIndex, InAddress, toSplitRegister, tempDataLine)
WriteLoop Effettua le reali operazioni di scrittura dalla cache alla memoria Pilota write, bus indirizzi e bus dati della memoria Effettua 32 cicli di scrittura (ognuno da 4 byte) per trasferire l’intera linea di cache da 128 byte Attivato al variare dei segnali Ready_From_2_level, Wr_in, Rd_in o Reset
SplitProcess_Read “Prepara” il componente all’esecuzione della reale operazione di trasferimento dell’intera linea dalla memoria alla cache Attivato al variare dei segnali Enable, Wr_in, Rd_in o Reset Disattiva il ready Setta variabili e segnali interni (loopEnabled_var, loopIndex, InAddress)
ReadLoop Effettua le reali operazioni di lettura dalla memoria alla cache Pilota read, bus indirizzi e bus dati della memoria Effettua 32 cicli di lettura (ognuno da 4 byte) per trasferire l’intera linea di cache da 128 byte Attivato al variare dei segnali Ready_From_2_level, Wr_in, Rd_in o Reset Registro tempDataLine che svolge il ruolo di “deposito” di dati in attesa del completamento dell’intera linea di cache
DummyMemory Memoria fittizia per le operazioni di read/write da parte della cpu Per le operazioni di read utilizza un generatore di numeri casuali (RandomNumberGenerator_32Bit) Le operazioni di write non vengono realmente eseguite
Segnali di input/output chipEnable : in STD_LOGIC ⇒ segnale di abilitazione della memoria MemWr : in STD_LOGIC ⇒ segnale che se asserito indica una scrittura in memoria MemRd : in STD_LOGIC ⇒ segnale che se asserito indica una lettura dalla memoria CLK : in STD_LOGIC ⇒ clock InputAddress : in STD_LOGIC_VECTOR (addressParallelism-1 downto 0) ⇒ bus degli indirizzi Ready : out STD_LOGIC ⇒ segnale di ready signal temp_dataout : STD_LOGIC_VECTOR (dataParallelism-1 downto 0) ⇒ contiene il numero casuale generato dal RandomNumberGenerator_32Bit DataInOut : inout STD_LOGIC_VECTOR (dataParallelism-1 downto 0) ⇒ dati in ingresso/uscita
ProcessoMemoria Unico processo del componente Riceve e risponde alle richieste di read/write provenienti dalla cpu Utilizza il generatore di numeri casuali RandomNumberGenerator_32Bit
L’uscita del generatore viene collegata all’uscita della DummyMemory Lettura di un dato Il segnale di ingresso MemRd viene collegato al clock del generatore di numeri casuali L’uscita del generatore viene collegata all’uscita della DummyMemory
Scrittura di un dato L’operazione di write non viene realmente eseguita Alza il segnale di Ready
CpuController Il CpuController rappresenta l’interfaccia verso l’esterno per i vari componenti Gestisce il lato client del protocollo di gestione per l’accesso ai bus esterni. Gestione delle operazioni di snoop verso le cache interne.
Interfacciamento con i componenti interni alla cpu DLX CPU_CONTROLLER MemWr_from_cpu ch_memwr Il cpuController necessita di conoscere se l’operazione in corso è di lettura o scrittura per poter eseguire delle operazioni coerenti al protocollo mesi.
Interfacciamento con i componenti interni alla cpu CACHE L1 – L2 CPU_CONTROLLER Ram_Address Ram_data_out Ram_data_in Ram_we Ram_oe Ram_ready ch_hit_1 ch_hit_2 ch_hitm_1 ch_hitm_2 ch_inv_1 ch_inv_2 ch_eads ch_wtwb_2 ch_snoop_addr transaction_complete Address_from_cache Data_from_cache Data_to_cache WriteBack_from_cache MemRd_from_cache Ready_to_cache Hit_1 Hit_2 HITM_1 HITM_2 invalidate_to_cache EADS_to_cache WbWt_2 snoop_address I segnali inviati dalle Cache e che normalmente sarebbero diretti alle memorie vengono intercettati dall’interfaccia del cpu_controller.
Interfacciamento con i componenti esterni alla cpu CPU_CONTROLLER MEMORY_CONTROLLER BReq BGrnt Eads_from_controller Invalidate_out invalidate Hit HITM WbWt Restart_op snoop_address_in Address MemRd MemWr Breq[ ] BGrnt[ ] Eads Invalidate_in Invalidate Hit[ ] Hitm[ ] WbWt[ ] Restart_op[ ] snoop_addr[] Address_for_snoop Il cpuController si collega al MemoryControll er per gestire tutte le operazioni del protocollo Mesi
Interfacciamento con i componenti esterni alla cpu L’interfaccia mento con la memoria rappresenta il collegamento della cpu con la risorsa condivisa. La cpu potrà leggere o scrivere solo quando le sarà concesso. CPU_CONTROLLER MEMORY MemRd MemWr Address DataInOut Ready InputAddress
transaction_complete : in STD_LOGIC segnale di completamento del trasferimento dalla cache alla memoria e viceversa. Attivato al termine dall’esterno al termine del trasferimento di una linea di livello2 Segnali di input Address_from_cache: in STD_LOGIC_VECTOR (PARALLELISM-1 downto 0) indirizzo richiesto dalla cache in lettura o scrittura Ready_from_mem: in STD_LOGIC segnali di ready dalla memoria, verrà propagato direttamente alla cache BGrnt : in STD_LOGIC segnale di Bus Grant per l'utilizzo del Bus MemRd_from_cache: in STD_LOGIC segnale di lettura proveniente dalla cache snoop_address_in: in STD_LOGIC_VECTOR(PARALLELISM-1 downto 0) indirizzo di snoop in ingresso WriteBack_from_cache: in STD_lOGIC segnale di scrittura a causa di un writeBack. (unico caso in cui la cache emette un segnale di Wr) MemWr_from_cpu: in STD_LOGIC segnale di scrittura da parte della memoria, utilizzato per invalidare le altre cache Invalidate : in STD_LOGIC segnale in ingresso per indicare di invalidare i dati trovate dallo snoop HITM_2: in STD_LOGIC hitm dalla seconda cache
Segnali di input HITM_1: in STD_LOGIC hitm dalla prima cache Eads : in STD_LOGIC ingresso del segnale eads esterno proveniente dal memory controller Hit_2 :in STD_LOGIC hit dalla seconda cache WbWt: in STD_LOGIC indica lo stato in cui portare la linea in caricamento Reset : in STD_LOGIC segnale di reset Data_from_cache : in STD_LOGIC_VECTOR( dataparallelism-1 downto 0) dati dalla cache in caso di scrittura Hit_1 : in STD_LOGIC hit dalla prima cache
Inv_to_others_cpu: out STD_LOGIC segnale inviato al memory controller nel caso di scritture con propagazione per fare invalidare le cache degli altri processori Segnali di output HITM: out STD_LOGIC segnale inviato a seguito di uno snoop in ingresso MemWr: out STD_LOGIC segnale di scrittura verso la memoria (propaga quello della cache - segnale in input WriteBack_from_cache) Ready_to_cache: out STD_LOGIC Þ segnali di ready per la cache MemRd : out STD_LOGIC segnale di lettura verso la memoria (propaga quello della cache - segnale in input MemRd_from_cache) BReq : out STD_LOGIC segnale di richiesta del bus AddressOut : out STD_LOGIC_VECTOR (PARALLELISM-1 downto 0) indirizzo in uscita verso la memoria snoop_address: out STD_LOGIC_VECTOR(PARALLELISM-1 downto 0) indirizzo di snoop da inviare alle cache
Data_to_cache : out STD_LOGIC_VECTOR (dataparallelism-1 downto 0) Dati in uscita per la cache WbWt_2 : out STD_LOGIC segnale per indicare lo stato finale della linea di secondo livello al caricamento Segnali di output inv_to_cache : out STD_LOGIC segnale di invalidazione per le cache (propaga quello del MemoryController - segnale in input Invalidate) HIT: out STD_LOGIC segnale inviato a seguito di uno snoop in ingresso EADS_to_cache: out STD_LOGIC segnale di EADS per le cache (propaga il segnale inviato dal MemoryController - segnale in input EADS) DataInOut : inout STD_LOGIC_VECTOR(dataparallelism-1 downto 0) dati da/per la memoria
Gestione protocollo di Accesso Arbitraggio lato client l’accesso al bus dati, al bus indirizzi ed ai segnali di controllo della memoria. Adattamento dei segnali provenienti dalle cache ai segnali di protocollo utilizzati.
ProcessoRichiestaBus Il processo si comporta da “245” per i segnali provenienti da e verso le cache il cui segnale di abilitazione è dato dal segnale BGrnt inviato dal memory controller. Conforma la semantica dei segnali a quella richiesta dal memory controller per gestire correttamente la coerenza del protocollo Mesi.
Gestione protocollo di Accesso Indirizzo Operazione Dati CPU CONTROLLER Breq Indirizzo Operazione Dati BGrnt
Gestione snoop Il componente Cpu Controller si occupa della gestione dello snoop a livello di processore Provvede l’invio dei segnali di snoop ricevuti dal MemoryController verso le cache Fornisce le risposte alle richieste di snoop.
Gestione snoop I processi che gestiscono le problematiche di snoop sono: ProcessoRispostaASnoop ProcessoSnoopEsterno
ProcessoSnoopEsterno Gestisce la propagazione verso le cache dei segnali di snoop Invia i segnali di Eads ed Invalidate alle cache. Invia l’indirizzo di snoop alle cache.
ProcessoRispostaASnoop Il processo si occupa di gestire le risposte allo snoop ricevute dalle due cache. Fa confluire i segnali Hit ed Hitm generati dalle due cache in due segnali Hit ed Hitm inviati al memory controller.
Hit_1 Hit_2 Hitm_1 Hitm_2 Snoop Address CPU CONTROLLER Eads Invalidate Hit Hitm Eads Invalidate Snoop Address
MemoryController Gestisce la parte server del protocollo di accesso al bus da parte dei processori Viene utilizata la politica a priorità rotanti Altra problematica gestita è l’attivazione dello snoop verso gli altri processori durante le operazioni di lettura e scrittura del processore che possiede il BGrnt
HitM : in STD_LOGIC_VECTOR (cpuNumber-1 downto 0) indica all’esterno se il ciclo di snoop ha trovato il dato richiesto all’interno di una delle, ma tale dato è stato ivi modificato Segnali di Input Ready_from_mem: in STD_LOGIC segnali di ready proveniente dalla memoria Address_for_snoop: in STD_LOGIC_VECTOR(addressParallelism-1 downto 0) indirizzo di snoop da propagare verso le altre cpu BReq : in STD_LOGIC_VECTOR (cpuNumber-1 downto 0) nei sistemi multiprocessore, è utilizzato per segnalare al controllore di memoria la necessità di avere il controllo del bus BOff : in STD_LOGIC Þ segnale di input, obbliga il processore ad abortire il ciclo di bus in corso e a porsi in 3‐state nei confronti del bus fino alla disattivazione del segnale Reset: in STD_LOGIC segnale di reset del dispositivo Hit : in STD_LOGIC_VECTOR (cpuNumber-1 downto 0) indica all’esterno se il ciclo di snoop ha trovato il dato richiesto all’interno di una cache Invalidate_in: in STD_LOGIC_VECTOR (cpuNumber-1 downto 0) segnale di richiesta invalidazione da parte della cpu master MemRD: in STD_LOGIC_VECTOR (cpuNumber-1 downto 0) segnali di Lettura dalle cpu MemWR : in STD_LOGIC_VECTOR (cpuNumber-1 downto 0) segnali di scrittura dalle cpu
Segnali di Output EAds : out STD_LOGIC External ADdress Strobe. Segnale utilizzato dai controllori di memoria per verificare se il dato il cui indirizzo è pilotato sul bus address è in cache al processore snoop_addr: out STD_LOGIC_VECTOR(addressParallelism-1 downto 0) indirizzo di snoop in uscita verso le altre cpu Invalidate: out STD_LOGIC determina lo stato finale di una linea di cache dopo uno snoop BGrnt : out STD_LOGIC_VECTOR (cpuNumber-1 downto 0) segnali di permesso accesso al bus Restart_op: out std_logic_vector(cpuNumber-1 downto 0) segnale di restart dell'operazione per la cpu master in caso di writeBack WbWt : out STD_LOGIC_VECTOR (cpuNumber-1 downto 0) utilizzato per la gestione del protocollo MESI, consente di definire, per ogni linea di cache, il tipo di politica di scrittura (Write Back o Write Through).
Processi Il componente è costituito da quattro processi: Processo di aggiornamento del BGrnt alla cpu attualmente master Processo di risoluzione conflitti per l'accesso al bus Processo Attivazione dello snoop Processo che attende l'attivarsi dei segnali Hit ed Hitm da parte delle varie cpu
ProcessoAggiornamentoBGrnt Si occupa dell’aggiornamento del bus grant Viene risvegliato quando una Cpu fa richiesta del bus Se è già occupato non posso assegnarlo Se è libero allora lo assegno e aggiorno che la cpu che ha fatto richiesta ora è la master
ProcessoRichiestaBus E’ possibile che durante l’esecuzione più processori richiedano il bus contemporaneamente La politica delle priorità applicata è rotazione, l’ultimo processore che ha ottenuto il bus viene inserito in coda ottenendo la priorità più bassa Se il bus non è occupato procedo all’assegnazione scorrendo la lista delle cpu
ProcessoAttivazioneSnoop Si occupa di attivare i segnali per lo snoop dell’indirizzo di ogni linea di cache di secondo livello che deve essere trasferita I segnali sono inviati alle cpu che non hanno il possesso del bus (non hanno assegnato il bus grant)
ProcessoRilevazioneEsitiSnoop Si occupa di verificare ciclicamente quali sono gli esiti degli snoop attivati. Due casi: Una cpu ha la linea modificata Nessuna cpu ha la linea modificata Se la linea è presente in un’altra cache verrà caricata in stato shared Altrimenti in stato Exclusive
Cache_2_livelli Unisce i componenti Cache_cmp e Cache_cmp_2 in un'unica entità Questo permette un accesso da parte della cpu alla cache in modo del tutto trasparente Per risolvere problematiche di coerenza del protocollo Mesi vengono eseguiti snoop consecutivi alla cache di primo livello ed infine a quella di secondo livello
Altri componenti Cache_cmp_2 Cache_with_sequencer Cpu è un evoluzione del componente Cache_cmp, sviluppato nel progetto Cache_dlx la differenza risiede solamente nella dimensione delle linee memorizzate e trasferite verso l’esterno Cache_with_sequencer unisce la Cache_2_livelli al component Sequencer per eseguire trasferimenti di linee di cache di secondo livello in modo sequenziale in base al parallelismo del bus dati del processore Cpu contiene tutte le componenti sopracitate con l’aggiunta del controller della CPU (CPU Controller) fornisce l’interfaccia di ingresso da parte della pipeline e l’interfaccia d’uscita verso i bus dati.
TestBench Caso Monoprocessore Caso Multiprocessore
Testbench Monoprocessore Nelle slide successive sono riportati i testbench eseguiti per i seguenti casi di interesse in un sistema monoprocessore. Mono processore: Lettura di un dato non presente in Cache L1 e Cache L2 Lettura di un dato non presente in Cache L1 e presente in Cache L2 in stato Exclusive o Modified. Scrittura con dato presente in Cache L1. Scrittura con dato non presente in Cache L1 o in entrambe.
Lettura di un dato non presente in Cache L1 e Cache L2 La lettura di un dato non presente all’interno delle cache genera una richiesta di trasferimento per il Cpu Controller. La linea di cache viene quindi caricata dalla memoria non appena la cpu riceve il diritto di accesso ai bus.
Lettura di un dato non presente in Cache L1 e Cache L2 La lettura della linea viene sequenzializza ta dal sequencer. Le linee saranno caricate in stato Shared per la cache L1 e Exclusive per la cache L2
Lettura di un dato non presente in Cache L1 e presente in Cache L2 in stato Exclusive o Modified. In questo caso la linea della cache L1 può assumere due stati in base allo stato della linea della cache L2 Caso 1: se la linea della cache L2 è presente in stato Exclusive o Shared la linea di livello 1 sarà caricata in stato Shared Caso 2: se la linea della cache L2 è presente in stato Modified la linea di livello 1 sarà caricata in stato Exclusive
Scrittura con dato presente in Cache L1. La scrittura di un dato presente in cache L1 in stato Shared produce una scrittura nella cache L2. Ciò porterà ad avere la cache L1 in stato exclusive mentre la cache L2 verrà portata in stato Modified. Diversamente se la linea è presente nella cache L1 in stato Exclusive, questa verrà portata in stato Modified senza scrittura a valle
Scrittura con dato non presente in Cache L1 o in entrambe. In questo caso ,utilizzando la strategia write-allocate, si avrà una lettura dalla cache di livello due o dalla memoria e successivamente una scrittura. Si avranno quindi la successione dei due punti precedentemente discussi: Lettura di un dato non presente in cache L1 e L2 “ o “Lettura di un dato non presente in Cache L1 e presente in Cache L2 in stato Exclusive o Modified” “Scrittura con dato presente in Cache L1.”
Testbench Multiprocessore Nelle slide successive sono riportati i testbench eseguiti per i seguenti casi di interesse in un sistema multiprocessore. Multi processore: lettura di dato non presente nella cache con snoop hit. Snoop di Invalidazione dei dati a causa di una scrittura. WriteBack a seguito di uno snoop in lettura. Protocollo contesa bus.
Lettura di dato non presente nella cache con snoop hit. Il testbench prevede la lettura consecutiva da parte delle due cpu ad indirizzi contenuti all’interno della stessa linea di cache di livello 2.
Lettura di dato non presente nella cache con snoop hit. La seconda lettura provocherà un cache hit che caricherà le linee in stato shared su entrambi i livelli di cache.
Snoop di Invalidazione dei dati a causa di una scrittura. Nel caso in cui una scrittura venga propagata fino alla memoria (cache di livello 1 e 2 in stato shared). La scrittura provocherà un invalidazione delle altre cpu che contengono il dato nelle loro cache. Dopo la scrittura lo stato delle linea di primo livello sarà Shared mentre quella di socondo livello avrà stato Exclusive. La cache dell’altro processore sarà invece invalidata
WriteBack a seguito di uno snoop in lettura. Questo testbench mostra il comportamento del sistema a seguito di un operazione di snoop che trova la linea cercata in stato modified. La linea verrà quindi scritta in memoria togliendo il Bgrnt alla Cpu che ha eseguito lo snoop ed assegnandolo alla Cpu con la linea modificata per permettergli di eseguire il Writeback
Protocollo contesa Bus Il protocollo di accesso al bus mostra le sue politiche di assegnamento per priorità solo nel caso in cui gli accessi avvengano in modo contemporaneo. L’accesso multiplo al bus fa si che quest’ultimo venga assegnato al processore conL’ac priorità più alta. L’immagine si riferisce a due accessi contemporanei successivi alla risorsa bus ed a come il protocollo gestisce le priorità assegnando il bus, nel primo conflitto a CPU1, nel secondo a CPU2.
Conclusioni e possibili estensioni
Conclusioni Il controllore di memoria è in grado di gestire in maniera accademica i conflitti fra letture e scritture sulla memoria comune ed in generale le problematiche di coerenza fra dati in cache ed in memoria principale. Il cuore pulsante del progetto definito dal memory controller resta legato a principi che garantiscono la presenza di una forte modularità, la quale persiste nell’eventualità di una possibile futura espansione ad un sistema virtuale che supporti una moltitudine qual si voglia elevata di processori e livelli di cache.
Possibili Estensioni Alcune parti software hanno lasciato spazio a delle possibili migliorie nel campo delle prestazioni. Si potrebbe modificare il sequencier in modo da far pervenire alla cpu in maniera prioritaria i dati necessari a continuare l’esecuzione dell’istruzione corrente per poi caricare in un secondo momento la parte restante della linea.