Práctica 3: Unidad de Control
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
|
- 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.
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
|
FAQ DE LA PRÁCTICA Nº3
1º) ¿Dónde puedo encontrar las tablas de equivalencia de las diferentes instrucciones de MIPS?
Las tablas de equivalencia se pueden encontrar en los apuntes del Campus Virtual, y también en la red.
2º) ¿En qué consiste la secuencia de transferencias y acciones?
Consiste en indicar mediante una tabla, lo que sucede dentro de la CPU por medio de las transferencias.
Para
que cada operación se realice hace falta activar una serie de señales
de control que quedan reflejadas en las tablas de la práctica.
3º) ¿Por qué se producen errores cuando hay más de un triestado activado?
Cuando se abre un triestado, es como una puerta que deja pasar la información hacia el destino.
Si se abren varios triestados, llega información de varias fuentes mezcladas, por lo que se produce un error.
4º) ¿Es necesario realizar el circuito de la CPU en Logisim?
No, ya que el circuito se deja adjuntado en el Campus Virtual, debido a que sería muy tedioso hacerlo.
5º) ¿Para qué sirve la señal de “RESET” situada en la esquina inferior derecha del circuito de la CPU?
Como
su propio nombre indica, el RESET permite reiniciar todo el circuito,
para así poder realizar nuevos cambios. Por ejemplo, si tras guardar una
dirección en el registro MBR y el resultado no es el esperado, o nos
hemos equivocado al activar alguna señal,le damos al RESET (lo ponemos a
“1”) y automáticamente se pone todo a 0.
No hay comentarios:
Publicar un comentario