Está en la página 1de 22

UNIDAD 4: El procesador: Camino de los datos y Control.

4.1 Introducción

El rendimiento de una máquina depende de tres factores clave: Conteo de Instrucciones,


tiempo del ciclo de reloj y ciclos de reloj por instrucción. Para un programa dado, el conteo
de instrucciones depende del repertorio de instrucciones y del compilador; sin embargo, el
tiempo del ciclo de reloj y los ciclos de reloj por instrucción dependen directamente de la
implementación del procesador. En este capítulo revisaremos dos implementaciones
diferentes para el repertorio MIPS previamente estudiado.

Diseñaremos una implementación que incluya un subconjunto con las instrucciones mas
importantes:

ƒ Instrucciones de acceso a memoria: Carga y almacenamiento de palabras (lw y sw).


ƒ Instrucciones aritmético-lógicas: add, sub, and, or y slt.
ƒ Brincos sobre igual (beq) y saltos (j).

No se incluye al repertorio completo por que la idea principal consiste en conocer los
principios aplicados en la creación de un camino de datos y el diseño del control. La
implementación de las demás instrucciones puede hacerse en forma similar.

Entonces, el punto importante consiste en mostrar como el repertorio de instrucciones


determina muchos de aspectos de la implementación, y como la elección de diferentes
estrategias de implementación afecta al ciclo de reloj y al CPI de la máquina. La mayoría
de conceptos expuestos durante la implementación de este sub-conjunto MIPS, son ideas
básicas para la construcción de una amplia gama de microprocesadores de propósito
general utilizados en computadoras de alto rendimiento, así como en el desarrollo de
procesadores de propósito específico, los cuales son usados en una amplia gama de
productos desde VCRs hasta automóviles.

Un vistazo de la implementación

El sub-conjunto a implementar contempla instrucciones aritmético lógicas, instrucciones de


referencia a memoria (para carga o almacenamiento de datos) e instrucciones condicionales
(brinco sobre igual). Independientemente de la instrucción que se ejecute, los primeros dos
pasos son idénticos en todos los casos:

1. Enviar el contador del programa (PC) a la memoria que contiene el código y atrapar
la instrucción desde esa memoria.

2. Leer uno o dos registros, usando los campos de la instrucción para seleccionar los
registros a leer. Para la instrucción de carga solo se requiere la lectura de un
registro, pero para las demás instrucciones es necesaria la lectura de dos de ellos.

Después de estos dos pasos, las acciones requeridas para completar la instrucción dependen
de la clase de instrucción. Sin embargo, a pesar de ser instrucciones diferentes, en el paso
siguiente las tres instrucciones utilizan la unidad aritmético lógica (ALU). Las instrucciones
de referencia a memoria usan la ALU para el cálculo de una dirección; las instrucciones
aritmético lógicas para la ejecución de la operación y los brincos para la comparación.
Como se puede ver, la simplicidad y regularidad del repertorio de instrucciones simplifica
la implementación haciendo la ejecución similar en diferentes clases de instrucciones.

Después de usar la ALU, las acciones requeridas para completar la instrucción son
distintas en cada clase. Las instrucciones de referencia a memoria harán el acceso para la
escritura de un dato (en el caso de los almacenamientos) o para su lectura (en el caso de las
cargas). Las instrucciones aritmético lógicas escribirán el resultado en un registro y las
instrucciones de brincos, tal vez requieran cambiar el valor del contador del programa para
continuar con la siguiente instrucción, de acuerdo al resultado de la comparación.

En la figura 4.1 se muestra un vistazo de la implementación MIPS. Se muestra la conexión


de diferentes bloques funcionales cuyos detalles se irán mostrando a lo largo de la unidad.
Por supuesto, estos bloques sólo constituyen parte del camino de los datos, también se
mostrará mas adelante el diseño y la implementación del control.

Fig. 4.1 Las unidades principales en la implementación del subconjunto MIPS,


un vistazo de la implementación

Convenciones acerca de la Lógica y la sincronización

En el diseño de circuitos lógicos, frecuentemente el diseñador cambia el mapeo entre una


señal lógicamente verdadera o falsa y el nivel de voltaje asociado. En lógica positiva una
señal verdadera corresponde a un nivel de voltaje alto (típicamente 5 V, aunque
actualmente se utilizan dispositivos de muy bajo voltaje), sin embargo en lógica negada
ocurre lo contrario, una señal verdadera corresponderá a un nivel bajo de voltaje (0 V). En
ocasiones es necesario combinar las dos ideas, por que algunos dispositivos, como las
memorias, se habilitan con un nivel bajo de voltaje, pero su lectura requiere de una
habilitación con un nivel alto de voltaje. Para mantener consistencia, y no entrar en detalles
de los valores de voltaje, utilizaremos la palabra acertada para indicar que una señal es
lógicamente verdadera.
Las unidades funcionales utilizadas en la implementación, son elementos lógicos de dos
tipos diferentes: Los elementos que operan sobre los valores de los datos y los elementos
que contienen estado. Los elementos que operan sobre los valores de los datos son
combinacionales, lo cual significa que sus salidas dependen únicamente del valor actual de
sus entradas. En la figura 4.1, la ALU es un elemento combinacional.

