SimCo: Simulador Educativo de Procesadores
SimCo: Simulador Educativo de Procesadores
Federico Rivero
Tutores: Eduardo Grampín, Matías Richart
29 de julio de 2014
1
1. R ESUMEN
Dada la realidad presentada anteriormente, el objetivo del proyecto es realizar una actuali-
zación en la materia de simulación en arquitecturas de computadoras, encontrar espacio
abierto de investigación en el área y finalmente desarrollar o extender un simulador con
enfoque educativo y con soporte de simulación para procesadores multihilo y multinúcleo,
para uso en las asignaturas del Departamento de Arquitectura, Sistemas Operativos y Redes
de Computadoras del Instituto de Computación, Facultad de Ingeniería.
2
Í NDICE
1. Resumen 2
2. Introducción 5
2.1. Arquitectura y Microarquitectura de Computadoras . . . . . . . . . . . . . . . 5
2.2. Simulación en Arquitectura de Computadoras . . . . . . . . . . . . . . . . . . . 6
2.3. Procesadores Multinúcleo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3.1. Esquemas de memoria compartida . . . . . . . . . . . . . . . . . . . . . 8
2.3.2. Tipos de redes de interconexión . . . . . . . . . . . . . . . . . . . . . . . 9
2.3.3. Arbitraje en NoCs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3.4. Coherencia de cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
4. Desarrollo de SimCo 21
4.1. Requerimientos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.1.1. Requerimientos funcionales . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.1.2. Requerimientos no funcionales . . . . . . . . . . . . . . . . . . . . . . . 23
4.1.3. Metodología y condiciones de implementación . . . . . . . . . . . . . . 24
4.2. Análisis y Diseño . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.2.1. Diagrama de clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
4.2.2. Algoritmo de simulación . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.3. Análisis de riesgos y Plan de desarrollo . . . . . . . . . . . . . . . . . . . . . . . 29
4.4. Consideraciones de implementación . . . . . . . . . . . . . . . . . . . . . . . . 31
4.4.1. Implementación del sistema de eventos . . . . . . . . . . . . . . . . . . 31
4.4.2. Sistema de memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.4.3. Arquitectura MIPS32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.4.4. Ancho de la arquitectura simulada . . . . . . . . . . . . . . . . . . . . . . 34
4.4.5. Memoria Cache . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
4.4.6. Archivo de configuración . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.5. SimcoViewer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.6. Verificación y ejemplos de uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5. Conclusiones 49
6. Trabajo Futuro 50
7. Apéndices 52
7.1. Protocolos de coherencia de cache . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3
7.2. Propuesta de investigación con SimCo . . . . . . . . . . . . . . . . . . . . . . . 52
7.3. Ejemplo de archivo de configuración de SimCo . . . . . . . . . . . . . . . . . . 54
4
2. I NTRODUCCIÓN
Dado que durante este trabajo se realiza un trabajo muy íntimo con la arquitectura y microar-
quitectura de las computadoras, es conveniente comenzar definiéndolas. La arquitectura de
una computadora (o su más descriptivo nombre en inglés: Instruction Set Architecture - ISA),
refiere a aquellos aspectos de la computadora que son visibles al programador, mientras que
la microarquitectura concierne a cómo esta se implementa. Dentro de la arquitectura de una
computadora quedan incluidos elementos tales como el set de instrucciones del procesador
y qué registros programables contiene, mientras que dentro de la microarquitectura se
incluyen aspectos tales como la disposición de los componentes, qué frecuencia de reloj se
utiliza o qué tecnología de fabricación de semiconductores es utilizada.
5
Si se realiza una abstracción por capas de la estructura lógica utilizada en la programación y
ejecución de un programa, se explicita que todo lo que queda por debajo de la arquitectura
refiere a aspectos de hardware, mientras que aquellas capas superiores corresponden a
piezas de software. Por esta razón es que la arquitectura de computadoras es referida como
la interfaz entre el hardware y el software, denominación que será utilizada a lo largo del
trabajo pues es más apropiado que el término arquitectura de computadoras, dado que el
objetivo del proyecto no es simular totalmente una computadora según la definición más
común que se tiene de ella [4], sino limitarse a los procesadores y su interacción con el
sistema de memoria.
Como se verá a lo largo de este trabajo, es posible simular con más precisión que a ni-
vel de ciclo, obteniendo resultados intermedios. A ese tipo se los llamará simuladores de
precisión de subciclo. Por último, a un simulador que simule fielmente el hardware de un
procesador, calculando en software el valor de las señales físicas y su propagación a través
de las compuertas lógicas se lo llamará simulador de señales. La decisión de qué simulador
utilizar o desarrollar se debe realizar en función de dos parámetros esenciales, generalmente
contrapuestos: el nivel de detalle que se desea obtener y la velocidad a la que se desea
simular. Existen situaciones en las cuales uno de los dos parámetros no es relevante, como
por ejemplo al simular un programa muy corto, o si directamente un cierto nivel de detalle
ya no es relevante, pero en general la decisión dependerá de la ponderación de ambas
6
Figura 2.2: Clasificación de simuladores de procesadores en base a su nivel de detalle
variables.
7
Figura 2.3: Rol de la simulación en conferencia HPCA
más importantes de este tipo de procesadores, los cuales no son abordados en la currícula
básica del ingeniero en computación. A nivel lógico (es decir, dejando de lado consideracio-
nes físicas), un multiprocesador consiste en múltiples CPU’s, conectadas por una cierta red
y operando con un cierto conjunto de memoria, generalmente compartida. Cuando dichos
procesadores se encuentran dispuestos en un mismo chip, se denominan procesadores
multinúcleo (multicore), y a la red que los interconecta se la denomina Network on Chip
(NoC). Se diferencian de una red de computadoras tradicional en que en la mayoría de los
casos la interconexión no se realiza a través del subsistema de entrada/salida.
8
Figura 2.4: Procesador de memoria compartida UMA - Imagen tomada de [1]
En [5] se define una red de interconexión como un sistema programable que transporta datos
entre terminales. A lo largo de este trabajo se abordarán dos tipos de redes de interconexión
diferentes: buses y redes basadas en switches, aunque de los dos, mayoritariamente se
utilizará el medio de difusión clásico de las computadoras: el bus. Se dará por sentado que
el lector conoce las características elementales de este elemento de la arquitectura Von
Neumann.
9
Figura 2.5: Procesador de memoria distribuida (compartida o no compartida)
Imagen tomada de [1]
la topología de la red es buena, se logra proveer un ancho de banda superior que con un
bus. La contrapartida de este beneficio es que se deben resolver los problemas tradicionales
de redes, como el enrutamiento y el reenvío, la pérdida de paquetes por sobrecarga en los
conmutadores, entre otras. Estas complejidades serán abordadas superficialmente a lo largo
del presente trabajo.
2.3.3. A RBITRAJE EN N O C S
10
(a) Red malla de dos dimensio-(b) Red toroide de dos dimen-
nes siones
tanto el CPU como los dispositivos de entrada salida deben hacer uso del bus, durante la
mayoría del tiempo es el CPU quien lo controla. Al agregar otros procesadores al dominio de
difusión, se aumenta la probabilidad de que estos deseen hacer uso del medio compartido
al mismo tiempo. La función de arbitraje en estos casos cobra mayor importancia.
Funciones de arbitraje clásicas de los buses son round robin, la cual consiste en asignar el
control del bus a los distintos dispositivos en forma equitativa en el tiempo, y least recently
served, en el cual se asigna control del bus a aquel dispositivo que hace mayor tiempo realizó
su última transferencia.
1
Se denomina problema de coherencia de cache, cuando por algún motivo el valor contenido en un cache
no es el correcto según el sistema de memoria. Por ejemplo, si un controlador DMA escribe un valor en
una dirección de memoria principal, la cual estaba guardada también en memoria cache, si no se toma
ninguna acción y el procesador realiza una lectura a dicha dirección, obtendrá el valor desactualizado
desde el cache.
11
se denominan protocolos de husmeo (snooping protocols), son usados fundamentalmente
en procesadores simétricos (ver figura 2.4) y consisten en que los caches de último nivel
(last level caches - aquellos que están más cerca de la memoria principal) estén pendientes
de las transferencias realizadas en el bus principal, de forma tal que al notar un pedido de
lectura o escritura a una dirección contenida en el cache, se tomen las acciones necesarias
para que no ocurra un problema de coherencia (por ejemplo, si se realiza una escritura
en el bus principal a una dirección que está en un cache, dicho cache puede actualizar
el valor guardado con el valor disponible en el bus). Los protocolos del segundo grupo se
denominan protocolos basados en directorios (directory based protocols), son utilizados
generalmente en sistemas de memoria distribuida (ver figura 2.5) y consisten en disponer
de forma centralizada el estado de cada bloque de memoria, en estructuras de hardware
llamadas directorios. De este modo, cuando se quiere realizar una lectura o escritura sobre
una línea de cache, se envía un mensaje al directorio indicando la acción realizada, para
que este tome las medidas necesarias para mantener el sistema de memoria consistente.
Por ejemplo, si un cache de algún procesador contiene el valor de una cierta dirección de
memoria y otro procesador quiere escribir en la misma dirección, al escribir el valor en
su cache, se le avisará de la escritura al directorio correspondiente, quien a su vez enviará
un mensaje al otro cache para o bien actualizar el valor o para invalidar la línea (según el
protocolo utilizado).
En este proyecto se trabaja con ambos tipos, a nivel de husmeo se utilizan los protocolos
MSI (utilizado en la bibliografía a modo educativo) y MESI (implementado actualmente a
nivel comercial). En el apéndice se encuentra una descripción de dichos protocolos.
12
3. E STADO DEL A RTE EN S IMULACIÓN DE P ROCESADORES
En esta sección se describirá el trabajo realizado como relevo del estado del arte en el área
de simulación de procesadores.
Además se encontró que muchos artículos en los cuales se proponían nuevas técnicas o
diseños para procesadores validaban sus resultados usando algún simulador, por tanto, la
otra fuente de datos para el estado del arte fueron los artículos presentados en las últimas
conferencias internacionales en la materia de arquitectura, microarquitectura y diseño de
computadores [2], [3] [6] [7] [8].
1. SimpleScalar
13
distribución incluye además varias versiones más simples del simulador, en las cuales
se gana mayor velocidad de ejecución a cambio de menos funcionalidades.
SimpleScalar fue considerado un estándar de facto a principios del 2000 por su enorme
popularidad en la comunidad científica y la evidencia de esto es innegable. Como
se informa en su página ’Who’s using it?’, más de un tercio de los artículos en diseño
de computadoras publicados en el 2002 validaban sus resultados en SimpleScalar.
Otro de los reconocimientos que se debe hacer al SimpleScalar es que fue uno de los
primeros simuladores de procesadores y de los que más influyeron en la orientación
de la comunidad hacia el uso de estos para evaluar el rendimiento de nuevos diseños,
como se puede ver en en la figura 2.3.
2. Graphite
Si bien Graphite parece muy prometedor por la proclama de estar desarrollado mo-
dularmente, tiene la desventaja de ser sumamente nuevo y por tanto no disponer de
demasiadas herramientas.
3. SESC y ESESC
SESC [29] y ESESC [17] son dos simuladores desarrollados por el grupo de i-acoma de
la University of Illinois, siendo el segundo un modificación del primero (E viene de
Enhaced). Es un simulador de rendimiento con precisión de ciclo, modular, el cual
implementa multiprocesadores con variadas interconexiones y configuraciones de
memoria. Lo más atractivo de SESC es la filosofía con la cual fue implementado, ya
que la justificación del grupo para la implementación de un nuevo simulador fue
crear uno con buena documentación, de forma tal que fuera fácilmente extensible,
como se puede ver en el siguiente pasaje tomado del artículo de presentación de SESC:
"The biggest challenge for new students in architecture research groups is not passing
14
theory or software classes. It is not finding a new apartment or registering with the
INS. It is understanding the architecture of the processor simulator that will soon
confront them. A simulator coded not for perfection, but for deadlines. Even the most
well-conceived simulator can quickly look like a Big Ball of Mud to the unitiated."[29].
ESESC es un simulador basado en SESC, el cual tiene como objetivo principal lograr
simulaciones rápidas, haciendo uso de una simulación estadística (ver las conclu-
siones del estudio para una explicación de esta técnica). Si bien en su artículo de
presentación parece muy prometedor y seguramente lo sea, al estudiarlo se encontró
que los agregados no aportan demasiado para los intereses del proyecto, ya que el
aumento de velocidad de ejecución está apuntado a la comunidad científica, que tiene
necesidad de realizar extensas y reiteradas simulaciones sobre varias configuraciones
de diseño diferentes, a fin de explorar los beneficios de cada una.
4. gem5
5. Otros simuladores
2
Se denominan simuladores de sistema completo (full sistem simulators), a aquellos simuladores que imple-
mentan un sistema computacional completo, de forma tal que programas reales puedan ejecutar sobre
ellos sin modificaciones, incluyendo sistemas operativos.
15
GPUs no fueron incluidos en la reseña por encontrarse fuera del alcance del proyecto, se
encontraron varios artículos presentando estos simuladores [14] [15]. A nivel de simulación
de multicores, la preocupación más notoria se encuentra en lograr que las simulaciones
sean más veloces. Esto es lógico si se piensa que a mayor cantidad de núcleos que contenga
el sistema computacional a simular, mayor es el esfuerzo que se debe realizar para simularlo.
Si se toma como referencia el SimpleScalar [10], el cual es un procesador cycle-accurate y
ejecuta cientos de KIPS (en el orden de un millón de veces más lento que lo que ejecutaría la
máquina simulada), resulta presumible que la simulación de un procesador con mil núcleos
sea mil veces más lenta 3 logrando una velocidad de simulación de algunas instrucciones por
segundo, algo totalmente inaceptable. Varias técnicas se han implementado para afrontar
esta problemática: simuladores paralelizables [13]; simulación estadística [18] [17], la cual
consiste en hacer varias simulaciones de pequeñas porciones del programa y tomar los
resultados como generales, basándose en el teorema central del límite. Para poder realizar
una simulación real de una porción de código cualquiera primero se debe aplicar la técnica
de checkpointing, la cual consiste en realizar una simulación funcional del programa, de-
jando como salida una traza del estado del sistema computacional ciclo por ciclo y luego
realizar las simulaciones de pequeñas porciones partiendo de algún punto en particular
(checkpoint); o simulación acelerada por FPGA [19], la cual consiste en programar el análisis
temporal en hardware reconfigurable (FPGA).
Por otra parte, se apreció que en los últimos años han aflorado estudios de investigación en
arquitecturas heterogéneas, llamadas APU (accelerated processing units), las cuales integran
CPU y GPGPU en la el mismo chip [16], delegando las secciones de código mayormente
paralelizables para que sea ejecutada en la GPGPU mientras que la CPU ejecuta las fun-
ciones del sistema operativo y otras porciones de código más irregulares. A pesar de este
interés, no se encontraron simuladores orientados a modelar este tipo de organizaciones,
o siquiera alguno que aclamara poder hacerlo. Este es un posible punto de interés para
futuros proyectos.
Otro tema activo de investigación es el del control térmico y energético de los componen-
tes computacionales. Se encontró un gran número de artículos orientados a disminuir el
consumo de procesadores, memorias y demás, los cuales también basaban sus resultados
en simulaciones (ver [20] como ejemplo). Conjuntamente con esto se encontró que mu-
chos simuladores han agregado en los últimos años funcionalidades que permiten modelar
componentes físicos de los procesadores (por ejemplo [17]), como ser la tecnología de
fabricación, material de construcción, velocidad del ventilador, temperatura ambiente y
unas cuantas otras variables, que permitieron determinar a simple vista la complejidad de
los modelos implementados.
3
Más adelante se verá que el orden de ejecución de un simulador es generalmente superlineal en el número
de procesadores, por lo cual la suposición anterior es en el mejor de los casos una cota superior de la
velocidad de simulación
16
3.3. E VALUACIÓN DE TRABAJO FUTURO
Una vez culminado el estudio del estado del arte, se estuvo en condiciones de evaluar cómo
debía continuar el proyecto. Dicha tarea consistió en decidir si se iba a desarrollar un nuevo
simulador o si se iba a extender alguno de los vistos durante el estudio previo.
Realizar una comparación de los simuladores es complejo pues hay muchas características
deseables que no todos cumplen, por esta razón, se elaboró un cuadro comparativo con las
características deseables del simulador elegido, el cual ayudará para definir una métrica.
Para cada característica, se utilizó un rango del 1 al 5 para cuantificar, entendiendo un 1
como que no cumple con la característica y 5 como que la cumple muy bien (por ejemplo,
en el ítem ’Configurabiidad de la jerarquía de memoria’ se le asignó un 3 al SimpleScalar,
pues si bien modela caches, sólo permite configurar uno o dos niveles de jerarquía).
17
Es importante que se domine completamente el código del simulador, para de este
modo poder asesorar correctamente las extensiones al proyecto, tanto propias como
por parte de otros estudiantes de grado. Además, también es importante el dominio a
nivel de usuario, para poder facilitar la enseñanza del uso del mismo.
Del análisis realizado se eligió en primera instancia a SESC como simulador a extender, por la
gran cantidad de funcionalidades que brinda y porque la filosofía con la que está escrito está
alineada con la filosofía del proyecto. Entre todos los simuladores estudiados, realizando
un análisis informal parece ser aquel con el cual se obtendrían más eficientemente los
resultados del proyecto.
Se trabajó durante poco más de un mes sobre este simulador, estudiando sus módulos y
modificando el código en puntos clave para obtener nuevas estadísticas. Se logró obtener
nuevos datos como salida del simulador, que cuantifican los fallos producidos por false
sharing 4 .
Pasado poco más de un mes de trabajo, el dominio del simulador no era demasiado. To-
do aparentaba a que, proyectando el mismo ritmo de trabajo durante el resto del plazo
del proyecto, no se obtendrían resultados interesantes. Esto se debió principalmente a la
complejidad del código, tanto algorítmica, como de estilo, debido a que actualmente hay
múltiples colaboradores en el desarrollo del simulador. Además, durante este período de
trabajo se estudiaron diferentes posibilidades para implementar el algoritmo principal del
simulador, encontrando que modificar SESC para que utilice aquel que se encontró como
óptimo, conllevara una cantidad de trabajo demasiado grande. Debido a este lento avance,
se decidió realizar el análisis del esfuerzo necesario para desarrollar un nuevo simulador.
En esta sección se presenta un cronograma aproximada del trabajo de esta parte del proyecto,
donde se muestra el esfuerzo dedicado a cada tarea:
1. Agosto 2013:
18
meses del proyecto se estudió su funcionamiento, la organización de los mismos,
cómo se utilizan desde el punto de vista del sistema operativo, cómo es el proceso
de booteo, etc. El estudio se basó fundamentalmente en la lectura del libro
’Computer Architecture: A Quantitative Approach’ de Hennessy y Patterson [1] y
el manual de la arquitectura IA32 [42].
Estudio del simulador SimpleScalar: Para poder realizar el estudio del estado
del arte, primero se debía tener un mínimo de experiencia con simuladores
de procesadores para poder evaluar los demás de forma correcta. Se estudió el
funcionamiento del simulador SimpleScalar, pues es un simulador simple y no
demasiado abarcativo. Se estudió el código del mismo, lo cual permitió aprender
no sólo de simuladores, sino de organizaciones avanzadas de procesadores
superescalares.
2. Setiembre 2013:
3. Octubre 2013:
4. Noviembre 2013:
19
Desarrollo con SESC: Dado que se eligió el simulador SESC para como simulador
a extender, se trabajó en él, estudiando su código y modificándolo para incorpo-
rar nuevas funcionalidades, las cuales fueron mencionadas en puntos anteriores
de este documento.
5. Diciembre 2013:
20
4. D ESARROLLO DE S IM C O
4.1. R EQUERIMIENTOS
Teniendo la anterior descripción como punto de partida se pueden detallar los siguientes
requerimientos.
21
3. Configurabilidad del sistema de memoria: Se permitirá configurar un sistema de me-
moria consistente en varios niveles de cache y memoria principal. Se deberá poder
especificar si se trabajará con memoria centralizada o distribuida, debiéndose indicar
en este último caso qué rangos de direcciones se asocian a cada dispositivo de me-
moria DRAM. En cualquiera de los dos casos, para cada DRAM configurada se deberá
especificar como mínimo:
22
Algoritmo de arbitraje a utilizar
5. Generación de trazas: El simulador deberá generar como salida una traza que describa
el estado del sistema computacional en todo momento.
7. Visor de trazas: Una vez terminada la simulación, se deberá poder visualizar la traza
generada a través de una interfaz gráfica, de forma que permita identificar fácilmente
el estado de cada componente en todo momento.
2. Velocidad de ejecución: Si bien para los primeros usos el tiempo de ejecución del
simulador no será crítico, es probable que eventualmente sea utilizado con fines de
investigación, donde la velocidad de ejecución sí es crítica para una ágil exploración
del espacio de diseño. Por esta razón se tomarán donde se pueda decisiones que
mejoren la velocidad de ejecución de la aplicación.
23
4.1.3. M ETODOLOGÍA Y CONDICIONES DE IMPLEMENTACIÓN
En esta subsección se detalla el resultado del análisis del dominio a implementar, así como
algunos diagramas que ilustran las relaciones entre las principales clases. Dado el gran
número de clases que forman parte del modelo de dominio, el mismo se presentará de
forma dividida. La arquitectura de la aplicación se puede descomponer en algunas clases
principales:
ISA: Clase abstracta, base de cualquier set de instrucciones. Provee funciones para
traducir instrucciones de binario y String al modelo genérico de instrucciones del
simulador y viceversa. Además provee funciones de construcción del set de registros
de la arquitectura.
ComputationalSystem: Clase principal de la aplicación, contiene referencias hacia
todos los elementos relevantes de la simulación.
MemorySystem: Esta clase mantiene la colección de los diferentes dispositivos de
memoria que integran el sistema, así como un mapa de memoria (para los casos de
sistemas de memoria distribuida), el cual indica qué direcciones globales se mapean
a qué dispositivo.
MemoryDevice: clase base para todos los dispositivos de memoria (DRAM, cache),
contiene algunas variables comunes a estos, como latencia, número de puertos, y
24
mantiene estadísticas como número de accesos, cantidad de lecturas, de escrituras,
etc.
Processor: Clase base para todos los procesadores a soportar. Contiene algunos ele-
mentos que se prevee serán comunes a todos los procesadores: un program counter,
la referencia al set de registros de la arquitectura y links hacia los objetos de tipo
’InterconnectionNetwork’ a través de los cuales se accede a la memoria de datos e
instrucciones.
Interconnection Network: Clase abstracta, base de todas las interconexiones entre
dispositivos del sistema. Las implementaciones más usuales de este clase son Bus y
P2PLink. Un bus conecta N dispositivos entre si, mientras que un P2PLink conecta
dos switches, un switch y un dispositivo de memoria, o un switch y un procesador.
Loader: Clase abstracta, base para cualquier loader, tiene la responsabilidad de leer el
archivo con el programa a ejecutar y colocarlo en memoria.
ConfigManager: Clase Singleton encargada de realizar el parseo y carga de la configu-
ración.
25
Modelo genérico de arquitectura
26
Con esta solución, para aceptar un nuevo set de instrucciones, se debe implementar una
subclase de ‘ISA’ que provea los métodos de conversión de instrucciones de binario a la
estructura de clases presentada anteriormente, una clase que herede de Loader que realice la
carga desde un archivo de texto, y la ejecución de las instrucciones únicas de la arquitectura,
dentro del procesador.
Es digno de mencionar que el modelo presentado no contempla todos los sets de instruc-
ciones existentes. En particular no permite modelar aquellos de las arquitecturas EPIC
[21] aunque puede ser extendido para hacerlo (por ejemplo, definiendo una clase hija de
instrucción la cual se asociará con un conjunto de instrucciones).
Para esta versión de SimCo se implementó una versión reducida de la arquitectura MIPS32.
La especificación de esta arquitectura se encuentra en [30]. Se decidió incorporar esta
arquitectura por dos razones: es una arquitectura RISC, muy simple, y es utilizada en algunos
cursos del Instituto de Computación [31]. Dado lo extenso del proyecto, es importante no
agregar complejidad en áreas no medulares, por lo tanto la elección de una arquitectura
simple es imperativa. La especificación de la arquitectura se implementa en dos clases:
MIPS32ISA, la cual extiende la clase ISA y contiene la especificación del set de instrucciones,
y MIPS32Loader, la cual extiende la clase Loader y es la encargada de realizar la carga de
las instrucciones desde archivo a la memoria del simulador, implementando funciones de
ensamblador, como resolver etiquetas. Utiliza las funciones de MIPS32ISA para realizar las
traducciones a binario.
Para modelar también el arbitraje del medio compartido, se definió un método requestAccess,
el cual es utilizado como punto de sincronización para la función de arbitraje del medio
compartido. Esta decisión no afecta la implementación de buses más simples donde tal fun-
ción no aplique, pudiendo la implementación simplemente llamar al método accessGranted
del solicitante. Para soportar la existencia de dicho método sea cual sea el dispositivo que
solicita acceso al medio, se define una interfaz IMessageDispatcher la cual implementa-
rán todas las clases que tengan que hacer uso de algún medio compartido (procesadores,
memorias, controladores de diccionario, switches, etc).
27
Figura 4.3: Diagrama de clases - Red de interconexión
Por último, para el caso de redes basadas en conmutadores (switches), se define una clase
P2PNetwork que tendrá la información de la topología de la red implementada y será
consultada por los conmutadores al momento de realizar los reenvíos. Además detectará la
aparición de deadlocks o livelocks en configuraciones que lo permitan.
Donde la condición de finalización de simulación está dada o bien porque se llegó al límite
de ciclos ingresado en la ejecución, o porque todos los procesadores culminaron la ejecución
de sus respectivas porciones de código.
Si bien el algoritmo principal parece trivial, la complejidad se presenta al respecto del refina-
28
miento de dicho pseudocódigo. Dado que en cada ciclo de reloj se simularán varias acciones
que ocurren de forma concurrente y de las cuales varias son mutuamente dependientes, se
deberá mantener durante toda la iteración el estado del sistema al inicio del ciclo de reloj y
además los cambios calculados para el próximo ciclo (si se utilizara una única variable se
podrían calcular resultados en función de valores que no deberían ser ’visibles’ aún para los
eventos del simulador). Por esta razón, el pseudocódigo de cada iteración será en principio
el siguiente:
Donde ’actualizar inicio de ciclo’ incluye, como fue mencionado anteriormente, actualizar
el estado de cada entidad simulada con los cambios calculados durante el ciclo anterior.
El while siguiente en el pseudocódigo se puede interpretar simplemente como realizar
las acciones del sistema computacional para ese ciclo. Se decidió utilizar eventos como
unidad de simulación en lugar de iterar sobre las entidades simuladas y realizar las acciones
correspondientes, fundamentalmente para desacoplar el orden en que deben ser ejecu-
tados los eventos de los eventos en si. De este modo, cuando se simula una acción en un
componente que desencadena una en otra entidad, simplemente dispara un evento y lo
agenda en el simulador en el tiempo correspondiente. Por ejemplo, cuando un dispositivo
de memoria recibe un pedido de una palabra de memoria, si la latencia de este fuera nula,
la devolución podría ser inmediata mediante una llamada a la función submitMessage del
medio compartido que la conecta al resto del sistema y dicha llamada podría estar escrita
directamente en el código, sin embargo, si la latencia fuera t mayor que cero, esa llamada
tendría que realizarse t ciclos después y por tanto la llamada no podría estar codificada del
mismo modo. Con el sistema de eventos, ambas pueden ser tratadas de la misma manera,
simplemente cambiando la cantidad de ciclos en la cual se debe realizar la llamada.
29
características más particulares de SimCo en primer lugar (el modelo genérico de arquitec-
tura y la interconexión), y la implementación de procesadores luego. De esta forma, si el
alcance resultara excesivo, se podría limitar sobre la marcha y aún contar con un producto
útil (que por lo menos permitiera estudiar el desempeño de un sistema de memoria en
multiprocesadores).
Cronograma de desarrollo
Arbitraje de buses.
Implementación de memorias cache
Implementación de un protocolo de coherencia de cache para memoria de
acceso uniforme, por ejemplo bus snooping.
Switches.
Algoritmo de enrutamiento ’Direction Order Routing’ para topología de malla de
dos dimensiones.
Controlador de ‘Directorio’ para protocolo de coherencia de cache basado en
directorios.
30
5. Iteración 4: 07/04/2014 - 28/04/2014
Dado que cada iteración se planificó para ser implementada en dos semanas, del crono-
grama final de implementación se puede deducir la desviación obtenida durante cada
etapa.
El desarrollo de los módulos propuestos para cada etapa se encuentra completo, a excepción
del módulo de redes basadas en switches, el cual si bien es utilizable en el simulador, su
verificación no fue completa y hay algunas fallas documentadas en el código. A su vez, la
visión de los resultados de estas redes en la aplicación SimcoViewer aún no está completa.
Dado que el disparo de un evento consiste en agendar una función a ser ejecutada duran-
te un cierto tiempo posterior, una implementación sencilla del sistema de eventos sería
poder guardar funciones como si fuera cualquier otro objeto en alguna estructura de tipo
calendario. Como C++ no permite el tratamiento de funciones como parámetro a otras
funciones (como se realizaría en algún lenguaje de programación funcional como Haskell
[25]), la estrategia abordada fue definir una interfaz IEventCallback con una única función
simulate y una clase que herede de ella por cada tipo de evento existente en el sistema, que
en la implementación de simulate llame a la función correspondiente. De este modo, en
31
el bucle principal del simulador se puede mantener una estructura de objetos IEventCall-
back, los cuales al invocárseles el método simulate, gracias al polimorfismo de esta función,
provocarán la invocación a la función correspondiente.
Como para cada ciclo puede existir un número no acotado de eventos, la estructura elegida
para mantener los eventos para cada ciclo es una cola. A su vez, se guarda una cola de estos
eventos para cada ciclo en los que existan eventos agendados.
Esta estrategia, utilizada extensamente en sistemas de memoria virtual para mantener las
32
tablas de páginas, permite reducir drásticamente la memoria utilizada en caso de que sólo
un subconjunto de la memoria esté en uso, y aún así mantener de forma ordenada el espacio
de direccionamiento (es decir que es fácil obtener el valor de una palabra y las siguientes
dada una dirección) sin el overhead de otras estructuras de datos como un diccionario
hash.
5
Las arquitecturas Load/Store son aquellas que acceden al sistema de memoria únicamente a través de
las instrucciones clásicas Load (cargar desde memoria) y Store (guardar hacia memoria). MIPS32 es una
arquitectura Load/Store.
33
mientras que en los saltos condicionales el resultado se conoce recién luego de la eje-
cución. Del set de instrucciones implementado se mapean a esta clase las siguientes
instrucciones: j, jal.
El ancho de una arquitectura especifica entre otras cosas, de cuántos bits disponen sus
registros. De este modo, si una arquitectura es de 64 bits, sus registros serán típicamente
de 64 bits. Actualmente la mayoría de las arquitecturas son de 32 y 64 bits y a lo largo de la
historia se han construido también máquinas de 16 y 8 bits. Esto indica que eventualmente
podrían existir máquinas de 128 bits o más grandes aún 7 , por lo tanto sería interesante que
SimCo aceptara tales características. Dicha incorporación no es trivial: si se considera la
jerarquía de instrucciones presentada en 4.2, el valor del operando ’Inmediato’ diferirá en
tamaño según el ancho de la arquitectura (pudiendo requerir hasta 128 bits en arquitecturas
de este tamaño). A su vez, la variable con la cual se modelará el valor de cada registro
también puede exigir 128 o más bits de memoria en arquitecturas de ese ancho. Para la
elección del tipo de dato con el cual se guardarán esos valores se consideraron los siguientes
candidatos:
34
2. Una variable del tipo ’long int’ de C++, la cual es guardada en memoria con 64 bits en
la mayoría de los sistemas. Ésta solución no permite la incorporación de arquitecturas
de 128 y más bits pues dicha variable no es suficiente para guardar el valor completo
de un registro. Sin embargo, presenta la enorme ventaja de ser de muy simple y de
rápida manipulación (es posible usar los operadores definidos en el lenguaje C++ para
operarlas).
Dado el análisis anterior se decidió implementar los anchos de los registros y demás valores
críticos con variables ’long int’, fundamentalmente para no agregar más complejidad aún a
la implementación. No se descarta un cambio en la implementación en algún futuro y por
lo tanto se deja presentada una alternativa que aborde el problema de forma general.
8
El simulador Zesto presenta una solución bien documentada al problema de accesos de memoria que
involucren varias líneas de cache [34].
35
actualizados en los niveles inferiores de la jerarquía de memoria. Si se utiliza la política de
escritura writethrough, se propaga la escritura hacia la siguiente memoria.
En caso de producirse un fallo en el acceso, la primera acción es ubicar una línea del
cache para colocar el nuevo bloque de memoria a cargar. Si existe alguna línea libre en
el conjunto correspondiente, se la asigna. De lo contrario se selecciona alguna linea a
liberar mediante la política de reemplazo utilizada. En cualquier caso, la línea que está
por ser reemplazada se la marca como efímera, posteriores lecturas y escrituras sobre
líneas efímeras se tratan de forma normal, sin embargo, en el anexo se presenta una idea
de diseño al respecto de las líneas efímeras que puede ser explorada con el simulador.
Una vez elegida la línea que ubicará el bloque accedido, se inicia un pedido de lectura de
bloque hacia el siguiente dispositivo de memoria. Cuando este es devuelto, se escribe en la
línea seleccionada, realizando una escritura del bloque en caso de que este se encuentre
modificado y se utilice la política de escritura writeback.
Todas las escrituras que se deben realizar sobre los niveles inferiores de la jerarquía se
realizan a través de un buffer de escritura 9 , el cual actualmente tiene largo infinito. Como
trabajo futuro se debería permitir configurar la cantidad de mensajes permitidos en dicho
buffer, así como definir qué hacer en caso de que se deba realizar una escritura en un nivel
inferior de memoria y el buffer de escritura se encuentre completo.
9
Un buffer de escritura (write buffer) es una pequeña memoria incluida en los sistemas de memoria cache para
almacenar temporalmente valores a escribir en niveles inferiores de la jerarquía. Su utilidad es no bloquear
al CPU cuando algún acceso de este desencadena una escritura a un nivel inferior, dejando los valores a
escribir accesibles en el buffer mientras son escritos en memoria principal. Cuando posteriormente se
realice una lectura en cache y esta resulte en miss, se deberá chequear el buffer para verificar si no contiene
el valor buscado, antes de buscar el dato en el nivel inferior de la jerarquía. Más sobre buffers de escritura
se puede encontrar en [33]
36
(a) Principal
SimcoViewer es el nombre del visor de trazas del simulador. El objetivo del mismo es
presentar los resultados obtenidos a través de SimCo de un modo más amigable para el
usuario, mediante una interfaz gráfica. Este punto, aunque menor para muchos programas,
es en el proyecto de vital importancia, ya que una compleja presentación de los resultados
puede provocar que el simulador no sea útil a nivel educativo.
Dado que los sistemas computacionales a simular pueden variar muchísimo, desde un
microcontrolador con memoria principal únicamente, pasando por una organización multi-
núcleo y varios sistemas de cache como en la figura 4.8, hasta clusters con una centena de
núcleos de ejecución y una red de interconexión basada en switches, es claro que la interfaz
gráfica deberá ser fundamentalmente flexible. Por esta razón se eligió que la pantalla princi-
pal del visor presente los diferentes elementos que componen el sistema computacional,
pudiéndose abrir una nueva ventana para ver el estado ciclo a ciclo de cada uno. En la
ventana principal existirán comandos que permitan avanzar el estado, el cual será reflejado
en las diferentes entidades.
37
4.6. V ERIFICACIÓN Y EJEMPLOS DE USO
A continuación se muestran algunos ejemplos de uso de SimCo, los cuales servirán además
como validación del funcionamiento del simulador, pues las salidas se verificarán contra
resultados teóricos.
En esta prueba se mostrará cómo SimCo puede ser utilizado para mostrar el resultado
38
de una ejecución. Esto podría ser útil en cursos de lenguaje ensamblador, para que
los estudiantes pueden corroborar los resultados de sus programas. Para esta parte, el
programa utilizado es el siguiente:
ORG 0x5000
XOR R2, R2, R2 # se carga el registro R2 con valor 0
XOR R3, R3, R3 # se carga el registro R3 con valor 0
XOR R4, R4, R4 # se carga el registro R4 con valor 0
ADDI R2, R2, 1 # se suma 1 al registro R2
SLL R2, R2, 4 # se realiza un corrimiento de 4 lugares del registro R2
OR R3, R2, R3 # R3 = R2 OR R3 (equivalente a la asignación pues R3 tiene
el valor 0)
LLO R4, 1 # Se carga 1 en los bits menos significativos de R4
SUB R3, R3, R4 # R3 = R3 - R4
ADD R5, R3, R2 # R5 = R3 + R2
HALT
El código del programa es muy simple. En él, se realizan algunas operaciones arit-
méticas, las cuales están explicadas en los comentarios. Al simular la ejecución del
programa en SimCo con cualquier configuración de memoria e interconexión y car-
gando la traza generada en la aplicación SimcoViewer, se pueden ver los resultados
obtenidos por cada una de las operaciones. En la figura 4.6, se muestra una captura de
pantalla al ejecutar la instrucción ’ADD’, donde se pueden verificar los valores finales
de los registros. Es sencillo observar que los resultados son los correctos.
En esta prueba se mostrará la utilidad de SimCo para estudiar la utilización del sistema
de memoria para un cierto programa. Se utilizará un uniprocesador con una jerarquía
de memoria de tres niveles como el de la figura 4.8. A continuación se presenta la
configuración de la jerarquía de memoria:
Cache L2 Unificada
Sets: 16
Asociatividad: 4
Tamaño de línea: 32 bytes
Política de remplazo: LRU
Política de escritura: writeback
39
Figura 4.6: Estado final de registros en ejemplo 1
Cache L3 Unificada
Sets: 32
Asociatividad: 8
Tamaño de línea: 128 bytes
Política de remplazo: LRU
Política de escritura: writeback
ORG 0x5000
# Iniciación de variables
ANDI R2, R2, 0
LLO R2, 64
ANDI R1, R1, 0
LLO R1, 0x1000 ; dirección de comienzo 0x1000
# Itero palabras
loop:
SW R2, 0, R1
40
ADDI R1, R1, 4
JAL loop
Memory Cache
Name: L3cache
MemoryDevice Accesses: 33
MemoryDevice Reads: 33
MemoryDevice Writes: 0
Hit Count: 24
Miss Count: 9
Repl. Count: 0
Memory Cache
Name: L2cache
MemoryDevice Accesses: 112
MemoryDevice Reads: 65
MemoryDevice Writes: 47
Hit Count: 79
Miss Count: 33
Repl. Count: 0
Memory Cache
Name: Dl1cache
MemoryDevice Accesses: 250
MemoryDevice Reads: 0
MemoryDevice Writes: 250
Hit Count: 187
Miss Count: 63
Repl. Count: 47
Memory Cache
41
Name: Il1cache
MemoryDevice Accesses: 754
MemoryDevice Reads: 754
MemoryDevice Writes: 0
Hit Count: 752
Miss Count: 2
Repl. Count: 0
Análisis de resultados
Como indica la salida del simulador, se ejecutaron 754 instrucciones. Al analizar el flujo
del programa, se puede ver que esto incluye las cuatro instrucciones de inicialización
y 250 iteraciones del loop. Dado que se ejecutaron 754 instrucciones, se realizaron esa
misma cantidad de lecturas sobre el cache de instrucciones. Dado que los bloques del
cache IL1 tienen 16 bytes y que el programa comienza alineado con estos (la primer
instrucción se encuentra al inicio de un bloque), todo el programa queda contenido
en dos bloques de memoria, dando como resultado que de los 754 accesos, sólo dos
resulten en miss (la primera vez que se requiere alguno de los dos bloques) y los
restantes 752 sean hits.
Dado que el loop se ejecutó 250 veces, se realizaron 250 escrituras sobre el cache
de datos de primer nivel, como se puede ver en los resultados. Como la memoria se
recorre secuencialmente en el ejemplo, las direcciones accedidas son 0x1000, 0x1004,
0x1008, 0x100C, 0x1010, 0x1014, etc, las cuales están alineadas con los bloques (la
dirección 0x1000 marca el inicio de un bloque pues es múltiplo de 16). Por cada cuatro
escrituras sobre el cache, una será miss (la primer referencia a dicho bloque) y las
siguientes resultarán en hit. Como cada cuatro accesos se accede a un nuevo bloque y
reemplazos.
Para realizar el análisis sobre el cache de segundo nivel primero se contará la cantidad
de accesos. Tanto los fallos en el cache L1 de instrucciones como en el de datos
resultarán en accesos para el segundo nivel, por otro lado cada reemplazo existente en
42
el cache DL1 exigirá una escritura en el cache de segundo nivel, pues como se utiliza la
política writeback, el valor se encuentra actualizado únicamente en el cache de menor
nivel y debe escribirse en las posiciones bajas de memoria. Dado que
, se darán 112 accesos al cache de segundo nivel (DL2). De esos accesos, los misses
en primer nivel corresponden a lecturas (pues se están trayendo bloques de niveles
menores de jerarquía) y los correspondientes a reemplazos resultan en escrituras en
los niveles inferiores, por esta razón existen 47 escrituras y 65 lecturas sobre el cache
L2.
Figura 4.7: Captura de pantalla de visor de trazas Simco Viewer para el ejemplo de jerarquía
de memoria
En la figura 4.7 se puede ver una captura de pantalla del visor de trazas, donde se
evidencia cómo se podrían visualizar los diferentes componentes del sistema. Gracias
a esta disposición, se muestra que SimCo podría ser utilizado a nivel educativo para
apoyar la comprensión de los sistemas con cache (sea cual sea su configuración),
permitiendo validar suposiciones al respecto de la variación del sistema en cada ciclo.
43
será la mostrada en la figura 4.8, a excepción del cache L3, que fue removido pues
no aporta al ejemplo. Como núcleos de ejecución se utilizó la el CPU implementado
’SimpleUnipipedProcessor’ y todas las interconexiones se realizaron con buses.
Cache L2 Unificada
Sets: 16
Asociatividad: 4
Tamaño de línea: 32 bytes
Política de remplazo: LRU
Política de escritura: writeback
Protocolo de coherencia utilizado: MSI
44
# Código del procesador 1
ORG 0x5000
# Iniciación de variables
ANDI R2, R2, 0 # se realiza la operación and de R2 con 0, cargando el valor
0 en R2
ANDI R1, R1, 0
LLO R2, 35
# Carga de dirección 0
SW R2, 0, R1
# Instrucciones de relleno para demorar
ADDI R2, R2, 1
ADDI R2, R2, 1
SW R2, 0, R1
HALT
10
La directiva ORG es típica de lenguajes ensambladores para indicar que las subsiguientes instrucciones se
deberán colocar a partir de la dirección parámetro.
45
Figura 4.9: Escritura a dirección 0 por el procesador 1, por tanto, su estado pasa a ser modifi-
cado.
Figura 4.10: Lectura a dirección 0 por el procesador 2. Se provee el valor desde el cache del
procesador 1, indicando que se debe invalidar el acceso al nivel inferior de la
jerarquía. Ambas líneas pasan a estar en estado compartido.
46
Figura 4.11: Escritura a dirección 0 por el procesador 1, su estado pasa a ser modificado y se
envía un mensaje de invalidación hacia el resto de los caches.
Con los resultados de esta prueba se pretende mostrar cómo SimCo podría ser utilizado para
enseñar los algoritmos de coherencia de cache utilizados en multiprocesadores de memoria
47
compartida, así como la sobrecarga que demandan sobre la interconexión.
48
5. C ONCLUSIONES
Como resultado colateral del estudio, se logró una noción de cuáles son las propuestas
actuales a nivel de diseño de arquitectura y microarquitectura en sistemas computacionales,
lo cual permitirá en un futuro orientar de forma más precisa a aquellos estudiantes que
deseen realizar investigación en el área de arquitectura de computadoras. Esto es un aporte
al grupo de investigación MINA (Network Management - Artificial Intelligence) del Instituto
de Computación, pues actualmente no se está investigando en el área de arquitectura de
computadoras.
49
6. T RABAJO F UTURO
Las líneas de trabajo futuro serán presentadas en dos grandes grupos. En primer lugar están
aquellas mejoras y optimizaciones que por ser de una carga de trabajo pequeña no ameritan
un proyecto nuevo. En esta categoría hay varios puntos para trabajar, donde se destacan
dos: mejorar el tiempo de ejecución de la aplicación, mediante la aplicación de técnicas
de aceleración sugeridas a lo largo del código (por ejemplo, la utilización de pools 11 de
objetos para los pedidos de memoria) e implementar la interfaz gráfica para las redes de
interconexión basadas en switches.
Para el interés del grupo de investigación MINA, las posibilidades con el simulador son
bastante amplias. En el anexo se presenta un ejemplo de cómo podría ser utilizado el
simulador en el contexto de un proyecto de investigación y se presenta una propuesta de
diseño para explorar. Otra posible continuación de este proyecto a nivel de investigación se
podría centrar en el estudio de las redes de interconexión de multiprocesadores, tanto de
aquellas que se localizan dentro del mismo chip (NoC), como las que se encuentran fuera.
Según lo investigado, al día de hoy se están realizando propuestas de mejores protocolos
de enrutamiento, de detección de deadlock y livelock, de ahorro de energía, entre otras, y
por tanto proveer a SimCo de una herramienta de modelado más poderosa para estas redes
abriría puertas a más trabajos y posibles aportes.
Por último, dentro de las líneas de interés más lejanas a lo abordado por este proyecto se
encuentra el estudio del uso energético del sistema computacional. Según lo estudiado,
11
Un pool de objetos es un tipo abstracto de datos utilizado para evitar el uso intensivo de memoria dinámica
en objetos con ciclo de vida corto. El pool mantiene una colección de un cierto tipo de objetos, los cuales
están a disposición para cuando algún otro módulo los necesite. En ese momento, se solicita al pool un
nuevo objeto y cuando se termina su utilización es devuelto a la estructura.
50
permitir a SimCo el modelado de dichas variables requiere del trabajo conjunto con el área
de Ingeniería Eléctrica pero sería sin lugar a dudas de vital importancia si se desea realizar
contribuciones de vanguardia en diseño de computadoras.
51
7. A PÉNDICES
1. Protocolo MSI: A cada línea del cache se le asocia un estado, el cual indica la relacion
de los datos contenidos con respecto al resto de la jerarquía de memoria. Los estados
posibles son:
Modificado (Modified - M): La línea contiene la copia más actualizada del bloque.
Inválido (Invalid - I): El bloque contenido en esta línea está desactualizado y por
lo tanto es inválido.
Cuando se realiza un acceso a una cierta línea, según el estado en que esta se encuentre
se deberán enviar mensajes por el bus para mantener la coherencia del estado de un
cieto bloque. Por ejemplo, si un bloque se encuentra compartido (estado S) y este se
escribe en uno de los caches, primero se deberá cambiar el estado de las demás copias
a inválido.
2. Protocolo MESI: Similar al protocolo MSI pero con un estado extra (E - Exclusivo), el
cual indica que el bloque no está modificado, pero sí que es la única copia del mismo
que existe en los caches. La incorporación de este estado reduce el uso del bus común.
[1]
La definición de AMAT (average memory access time - AMAT) para una memoria cache es la
siguiente:
AM AT = Hi t _t i me + Mi ss_r at e ∗ Mi ss_penal t y
, donde hit time es el tiempo de acceso a memoria en caso de que el dato buscado se
encuentre en el cache, miss rate es la fracción de accesos fallidos al cache y miss penalty es
el tiempo extra que se debe invertir para obtener el dato en caso de que este no se encuentre
en el cache.
52
De la definición de AMAT, reducir la penalización por fallos es una de las posibles técnicas
para reducir el tiempo de acceso promedio a memoria. Las técnicas más simples se basan
en un buen diseño del cache, como aumentar la asociatividad y el tamaño de los bloques,
sin embargo, dichas técnicas tienen un cierto grado de aplicabilidad antes de volverse
contraproducentes (por ejemplo, el aumento de la asociatividad aumenta el hit time [1]).
Varias técnicas avanzadas han sido propuestas, siendo la incorporación de una cache de
víctimas (victim cache), una de las más exitosas. Una cache de víctimas consiste en una
pequeña memoria cache ubicada cerca del cache, de unas pocas líneas (4 u 8 típicamente),
totalmente asociativa, y que guarda las distintas líneas que van siendo expulsadas del cache
a causa de los reemplazos. Si se produce un fallo en un acceso, antes de solicitar el bloque
al siguiente nivel de jerarquía, se verifica si el bloque buscado se encuentra en la cache de
víctimas, como se muestra en la figura 7.1. El resultado visto de la cache de víctimas es que
aumenta temporalmente la asociatividad de cualquier bloque durante el tiempo en que éste
está siendo utilizado de forma intensiva.
Siguiendo la línea de pensamiento de las cache de víctimas, se propone una mejora a aplicar
para el caso de las líneas efímeras (transient). Una línea se denomina efímera mientras
el bloque que la va a ocupar está siendo buscado desde memoria. Según la investigación
realizada a comienzo del proyecto, no se encontró consenso al respecto de qué realizar en
caso de obtener accesos a una línea con estas características (en [33] se consideran dichas
posiciones de memoria como perdidas y se propone usarlas para otras funciones). Si se
utiliza una política de remplazo LRU y se obtiene un acceso a una línea efímera, esto significa
que el bloque que está por ser desplazado es ahora el más recientemente usado y por tanto
no debería ser desplazado. Una mejora posible sería, en caso de obtener un acceso como el
mencionado, realizar una nueva selección de línea a reemplazar e intercambiar el valor de la
línea elegida con el de la línea efímera accedida. El simulador SimCo podría ser modificado
levemente para soportar este cambio y verificar de este modo la aceleración obtenida en el
AMAT con dicho agregado, ante un conjunto de benchmarks a seleccionar.
53
7.3. E JEMPLO DE ARCHIVO DE CONFIGURACIÓN DE S IM C O
cyclelimit = 100
isa = mips32
bus
name = cpu1bus
width = 4
end
bus
name = membus
width = 16
end
simpleunpipedprocessor
name = simpleprocessor1
meminterface = cpu1bus
pcvalue = 5540
end
ram
name = ram
capacity = 8192
ports = 1
latency = 9
interface = membus
end
cache
name = l1cache
setcount = 8
associativity = 2
linesize = 16
replpolicy = lru
writepolicy = writeback
coherence = msi
ports = 1
latency = 1
upperinterface = cpu1bus
lowerinterface = membus
end
54
R EFERENCIAS
[5] W. J. Dally and B. Towles. Principles and practices of interconnection networks. Morgan
Kaufmann, 2003.
[9] J. J. Yi, L. Eeckhout,D. J. Lilja, B. Calder, L. K. John, and J. E. Smith. “The Future of
Simulation: A Field of Dreams,” IEEE Computer, 39(11):22–29, Nov. 2006.
[12] Charles Price. MIPS IV Instruction Set, revision 3.1. MIPS Technologies, Inc., Mountain
View, CA, January 1995.
[13] Jason E. Miller, Harshad Kasture, George Kurian, Charles Gruenwald III, Nathan Beck-
mann, Christopher Celio, Jonathan Eastep and Anant Agarwal "Graphite: A Distri-
buted Parallel Simulator for Multicores"The 16th IEEE International Symposium on
High-Performance Computer Architecture (HPCA), Jan 2010
55
[14] A. Bakhoda, G. Yuan, W. W. L. Fung, H. Wong, and T. M. Aamodt, Analyzing CUDA
workloads using a detailed GPU simulator. IEEE International Symposium on Perfor-
mance Analysis of Systems and Software, April 2009.
[16] Yi Yang, Ping Xiang, Mixe Mantor, Huiyang Zhou: CPU-assisted GPGPU on fused CPU-
GPU architectures. In: Proceedings of the 2012 IEEE 18th International Symposium
on High Performance Computer Architecture HPCA ’12 (2012)
[17] Ehsan K. Ardestani and Jose Renau, ’ESESC: A Fast Multicore Simulator Using Ti-
me Based Sampling’ The 19th IEEE International Symposium on High Performance
Computer Architecture (HPCA), 2013
[18] S. Nussbaum and J. Smith, “Modeling Superscalar Processors via Statistical Simula-
tion,” Proc. 11th Ann. Int’l Conf. Parallel Architectures and Compilation Techniques,
IEEE CS Press, 2001, pp. 15-24.
[19] Chiou, Derek, et al. "Fpga-accelerated simulation technologies (fast): Fast, full-system,
cycle-accurate simulators."Proceedings of the 40th Annual IEEE/ACM international
Symposium on Microarchitecture. IEEE Computer Society, 2007.
[22] Simulation Modelling with Pascal, Davies R. and O’Keefe R., Prentice Hall, ISBN
013811571-0, 1989.
[27] Desikan, Rajagopalan, Doug Burger, and Stephen W. Keckler. "Measuring experimental
56
error in microprocessor simulation."Proceedings of the 28th annual international
symposium on Computer architecture. ACM, 2001.
[29] J. Renau, B. Fraguela, J. Tuck, W. Liu, M. Prvulovic, L. Ceze, S. Sarangi, P. Sack, K. Strauss,
and P. Montesinos. SESC Simulator. [Link] 2005.
[33] González, Antonio, Fernando Latorre, and Grigorios Magklis. "Processor microarchi-
tecture: An implementation perspective."Synthesis Lectures on Computer Architectu-
re 5.1 (2010): 1-116.
[34] Loh, Gabriel H., Samantika Subramaniam, and Yuejian Xie. "Zesto: A cycle-level si-
mulator for highly detailed microarchitecture exploration."Performance Analysis of
Systems and Software, 2009. ISPASS 2009. IEEE International Symposium on. IEEE,
2009.
[35] A. Patel, F. Afram, S. Chen, and K. Ghose. MARSSx86: A full system simulator for x86
CPUs. In Proceedings of the 2011 Design Automation Conference, June 2011.
[36] Magnusson, P. S., Christensson, M., Eskilson, J., Forsgren, D., Hallberg, G., Hogberg, J.,
Werner, B. (2002). Simics: A full system simulation platform. Computer, 35(2), 50-58.
[37] C. J. Hughes, V. S. Pai, P. Ranganathan, and S. V. Adve, “Rsim: Sim- ulating shared-
memory multiprocessors with ilp processors,” Computer, vol. 35, no. 2, pp. 40–49,
2002.
[39] Binkert, Nathan, Bradford Beckmann, Gabriel Black, Steven K. Reinhardt, Ali Saidi,
Arkaprava Basu, Joel Hestness et al. ’The gem5 simulator.’ ACM SIGARCH Computer
Architecture News 39, no. 2 (2011): 1-7.
[40] Binkert, N. L., Dreslinski, R. G., Hsu, L. R., Lim, K. T., Saidi, A. G., and Reinhardt, S. K.
57
The M5 Simulator: Modeling Networked Systems. IEEE Micro 26, 4 (Jul/Aug 2006),
52-60.
[41] Martin, M. M. K., Sorin, D. J., Beckmann, B. M., Marty, M. R., Xu, M., Alameldeen, A.
R., Moore, K. E., Hill, M. D., and Wood, D. A. Multifacet’s general execution-driven
multiprocessor simulator (GEMS) toolset. SIGARCH Comput. Archit. News 33, 4 (2005),
92-99.
[42] Intel Corporation, “Intel® 64 and IA-32 Architectures Software Developer’s Manual”,
disponible en Web: [Link]
58