Está en la página 1de 19

Laboratorio 1 - Simulación Base PDUA

Edward Nicolás Duarte - Juan Esteban Montagut - Camilo Andres Ramírez


Pontificia Universidad Javeriana
Organización de Computadores
12 de octubre de 2022

Resumen
Este laboratorio tiene como objetivo la realización de un código por medio del PDUA que permita llevar
al cabo el proceso de multiplicación por del método de Booth. Para ello, se realiza la programación con una
lógica de almacenamiento en memoria RAM, y uso de controles dentro del CTRL. Para la RAM, se realiza
la totalidad de almacenamiento de variables, constantes y demás valores que se usen a lo largo de la lógica
desarrollada. Adicionalmente, se realiza la codificación de un total de 7 controles. Que, en su defecto permiten
o facilitan llevar al cabo el algoritmo de Booth para dos variables de 8 bits sin importar el signo de éstas.
Para desarollarlo, se realiza un código a nivel de la ROM por medio de la lógica explicada en el diagrama de
bloques del proceso secuencial del algoritmo. Es allí, donde se llaman los controles programados y en general
se tienen en cuenta cualquier caso de multiplicación que pueda pasar (multiplicación con 0, con negativos,
negativo-positivo, y positivo-positivo). Para realizar la corroboración de un adecuado comportamiento se hace
una simulación por medio de la herramienta de Quartus y el simulador ModelSim. Allí, se observa a detalle los
espacios de memoria de la RAM. El ACC, A, PC, SP, DPRT, AVI, TEMP, CTE. Y, por medio de varias pruebas
y un proceso matemático explicado detalladamente se encuentran como están distribuidos los tiempos y ciclos
del programa para diferentes casos de multiplicación. Es allí donde se tienen en cuenta tiempos constates
para cualquiera de los 4 posibles casos de la multiplicación. Así mismo, el tiempo promedio para todas las
posibilidades de cada caso (multiplicación desde 0 hasta 255). Para finalmente, hallarle un promedio a los
tiempos y ciclos encontrados en cada caso obteniendo cual es el promedio general del tiempo y numero de
ciclos que toma realizar cualquier multiplicación en el código desarrollado.

1. Introducción
Inicialmente, se realiza un proceso regresivo. En donde por medio de un ejemplo en prueba de escritorio se
plantea en su totalidad la lógica utilizada en el proceso de multiplicación de dos números de 8 bits con el algoritmo
de Booth. Con ello, se tiene una claridad de la secuencia a realizar. Con lo cual, se plasma en un diagrama de
flujo en la imagen 1.

Inicialmente, se crean las siguientes variables:

M: Variable que almena el multiplicando


P: variable que almacena el multiplicado
Z0: Variable inicializada en P que almacena los resultados de 8 bits de lo que inicialmente es P.
Z1: Variable inicializada en 0 que almacena los valores de los 8 bits de la izquierda en el algoritmo booth.
X0: Variable inicializada en 0 que almacena el segundo bit de la variable Z0.
X1: Variable inicializada en el valor del bit menos significativo de Z0(0) que almacena el primer bit de la
variable Z0.

1
Contador: Variable inicializada en 1 que se encarga de almacenar el número de ciclos o iteraciones en el
algoritmo para detenerlo una vez se cumpla la cantidad de iteraciones equivalente a la cantidad de bits.
Auxiliar: Variable inicializada como (80)10 = (10000000)2 usada para agregarle al bit mas significativo de
Z0 un 1 en dado caso que lo herede de Z1 al realizar el corrimiento.

Con ello, se procede a inicializar el proceso, en donde inicialmente se le asigna al registro A X1, y a ACC
X0. De esta manera, se establece la primera condición del algoritmo teniendo en cuenta que X0 se inicializa
como 0 y X1 contiene el bit Z0(0). Para lograr lo anterior en X1, se desarrollo un control en el CTRL llamado
ıACC = A(Log2 [ACC])ȷ. Dicho control requiere que se almacene en el registro A el numero al que se quiere
extraer el bit y en ACC la posición en la forma 2 ( alaposicindeseada).