Los elementos que no son combinacionales son elementos que contienen estado, es decir,
tienen alguna forma de almacenamiento interno. Se les conoce como elementos de estado
por que por medio de estos elementos se caracteriza completamente el comportamiento de
la máquina. Por ejemplo, si salvamos los elementos de estado, justo antes de retirar la
alimentación de la máquina y les restauramos su valor al reactivar la alimentación, podría
parecer que la potencia nunca se perdió; por que el estado de la máquina se ha conservado.
En la figura 4.1, las memorias de datos e instrucciones, así como los registros son
elementos de estado.

Un elemento de estado tiene al menos dos entradas y una salida. Las entradas requeridas
son: el valor del dato a ser escrito en el elemento y una entrada de reloj, la cual determina
cuando el valor del dato va a ser escrito. La salida del elemento de estado proporciona el
valor que fue escrito en el ciclo de reloj mas cercano. Un ejemplo simple de un elemento de
estado es un flip-flop tipo D; su salida puede leerse en cualquier momento, sin embargo, la
señal de reloj determina cuando se hará la escritura.

A los elementos lógicos que contienen estado también se les denomina secuenciales por
que sus salidas dependen de sus entradas así como también de su estado contenido
internamente. Por ejemplo, en la figura 4.1, la salida de la unidad funcional de los registros
depende del número de registro suministrado, así como del dato que fue escrito
previamente en cada registro.

Metodología de Reloj

Una metodología de reloj define cuando las señales pueden ser leídas y cuando pueden ser
escritas. Es importante especificar los tiempos de lectura y escritura por que, si una señal es
leída al mismo tiempo en que se va a escribir, el valor de la lectura podría corresponder al
viejo valor, al nuevo valor que será escrito o a alguna mezcla de los dos. Una metodología
de reloj debe plantearse para prevenir esas circunstancias; definitivamente no se pueden
tener situaciones impredecibles.

Los dispositivos actuales utilizan una metodología disparada por flancos, lo que significa
que cualquier valor que se almacenará en la máquina se actualizará solamente durante el
flanco de reloj. Entonces, los elementos de estado actualizarán sus almacenamientos
internos solamente sobre el flanco de reloj. Debido a que los elementos de estado
determinan el comportamiento del sistema, cualquier circuito combinacional toma sus
entradas como las salidas de alguno de los elementos de estado, y sus salidas las dirige a
otro elemento de estado, para que se escriban en el siguiente ciclo de reloj.

En la figura 4.2 se muestra a dos elementos de estado conectados por un bloque de lógica
combinacional. Todas las señales deben propagarse desde el elemento de estado 1 y a
través de la lógica combinacional, alcanzarán al elemento de estado 2, en el tiempo que
tarda el ciclo de reloj. La longitud del ciclo de reloj debe incluir la lectura de los elementos
de estado 1 y el tiempo suficiente para que el circuito lógico combinacional produzca sus
salidas a partir de sus entradas.

Fig. 4.2 La lógica combinacional, los elementos de estado y la duración del ciclo de reloj
están directamente relacionados.

Por simplicidad, para aquellos elementos de estado que se modificarán en todos los ciclos
de reloj, no se colocarán las señales de control específicas, por que su habilitación para la
escritura puede tomarse directamente de la señal de reloj. Por lo tanto, solo colocaremos las
señales de control en aquellos elementos cuya escritura dependerá de alguna instrucción
particular.

Una metodología disparada por flancos permite la lectura del contenido de un registro,
enviar su valor a través de una lógica combinacional y escribir ese registro en el mismo
ciclo de reloj, como se muestra en la figura 4.3. No importa si suponemos que la escritura
se hará durante el flanco de subida o de bajada, dado que las entradas al bloque de lógica
combinacional no podrán cambiar, excepto en el flanco elegido. Al emplear esta
metodología, no hay retroalimentación dentro del ciclo.

Fig. 4.3 Una metodología disparada por flancos permite a un elemento de estado ser leído y escrito en el
mismo ciclo de reloj sin dejar datos indeterminados para algún valor.

Primera implementación del subconjunto MIPS

Iniciamos con una implementación simple que utiliza un solo ciclo de reloj para cada
instrucción y sigue el esquema general mostrado en la figura 4.1. En este primer diseño,
cada instrucción inicia su ejecución sobre el flanco de reloj y la completa sobre el siguiente
flanco de reloj.
Este enfoque es fácil de entender, sin embargo no es práctico, por que todas las
instrucciones tardarán el mismo intervalo de tiempo, lo que significa que las instrucciones
mas lentas determinan la duración del ciclo de reloj. Mas adelante se estudiará un segundo
enfoque en el cual la ejecución de una instrucción requerirá de múltiples ciclos de reloj, de
manera que se podrá usar un reloj con una duración menor y las instrucciones mas lentas
requerirán de una cantidad mayor de ciclos que las instrucciones mas rápidas.

