lunes, 27 de mayo de 2013

Práctica 4: Unidad de control

Práctica 4
Por Iván Piña Arévalo.
En esta práctica utilizaremos el programa Logisim, que podemos obtener a través del campus virtual. El principal objetivo de esta práctica es que el alumno realice las funciones de la unidad de control, Esta práctica consta de tres actividades.
Sean las siguientes instrucciones:
a)  ADD $t0, $t1, $t2
b)  ADDI $s0,$s1, 0x0011
c)  ORI $t0, $t2, 0x00A1
d)  SLL $t0, $t0, 0x0002
e)  SLR $t1, $t0, 0x0002
f)  LUI $s0, 0x0011
g)  SW $t4, 0x0111
h)  SLT $t1, $t2, $t0
i)  J 0x000001A
j)  JR $S0
1- Traducir a lenguaje hexadecimal.
En esta actividad se nos pide traducir al lenguaje hexadecimal, este apartado ya lo desarrollamos en el tema 2, lenguaje ensamblador “MIPS”
Por este motivo no nos explayaremos demasiado con el fin de no aburrir a los usuarios. Aún así, es importante recordar que para traducir la instrucción a lenguaje hexadecimal, debemos tener en cuenta el tipo de instrucción (R, I, J) ya que su tipo determinara la estructura de la instrucción. Estos formatos responden a las siguientes estructuras.


1)       ADD $t0, $t1, $t2
Hexadecimal: 0x012A4020
Suma el contenido de los registros $t1 y $t2 y almacena el resultado en $t0.
2)        ADDI $s0,$s1, 0x0011
Hexadecimal: 0x22300011
Suma $s1 y 0x0011 y almacena el resultado en $s0.
 
3)      ORI $t0, $t2, 0x00A1
Realiza una operación OR entre $t2 y 0x00A1, almacenando el valor en $t0.
Hexadecimal: 0x354800A1

4)        SLL $t0, $t0, 0x0002
Esta instrucción realiza un desplazamiento lógico a la izquierda en $t0, 0x0002 es el número de que indica las rotaciones a realizar, almacenándose el resultado de la operación en el registro $t0.
Hexadecimal: 0x0084080

5)        SLR $t1, $t0, 0x0002
Esta operación realiza un desplazamiento lógico hacia la derecha con el contenido del registro $t0, 0x002 es el valor que indica el número de posiciones a rotar. El resultado del desplazamiento se almacena en $t1.
Hexadecimal: 0x00084882


6)        LUI $s0,0x0011
Esta instrucción carga un valor inmediato (en este caso 0x0011) en el registro $s0.
Hexadecimal: 0x3C100011

7)        SW $t4, 0x0111
Esta instrucción toma el valor inmediato como una dirección de memoria y la almacena en $t4. Esta instrucción es de tipo I
Hexadecimal: 0xAC0C0111

8)        SLT $t1, $t2, $t0
Esta instrucción comprueba si el registro $t2 es menor que el registro $t0.
Por tanto si t2<t0 à t1=1 (Si el contenido del registro t2 es menor que el registro t0 en t1 se guarda un 1, y si t2>=t0 à t1=0 (si el contenido del registro t2 es mayor o igual que el registro t0 en t1 se guarda un 0.
Hexadecimal: 0x0148482A

9)        J 0x000001A
Esta instrucción carga un valor inmediato en el registro contador de programa.
Hexadecimal: 0x00800001A



10)   JR $S0
Esta instrucción carga en PC el contenido del registro $s0.  
Hexadecimal: 0x0200001A

2- Utilizando la CPU descrita en clase teórica y el lenguaje de transferencia de registro, realizar la secuencia de transferencias y acciones.

 
       ADD $t0, $t1, $t2    


S1: MAR ← PC
T4, C1
S2: PC ← PC+4
C4
S2: MBR ← MP
Td, L, C2
S3: RI ← MBR
T3, C6
S4: Decodificación