Para lograr lo anteriormente mencionado se realizó la siguiente lógica en CTRL: Se hace un XOR de ACC
con ACC para obtener un cero total almacenado en el registro temporal. Posteriormente, se realiza un AND entre
ACC y A (recordando los valores de ACC y A mencionados en el párrafo anterior). Si los dos bits están activos, el
resultado se activará, pero si alguno se encuentra en 0 no se va a activar. Luego, se realiza un salto condicional
si es cero. En dado caso que sea 0 quiere decir que el bit analizado era cero por lo tanto al ACC se le asigna
temporal que es cero. Pero, para el otro caso, el bit estaba activo. Por lo cual, el ACC será temporal +1. Y, de
esta manera se logra extraer el valor en la posición especificada.

Con todo ello, se logra separar claramente el caso cuando hay que realizar una resta. En cuyo proceso, se hace
el complemento a dos por medio de la función de control que ya existe en el CTRL. Posteriormente, se suma M
(o menos M) + Z1. Cabe resaltar que cada vez que se realiza una modificación de las variables almacenadas en
memoria se debe realizar el proceso de cargarlas en los registros de la ALU en dado caso que no se encuentren ahí y
luego de modificarlas se deben cargar nuevamente a la memoria. Para efectos prácticos se omitirá esa explicación,
pero es relevante tenerla en cuenta.

Para lograr lo anteriormente mencionado se realizó la siguiente lógica en CTRL: Se hace un XOR de ACC
con ACC para obtener un cero total almacenado en el registro temporal. Posteriormente, se realiza un AND entre
ACC y A (recordando los valores de ACC y A mencionados en el párrafo anterior). Si los dos bits están activos, el
resultado se activará, pero si alguno se encuentra en 0 no se va a activar. Luego, se realiza un salto condicional
si es cero. En dado caso que sea 0 quiere decir que el bit analizado era cero por lo tanto al ACC se le asigna
temporal que es cero. Pero, para el otro caso, el bit estaba activo. Por lo cual, el ACC será temporal +1. Y, de
esta manera se logra extraer el valor en la posición especificada.

Luego del XOR se analiza el resultado almacenado en ACC. Que, en dado caso que sea 0 quiere decir que
se encuentra en alguno de los posibles casos 00 y 11. Los cuales, realizan únicamente los desplazamientos de Z0
y Z1. Mientras que en el caso que el XOR no de un cero existe la posibilidad que los valores de X0 y X1 sean
respectivamente 10 o 01. En cuyo caso, se toma A (X1) y se revisa si es 0 o no. La razón de lo anterior se basa en
el descarte que se realizó inicialmente de 2 de los cuatro casos posibles. En donde los casos restantes presentan
valores invertidos entre los X0 con ellos mismos y los X1 de igual manera.

Con todo ello, se logra separar claramente el caso cuando hay que realizar una resta. En cuyo proceso, se hace
el complemento a dos por medio de la función de control que ya existe en el CTRL. Posteriormente, se suma M
(o menos M) + Z1. Cabe resaltar que cada vez que se realiza una modificación de las variables almacenadas en
memoria se debe realizar el proceso de cargarlas en los registros de la ALU en dado caso que no se encuentren ahí y
luego de modificarlas se deben cargar nuevamente a la memoria. Para efectos prácticos se omitirá esa explicación,
pero es relevante tenerla en cuenta.

Continuando con el proceso, después de la sumatoria es necesario almacenar los X0 y X1 nuevamente con
respecto al nuevo Z1. Esta asignación se debe realizar antes de realizar el corrimiento de las Z ya que en este
punto los dos primeros bits de Z1 son la combinación que definirá cual es la próxima operación para realizar del

2
M (resaltar que para X1, se llama el control que extrae el bit 0 con la lógica explicada previamente).