4.2 Construyendo un camino de datos

Iniciaremos el diseño examinado los principales componentes requeridos para cada clase de
instrucción. En principio, necesitamos un lugar para almacenar las instrucciones, un
registro que nos indique la instrucción que se está ejecutando y algún medio que nos
permita avanzar a la siguiente instrucción. En la figura 4.4 se muestran estos tres
elementos. Los dos primeros son elementos de estado, una memoria y un registro, mientras
que para calcular la dirección de la siguiente instrucción se utilizará un sumador, por medio
del cual se sumará 4 al registro del contador del programa (este elemento mas simple que
una ALU, puesto que solo realiza la operación de la suma).

Fig. 4.4 Dos elementos de estado son necesarios para almacenar y accesar a las instrucciones, y un sumador
es necesario para calcular la dirección de la siguiente instrucción.

La conexión de los elementos de la figura 4.4 se muestran en la figura 4.5, el contenido del
contador del programa corresponde a la dirección de la instrucción que se está ejecutando,
por lo que se conecta al bus de direcciones de la memoria de instrucciones. La dirección de
la siguiente instrucción se obtiene sumando 4 al contador del programa. En estos elementos
de estado no se muestran sus señales de control, por que serán acertados en todos los
flancos de reloj elegidos. Este es el hardware que ejecuta la búsqueda y captura de la
instrucción (ciclo de fetch).

Ahora consideraremos a las instrucciones tipo R o aritmético-lógicas. Esta clase de


instrucciones lee dos registros, realiza alguna operación con la ALU sobre el contenido de
los registros y escribe el resultado. En esta clase se incluye a las instrucciones add, sub, slt,
and y or.
Fig. 4.5 Una porción del camino de los datos usada para atrapar la instrucción e incrementar al contador del
programa.

Los 32 registros del procesador son almacenados en una estructura a la que llamaremos
Archivo de Registros. Esta estructura contiene una colección de registros en la que
cualquier registro puede ser leído o escrito especificando el número de registro en el
archivo. El archivo de registros mantiene el estado de la máquina. Además, necesitaremos
de una ALU que opere sobre los datos leídos desde los registros.

Debido a que las instrucciones tipo R tienen 3 operandos, para cada instrucción
necesitamos leer dos palabras desde el archivo de registros y escribir un dato en un registro
del archivo. Las entradas al archivo de registros deben incluir los números de los registros a
leer y el número del registro a escribir, así como el dato que se escribirá en el registro
especificado. La lectura se realiza en cada flanco del reloj, sin embargo la escritura solo se
realiza en algunas instrucciones, por lo tanto, se debe incluir una entrada de control que
habilite la escritura de un dato en un registro. Las salidas del archivo de registros
corresponden a los dos datos leídos. En la figura 4.6 (a) se muestra al archivo de registros,
las entradas que corresponden al número de registro son de 5 bits, la entrada del dato a
escribir es de 32 bits y la habilitación es de 1 bit.

La ALU que se muestra en la figura 4.6 (b) tiene 3 entradas de control y su comportamiento
es el descrito en la sección 3.5. Las entradas de los operandos son de 32 bits y el resultado
producido también lo es.

En la figura 4.7 se muestra la conexión del archivo de registros con la ALU, hasta este
momento solo hemos considerado instrucciones tipo R, por lo que los datos obtenidos del
archivo de registros se conectan directamente a las entradas de la ALU y el resultado
producido, se dirige hacia la entrada de datos del archivo de registros. Este es el camino de
los datos necesario para le ejecución de instrucciones tipo R.
Fig. 4.6 El archivo de registros y la ALU son los elementos necesarios para implementar las instrucciones
tipo-R.

Fig. 4.7 El camino de los datos para las instrucciones tipo-R.

Las siguientes instrucciones a considerar corresponden a las cargas y almacenamientos,


cuyos formatos son: lw $t1, desplazamiento ($t2) y sw $t1, desplazamiento($t2). Estas
instrucciones nos permiten las transferencias de memoria a registro o de registros a
memoria, para calcular la dirección del dato a accesar en memoria sumando el contenido
del registro base con el desplazamiento. El desplazamiento es una constante de 16 bits
incluida en la instrucción.

Además del archivo de registros y de la ALU, para soportar estas instrucciones necesitamos
de otros elementos: una memoria de datos, la cual nos permitirá lecturas (para cargas) y
escrituras (para almacenamientos) y un módulo de extensión de signo; el cual en su entrada
tendrá una palabra de 16 bits y la extenderá en signo para completar una palabra de 32 bits.

La extensión de signo es necesaria por que la constante incluida en la instrucción se