S5:RT3 <- RA+RB
RA=01001, MA=0
RB=01010, MB=0
OP= ADD, C11
S6: RC ← RT3  (“envía al registro el resultado de la operación)
T6, RC=01000, SC=0
S7: Ciclo de comprobación de interrupciones










      ADDI $s0,$s1, 0x0011     


S1: MAR ← PC
T4, C1
S2: PC ← PC+4
C4
S2: MBR ← MP
Td, L, C2
S3: RI ← MBR
T3, C6
S4: Decodificación

S5: RT2←RI
T8,C10
S6: Rt3 ← RT2 + R17
RA=10001, MA=0, MB=1
OP= ADD, C11
S7: RC ← RT3
T6, RC=S0, SC
S8:Ciclo de comprobación de interrupciones



            ORI $t0, $t2, 0x00A1  


S1: MAR ← PC
T4, C1
S2: PC ← PC+4
C4
S2: MBR ← MP
Td, L, C2
S3: RI ← MBR
T3, C6
S4: Decodificación

S5: RT3 ← RI(0x00A1) OR R10
T8, C10,  MB=1, C11
S6: RC ← RT3
T6, RC= 01000, SC
S8: Ciclo de comprobación de interrupciones


 

       SLL $t0, $t0, 0x0002 
Instrucciones
Señales
S1: MAR ← PC
T4, C1
S2: PC ← PC+4
C4
S2: MBR ← MP
Td, L, C2
S3: RI ← MBR
T3, C6
S4: Decodificación

S5: RT2 ← RI
T8, C10
S6: ALU ← RT2
MB=1
S7: RT3← $t0 SLL RT2
RA=01000, MA=0
S8: RC ←RT3
T6, RC=01000, SC
S9: Ciclo de comprobación de interrupciones





        SLR $t1, $t0, 0x0002
 Instrucciones
Señales
S1: MAR ← PC
T4, C1
S2: PC ← PC+4
C4
S2: MBR ← MP
Td, L, C2
S3: RI ← MBR
T3, C6
S4: Decodificación

S5: RT2 ← RI (0x0002)
T8, C10
S6: RT3 ← RT2 SLR R0
Código operación=OR, MA=0, MB=1
S7: RC ← RT3
T6, RA=01001, SC  
S8: Ciclo de comprobación de interrupciones. 







f          LUI $s0,0x0011  
Instrucciones
Señales
S1: MAR ← PC
T4, C1
S2: PC ← PC+4
C4
S2: MBR ← MP
Td, L, C2
S3: RI ← MBR
T3, C6
S4: Decodificación

S5: RC ← RI (0x0011)
T8, RC=10000,SC
S6: Ciclo de comprobación de interrupciones


 
 
g        SW $t4, 0x0111
Instrucciones
Señales
S1: MAR ← PC
T4, C1
S2: PC ← PC+4
C4
S2: MBR ← MP
Td, L, C2
S3: RI ← MBR
T3, C6
S4: Decodificación

S5: MAR ← RI (0x0111)
T8, C1
S6: MBR ← MP
TD, C2
S7: RC ← MBR
T3, RC= 01100  SC
S8: Ciclo de comprobación de interrupciones








        J 0x000001A
Instrucciones
Señales
S1: MAR ← PC
T4, C1
S2: PC ← PC+4
C4
S2: MBR ← MP
Td, L, C2
S3: RI ← MBR
T3, C6
S4: Decodificación

S5: PC ← RI(0x000001A)
T8
S6: Ciclo de reconocimiento de interrupciones.


i             JR $S0
Instrucciones
Señales
S1: MAR ← PC
T4, C1
S2: PC ← PC+4
C4
S2: MBR ← MP
Td, L, C2
S3: RI ← MBR
T3, C6
S4: Decodificación

S5: PC ← $s0
RA=10000, T1, C5
S6: Ciclo de comprobación de interrupciones


3-  Simular las instrucciones con nuestra ALU.
En este apartado explicaremos como realizar  este ejercicio de la forma más sencilla y correcta. Comenzaremos relatando como realizar el primer ciclo de la instrucción (es común para todas las instrucciones).
Para comenzar debemos abrir el triestado T4 (para obtener la dirección de memoria donde se encuentra la instrucción). Despues de haber abierto T4, activamos la señal de carga del registro MAR (Mar se comunica con memoria, por lo que en la dirección de memoria que le hemos enviado a MAR se encuentra la instrucción, la instrucción se encuentra en memoria codificada en hexadecimal). Despues de este paso, abriremos la memoria en modo lectura, de esta forma, la instrucción se almacena en el registro MBR. A la vez, deberemos activar la señal de carga del contador (C4) para sumar un ciclo y poder pasar a la siguiente instrucción.
Por último, la instrucción almacenada en MBR deberemos enviarla al registro RI, para hacerlo debemos activar el triestado T3 (envía al bus el contenido de MBR) y la señal de carga de RI (C6). El último ciclo se emplea para la decodificación de la instrucción, por lo que no es necesario realizarlo nosotros.

a)      ADD $t0, $t1, $t2
Para realizar esta operación, deberemos llevar los datos a la Unidad Aritmetico Logica, por lo que debemos sacarlos del banco de registro, para ello, seleccionamos los registros empleando RA y RB respectivamente, después debemos activar a  0 los multiplexores A y B (esto significa que los datos provienen del banco de registros, si viniesen de los registros  temporales, habría que colocarlos a 1).  Ya tenemos los datos en la ALU, pero falta el código de operación, por lo que habremos de seleccionar en este caso el valor que haga referencia a la operación suma (los valores de operación pueden variar de una ALU a otra). Por último, almacenaremos el resultado en el registro $t0, para esto, activamos la señal T5 para enviar el resultado al bus de datos, simultáneamente, seleccionamos el registro $t0 con la señal RC y cargamos el resultado obtenido de la ALU con la señal SC.
b)      ADDI $s0, $s1, 0x0011
En esta operación simplemente debemos sumar el valor 0x0011 y el valor contenido en $s1, almacenando el resultado en $s0. En el ciclo de captación ya hemos dispuesto 0x0011 en el registro RI.
Lo primero a realizar será enviar el dato de RI  a un registro temporal (por ejemplo a RT2), para hacerlo, activaremos la señal de salida T8 y la señal C10 de carga. Despues de esto, debemos enviar el valor de $s1 a la ALU, es decir, seleccionaremos $s1 con RA y en el triestado MA colocaremos un 0 para indicar de donde viene el valor. En MB deberemos colocar 1 ya  que el valor proviene de un registro temporal. Seleccionaremos el código de operación en la operación suma y enviaremos el resultado al banco de registros, donde se encuentra $s0. Activaremos T5, seleccionamos $s0 con RC y para cargar el valor en el registro activamos la señal SC.

c)       ORI $t0, $t2, 0x00A1
Primero debemos llevar el dato de $t2 y el inmediato a la ALU. Es decir, activar la señal C6 (sacar el dato de RI) y activar la señal C10 (cargar el valor en registro temporal RT2), MB=1 (dato en registro temporal). Después, en RA seleccionamos el registro $t2 y colocamos en MA 0 para indicar que la carga viene del banco de registros. Seleccionamos el código de operación  OR en la ALU y esta vez debemos almacenar el resultado en RT3, ya que el bus contiene el valor inmediato, para almacenarlo activamos la señal de carga C11. A partir de aquí comienza el sexto ciclo. Ahora enviaremos el resultado de la operación OR al registro $t0. Comenzaremos activando la señal de salida T6 y seleccionamos $s0 en el banco de registro con RC y activamos la señal de carga SC para almacenar el valor en el registro seleccionado.

