830 likes | 1.02k Views
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.
E N D
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.
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 • 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 signalsr_in: std_logic ⇒ bit inserito nel registro a scorrimento U : out std_logic_vector(31 downto 0) ⇒ bus a 32 bit checonsente 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) xorsr(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 inizializza variabili interne per la sincronizzazione delle operazioni aggiorna il segnale di ready ad ogni clock Operazione di lettura (memoria - cache) Operazione di scrittura (cache - memoria) Processi “accessori” inizializza le variabili interne necessarie al trasferimento cache - memoria effettua i cicli di scrittura per trasferire l’intera linea di cache in memoria inizializza le variabili interne necessarie al trasferimento memoria - cache effettua cicli di lettura per trasferire l’intera linea di cache dalla memoria
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_ino 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_ino Reset • Registro tempDataLineche 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 signaltemp_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
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.
MemWr_from_cpu ch_memwr Interfacciamento con i componenti interni alla cpu • Il cpuController necessita di conoscere se l’operazione in corso è di lettura o scrittura per poter eseguire delle operazioni coerenti al protocollo mesi. DLX 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 invalidate_to_cache EADS_to_cache WbWt_2 snoop_address transaction_complete Interfacciamento con i componenti interni alla cpu CPU_CONTROLLER CACHE L1 – L2 • I segnali inviati dalle Cache e che normalmente sarebbero diretti alle memorie vengono intercettati dall’interfaccia del cpu_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 MemRd MemWr Interfacciamento con i componenti esterni alla cpu CPU_CONTROLLER MEMORY_CONTROLLER • Il cpuController si collega al MemoryController per gestire tutte le operazioni del protocollo Mesi
MemRd MemWr Address DataInOut Ready MemRd MemWr InputAddress DataInOut Ready Interfacciamento con i componenti esterni alla cpu • L’interfacciamento 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
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 • snoop_address_in: in STD_LOGIC_VECTOR(PARALLELISM-1 downto 0)indirizzo di snoop in ingresso • MemRd_from_cache: in STD_LOGIC segnale di lettura proveniente dalla cache • 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_LOGIChitm dalla seconda cache
Segnali di input • HITM_1: in STD_LOGIChitm 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
WbWt_2 : out STD_LOGIC segnale per indicare lo stato finale della linea di secondo livello al caricamento • Data_to_cache : out STD_LOGIC_VECTOR (dataparallelism-1 downto 0) Dati in uscita per la cache 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.