presenta en complemento a 2, para poder accesar a los datos en direcciones posteriores o
anteriores al registro base; y puesto que la ALU es de 32 bits, los dos operandos deberán
tener ese tamaño. En la figura 4.8 se muestran esos dos elementos, en la memoria pueden
observarse las dos señales de control, puesto que la escritura o la lectura solo la realizan
algunas instrucciones. La memoria de datos es un elemento de estado y la unidad de
extensión de signo es un circuito combinacional.

Fig. 4.8 Los dos elementos necesarios para implementar las cargas y almacenamientos,
además de los elementos mostrados en la figura 4.6.

En la figura 4.9 se muestra la combinación de estos elementos con el archivo de registros y


la ALU para construir el camino de los datos requerido para los accesos a memoria. Se
supone que la instrucción ya ha sido atrapada y se encuentra presente en el bus de la
entrada. La instrucción incluye al registro base, cuyo contenido se toma del archivo de
registros, y al desplazamiento que se extenderá en signo para sumarse al registro base; el
resultado de la suma corresponde a la dirección de la palabra que se accesará en memoria.
En el caso de una carga, se tomará la palabra de la memoria y se colocará en la entrada de
datos del archivo de registros; pero si se trata de un almacenamiento, el dato leído del
archivo de registros deberá escribirse en memoria.

Como instrucción condicional consideraremos a la instrucción beq, esta instrucción tiene


tres operandos: los dos registros que se comparan para la igualdad y una constante de 16
bits utilizada como desplazamiento para hacer brincos relativos al PC. Su forma es beq $t1,
$t2, desplazamiento. Para implementar esta instrucción, se debe calcular la dirección
destino del salto sumando el desplazamiento extendido en signo al PC. Hay dos detalles en
la definición de las instrucciones de brincos:

• El repertorio de instrucciones especifica que la base para el cálculo de la dirección


destino es la dirección siguiente a la instrucción del brinco. Dado que en el camino de
los datos dedicado a buscar y capturar la instrucción, calculamos PC + 4, este valor se
usará como base para obtener el destino del salto.
• También se tiene que, debido a que las instrucciones utilizan palabras de 32 bits, el
desplazamiento debe corresponder a un desplazamiento de palabras y no de bytes. Para
ello, una vez que se haya extendido en signo al campo del desplazamiento, será
necesario multiplicarlo por 4, esto se consigue si se desplaza 2 lugares a la izquierda.

Fig. 4.9 El camino de los datos para cargas y almacenamientos, hace un acceso a registros seguido por el
cálculo de una dirección de memoria, para después leer o escribir en la memoria, y en el caso de una carga,
concluir con la escritura de un registro.

Además de calcular la dirección destino del brinco, se debe determinar cual será la
siguiente instrucción a ejecutarse, de acuerdo a la igualdad o desigualdad entre los
registros. Si los contenidos de los registros son iguales el brinco debe realizarse, por lo que
el contador del programa deberá ser sustituido por la dirección calculada. Pero si no son
iguales, el brinco no se realizará por lo que se continuará con la instrucción ubicada en la
dirección siguiente a la dirección del brinco.

Entonces, el camino de los datos debe realizar las dos operaciones: Calcular la dirección
destino del brinco y comparar los contenidos de los registros. En la figura 4.10 se muestra
el camino de los datos para los brincos; con la ALU se realiza una resta entre el contenido
de los dos registros, de manera que el brinco queda condicionado a la puesta en alto la
bandera de zero. Con otro sumador se obtendrá la dirección destino del brinco. En la
instrucción se incluye al desplazamiento en 16 bits, éste se extiende en signo y luego, para
que corresponda a un desplazamiento de palabras, se desplaza a la izquierda dos lugares, lo
cual equivale a multiplicar por 4. El valor resultante es el que se sumará a PC + 4, el
resultado de la suma es la dirección destino del brinco.

En el caso de la instrucción j, el salto es incondicional; es decir, no está sujeto al resultado


de una comparación. La instrucción j tiene dos campos, un campo de 6 bits que
corresponde al opcode y otro de 26 bits que indica la dirección destino del salto. Para esta
instrucción también deberá considerarse que las instrucciones ocupan 4 bytes, de manera
que también será necesario desplazar este campo 2 bits a la izquierda. Después del
desplazamiento se tendrán 28 bits, de manera que el nuevo valor del contador del programa
se obtendrá concatenando los 4 bits más significativos del PC; de manera que este es un
salto pseudo directo para todo el espacio de memoria, o directo dentro de una página de 256
Mbytes (232). La implementación de esta instrucción se incorporará una vez que se hayan
implementado las demás instrucciones.

Fig. 4.10 El camino de los datos para un brinco condicional, la ALU evalúa la condición del salto y otro
sumador calcula la dirección destino del salto, con relación al valor actual del contador del programa.

4.3 Un simple esquema de implementación