Para realizar el corrimiento de Z1 y Z0 es importante remitirse a la lógica del algoritmo. Para empezar, la
explicación de Z1. El cual debe tener desplazamientos de sus valores hacia la derecha. Es por ello por lo que se
creó el control encargado de realizar dicho desplazamiento llamado en el CTRL como “10100 ACC 1 (sin signo)”.
El cual solo hace uso de la función desplazamiento. Como se evidenció en la teoría este procesador presenta el
bloque de desplazamiento por fuera de la ALU. Es por ello por lo que, en control realizado, se realiza una última
línea que simplemente iguala ACC a si mismo. Y, de esta manera se asegura que exista un correcto comporta-
miento de alza de banderas Intrínseca de la ALU. Aunque existe un problema para el caso de Z1, el cual radica
en que el corrimiento para valores negativos modifica el valor existente actual. Para solucionar lo anterior, se
debe realizar una lógica que revise el bit más significativo si encuentra que es un número negativo (bit en 1) el
desplazamiento mueva los bits pero, poniendo un 1 en vez de un 0. Es por ello, que se requiere hacer uso de
otra función en el CTRL creada llamada “– 10011 ACC 1 (con signo)”. Dicha función permite hacer la revisión
explicada previamente almacenando el valor inicial en el registro temporal, posteriormente realizar un corrimiento
hacia la izquierda y luego hacia la derecha para dejar el bit mas significativo en 0 y finalmente realizar el XOR
entre el registro temporal y el ACC modificado. Finalmente, se realiza un corrimiento del registro temporal (valor
inicial) y se le suma al resultado de ACC obteniendo el corrimiento con un 1 en el bit mas significativo en dado
caso que el número inicial fuese negativo.

Por otra parte, el Z0 no requiere realizar ninguna revisión de número positivo o negativo. Por lo cual se hace
uso del control “10100 ACC 1 (sin signo)”. Y, adicionalmente se extrae el bit menos significativo de Z1 por medio
del control ı − −10110ACC = A(Log2 [ACC])ȷ. Se realiza un salto en dado caso que el bit tomado sea 1. Y
se trae de memoria a Auxiliar para sumarla con le número desplazado. La lógica previamente explicada permite
hacer el corrimiento de Z0, y en dado caso que el bit menos significativo de Z1 sea uno se lo deje agregado en el
bit más significativo de Z0.

Con todo ello, se da por concluido el primer ciclo del algoritmo y se procede a traer de memoria el contador,
realizarle un corrimiento a la derecha. Esto, recordando que el algoritmo se repite la cantidad de veces equivalente
a la cantidad de bits de los operandos (para este caso 8). Por lo cual, el realizar el corrimiento del contador una
vez por ciclo permite obtener un resultado de 0000 0000 en contador en el octavo ciclo. Y, si luego de realizar
cada corrimiento se pregunta al ACC (asumiendo que ya se cargó el contador al ACC) si es igual a 0 (si se activa
la bandera Z), es posible conseguir una iteración equivalente a la cantidad de bits de los números. En dado caso
que si lo sea se acaba el programa dejándolo en el loop infinito del Fin. Pero si por el contrario el contador no ha
llegado a cero, debe volver a cargar X1 en A y X0 en ACC para realizar nuevamente el XOR explicado anteriormen-
te que permite determinar si se encuentra en los casos 11-00 o 10-01. Para repetir el ciclo hasta que deba terminar.

Lo anterior, hace uso del código del procesador PDUA desarrollado por la universidad a de los Andes y la
universidad Javeriana. Allí, se tiene un espacio asignado para las ordenes asignadas en la ROM. Es allí, donde se
realiza la totalidad de las instrucciones para llevar al cabo la lógica de multiplicación por Booth. De igual manera,
se realiza la creación de siete registros en CTRL mostrados a continuación:

10011 ACC >1 (con signo)


10100 ACC >1 (sin signo)

10101 ACC = ACC XOR A


10110 ACC = A(Log2 [ACC])
10111 ACC <1

11001 MOVE [DPTR] , ACC / DPTR = CTE

3
11010 MOVE ACC , [DPTR] / DPTR = CTE

Como se explicó previamente, algunos hacen parte de la lógica importante del programa mientras que otros
tienen la función de simplificar y disminuir las líneas de código de la ROM recordando que son limitadas y se
diseñó un programa que hace uso de una gran cantidad de líneas. Tal es el ejemplo de los controles “MOVE
[DPTR] , ACC / DPTR = CTE” y “MOVE ACC , [DPTR] / DPTR = CTE”. Los cuales, son la unión de dos
controles dados por el código inicial que se encargan de usar el apuntador DPTR e importar o llevar información
a la RAM haciendo uso de una constante en ACC que define directamente la dirección de registro que se desea
almacenar. Este pequeño cambio permite agrupar y disminuir 2/3 de la cantidad de líneas en la ROM. Este cambio
tan importante radica en que todas las variables y/o constantes se están almacenando en RAM. Por lo cual el
llamamiento o el envío de información son constantes y comunes a lo largo del código.

