SIMULACION DEL R2000

Introducción

En esta práctica simulamos el funcionamiento del microprocesador MIPS R2000 de Silicon Graphics. Toda la información se ha sacado del libro Organización y Diseño de Computadores de John L. Hennessy y David A. Patterson.

Concretamente mi simulación se corresponde al microprocesador multiciclo.

Características del sistema

El simulador que se presenta a continuación dispone de una pequea interfaz interactiva con el usuario que atiende a necesidades más comunes del usuario con el programa, aunque también su funcionamiento puede ser totalmente comprobado con el depurador de linux GDB.

El programa se carga en el fichero Programa.asm en ensamblador y los datos se cargan en el fichero Datos.asm, también en ensamblador. La memoria principal es de 64 direcciones por 32 bits de datos por dirección. Desde la posición 0 hasta la posición 31 se utiliza para cargar las instrucciones, mientras que desde la posición 32 hasta la 64 se utiliza para los datos.

La memoria se podia haber partido de otra forma, yo lo he hecho así por comodidad.

Funcionamiento de mi programa

Para hacer funcionar la simulación , tan solo debemos de escribir el programa en el fichero PROGRAMA.asm y los datos que va a utilizar el programa en el fichero DATOS.asm. Tan solo en el fichero DATOS.asm tendremos que indicar el número de datos que vamos a utilizar al principio del programa.

A continuación se debe de ejecutar el script ejecuta, y automáticamente el simulador arrancará. En el terminal que el simulador nos ofrece, podemos poner la orden help, la cual nos indicará lo que se podrá hacer con el simulador.

Memoria sobre la práctica

Como hemos dicho anteriormente, lo que se ha construido es un simulador del microprocesador R2000 multiciclo. Para llegar a esta simulación se ha necesitado tiempo y esfuerzo.

Lo primero que hice ante todo fue analizar el problema, aunque hay que reconocer que esto no es nada fácil. En primer lugar tuve que coger el libro de Organización y diseño de Computadores (olvidado tiempo atrás), y volver a repasar algo que ya estudie en mi tiempo.

Pasado el tiempo tiempo ya me acordaba de su funcionamiento e integración, pero el paso dificil quedaba por llegar. A continuación creí conveniente recolectar todos los componentes que durante el curso me habian dado (memorias, registros, and, or, etc) y saber de lo que disponia, de forma que me fuí al esquema que queria implementar (multiciclo) y comprobé los componentes que tenía y los que me hacian falta. No muchos eran los componentes, pero entre ellos destacó tan solo la Unidad de Control, y me puse a construirla.

Una vez construida la unidad de control, y demás componentes (muxes, extensor de signo, etc) me ví obligado a montar el procesador. Para ello seguí la misma filosofia que sigue el libro de Patterson y Hennessy. Primeramente se debe de actualizar el estado en el que el procesador se encuentra para su posterior procesamiento de los datos. En segundo lugar, y una vez que conocemos el estado del procesador, debemos de actualizar todas las líneas de los componentes y sus correspondientes estados, y por último escribimos la secuencia de ejecución, tal cual como Patterson y Hennessy la describen, empezando por el PC, siguiendo por el multiplexor siguientes, y finalizando por la ALU. Tal vez la filosofia que se ha empleado en este último punto se puede alterar, pero yo lo he visto más fácil de esta manera.

Y de esta manera apareció el simulador MIPSR2000. La implementación del mismo se ha realizado en C++ con objetos, obteniendo así una clase del MIP-SR2000, o sea, con esta clase puedo declarar tantos procesador como a mí me hagan falta dentro de algún programa, y sin problemas en cuanto al reparto de la memoria entre sus variables. Esta implementación se puede ver dentro del fichero MIPSR2000.cc y MIPSR2000.h.

Construcción de nuevos componentes.

En esta parte vamos a hablar de los componentes que he tenido que construir para poder implementar el multiciclo. Pocos son estos y entre ellos destacamos la Unidad de Control. Para construirla me he basado en la PLA que viene en el apéndice C página 693. Una vez que hemos hecho la PLA (fácil de realizar) debemos de interconectarla con un regsitro que va a ser el que va a contener el estado siguiente que la PLA a calculado a trevés del estado de entrada y que va a valer para que ejecución de las instrucciones sea parecida al diagrama de la página 683. El esquema final implementado es el que viene en la página 684 y se puede ver la implementación total en el fichero UCM.cc y UCM.h, el registro utilizado es síncrono, por ello que utilizamos la entrada de reloj.

Otro componente más que se ha implementado es la unidad de control de la ALU que viene reflejada en la Figura 5.18 de la página 256, que se utilizaría para indicar a la ALU las operaciones que debe de realizar. Esta implementación es fácil de realizar y tan solo se debe de utilizar gates.h y defs.h para su implementación, y lo podemos ver en el fichero control ALU.cc y control ALU.h, donde se ha incorporado una pequeña comprobación del código.

Otros componentes más que se han creado pero no con mucha dificultad, son los multiplexores que componen parte del multiciclo. Para ello se han creado las clases MUX 2 1 32b, MUX 2 1 5b y MUX 4 1 32b reutilizando clases anteriormente creadas. La implementación se pueden ver en los fichero muxs.h y muxs.cc. Otro componente más que podemos destacar es el extensor de signo de 16 bits, fácil de hacer y que se encuentra dentro del fichero Ext Signo16b.h y Ext Signo16b.cc.

Anomalías durante la construcción.

Una vez que tuve todos los componentes implementados, la fase de implementación comenzo. Los primero paso eran lentos y comprobando todo, pero conforme la implementación crecía también lo hacía con ella el diseno. Durante este periodo muchos son los errores que he cometido, pero también otros tantos los fallos que he descubierto. Entre ellos destaca el registro $0 de la memoria de registros. Forzosamente este registro debe de estar a 0 siempre (según la norma MIPS), pero esto no ocurría. El fallo casi seguro se encuentra en la propia implentación de la memoria de registros. No me he parado en verlo, pero lo soluciono escribiendo el 0 en el constructor de la clase MIPSR2000.

Otro problema que tuve fue durante la fase de pruebas, donde la instrucción sw no funcionaba correctamente al no escribir el valor adecuado dentro de la memoria. Esto se lleguó a solucionar interconectando una puerta AND entre el reloj, su entrada de control de escritura y la seal de control de escritura que proviene de la unidad de control.

Como nuestra memoria es de posiciones contiguas se ha suprimido en la implementación los desplazamientos de 2 bits.

El fichero SIMULACION.cc.

Una vez que tenenemos todo bien planteado y contruida la clase MIPSR2000, necesitamos interactuar de alguna forma esta con el resto de los componentes importantes como son la memoria y el reloj. Esto precisamente se realiza en el fichero SIMULACION.cc. Dentro de un bucle hacemos que el procesador se comunica con el reloj del sistema y con la memoria que va a contener las instrucciones y los datos necesarios para esas instrucciones. Cada ciclo que realiza el bucle sobre estos componentes es lo que denominamos iteracción, y un ciclo de reloj va ha estar compuesto por varias iteracciones del programa. Pero no solamente en este fichero hacemos esto que es lo más importante. También realizamos la carga de las instrucciones y datos en la memoria que vamos a utilizar dentro de la simulación.

La instrucción END.

Cuando al principio empezé a ejecutar la simulación, tenía que contar con previo aviso, el número de iteracciones que necesitaba el programa que se iba a ejecutar. Al principio de todo cuando estaba depurando la simulación esto no me parecía engorroso, pero con el tiempo si lo fué. De esta necesidad surgió la instrucción END. La instrucción END es una instrucción inventada por mí y que he incluido en el repertorio de instrucciones para cuando el programa acabe de ejecutarse, una patilla de la unidad de control se active y me indique la finalización de este. Para instroduccir esta instrucción dentro del repertorio he tenido que modificar la unidad de control y sus correspondientes tablas que se incluyen en el apéndice C. Para incluir esta instrucción dentro de un programa, tan solo debemos de aadir al final de la secuencia de ejecución end. Un ejemplo claro es el programa ejemplo que muestro con el simulador.

La interfaz del simulador.

Es una interfaz sencilla y suficiente como para que un usuario pueda sacar del simulador lo mínimo e imprescindible. No era objetivo de esta asignatura realizar una buena interfaz pero si es aconsejable hacerla para el simulador. La interfaz es interactiva e incluye una información sobre las instrucciones que lleva, con tan solo poner help en el terminal. En cualquier momento puedes salidar del programa y al final de la ejecución del mismo, mostramos la memoria de datos (para comprobar resultados) junto con los ciclos de reloj e iteracciones que se han consumido. La implementación la podemos encontrar dentro del fichero SIMULACION.cc, y pasamos como parámetro el objeto micro. Esto lo podemos hacer gracias a unas de las propiedades que tiene el lenguaje O.O. que es poder hacer amiga (friends) a una función determinada dentro de una clase, y podiendo acceder a las variables privadas del mismo. Con esta propiedad nos evitamos tener que pasar bastantes parámetros y dar un gran valor de independencia a la clase MIPSR2000.

El script Ejecuta.

A la hora de ejecutar el simulador debemos de poner ./ejecuta. Este fichero es un script que contiene;

./asm programa.asm prog.txt ./filtro prog.txt¿programa.txt ./asm datos¿datos.txt ./test SIMUL

En primer lugar asm es un fichero ejecutable que se obtiene a travs del fichero asm2r2k.c (un poco modificado del que nos distes). Este programa permite pasar un programa en ensamblador a código máquina y que este se refleje en el archivo prog.txt. Este archivo lo tomarún segundo ejecutable que se llama filtro y lo que va ha hacer es poner el fichero prog.txt de manera que a nosotros nos venga bien. El resultado se descarga en el fichero programa.txt. El fichero ejecutable asm datos, lo que hace es pasar los datos de ensamblador y que se encuentran en el fichero datos.asm a código máquina. Este ejecutable lo he realizado yo y se encuentra en el fichero asm datos.c. Pos último ejecutamos el simulador que viene por el ejecutable test SIMUL. Este script nos centraliza más el funcionamiento del simulador.

Planeamiento de posibles mejoras.

Son muchas la mejoras que se pueden hacer pero entre ellas destaco la incorporación de una memoria caché y una mejora en la ALU con anticipación de arrastre. Otro posible planteamiento sería la construcción del procesador segmentado, y posr supuesto y debido a la grandes características que nos brinda la programación orientada a objetos, sería la construcción de un programa que nos simulara el procesamiento en paralelo de dos procesadores, y por que no de n-procesadores.

José Antonio Gil Rosa 3 ITIS.