En esta sección se pretende realizar una implementación completa - camino de los datos y
control - para las instrucciones: cargar palabra (lw), almacenar palabra (sw), brincar sobre
igual (beq) y las instrucciones aritmético lógicas: add, sub, and, or y slt. Al final se
incorporará la instrucción de salto (j).

Construcción del camino de los datos

En las figuras 4.5, 4.7, 4.9 y 4.10 se mostraron algunas piezas del camino de datos para las
instrucciones individuales, ahora se combinaran todas estas piezas para tener un único
camino de los datos. Debe tomarse en cuenta que se trata de una implementación que
ejecutará todas las instrucciones en 1 ciclo de reloj. Esto significa que los recursos en el
camino de los datos no pueden ser usados mas de una vez por instrucción, de manera que
cualquier elemento que se requiera mas de una vez, deberá ser duplicado. Por lo tanto,
necesitamos de una memoria de instrucciones separada de la memoria de datos. Aunque
algunos elementos necesitan duplicarse, también tenemos que diferentes elementos serán
compartidos por diferentes flujos de instrucciones.
Al compartir elementos, pueden requerirse múltiples conexiones a una entrada. Para ello se
utilizarán multiplexores, y será el control el que determine cual de los datos fluirá a cada
entrada.

Primero combinaremos las instrucciones Tipo-R con las instrucciones de acceso a memoria
(figuras 4.7 y 4.9). Ambas instrucciones utilizan a la ALU y el primer operando en ambos
casos es el dato escrito en el registro 1, obtenido del archivo de registros, sin embargo el
segundo operando difiere para las dos instrucciones: En el caso de las instrucciones tipo-R
el segundo operando es el dato escrito en el registro 2, obtenido del archivo de registros.
Mientras que para los accesos a memoria, el segundo operando es una constante extendida
en signo. Por lo que es necesario un multiplexor en la entrada del segundo operando de la
ALU.

Las instrucciones tipo-R escriben el resultado en un registro y en el caso de las cargas, se


obtiene un dato de memoria para ser escrito en un registro. Entonces, en la entrada de datos
del archivo de registros también deberá colocarse un multiplexor por medio del cual se
haga esta selección. En el caso de los almacenamientos, este multiplexor no es importante
por que no hacen escritura en registro.

En la figura 4.11 se muestra la combinación de ambos caminos de datos, en color naranja se


muestran las señales de control, necesarias hasta el momento.

Fig. 4.11 Combinando el camino de los datos para una instrucción de acceso a memoria y el de las
instrucciones tipo-R.

La parte de búsqueda y captura de la instrucción mostrada en la figura 4.4 puede fácilmente


agregarse a la figura 4.11 para producir la figura 4.12, en la cual se muestra la presencia de
las dos memorias, la memoria de instrucciones y la memoria de datos. Este camino de los
datos requiere de un sumador además de la ALU, esto por que simultáneamente la ALU
realizará la operación sobre los datos, mientras que el sumador obtendrá la dirección de la
siguiente instrucción a ejecutar.
Fig. 4.12 La parte de captura de la instrucción se agrega al camino de los datos.

Para completar el camino de los datos, debemos agregar la parte necesaria para los brincos,
que se muestra en la figura 4.10. Al agregar estos elementos, será necesario el uso de un
multiplexor a la entrada del PC, para poder seleccionar entre PC + 4 y el resultado de haber
sumado a PC + 4 una constante. En la figura 4.13 se muestra al camino de los datos
obtenido hasta el momento, el cual puede ejecutar instrucciones tipo-R, cargas,
almacenamientos y brincos sobre igual.

Fig. 4.13 Un camino de los datos que combina los elementos requeridos
por diferentes clases de instrucciones MIPS.
Ahora que hemos completado el camino de los datos podemos agregar la unidad de control.
La unidad de control deberá tener la habilidad de generar las señales de escritura para cada
elemento de estado, la selección de cada multiplexor y el control de la ALU; a partir de las
entradas que definan al tipo de instrucción (opcode). Sin embargo las instrucciones
aritmético-lógicas comparten el mismo opcode, de manera que para simplificar las cosas,
diseñaremos por separado el control de la ALU y luego diseñaremos el resto de la unidad
de control.

Control de la ALU

Recordemos que la ALU tiene tres entradas de control y que sólo cinco de las ocho
combinaciones posibles son utilizadas. En la tabla 3.5 se definió el comportamiento de la
ALU, la cual se repite en la tabla 4.1 por conveniencia.

Líneas de Control de la ALU Función


000 And
001 Or
010 Suma
110 Resta
111 Slt
Tabla 4.1 Comportamiento de la ALU

La selección entre cada una de estas cinco funciones dependerá de la clase de instrucción.
Para cargas y almacenamientos se requiere que la ALU realice una suma para calcular la
dirección de la localidad de memoria a la que se realizará el acceso. Para instrucciones
aritmético lógicas la ALU realizará una suma, resta, AND, OR o ajuste sobre menor que,
dependiendo del campo de función que se encuentra en los 6 bits menos significativos en
esta clase de instrucciones. Para el salto sobre igual la ALU necesita realizar una resta.