2. Diagrama de flujo del algoritmo de multiplicación teniendo en


cuenta las restricciones del PDUA.

Figura 1: Diagrama de flujo del algoritmo de la multiplicación.

4
3. Código en lenguaje de ensamble y máquina

Figura 2: Código en lenguaje de máquina.

Listing 1: Código en lenguaje de ensamble.

when "0000000" = > data <= "01010000"; -- 0 x00 JMP MAIN


when "0000001" = > data <= "00000011"; -- 0 x01 MAIN
when "0000010" = > data <= "00011000"; -- 0 x02 RAI

-- Ingreso del valor de auxiliar en memoria --

when "0000011" => data <= "00011000"; -- 0 x03 MOVE ACC , CTE
when "0000100" => data <= "10000000"; -- 0 x04 CTE / 0 x80
when "0000101" => data <= "11001000"; -- 0 x05 MOVE [ DPTR = CTE ] , ACC
when "0000110" => data <= "10000110"; -- 0 x06 CTE 0 x86

-- Ingreso del valor del contador en memoria --

when "0000111" => data <= "00011000"; -- 0 x07 MOVE ACC , CTE
when "0001000" => data <= "00000001"; -- 0 x08 CTE / 0 x01 = Contador
when "0001001" => data <= "11001000"; -- 0 x09 MOVE [ DPTR = CTE ] , ACC
when "0001010" => data <= "10000111"; -- 0 x0A CTE 0 x87

5
-- Ingreso del valor de M en memoria --

when "0001011" => data <= "00011000"; -- 0 x0B MOVE ACC , CTE
when "0001100" => data <= "11111100"; -- 0 x0C CTE / M
when "0001101" => data <= "11001000"; -- 0 x0D MOVE [ DPTR = CTE ] , ACC
when "0001110" => data <= "10000001"; -- 0 x0E CTE 0 x81

-- Ingreso del valor de Z1 en memoria --

when "0001111" => data <= "00011000"; -- 0 x0F MOVE ACC , CTE
when "0010000" => data <= "00000000"; -- 0 x10 CTE / 0 x00 = Z1
when "0010001" => data <= "11001000"; -- 0 x11 MOVE [ DPTR = CTE ] , ACC
when "0010010" => data <= "10000011"; -- 0 x12 CTE 0 x83

-- Ingreso del valor de X0 en memoria --

when "0010011" = > data <= "11001000"; -- 0 x13 MOVE [ DPTR = CTE ] , ACC
when "0010100" = > data <= "10000100"; -- 0 x14 CTE 0 x84

-- Ingreso del valor de P en memoria --

when "0010101" => data <= "00011000"; -- 0 x15 MOVE ACC , CTE
when "0010110" => data <= "00000011"; -- 0 x16 CTE / P
when "0010111" => data <= "11001000"; -- 0 x17 MOVE [ DPTR = CTE ] , ACC
when "0011000" => data <= "10000000"; -- 0 x18 CTE 0 x80

-- Ingreso del valor de Z0 en memoria --

when "0011001" = > data <= "11001000"; -- 0 x19 MOVE [ DPTR = CTE ] , ACC
when "0011010" = > data <= "10000010"; -- 0 x1A CTE 0 x82

-- Ingreso del valor de X1 en memoria --

when "0011011" => data <= "00010000"; -- 0 x1B MOVE A , ACC


when "0011100" => data <= "00011000"; -- 0 x1C 0 x06 MOVE ACC , CTE
when "0011101" => data <= "00000001"; -- 0 x1D 0 x07 CTE / 0 x01
when "0011110" => data <= "10110000"; -- 0 x1E ACC = A [0]
when "0011111" => data <= "11001000"; -- 0 x1F 0 x08 MOVE [ DPTR ] , ACC
when "0100000" => data <= "10000101"; -- 0 x20 CTE 0 x85