d)      SLL $t0, $t0, 0x0002
En esta operación primero debemos llevar el dato (almacenado en $t0) y el valor inmediato (almacenado en RI) a la ALU. Seleccionamos $t0 en el banco de registros con RA y colocamos 0 en MA para indicar de donde proviene el dato, después, activamos T8 para enviar el valor inmediato al bus de datos y activamos C10 para almacenarlo en RT2, también debemos activar MB, en este caso un 1, y seleccionar el código de desplazamiento a la izquierda en nuestra ALU. Almacenaremos el resultado en RT3 (el bus interno está ocupado por el valor inmediato).Aquí comienza un nuevo ciclo, después de esto, solo nos queda almacenar el resultado en el registro $t0, para hacerlo, activamos T6 para enviar el valor que contiene RT3 al bus interno, seleccionamos el registro con RC y por último activamos la señal de carga SC.
e)      SRL $t1, $t0, 0x0002
Esta operación es exactamente igual a la anterior, salvo porque el desplazamiento se realiza a la derecha, como lo único que varía el código de operación, no consideramos necesario repetirlo.
f)       LUI $s0, 0x0011
En esta instrucción cogeremos el valor  0x0011 y lo almacenaremos en $s0, para hacerlo, activamos T8 para volcar el valor al bus interno (el valor se encuentra en el registro RI) y a continuación seleccionamos $s0 con RC y activamos la señal de carga SC.
g)       SW $t4, 0x0111.
En esta instrucción buscaremos en memoria el valor que se encuentra en la dirección 0x011 y  lo almacenaremos posteriormente en el registro $t4.
Para buscar en memoria el dato, activamos T8 y C1 para almacenar el valor en el registro MAR, a continuación activamos td y abrimos la memoria en modo lectura. Después, activamos T3 para volcar el dato en el bus interno, y finalmente seleccionamos con Rc el registro $t4 y almacenamos el valor activando la señal de carga SC.



h)      SLT $t1, $t2, $t0
  Activaremos RA y MA para llevar el contenido de $t2 a la ALU. A su vez, activamos RB  y MB para hacer lo mismo con $t2. Seleccionamos el código de operación para la resta. Deberemos almacenar los indicadores de la resta, para lo cual deberemos activar C8. Procederemos a activar las señales T7, C9 y MA para llevar el contenido del registro de estado a la ALU mediante RT1. (incompleto.)
i)        J 0x000001A
Para realizar este salto, activaremos las señal T8 y C5 para llevar el valor inmediato desde RI hasta PC.

j)        JR $s0
Activaremos las señales RA y T! para volcar el dato de $s0 en el bus interno, después lo cargaremos en PC activando C5


Dificultades:
El correcto manejo de la estructura de una cpu, para solucionar esta dificultad lo principal es conocer cada una de las partes que la componen y cuál es su función, sin embargo, posee caracteres repetitivos que ayudan a la comprensión (por ejemplo todas las señales que empiezan por “c” son de carga)


FAQS

¿Cómo abro el archivo que tiene el circuito?
Primero abres el Logisim y con Archivo/abrir lo seleccionas y se abrirá.

¿Como paso las instrucciones a hexadecimal?
Primero lo pasas a binario, mirando en el apéndice Hennessy Patterson del tema 2 como se codifican. Una vez que lo tienes en binarios, separas los bits en grupos de cuatro y cada grupo lo traduces a hexadecimal. Al final te tienen que quedar 8 dígitos.

¿Cómo meto las instrucciones en el circuito?
En modo para hacer funcionar el circuito, pinchas en la RAM que hay arriba, que hace las veces de memoria principal, y pones en cada uno de los cuadritos la instrucción que quieres que se ejecute.

¿Cómo meto datos en el banco de registros del archivo de la CPU?
En el menú de la izquierda haces doble clic en donde pone BANCO. Una vez allí, buscas el registro que quieres, el de arriba a la izquierda es el R0 y desde allí los siguientes van en vertical, y luego a la linea siguiente. Una vez localizado, en el modo para hacer funcionar el circuito, pinchas en los números del registro y metes lo que quieres.

¿Cómo reinicio el circuito?
Abajo a la derecha hay un botón que pone RESET. En cuanto lo pulses se resetearán todos los datos del circuito.

¿Por qué se me pone el cable del bus en color rojo?
Porque tienes abiertos dos o más triestados a la vez, por lo que hay un conflicto y los datos salen erróneos. Para solucionarlo, tan sólo cierra los sobrantes.

No hay comentarios:

Publicar un comentario