Práctica Nº3

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) SRL $t1, $t0, 0x0002
f) LUI $s0,0x0011
g) SW $t4, 0x0111
h) SLT $t1, $t2, $t0
i) J 0x000001A
j) JR $S0
  1. Codificar las instrucciones en hexadecimal, tal como quedarían en memoria.
Para codificar las instrucciones en hexadecimal, es necesario saber las tablas de equivalencia de las diferentes instrucciones de MIPS. Cada instrucción se codifica en base a su propia tabla específica que combina su código de instrucción con los diferentes registros, y el número de bits necesarios para su codificación.


ADD $t0, $t1, $t2
Así pues, para la primera instrucción, tendremos la siguiente tabla:


A continuación debemos poner los registros en sus correspondientes celdas, teniendo en cuenta que la instrucción es:

Una vez claro lo anterior, debemos tener en cuenta la codificación en hexadecimal de cada uno de los registros, que lo podemos mirar en la siguiente tabla:

Los registros con puntos suspensivos, por ejemplo t0…t7 – 8…15, se refiere a que los registros intermedios tienen números correlativos entre el 8 y el 15.
Una vez que ya sabemos el código de los registros utilizados en la operación, podemos proceder a codificar la instrucción, según el número de bits antes citado, primero en decimal, luego en binario, y por último, agrupando los números de 4 en 4, en hexadecimal.
El número 0x20, está en hexadecimal y no en decimal, así que tenemos que pasarlo a decimal para mayor comodidad al convertirlo a binario.

0
9 ($t1)
10 ($t2)
8 ($t0)
0
32 (0x20)
000000
01001
01010
01000
00000
100000
Una vez codificado en binario, tenemos que agrupar los números de 4 en 4 bits de la siguiente manera:
0000 – 0001 – 0010 – 1010 – 0100 - 0000 – 0010 – 0000
Ahora para pasarlo a hexadecimal, tenemos que pasar cada grupo de cuatro a decimal, teniendo en cuenta que a partir del 10, serían A, B, C... hasta F. Por tanto la codificación en memoria de la instrucción en hexadecimal, sería la siguiente: 0x012A4020
Las siguientes instrucciones se codifican de la misma forma, pero en base a las diferentes tablas de cada instrucción, escritas más abajo:
ADDI $s0, $s1, 0x0011


El addi se realiza exactamente igual que el anterior, pero con la única diferencia, de que los últimos 16 bits, son para el inmediato, en lugar de para Rd, el 0 y el 0x20, y que en este caso es 0x0011. El resultado de la codificación es: 0x22300001

ORI $t0, $t2, 0x00A1


Esta instrucción se codifica igual que el addi pero cambiando el código de la instrucción, que es 0xD en lugar de 8. El resultado de la codificación es: 0x354800A1
SLL $t0, $t0, 0x0002


En este caso, Rs no existe en la instrucción, por tanto, seria 00000. El resultado es: 0x00084080.

SRL $t1, $t0, 0x0002


El SRL, al igual que SLL, no tiene Rs, por tanto, ese espacio se rellena con 00000. La instrucción codificada es: 0x00084882

LUI $s0, 0x0011


Esta instrucción carga los 16 bits de la parte baja del valor inmediato en la parte alta del registro. Los bits de la parte baja se ponen a 0. Rt sería $s0 y el inmediato sería 0x0011. La codificación sería: 0x3C100011

SW $t4, 0x0111

En esta instrucción no existe Rs, por tanto se rellena de ceros (00000). El offset sería la dirección, es decir, 0x0111. La codificación sería: 0xAC0C0111.
SLT $t1, $t2, $t3

Esta instrucción se codifica igual que la instrucción ADD (ya que la tabla es muy similar). La codificación sería: 0x014B482A.
J 0x000001A

Esta instrucción es la más fácil. Solo hay que poner la dirección 0x000001A en binario en los 26 bits restantes de poner el código de operación que es 2. La codificación sería: 0x0800001A.

JR $s0

En esta instrucción, al igual que la anterior, solo habría que colocar $s0 en rs. El resultado sería: 0x02000008.


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


La secuencia de transferencia de registros, se hace en tres pasos, que corresponden con las tres fases de ejecución de una instrucción, y observando el esquema anterior para así poder saber qué debemos hacer y qué señales tendremos que activar. Las diferentes secuencias que se realizan se indican con C1, C2, C3... Así de C1 a C3, corresponden con la fase de lectura de instrucciones que es igual en todas las instrucciones, la C4 con la fase de decodificación y las demás con la de ejecución.
Pasemos pues a explicar lo que significa lo que hay en cada secuencia de transferencia:
· MAR es un registro que permite a la CPU comunicarse con la memoria y los dispositivos externos, al igual que MBR.
· PC es el registro encargado de almacenar la dirección de memoria a la que se está accediendo.
· MP corresponde con la memoria principal, que permite almacenar programas y datos.
· RI es el registro de instrucciones que almacena la instrucción a ejecutar.