-- Inicio del ciclo --

-- X1 XOR X0 --

when "0100001" => data <= "11010000"; -- 0 x21 SALTO : MOVE ACC
when "0100010" => data <= "10000101"; -- 0 x22 CTE 0 x85 / X1
when "0100011" => data <= "00010000"; -- 0 x23 MOVE A , ACC
when "0100100" => data <= "11010000"; -- 0 x24 MOVE ACC , [ DPTR = CTE ]
when "0100101" => data <= "10000100"; -- 0 x25 CTE 0 x84 / X0
when "0100110" => data <= "10101000"; -- 0 x26 ACC = ACC XOR A

6
-- SALTO SI LOS 2 SON IGUALES --

when "0100111" = > data <= "01011000"; -- 0 x27 JZ ACC == 0


when "0101000" = > data <= "00111001"; -- 0 x28 DESPLAZAMIENTO

-- SALTO SIN SE NIEGA M --

when "0101001" = > data <= "00001000"; -- 0 x29 MOVE ACC , A


when "0101010" = > data <= "01011000"; -- 0 x2A JZ ACC == 0
when "0101011" = > data <= "00110010" ; -- 0 x2B POSITIVO

-- NEGAR M ----

when "0101100" => data <= "11010000"; -- 0 x2C MOVE ACC , [ DPTR = CTE ]
when "0101101" => data <= "10000001"; -- 0 x2D CTE 0 x81
when "0101110" => data <= "10000000"; -- 0 x2E ACC = NOT ( ACC ) + 1
when "0101111" => data <= "00010000"; -- 0 x2F MOVE A , ACC

-- M --

when "0110000" => data <= "01010000"; -- 0 x30 JMP SUMA


when "0110001" => data <= "00110101"; -- 0 x31 SUMA
when "0110010" => data <= "11010000"; -- 0 x32 POSITIVO : MOVE ACC
when "0110011" => data <= "10000001"; -- 0 x33 CTE 0 x81
when "0110100" => data <= "00010000"; -- 0 x34 MOVE A , ACC

-- -- Z1 = Z1 + M ------

when "0110101" => data <= "11010000"; -- 0 x35 SUMA : MOVE ACC
when "0110110" => data <= "10000011"; -- 0 x36 CTE 0 x83
when "0110111" => data <= "01001000"; -- 0 x37 ACC = ACC + A
when "0111000" => data <= "00110000"; -- 0 x38 MOVE [ DPTR ] , ACC

-- -- Volver a asignar X0 y X1 ------

when "0111001" => data <= "11010000"; -- 0 x39 DESPLAZAMIENTO : MOVE ACC
when "0111010" => data <= "10000010"; -- 0 x3A CTE 0 x82 / Z0
when "0111011" => data <= "00010000"; -- 0 x3B MOVE A , ACC
when "0111100" => data <= "00011000"; -- 0 x3C MOVE ACC , CTE
when "0111101" => data <= "00000001"; -- 0 x3D CTE / 0 x01
when "0111110" => data <= "10110000"; -- 0 x3E ACC = A [ ACC ] / X0
when "0111111" => data <= "11001000"; -- 0 x3F MOVE [ DPTR = CTE ] , ACC
when "1000000" => data <= "10000100"; -- 0 x40 CTE 0 x84 / X0
when "1000001" => data <= "00011000"; -- 0 x41 MOVE ACC , CTE
when "1000010" => data <= "00000010"; -- 0 x42 CTE / 0 x02
when "1000011" => data <= "10110000"; -- 0 x43 ACC = A [ ACC ] / X1
when "1000100" => data <= "11001000"; -- 0 x44 MOVE [ DPTR = CTE ] , ACC
when "1000101" => data <= "10000101"; -- 0 x45 CTE 0 x85 / X1

-- -- Z0 >> 1 ----

7
when "1000110" => data <= "00001000"; -- 0 x46 MOVE ACC , A
when "1000111" => data <= "10100000"; -- 0 x47 ACC = ACC >> 1
when "1001000" => data <= "11001000"; -- 0 x48 0 x0E MOVE [ DPTR = CTE ] ,
when "1001001" => data <= "10000010"; -- 0 x49 CTE 0 x82

