Created
July 2, 2016 05:22
-
-
Save eariassoto/79e0ab90a846ca9c8e22256985f6c555 to your computer and use it in GitHub Desktop.
load y store
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// | |
/// </summary> | |
/// <param name="posMem"></param> | |
/// <param name="regFuente"></param> | |
/// <returns></returns> | |
public bool StoreWord(int posMem, int regFuente) | |
{ | |
/// resultado final, sirve para | |
/// 1. bajar el PC | |
/// 2. indica si sí se hizo el SW | |
bool exito = true; | |
/// banderas de locks | |
bool bloqueoMiCache = false; | |
bool bloqueoDirecCasa = false; | |
bool bloqueoDirecVictima = false; | |
bool bloqueoDirecBloque = false; | |
bool bloqueoCacheModif = false; | |
/// Punteros que hay que liberar | |
object objMiCache = null; | |
object objDirecCasa = null; | |
object objDirecVictima = null; | |
object objDirecBloque = null; | |
object objCacheModif = null; | |
/// en caso que no se logre lock de directorio bloque victima no deja pasar | |
bool puedeContinuarDesdeBloqueVictima = true; | |
Contexto contPrincipal = contextos.ElementAt(0); | |
try | |
{ | |
/// Intento bloquear mi caché | |
Monitor.TryEnter(this.cacheDatos, ref bloqueoMiCache); | |
if(bloqueoMiCache) | |
{ | |
#region bloqueoMiCache | |
objMiCache = this.cacheDatos; | |
var direccion = getPosicion(posMem); | |
if (bloqueEnMiCache(direccion.numeroBloque)) | |
{ | |
#region hitMiCache | |
/// En este caso de da un HIT | |
int estadoMiBloque = this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][CACHDAT_COL_ESTADO]; | |
/// Hay que revisar el estado del bloque | |
/// Si está Modificado entonces modifiquelo de nuevo y ya | |
/// Si está compartido hay que ir a invalidar a otros lados y luego modificar | |
switch (estadoMiBloque) | |
{ | |
case ESTADO_MODIFICADO: | |
/// Ya el estado esta modificado, solo cambio palabra | |
cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][direccion.numeroPalabra] = contPrincipal.registro[regFuente]; | |
break; | |
case ESTADO_COMPARTIDO: | |
/// Busco el procesador que tiene el directorio casa del bloque | |
/// lo intento bloquear | |
int numProc = getNumeroProcesador(direccion.numeroBloque); | |
Procesador procesadorDirecCasa = procesadores.ElementAt(numProc); | |
Monitor.TryEnter(procesadorDirecCasa.directorio, ref bloqueoDirecCasa); | |
if (bloqueoDirecCasa) | |
{ | |
/// Si lo logro bloquear, esa función intentará invalidar, si lo logra | |
/// devuelve true y entonces puedo modificar el bloque | |
objDirecCasa = procesadorDirecCasa.directorio; | |
bool res = InvalidarCachesCompartidas(procesadorDirecCasa, direccion); | |
if (res) | |
{ | |
/// Actualizo directorio | |
procesadorDirecCasa.directorio[direccion.numeroBloque % DIRECT_FILAS][DIRECT_COL_ESTADO] = ESTADO_MODIFICADO; | |
procesadorDirecCasa.directorio[direccion.numeroBloque % DIRECT_FILAS][id + 1] = 1; | |
/// Hago el cambio | |
this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][direccion.numeroPalabra] = contPrincipal.registro[regFuente]; | |
this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][CACHDAT_COL_ESTADO] = ESTADO_MODIFICADO; | |
} | |
else | |
{ | |
exito = false; | |
} | |
} | |
else | |
{ | |
exito = false; | |
} | |
break; | |
} | |
#endregion | |
} | |
else | |
{ | |
#region missMiCache | |
/// En caso que haya MISS | |
/// Primero veo el bloque víctima | |
int estadoBloqueVictima = cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][CACHDAT_COL_ESTADO]; | |
if (estadoBloqueVictima == ESTADO_COMPARTIDO || estadoBloqueVictima == ESTADO_MODIFICADO) | |
{ | |
/// Intento bloquear el directorio casa del bloque víctima | |
int numeroBloqueVictima = blockMapDatos[direccion.numeroBloque % CACHDAT_FILAS]; | |
Procesador procesadorBloqueVictima = procesadores.ElementAt(getNumeroProcesador(numeroBloqueVictima)); | |
Monitor.TryEnter(procesadorBloqueVictima.directorio, ref bloqueoDirecVictima); | |
if (bloqueoDirecVictima) | |
{ | |
#region bloqueoDirecVictima | |
objDirecVictima = procesadorBloqueVictima.directorio; | |
switch(estadoBloqueVictima) | |
{ | |
case ESTADO_COMPARTIDO: | |
/// Actualizo directorio | |
procesadorBloqueVictima.directorio[numeroBloqueVictima % DIRECT_FILAS][id + 1] = 0; | |
/// Reviso si tengo que ponerlo UNCACHED | |
bool compartidoEnOtrasCaches = false; | |
for (int i = 1; i < 4; i++) | |
{ | |
if (procesadorBloqueVictima.directorio[numeroBloqueVictima % DIRECT_FILAS][i + 1] == 1) | |
{ | |
compartidoEnOtrasCaches = true; | |
} | |
} | |
if (!compartidoEnOtrasCaches) | |
{ | |
procesadorBloqueVictima.directorio[numeroBloqueVictima % DIRECT_FILAS][0] = ESTADO_UNCACHED; | |
} | |
/// Lo invalido en caché | |
this.cacheDatos[numeroBloqueVictima % CACHDAT_FILAS][CACHDAT_COL_ESTADO] = ESTADO_INVALIDO; | |
this.blockMap[numeroBloqueVictima % CACHDAT_FILAS] = -1; | |
break; | |
case ESTADO_MODIFICADO: | |
/// manda a guardar el bloque a memoria | |
for (int i = 0; i < 4; i++) | |
{ | |
procesadorBloqueVictima.memoriaPrincipal[numeroBloqueVictima % BLOQUES_COMP][i][0] = this.cacheDatos[numeroBloqueVictima % CACHDAT_FILAS][i]; | |
} | |
/// Actualizo directorio | |
procesadorBloqueVictima.directorio[numeroBloqueVictima % DIRECT_FILAS][id + 1] = 0; | |
procesadorBloqueVictima.directorio[numeroBloqueVictima % DIRECT_FILAS][DIRECT_COL_ESTADO] = ESTADO_UNCACHED; | |
/// Lo invalido en caché | |
this.cacheDatos[numeroBloqueVictima % CACHDAT_FILAS][CACHDAT_COL_ESTADO] = ESTADO_INVALIDO; | |
this.blockMap[numeroBloqueVictima % CACHDAT_FILAS] = -1; | |
break; | |
} | |
#endregion | |
} | |
else | |
{ | |
puedeContinuarDesdeBloqueVictima = false; | |
} | |
} | |
if (puedeContinuarDesdeBloqueVictima) | |
{ | |
/// Si los locks salieron bien en la parte del bloque víctima, sigo | |
/// Intento bloquear directorio casa del bloque que voy a cargar | |
int numProcBloque = getNumeroProcesador(direccion.numeroBloque); | |
Procesador procesadorDirecCasa = procesadores.ElementAt(numProcBloque); | |
Monitor.TryEnter(procesadorDirecCasa.directorio, ref bloqueoDirecBloque); | |
if(bloqueoDirecBloque) | |
{ | |
#region bloqueoDirecBloque | |
/// Tengo que fijarme en el estado del bloque: | |
/// UNCACHED: cargo de memoria, actualizo direct, actualizo estado caché | |
/// MODIFICADO: busco el procesador que lo tiene modificado, intentlo bloquear su cache | |
/// si sí, bajo a memoria, copio en mi caché, actualizo cachés y directorio | |
/// COMPARTIDO: intento invalidar otras cachés y si si, cambio la mía y actualizo | |
objDirecBloque = procesadorDirecCasa.directorio; | |
int estadoBloque = procesadorDirecCasa.directorio[direccion.numeroBloque % DIRECT_FILAS][DIRECT_COL_ESTADO]; | |
switch (estadoBloque) | |
{ | |
case ESTADO_UNCACHED: | |
/// Cargo de memoria a mi caché | |
for(int i = 0; i < 4; i++) | |
{ | |
this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][i] = procesadorDirecCasa.memoriaPrincipal[direccion.numeroBloque % BLOQUES_COMP][i][0]; | |
} | |
this.blockMapDatos[direccion.numeroBloque % CACHDAT_FILAS] = direccion.numeroBloque; | |
/// Actualizo directorio | |
procesadorDirecCasa.directorio[direccion.numeroBloque % DIRECT_FILAS][DIRECT_COL_ESTADO] = ESTADO_MODIFICADO; | |
procesadorDirecCasa.directorio[direccion.numeroBloque % DIRECT_FILAS][id + 1] = 1; | |
/// Modifico bloque y cambio estado | |
cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][direccion.numeroPalabra] = contPrincipal.registro[regFuente]; | |
cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][CACHDAT_COL_ESTADO] = ESTADO_MODIFICADO; | |
break; | |
case ESTADO_MODIFICADO: | |
/// Busco el procesador | |
Procesador procesQueTieneModificado = null; | |
for(int i = 0; i < 3; i++) | |
{ | |
if(i != this.id && procesadorDirecCasa.directorio[direccion.numeroBloque % DIRECT_FILAS][i + 1] == 1) | |
{ | |
procesQueTieneModificado = procesadores.ElementAt(i); | |
} | |
} | |
/// Intento bloquear su caché | |
Monitor.TryEnter(procesQueTieneModificado.cacheDatos, ref bloqueoCacheModif); | |
if(bloqueoCacheModif) | |
{ | |
objCacheModif = procesQueTieneModificado.cacheDatos; | |
for (int i = 0; i < 4; i++) | |
{ | |
/// copio a memoria | |
procesadorDirecCasa.memoriaPrincipal[direccion.numeroBloque % BLOQUES_COMP][i][0] = procesQueTieneModificado.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][i]; | |
/// cargo a mi caché | |
this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][i] = procesadorDirecCasa.memoriaPrincipal[direccion.numeroBloque % BLOQUES_COMP][i][0]; | |
} | |
/// Actualizo caché otro procesador | |
procesQueTieneModificado.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][CACHDAT_COL_ESTADO] = ESTADO_INVALIDO; | |
procesQueTieneModificado.blockMapDatos[direccion.numeroBloque % CACHDAT_FILAS] = -1; | |
/// Cambio palabra, actualizo estado | |
this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][direccion.numeroPalabra] = contPrincipal.registro[regFuente]; | |
this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][CACHDAT_COL_ESTADO] = ESTADO_MODIFICADO; | |
} | |
else | |
{ | |
exito = false; | |
} | |
break; | |
case ESTADO_COMPARTIDO: | |
bool res = InvalidarCachesCompartidas(procesadorDirecCasa, direccion); | |
if (res) | |
{ | |
/// Actualizo directorio | |
procesadorDirecCasa.directorio[direccion.numeroBloque % DIRECT_FILAS][DIRECT_COL_ESTADO] = ESTADO_MODIFICADO; | |
procesadorDirecCasa.directorio[direccion.numeroBloque % DIRECT_FILAS][id + 1] = 1; | |
/// Cambio palabra, actualizo estado | |
this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][direccion.numeroPalabra] = contPrincipal.registro[regFuente]; | |
this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][CACHDAT_COL_ESTADO] = ESTADO_MODIFICADO; | |
} | |
else | |
{ | |
exito = false; | |
} | |
break; | |
} | |
#endregion | |
} | |
else | |
{ | |
exito = false; | |
} | |
} | |
else | |
{ | |
exito = false; | |
} | |
#endregion | |
} | |
#endregion | |
} | |
else | |
{ | |
exito = false; | |
} | |
} | |
finally | |
{ | |
if (bloqueoMiCache) | |
Monitor.Exit(objMiCache); | |
if (bloqueoDirecCasa) | |
Monitor.Exit(objDirecCasa); | |
if (bloqueoDirecVictima) | |
Monitor.Exit(objDirecVictima); | |
if (bloqueoDirecBloque) | |
Monitor.Exit(objDirecBloque); | |
if (bloqueoCacheModif) | |
Monitor.Exit(objCacheModif); | |
if(exito == false) | |
contPrincipal.pc -= 4; | |
} | |
return exito; | |
} | |
/// <summary> | |
/// | |
/// </summary> | |
/// <param name="regFuente2"></param> | |
/// <param name="posMem"></param> | |
/// <returns></returns> | |
public bool loadWord(int regFuente2, int posMem) | |
{ | |
bool resultado = true; | |
/// banderas de locks | |
bool bloqueoMiCache = false; | |
bool bloqueoDirecVictima = false; | |
bool bloqueoDirecBloque = false; | |
bool bloqueoCacheBloque = false; | |
/// punteros a los objetos que hay que liberar | |
object objMiCache = null; | |
object objDirecVictima = null; | |
object objDirecBloque = null; | |
object objCacheBloque = null; | |
// en caso que no se logre lock de direc bloque victima no deja pasar | |
bool puedeContinuarDesdeBloqueVictima = true; | |
var direccion = getPosicion(posMem); | |
Contexto contPrincipal = contextos.ElementAt(0); | |
try | |
{ | |
Monitor.TryEnter(this.cacheDatos, ref bloqueoMiCache); | |
if (bloqueoMiCache) | |
{ | |
#region bloqueoMiCache | |
objMiCache = this.cacheDatos; | |
if (bloqueEnMiCache(direccion.numeroBloque)) | |
{ | |
/// caso que hay HIT | |
/// copie y vamonos | |
contPrincipal.registro[regFuente2] = this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][direccion.numeroPalabra]; | |
} | |
else | |
{ | |
/// caso que hay un MISS | |
/// Hay que revisar el estado de bloque víctima | |
int estadoBloqueVictima = this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][CACHDAT_COL_ESTADO]; | |
if (estadoBloqueVictima == ESTADO_COMPARTIDO || estadoBloqueVictima == ESTADO_MODIFICADO) | |
{ | |
int numeroBloqueVictima = this.blockMapDatos[direccion.numeroBloque % CACHDAT_FILAS]; | |
Procesador procesadorBloqueVictima = procesadores.ElementAt(getNumeroProcesador(numeroBloqueVictima)); | |
Monitor.TryEnter(procesadorBloqueVictima.directorio, ref bloqueoDirecVictima); | |
if (bloqueoDirecVictima) | |
{ | |
#region bloqueoDirecVictima | |
/// Logra bloquear el directorio víctima | |
objDirecVictima = procesadorBloqueVictima.directorio; | |
/// Ciclos de retraso | |
if (procesadorBloqueVictima == this) | |
{ | |
estoyEnRetraso = true; | |
ciclosEnRetraso += 2; // ciclos que gasta en consulta directorio local | |
} | |
else | |
{ | |
estoyEnRetraso = true; | |
ciclosEnRetraso += 4; // ciclos que gasta en consulta directorio remoto | |
} | |
/// Evalua el estado del bloque | |
/// Si está compartido, lo invalida y actualiza cachés y directorios | |
/// Si está modificado, hace eso mismo pero adémás guarda en memoria | |
switch(estadoBloqueVictima) | |
{ | |
case ESTADO_COMPARTIDO: | |
/// Actualiza el directorio | |
procesadorBloqueVictima.directorio[numeroBloqueVictima % DIRECT_FILAS][id + 1] = 0; | |
/// Ve a ver si tiene que poner UNCACHED | |
bool compartidoEnOtrasCaches = false; | |
for (int i = 0; i < 3; i++) | |
{ | |
if (procesadorBloqueVictima.directorio[numeroBloqueVictima % DIRECT_FILAS][i + 1] == 1) | |
{ | |
compartidoEnOtrasCaches = true; | |
} | |
} | |
if (!compartidoEnOtrasCaches) | |
{ | |
procesadorBloqueVictima.directorio[numeroBloqueVictima % DIRECT_FILAS][DIRECT_COL_ESTADO] = ESTADO_UNCACHED; | |
} | |
/// Invalida la caché | |
this.cacheDatos[numeroBloqueVictima % CACHDAT_FILAS][CACHDAT_COL_ESTADO] = ESTADO_INVALIDO; | |
this.blockMap[numeroBloqueVictima % CACHDAT_FILAS] = -1; | |
break; | |
case ESTADO_MODIFICADO: | |
/// Guardo en memoria | |
for (int i = 0; i < 4; i++) | |
{ | |
procesadorBloqueVictima.memoriaPrincipal[numeroBloqueVictima % BLOQUES_COMP][i][0] = this.cacheDatos[numeroBloqueVictima % CACHDAT_FILAS][i]; | |
} | |
/// Ciclos de retraso | |
estoyEnRetraso = true; | |
ciclosEnRetraso += 16; | |
/// Actualizo directorio | |
procesadorBloqueVictima.directorio[numeroBloqueVictima % DIRECT_FILAS][DIRECT_COL_ESTADO] = ESTADO_UNCACHED; | |
procesadorBloqueVictima.directorio[numeroBloqueVictima % DIRECT_FILAS][id + 1] = 0; | |
/// Invalido en caché | |
this.cacheDatos[numeroBloqueVictima % CACHDAT_FILAS][CACHDAT_COL_ESTADO] = ESTADO_INVALIDO; | |
this.blockMap[numeroBloqueVictima % CACHDAT_FILAS] = -1; | |
break; | |
} | |
#endregion | |
} | |
else | |
{ | |
puedeContinuarDesdeBloqueVictima = false; | |
} | |
} | |
if (puedeContinuarDesdeBloqueVictima) | |
{ | |
/// Significa que los locks del bloque victima se hicieron bien | |
int numProc = getNumeroProcesador(direccion.numeroBloque); | |
Procesador proceQueTieneElBloque = procesadores.ElementAt(numProc); | |
Monitor.TryEnter(proceQueTieneElBloque.directorio, ref bloqueoDirecBloque); | |
if (bloqueoDirecBloque) | |
{ | |
/// Se bloqueo el directorio casa del bloque | |
#region bloqueoDirecBloque | |
objDirecBloque = proceQueTieneElBloque.directorio; | |
/// Ciclos de retraso | |
if (proceQueTieneElBloque == this) | |
{ | |
estoyEnRetraso = true; | |
ciclosEnRetraso += 2; // ciclos que gasta en consulta directorio local | |
} | |
else | |
{ | |
estoyEnRetraso = true; | |
ciclosEnRetraso += 4; // ciclos que gasta en consulta directorio remoto | |
} | |
/// Veo el estado del bloque | |
int estadoBloque = proceQueTieneElBloque.directorio[direccion.numeroBloque % DIRECT_FILAS][DIRECT_COL_ESTADO]; | |
/// Si alquien lo tiene modificado | |
if (estadoBloque == ESTADO_MODIFICADO) | |
{ | |
/// Busco el procesador | |
Procesador procQueLoTieneM = null; | |
for (int i = 0; i < 3; i++) | |
{ | |
if (proceQueTieneElBloque.directorio[direccion.numeroBloque % DIRECT_FILAS][i + 1] == 1) | |
{ | |
procQueLoTieneM = procesadores.ElementAt(i); | |
} | |
} | |
Monitor.TryEnter(procQueLoTieneM.cacheDatos, ref bloqueoCacheBloque); | |
if (bloqueoCacheBloque) | |
{ | |
/// Logro bloquear la cache del procesador que tiene el bloque modificado | |
objCacheBloque = procQueLoTieneM.cacheDatos; | |
/// Guarda en memoria | |
for (int i = 0; i < 4; i++) | |
{ | |
proceQueTieneElBloque.memoriaPrincipal[direccion.numeroBloque % BLOQUES_COMP][i][0] = procQueLoTieneM.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][i]; | |
} | |
/// Actualiza estado de la caché | |
procQueLoTieneM.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][DIRECT_COL_ESTADO] = ESTADO_COMPARTIDO; | |
/// Actualiza el directorio | |
proceQueTieneElBloque.directorio[direccion.numeroBloque % DIRECT_FILAS][DIRECT_COL_ESTADO] = ESTADO_COMPARTIDO; | |
proceQueTieneElBloque.directorio[direccion.numeroBloque % DIRECT_FILAS][procQueLoTieneM.id + 1] = 1; | |
} | |
} | |
/// Esta validación asegura que no hizo fail de try lock en el paso anterior | |
if (estadoBloque != ESTADO_MODIFICADO || (estadoBloque == ESTADO_MODIFICADO && bloqueoCacheBloque)) | |
{ | |
/// Se trae el bloque de memoria a mi caché | |
for (int i = 0; i < 4; i++) | |
{ | |
this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][i] = proceQueTieneElBloque.memoriaPrincipal[direccion.numeroBloque % BLOQUES_COMP][i][0]; | |
} | |
/// Actualizo mi caché | |
this.cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][DIRECT_COL_ESTADO] = ESTADO_COMPARTIDO; | |
this.blockMapDatos[direccion.numeroBloque % CACHDAT_FILAS] = direccion.numeroBloque; | |
/// Actualizo directorio | |
proceQueTieneElBloque.directorio[direccion.numeroBloque % DIRECT_FILAS][DIRECT_COL_ESTADO] = ESTADO_COMPARTIDO; | |
proceQueTieneElBloque.directorio[direccion.numeroBloque % DIRECT_FILAS][id + 1] = 1; | |
/// Guardo en el registro | |
contPrincipal.registro[regFuente2] = cacheDatos[direccion.numeroBloque % CACHDAT_FILAS][direccion.numeroPalabra]; | |
} | |
else | |
{ | |
resultado = false; | |
} | |
#endregion | |
} | |
else | |
{ | |
resultado = false; | |
} | |
} | |
else | |
{ | |
resultado = false; | |
} | |
} | |
#endregion | |
} | |
else | |
{ | |
resultado = false; | |
} | |
} | |
finally | |
{ | |
if (bloqueoMiCache) | |
Monitor.Exit(objMiCache); | |
if (bloqueoDirecVictima) | |
Monitor.Exit(objDirecVictima); | |
if (bloqueoDirecBloque) | |
Monitor.Exit(objDirecBloque); | |
if (bloqueoCacheBloque) | |
Monitor.Exit(objCacheBloque); | |
if (resultado == false) | |
contPrincipal.pc -= 4; | |
} | |
return resultado; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment