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
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.
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
|
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
|
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
|
h 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)
¿Cómo abro el archivo que tiene el circuito?
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