ADD $t0, $t1, $t2

C1: MAR ß PC
Lleva la dirección de memoria a la que se accede al registro MAR
C2: PC ß PC + 4
Incrementa la dirección de memoria en 4 unidades, como se observa en el esquema.
C2: MBR ß MP
Carga en MBR lo contenido en la memoria principal.
C3: RI ß MBR
Carga los datos del registro MBR en el registro de instrucciones para poder operar con ellos.
C4: Decodificación
Corresponde con la segunda fase de ejecución de una instrucción. Este ciclo permite que la unidad de control realice la ejecución de la secuencia de señales de control que den lugar a la instrucción.
C5: R8 ($t0)=R9($t1)+R10($t2)
Esta línea se encarga de realizar la operación. R8, R9 y R10 se refiere a los registros sacados del banco de registros del esquema. La equivalencia es la misma que en el ejercicio 1.



Como las secuencias de C1 a C4 son siempre igual, sólo se pondrá la secuencia de C5 en     adelante.




ADDI $s0, $s1, 0x0011
C5: RT1 ß  MBR
Se guarda en el registro temporal RT1 el inmediato, encontrado en MBR.
C6: R16($s0)=R17($s1)+RT1(0x0011)
Esta línea se encarga de realizar la operación, guardando el resultado en el registro $s0, la suma de $s1 con el inmediato. R16 y R17 se sacan del banco de registros del esquema.

ORI $t0, $t2, 0x00A1
C5: RT1 ß MBR
Se guarda en el registro temporal RT1 el inmediato, encontrado en MBR.
C6: R8 ($t0)=R10($t2)OR RT1(0x00A1)
Esta línea se encarga de realizar la operación, guardando el resultado en el registro $t0 el resultado de la operación R10 OR RT1


SLL $t0, $t0, 0x0002
C5: RT1 ß MBR
Se guarda en el registro temporal RT1 el inmediato, encontrado en MBR.
C6:
R8($t0) = Desplazado.Izq(R8($t0),RT1(=0x0002))

Esta línea se encarga de realizar la operación, guardando el resultado en el registro $t0 de desplazar a la izquierda el propio registro 0x0002.

SRL $t1, $t0, 0x0002
C5: RT1 ß  MBR
Se guarda en el registro temporal RT1 el inmediato, encontrado en MBR.
C6:
R9($t1) = Despl. Der.(R8($t0),RT1(=0x0002))

Esta línea se encarga de realizar la operación, guardando el resultado en el registro $t1 de desplazar a la derecha el número 0x0002 a $t0.

LUI $s0, 0x0011
C5: RT1 ß MBR
Se guarda en el registro temporal RT1 el inmediato, encontrado en MBR.
C6:
Esta línea se encarga de realizar la operación.

SW $t4, 0x0111
C5: MAR ß RI

Se guarda en el registro temporal RT1 el inmediato, encontrado en MBR.
C6:  MBR ß R12($t4)
Esta línea guarda el registro 12 del banco de registros, en MBR.
C7: MP ßMBR
Lleva el registro MBR a la memoria principal.




3.       Comprobar que todo lo anterior se ha realizado de forma correcta mediante el simulador que se adjunta para la práctica. Se introducirá el código de instrucción en la memoria de manera que     sean posible realizar todas las fases de la instrucción.
Para realizar este ejercicio, debemos saber las señales que se activan en el circuito de la práctica. Dicho circuito nos lo dan para poder realizar lo pedido. El programa que utilizaremos para visualizar el circuito es el logisim-win2.7.1. Se adjunta la imagen del circuito a continuación:

Lo más cómodo es ir mirando la siguiente imagen para saber que señales debemos de activar y así poder ir siguiendo los pasos en Logisim:



Debemos tener en cuenta que los triestados no pueden estar activados ya que cuando se activa un triestado hay que desactivar los demás para que no se produzcan errores.
ADD $t0, $t1, $t2

Señales que se activan
C1: MARß PC
T4 = 1
C1 = 1
C2: PC ß PC + 4
C1 = 0
TD = 1
Sel = 1
L = 1
C4 = 1
C4 = 0
C2: MBR ß MP
C2 = 1
C2 = 0
C3: RI ß MBR
T4 = 0
T3 = 1
C7 = 1
C7 = 0
C4: Decodificación
Ninguna
C5: R8 ($t0)=R9($t1)+R10($t2)