Como un primer paso realizaremos una pequeña unidad de control que tenga una entrada de
2 bits a la que denominaremos ALUOp. Con esta entrada se determinará si la ALU
realizará una suma (ALUOp = 00) para cargas y almacenamientos, una resta (ALUOp = 01)
para brincos sobre igual o si la operación quedará determinada por el campo de función
(ALUOp = 10) para instrucciones tipo-R. La salida de este Control de la ALU será de 3 bits
y se conectará directamente con las líneas de control de la ALU.

En la tabla 4.2 se muestra el comportamiento de la ALU basado en las entradas de dos bits
(ALUOp) y en los 6 bits del campo de función. La unidad de control principal generará los
valores para ALUOp.

Este estilo de usar diferentes niveles de decodificación (p. Ej., la unidad de control
principal genera los bits ALUOp, los cuales son usados como entradas al control de la ALU
para generar las señales que controlan a la ALU) es una técnica de implementación común.
El usar múltiples niveles de control reduce el tamaño del control principal, por que el
control principal ya no necesitará como entrada al campo de función, solamente al código
de operación (opcode), con ello se aumenta su velocidad de respuesta considerablemente.

Instrucción ALUOp Operación Campo de Acción deseada en Entrada de


(opcode) Función la ALU control de la ALU
LW 00 Cargar palabra XXXXXX Suma 010
SW 00 Almacenar palabra XXXXXX Suma 010
BEQ 01 Saltar sobre igual XXXXXX Resta 110
Tipo-R 10 Suma (Add) 100000 Suma 010
Tipo-R 10 Resta (Sub) 100010 Resta 110
Tipo-R 10 AND 100100 AND 000
Tipo-R 10 OR 100101 OR 001
Tipo-R 10 Ajuste sobre menor 101010 SLT 111
que (slt)
Tabla 4.2 Comportamiento de la ALU en función de ALUOp y del campo de función, también se muestran
las instrucciones para cada combinación.

La tabla 4.2 nos muestra que para el diseño del control de la ALU se deben considerar los 6
bits del campo de función. Sin embargo, esto nos lleva a diseñar un circuito combinacional
con 8 entradas y 3 salidas. Si construimos la tabla de verdad considerando todas las
combinaciones, tendremos una tabla muy grande en la que muchas de las combinaciones en
realidad no importan por que no van a ocurrir. Entonces, para hacer un diseño simple (con
pocas compuertas), a partir de la tabla 4.2 observaremos las condiciones necesarias y
suficientes para generar cada una de las entradas de la ALU. En la tabla 4.3 se muestra a los
3 bits del control de la ALU en función de ALUOp y el campo de función; se han colocado
X en aquellos valores que no son determinantes para definir la operación.

ALUOp Campo de Función Operación


ALUOp1 ALUOp0 F5 F4 F3 F2 F1 F0 Sal2 Sal1 Sal0
0 0 X X X X X X 0 1 0
X 1 X X X X X X 1 1 0
1 X X X 0 0 0 0 0 1 0
1 X X X 0 0 1 0 1 1 0
1 X X X 0 1 0 0 0 0 0
1 X X X 0 1 0 1 0 0 1
1 X X X 1 0 1 0 1 1 1
Tabla 4.3 Las salidas del control de la ALU en función de ALUOp y del campo de función.

En la tabla 4.3, en cuanto a las entradas ALUOp, se colocó X en la segunda fila de


ALUOp1, por que es suficiente si ALUOp0 = 1 y de la 3ª a la 7ª filas con detectar el 1 de
ALUOp1 es suficiente. Para el campo de Función, las columnas para F5 y F4 tiene el
mismo valor, de manera que no son determinantes.

Entonces, observando las condiciones mínimas para la generación de cada salida tenemos
que:
Sal0 = ALUOp1xF3 + ALUOp1xF0
Sal1 = ALUOp1’xALUOp0’ + ALUOp0 + ALUOp1xF2’
Sal2 = ALUOp0 + ALUOp1xF1
Estas ecuaciones van a funcionar en el caso de que solo se consideren estas combinaciones;
ya que si se incrementan las operaciones, el campo de función introducirá nuevas
combinaciones y las ecuaciones puede no cumplirse.

Diseñando el control principal

Ahora que contamos con un control para la ALU, es posible realizar el control principal;
para ello es conveniente repasar los formatos de las instrucciones que se están
considerando:

Las instrucciones tipo-R tiene el formato:

0 rs rt rd shamt funct
31-26 25-21 20-16 15-11 10-6 5-0

Para las cargas y almacenamientos el formato es:

35 o 43 rs rt dirección
31-26 25-21 20-16 15-0

Y el salto condicional tiene como formato:

4 rs rt dirección
31-26 25-21 20-16 15-0

Algunas observaciones relacionadas con los formatos y que pueden ser importantes para el
diseño del hardware son:

ƒ El código de operación (opcode), está siempre contenido en los bits 31-26. A este
campo lo referiremos como Op[5-0].
ƒ Los dos registros a ser leídos están siempre especificados por los campos rs y rt, en las
posiciones 25-21 y 20-16. Esto para las instrucciones tipo-R, brincos sobre igual y los
almacenamientos.
ƒ El registro base para las instrucciones de cargas y almacenamientos es rs y está en los
bits 25-21.
ƒ Los 16 bits de desplazamiento para brincos sobre igual, cargas y almacenamientos están
siempre en las posiciones 15-0.
ƒ El registro destino está en uno de dos lugares. Para las cargas está en los bits de
posición 20-16 (rt), mientras que para instrucciones tipo-R su posición es 15-11 (rd).
Entonces necesitamos un multiplexor para seleccionar el campo que corresponda al
registro que se escribirá de acuerdo a la operación.

Usando esta información, podemos agregar etiquetas y el multiplexor extra al camino de


los datos. También podemos agregar el control de la ALU, obteniendo como resultado la
figura 4.14.
Fig. 4.14 El camino de los datos mostrado en la figura 4.13 con los multiplexores necesarios para evitar colisiones y todas las líneas de control identificadas.
En la figura 4.14 se tienen 7 señales de control, mas las señales del control de la ALU
(ALUOp), en la tabla 4.4 se describe el efecto de acertar o desacertar a cada una de las
señales. Recordemos que acertado significa lógicamente verdadero y depende del valor
necesario para la habilitación de un dispositivo, sin embargo, para los multiplexores
tomaremos acertado = 1.

Nombre de la señal Efecto cuando es desacertada Efecto cuando es acertada


RegDst El número del registro destino El número del registro destino
para la escritura viene del campo para la escritura viene del campo
rt (20-16) rd (15-11)
RegWrite Ninguno Se escribirá un dato en el archivo
de registros
ALUSrc El segundo operando de la ALU El segundo operando de la ALU
es el segundo dato leído en el son los 16 bits de desplazamiento
archivo de registros tomados de la instrucción y
extendidos en signo
PCSrc El PC es remplazado por PC + 4 El PC es remplazado por la suma
de una dirección calculada para
un brinco
MemRead Ninguno Se hace la lectura de la memoria
de datos
MemWrite Ninguno Se hace la escritura en la
memoria de datos
MemtoReg El valor del dato que se escribirá El valor del dato que se escribirá
en el archivo de registros viene en el archivo de registros viene
de la ALU de la memoria de datos
Tabla 4.4 El efecto de cada una de las 7 señales de control.

La unidad de control ajustará el valor de todas las señales dependiendo del código de
operación (opcode), con excepción de la señal PCSrc. Esta señal deberá acertarse cuando se
trate de un brinco condicional, sólo si el resultado de la comparación es verdadero. Por lo
que a la entrada de la señal PCSrc colocaremos una AND de dos entradas, una de ellas
provendrá de la bandera zero (producida por la ALU) y la otra la generará la unidad de
control siempre que se trate de un brinco, a esta última señal la denominaremos branch.

Por lo tanto, el control básicamente es un circuito lógico combinacional cuyas entradas


corresponden a los 6 bits del opcode y sus salidas son las 7 señales de control mostradas en
la tabla 4.4 mas las dos señales que requiere el control de la ALU. En la figura 4.15 se
muestra al camino de los datos y el control para soportar instrucciones tipo-R, cargas y
almacenamientos y brincos sobre igual.

En la tabla 4.5 mostramos el valor que deberá colocarse a las señales de control, en función
del opcode. Se presentan algunos casos en los que el valor de la señal no importa, por
ejemplo, si no se escribirá en un registro, no importa de donde provenga el dato. Para la
tabla 4.5, en relación a las memorias y al archivo de registros, se consideró que acertado
equivale a 1.
Fig. 4.15 El camino de los datos con la unidad de control.
Tabla 4.5 El valor de las señales de control queda determinado por el código de operación.

Para el diseño del control, es necesario recordar los códigos de operación para cada una de
las instrucciones bajo consideración, esto se muestra en la tabla 4.6.

Nombre Opcode Opcode en Binario


en Decimal Op5 Op4 Op3 Op2 Op1 Op0
Tipo-R 0 0 0 0 0 0 0
lw 35 1 0 0 0 1 1
sw 43 1 0 1 0 1 1
beq 4 0 0 0 1 0 0
Tabla 4.6 Los códigos de operación en decimal y en binario.

Con base en las tablas 4.5 y 4.6 se obtiene directamente el circuito del control, el cual se
muestra en la figura 4.16.

Inputs
Op5
Op4
Op3
Op2
Op1
Op0

Outputs
R-format Iw sw beq
RegDst

