En esta lección completaremos las especificaciones de
nuestro procesador cuya descripción estructural ya
vimos como un diagrama de bloques formado por cinco bloques.
Dos de ellos ya fueron definidos en la lección anterior,
solo falta la definición de los tres bloques restantes.
Empezaremos por el bloque "banco de registros" que es el
que tenemos marcado aquí dentro del diagrama de bloques.
Este bloque está formado por un conjunto de 16 elementos de memoria
de "X0" a "X15" y los valores almacenados en estos elementos de memoria pueden
ser actualizados a través del valor de la entrada "to X(k)" que tenemos aquí.
Esta entrada viene del bloque de selección de entradas.
También pueden ser leídos los contenidos de estos registros
hacia dos salidas X(i) y X(j).
Las instrucciones que trabajan con el banco
de registros, que actualizan algunos de los registros o elementos de memoria
o que leen algunos de estos registros, las vamos a marcar
en azul en nuestra descripción algorítmica funcional del procesador.
Vemos que son muchas de ellas las que hacen referencia
o hacen uso de este banco de registros.
Es importante observar que en relación con las operaciones de lectura del banco
de registros, en el caso de una instrucción tipo data output,
el registro X(j) es el que sale por la derecha
del banco de registros y se conecta a la entrada del bloque de selección de salida.
Aquí vemos el X(j) y ese mismo X(j)
es la entrada del bloque de selección de salidas.
En el caso de la instrucción operation, operación,
ambas salidas la X(i) y la X(j) del banco de registros se leen simultáneamente
y se conectan a las entradas del bloque dedicado a los recursos de cálculo.
El resultado de la operación debe almacenarse,
este resultado debe almacenarse en el registro X(k)
X(k) a través del bloque de selección de entradas.
Y por último en el caso de las instrucciones de salto condicional,
estas dos que tenemos aquí, "jump si positivo" o "jump si negativo",
es el registro X(i), la salida de la izquierda de nuestro
banco de registros, sobre el que se establece la condición a verificar,
es el que sale por la izquierda de nuestro banco de registros y
se conecta al bloque "go to" que es donde en realidad se
valora si se cumple o no se cumple la citada condición.
Luego las entradas del banco de registros son el "reg_in" y la instrucción en curso.
Mientras que sus salidas son "left_out" y right_out
y este loop constituye la especificación funcional
del banco de registros donde esta expresión que tenemos
aquí "program(number)" hace referencia a la instrucción en curso, es decir
el contenido del programa según un number es la instrucción que estamos procesando.
En el caso de instrucciones que actualizan registros pero que no leen el valor
de los registros como son el "assign_value" y el "data_input",
que solo actualizan un determinado registro
X(k) con el valor que había en "reg_in" en ambos casos,
pero que no se lee ninguna información de los registros hacia la salida, pues las
salidas "left_out" y "right_out" en ambos casos se dejan a un valor indeterminado.
En el caso de las instrucciones tipo "data_output" el valor del registro
X(j) tiene que enviarse a través de la salida "right_out" y esto es lo que hacemos aquí,
mientras que por la salida "left_out" no importa lo que tengamos, luego don´t care.
En el caso de "operation" ambos registros X(i) y X(j) deben ser leídos
hacia el exterior, luego deben ser leídos hacia "left_out" y "right_out"
y esto es lo que hacemos aquí. Y aquí, y al mismo tiempo,
el resultado de la operación que nos llegará a través
de la señal "reg_in" debe almacenarse en el registro X(k).
En el caso de las dos instrucciones de salto condicional,
el registro indicado por el índice i, el X(i) debe
ser leído hacia la salida "left_out" en ambos casos,
porque es la salida que se irá al bloque "go to".
Mientras que en estos casos la otra salida no
no tiene ninguna relevancia y la dejamos en el valor indeterminado.
Y finalmente en el caso de las instrucciones de salto incondicional,
esta de aquí, y "output_value" el contenido del banco de registros
ni se actualiza ni se lee, por lo tanto todas sus
salidas se dejan en indeterminado en estos dos casos.
La especificación del bloque de recursos de cálculo es muy simple,
pues solo hay una instrucción que utiliza este bloque y que es esta que tenemos
aquí, es "operation i j k f", y por lo tanto este bloque
lo que necesita para trabajar es la información de la instrucción en curso,
que le indicará que función o recurso de cálculo tiene que utilizar,
los dos operandos de entrada que vienen del banco de registros y una salida
para el resultado que es la que enviará a través del
bloque de selección de entrada de nuevo
hacia el registro X(k) de nuestro banco de registros.
Así pues, este bloque de recursos de cálculo tiene dos
entradas de datos, "left_in" y "right_in",
una entrada de control "f", que nos indicará la operación a realizar,
ya dijimos una suma o una resta, y una señal de salida "result" que es
donde estará el resultado de la operación que hayamos realizado.
Su funcionamiento se describe mediante este simple algoritmo,
si el valor de "f" es igual a cero entonces el resultado es la
suma de las dos entradas, "left_in" más "right_in".
Y si no, es decir si "f" es igual a uno, entonces el resultado es el valor
de la diferencia entre "left_in" y "right_in". left in menos right in.
Por ultimo abordamos el bloque "go to",
que actualiza en cada paso de ejecución del programa el valor de la
salida "number" que indica la posición de memoria donde se encuentra
la siguiente instrucción a ejecutar y que en la mayoría de casos corresponde al
valor de la posición de la instrucción en curso incrementado en uno.
Esto es así excepto cuando la instrucción en curso se trata de una bifurcación
o salto incondicional o condicional, y en este segundo caso si se cumple la condición.
Por lo tanto el bloque "go to" tiene dos entradas, tiene la instrucción propiamente
dicha, para saber de qué instrucción se trata, y la entrada "data", que recordemos
está conectada a la salida del banco de registros.
Y es sobre esa entrada sobre la que se validará, se verificará
si se cumple la condición en aquellas instrucciones de salto condicional.
También hemos visto una salida "number" que, como ya hemos comentado,
representa o contiene el número de la siguiente instrucción a ejecutar.
Esta de aquí es la especificación funcional de este bloque
donde vemos que si la instrucción es un "jump" incondicional,
lo que hacemos es actualizar el valor de "number"
"number" con el número "n" que venía en la propia instrucción.
Si por el contrario la instrucción es un salto condicional,
estos dos casos de aquí, entonces el nuevo valor de "number"
es "n" si y solo si se cumple la condición, es decir,
si se cumple la condición, "number" toma el valor "n" que venía en la
propia instrucción y lo mismo en la otra instrucción de salto condicional,
si se cumple la condición "number" toma el valor "n" que venía en la propia instrucción.
Si no se cumple esta condición en ambos casos,
"number" se incrementa en uno.
Y para cualquier otra instrucción que no sea un salto condicional o incondicional,
"number" siempre se incrementa en uno.
Y con esto llegamos al final de esta sesión, cuyo resumen podría ser que
hemos completado la descripción estructural de nuestro procesador y
hemos descrito el funcionamiento de los tres bloques que nos faltaban,
que eran: el banco de registros, los recursos de cálculo y el bloque "go to".
Y con esto damos por cerrada esta sesión.
Gracias y hasta la próxima.