-- --- Z1 [0] -----

when "1001010" => data <= "11010000"; -- 0 x4A MOVE ACC , [ DPTR = CTE ]
when "1001011" => data <= "10000011"; -- 0 x4B CTE 0 x83
when "1001100" => data <= "00010000"; -- 0 x4C MOVE A , ACC
when "1001101" => data <= "00011000"; -- 0 x4D MOVE ACC , CTE
when "1001110" => data <= "00000001"; -- 0 x4E CTE / 0 x01
when "1001111" => data <= "10110000"; -- 0 x4F ACC = A [ ACC ]

-- - Salto si Z1 [0] == 0 ----

when "1010000" = > data <= "01011000"; -- 0 x50 JP ACC == 0


when "1010001" = > data <= "01011001"; -- 0 x51 valor

-- -- Z0 + Auxiliar -------

when "1010010" => data <= "11010000"; -- 0 x52 MOVE ACC , [ DPTR = CTE ]
when "1010011" => data <= "10000110"; -- 0 x53 CTE 0 x86 / auxiliar
when "1010100" => data <= "00010000"; -- 0 x54 MOVE A , ACC
when "1010101" => data <= "11010000"; -- 0 x55 MOVE ACC , [ DPTR = CTE ]
when "1010110" => data <= "10000010"; -- 0 x56 CTE 0 x82 / Z0
when "1010111" => data <= "01001000"; -- 0 x57 ACC = ACC + A
when "1011000" => data <= "00110000"; -- 0 x58 0 x0E MOVE [ DPTR ] , ACC

-- -- Z1 >> 1 - - - - - - - - - - - - -