Lo primero que debemos hacer al abrir el circuito en el Logisim es fijarnos donde está cada cosa que vamos a necesitar. Tras esto, seleccionamos el botón de la mano marrón (situado en la esquina superior izquierda) para poder comenzar a realizar la simulación. Luego, empezamos activando las señales antes indicadas una detrás de otra pinchando en el botón cuadrado correspondiente de cada señal. Así si T4 = 1 pincharemos en dicho recuadro para poner el “1” y pinchando de nuevo ponemos un “0”. Las señales de la secuencia desde C1 a C4 se activan siempre igual para todas las instrucciones.
Debemos tener en cuenta que la ALU sólo tiene implementadas en el circuito las siguientes funciones:
  •  00001 Suma
  • 00002 Resta
  • 00003 OR
  •  00004 AND
  •   00005 Desplazamiento a la derecha de 1,2,3,4 bits
  •   00006 Desplazamiento a la izquierda de 1,2,3,4 bits
  • 00007 NOT
  • 00008 XOR

Por lo tanto, sólo podremos usar esas funciones, poniendo los números de cada función en binario. Así si queremos realizar un AND, pondríamos en el “Código de operación” el valor 00100. También debemos tener en cuenta que el acceso a la memoria solo se realiza en formato Word (32 bits). Las direcciones se visualizan como bloque de 4 bytes:
00000000 representan las direcciones 00000000-00000003
00000001 representan las direcciones 00000004-00000007
00000002 representan las direcciones 00000008-0000000B

Para que se inicie el programa la memoria debe estar activada: Sel = 1, en modo lectura L=1 y el triestado que conecta el bus de direcciones con el registro MAR abierto TD=1. La señal “Sel” se encuentra arriba del circuito (y es la primera empezando por la izquierda) y es como se muestra en la imagen siguiente, y la señal “L” es la tercera empezando por la izquierda:


Para reiniciar todo el sistema se cuenta con una entrada de RESET general.





 ADDI $s0, $s1, 0x0011

Señales que se activan
C1: MAR ß PC
T4 = 1
C1 = 1
C2: PC ß PC + 4
C1 = 0
TD = 1
Sel = 1
L = 1
C4 = 1
C4 = 0
C2: MBR ß MP
C2 = 1
C2 = 0
C3: RI ßMBR
T4 = 0
T3 = 1
C7 = 1
C7 = 0
C4: Decodificación
Ninguna
C6: R16($s0)=R17($s1)+RT1(0x0011)
RA = 10000 ($s0)
RB = 10001 ($s1)
MA = 0
MB = 0
T3 = 0
T8 = 1
C10 = 1
C10 = 0
T8 = 0
MB = 1
C. Op = 000001
T5 = 1
RC = 16(10 = 10000
SC = 1 y SC = 0


 ORI $t0, $t2, 0x00A1
Como las señales que se activan en la secuencia de C1 a C4 son siempre igual en todas las instrucciones, no las ponemos. Por ello a partir de ahora, sólo vamos a ir poniendo las secuencias de C5 en adelante.


Señales que se activan






C5: RT1 ß MBR
E = 0
TD = 0
TA = 0
T1 = 0
T3 = 0
T4 = 1
C1 = 1 y luego C1 = 0
TD = 1
Sel = 1 y L = 1
T4 = 0
T3 = 1
C7 = 1 y C7 = 0
C9 = 1 y C9 = 0



C6: R8 ($t0)= R10($t2) OR RT1(0x00A1)
RA = 01000
MA = 0 y MB = 0
C.Op = 00011 (OR)
T8 = 0
T1 = 1
C3 = 1 y C3 = 0
TA = 1
E = 1

SLL $t0, $t0, 0x0002

Señales que se activan






C5: RT1ß MBR
T5 = 0
T4 = 1
C1 = 1 y luego C1 = 0
TD = 1
Sel = 1 y L = 1
T4 = 0
T3 = 1
C7 = 1 y C7 = 0

C6:
R8($t0) = Desplazado.Izq(R8($t0),RT1(=0x0002))

RB = 01000
MA = 0 y MB = 0
C9 = 1 y C9 = 0
T3 = 0
MA = 1
C.Op= 00110 (despl. a la izq)
T5 = 1
SC = 1 y SC = 0

SW $t4, 0x0111

Señales que se activan
C5: MAR ß RI

C7 = 1 y C7 = 0
T8 = 1
C1 = 1 y luego C1 = 0

C6:  MBR ß R12($t4)
T5 = 0
T4 = 1
TD = 1
Sel = 1 y L = 1 en memoria
T4 = 0
T3 = 1

C7: MP ßMBR
RA = 001100
MA = 0 y MB = 0
T8 = 0
T1 = 1
C3 = 1 y C3 = 0
TA = 1
E = 1