ALUSrc
MemtoReg
RegWrite
MemRead
MemWrite
Branch
ALUOp1

ALUOpO
Fig. 4.16 Implementación del control.
Implementación de los Saltos

A la implementación mostrada en la figura 4.15 le agregaremos el hardware necesario para


soportar los saltos. El formato de la instrucción j es:

4 dirección
31-26 25-0

La diferencia entre j y beq es que la primera instrucción es incondicional, de manera que el


salto siempre se realizará. Sin embargo mantienen en común el hecho de que se trata de un
salto de palabras de 4 bytes, por lo que los 26 bits encontrados en la instrucción deben
desplazarse a la izquierda en 2, llenando estos espacios con ceros. De manera que al
realizarse el salto, el nuevo valor del contador del programa se formará por la
concatenación de:

ƒ Los 4 bits mas significativos del valor de PC + 4 (estos son los bits 31-28 de la
dirección secuencialmente continúa al salto).

ƒ Los 26 bits del campo inmediato de la instrucción del salto.

ƒ Los bits 00dos.

Debe agregarse un multiplexor mas, por medio del cual se podrá seleccionar entre PC + 4 y
el valor obtenido de la concatenación anterior. En la figura 4.17 se muestra el hardware
agregado para el camino de los datos para el salto, así como la nueva señal de control para
la selección del valor correcto para el PC.

Por que una implementación de un ciclo de reloj no es usada

Aunque la implementación mostrada en la figura 4.17 trabajará correctamente, los diseños


que trabajan en un ciclo de reloj no son usados en los procesadores modernos por que son
ineficientes.

Una implementación de este estilo tiene un CPI igual a 1 (Ciclos por Instrucción) y puesto
que no sabemos cual es la instrucción que se estará ejecutando, hasta que inicie su
ejecución, todos los ciclos de reloj deberán ser del mismo tamaño. Por lo que el tamaño del
ciclo de reloj estará determinado por la ruta mas larga posible en la máquina. Esta ruta
ciertamente es para una instrucción de carga, la cual utiliza cinco unidades funcionales en
serie: La memoria de instrucciones, el archivo de registros, la ALU, la memoria de datos y
nuevamente el archivo de registros. Esta instrucción determinará el tamaño del ciclo.

Las instrucciones que podrían ser rápidas, como los saltos que aunque solo ocupan la
memoria de instrucciones, tardarán lo mismo que las cargas. Entonces, aunque el CPI es
igual a 1, el rendimiento de esta implementación no es muy bueno dado que diferentes
clases de instrucciones podrían ejecutarse en menos tiempo.
Instruction [25-0] Jump Address [31-0]
Shift 1
Left 2 M
0 u
M x
u 0
PC + 4[31-28]
x
1
Shift
Left 2 PCSrc
4
RegDst
Jump
Branch
MemRead
Instruction [31-26]
MemtoReg
ALUOp
MemWrite
ALUSrc
RegWrite

Instruction [25-21] Read


Register1
Read
Instruction [20-16] data 1 Zero
Read Read
PC Register2 ALU
address
0 ALU
Instruction M Write Read 0 Address
result
[31 - 0] u Register data 2 M Read 1
x u data M
Instruction Instruction [15-11] x
1 Write u
memory Data 1 x
Registers
Write 0
data Data
Memory

Instruction [15- 0] 16 Sign 32


extend

Instruction [5- 0] ALU


control

Fig. 4.17 El camino de los datos con la unidad de control, soporta la ejecución de instrucciones tipo-R, cargas, almacenamientos, brincos y saltos.
TAREA 8

Para los problemas del 1 al 4 de esta tarea se sugiere que se imprima la figura 4.17 para
realizar lo que se pide en cada punto.

1. Suponiendo que los registros $t0 y $t1 tienen los valores 30 y 40 respectivamente, al
ejecutarse la instrucción: add $t2, $t1, $t0. En la figura 4.17, resaltar las líneas que estarán
activas durante la ejecución de esta instrucción y escribir el valor de cada una de las líneas
activas (para las del camino de los datos usar color rojo y verde para las de control).

2. Este ejercicio es similar al anterior, pero ahora se trata de la instrucción: beq $t1, $t2, et1
y debemos suponer que tanto $t1 y $t2 tienen el dato 33, que la instrucción esta ubicada en
la dirección 4000diez y que la etiqueta está ubicada 10 instrucciones antes de la que se está
evaluando.

3. Al resultado mostrado en la figura 4.17, agregar el hardware necesario (camino de los


datos y control) para poder soportar a la instrucción addi.

4. Esta pregunta es similar a la anterior, pero ahora se trata de soportar a la instrucción jal.

5. Se nos propone que la señal de control MemtoReg sea eliminada. Por lo que el
multiplexor que tiene como entrada a MemtoReg deberá usar la señal de control MemRead
¿Trabajará el hardware con las modificaciones propuestas? ¿Por qué?