when "1011001" => data <= "11010000"; -- 0 x59 Valor : MOVE ACC , [ DPTR
when "1011010" => data <= "10000011"; -- 0 x5A CTE 0 x83 / Z1
when "1011011" => data <= "10011000"; -- 0 x5B ACC = ACC >> 1
when "1011100" => data <= "00110000"; -- 0 x5C MOVE [ DPTR ] , ACC

-- -- Contador << 1 -------

when "1011101" => data <= "11010000"; -- 0 x5D MOVE ACC , [ DPTR = CTE ]
when "1011110" => data <= "10000111"; -- 0 x5E CTE 0 x87 / Contador
when "1011111" => data <= "10111000"; -- 0 x5F ACC = ACC << 1
when "1100000" => data <= "00110000"; -- 0 x60 MOVE [ DPTR ] , ACC

-- -- Salto si Contador == 0 --------

when "1100001" => data <= "01011000"; -- 0 x61 JZ ACC == 0


when "1100010" => data <= "01100101"; -- 0 x62 SALTO
when "1100011" => data <= "01010000"; -- 0 x63 JMP SALTO
when "1100100" => data <= "00100001"; -- 0 x64 SALTO

-- -- Fin ----

8
when "1100101" = > data <= "01010000"; -- 0 x65 JMP FIN
when "1100110" = > data <= "01100100"; -- 0 x66 FIN

4. Simulaciones y análisis de los casos de validación


Para el primer caso se realiza la multiplicación de -1 * 85 que es el caso con el mayor tiempo de ejecución.

Se puede observar el funcionamiento de la nueva función ctrl de asignación de memoria que primero cambia
el ACC por el espacio de memoria y luego se asigna este valor al espacio.

Figura 3: Inicialización de las variables.

En la siguiente imagen se observa el primer ciclo del programa, observando como el programa no realiza ningún
salto debido a que el numero comienza en el valor 1, que complementado con el 0 a su izquierda produce el caso
donde se tiene que sumar -M al segundo registro del resultado.

Figura 4: Primer ciclo, parte 1.

9
Figura 5: Primer ciclo, parte 2.

Para el segundo ciclo el tiempo de ejecución es menor, debido a que la operación es 01 que solamente suma
M al segundo registro del resultado.

Figura 6: Segundo ciclo, parte 1.

10
Figura 7: Segundo ciclo, parte 2.

Para finalizar esta simulación se observa el resultado final, confirmando el resultado que se esperaba obteniendo
el resultado de -85 en formato de complemento A2.

Figura 8: Ciclo final.

11
Para el segundo caso se realiza la multiplicación de 3 * 4

Ahora se realiza una simulación con unos valores básicos, en este caso será 3*4, en la primera imagen solamente
se observa como se asignan las diferentes variables a los espacios de memoria.

Figura 9: Asignación de las variables.

Como P es igual a 4, el primer ciclo es el menor de los tiempos. Se puede observar en el registro del PC que
salta de 26 a 3B aproximadamente.

Figura 10: Primer ciclo.

12
Para el segundo ciclo se tiene un ciclo muy similar al anterior, entonces el tiempo de ejecución es muy parecido.

Figura 11: Segundo ciclo.

El siguiente ciclo debido a que se analiza dos bits en 10, se aumenta el tiempo de ejecución, evidenciado que
el PC no salta en el 28.

Figura 12: Tercer ciclo, parte 1.

13
Figura 13: Tercer ciclo, parte 2.

Finalmente el ciclo final también tiene una condición de 00, lo que genera un salto en el PC que acorta el
tiempo de ejecución.

Figura 14: Ciclo final.

Para el caso final se busca observar el algoritmo, cuando el registro P es igual a 0, como en los anteriores
ejemplos la imagen ilustra la asignación de variables en los espacios de memoria.

14
Figura 15: Asignación de varibales.

Debido a que P es igual a 0 se va a repetir continuamente el ciclo de 00, que produce un salto en el PC que
acorta gran parte del código.

Figura 16: Ciclo completo.

Observando que este es el caso que utiliza la menor cantidad de tiempo con un valor de aproximadamente
2,1ms

15
Figura 17: Ciclo final.

5. Estimaciones de rendimiento para los casos límites y el caso pro-


medio
Determinación del caso promedio

Booth así como otros métodos de multiplicación utilizan uno de los números ingresados para realizar repe-
ticiones del proceso, en el caso de esta implementación se utiliza el registro que almacena M, entonces esta
variable determina los tiempos de la variable. El programa analiza las relaciones de parejas de 2 Bits y por cada
combinación realiza acciones diferentes, esto repercute en el programa debido a que cada acción tiene tiempos de
ejecución diferentes.

Los cuales son los siguientes:

T00: 230 ciclos de reloj


T01: 277 ciclos de reloj
T10: 323 ciclos de reloj
T11: 230 ciclos de reloj

Booth mantiene fijo la cantidad de repeticiones dependiendo del tamaño de los registros que se utilizan, en el
caso del PDUA son registros de 8 bits.

Por lo tanto, es a partir de la combinación de los 4 tiempos previamente mencionados dentro de los 8 ciclos
que se obtiene el tiempo promedio del programa.

Pero estos tiempos no se generan al azar, debido a que al final se analizan parejas de bits, los tiempos son
condicionales al valor previo en específico.

16
Si el valor previo es T00 solamente puede seguir T00 y T10
Si el valor previo es T01 solamente puede seguir T00 y T10
Si el valor previo es T10 solamente puede seguir T11 y T01
Si el valor previo es T11 solamente puede seguir T00 y T10

Figura 18: Diagrama de ramifiación de tiempos.

Los registros de 8 bits pueden almacenar un total de 256 números diferentes, eso será el total de casos del
promedio.

Del diagrama se puede afirmar 2 cosas:

Para el primer ciclo solamente se pueden presentar T00 y T10


Para los siguientes ciclos los tiempos se distribuyen uniformemente en los 4 casos

Estas afirmaciones nos permiten deducir la cantidad de veces que se presenta todos los tiempos. En base al
primer ciclo se puede confirmar que T00 se presenta en la mitad de los casos mientras que T10 en la otra.

Para los siguientes ciclos como los tiempos se distribuyen uniformemente aparecen ¼ de los casos cada uno.

En base a ello se puede afirmar que la suma total de tiempos es igual a

Ttotal−ciclos = T 00 ∗ 128 + T 10 ∗ 128 + 7 ∗ (T 00 ∗ 64 + T 11 ∗ 64 + T 10 ∗ 64 + T 01 ∗ 64)

Este seria el tiempo total para los ciclos de Booth, también se tiene que considerar el tiempo de inicialización
de variables, que como se mantiene constante en cualquier caso solamente se multiplica por los casos totales.

TInicializacin : 166ciclosdereloj

17
Ttotal−inicializacin = 256 ∗ Tinicializacin

Entonces, el tiempo promedio es igual a


256∗Tinicializacin +T 00∗128+T 10∗128+7∗(T 00∗64+T 11∗64+T 10∗64+T 01∗64
Tpromedio = 256

Remplazando los valores se determina el tiempo promedio en ciclos de reloj

Tpromedio = 2297,5ciclosdereloj

Caso maximo

El caso mas extremo se presenta cuando se utilizan los tiempos de ciclo con mayor duración, debido a las
condiciones previamente mencionadas no se puede realizar un proceso con únicamente T10 (El caso con el mayor
tiempo de simulación). En cambio, el caso con el mayor tiempo de simulación es

Tmaximo = Tinicializacin + 4 ∗ T 01 + 4 ∗ T 10

Reemplazando los valores se obtiene

Tmaximo = 2566ciclosdereloj

Debido a que la simulación tiene una duración de 1us el tiempo máximo es igual a

Tmaximo = 2,566ms

6. Conclusiones
El proceso de multiplicación por Booth tiene una superioridad en términos del promedio del tiempo de
procesamiento con respecto al algoritmo de sumas sucesivas. En donde el promedio de booth se sitúa
alrededor de 2.29 ms con respecto a los 15 ms (aproximados) del algoritmo de sumas sucesivas. Con una
eficiencia mejorada en aproximadamente 6.5 veces. Dicha eficiencia, se debe en su mayoría a que la cantidad
de iteraciones respecto a tareas como realizar sumas y restas no incrementa dependiendo de los valores de
los operandos, sino que depende en gran parte de la cantidad de bits de los números.
La varianza encontrada por las pruebas de comprobación matemática del algoritmo de Booth es baja (±0.5
ms). Dicho valor, se genera por la distribución de los bits encendidos y a apagados de los operandos. A
pesar de que el tiempo de procesamiento sea dependiente en gran medida de la cantidad de Bits de los
operandos. El tener el operando P con bits intercalados (101010) genera que la totalidad de desplazamientos
con esos bits intercalados vengan acompañados de una cantidad de ciclos adicionales por las sumas o restas
realizadas (de acuerdo con la tabla de operaciones de Booth). A diferencia de números con bits iguales
como vecinos (11111), en donde los desplazamientos no estarán acompañados de una carga adicional en
términos de ciclos (y por lo tanto de tiempo adicional) por sumas o restas.
La cantidad de líneas posibles a usar en la ROM es de 125. Por lo cual, se encuentra una limitación a
tener en cuenta para desarrollar algoritmos largos o que requieran de una cantidad de líneas importante con
respecto al número mencionado previamente. Tal como es el caso del algoritmo de Booth, se requiere una
gran cantidad de líneas para llevarlo al cabo. Es por ello, que el uso de controles que permitan disminuir la
cantidad de líneas usadas resulta fundamental. La creación de los 7 controles en el CTRL no solo permitió
desarrollar la lógica del programa sino disminuir la cantidad de líneas usadas en la ROM. En especial,
los controles que simplificaban el envío y recibimiento de datos de la RAM fueron fundamentales para no
sobrepasar el límite de líneas. Tal fue la importancia de hacer uso de estos. Que, a pesar de tenerlos (con

18
una disminución de 2/3 de la cantidad de líneas en la ROM si no se hubiesen realizado) se hizo uso de mas
del 80 % de las líneas permitidas.
El caso de mayor gasto de ciclos de reloj por parte del algoritmo es tener en la variable P el número 10101010
ya que por cada desplazamiento debe realizar una operación (ya sea de suma o resta).

Si se interpreta el resultado del formato sin signo el rango dinámico aumenta para los números positivos en
1 bit (hasta 255). Mientras que en los números negativos se llegaría únicamente a (-127)

19

También podría gustarte