Ejemplo n.º 1
0
 /// <summary>
 /// Constructor para crear los bloques por defecto de la cache
 /// </summary>
 /// <param name="controlador">Controlador de la simulacion</param>
 /// <param name="solicitante">Cache dueña del bloqueMemoria</param>
 public BloqueCacheDatos(Controlador controlador, CacheDatos cache)
     : base(-1, -1, -1)
 {
     this.controlador = controlador;
     this.cache       = cache;
     this.estado      = EstadosB.Invalido;
 }
Ejemplo n.º 2
0
        public void ModificarBloque(CacheDatos solicitante, BloqueCacheDatos bloque)
        {
            Esperar(solicitante);

            Debug.Assert(EstaBloqueado());
            Debug.Assert(usuarios[bloque.IndiceMemoriaPrincipal].Count == 1);

            Estados[bloque.IndiceMemoriaPrincipal] = EstadosD.Modificado;
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Obtiene la informacion necesaria con respecto a la operacion que se quiere leer
        /// </summary>
        /// <param name="controlador"></param>
        /// <param name="solicitante"></param>
        /// <param name="direccionPalabra"></param>
        public InformacionPalabra(Controlador controlador, CacheDatos solicitante, int direccionPalabra)
        {
            this.controlador = controlador;
            this.solicitante = solicitante;
            this.id          = direccionPalabra / BytesPorMemoria;
            int direccionPalabraLocal = direccionPalabra % BytesPorMemoria;

            this.indiceBloqueMemoria = direccionPalabraLocal / BytesPorBloque;
            this.indicePalabra       = (direccionPalabraLocal % BytesPorBloque) / BytesPorPalabra;
            ActualizarBloque();
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Cantidad de ciclos a esperar en caso de que se trate de una operación local o remota
 /// </summary>
 /// <param name="solicitante">Cache de Datos solicitante</param>
 private void Esperar(CacheDatos solicitante)
 {
     if (id == solicitante.ID)
     {
         controlador.Esperar(EsperaOperacionDirectorioLocal);
     }
     else
     {
         controlador.Esperar(EsperaOperacionDirectorioRemoto);
     }
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Crea todas las condiciones necesarias para la simulacion y
        /// posteriormente la inicia simplemente diciendole a cada procesador
        /// que se ejecute
        ///
        /// Este metodo esta pensado en que se va a envolver en un hilo cuando se
        /// cree desde la vista!
        /// </summary>
        public void EjecutarSimulacion()
        {
            Debug.WriteLine("Simulador: Iniciando...");
            Debug.Flush();

            // Modificar aqui la cantidad de procesadores deseados!
            int numeroProcesadores = cantidadProgramas > 2 ? 3 : cantidadProgramas; //para ajustar la cantidad según necesidad

            // Se crean vectores para todos los objetos necesarios
            Controlador controlador = new Controlador();

            Procesador[]       procesadores       = new Procesador[numeroProcesadores];
            CacheInstrucciones cacheInstrucciones = new CacheInstrucciones(numeroProcesadores, instrucciones, iniciosProgramas, cantidadProgramas, nombresProgramas);

            CacheDatos[]       cachesDatos         = new CacheDatos[numeroProcesadores];
            Directorio[]       directorios         = new Directorio[numeroProcesadores];
            MemoriaPrincipal[] memoriasPrincipales = new MemoriaPrincipal[numeroProcesadores];

            // Se inicializan todos los objetos relacionados a los procesadores
            for (int i = 0; i < numeroProcesadores; ++i)
            {
                directorios[i]         = new Directorio(controlador, i);
                memoriasPrincipales[i] = new MemoriaPrincipal(controlador, i);
                cachesDatos[i]         = new CacheDatos(controlador, i);
                procesadores[i]        = new Procesador(controlador, i);
            }

            // Se agrega la interfaz como listener del controlador/modelo
            controlador.AddListener(interfaz);

            // Se inicializa el controlador que hasta el momento no conocia a nadie
            controlador.Inicializar(procesadores, cachesDatos, cacheInstrucciones, directorios, memoriasPrincipales);

            // Se crean los hilos necesarios
            Thread[] hilosProcesadores = new Thread[numeroProcesadores];
            for (int i = 0; i < numeroProcesadores; ++i)
            {
                // Se crea un hilo para cada procesador y se manda a ejectuar instrucciones
                hilosProcesadores[i] = new Thread(procesadores[i].Procesar);
                hilosProcesadores[i].Start();
            }

            // Cuando todos los procesadores comienzan, se empiezan a sincronizar
            // solos con ayuda del objeto controlador porque ahi esta la barrera

            // Se espera que cada procesador termine
            for (int i = 0; i < numeroProcesadores; ++i)
            {
                hilosProcesadores[i].Join();
            }

            // El hilo del simulador termina en el momento que todos los procesadores terminan!
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Método que devuelve cuantos usuarios comparten un bloque menos yo
        /// </summary>
        /// <param name="bloqueMemoria">Bloque para obtener el índice de memoria principal</param>
        /// <returns>Lista de Caches que comparten el bloqueMemoria</returns>
        public int CountUsuariosQueComparten(CacheDatos solicitante, Bloque bloque)
        {
            Esperar(solicitante);

            Debug.Assert(EstaBloqueado());

            List <int> tmp = new List <int>(usuarios[bloque.IndiceMemoriaPrincipal]);

            tmp.Remove(solicitante.ID);

            return(tmp.Count);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Se elimina cache de la lista respectiva
        /// </summary>
        /// <param name="solicitante">Cache de datos que ya no es usuaria del bloqueMemoria</param>
        /// <param name="bloqueMemoria">Bloque ya no utilizado</param>
        public void EliminarUsuarioBloque(CacheDatos solicitante, BloqueCacheDatos bloque)
        {
            Esperar(solicitante);

            Debug.Assert(EstaBloqueado());
            Debug.Assert(usuarios[bloque.IndiceMemoriaPrincipal].Contains(solicitante.ID));
            Debug.Assert(bloque.ID == this.id);

            usuarios[bloque.IndiceMemoriaPrincipal].Remove(solicitante.ID);
            if (usuarios[bloque.IndiceMemoriaPrincipal].Count == 0)
            {
                estados[bloque.IndiceMemoriaPrincipal] = EstadosD.Uncached;
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Método que devuelve la cache que modificó un bloqueMemoria.
        /// Devuelve null si nadie ha modificado el bloqueMemoria.
        /// </summary>
        /// <param name="solicitante">Solicitante del cambio</param>
        /// <param name="bloqueMemoria">Bloque para obtener el id</param>
        /// <returns>Cache que modificó una palabra del bloqueMemoria</returns>
        public CacheDatos GetUsuarioQueModifica(CacheDatos solicitante, Bloque bloque)
        {
            Esperar(solicitante);

            Debug.Assert(EstaBloqueado());

            CacheDatos cache  = null;
            int        indice = bloque.IndiceMemoriaPrincipal;

            if (estados[indice] == EstadosD.Modificado && usuarios[indice].Count == 1)
            {
                cache = controlador.CachesDatos[usuarios[indice][0]];
            }
            return(cache);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Agrega una cache como usuaria de un bloque. Siempre se agregan los bloques en C.
        /// </summary>
        /// <param name="solicitante">Cache de datos usuaria del bloqueMemoria</param>
        /// <param name="bloqueMemoria">Bloque siendo utilizado</param>
        public void AgregarUsuarioBloque(CacheDatos solicitante, BloqueCacheDatos bloque)
        {
            Esperar(solicitante);

            // Debido a la implementación los bloques siempre se agregan como compartidos al directorio
            // Si la cache los modifica, luego llama al método de ModificarBloque del directorio
            Debug.Assert(EstaBloqueado());
            Debug.Assert(estados[bloque.IndiceMemoriaPrincipal] != EstadosD.Modificado);
            Debug.Assert(bloque.Estado != EstadosB.Modificado);
            Debug.Assert(!usuarios[bloque.IndiceMemoriaPrincipal].Contains(solicitante.ID));
            Debug.Assert(bloque.ID == this.id);
            Debug.Assert(solicitante[bloque.IndiceCache].Direccion == bloque.Direccion);

            usuarios[bloque.IndiceMemoriaPrincipal].Add(solicitante.ID);
            estados[bloque.IndiceMemoriaPrincipal] = EstadosD.Compartido;
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Se invalida el bloqueMemoria en todas las cachés que lo usen
        /// </summary>
        /// <param name="solicitante">Cache de Datos solicitante</param>
        /// <param name="bloqueMemoria">Bloque para obtener la dirección</param>
        public void InvalidarBloque(CacheDatos solicitante, Bloque bloque)
        {
            Esperar(solicitante);

            // Solo se puede invalidar un bloqueMemoria si alguien lo está compartiendo
            Debug.Assert(EstaBloqueado());
            Debug.Assert(estados[bloque.IndiceMemoriaPrincipal] == EstadosD.Compartido);
            Debug.WriteLine("Cache " + solicitante.ID + ": Invalidando a quienes comparten el bloque " + bloque.Direccion);

            //Obtengo quienes son las caches que tienen bloqueN compartido
            List <int> lectores = usuarios[bloque.IndiceMemoriaPrincipal];

            // Creo una copia de la lista de lectores sin la cache solicitante
            // Si es que se encuentra
            List <int> tmp = new List <int>(lectores);

            tmp.Remove(solicitante.ID);

            // TODO Mejorar este código para que reintente sobre las caches
            // Mientras no falle consecutivamente en todas
            foreach (int id in tmp)
            {
                CacheDatos cache = controlador.CachesDatos[id];

                // Bloqueo la cache
                cache.Bloquear(this.Nombre);

                BloqueCacheDatos bloqueCache = cache[bloque.IndiceCache];

                Debug.Assert(bloqueCache.Direccion == bloque.Direccion);

                // Invalido el bloque
                bloqueCache.Invalidar();

                // Debloqueo la cache
                cache.Desbloquear(this.Nombre);
            }

            // O no hay nadie compartiendo el bloque o la solicitante es la unica que lo comparte
            Debug.Assert(lectores.Count == 0 || lectores[0] == solicitante.ID && lectores.Count == 1);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Método que realmente se encarga de ejecutar la lógica de leer una palabra.
        /// Si no puede bloquear algo, tira una excepción del tipo RebootNeededException.
        /// </summary>
        /// <param name="info">Información de la palabra que se quiere leer</param>
        /// <returns>Palabra que se quiere leer</returns>
        private int Leer(InformacionPalabra info)
        {
            int palabraLeida = -1;

            // Se bloquea la cache
            this.Bloquear(this.Nombre);
            bloqueados.Add(this);

            // Se pregunta si es Hit
            if (!info.EsHit())
            {
                // Se envia el bloqueV a memoria si está modificado
                EnviarAMemoriaBloqueVSiModificado(this[info.IndiceCache]);

                // Bloqueo el directorio que contiene la palabra que busco
                info.Directorio.Bloquear(this.Nombre);
                bloqueados.Add(info.Directorio);

                // Consulto el directorio del bloqueMemoria que contiene la palabra que busco
                // para ver si alguna cache lo tiene modificado
                CacheDatos modificante = info.Directorio.GetUsuarioQueModifica(this, info.Bloque);

                if (modificante == null)
                {
                    // Traigo el bloqueMemoria de memoria
                    BloqueCacheDatos.TraerBloqueCacheDatos(info.Bloque, controlador, this, true);
                }
                else
                {
                    // Bloqueo la cache que modificó el dato
                    modificante.Bloquear(this.Nombre);
                    bloqueados.Add(modificante);

                    // Se envía el bloque en la cache modificante a memoria
                    modificante[info.IndiceCache].EnviarAMemoria();

                    // Se actualiza la información del bloque con lo último de memoria
                    info.ActualizarBloque();

                    // Traigo el dato de la cache modificante
                    BloqueCacheDatos.TraerBloqueCacheDatos(info.Bloque, controlador, this, false);

                    // Desbloqueo la cache que modificó el dato
                    modificante.Desbloquear(this.Nombre);
                    bloqueados.Remove(modificante);
                }

                // Desbloqueo el directorio
                info.Directorio.Desbloquear(this.Nombre);
                bloqueados.Remove(info.Directorio);
            }

            // Leo la palabra
            palabraLeida = this[info.IndiceCache][info.IndicePalabra];

            // Desbloqueo la cache
            this.Desbloquear(this.Nombre);
            bloqueados.Remove(this);

            // Devuelvo la palabra leída
            return(palabraLeida);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Método que escribe una palabra en una dirección de memoria
        /// </summary>
        /// <param name="info">Guarda información de donde debe escribirse la palabra</param>
        /// <param name="palabra">Palabra que se quiere escribir</param>
        public void Escribir(InformacionPalabra info, int palabra)
        {
            //Se bloquea mi cache
            this.Bloquear(this.Nombre);
            bloqueados.Add(this);

            // Si es hit
            if (info.EsHit())
            {
                BloqueCacheDatos bloqueN = this[info.IndiceCache];

                if (bloqueN.Estado == EstadosB.Modificado)
                {
                    // Si está en mi cache modificado nada más lo escribo
                    bloqueN[info.IndicePalabra] = palabra;
                    bloqueN.Estado = EstadosB.Modificado;
                }
                else
                {
                    // Si lo tengo compartido, bloqueo el directorio correspondiente
                    info.Directorio.Bloquear(this.Nombre);
                    bloqueados.Add(info.Directorio);

                    // Invalido a todos quienes compartan el bloque
                    info.Directorio.InvalidarBloque(this, info.Bloque);

                    // Escribo la palabra
                    bloqueN[info.IndicePalabra] = palabra;
                    bloqueN.Estado = EstadosB.Modificado;
                    info.Directorio.ModificarBloque(this, bloqueN);

                    // Desbloqueo el directorio
                    info.Directorio.Desbloquear(this.Nombre);
                    bloqueados.Remove(info.Directorio);
                }
            }
            else
            {
                // Se envia el bloqueV a memoria si está modificado
                EnviarAMemoriaBloqueVSiModificado(this[info.IndiceCache]);

                // Bloqueo el directorio que contiene la palabra que busco
                info.Directorio.Bloquear(this.Nombre);
                bloqueados.Add(info.Directorio);

                // Consulto el directorio del bloqueMemoria que contiene la palabra que busco
                // para ver si alguna cache lo tiene modificado
                CacheDatos modificante = info.Directorio.GetUsuarioQueModifica(this, info.Bloque);

                if (modificante == null)    //Si no hay nadie que esté modificando en bloque

                {
                    if (info.Directorio.CountUsuariosQueComparten(this, info.Bloque) > 0)
                    {
                        //Se les invalida el BloqueN a todas las caches que lo tengan compartido
                        info.Directorio.InvalidarBloque(this, info.Bloque);
                    }

                    // Traigo el bloqueMemoria de memoria
                    // El constructor pone el bloque en la cache
                    BloqueCacheDatos.TraerBloqueCacheDatos(info.Bloque, controlador, this, true);
                }
                else
                {
                    // Bloqueo la cache que modificó el dato
                    modificante.Bloquear(this.Nombre);
                    bloqueados.Add(modificante);

                    // Se envía el bloque en la cache modificante a memoria
                    modificante[info.IndiceCache].EnviarAMemoria();

                    // Se actualiza la información del bloque
                    info.ActualizarBloque();

                    // Traigo el dato desde la cache modificante
                    BloqueCacheDatos.TraerBloqueCacheDatos(info.Bloque, controlador, this, false);

                    // Desbloqueo la cache que modificó el dato
                    modificante.Desbloquear(this.Nombre);
                    bloqueados.Remove(modificante);
                }

                // Escribo la palabra
                this[info.IndiceCache][info.IndicePalabra] = palabra;
                this[info.IndiceCache].Estado = EstadosB.Modificado;
                this[info.IndiceCache].Directorio.ModificarBloque(this, this[info.IndiceCache]);

                // Desbloqueo el directorio
                info.Directorio.Desbloquear(this.Nombre);
                bloqueados.Remove(info.Directorio);
            }

            // Desbloqueo mi cache
            this.Desbloquear(this.Nombre);
            bloqueados.Remove(this);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Trae un bloque de memoria o desde otra cache
        /// </summary>
        /// <param name="bloque">Bloque</param>
        /// <param name="controlador">Controlador</param>
        /// <param name="cache">Cache dueña del bloque</param>
        /// <param name="vieneDeMemoria">Indica si viene de memoria (true) o de otra cache (false)</param>
        public static BloqueCacheDatos TraerBloqueCacheDatos(Bloque bloque, Controlador controlador, CacheDatos cache, bool vieneDeMemoria)
        {
            // Se copian los datos del bloque
            BloqueCacheDatos bloqueCache = new BloqueCacheDatos(controlador, cache);

            bloqueCache.id = bloque.ID;
            bloqueCache.direccionInicial       = bloque.Direccion;
            bloqueCache.indiceMemoriaPrincipal = bloque.IndiceMemoriaPrincipal;
            for (int i = 0; i < PalabrasPorBloque; ++i)
            {
                bloqueCache.palabras[i] = bloque[i];
            }

            // Asigna el controlador y la cache
            bloqueCache.controlador = controlador;
            bloqueCache.cache       = cache;

            Debug.Assert(cache.EstaBloqueado());
            Debug.Assert(bloqueCache.Directorio.EstaBloqueado());

            // Se espera que el bloque venga de memoria
            bloqueCache.EsperarTraida(vieneDeMemoria);

            // Se pone el bloque como compartido
            bloqueCache.estado = EstadosB.Compartido;

            // Me pongo en la cache
            cache[bloqueCache.IndiceCache] = bloqueCache;

            // Se refleja el cambio en el directorio
            // Se pone como compartido en el directorio
            bloqueCache.Directorio.AgregarUsuarioBloque(cache, bloqueCache);

            return(bloqueCache);
        }