Вы находитесь на странице: 1из 58

Capítulo 3

Procesamiento superescalar

Los procesadores superescalares son procesadores segmentados que incorporan recursos


hardware para aumentar el aprovechamiento del paralelismo entre instrucciones
incrementando el número de instrucciones terminadas por ciclo (IPC), o lo que es lo mismo,
reduciendo el número medio de ciclos por instrucción (CPI) en las instrucciones procesadas.
En un procesador superescalar, cada una de las etapas del cauce puede procesar varias
instrucciones por ciclo.

Captación Cola de
(IF) instrucciones

Registros de Emisión Ventana de instrucciones, Decodificación


la arquitectura (ISS) ROB, Búfer de renombrado, etc. (ID)

Registros UF Registros UF Registros UF

Escritura Unidad Unidad Unidad Ejecución


(WB) funcional funcional funcional (EX)

Registro UF Registro UF Registro UF

Figura 1. Esquema simplificado de un cauce superescalar.

La Figura 1 muestra un esquema simplificado de las etapas de un procesador superescalar y


de las estructuras que suelen incluirse para acoplar la velocidad de procesamiento en ciertas
etapas consecutivas y controlar el paso de instrucciones entre ellas. La etapa de captación
puede captar varias instrucciones por ciclo y las almacena en una cola de instrucciones, desde
donde la etapa de decodificación las toma para su decodificación, también a un ritmo de
varias instrucciones por ciclo instrucciones. Las instrucciones decodificadas se introducen en
unas estructuras que permiten determinar si una instrucción puede pasar a ejecutarse porque
tiene sus operandos disponibles y la unidad funcional que necesita disponible. Estas tareas se
pueden implementar utilizando distinto tipo de estructuras como son la ventana de
instrucciones, la estación de reserva, el búfer de renombrado, o el búfer de reordenamiento
(ROB). Las instrucciones que están disponibles pueden emitirse a las unidades de
procesamiento para su ejecución. El número máximo de instrucciones que pueden emitirse
es una característica importante de la microarquitectura del procesador superescalar. Una vez
que las instrucciones han terminado su ejecución escriben sus resultados en estructuras como
el búfer de reordenamiento, desde donde se van pasando al banco de registros, o bien se
escriben directamente en el banco de registros. El número de resultados por ciclo que
pueden escribirse en el banco de registros, desde las unidades funcionales o desde el búfer de
reordenamiento (a fin de cuentas es el número máximo de instrucciones que pueden
terminar de procesarse por ciclo) es otra característica importante del procesador
superescalar.

En un procesador superescalar las instrucciones se captan y se decodifican ordenadamente,


es decir en el mismo orden en que se encuentran en el programa almacenado en memoria.
Una vez decodificadas, las instrucciones se almacenan en una o varias estaciones de reserva
desde donde se envían (dispatch) a las unidades funcionales disponibles en el procesador para
su ejecución. Para que una instrucción pueda enviarse a la unidad funcional correspondiente
ésta debe estar libre y los operandos de la instrucción disponibles. En el caso de que haya
una única estación de reserva centralizada a la que se conectan todas las unidades funcionales
(en cuyo caso, a veces, también se llama ventana de instrucciones), el envío de instrucciones se
suele denominar emisión (issue) y comprende tanto la selección como el envío a la unidad
funcional donde se ejecutará la instrucción. Cuando hay varias estaciones de reserva
asociadas cada una a una unidad funcional, o a un grupo de ellas, en el procesamiento de la
instrucción se distingue entre emisión (issue), desde la unidad de decodificación hasta la
estación de reserva adecuada, y envío (dispatch), desde la estación de reserva a la unidad
funcional cuando la instrucción tiene sus operandos disponibles. El envío (o la emisión en el
caso de una estación de reserva centralizada) puede ser ordenado o desordenado. En el caso de
emisión o envío ordenado, una instrucción no se envía a ejecutar hasta que las instrucciones
que están delante de ella en el código (y por lo tanto estarán antes que ella en la estación de
reserva) no estén listas para enviarse junto a ella, o se hayan enviado ya. En el caso de
emisión o envío desordenado, una instrucción puede enviarse a ejecutar incluso aunque haya
instrucciones que la preceden en la estación de reserva que no puedan empezar a ejecutarse
porque necesitan alguno de sus operandos o que la unidad funcional correspondiente esté
libre. En los procesadores superescalares ha habido una tendencia clara hacia el
envío/emisión desordenado para aprovechar el máximo paralelismo posible entre
instrucciones.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11
mult r5, r1, r5 IF ID EX WB
sub r6, r5, r2 IF ID EX WB
sub r5, r4, r3 IF ID EX WB
add r2, r3, r1 IF ID EX WB

Figura 2. Traza de la ejecución de un fragmento de código en un procesador con emisión desordenada,


una unidad de suma/resta y un multiplicador.
CICLO # CÓDIGO REGISTRO OP1 OK1 OP2 OK2 PRED
OPERACIÓN DESTINO
2 1 sub r6 r5 0 [r2] 1 –
0 mult r5 [r1] 1 [r5] 1 –
3 3 add r2 [r3] 1 [r1] 1 –
2 sub r5 [r4] 1 [r3] 1 –
1 sub r6 r5 0 [r2] 1 –
4 3 add r2 [r3] 1 [r1] 1 –
1 sub r6 r5 0 [r2] 1 –
6 1 sub r6 r5 0 [r2] 1 –
9

Tabla 1. Evolución de la ventana de instrucciones en el ejemplo mostrado en la Figura 2.

La Figura 2 proporciona un ejemplo de emisión desordenada de una secuencia de cuatro


instrucciones en un procesador que utiliza una ventana de instrucciones o estación de reserva
centralizada a la que están conectadas una unidad de suma/resta y otra de multiplicación. En
la Tabla 1 se puede observar la evolución de la ventana de instrucciones o estación de reserva
centralizada del procesador usado en este ejemplo. Cada una de las filas de esta estructura
está formada por los siguientes campos de izquierda a derecha:

 El número de la entrada de la ventana de instrucciones.

 La operación a realizar.

 El registro en el que se debe almacenar el resultado.

 Dos campos consecutivos para el primer operando y otros dos para el


segundo. El primero de ellos indica el valor del operando si el segundo
campo (denominado usualmente campo de operando válido) es igual a uno.
En el caso de que el segundo campo de operando sea cero, el primer
operando codifica el registro de donde se obtendrá el dato. Cuando se
genere el valor del operando, el primer campo se cargará con el valor
obtenido y el segundo campo se hará igual a uno.

 Un campo que indica si la instrucción se ha introducido en el cauce de


forma especulativa.

Haciendo uso de esta estructura, la etapa de emisión podrá mandar a ejecutar las
instrucciones en cuanto tengan sus dos campos de operando válido a uno y esté disponible la
unidad funcional que se necesita para la operación. Como se puede observar en la Tabla 1,
las instrucciones se han introducido de forma ordenada (en la etapa de decodificación) en la
estación de reserva o ventana de instrucciones. En el ciclo 3 podrá emitirse la primera
instrucción, dado que tiene sus operandos disponibles y la unidad de ejecución que necesita
también se supone libre. La instrucción (2) necesita el valor de r5 calculado por la instrucción
(1), por lo que tendrá que esperar hasta el ciclo 9 para ser emitida. Por último, las
instrucciones (3) y (4) entran en la ventana de instrucciones en el ciclo 3. Ambas tienen sus
operandos disponibles, pero como sólo hay una única unidad de suma/resta, la instrucción
(4) tendrá que esperar a que se ejecute la instrucción (3) para ser emitida. Como se puede
comprobar, las instrucciones empiezan a ejecutarse (y terminan de hacerlo) en un orden
distinto al que tienen en el código.
Uno de los problemas que se deben afrontar a la hora de diseñar un cauce superescalar es el
de los riesgos de datos. La Figura 2 muestra un ejemplo de los tres tipos de riesgos que
pueden aparecer: RAW (Read-After-Write), WAR (Write-After-Read) y WAW (Write-After-Write).
El primero de ellos aparece cuando una instrucción necesita un operando (read) después
(after) de que sea generado (write) por otra instrucción previa, tal y como ocurre entre las
instrucciones (2) y (1). Para solucionar este tipo de riesgo, la etapa de emisión bloquea a las
instrucciones en la ventana de instrucciones (o bien las etapa de envío en las estaciones de
reserva) hasta que no tengan sus operandos disponibles, tal y como se ha explicado más
arriba.

En cuanto a los riesgos de datos WAR y WAW, realmente no son riesgos de datos
verdaderamente, ya que aparecen debido al uso repetido del mismo registro como registro de
destino de diferentes instrucciones, por lo que se pueden evitar usando diferentes registros
para almacenar los resultados, es decir, renombrando los registros de destino. La Figura 2
muestra un ejemplo de cada uno de estos riesgos. Por ejemplo, entre las instrucciones (4) y
(2) existe un riesgo WAR causado por el uso de r2, ya que aunque la instrucción (4) es
posterior a la instrucción (2), modifica el valor de r2 antes de que se ejecute la instrucción (2),
por lo que cuando se ejecute la instrucción (2) operará con un valor futuro de r2 en lugar de
operar con el valor adecuado. Por otra parte, también existe un riesgo WAW entre las
instrucciones (3) y (1) a causa del uso repetido del registro de destino r5. Como la instrucción
(1) modifica el registro después que la instrucción (3), a partir de ciclo 10 todas las
instrucciones que usen r5 operarán con un valor pasado del registro. Para evitar estos dos
riesgos bastaría con que las instrucciones (3) y (4) escribieran sus resultados en otros
registros, por ejemplo en r7 y r9.

El renombrado de registros es, por tanto, una técnica que hace desaparecer los riesgos WAR
y WAW y puede ser implementada por el compilador, o bien mediante hardware, usando
unas estructuras denominadas búferes de renombrado. En la Figura 3 se muestran dos esquemas
de búferes de renombrado correspondientes a dos alternativas de acceso posibles. En el
búfer de renombrado con acceso asociativo (Figura 3.a) se distinguen cinco campos en cada
línea, de izquierda a derecha:

 El campo entrada válida indica, cuando está a 1, que esa línea se está
utilizando para hacer un renombrado de registro.

 El campo registro de destino indica el registro que se ha renombrado en esa


línea.

 El campo valor es el que corresponde al espacio reservado para el


renombrado, es decir la nueva ubicación para el dato asociada al registro de
destino usado en la instrucción.

 El campo valor válido indica si el contenido de lo almacenado en el campo


valor es válido.

 El campo último indica si esa línea contiene el último renombrado que se ha


hecho para el registro.

Cuando llega una instrucción se comprueba asociativamente si alguno de sus operandos está
incluido en el búfer de renombrado. Por ejemplo, en la Figura 3.a se está comprobando si
hay algún renombrado del registro r2 (se supone que es uno de los operandos de una
instrucción) comparando asociativamente con las entradas del búfer de renombrado. Si
hubiera varias entradas que renombraran al registro buscado, se utilizará la línea
correspondiente al último renombrado (la que tenga a 1 campo último).

En el caso de acceso indexado, hay un búfer con una línea para cada uno de los registros del
banco de registros del procesador. En cada una de esas líneas hay un campo entrada válida que
indica (cuando está a 1) si se ha hecho un renombrado al registro correspondiente a esa línea
y otro campo que apunta a una línea del búfer de renombrado propiamente dicha. En esa
línea está el espacio reservado para el renombrado del registro (campo valor) y hay además
otro campo que indica si el valor es válido o no (campo valor válido). Aquí no hay necesidad
de un campo de último dado que en el campo de índice se mantiene el puntero al último
renombrado realizado para el registro de la línea correspondiente.

# ENTRADA REGISTRO VALOR VALOR ÚLTIMO


VÁLIDA DE DESTINO VÁLIDO
0 1 r2 50 1 0
1 1 r3 1200 1 1
2 1 r2 20 1 1
3 1 r1 – 0 1
… … … … … …

(a) Búfer asociativo.

# ENTRADA ÍNDICE # VALOR VÁLIDO


VÁLIDA BÚFER
0 0 – 0
1 1 5 1 50 1
2 1 4 2
3 1 3 3 1200 1
… … ... 4 20 1
5 – 0
… … …

(b) Búfer indexado.

Figura 3. Búferes de renombrado.

En un procesador superescalar las instrucciones pueden terminar de ejecutarse en un orden


distinto al que aparecen en el código, incluso aunque la emisión sea ordenada, dado que las
unidades funcionales pueden tener tiempos de latencia diferentes. Por tanto, es necesario
mantener la consistencia secuencial de los programas, es decir, asegurar que el orden en que
se completa el procesamiento de las instrucciones (escribiendo sus resultados en los registros
de la arquitectura) y el orden en que se hacen las lecturas y escrituras en memoria es
consistente con el orden que las instrucciones tienen en el código. Se distinguen dos tipos de
consistencia, consistencia de procesador que se refiere al orden en que se completan las
instrucciones, y consistencia de memoria, en relación con el orden en que se realizan los accesos a
memoria. Se puede distinguir entre consistencia fuerte y débil, en función de que se respete o no
el orden en que las instrucciones aparecen en el código.

Así, en un procesador hay consistencia de memoria fuerte si los accesos a memoria para
lectura o escritura se realizan en el mismo orden en que aparecen en el código, y hay
consistencia débil si se permiten accesos a memoria desordenados, siempre y cuando se
respeten las dependencias de datos. En cuanto a la consistencia de procesador, la
consistencia débil permite que las instrucciones se completen desordenadamente
(lógicamente, respetando las dependencias) mientras que en la dependencia fuerte se
completan en el orden en que aparecen en el código. La tendencia en el diseño de los
procesadores ha ido hacia la consistencia de memoria débil y hacia la consistencia de
procesador fuerte.

Para mantener la consistencia de procesador fuerte se han propuesto diversas estructuras,


entre las que está el búfer de reordenamiento (ROB). El ROB es un búfer en el que las
instrucciones se introducen ordenadamente a medida que se van decodificando (es decir, se
encuentran en el orden de programa) ocupando una línea del búfer cada una. Una
instrucción se podrá retirar del búfer cuando haya finalizado su ejecución y además todas las
instrucciones que la precedan en el ROB (y por tanto en el código) se hayan retirado. El
momento en que una instrucción se retira del ROB es cuando se escribe el resultado de la
misma en el banco de registros de la arquitectura y se dice que la instrucción finaliza su
procesamiento (desaparece del cauce del procesador). Hasta ese momento, los resultados de
las instrucciones que están en el ROB pueden estar almacenados en un campo específico de
la propia línea del ROB donde esté la instrucción, o bien en un campo de una línea del búfer
de renombrado al que apunte un puntero en la línea del ROB, dependiendo de la
implementación del procesador. El número máximo de instrucciones que pueden retirarse
del ROB (es decir el número máximo de instrucciones que pueden finalizar por ciclo en el
procesador) es una característica importante para determinar la velocidad pico del procesador
(en MIPS) y depende de ciertas características de la microarquitectura (número de puertos de
escritura del banco de registros, buses de conexión entre el ROB y el banco de registros,
etc.).

# CÓDIGO REGISTRO VALOR VALOR


OPERACIÓN DESTINO VÁLIDO
3 mult r1 – 0
4 st – – 0
5 add r1 17 1
6 xor r1 – 0

Tabla 2. Ejemplo de búfer de reordenamiento.

En la Tabla 2 se muestra un ROB en el que hay cuatro instrucciones que se han introducido
ordenadamente (desde la línea número 3 a la número 6). Los campos de las líneas del ROB
que se muestran en la Tabla 2 tienen el siguiente significado, de izquierda a derecha:

 Número de línea del ROB (no hace falta que esté implementado como tal
en la línea).

 Código de la operación a ejecutar para cada instrucción.

 Registro del banco de registros del procesador donde se debe escribir el


resultado de la instrucción cuando se retire.

 Campo donde se almacenará temporalmente el resultado de la operación


hasta que la instrucción se retire.

 Campo que indica si el valor almacenado para el dato en la línea del ROB es
válido.
Para que una instrucción pueda retirarse, tanto dicha instrucción como todas las que estén en
líneas anteriores del ROB tienen que tener el campo valor válido (o el campo flush) con el valor
1. Como se puede ver en la Tabla 2, la suma (en la línea 5 del ROB) ha terminado de
ejecutarse pero todavía no ha escrito su resultado en el registro r1 dado que no puede
retirarse antes que las instrucciones de las líneas anteriores del ROB. En esta implementación
del ROB que hemos descrito, el renombrado de registros se hace en el ROB, por lo que no
sería necesario añadir a nuestro procesador búferes de renombrado. El ROB es una
estructura muy útil. De hecho, con ayuda del campo flush puede ayudar también en el
procesamiento de interrupciones y saltos, como veremos a continuación.

Como los procesadores superescalares son también procesadores segmentados, las


instrucciones de salto y las interrupciones tienen un efecto muy pernicioso en sus
prestaciones dado que pueden dar lugar a cambios en la secuencia de instrucciones que
deben introducirse en el cauce (debiéndose anular o evitar el efecto de instrucciones que ya
se habían introducido en el mismo). Como, además, el número de instrucciones que se
captan y decodifican en cada ciclo puede ser considerable, la probabilidad de que se procesen
instrucciones de salto en un ciclo aumenta, por lo que el número de instrucciones que
pueden haberse introducido incorrectamente en el cauce también es elevado.

En los procesadores superescalares la técnica de salto retardado no es eficaz porque las


instrucciones se envían a ejecutar desordenadamente, adelantando las instrucciones
independientes a las que están bloqueadas por algún tipo de dependencia. La técnica usual
para el procesamiento de las instrucciones de salto es la predicción de saltos. Esta técnica se basa
en continuar el procesamiento de instrucciones a partir de la instrucción que, con más
probabilidad, seguirá a la instrucción de salto que se introduce en el cauce. Cuando la
condición de salto se evalúa, se comprueba si la predicción que se había hecho era correcta o
no. En el caso de que no sea correcta habrá que retomar el procesamiento de instrucciones a
partir de la instrucción correspondiente y deshacer el efecto de las instrucciones que se han
introducido en el cauce incorrectamente. Obviamente, la eficacia de este procedimiento se
basa en la capacidad para predecir correctamente la instrucción que seguirá a la instrucción
de salto antes de que ésta se procese. Existen procedimientos de predicción estáticos en los que
el procesador actúa a partir de características de la propia instrucción de salto como por
ejemplo, según la dirección del salto sea hacia direcciones anteriores o posteriores a la
dirección de la instrucción de salto, según la condición de salto utilizada (saltar si igual a cero,
si mayor que cero, etc.), o incluso según el compilador ponga a uno o a cero un bit
determinado en el código máquina de la instrucción de salto. En todos estos casos, la
predicción de saltos se especifica a través del código que se va a ejecutar y las predicciones
no tienen en cuenta el comportamiento real del código al ejecutarse con las entradas
correspondientes. Las técnicas de predicción dinámica tienen en cuenta la historia del
comportamiento pasado de cada instrucción de salto condicional para determinar el
comportamiento más probable cada vez que dicha instrucción entre en el cauce. Para ello se
utiliza una estructura, denominada frecuentemente BTB (Branch Target Buffer). En cada línea
del BTB se introduce información para una instrucción de salto del programa que se está
ejecutando. Así, junto con la dirección de la instrucción de salto, la línea también almacena
una serie de bits que codifican la historia la ejecución del salto en las últimas iteraciones y, en
algunas implementaciones se incluyen campos para la dirección de destino de salto en el caso
de que deba producirse o incluso la propia instrucción de destino de salto, para acelerar así el
acceso a dicha instrucción en el caso de que se prediga que hay que saltar.
Cuando una instrucción llega al cauce se comprueba si hay información de ella en el BTB
buscando (asociativamente) si su dirección se encuentra en el campo correspondiente del
BTB. Si es la primera vez que se procesa la instrucción, no estará incluida en el BTB, por lo
que se tendrá que realizar una predicción estática del salto (por ejemplo una predicción
teniendo en cuenta si el salto es hacia atrás o hacia adelante), se le asignará una línea del BTB
y se inicializará convenientemente el campo de bits de historia teniendo en cuenta si se ha
acertado o no en la predicción. En el caso de que la instrucción de salto que entra en el cauce
ya esté incluida en el BTB, se realiza la predicción según los bits de historia y se actualizan los
mismos según se haya acertado o no en la predicción. La Figura 4 proporciona un ejemplo
de diagrama de estados para un procedimiento de predicción dinámica de salto basado en
dos bits de historia. Existen cuatro posibles estados correspondientes a las cuatro
combinaciones de los dos bits de historia. A dos de esas combinaciones se les asigna la
predicción de salto tomado (Tomado Fuerte y Tomado Débil) y a las otras dos la de salto no
tomado (No Tomado Débil y No Tomado Fuerte). Según se produzca el salto (T, salto tomado) o
no (NT, salto no tomado), los arcos del diagrama indican cómo cambiarán los bits de historia
para realizar la predicción la siguiente vez que llegue la instrucción de salto. Como se puede
ver, mientras que se acierta en la predicción se mantiene la misma, y sólo cuando se falla dos
veces consecutivas se cambia el sentido de ésta. Dada la importancia de disponer de un
esquema de predicción con elevados porcentajes de aciertos, ha habido un trabajo de
investigación bastante activo en este ámbito y se han propuesto una gran cantidad de
procedimientos de predicción con unos requisitos de memoria para los bits de historia
bastante considerables en muchos casos. En [ORT05] se puede completar la información
acerca de éstos.

NT NT NT
T 11 10 01 00 NT

T T T
Tomado Tomado No tomado No tomado
fuerte débil débil fuerte

Predecir tomado Predecir no tomado

Figura 4. Diagrama de estados para predicción dinámica con dos bits de historia.

El ROB facilita el procedimiento de recuperación tras una predicción incorrecta. Para ello se
puede añadir un campo nuevo a cada línea, pred, que permite marcar las instrucciones que se
hayan introducido en el cauce tras la predicción de un salto (incluso se puede indicar el tipo
de predicción, T o NT que se haya hecho). Además, se añade un bit (frecuentemente
denominado bit de vaciado o de flush) a cada línea. Este bit de vaciado se activa, en todas las
instrucciones que se introdujeron tras la instrucción de salto, en el momento en que se
resuelve la condición de salto y, al procesar la instrucción de salto, se determina que la
predicción era incorrecta. Todas las instrucciones que tienen ese bit activado (todas las que se
habían introducido especulativamente en el cauce) se retiran del ROB sin realizar ninguna
modificación en el procesador.

La gestión de las interrupciones/excepciones precisas en un procesador superescalar también


puede facilitarse gracias a la utilización del ROB. Para ello se introduce en cada línea del
ROB otro campo adicional, denominado campo de excepción, tal y como muestra la Tabla 3.
Cuando se produce una excepción en el procesamiento de una instrucción, se activa el
campo de excepción de la línea del ROB correspondiente a dicha instrucción y se activan
también los bits de vaciado o flush de las instrucciones que están en el ROB a continuación de
la que da lugar a la excepción. Cuando una instrucción se retira (es decir, cuando todas las
que le preceden se han retirado ya) se comprueba si el bit del campo de excepción está
activo. Si es así, se retiran del ROB todas las instrucciones con el campo de vaciado activo
(las que siguen a la instrucción que genera la excepción) sin que tengan ningún efecto en el
procesador y se atiende la excepción. Según el tipo de excepción, el programa se reanudará
en la propia instrucción que dio lugar a la excepción o en la siguiente. En la Tabla 3, el
procesamiento de la instrucción de almacenamiento (en la línea 4 del ROB) ha dado lugar a
una excepción que se atenderá cuando dicha instrucción se vaya a retirar (después de que se
termine la ejecución de la multiplicación y ésta se retire escribiendo su resultado en el registro
r1). Las siguientes instrucciones (entradas 5 y 6) se retirarán del cauce sin tener ningún efecto
(no se escribirán sus resultados en el registro r1).

# CÓDIGO REGISTRO VALOR VALOR EXCEP FLUSH


OPERACIÓN DESTINO VÁLIDO
3 mult r1 – 0 0 0
4 st – – 0 1 1
5 add r1 17 1 0 1
6 xor r1 0xa1 1 0 1

Tabla 3. Gestión de interrupciones/excepciones precisas con un ROB.

Existen otros procedimientos para gestionar las interrupciones/excepciones, como son el


uso de búferes de historia, puntos de chequeo, o registros de futuro. En [ORT05] se
describen con más detalle.
Problemas
1. Para el fragmento de código siguiente:

lw r1, 0x1ac ; (1)


lw r2, 0xc1f ; (2)
add r3, r0, r0 ; (3)
mul r4, r2, r1 ; (4)
add r3, r3, r4 ; (5)
add r5, r0, 0x1ac ; (6)
add r6, r0, 0xc1f ; (7)
sub r5, r5, #4 ; (8)
sub r6, r6, #4 ; (9)
sw (r5), r3 ; (10)
sw (r6), r4 ; (11)

y suponiendo que se pueden captar cuatro instrucciones por ciclo y emitir cuatro
instrucciones por ciclo, indique el orden en que se emitirán las instrucciones para cada uno
de los siguientes casos:

a) Una ventana de instrucciones centralizada con emisión ordenada y alineada

b) Una ventana de instrucciones centralizada con emisión desordenada y


alineada

c) Una estación de reserva de tres líneas para cada unidad funcional, con envío
ordenado y ventana deslizante.

NOTA: Considere que hay una unidad funcional para la carga (2 ciclos), otra para el almacenamiento
(1 ciclo), tres para la suma/resta (1 ciclo), y una para la multiplicación (6 ciclos).

Solución
La Figura 5 muestra la evolución de las instrucciones en un cauce con una ventana de instrucciones
centralizada con emisión ordenada y alineada. En este caso, hasta que no se han emitido todas las
instrucciones que entraron en la ventana al decodificarse, no se introducen nuevas instrucciones que
puedan ser emitidas. Esta situación se muestra en la figura mediante una línea gruesa. A continuación
se comentan los atascos que se producen en el cauce:

 Ciclo 5:

 La ejecución de la instrucción (2) debe retrasarse al producirse un riesgo


estructural en la unidad de carga con la instrucción (1).

 La instrucción (3) debe retrasarse hasta que la instrucción (1) haya cargado el
valor de r1.

 Ciclo 7:

 La instrucción (4) debe retrasarse hasta que la instrucción (2) haya cargado el
valor de r2.

 Las instrucciones (5) – (8) no se pueden decodificar hasta que se vacíe la


ventana de instrucciones porque la emisión es alineada.
 Ciclo 13:

 La instrucción (5) depende del resultado de la (4).

 Las instrucciones (6) y (7) deben esperar a que se emita la (5) porque la emisión
es ordenada.

 Ciclo 14:

 La instrucción (8) depende del resultado de la (6).

 Las instrucciones (9) – (11) no se pueden decodificar hasta que se vacíe la


ventana de instrucciones porque la emisión es alineada.

 Ciclo 16:

 La instrucción (11) depende del resultado de la (9).

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
lw r1, 0x1ac IF ID EX
lw r2, 0xc1f IF ID EX
add r3, r0, r0 IF ID EX
mul r4, r2, r1 IF ID EX
add r3, r3, r4 IF ID EX
add r5, r0, 0x1ac IF ID EX
add r6, r0, 0xc1f IF ID EX
sub r5, r5, #4 IF ID EX
sub r6, r6, #4 IF ID EX
sw (r5), r3 IF ID EX
sw (r6), r4 IF ID EX

Figura 5. Traza de la ejecución del código del problema 1 usando una ventana de instrucciones
centralizada con emisión ordenada y alineada.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
lw r1, 0x1ac IF ID EX
lw r2, 0xc1f IF ID EX
add r3, r0, r0 IF ID EX
mul r4, r2, r1 IF ID EX
add r3, r3, r4 IF ID EX
add r5, r0, 0x1ac IF ID EX
add r6, r0, 0xc1f IF ID EX
sub r5, r5, #4 IF ID EX
sub r6, r6, #4 IF ID EX
sw (r5), r3 IF ID EX
sw (r6), r4 IF ID EX

Figura 6. Traza de la ejecución del código del problema 1 usando una ventana de instrucciones
centralizada con emisión desordenada y alineada.

La Figura 6 muestra la evolución de las instrucciones en un cauce con una ventana de instrucciones
centralizada con emisión desordenada y alineada. Los cambios con respecto a la situación anterior son:

 Ciclo 3:

 Se adelanta la ejecución de la instrucción (3).

 Ciclo 8:

 Se adelanta la ejecución de las instrucciones (5) y (6).

 Ciclo 13:
 Las instrucciones (9) – (11) se han podido decodificar un ciclo antes, ya que la
emisión desordenada ha permitido que se vacíe la ventana de instrucciones un
ciclo antes.

En el caso se utilizar estaciones de reserva, las instrucciones se emiten desde el decodificador a cada
estación de reserva en la etapa de decodificación. Desde ahí se envían a las correspondientes unidades
funcionales. Se ha supuesto que la emisión a las estaciones de reserva se hace de forma que se
distribuyen las instrucciones entre todas las unidades del mismo tipo, para minimizar las colisiones y
los tiempos de espera en la correspondiente estación. Como muestra la Figura 7, en este caso el
tiempo de ejecución del programa está determinado por el riesgo estructural en la unidad de carga
entre las instrucciones (1) y (2), y por las dependencias RAW entre las instrucciones (4) y (2), (5) y (4),
(10) y (5), y (11) y (10).

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
lw r1, 0x1ac IF ID EX
lw r2, 0xc1f IF ID EX
add r3, r0, r0 IF ID EX
mul r4, r2, r1 IF ID EX
add r3, r3, r4 IF ID EX
add r5, r0, 0x1ac IF ID EX
add r6, r0, 0xc1f IF ID EX
sub r5, r5, #4 IF ID EX
sub r6, r6, #4 IF ID EX
sw (r5), r3 IF ID EX
sw (r6), r4 IF ID EX

Figura 7. Traza de la ejecución del código del problema 1 usando una estación de reserva de tres líneas
para cada unidad funcional, con envío ordenado y ventana deslizante.

2. Indique como evolucionarían los registros de renombrado al ejecutar las siguientes


instrucciones en un procesador superescalar con renombrado de registros en el que se
utilizan registros específicos para implementar el renombrado y acceso indexado a esos
registros a través de una tabla de mapeo.

mul r2, r0, r1 ; (1)


add r3, r1, r2 ; (2)
sub r2, r0, r1 ; (3)

Solución
La Figura 8 muestra el resultado de insertar la primera instrucción de la secuencia en el búfer de
renombrado. Se ha supuesto que los registros r0 y r1 estaban previamente renombrados y con valores
válidos en las entradas 2 y 4 del búfer, y se ha reservado la entrada 6 para almacenar el resultado de la
instrucción, por tanto, dicha entrada permanecerá marcada como no válida hasta que el resultado esté
disponible.

La Figura 9 muestra el estado del búfer tras la inserción de la instrucción de suma. Se reserva la
entrada 5 del búfer para almacenar el resultado de la instrucción, se marca como no válida, y como el
valor de r2 todavía no está disponible, se indica que el valor de dicho registro se tomará de la entrada 6
del búfer cuando esté disponible.

Por último, la Figura 10 muestra el contenido del búfer de renombrado tras la inserción de la última
instrucción de la secuencia. Se reserva la entrada 7 para el nuevo valor de r2 y se marca como no
válida. Las dos instrucciones anteriores no se ven afectadas por este nuevo renombrado, ya que la
multiplicación almacenará el valor anterior de r2 en la entrada 6, de la que lo tomará la suma,
independientemente del resultado de la resta, que se almacenará en la entrada 7.
REGISTRO ENTRADA ÍNDICE VALOR VÁLIDO
VÁLIDA BÚFER
0 1 2
1 1 4
2 1 6 10 1
3
15 1

Figura 8. Introducción de la instrucción de multiplicación en el búfer de renombrado del problema 2.

REGISTRO ENTRADA ÍNDICE VALOR VÁLIDO


VÁLIDA BÚFER
0 1 2
1 1 4
2 1 6 10 1
3 1 5
15 1
0
0

Figura 9. Introducción de la instrucción de suma en el búfer de renombrado del problema 2.

REGISTRO ENTRADA ÍNDICE VALOR VÁLIDO


VÁLIDA BÚFER
0 1 2
1 1 4
2 1 7 10 1
3 1 5
15 1
0
0
0

Figura 10. Introducción de la instrucción de resta en el búfer de renombrado del problema 2.

3. Suponga que las siguientes instrucciones se introducen una tras otra (en los ciclos indicados
entre paréntesis) en un búfer de renombrado con acceso asociativo.

multd f3, f1, f2 ; (ciclo 3)


addd f2, f3, f1 ; (ciclo 4)
subd f3, f3, f1 ; (ciclo 5)
addd f5, f1, f2 ; (ciclo 5)

a) ¿Cómo evoluciona el búfer de renombrado para esas instrucciones?

b) ¿En qué momento empieza y termina la ejecución de las instrucciones?


c) ¿Cuáles son los valores que quedan en los registros de la arquitectura al
terminar, si inicialmente f1 = 2.0 y f2 = 3.0?

NOTA: La multiplicación tarda 6 ciclos, y la suma y la resta 2 ciclos, y hay suficientes unidades
funcionales como para que no afecten los riesgos estructurales.

Solución
La Tabla 4 muestra la evolución del búfer de renombrado a lo largo de la ejecución de las
instrucciones del fragmento de código del enunciado, marcando en negrita los cambios que ocurren
en cada ciclo. Se ha supuesto que los registros f1 y f2 están previamente renombrados y con los valores
válidos 2.0 y 3.0 respectivamente. A continuación se describe brevemente el contenido de la tabla:

 En el ciclo 3 se decodifica la multiplicación y se crea la entrada 2 para renombrar f3,


con un valor no válido, ya que todavía no se ha ejecutado y con el bit último
activado porque es la última entrada que ha renombrado el registro f3.

 En el ciclo 4 se introduce la suma en el búfer de renombrado, y como se hace una


asignación nueva a f2, el bit último de la entrada 1 del búfer se fija al valor 0,
indicando que si una instrucción posterior necesitase tomar el valor de f2, lo debe
tomar de la entrada 3 del búfer. El bit valor válido de la nueva entrada asignada
debe estar a 0.

 En el ciclo 5 se insertan las dos últimas instrucciones en el búfer de renombrado. Se


asigna la entrada 4 a f3, por lo que el bit último de la entrada 2 del búfer se pone a 0.
También se asigna la entrada 5 del búfer a f5.

CICLO # ENTRADA REGISTRO VALOR VALOR ÚLTIMO


VÁLIDA VÁLIDO
3 0 1 f1 2.0 1 1
1 1 f2 3.0 1 1
2 1 f3 – 0 1
4 0 1 f1 2.0 1 1
1 1 f2 3.0 1 0
2 1 f3 – 0 1
3 1 f2 – 0 1
5 0 1 f1 2.0 1 1
1 1 f2 3.0 1 0
2 1 f3 – 0 0
3 1 f2 – 0 1
4 1 f3 – 0 1
5 1 f5 – 0 1

Tabla 4. Evolución del búfer de renombrado en el problema 3.

La Figura 11 muestra la traza de ejecución de la secuencia de instrucciones. Sólo se han dibujado las
etapas de decodificación y ejecución, ya que es en la primera en la que se introducen las instrucciones
en el búfer de renombrado y en la segunda en la que se ejecutan las instrucciones. Como la
multiplicación tiene sus dos operandos disponibles, se comenzará su ejecución en el siguiente ciclo, y
se terminará en el ciclo 9. La operación de suma de addd f2, f3, f1 no podrá ejecutarse antes del ciclo 10
(cuando termine la multiplicación), y tomará el valor de f3 de la entrada 2 del búfer de renombrado.
Terminará en el ciclo 11, y el resultado se escribirá en la entrada 3 del búfer. La instrucción subd
f3, f3, f1 tomará el valor de f1 de la entrada 1 del búfer (su valor es 2.0) y tomará el valor de f3 que
necesita de la entrada 2 del búfer. Esta operación empezará a ejecutarse en el ciclo 10 y terminará en el
ciclo 11 escribiendo el resultado en la entrada 4. En cuanto a la instrucción addd f5, f1, f2, tomará el
valor de f1 de la entrada 1 del búfer (su valor es 2.0) y tomará el valor de f2 que necesita de la entrada 3
del búfer. Esta operación empezará a ejecutarse en el ciclo 12 y terminará en el ciclo 13.

INSTRUCCIÓN 3 4 5 6 7 8 9 10 11 12 13
multd f3, f1, f2 ID EX
addd f2, f3, f1 ID EX
subd f3, f3, f1 ID
addd f5, f1, f2 ID EX

Figura 11. Traza de la ejecución del código del problema 3.

La Tabla 5 muestra los momentos de inicio y finalización de las instrucciones de la secuencia así como
sus valores finales. De esta tabla se pueden obtener los valores finales para los registros de la
arquitectura, que serán f1 = 2.0, f2 = 8.0, f3 = 4.0, f5 = 10.0.

INSTRUCCIÓN INICIO FIN RESULTADO

multd f3, f1, f2 4 9 2.0 × 3.0 = 6.0


addd f2, f3, f1 10 11 6.0 + 2.0 = 8.0
subd f3, f3, f1 10 11 6.0 – 2.0 = 4.0
addd f5, f1, f2 12 13 2.0 + 8.0 = 10.0

Tabla 5. Resultados y ciclos de inicio y finalización de las instrucciones del problema 3.

4. Suponga que las siguientes instrucciones se introducen una tras otra (en los ciclos indicados
entre paréntesis) en un búfer de renombrado con acceso asociativo.

multd f3, f1, f2 ; (ciclo 3)


addd f2, f3, f1 ; (ciclo 4)
subd f3, f3, f1 ; (ciclo 4)
multd f5, f1, f4 ; (ciclo 5)
addd f6, f2, f3 ; (ciclo 6)

a) ¿Cómo evoluciona el búfer de renombrado para esas instrucciones?

b) ¿En qué momento empieza y termina la ejecución de las instrucciones


suponiendo que en el procesador hay una unidad de multiplicación y otra de
suma/resta, y se utiliza emisión desordenada?

c) Indique el menor número de unidades de multiplicación y de suma/resta


que habría que añadir para minimizar el tiempo de ejecución de las
instrucciones.

NOTA: La unidad de multiplicación tarda 5 ciclos, y la de suma/resta 2 ciclos, y cada unidad dispone
de una estación de reserva con espacio suficiente para tres instrucciones.

Solución
La Tabla 6 muestra la evolución del búfer desde el ciclo 3 al ciclo 6, marcando en negrita los cambios
que ocurren en cada ciclo. A continuación se describe brevemente su contenido:

 En el ciclo 3 se decodifica la instrucción multd f3, f1, f2 y se renombra f3 en la


entrada 0. Como hemos supuesto que inicialmente el búfer de renombrado está
vacío y que todos los valores con los que se va a operar están preparados en el
banco de registros del computador, esta instrucción podrá empezar a ejecutarse en
el ciclo siguiente.

 En el ciclo 4 se introducen en el búfer de renombrado las instrucciones


addd f2, f3, f1 y subd f3, f3, f1. Como ambas operan con los mismos operandos, las
dos toman el operando f1 del banco de registros y marcan al segundo operando en
la estación de reserva como pendiente y esperando a que se calcule y se almacene en
la entrada 1 del búfer de renombrado. Como la instrucción subd f3, f3, f1 vuelve a
escribir en f3, se pone a 1 el bit último de la entrada 3 y a 0 el de la entrada 0.

 En el ciclo 5 se introduce en el búfer de renombrado la instrucción multd f5, f1, f4,


con lo que se renombra al registro f5 en la siguiente entrada del búfer de
renombrado. Como tiene sus dos operandos disponibles en el banco de registros,
podrá pasar a ejecutarse en el siguiente ciclo.

 Por último, en el ciclo 6, se introduce en el búfer de renombrado la instrucción


addd f6, f2, f3, que depende de los operandos f2 y f3 que están pendientes y que se
tomarán de las entradas del búfer de renombrado 2 y 3 respectivamente cuando
estén disponibles. Esta instrucción provoca el renombrado del registro f6.

CICLO # ENTRADA REGISTRO VALOR VALOR ÚLTIMO


VÁLIDA VÁLIDO
3 0 1 f3 – 0 1
4 0 1 f3 – 0 0
1 1 f2 – 0 1
2 1 f3 – 0 1
5 0 1 f3 – 0 0
1 1 f2 – 0 1
2 1 f3 – 0 1
3 1 f5 – 0 1
6 0 1 f3 – 0 0
1 1 f2 – 0 1
2 1 f3 – 0 1
3 1 f5 – 0 1
4 1 f6 – 0 1

Tabla 6. Evolución del búfer de renombrado en el problema 4.

INSTRUCCIÓN 3 4 5 6 7 8 9 10 11 12 13 14
multd f3, f1, f2 ID EX
addd f2, f3, f1 ID EX
subd f3, f3, f1 ID EX
multd f5, f1, f4 ID EX
addd f6, f2, f3 ID EX

Figura 12. Traza de la ejecución del código del problema 4.

Conforme vaya finalizando la ejecución de las instrucciones, se irán escribiendo sus resultados en el
campo valor de sus entradas del búfer de renombrado. En el momento de escribir el valor, se
cambiará el campo valor válido de 0 a 1 y cualquier instrucción que esté esperando el dato escrito
podrá pasar a ejecutarse. Teniendo en cuenta las dependencias de datos, las latencias de las unidades
de ejecución, y que solamente hay un sumador y un multiplicador, los ciclos de inicio y finalización de
la ejecución de las instrucciones son los que se muestran en la Figura 12. Sólo se han dibujado las
etapas de decodificación y ejecución, ya que es en la primera en la que se introducen las instrucciones
en el búfer de renombrado y en la segunda en la que se ejecutan las instrucciones.
Aumentando el número de sumadores y de multiplicadores a 2, eliminamos todos los riesgos
estructurales y conseguimos que los únicos atascos en el cauce se deban a dependencias entre datos, lo
que nos ahorra dos ciclos en la ejecución del programa, como muestra la Figura 13.

INSTRUCCIÓN 3 4 5 6 7 8 9 10 11 12
multd f3, f1, f2 ID EX
addd f2, f3, f1 ID EX
subd f3, f3, f1 ID EX
multd f5, f1, f4 ID EX
addd f6, f2, f3 ID EX

Figura 13. Traza de la ejecución del código del problema 4 aumentando el número de unidades de
ejecución.

5. Suponga que las siguientes instrucciones se han decodificado en los ciclos indicados entre
paréntesis, introduciéndose en una estación de reserva común para todas las unidades
funcionales de coma flotante.

multd f3, f1, f2 ; (ciclo 2)


addd f2, f3, f1 ; (ciclo 2)
subd f3, f3, f1 ; (ciclo 3)
addd f4, f1, f2 ; (ciclo 3)

Teniendo en cuenta que el procesador superescalar dispone de un ROB para implementar la


finalización ordenada, y que la emisión es desordenada y no alineada,

a) ¿Cómo evolucionaría el ROB para esas instrucciones?

b) ¿En qué momento empieza y termina la ejecución de las instrucciones?

c) ¿Cuáles son los valores que quedan en los registros de la arquitectura al


terminar, si inicialmente f1 = 3.0 y f2 = 2.0?

NOTA: La multiplicación tarda 4 ciclos, y la suma y la resta 2 ciclos. Hay tantas unidades funcionales
como sea necesario para que no haya riesgos estructurales. Se pueden enviar, retirar, etc., dos
instrucciones por ciclo como máximo.

Solución
Para resolver el problema se parte de la Figura 14, en la que se indican los ciclos en los que las
instrucciones se terminan de decodificar (ID) y han pasado a la estación de reserva, los ciclos en los
que comienza y termina la ejecución de la operación correspondiente a la instrucción (EX), los ciclos
en los que el resultado de la operación se ha almacenado en el ROB, y el momento en que después de
retirar la instrucción del ROB, los resultados se han almacenado en el banco de registros de la
arquitectura (WB). Esta figura constituye la respuesta al segundo del problema. Las instrucciones
segunda y tercera deben esperar que termine la ejecución de la primera, y la cuarta instrucción espera
que termine la segunda.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12
multd f3, f1, f2 IF ID EX ROB WB
addd f2, f3, f1 IF ID EX ROB WB
subd f3, f3, f1 IF ID EX ROB WB
addd f4, f1, f2 IF ID EX ROB WB

Figura 14. Traza de la ejecución del código del problema 5.


CICLO # CÓDIGO REGISTRO VALOR VALOR
OPERACIÓN DESTINO VÁLIDO
2 0 multd f3 – 0
1 addd f2 – 0
3 0 multd f3 – 0
1 addd f2 – 0
2 subd f3 – 0
3 addd f4 – 0
7 0 multd f3 6.0 1
1 addd f2 – 0
2 subd f3 – 0
3 addd f4 – 0
8 1 addd f2 – 0
2 subd f3 – 0
3 addd f4 – 0
9 1 addd f2 9.0 1
2 subd f3 3.0 1
3 addd f4 – 0
10 3 addd f4 – 0
11 3 addd f4 12.0 1

Tabla 7. Evolución del ROB en el problema 5.

La Figura 14 también ayuda a determinar la evolución del ROB, detallada en la Tabla 7:

 El ROB empieza a llenarse al final del ciclo 2, después de haberse decodificado las
dos primeras instrucciones.

 Al finalizar el tercer ciclo se introducen en el ROB las dos instrucciones restantes, y


también habrá empezado a ejecutar la multiplicación.

 Hasta el ciclo 7 no ocurre nada en el ROB (en relación con las instrucciones que
indica el problema). Al final de este ciclo se habrá terminado la multiplicación, y el
resultado estará almacenado en el campo de valor de la entrada 0 del búfer, el bit de
valor válido estará a 1, y también se habrá iniciado la ejecución de las instrucciones
(2), y (3).

 En el ciclo 8 se retirará la instrucción (1) del ROB.

 Al final del ciclo 9 habrá terminado la ejecución de las instrucciones (2) y (3) y sus
resultados estarán almacenados en las entradas 1 y 2 el ROB, y habrá empezado la
ejecución de la instrucción (4).

 Al final del ciclo 10 se habrán retirado las instrucciones (2) y (3) y se escribirán sus
resultados en los registros f2 y f3.

 Al finalizar el ciclo 11 el resultado de la instrucción 4 se habrá almacenado en la


entrada 3 del ROB.

 En ciclo 12 se retirará la instrucción (4) y se escribirá el resultado en f1.


Teniendo en cuenta la evolución del ROB y las operaciones realizadas, los registros quedan al final
con los valores:

 f1 = 3.0

 f2 = 9.0

 f3 = 3.0

 f4 = 12.0

6. Se dispone de un procesador superescalar con la siguiente configuración:

 una estación de reserva RS1 para las sumas y restas

 una estación de reserva RS2 para las multiplicaciones y divisiones

 un búfer de reordenamiento ROB

 dos unidades de ejecución de sumas/restas con una latencia de 2 ciclos

 una unidad de ejecución de multiplicaciones con una latencia de 5 ciclos

 una unidad de ejecución de divisiones con una latencia de 40 ciclos

El procesador es capaz de captar, decodificar, emitir y retirar hasta dos instrucciones por
ciclo, y las estaciones de reserva pueden realizar envíos no alineados y desordenados a las
unidades de ejecución. Si los registros f1 y f2 tienen inicialmente los valores 10.0 y 5.0, ¿qué
valores se obtendrán tras la ejecución del siguiente programa y en qué ciclos se escribirá en
los registros de la arquitectura?

addd f3, f1, f2 ; (1)


addd f2, f3, f2 ; (2)
multd f4, f3, f2 ; (3)
divd f5, f2, f1 ; (4)
subd f2, f3, f1 ; (5)

Solución
La Figura 15 muestra una traza de la ejecución del programa en el procesador que se detalla en el
enunciado. A continuación se describe lo que ocurre en el procesador para cada instrucción:

 La instrucción (1) se emite a la estación de reserva RS1 en el ciclo 2 y puede


enviarse al sumador 1 al siguiente ciclo (ciclo 3) de su emisión, ya que sus
operandos f1 y f2 están disponibles en la estación de reserva RS1 en el momento de
su emisión. Tras los dos ciclos que tarda una suma, la instrucción finaliza almacena
el resultado en el ROB y en las estaciones de reserva que necesiten el nuevo valor
de f3 en el ciclo 5. Al ciclo siguiente (ciclo 6) se retirará del ROB almacenando en el
registro f3 el valor 15.

 La instrucción (2) también se emite en el ciclo 2 a RS1, pero como tiene una
dependencia RAW con la instrucción (1) en f3, debe esperar a que f3 se haya
calculado para poder ejecutarse. En cuanto tiene disponible f3 (ciclo 5) pasa a
ejecutarse al sumador 1 y almacena el resultado en el ROB en el ciclo 7 (los
sumadores tienen una latencia de 2 ciclos). En el siguiente ciclo (ciclo 8) se retirará
del ROB y almacenará en el registro f2 el valor 20.
 La instrucción (3) se emite en el ciclo 3 a la estación de reserva RS2, ya que las dos
primeras se emitieron en el ciclo 2 y sólo se pueden emitir dos instrucciones por
ciclo. Esta instrucción no podrá ejecutarse hasta el ciclo 7, ya que tiene
dependencias RAW con las instrucciones (1) y (2) en los registros f3 y f2
respectivamente, y almacenará su resultado en el ROB en el ciclo 12 porque el
multiplicador tiene una latencia de 5 ciclos. En el ciclo 13 se retirará del ROB
escribiendo en el registro f4 el valor 300.

 La instrucción (4) se emite también a RS2 en el ciclo 3 pero no podrá ejecutarse


hasta el ciclo 7 debido a la dependencia RAW con las instrucción (2) en f2. Como
las divisiones tienen una latencia de 40 ciclos, esta instrucción estará ejecutándose
desde el ciclo 7 hasta el 46. En el ciclo 47 escribirá el resultado en el ROB y en el
ciclo 48 se retirará escribiendo en el registro f5 el valor 2.

 La instrucción (5) se emitirá en el ciclo 4 a RS1, ya que las dos anteriores se


emitieron en el ciclo anterior, y en el ciclo 5, como ya tiene disponible el valor de f3
que produce la instrucción (1), podrá pasar a ejecutarse a uno de los sumadores. En
el ciclo 7 almacenará el resultado en el ROB, pero no podrá retirarse hasta el ciclo
48, que es cuando se retira la instrucción (4), ya que la retirada debe ser ordenada,
así que como pueden retirarse dos instrucciones por ciclo, en el ciclo 48 se retirará y
escribirá en el registro f2 el valor 5.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 … 46 47 48
addd f3, f1, f2 IF ID EX ROB WB
addd f2, f3, f2 IF ID EX ROB WB
multd f4, f3, f2 IF ID EX ROB WB
divd f5, f2, f1 IF ID EX … ROB WB
subd f2, f3, f1 IF ID EX ROB … WB

Figura 15. Traza de la ejecución del código del problema 6.

7. Considere que el fragmento de código siguiente:

lw r3, 0x10a ; (1)


addi r2, r0, #128 ; (2)
add r1, r0, 0x0a ; (3)
lw r4, 0(r1) ; (4)
lw r5, –8(r1) ; (5)
mult r6, r5, r3 ; (6)
add r5, r6, r3 ; (7)
add r6, r4, r3 ; (8)
sw 0(r1), r6 ; (9)
sw –8(r1), r5 ; (10)
sub r2, r2, #16 ; (11)

se ejecuta en un procesador superescalar que es capaz de captar 4 instrucciones/ciclo, de


decodificar 2 instrucciones/ciclo, de emitir (utilizando una ventana de instrucciones con
emisión no alineada) 2 instrucciones/ciclo, escribir hasta 2 resultados/ciclo en los registros
correspondientes (registros de reordenamiento, o registros de la arquitectura según el caso), y
completar (o retirar) hasta 2 instrucciones/ciclo.

a) Indique el número de ciclos que tardaría en ejecutarse el programa


suponiendo:

 Emisión ordenada y ejecución desordenada.

 Emisión desordenada y ejecución desordenada.


b) ¿Qué mejoras realizaría en el procesador para reducir el tiempo de ejecución
en la mejor de las opciones anteriores sin cambiar el diseño de las unidades
funcionales (multiplicador, sumador, etc.) y sin cambiar el tipo de memorias
ni la interfaz entre procesador y memoria (no varía el número de
instrucciones captadas por ciclo)?

c) ¿Qué pasaría si se reduce el tiempo de multiplicación a la mitad?

NOTA: Considere que el procesador tiene una unidad funcional de carga con una latencia de 2 ciclos,
una unidad de almacenamiento con una latencia de 1 ciclo, tres unidades de suma/resta con
una latencia de 1 ciclo, una unidad de multiplicación con una latencia de 6 ciclos, y que no
hay limitaciones para el número de líneas de la cola de instrucciones, ventana de
instrucciones, búfer de reordenamiento, puertos de lectura/escritura etc.

Solución
En la emisión ordenada (Figura 16) los instantes en los que las instrucciones empiezan a ejecutarse
(etapa EX) deben estar ordenados de menor a mayor, a diferencia de lo que ocurre en la emisión
desordenada (Figura 17). Dado que el procesador utiliza un búfer de reordenamiento (ROB), la
finalización del procesamiento de las instrucciones es ordenada y por ello, las etapas WB de las
instrucciones (momento en que se retiran las instrucciones del ROB y se escriben en los registros de la
arquitectura) deben estar ordenadas en ambas tablas.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
lw r3, 0x10a IF ID EX ROB WB
addi r2, r0, #128 IF ID EX ROB WB
add r1, r0, 0x0a IF ID EX ROB WB
lw r4, 0(r1) IF ID EX ROB WB
lw r5, –8(r1) IF ID EX ROB WB
mult r6, r5, r3 IF ID EX ROB WB
add r5, r6, r3 IF ID EX ROB WB
add r6, r4, r3 IF ID EX ROB WB
sw 0(r1), r6 IF ID EX ROB WB
sw –8(r1), r5 IF ID EX ROB WB
sub r2, r2, #16 IF ID EX ROB WB

Figura 16. Traza de la ejecución del código del problema 7 usando una emisión ordenada.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
lw r3, 0x10a IF ID EX ROB WB
addi r2, r0, #128 IF ID EX ROB WB
add r1, r0, 0x0a IF ID EX ROB WB
lw r4, 0(r1) IF ID EX ROB WB
lw r5, –8(r1) IF ID EX ROB WB
mult r6, r5, r3 IF ID EX ROB WB
add r5, r6, r3 IF ID EX ROB WB
add r6, r4, r3 IF ID EX ROB WB
sw 0(r1), r6 IF ID EX ROB WB
sw –8(r1), r5 IF ID EX ROB WB
sub r2, r2, #16 IF ID EX ROB WB

Figura 17. Traza de la ejecución del código del problema 7 usando una emisión desordenada.

Otro aspecto que debe tenerse en cuenta a la hora de realizar la traza es la posibilidad de que ocurran
riesgos estructurales. En este caso, debido a que sólo hay una unidad de carga, aparece un riesgo
estructural entre las instrucciones (4) y (5), lo que provoca que la ejecución de la instrucción (5) se
tenga que retrasar hasta el ciclo 7. Además hay que tener en cuenta que se decodifican, emiten,
escriben en el ROB, o retiran, dos instrucciones por ciclo como máximo, por tanto, en un mismo ciclo
no puede haber más de dos instrucciones en las etapas ID, EX, ROB, y WB. Esta limitación afecta a la
instrucción (11) en la Figura 17 que escribe el resultado en el ROB en el ciclo 10, y no en el 9.
Como excepción a la regla anterior tenemos el caso de las instrucciones de almacenamiento en la etapa
WB. Se ha supuesto que la limitación de retirar hasta dos instrucciones por ciclo se deriva de que sólo
hay dos puertos de escritura en el banco de registros, pero como las instrucciones de almacenamiento
no escriben en el banco de registros, en un mismo ciclo se podrán retirar hasta dos instrucciones que
escriban en el banco de registros y además todas las instrucciones de almacenamiento que hayan
finalizado.

Para resolver la segunda cuestión, inicialmente se considera que se decodifican el mismo número de
instrucciones que se captan, ya que no existen limitaciones impuestas por las instrucciones al ritmo de
decodificación (éste viene determinado por las posibilidades de los circuitos de descodificación y la
capacidad para almacenar las instrucciones decodificadas hasta que se emitan). También se considera
que no existen limitaciones para el número de instrucciones por ciclo que se emiten, escriben el ROB,
y se retiran. Por último, se consideran que están disponibles todas las unidades funcionales que se
necesiten para que no haya colisiones (riesgos estructurales).

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
lw r3, 0x10a IF ID EX ROB WB
addi r2, r0, #128 IF ID EX ROB WB
add r1, r0, 0x0a IF ID EX ROB WB
lw r4, 0(r1) IF ID EX ROB WB
lw r5, –8(r1) IF ID EX ROB WB
mult r6, r5, r3 IF ID EX ROB WB
add r5, r6, r3 IF ID EX ROB WB
add r6, r4, r3 IF ID EX ROB WB
sw 0(r1), r6 IF ID EX ROB WB
sw –8(r1), r5 IF ID EX ROB WB
sub r2, r2, #16 IF ID EX ROB WB

Figura 18. Traza de la ejecución del código del problema 7 usando una emisión desordenada y sin
restricciones en el número de unidades de ejecución, instrucciones procesadas por etapa, tamaño de los
búferes, etc.

Una vez encontrada la distribución temporal de las instrucciones en las distintas etapas, tal y como se
muestra en la Figura 18, se observa que, las mejoras necesarias (sin modificar los tiempos de
procesamiento de las unidades funcionales) para reducir el tiempo al mínimo que permiten las
dependencias RAW entre las instrucciones han sido: decodificar 4 instrucciones por ciclo, emitir,
escribir en el ROB, y retirar hasta tres instrucciones por ciclo, y añadir una unidad de carga de
memoria más.

En la Figura 19 se muestra la distribución temporal de instrucciones en etapas cuando, además de las


mejoras anteriores, se reduce el tiempo de la multiplicación a tres ciclos (la mitad de lo que duraba
antes). Como se puede comprobar, esa reducción de tres ciclos también se observa en el tiempo final
de la secuencia de instrucciones. Se pone así de manifiesto, que el tiempo de la multiplicación es uno
de los determinantes fundamentales de las prestaciones.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12
lw r3, 0x10a IF ID EX ROB WB
addi r2, r0, #128 IF ID EX ROB WB
add r1, r0, 0x0a IF ID EX ROB WB
lw r4, 0(r1) IF ID EX ROB WB
lw r5, –8(r1) IF ID EX ROB WB
mult r6, r5, r3 IF ID EX ROB WB
add r5, r6, r3 IF ID EX ROB WB
add r6, r4, r3 IF ID EX ROB WB
sw 0(r1), r6 IF ID EX ROB WB
sw –8(r1), r5 IF ID EX ROB WB
sub r2, r2, #16 IF ID EX ROB WB

Figura 19. Traza de la ejecución del código del problema 7 usando una emisión desordenada,
procesando hasta res instrucciones por ciclo, con dos unidades de carga y con un multiplicador de tres
ciclos de latencia.
Si se tiene en cuenta que la secuencia consta de 11 instrucciones, que el tiempo mínimo que tarda la
primera instrucción en salir son 6 ciclos (lo tomamos como tiempo de latencia de inicio del cauce), y
que el tiempo total de ejecución en este caso es de 12 ciclos, se puede escribir:

T n   12  TLI  n  1  CPI  6  11  1  CPI

con lo que, si se despeja, se tiene que el procesador superescalar presenta una media de 0.6 ciclos por
instrucción, o lo que es lo mismo, ejecuta 1.67 instrucciones por ciclo.

8. Indique cómo evolucionaría el búfer de reordenamiento en el mejor de los casos del


problema anterior.

Solución
La Tabla 8 muestra la evolución del búfer de reordenamiento marcando en negrita los cambios que se
producen en cada ciclo:

 En el ciclo 2 se decodifican las instrucciones (1) – (4) y se introducen en el ROB.

 En el ciclo 3 se decodifican las instrucciones (5) – (8) y se introducen en el ROB.

 En el ciclo 4 se decodifican las instrucciones (9) – (11) y se introducen en el ROB.


Simultáneamente se almacena en el ROB los resultados de las instrucciones (2) y
(3), cuya ejecución finalizó en el ciclo anterior.

 En el ciclo 5 se escribe en el ROB el resultado de la instrucción (1).

 En el ciclo 6 se retiran las tres primeras instrucciones y se escriben los resultados de


las instrucciones (4), (5) y (11) en el ROB.

 En el ciclo 7 se retiran las instrucciones (4) y (5) y se escribe en el ROB el resultado


de la instrucción (8).

 En el ciclo 8 se activa el bit valor válido de la instrucción (9) en el ROB, indicando


que la instrucción de almacenamiento ya ha escrito en memoria.

 En el ciclo 9 se escribe el resultado de la instrucción (6) en el ROB.

 En el ciclo 10 se retira la instrucción (6) y se escribe el resultado de la instrucción


(7) en el ROB.

 En el ciclo 11 se retiran las instrucciones (7), (8) y (9) y se indica que la instrucción
(10) ya ha escrito en memoria.

 En el ciclo 12 se retiran las dos últimas instrucciones del ROB.

CICLO # CÓDIGO REGISTRO VALOR VALOR


OPERACIÓN DESTINO VÁLIDO
2 0 lw r3 – 0
1 addi r2 – 0
2 add r1 – 0
3 lw r4 – 0

Tabla 8. Evolución del ROB en el problema 8.


CICLO # CÓDIGO REGISTRO VALOR VALOR
OPERACIÓN DESTINO VÁLIDO
3 0 lw r3 – 0
1 addi r2 – 0
2 add r1 – 0
3 lw r4 – 0
4 lw r5 – 0
5 mult r6 – 0
6 add r5 – 0
7 add r6 – 0
4 0 lw r3 – 0
1 addi r2 128 1
2 add r1 0x0a 1
3 lw r4 – 0
4 lw r5 – 0
5 mult r6 – 0
6 add r5 – 0
7 add r6 – 0
8 sw – – 0
9 sw – – 0
10 sub r2 – 0
5 0 lw r3 [0x1a] 1
1 addi r2 128 1
2 add r1 0x0a 1
3 lw r4 – 0
4 lw r5 – 0
5 mult r6 – 0
6 add r5 – 0
7 add r6 – 0
8 sw – – 0
9 sw – – 0
10 sub r2 – 0
6 3 lw r4 [0x0a] 1
4 lw r5 [0x0a – 8] 1
5 mult r6 – 0
6 add r5 – 0
7 add r6 – 0
8 sw – – 0
9 sw – – 0
10 sub r2 112 1

Tabla 8. Evolución del ROB en el problema 8.


CICLO # CÓDIGO REGISTRO VALOR VALOR
OPERACIÓN DESTINO VÁLIDO
7 5 mult r6 – 0
6 add r5 – 0
7 add r6 r4 + r3 1
8 sw – – 0
9 sw – – 0
10 sub r2 112 1
8 5 mult r6 – 0
6 add r5 – 0
7 add r6 r4 + r3 1
8 sw – – 1
9 sw – – 0
10 sub r2 112 1
9 5 mult r6 r5 × r3 1
6 add r5 – 0
7 add r6 r4 + r3 1
8 sw – – 1
9 sw – – 0
10 sub r2 112 1
10 6 add r5 r6 + r3 1
7 add r6 r4 + r3 1
8 sw – – 1
9 sw – – 0
10 sub r2 112 1
11 9 sw – – 1
10 sub r2 112 1

Tabla 8. Evolución del ROB en el problema 8.

9. Considere que el fragmento de código siguiente:

subd f2, f2, f1 ; (1)


addd f4, f2, f3 ; (2)
subd f5, f2, f3 ; (3)
multd f6, f2, f3 ; (4)
subd f2, f2, f5 ; (5)
subd f7, f4, f6 ; (6)

se ejecuta en un procesador superescalar capaz de captar, decodificar y emitir (mediante una


ventana de instrucciones centralizada) 3 instrucciones/ciclo, y completar (o retirar) hasta 2
instrucciones/ciclo.

a) Si el procesador dispone de un búfer de reordenamiento para permitir la


ejecución desordenada y la finalización ordenada, indique el tiempo de
ejecución en el caso de emisión ordenada (no alineada). ¿Se gana tiempo si
la emisión es desordenada (y no alineada)?
b) Para la situación más favorable, ¿qué es mejor aumentar en uno el número
unidades de suma/resta o reducir el tiempo de ejecución de las existentes en
una unidad?

NOTA: El procesador dispone de 2 unidades de suma/resta (de 2 ciclos), una de multiplicación (de 4
ciclos), y que no hay limitaciones en el número de líneas de la cola de instrucciones, búfer de
reordenamiento, puertos de lectura/escritura, etc.

Solución
En la Figura 20 se muestra la evolución temporal del conjunto de instrucciones indicado usando una
emisión ordenada (no alineada).

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12
subd f2, f2, f1 IF ID EX ROB WB
addd f4, f2, f3 IF ID EX ROB WB
subd f5, f2, f3 IF ID EX ROB WB
multd f6, f2, f3 IF ID EX ROB WB
subd f2, f2, f5 IF ID EX ROB WB
subd f7, f4, f6 IF ID EX ROB WB

Figura 20. Traza de la ejecución del código del problema 9 usando emisión ordenada.

Las instrucciones (2), (3), y (4) han de esperar a que termine de ejecutarse la instrucción (1) para
disponer de su operando f2. La instrucción (5) también tiene que esperar al operando f2, pero como
también necesita f5, que es producida por la instrucción (3), debe esperar hasta que haya terminado
ésta. Por otra parte, tampoco podría enviarse, dado que no se pueden enviar más de tres instrucciones
por ciclo, y se envían las instrucciones (2), (3), y (4) en el ciclo 5. Por último, la instrucción (6) debe
esperar que termine la (4) porque depende de f6.

Si la emisión es desordenada no se ganaría nada para las instrucciones indicadas, ya que lo que limita
su emisión son las dependencias RAW entre ellas. Ninguna instrucción posterior a la instrucción (1) se
puede enviar antes del ciclo 5 (la instrucción (1) produce f2 que es consumido por las instrucciones
(2), (3), (4), y (5)). La instrucción (5) no puede enviarse antes del ciclo 7, ya que necesita el valor de f5
que produce la instrucción (3). La instrucción (6) no puede lanzarse antes del ciclo 9 dado que necesita
el valor de f6, que se tiene en el ciclo 8, obtenido por la instrucción (4).

Como hemos dicho antes, todas las instrucciones que se retrasan en la secuencia de código lo hacen
por un riesgo RAW, así que no conseguiríamos ninguna mejora añadiendo más unidades de ejecución.
Sin embargo, si las unidades de ejecución fueran un ciclo más rápidas, el programa tardaría 9 ciclos
independientemente de si la emisión es o no ordenada, como muestra la Figura 21. Por lo tanto, para
este programa es mejor reducir el tiempo de ejecución de las unidades funcionales existentes que
añadir nuevas unidades de ejecución.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9
subd f2, f2, f1 IF ID EX ROB WB
addd f4, f2, f3 IF ID EX ROB WB
subd f5, f2, f3 IF ID EX ROB WB
multd f6, f2, f3 IF ID EX ROB WB
subd f2, f2, f5 IF ID EX ROB WB
subd f7, f4, f6 IF ID EX ROB WB

Figura 21. Traza de la ejecución del código del problema 9 usando unidades de ejecución un ciclo más
rápidas.

10. Suponga un procesador superescalar en el que se pueden captar y decodificar hasta dos
instrucciones por ciclo, emitir hasta tres instrucciones por ciclo como máximo, y retirar hasta
dos instrucciones por ciclo. La emisión es desordenada y no alineada y se realiza
directamente a las unidades de ejecución, es decir, que el procesador no dispone de
estaciones de reserva. La ejecución también es desordenada, y para permitir la finalización
ordenada, se dispone de un búfer de reordenamiento (ROB) en el que se introducen las
instrucciones una vez decodificadas y del que se retiran en orden una vez que han finalizado.

a) Indique las dependencias entre las instrucciones, los ciclos en los que se
emiten para su ejecución y cómo evolucionaría en búfer de reordenamiento
hasta que se hayan retirado todas las instrucciones de la siguiente secuencia:

multd f1, f1, f5 ; (1)


addd f2, f2, f5 ; (2)
addd f4, f1, f2 ; (3)
addd f6, f1, f5 ; (4)
multd f5, f2, f2 ; (5)
subd f6, f2, f1 ; (6)

b) Suponiendo una frecuencia de 2 GHz, ¿cuánto tarda en procesarse la


secuencia de instrucciones? ¿Cuál es la velocidad pico del procesador?

NOTA: La suma y la resta consumen 1 ciclo de reloj y la multiplicación tres ciclos. Considere que no
hay limitaciones en la capacidad de los búferes ni en el número de unidades funcionales. Se
supone que f1, f2 y f5 tienen valores previos.

Solución
Ya que el procesador no dispone de estaciones de reserva, la lógica de emisión tiene que esperar a que
los operandos le sean facilitados por la lógica de bypass, por tanto, los riesgos RAW entre las
instrucciones (3), (4) y (6) y la instrucción (1), a causa de f1, afectarán al orden de emisión de las
instrucciones.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9
multd f1, f1, f5 IF ID EX ROB WB
addd f2, f2, f5 IF ID EX ROB WB
addd f4, f1, f2 IF ID EX ROB WB
addd f6, f1, f5 IF ID EX ROB WB
multd f5, f2, f2 IF ID EX ROB WB
subd f6, f2, f1 IF ID EX ROB WB

Figura 22. Traza de la ejecución del código del problema 10.

Teniendo en cuenta estas dependencias, las instrucciones se ejecutarían como se muestra en la Figura
22. En cuanto al búfer de reordenamiento, su evolución se detalla en la Tabla 9:

 En el ciclo 2 se decodifican las instrucciones (1) y (2) y se introducen en el ROB.

 En el ciclo 3 se decodifican las instrucciones (3) y (4) y se introducen en el ROB.

 En el ciclo 4 se decodifican las instrucciones (5) y (6), se introducen en el ROB y se


almacena el resultado de la instrucción (2).

 En el ciclo 6 se almacena el resultado de la instrucción (1) en el ROB.

 En el ciclo 7 se retiran las instrucciones (1) y (2) y se almacenan en el ROB los


resultados de las instrucciones (3), (4) y (6).

 En el ciclo 8 se retiran las instrucciones (3) y (4) y se almacena en el ROB el


resultado de la instrucción (5).

 En el ciclo 9 se retiran las instrucciones (5) y (6).


CICLO # CÓDIGO REGISTRO VALOR VALOR
OPERACIÓN DESTINO VÁLIDO
2 0 multd f1 – 0
1 addd f2 – 0
3 0 multd f1 – 0
1 addd f2 – 0
3 addd f4 – 0
4 addd f6 – 0
4 0 multd f1 – 0
1 addd f2 f2 + f5 1
3 addd f4 – 0
4 addd f6 – 0
5 multd f5 – 0
6 subd f6 – 0
6 0 multd f1 f1 × f5 1
1 addd f2 f2 + f5 1
3 addd f4 – 0
4 addd f6 – 0
5 multd f5 – 0
6 subd f6 – 0
7 3 addd f4 f1 + f2 1
4 addd f6 f1 + f5 1
5 multd f5 – 0
6 subd f6 f2 – f1 1
8 5 multd f5 f2 × f2 1
6 subd f6 f2 – f1 1

Tabla 9. Evolución del ROB en el problema 10.

Si el procesador funciona a 2 GHz, el tiempo de procesamiento sería

número de ciclos 9
T   4.5 ns
F 2  109

Para la calcular la velocidad pico, como se pueden retirar hasta dos instrucciones por ciclo, y la
frecuencia del procesador es de 2 GHz, suponiendo que no hubiera atascos en el cauce se podría
alcanzar:

Vpico  tasa de retirada F  2  2  109  4  109 instrucciones/s

11. Suponga un procesador superescalar en que se captan cuatro instrucciones por ciclo, se
decodifican tres instrucciones por ciclo, se emiten tres instrucciones por ciclo como máximo,
y se retiran hasta tres instrucciones por ciclo. La emisión y la ejecución son desordenadas, y
las instrucciones, una vez decodificadas, se introducen en un búfer de reordenamiento
(ROB) que permite la finalización ordenada del procesamiento de las instrucciones.
a) Indique las dependencias entre instrucciones y cómo evolucionaría el búfer
de reordenamiento hasta que se hayan retirado todas las instrucciones de la
secuencia:

addd f1, f1 ,f4 ; (1)


multd f3, f1, f2 ; (2)
addd f6, f1, f4 ; (3)
subd f4, f1, f6 ; (4)

b) Suponiendo una frecuencia de 2 GHz, ¿cuánto tarda en procesarse la


secuencia de instrucciones? ¿Cuál es la velocidad pico del procesador?

NOTA: La suma y la resta consumen un ciclo de reloj y la multiplicación cuatro ciclos. Considere que
no hay limitaciones en la capacidad de los búferes, y en el número de unidades funcionales.
Se supone que f1, f2, y f4 tienen valores válidos previos.

Solución
Analizando el código del enunciado se detecta fácilmente que las instrucciones (2) y (3) dependen del
valor de f1 producido por la instrucción (1) y que la instrucción (4) depende del valor de f6 producido
por la instrucción (3). Teniendo en cuenta estas dependencias, las instrucciones se ejecutarían como se
muestra en la Figura 23.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9
addd f1, f1 ,f4 IF ID EX ROB WB
multd f3, f1, f2 IF ID EX ROB WB
addd f6, f1, f4 IF ID EX ROB WB
subd f4, f1, f6 IF ID EX ROB WB

Figura 23. Traza de la ejecución del código del problema 11.

Teniendo en cuenta la traza de ejecución del código, la Tabla 10 muestra el estado del ROB en cada
durante la ejecución del fragmento de código, resaltando en negrita los cambios producidos en cada
ciclo de la ejecución. A continuación se describe la evolución del búfer de reordenamiento a lo largo
de la ejecución:

 En el ciclo 2 se decodifican las instrucciones (1), (2) y (3) y se introducen en el


ROB.

 En el ciclo 3 se decodifica la instrucción (4) y se introducen en el ROB.

 En el ciclo 4 finaliza la instrucción (1) y se escribe su resultado en el ROB.

 En el ciclo 5 se retira la instrucción (1) y finaliza la instrucción (3), escribiendo su


resultado en el ROB.

 En el ciclo 6 finaliza la instrucción (4) y se escribe el resultado en el ROB.

 En el ciclo 8 finaliza la instrucción (3) y se escribe el resultado en el ROB.

 En el ciclo 9 se retiran las instrucciones (2), (3) y (4) del ROB.


CICLO # CÓDIGO REGISTRO VALOR VALOR
OPERACIÓN DESTINO VÁLIDO
2 0 addd f1 – 0
1 multd f3 – 0
2 addd f6 – 0
3 0 addd f1 – 0
1 multd f3 – 0
2 addd f6 – 0
3 subd f4 – 0
4 0 addd f1 f1 + f4 1
1 multd f3 – 0
2 addd f6 – 0
3 subd f4 – 0
5 1 multd f3 – 0
2 addd f6 f1 + f4 1
3 subd f4 – 0
6 1 multd f3 – 0
2 addd f6 f1 + f4 1
3 subd f4 f1 – f6 1
8 1 multd f3 f1 × f2 1
2 addd f6 f1 + f4 1
3 subd f4 f1 – f6 1

Tabla 10. Evolución del ROB en el problema 11.

Si el procesador funciona a 2 GHz, el tiempo de procesamiento sería de:

número de ciclos 9
T   4.5 ns
F 2  109

Para la calcular la velocidad pico, como sólo se pueden retirar tres instrucciones por ciclo, suponiendo
que no hubiera atascos en el cauce:

Vpico  tasa de retirada  F  3  2  10 9  6  10 9 instrucciones/s

12. Suponga un procesador superescalar en el que se captan y decodifican hasta dos


instrucciones por ciclo, se emiten hasta tres instrucciones por ciclo como máximo, y se
retiran hasta dos instrucciones por ciclo. La emisión es desordenada y no alineada y se realiza
directamente a las unidades de ejecución, es decir, que el procesador no dispone de
estaciones de reserva. La ejecución también es desordenada, y para permitir la finalización
ordenada, se dispone de un búfer de reordenamiento (ROB) en el que se introducen las
instrucciones una vez decodificadas y del que se retiran en orden una vez que ha finalizado.

a) Indique las dependencias entre las instrucciones, los ciclos en los que se
emiten para su ejecución y cómo evolucionaría en búfer de reordenamiento
hasta que se hayan retirado todas las instrucciones de la siguiente secuencia
almacenada en la cola de instrucciones captadas:
multd f1, f1, f5 ; (1)
addd f2, f2, f5 ; (2)
divd f4, f1, f2 ; (3)
addd f6, f1, f5 ; (4)
multd f5, f2, f2 ; (5)
subd f6, f2, f1 ; (6)

b) Suponiendo una frecuencia de 2 GHz, ¿cuánto tarda en procesarse la


secuencia de instrucciones? ¿Cuál es la velocidad pico del procesador?

NOTA: La suma y la resta consumen 1 ciclo de reloj, la multiplicación tres ciclos y la división cuatro
ciclos. Considere que sólo hay un multiplicador, un divisor, y dos unidades para
sumar/restar, y que no hay limitaciones en la capacidad de los búferes. Se supone que f1, f2 y
f5 tienen valores previos.

Solución
La Figura 24 muestra una traza de la ejecución del programa de la que puede obtener su tiempo de
ejecución, los ciclos en los que se emite cada instrucción. También ilustra los riesgos RAW
ocasionados entre las instrucciones (3), (4) y (6) y la instrucción (1) ocasionados por el uso del registro
f1.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12
multd f1, f1, f5 IF ID EX ROB WB
addd f2, f2, f5 IF ID EX ROB WB
divd f4, f1, f2 IF ID EX ROB WB
addd f6, f1, f5 IF ID EX ROB WB
multd f5, f2, f2 IF ID EX ROB WB
subd f6, f2, f1 IF ID EX ROB WB

Figura 24. Traza de la ejecución del código del problema 12.

La evolución de búfer de reordenamiento se muestra en la Tabla 11, marcando en negrita los cambios
que se producen en cada ciclo de la ejecución:

 En el ciclo 2 se decodifican las instrucciones (1) y (2) y se introducen en el ROB.

 En el ciclo 3 se decodifican las instrucciones (3) y (4) y se introducen en el ROB.

 En el ciclo 4 se decodifican las instrucciones (5) y (6), se introducen en el ROB y se


escribe el resultado de la instrucción (2).

 En el ciclo 6 se escribe el resultado de la instrucción (1).

 En el ciclo 7 se retiran las instrucciones (1) y (2) y se escribe el resultado de las


instrucciones (4) y (6).

 En el ciclo 8 se escribe el resultado de la instrucción (5).

 En el ciclo 10 se escribe el resultado de la instrucción (3).

 En el ciclo 11 se retiran las instrucciones (3) y (4).

 En el ciclo 12 se retiran las instrucciones (5) y (6).


CICLO # CÓDIGO REGISTRO VALOR VALOR
OPERACIÓN DESTINO VÁLIDO
2 0 multd f1 – 0
1 addd f2 – 0
3 0 multd f1 – 0
1 addd f2 – 0
2 divd f4 – 0
3 addd f6 – 0
4 0 multd f1 – 0
1 addd f2 f2 + f5 1
2 divd f4 – 0
3 addd f6 – 0
4 multd f5 – 0
5 subd f6 – 0
6 0 multd f1 f1 × f5 1
1 addd f2 f2 + f5 1
2 divd f4 – 0
3 addd f6 – 0
4 multd f5 – 0
5 subd f6 – 0
7 2 divd f4 – 0
3 addd f6 f1 + f1 1
4 multd f5 – 0
5 subd f6 f2 – f1 1
8 2 divd f4 – 0
3 addd f6 f1 + f1 1
4 multd f5 f2 × f2 1
5 subd f6 f2 – f1 1
10 2 divd f4 f1 / f2 1
3 addd f6 f1 + f1 1
4 multd f5 f2 × f2 1
5 subd f6 f2 – f1 1
11 4 multd f5 f2 × f2 1
5 subd f6 f2 – f1 1

Tabla 11. Evolución del ROB en el problema 12.

En cuanto al tiempo de ejecución de la secuencia, suponiendo una frecuencia del procesador de


2 GHz, el tiempo de ejecución de este fragmento de código sería:

número de ciclos 12
T   6 ns
F 2  109

Para la calcular la velocidad pico, como se pueden retirar hasta dos instrucciones por ciclo, y la
frecuencia del procesador es de 2 GHz, suponiendo que no hubiera atascos en el cauce se podría
alcanzar:
Vpico  tasa de retirada F  2  2  109  4  109 instrucciones/s

13. Suponga un procesador superescalar en que se captan y decodifican dos instrucciones por
ciclo, se emiten tres instrucciones por ciclo como máximo (con emisión desordenada y no
alineada, sin estaciones de reserva), y se retiran hasta dos instrucciones por ciclo como
máximo. La emisión y la ejecución son desordenadas, y las instrucciones, una vez
decodificadas, se introducen en un búfer de reordenamiento (ROB) que permite la
finalización ordenada del procesamiento de las instrucciones.

a) Indique las dependencias entre instrucciones, los ciclos en los que se emiten
las instrucciones para su ejecución y cómo evolucionaría el búfer de
reordenamiento hasta que se hayan retirado todas las instrucciones de la
siguiente secuencia de instrucciones almacenadas en la cola de instrucciones
captadas:

multd f1, f1, f2 ; (1)


addd f3, f3, f2 ; (2)
multd f4, f1, f3 ; (3)
addd f5, f4, f2 ; (4)
addd f3, f1, f3 ; (5)
subd f5, f2, f1 ; (6)

b) Suponiendo una frecuencia de 3.0 GHz, ¿cuánto tarda en procesarse la


secuencia de instrucciones? ¿Cuál es la velocidad pico del procesador?

NOTA: La suma y la resta consumen dos ciclos de reloj y la multiplicación cuatro ciclos. Considere
que no hay limitaciones en la capacidad de los búferes, pero sólo tiene un multiplicador y dos
sumadores/restadores. Se supone que f1, f2, y f3 tienen valores válidos previos.

Solución
Ya que el procesador no dispone de estaciones de reserva, la lógica de emisión tiene que esperar a que
los operandos le sean facilitados por la lógica de bypass, por tanto, las dependencias RAW afectarán al
orden de emisión de las instrucciones. Por otro lado, como se pueden decodificar hasta dos
instrucciones por ciclo y emitir hasta tres, suponemos que cada una de estas tareas se realizarán en
etapas diferentes del cauce. Es decir, que la etapas serán IF para captar instrucciones, ID para
decodificarlas, EX para ejecutarlas, ROB para escribir los resultados en el ROB y WB para retirar las
instrucciones del cauce. La Figura 25 muestra una traza de la ejecución del fragmento de código del
enunciado en la que se muestra el número de ciclos que tarda en ejecutarse, el momento en que se
emite cada instrucción y los siguientes riesgos RAW entre instrucciones:

 Las instrucciones (3), (5) y (6) dependen de la instrucción (1) por f1.

 La instrucción (4) depende de la instrucción (3) por f4.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
multd f1, f1, f2 IF ID EX ROB WB
addd f3, f3, f2 IF ID EX ROB WB
multd f4, f1, f3 IF ID EX ROB WB
addd f5, f4, f2 IF ID EX ROB WB
addd f3, f1, f3 IF ID EX ROB WB
subd f5, f2, f1 IF ID EX ROB WB

Figura 25. Traza de la ejecución del código del problema 13.


CICLO # CÓDIGO REGISTRO VALOR VALOR
OPERACIÓN DESTINO VÁLIDO
2 0 multd f1 – 0
1 addd f3 – 0
3 0 multd f1 – 0
1 addd f3 – 0
2 multd f4 – 0
3 addd f5 – 0
4 0 multd f1 – 0
1 addd f3 – 0
2 multd f4 – 0
3 addd f5 – 0
4 addd f3 – 0
5 subd f5 – 0
5 0 multd f1 – 0
1 addd f3 f3 + f2 1
2 multd f4 – 0
3 addd f5 – 0
4 addd f3 – 0
5 subd f5 – 0
7 0 multd f1 f1 × f2 1
1 addd f3 f3 + f2 1
2 multd f4 – 0
3 addd f5 – 0
4 addd f3 – 0
5 subd f5 – 0
8 2 multd f4 – 0
3 addd f5 – 0
4 addd f3 – 0
5 subd f5 – 0
9 2 multd f4 – 0
3 addd f5 – 0
4 addd f3 f1 + f3 1
5 subd f5 f2 – f1 1
11 2 multd f4 f1 × f3 1
3 addd f5 – 0
4 addd f3 f1 + f3 1
5 subd f5 f2 – f1 1
12 3 addd f5 – 0
4 addd f3 f1 + f3 1
5 subd f5 f2 – f1 1

Tabla 12. Evolución del ROB en el problema 13.


CICLO # CÓDIGO REGISTRO VALOR VALOR
OPERACIÓN DESTINO VÁLIDO
13 3 addd f5 f4 + f2 1
4 addd f3 f1 + f3 1
5 subd f5 f2 – f1 1
14 5 subd f5 f2 – f1 1

Tabla 12. Evolución del ROB en el problema 13.

En cuanto a la evolución del ROB, la Tabla 12 muestra los cambios que se producen cada ciclo
resaltados en negrita:

 En el ciclo 2 se decodifican las instrucciones (1) y (2) y se introducen en el ROB.

 En el ciclo 3 se decodifican las instrucciones (3) y (4) y se introducen en el ROB.

 En el ciclo 4 se decodifican las instrucciones (5) y (6) y se introducen en el ROB.

 En el ciclo 5 se almacena el resultado de la instrucción (2) en el ROB.

 En el ciclo 7 se almacena el resultado de la instrucción (1) en el ROB.

 En el ciclo 8 se retiran las instrucciones (1) y (2) y se escriben sus resultados en los
registros de la arquitectura.

 En el ciclo 9 se almacenan los resultados de las instrucciones (5) y (6) en el ROB.

 En el ciclo 11 se almacena el resultado de la instrucción (3) en el ROB.

 En el ciclo 12 se retira la instrucción (3).

 En el ciclo 13 se almacena el resultado de la instrucción (4) en el ROB.

 En el ciclo 14 se retiran las instrucciones (4) y (5).

 En el ciclo 15 se retira la instrucción (6).

Si el procesador funciona a 3 GHz, el tiempo de procesamiento será de:

número de ciclos 15
T   5 ns
F 3  109

Para la calcular la velocidad pico, como sólo se pueden retirar hasta dos instrucciones por ciclo,
tenemos:

Vpico  tasa de retirada  F  2  3  109  6  109 instrucciones/s

14. Considere que el fragmento de código siguiente:

lf f3, 0(r1) ; (1)


lf f2, 8(r1) ; (2)
addf f4, f2, f3 ; (3)
sf 16(r1), f4 ; (4)
lf f5, 16(r2) ; (5)
addf f6, f5, f2 ; (6)
multf f6, f6, f4 ; (7)
sf 8(r2), f6 ; (8)
addi r3, r2, #32 ; (9)
lf f7, 0(r3) ; (10)
multf f8, f7, f3 ; (11)
sf 0(r3), f8 ; (12)

se ejecuta en un procesador superescalar que es capaz de captar (IF), decodificar/emitir


(ID/ISS) y finalizar (WB) 4 instrucciones/ciclo. El procesador utiliza un ROB para realizar el
renombramiento y la finalización ordenada y dispone de tres estaciones de reserva de 3 líneas
cada una (una para las instrucciones de acceso a memoria, otra para las operaciones de coma
flotante, y otra para las operaciones con enteros). Las estaciones de reserva pueden enviar
una instrucción por ciclo a cada una de las unidades funcionales conectadas a ellas (la
velocidad de envío depende, por tanto, del número de unidades que estén conectadas a cada
estación). El procesador sólo permite que las instrucciones load no especulativas adelanten a
las instrucciones store pendientes. Es decir, que no permite accesos especulativos a memoria.

a) Indique el número de ciclos que tardaría en ejecutarse el conjunto de


instrucciones anterior suponiendo envío desordenado desde las estaciones
de reserva a las unidades funcionales.

b) ¿Y si el envío fuera ordenado desde las estaciones de reserva para


operaciones con enteros y operaciones con datos en coma flotante, pero
desordenado para la estación de acceso a memoria?

NOTA: Considere que, conectadas a la estación de reserva para el acceso a memoria, tiene una
unidad funcional de carga con un retardo de dos ciclos y una de almacenamiento con retardo
de un ciclo; conectadas a la estación de reserva para enteros tiene dos ALU con retardo de
un ciclo; y, conectadas a la estación de reserva para coma flotante tiene una unidad de
multiplicación con tres ciclos de retardo y dos unidades de suma con dos ciclos de retardo.
No hay límite en el número de líneas de la cola de instrucciones y del ROB.

Solución
Suponiendo un envío desordenado para todas las estaciones de reserva, el código tardaría 25 ciclos en
ejecutarse, tal y como se muestra en la Figura 26. A continuación se describen las causas de los
retrasos de las instrucciones de la figura:

 En el enunciado se especifica que las cargas podrán adelantar a los


almacenamientos siempre que no sean especulativas, es decir cuando se sepa que se
va a acceder a direcciones de memoria diferentes. Las instrucciones (5) y (4),
acceden a memoria con el mismo desplazamiento y dos registros índice diferentes
(r2 y r1), con lo que si r2 tuviera un valor diferente al de r1, la instrucción (5) podría
adelantar a la (4). Como no sabemos los valores de estos registros, se ha supuesto el
peor caso, que es la coincidencia de r1 y r2, lo que obliga a que la instrucción (5)
tenga que esperar a la (4). Por otro lado, las instrucciones (10) y (8) acceden a
posiciones de memoria diferentes, ya que la instrucción (8) almacena en la posición
8 + r2 y la instrucción (10) lee de la posición 0 + r3 = 32 + r2. Como suponemos
que las direcciones efectivas se calculan en el primer ciclo de la etapa de ejecución
de las instrucciones de acceso a memoria, aunque las direcciones finales sean
diferentes, este hecho no se puede comprobar por la lógica de envío de la estación
de reserva, lo que obliga a enviar primero el almacenamiento y luego la carga.

 Como las estaciones de reserva tienen sólo tres entradas cada una, cuando alguna se
llena no permite que se puedan emitir más instrucciones hacia ella hasta que envíe
alguna instrucción y deje algún hueco. Este fenómeno se puede apreciar en la
instrucción (8), que no puede entrar hasta que se envía la instrucción (2) y se
quedan en la estación de reserva las instrucciones (4) y (5). También se crea un
cuello de botella en la estación de reserva de acceso a memoria con la instrucción
(10), que no puede emitirse hasta que se envía la instrucción (4), y que retrasa la
emisión de la instrucción (11), ya que la emisión es ordenada. Por último, la
instrucción (12) se bloqueará en la cola de instrucciones hasta que se envíe a
ejecutar la instrucción (5).

 En cuanto a las colisiones en las unidades de ejecución, la instrucción (2) debe


esperar a que la (1) libere la unidad de carga.

 Por último, se producen riesgos RAW entre las instrucciones (2) - (3) por f2,
(3) - (4) por f4, (5) - (6) por f5, (6) - (7) - (8) por f6, (10) - (11) por f7, y (11) - (12)
por f8.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
lf f3, 0(r1) IF ID EX ROB WB
lf f2, 8(r1) IF ID EX ROB WB
addf f4, f2, f3 IF ID EX ROB WB
sf 16(r1), f4 IF ID EX ROB WB
lf f5, 16(r2) IF ID EX ROB WB
addf f6, f5, f2 IF ID EX ROB WB
multf f6, f6, f4 IF ID EX ROB WB
sf 8(r2), f6 IF ID EX ROB WB
addi r3, r2, #32 IF ID EX ROB WB
lf f7, 0(r3) IF ID EX ROB WB
multf f8, f7, f3 IF ID EX ROB WB
sf 0(r3), f8 IF ID EX ROB WB

Figura 26. Traza de la ejecución del código del problema 14.

En el caso de que el envío fuese desordenado sólo para la estación de reserva de acceso a memoria, el
resultado sería exactamente el mismo, ya que debido a los riesgos del programa, todas las instrucciones
se han enviado ordenadamente.

15. En un programa, una instrucción de salto condicional (a una dirección de salto anterior) tiene
el siguiente comportamiento en una ejecución de dicho programa:

SSNNNSSNSNSNSSSSSN

donde S indica que se produce el salto y N que no. Indique la penalización efectiva que se
introduce si se utiliza:

a) Predicción fija (siempre se considera que se no se va a producir el salto).

b) Predicción estática (si el desplazamiento es negativo se toma y si es positivo


no).

c) Predicción dinámica con dos bits, inicialmente en el estado (11).

d) Predicción dinámica con tres bits, inicialmente en el estado (111).

NOTA: La penalización por saltos incorrectamente predichos es de 5 ciclos y para los saltos
correctamente predichos es 0 ciclos.

Solución
En el caso de usar predicción fija, se produciría un fallo del predictor cada vez que se tome el salto, tal
y como muestra la Tabla 13. Por tanto, la penalización total sería de:
Pfijo  Ffijo  P  11 5  55 ciclos

PREDICCIÓN N N N N N N N N N N N N N N N N N N
EJECUCIÓN S S N N N S S N S N S N S S S S S N
PENALIZACIÓN P P P P P P P P P P P

Tabla 13. Comportamiento del predictor fijo en el problema 15.

Si se usa el predictor estático, como la dirección de destino del salto es anterior, se producirá un fallo
en la predicción cuando no se produzca el salto, tal y como muestra la Tabla 14. Por tanto, la
penalización total sería de:

Pestático  N estático  P  7  5  35 ciclos

PREDICCIÓN S S S S S S S S S S S S S S S S S S
EJECUCIÓN S S N N N S S N S N S N S S S S S N
PENALIZACIÓN P P P P P P P

Tabla 14. Comportamiento del predictor estático en el problema 15.

En cuanto al predictor dinámico con dos bits de historia, la Tabla 15 muestra el estado del predictor
antes de ejecutar el salto, la predicción que realiza el predictor, el comportamiento del salto y si se
produce o no penalización. Teniendo en cuanta los fallos que se producen, la penalización total sería
de:

P2 bits  F2 bits  P  11 5  55 ciclos

ESTADO 11 11 11 10 01 00 01 10 01 10 01 10 01 10 11 11 11 11
PREDICCIÓN S S S S N N N S N S N S N S S S S S
EJECUCIÓN S S N N N S S N S N S N S S S S S N
PENALIZACIÓN P P P P P P P P P P P

Tabla 15. Comportamiento del predictor dinámico con dos bits de historia en el problema 15.

Por último, en la Tabla 16 se indican los bits de historia que existen antes de que se ejecute la
instrucción, la predicción que determinan esos bits, y lo que finalmente ocurre (según se indica en la
secuencia objeto del problema). La última fila indica si ha habido penalización (no coinciden la
predicción y lo que ocurre al final). Teniendo en canta esta información, tenemos que la penalización
total es de:

P3 bits  F3 bits  P  10  5  50 ciclos

ESTADO 111 111 111 011 001 000 100 110 011 101 010 101 010 101 110 111 111 111
PREDICCIÓN S S S S N N N S S S N S N S S S S S
EJECUCIÓN S S N N N S S N S N S N S S S S S N
PENALIZACIÓN P P P P P P P P P P

Tabla 16. Comportamiento del predictor dinámico con tres bits de historia en el problema 15.

Como se puede ver, en la secuencia de ejecuciones de la instrucción de salto considerada en este


problema, el mejor esquema de predicción es la predicción estática que aquí se utiliza. El esquema de
predicción de salto dinámico con dos bits es igual de bueno (o malo) que la predicción fija.
Así, se puede indicar que la eficacia de un esquema de salto depende del perfil de saltos a que de lugar
la correspondiente instrucción de salto condicional. En la práctica, los esquemas de predicción
dinámica suelen funcionar mejor que los de predicción estática porque las instrucciones de salto suelen
repetir el comportamiento de su ejecución previa. En ese sentido, la secuencia utilizada en este
problema es bastante atípica.

16. Un procesador utiliza un esquema de predicción dinámica de saltos de dos niveles similar al
del Pentium III: tres bits de historia se utilizan para indicar si en las tres últimas ejecuciones
de la instrucción hubo o no hubo salto, y esos tres bits de historia sirven de puntero a 8
contadores de dos bits, cada uno de los cuales se utiliza para realizar la predicción
correspondiente según su estado como en un esquema de predicción de dos bits. En la
primera ejecución, los tres bits que apuntan a los contadores de dos bits están a 000 y los bits
de los contadores de dos bits se inicializan a 00 (predice no saltar) si la instrucción de salto es
hacia adelante y a 11 (predice saltar) si el salto es hacia atrás. Si la predicción es correcta no
hay penalización, pero si es incorrecta, la penalización es de cuatro ciclos.

¿Cuál es la penalización para la secuencia N1 S2 N3 N1 N2 S3 N1 S2 N3 S1 S2 N3, teniendo en


cuenta que S significa que la instrucción de salto dará lugar a un salto, N que no dará lugar a
un salto, y cada subíndice (1, 2, 3) hace referencia a una instrucción de salto distinta?

NOTA: La instrucción 1 salta hacia atrás y las instrucciones 2 y 3 saltan hacia adelante.

Solución
Como para cada instrucción de salto se utiliza un contador y unos bits de estado independientes del
resto de los saltos, consideraremos cada una de las instrucciones de salto por separado. Así, para la
primera instrucción tenemos el comportamiento N1 N1 N1 S1, para la segunda S2 N2 S2 S2, y para la
tercera N3 S3 N3 N3.

SALTO 1 ÚLTIMAS ITERACIONES 000 000 000 000


ESTADO DEL CONTADOR 11 10 01 00
PREDICCIÓN S S N N
EJECUCIÓN N N N S
PENALIZACIÓN P P P
SALTO 2 ÚLTIMAS ITERACIONES 000 100 010 101
ESTADO DEL CONTADOR 00 00 00 00
PREDICCIÓN N N N N
EJECUCIÓN S N S S
PENALIZACIÓN P P P
SALTO 3 ÚLTIMAS ITERACIONES 000 000 100 010
ESTADO DEL CONTADOR 00 00 00 00
PREDICCIÓN N N N N
EJECUCIÓN N S N N
PENALIZACIÓN P

Tabla 17. Comportamiento del predictor dinámico en el problema 16.

La Tabla 17 muestra el comportamiento del predictor, así como la evolución de los bits de historia que
se usan para cada salto a lo largo de la ejecución del código. Con ayuda de esta tabla tenemos que en la
ejecución del primer salto se producen tres fallos, en la del segundo otros tres, y en la del tercero una
más, por lo que la penalización total obtenida es de:

Ptotal  F1  F2  F3   P  3  3  1  4  28 ciclos

17. Un procesador utiliza un esquema de predicción dinámica de saltos de dos niveles similar al
del Pentium III: tres bits de historia se utilizan para indicar si en las tres últimas ejecuciones
de la instrucción hubo o no hubo salto, y esos tres bits de historia sirven de puntero a 8
contadores de dos bits, cada uno de los cuales se utiliza para realizar la predicción
correspondiente, según su estado, como en un esquema de predicción dinámica de dos bits.
En la primera ejecución, los tres bits que apuntan a los contadores de dos bits están a 000 y
los bits de los contadores de dos bits se inicializan a 00 (predice no saltar) si la instrucción de
salto es hacia adelante, y a 11 (predice saltar) si el salto es hacia atrás. Si la predicción es
correcta no hay ciclos de penalización y si es incorrecta hay cuatro ciclos.

¿Cual es la penalización para el bucle que se indica a continuación, para 1 < d < 8?

for (i = 1 ; i <= 10 ; i ++)


{
b[i] = a[i] + d;
d = d + 1;
if (d > 8) then goto etiqueta;
}

etiqueta:

Compárelo con un esquema de predicción estática que predice saltar si el salto es hacia atrás
y no saltar si el salto es hacia adelante.

Solución
Una vez traducido el código a ensamblador tendría un aspecto similar a este:

bucle: …

saltar a etiqueta ; S1

saltar a bucle ; S2

etiqueta: …

En este código hay dos saltos, que a partir de ahora notaremos como S1 y S2 (si saltan) o N1 y N2 (si
no saltan). Para valores de d tales que 1 < d < 8 el patrón de saltos del código es:

N 1S 2 8d S1

es decir, que el salto del bucle siempre se va a tomar y el salto hacia delante no se tomará nunca
excepto la última vez, en la que se saldrá del bucle y continuará hacia delante. Como tenemos un
predictor dinámico de dos niveles, para cada salto habrá un conjunto de 8 contadores de dos bits, que
se inicializarán a 00 para el salto hacia delante y a 11 para el salto hacia atrás, y se seleccionará uno de
estos 8 contadores para hacer la predicción en función del los 3 bits de historia (según el
comportamiento del salto en las últimas tres iteraciones).
SALTO ITERACIONES 1 2 3 4 ÚLTIMA

SALTO 1 ÚLTIMAS ITERACIONES 000 000 000 000 000


ESTADO DEL CONTADOR 00 00 00 00 00
PREDICCIÓN N N N N N
EJECUCIÓN N N N N S
PENALIZACIÓN … P
SALTO 2 ÚLTIMAS ITERACIONES 000 100 110 111 111
ESTADO DEL CONTADOR 11 11 11 11 11
PREDICCIÓN S S S S –
EJECUCIÓN S S S S –
PENALIZACIÓN

Tabla 18. Comportamiento del predictor dinámico en el problema 17.

Según la Tabla 18, en la última iteración el salto S2 no se llega a ejecutar, ya que se sale del bucle por el
salto S1. Los predictores aciertan en el comportamiento del salto hacia atrás, que se toma todas las
veces, y en todas las ejecuciones del salto hacia adelante menos en la última, por lo que sólo se
equivocan una vez. Por tanto, la penalización total es de:

Pdinámico  F1  F2   P  1  0  4  4 ciclos

En el caso de que el mecanismo de predicción fuera estático, se usaría el mismo predictor para todos
los saltos. Este predictor, según el enunciado del problema, realizaría la siguiente predicción:

N 1S 2 8d N 1

Teniendo en cuenta el comportamiento del fragmento de código, el predictor estático sólo se


equivocaría en el último salto, con lo que volvemos a obtener una penalización de

Pestático  F  P  1  4  4 ciclos

18. Considere el bucle:

for (i = 1; i < = 10 ; i ++)


{
b[i] = a[i] * c;
c = c + 1;
if (c > 10) then goto etiqueta;
}

etiqueta:

Indique cuál es la penalización efectiva debida a los saltos, en función del valor inicial de c
(número entero), considerando que el procesador utiliza:

a) Predicción fija (siempre se considera que se va a producir el salto).

b) Predicción estática (si el desplazamiento es negativo se toma y si es positivo


no).

c) Predicción dinámica con un bit (1 = Saltar; 0 = No Saltar; Inicialmente está


a 1).
d) ¿Cuál de los tres esquemas anteriores es más eficaz por término medio si
hay una probabilidad del 25% de que c sea menor o igual a 0, una del 30%
de que sea mayor o igual a 10; y una del 45% de que sea cualquier número
entre 1 y 9, siendo todos equiprobables?

NOTA: La penalización por saltos incorrectamente predichos es de 4 ciclos y para los saltos
correctamente predichos es 0 ciclos.

Solución
Al igual que en el ejercicio anterior, al traducir el fragmento de código a ensamblador se codificarán
dos saltos: S1, que estará dentro del bucle y saltará hacia etiqueta, y S2, que será el salto al final del bucle
para iniciar otra iteración. Dependiendo del valor inicial de c se pueden distinguir tres
comportamientos diferentes de los saltos:

1. c ≤ 0: El salto S1 no salta nunca y el salto S2 salta 9 veces (el bucle realiza 10


iteraciones, el máximo de iteraciones del bucle):

N 1S 2 9 N 1 N 2

2. 1 ≤ c < 10:

 Si c = 9: N 1S 2 S1

 Si c = 8: N 1S 2 2 S1

 …

 Si c = 1: N 1S 2 9 S1

Es decir:

N 1S 2 10 c S1

3. c ≥ 10:

S1

ya que no se realizaría ninguna iteración completa, al verificarse la condición de


salto de la instrucción condicional que hay dentro del bucle.

Una vez obtenidos los comportamientos de los saltos correspondientes a los distintos valores posibles
de c, se pasa a considerar cada uno de los esquemas de predicción indicados. Para el caso de un
predictor fijo que esté diseñado para predecir que siempre se va a tomar el salto tendríamos las
siguientes penalizaciones en función del valor de c:

1. c ≤ 0: Como el comportamiento de la secuencia de saltos es N 1S 2 9 N 1 N 2 y la


predicción es S1S 2 10 , tendríamos un fallo por cada salto que no se tome, es decir:

Pfijo1  Ffijo1  P  9  1  1 4  44 ciclos

2. 1 ≤ c < 10: En este caso, el comportamiento es N 1S 2 10 c S1 , la predicción sigue -


siendo saltar siempre, por lo que tendríamos una penalización de:
Pfijo2  Ffijo2  P  10  c  4 ciclos

3. c ≥ 10: En este caso, como el comportamiento de la secuencia es S1 y la predicción


será siempre saltar, no se producirá ningún fallo, por lo que:

Pfijo3  Ffijo3  P  0  4  0 ciclos

En el segundo apartado del problema se nos pide que estimemos la penalización en el caso de usar un
predictor estático que suponga que los saltos hacia atrás se tomarán siempre y los saltos hacia adelante
no se tomarán nunca. Dependiendo del valor de c tendremos:

1. c ≤ 0: El comportamiento de los saltos sigue siendo N 1S 2 9 N 1 N 2 , pero en este


caso la predicción es N 1S 2 10 . Por tanto, tendemos un fallo en la última ejecución
del segundo salto. La penalización será de:

Pestático1  Festático1  P  1 4  4 ciclos

2. 1 ≤ c < 10: En este caso, el comportamiento es N 1S 2 10 c S1 , por lo que se


cometería un fallo cuando el salto S1 salte hacia adelante:

Pestático2  Festático2  P  1 4  4 ciclos

3. c ≥ 10: En este caso, como el comportamiento de la secuencia es S1 y el predictor


asume que los saltos hacia adelante no se toman, se cometerá un único fallo, por lo
que la penalización será:

Pestático3  Festático3  P  1 4  4 ciclos

Por consiguiente, para cualquier valor de c, este esquema de predicción siempre da lugar a 4 ciclos de
penalización.

El último esquema de predicción que se propone en este ejercicio es un predictor dinámico con un bit
de historia. En este caso, al tratarse de un esquema dinámico, habrá un predictor para cada salto, cuyo
bit de historia estará inicializado a 1, e irá cambiando a 1 ó 0 en función de la última ejecución del salto
(1 si saltó y 0 si no lo hizo). En función del valor de c tendremos:

1. c ≤ 0: El comportamiento N 1S 2 9 N 1 N 2 , se debe separar para cada salto, ya que


cada salto tendrá un bit de historia independiente.

 Para el primer salto tendremos el comportamiento N 1 10 y la predicción


S1 N 1 9 , ya que como los bits de historia están inicializados a 1, la primera
vez se predecirá saltar y se fallará la predicción. El resto de las
predicciones se realizarán en función de la última ejecución del salto, y
como nunca salta, se predecirán todas correctamente.

 Para el segundo salto tendremos el comportamiento S 2 9 N 2 y la


predicción S 2 10 , ya que el bit de historia comenzará inicializado a cero y
el salto se tomará todas las veces menos la última.

Por tanto, la penalización total será de:

Pdinámico1  F1  F2  P  1  1 4  8 ciclos


2. 1 ≤ c < 10:

 Para el primer salto tendremos el comportamiento N 1 10 c S1 y la


predicción S1 N 1 10 c . Por tanto, se cometerán dos fallos, en el primer y
en el último salto de la secuencia.

 Para el segundo salto tendremos el comportamiento S 2 10 c , que coincide


con la predicción, por lo que no se cometerá ningún fallo para este salto.

Por tanto, la penalización total será de:

Pdinámico2  F1  F2  P  2  0 4  8 ciclos

3. c ≥ 10: Como el comportamiento de la secuencia es S1 , el predictor del segundo


salto no se llega a usar, y como el predictor del primero está inicizalizado a 1,
acertará la predicción, por lo que no se producirá ningún fallo. Por tanto:

Pdinámico3  0  0 P  0 ciclos

Una vez que hemos determinado la penalización de la secuencia para cada tipo de predictor, podemos
pasar a resolver la última cuestión del problema dada la distribución de probabilidad de la variable c
que se da en el enunciado. Para el caso del predictor fijo, y teniendo en cuenta que todos los valores
de c entre 1 y 9 son equiprobables, tenemos:

 9 



c 1
10  c  4 

Pfijo  0.25  Pfijo1  0.45  Pfijo 2  0.30  Pfijo 3  0.25  44  0.45     0.30  0  20 ciclos
 9 
 
 

Para el predictor estático tenemos:

Pestático  0.25  Pestático1  0.45  Pestático2  0.30  Pestático3  0.25  4  0.45  4  0.30  4  4 ciclos

Y para el predictor dinámico:

Pdinámico  0.25  Pdinámico1  0.45  Pdinámico2  0.30  Pdinámico3  0.25  8  0.45  8  0.30  0  5.6 ciclos

Como se puede ver, para este bucle, y para la distribución de probabilidad de los valores de c, el
esquema de predicción más eficiente corresponde a la predicción estática. No obstante, como se ha
visto, esta situación depende de las probabilidades de los distintos valores de c. Si, por ejemplo, la
probabilidad de que c esté entre 1 y 9 fuera de 0.15, la penalización para la predicción dinámica con 1
bit de historia sería de 3.2 ciclos, mientras que la predicción estática seguiría presentando una
penalización de 4 ciclos.

19. En la secuencia de instrucciones DLX siguientes:

addi r1, r0, #4 ; (1)


add r4, r0, r1 ; (2)
lw r2, dato ; (3)
add r5, r2, r0 ; (4)
inicio: subi r3, r1, r2 ; (5)
beqz r3, final ; (6)
addf f3, f2, f1 ; (7)
beqz r5, final ; (8)
addf f3, f2, f1 ; (9)
addi r2, r2, #1 ; (10)
subi r5, r5, #1 ; (11)
subi r4, r4, #1 ; (12)
bnez r4, inicio ; (13)
final:

a) Indique cuál es la penalización efectiva debida a los saltos, en función del


valor inicial de dato (número entero mayor o igual que cero), considerando
que el procesador utiliza predicción dinámica con dos bits.

b) ¿Cuál es la penalización media si la probabilidad de que dato sea menor que


5 es un 80%?

NOTA: La penalización por saltos incorrectamente predichos es de 4 ciclos y para los saltos
correctamente predichos es 0 ciclos. Para hacer la predicción en la primera ejecución de la
instrucción de salto se utiliza un esquema de predicción estática (salta si el salto es hacia atrás
y no salta si el salto es hacia adelante) y el estado inicial es 00 si se ha predicho no saltar y 11
si se ha predicho saltar.

Solución
En la secuencia de instrucciones del problema aparecen tres saltos, que a partir de ahora notaremos
coma S1, S2 y S3 como se muestra a continuación:

addi r1, r0, #4


add r4, r0, r1
lw r2, dato
add r5, r2, r0
inicio: subi r3, r1, r2
beqz r3, final ; (S1)
addf f3, f2, f1
beqz r5, final ; (S2)
addf f3, f2, f1
addi r2, r2, #1)
subi r5, r5, #1)
subi r4, r4, #1
bnez r4, inicio ; (S3)
final:

Tras analizar el código podemos descubrir que:

 El salto S1 controla el contador ascendente r2, que se inicializa con el valor dato y
que provoca la salida del bucle cuando r2 alcanza el valor 4 (siempre que dato haya
sido inicializado a un valor menor o igual que 4).

 El salto S2 controla el contador descendente r5, que se inicializa con el valor dato y
que provoca la salida del bucle cuando r5 alcanza el valor 0.

 El salto S3 controla el contador descendente r4, que se inicializa con el valor


inmediato 4 y que permite la iteración del bucle un máximo de 4 veces, ya que deja
de saltar hacia inicio cuando r4 vale 0.
DATO 0 1 2 3 4 >4

SALTO 1 N N N N N S N S S N N N N
SALTO 2 S N S N N – N – – N N N N
SALTO 3 – S – S S – S – – S S S N

Tabla 19. Comportamiento de los saltos del problema 19.

Dependiendo del valor de dato, los saltos se comportarán según indica la Tabla 19, lo que se puede
resumir en los siguientes tres casos:

1. Si dato < 2:

 S1: N dato + 1.

 S2: N dato S.

 S3: S dato.

2. Si 2 ≤ dato ≤ 4:

 S1: N 4 – dato S.

 S2: N 4 – dato.

 S3: S 4 – dato.

3. Si dato > 4:

 S1: N 4.

 S2: N 4.

 S3:. S 3 N

Una vez obtenidos estos casos, podemos pasar a estudiar el comportamiento del predictor:

1. Si dato < 2, el predictor estático acertará la primera vez para cada uno de los tres
saltos, inicializando los bits de estado de S1 a 00, de S2 a 00 y de S3 a 11. Como
después de esta inicialización todos los saltos repiten su comportamiento hasta el
final excepto S2, que es el que provoca la salida del bucle, todos los saltos serán bien
predichos a excepción del último salto de S2, con lo que la penalización total de de
1 fallo, es decir, 4 ciclos.

2. Si 2 ≤ dato ≤ 4, el predictor estático acertará la primera vez para cada uno de los
tres saltos, como pasaba en el caso anterior. Como después de esta inicialización
todos los saltos repiten su comportamiento hasta el final excepto S1, que es el que
provoca la salida del bucle, todos los saltos serán bien predichos a excepción del
último salto de S1, con lo que la penalización total de de 1 fallo, es decir, 4 ciclos.

3. Si dato > 4, el predictor estático también acertará la primera vez para cada uno de
los tres saltos. Como después de esta inicialización todos los saltos repiten su
comportamiento hasta el final excepto S3, que es el que provoca la salida del bucle,
todos los saltos serán bien predichos a excepción del último salto de S3, con lo que
la penalización total de de 1 fallo, es decir, 4 ciclos.

Como conclusión podemos decir que independientemente del valor de la variable dato, la secuencia de
instrucciones tiene una penalización de 4 ciclos debida a los saltos.
20. Disponemos del siguiente código DLX:

lw r9, n ; (1)
add r10, r0, r0 ; (2)
inicio: lw r1, a(r10) ; (3)
sgt r2, r1, r0 ; (4)
bnez r2, mayor ; (5)
sub r1, r0, r1 ; (6)
beqz r2, fin ; (7)
mayor: add r1, r1, r1 ; (8)
fin: sw r1, a(r10) ; (9)
addi r10, r10, #1 ; (10)
seq r3, r9, r10 ; (11)
bnez r3, inicio ; (12)
trap #0 ; (13)

a) Suponiendo que el procesador que ejecutará este código tiene un predictor


estático que predice como tomados los saltos hacia atrás y como no
tomados los saltos hacia delante, y que la penalización en caso de errar la
predicción es de 5 ciclos, ¿qué penalización media se obtendrá si sólo el
10% de los elementos del vector a son positivos?

b) Se han añadido a este procesador nuevas instrucciones de salto condicional


para invertir el comportamiento del predictor de saltos. Estas nuevas
instrucciones añaden el sufijo n a las ya existentes y predicen como tomados
los saltos hacia delante y como no tomados los saltos hacia atrás.
Conociendo que sólo el 10% de los elementos del vector a son positivos,
modifique el programa con estas nuevas instrucciones para minimizar la
penalización media debida a los saltos mal predichos. ¿Qué penalización
media debida a los saltos tiene esta nueva versión del programa?

Solución
En la secuencia de instrucciones del problema aparecen tres saltos, que a partir de ahora notaremos
como S1, S2 y S3 como se muestra a continuación:

lw r9, n
add r10, r0, r0
inicio: lw r1, a(r10)
sgt r2, r1, r0
bnez r2, mayor ; (S1)
sub r1, r0, r1
beqz r2, fin ; (S2)
mayor: add r1, r1, r1
fin: sw r1, a(r10)
addi r10, r10, #1
seq r3, r9, r10
bnez r3, inicio ; (S3)
trap #0

Teniendo en cuenta el comportamiento del predictor estático descrito en el enunciado y que solo el
10% de los valores del vector a son positivos, podemos descubrir que:

 El salto S1 saltará hacia adelante el 10% de las iteraciones (dependiendo de si el


elemento es positivo), y cuando salte incurrirá en una penalización de 5 ciclos.

 El salto S2 saltará hacia adelante el 90% de las iteraciones (siempre que se ejecute y
no se haya saltado en S1), y cuando salte incurrirá en una penalización de 5 ciclos.
 El salto S3 controla el bucle, con lo que saltará hacia atrás en todas las iteraciones
excepto en la última, provocando una penalización de 5 ciclos.

Por tanto, para un vector a de tamaño n, la penalización debida a los saltos mal predichos será:

P  F1  F2  F3  P  0.1n  0.9n  1  5  5n  1 ciclos

Tras esto podemos darnos cuenta de que el salto S2 está mal predicho todas las veces que se ejecuta
(90% de las iteraciones), así que haciendo uso de las nuevas instrucciones de salto para cambiar la
predicción, deberíamos sustituirlo por la siguiente instrucción:

beqzn r2, fin ; (S2)

Esta instrucción cambia el comportamiento del predictor estático y hace que no se equivoque nunca,
con lo que con esta mejora la penalización se reduce a:

n  10
P  F1  F2  F3  P  0.1n  1 5  ciclos
2

Con este resultado podemos concluir que este cambio nos reduce la penalización debida saltos mal
predichos en casi un 90%.

21. Se desea ejecutar el siguiente programa en un procesador superescalar:

lw r1, N ; (1)
add r2, r0, r0 ; (2)
bucle: lw r3, X(r2) ; (3)
sgt r4, r3, r0 ; (4)
bnz r4, mayor ; (5)
sub r3, r0, r3 ; (6)
mayor: sw X(r2), r3 ; (7)
add r2, r2, #4 ; (8)
sub r1, r1, #1 ; (9)
bnz r1, bucle ; (10)

Si el procesador usa un predictor dinámico con dos bits de historia que se inicializan con un
predictor estático que predice como tomados los saltos hacia atrás y como no tomados los
saltos hacia delante, y que la penalización en caso de errar la predicción es de 5 ciclos, ¿qué
penalización se obtendrá si X(0) = 1 y X(i + 1) = 1 – X(i)? ¿Qué penalización se obtendría si
se optimizara el código usando sentencias de ejecución condicional?

Solución
El programa del enunciado calcula el valor absoluto de los elementos del vector X. Va procesándolos
de uno en uno y les cambia el signo si no son positivos. Consta de dos saltos, el primero de ellos, al
que notaremos como S1 en el código de más abajo, sirve para detectar si los números son positivos y
el segundo, notado como S2, se emplea para volver a ejecutar el código mientras queden elementos
por procesar en el vector X.

lw r1, N
add r2, r0, r0
bucle: lw r3, X(r2)
sgt r4, r3, r0
bnz r4, mayor ; (S1)
sub r3, r0, r3
mayor: sw X(r2), r3
add r2, r2, #4
sub r1, r1, #1
bnz r1, bucle ; (S2)

Para cada uno de los dos saltos, sus bits de historia se inicializarán según el predictor estático del
computador, que predice como tomados los saltos hacia atrás. Por tanto, los bits de historia de S1 se
iniciarán al valor 00, ya que es un salto hacia delante, y los de S2 al valor 11 porque salta hacia atrás.
Una vez inicializados los bits de historia, la penalización que introduzca cada uno de ellos dependerá
del comportamiento de cada salto. En el caso de S1, su comportamiento está determinado por el valor
de cada elemento del vector X. S1 saltará siempre que X(i) sea mayor que cero, y según el enunciado,
el vector X es de la forma X = {1, 0, 1, 0, 1, 0,…}, por lo que S1 saltará una vez sí y otra no hasta que
se termine de procesar el vector X. El salto S2 saltará tantas veces como elementos tenga el vector X
menos una, es decir N – 1 veces, ya que el programa se dedica a procesar dicho vector. Teniendo esto
en cuenta, el comportamiento del predictor será el que indica la Tabla 20.

ITERACIÓN 0 1 2 3 … N–1 N
VALOR DE X 1 0 1 0 … 0 1
SALTO 1 BITS DE HISTORIA 00 01 00 01 … 01 00
PREDICCIÓN N N N N … N N
EJECUCIÓN S N S N … N S
PENALIZACIÓN P P … P
SALTO 2 BITS DE HISTORIA 11 11 11 11 … 11 11
PREDICCIÓN S S S S … S S
EJECUCIÓN S S S S … S N
PENALIZACIÓN … P

Tabla 20. Comportamiento del predictor dinámico en el problema 21.

Por tanto, la penalización que introduce debida a los saltos es:

N  
Poriginal  F1  F2  P      1  5 ciclos
 2  

Está claro que el comportamiento de S1 no puede ser aprendido por el predictor dinámico, por lo que
nos va a ocasionar muchas faltas, así que sería interesante cambiarlo por una sentencia de ejecución
condicional, tal y como muestra el siguiente código:

lw r1, N
add r2, r0, r0
bucle: lw r3, X(r2)
sub r4, r0, r3
cmov.gt r4, r3, r3
sw X(r2), r4
add r2, r2, #4
sub r1, r1, #1
bnz r1, bucle

En esta versión mantenemos el mismo número de instrucciones para ejecutar el algoritmo, y además
evitamos el salto S1, que depende del valor de cada componente de X, por lo que la penalización total
del programa es de:

Poptimización  F2  P  1 5  5 ciclos

22. Se dispone de un procesador superescalar capaz de captar, decodificar y retirar hasta dos
instrucciones por ciclo, con una única ventana de instrucciones con emisión desordenada y
no alineada, búfer de reordenamiento para el renombrado y la finalización ordenada, y una
latencia de dos ciclos para las instrucciones de carga de memoria y de un ciclo para las
instrucciones aritméticas con enteros y los almacenamientos. Se desea ejecutar el siguiente
programa en el procesador:

lw r1, n
lw r2, a
add r3, r0, r0
bucle: add r3, r3, r2
subi r1, r1, #1
bnez r1, bucle
sw r3, b
trap #0

El procesador utiliza un predictor de saltos dinámico de dos bits que se consulta en el


momento de captar las instrucciones, de forma que si la dirección de memoria de la que se
está captando una instrucción se encuentra en el BTB, y la predicción es saltar, guarda el
contenido actual de PC y se cambia por la dirección de destino del salto para que se empiece
a captar desde ahí en el siguiente ciclo. Cuando la instrucción de salto entra en el búfer de
reordenamiento tras la decodificación, se marca con un bit pred = 1 si el predictor decidió
tomar el salto o pred = 0 en caso contrario. Posteriormente, cuando se resuelve la condición
del salto en la etapa de ejecución, se comprueba si la predicción se realizó con éxito, y en
caso contrario, se marcan con flush = 1 todas aquellas instrucciones que se han introducido
en el cauce de forma especulativa para que no actualicen los registros al ser retiradas, y se fija
PC al valor guardado en el momento de la predicción para continuar con la siguiente
instrucción en el siguiente ciclo. La primera vez que se capta un salto, obviamente no se
encuentra en el BTB, por lo que no se podrá predecir su comportamiento hasta la etapa de
decodificación, en la que se emplea un predictor estático que predice como tomados todos
los saltos hacia atrás y crea una entrada en el BTB para los saltos encontrados.

a) Realice una traza de la ejecución del programa en el procesador suponiendo


que n = 2 y a = 3. ¿Cuántos ciclos tarda en ejecutarse el programa?

b) Estime la penalización (en ciclos) que se produce en el procesamiento del


salto tanto si acierta como si falla cada uno de los predictores (estático y
dinámico) del procesador.

c) ¿Cuántos ciclos de penalización en total se sufrirían si n fuera igual a 100?

NOTA: Suponga que hay tantas unidades de ejecución y de acceso a memoria como sea necesario.

Solución
La Figura 27 muestra una traza de ejecución del programa. La primera vez que se capta el salto se usa
el predictor estático, que no puede realizar la predicción hasta que se decodifica la instrucción. Por
tanto, se introduce una penalización de un ciclo, ya que mientras que se decodifica el salto entran en el
cauce las instrucciones sw y trap que se deben anular en el momento en el que se predice que el salto se
va a realizar (cuando se retiren no se modificarán los registros de la arquitectura).

En la etapa de ejecución del salto se comprueba que la predicción ha sido correcta y se procede a la
inicialización del predictor dinámico creando una entrada en el BTB para estas instrucción de salto
con el estado 11 (saltar). A partir de ahora, todas las veces que se capte el salto, se captará junto con la
instrucción siguiente (sw), ya que las instrucciones se captan de dos en dos. En la etapa de captación se
consultará el BTB y se descubrirá que la instrucción captada es un salto con una predicción de saltar,
así que se anulará la instrucción sw y se comenzará a captar en el ciclo siguiente a partir de la
instrucción de destino del salto.

En la mayoría de los casos se acertará la predicción del salto, ya que se supone que un bucle va a iterar
bastantes veces. Sin embargo, en este problema el bucle sólo tiene que iterar n = 2 veces, así que en la
segunda iteración el predictor dinámico fallará. El procesador no se da cuenta del fallo de la
predicción hasta que el salto termina la etapa EX, en la que se calcula la condición del salto. En este
momento se anulan todas las instrucciones captadas especulativamente y se fija el contenido de PC a
la instrucción del camino secuencial. En total se pierden 2 ciclos. Tras introducir las instrucciones sw y
trap en el cauce, se sigue su ejecución hasta que se retiran en el ciclo 13, momento en el que finaliza la
ejecución del programa.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13
lw r1, n IF ID EX ROB WB
lw r2, a IF ID EX ROB WB
add r3, r0, r0 IF ID EX ROB WB
add r3, r3, r2 IF ID EX ROB WB
subi r1, r1, #1 IF ID EX ROB WB
bnez r1, bucle IF ID EX ROB WB
sw r3, b IF Flush
trap #0 IF Flush
add r3, r3, r2 IF ID EX ROB WB
subi r1, r1, #1 IF ID EX ROB WB
bnez r1, bucle IF ID EX ROB WB
sw r3, b IF Flush
add r3, r3, r2 IF Flush
subi r1, r1, #1 IF Flush
bnez r1, bucle IF Flush
sw r3, b IF Flush
sw r3, b IF ID EX ROB WB
trap #0 IF ID EX ROB WB
PENALIZACIÓN P P P

Figura 27. Traza de la ejecución del código del problema 22.

Analizado la traza del programa, podemos deducir que la penalización introducida por el predictor
estático es de:

 Pest_acierto = 1 ciclo (la predicción se realiza en la etapa de decodificación).

 Pest_fallo = 2 ciclos (no se corrige hasta después de la etapa de ejecución).

mientras que la del predictor dinámico es de:

 Pdin_acierto = 0 ciclos (la se realiza predicción anticipada en la captación).

 Pdin_fallo = 2 ciclos (al igual que el predictor estático, no se corrige hasta después de
la etapa de ejecución).

Por tanto, como el bucle itera n veces, la primera iteración se predice con el predictor estático, y el
resto con el dinámico, la expresión general para calcular su penalización es:

P n   Pest_acierto  n  2 Pdin_acierto  Pdin_fallo  1  n  2 0  2  3 ciclos

ya que se acertarán todas las predicciones excepto la de la última iteración, en la que se predecirá saltar
y se fallará. Esta penalización se producirá en cualquier ejecución del bucle, independientemente del
valor de n.

23. Suponga un procesador superescalar en que se captan, decodifican, emiten y retiran hasta dos
instrucciones por ciclo. La etapa de decodificación se realiza de forma ordenada, ya que es en
esta etapa donde se introducen las instrucciones en un búfer de reordenamiento (ROB) que
permite su finalización ordenada. Por el contrario, la emisión es desordenada y se
implementa mediante estaciones de reserva individuales para cada unidad funcional. El
procesador utiliza predicción dinámica de saltos con dos bits de historia. Para la primera
ejecución de una instrucción de salto dada, el procesador predice saltar si la dirección de salto
es hacia direcciones inferiores, y no saltar si la dirección es mayor. Las instrucciones de salto
se procesan en la etapa de ejecución y consumen un ciclo en esa etapa (en el siguiente ciclo
ya se tendría la dirección de salto correcta y se podría captar la instrucción correcta si la
predicción de salto no hubiera sido correcta).

Suponiendo una frecuencia de 2 GHz, que el cauce se encuentra inicialmente vacío, y que
inicialmente r2 = 100000, para la siguiente secuencia de instrucciones:

bucle: addd f1, f1, f6 ; (1)


multd f6, f2, f5 ; (2)
subd f5, f1, f3 ; (3)
loop r2, bucle ; (4)
addd f7, f1, f5 ; (5)

a) ¿Cuánto tarda en procesarse la secuencia de instrucciones?

b) ¿Cuál es la velocidad pico del procesador?

NOTA: La instrucción loop decrementa el registro y salta si el valor del registro es distinto de cero. La
suma y la resta en coma flotante consumen dos ciclos de reloj y la multiplicación en coma
flotante cuatro ciclos. Considere que no hay limitaciones en la capacidad de los búferes y en
el número de unidades funcionales. Se supone que todos los registros tienen valores válidos
previos.

Solución
Para responder al primer apartado es necesario realizar una traza de su ejecución. En la Figura 28 se
muestra una traza en la que se supone que r2 = 3 iteraciones. En esta traza se observan los riesgos de
control:

 La primera vez que se capta el salto, no se puede usar el predictor dinámico porque
no existe ninguna entrada en el BTB del procesador para él. Por tanto, en la etapa
de decodificación, una vez que se identifique el salto, se incluirá una entrada en el
BTB para que la siguiente vez que se capte se pueda usar el predictor dinámico, se
usará un predictor estático que predecirá saltar (el salto es hacia atrás), y se anularán
las dos instrucciones que se captaron erróneamente tras el salto. Teniendo en
cuenta las etapas del cauce, el predictor estático provocará una penalización de 1
ciclo para los saltos acertados.

 A partir de la segunda iteración, cada vez que se capte el salto se usará el predictor
dinámico, por lo que no hay penalización en caso de acertar. Esto ocurrirá en el
resto de iteraciones menos en la última, en la que el predictor fallará y obtendremos
una penalización de 2 ciclos hasta captar la siguiente instrucción al salto, ya que es
en la etapa de ejecución en la que se comprueba la corrección de la predicción. Una
vez que se comprueba que falló la predicción, se anulan todas las instrucciones
captadas especulativamente y se comienza a captar desde la dirección correcta para
terminar la ejecución del programa.
Estos ciclos de penalización se solapan con los introducidos por los riesgos RAW entre las sucesivas
iteraciones del bucle a causa de f6 y f5, por lo que al final no influyen en el tiempo de ejecución, que
está determinado por los riesgos RAW existentes en el código.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
addd f1, f1, f6 IF ID EX ROB WB
multd f6, f2, f5 IF ID EX ROB WB
subd f5, f1, f3 IF ID EX ROB WB
loop r2, bucle IF ID EX ROB WB
addd f7, f1, f5 IF Flush
Sig. instrucción IF Flush
addd f1, f1, f6 IF ID EX ROB WB
multd f6, f2, f5 IF ID EX ROB WB
subd f5, f1, f3 IF ID EX ROB WB
loop r2, bucle IF ID EX ROB WB
addd f1, f1, f6 IF ID EX ROB WB
multd f6, f2, f5 IF ID EX ROB WB
subd f5, f1, f3 IF ID EX ROB WB
loop r2, bucle IF ID EX ROB WB
addd f1, f1, f6 IF ID Flush
multd f6, f2, f5 IF ID Flush
subd f5, f1, f3 IF ID Flush
loop r2, bucle IF ID Flush
addd f7, f1, f5 IF ID EX ROB WB
PENALIZACIÓN P P P

TLI MLM MLM FIN

Figura 28. Traza de la ejecución del código del problema 23.

Si nos fijamos en el instante de tiempo en el que se retira la última instrucción del bucle en cada
iteración, podemos estimar que una vez terminada la primera iteración tras un tiempo TLI, el resto de
iteraciones irán terminando cada MLM ciclos, y una vez terminada la ejecución del bucle, la última
instrucción tardará un ciclo más en ejecutarse. Por tanto, para un número de iteraciones N, y teniendo
en cuenta que la frecuencia del procesador es de 2 GHz, podemos concluir que el tiempo de ejecución
es de:

TLI  N  1 MLM  FIN 9  N  1 4  1


T N     2 N  3 109
F 2  109

por lo que si r2 = 100000, el tiempo de ejecución será:

T 100000  2  100000 3 109  200 s

Para contestar al segundo apartado, como el procesador puede completar hasta 2 instrucciones por
ciclo, su velocidad pico es de:

F
Rpico   IPC  F  2  2  109  4  109 instrucciones/s
CPI

24. Se dispone de un procesador superescalar capaz de captar, decodificar y retirar hasta cuatro
instrucciones por ciclo, con una única ventana de instrucciones con emisión centralizada,
desordenada y no alineada, y con un búfer de reordenamiento para el renombrado y la
finalización ordenada. El procesador utiliza un predictor de saltos dinámico de dos bits que
se consulta en el momento de captar las instrucciones, de forma que si la dirección de
memoria de la que se está captando una instrucción se encuentra en el BTB, y la predicción
es saltar, guarda el contenido actual de PC y se cambia por la dirección de destino del salto
para que se empiece a captar desde ahí en el siguiente ciclo. Cuando la instrucción de salto
entra en el búfer de reordenamiento tras la decodificación, se marca con un bit pred = 1 si el
predictor decidió tomar el salto o pred = 0 en caso contrario. Posteriormente, cuando se
resuelve la condición del salto en la etapa de ejecución, se comprueba si la predicción se
realizó con éxito, y en caso contrario, se marcan con flush = 1 todas aquellas instrucciones
que se han introducido en el cauce de forma especulativa para que no actualicen los registros
al ser retiradas, y se fija PC al valor guardado en el momento de la predicción para continuar
con la siguiente instrucción en el siguiente ciclo. La primera vez que se capta un salto,
obviamente no se encuentra en el BTB, por lo que no se podrá predecir su comportamiento
hasta la etapa de decodificación, en la que se emplea un predictor estático que predice como
tomados todos los saltos hacia atrás y crea una entrada en el BTB para los saltos
encontrados. Si en el procesador descrito se ejecuta el siguiente programa:

lw r1, N ; (1)
lw r2, X ; (2)
add r3, r0, r0 ; (3)
bucle: add r3, r3, r2 ; (4)
add r4, r3, r3 ; (5)
subi r1, r1, #1 ; (6)
bnez r1, bucle ; (7)
sw R, r4 ; (8)
trap #0 ; (9)

a) ¿Qué valor tiene R al final del programa si inicialmente N = 3 y X = 3?

b) ¿Cuál es la penalización que se obtiene cuando se predice mal un salto en


este procesador?

c) ¿Cuántos ciclos tardaría en ejecutarse el programa si N tuviera el valor 500?

NOTA: Suponga un número de unidades de ejecución y un tamaño de búferes suficiente como para
que no se provoquen riesgos estructurales en el cauce. Las unidades funcionales de acceso a
memoria tienen una latencia de 2 ciclos y el resto de unidades funcionales utilizadas 1 ciclo
de latencia.

Solución
Para responder a la primera pregunta es necesario entender el funcionamiento del programa, que
básicamente consiste en lo siguiente:

r 3i   r 3i  1  X
r 4i   2  r 3i 

siendo i el número de iteraciones que se ejecutan y r3(0) = 0. Reescribiendo las expresiones anteriores
de forma que no se calculen de forma recursiva tenemos que:

r 3i   i  X
r 4 i   2  i  X

Como el número de iteraciones del programa está controlado por el registro r1, que inicialmente se fija
al valor de la variable N, el valor final para R es de:

R  r 4N   2  N  X  2  3  3  18

Para responder a la siguiente cuestión usaremos la traza de la ejecución del programa, mostrada en la
Figura 29. En este diagrama se puede comprobar que el predictor estático (que se aplica en la etapa de
decodificación la primera vez que se capta un salto) introduce un ciclo de penalización para los saltos
tomados. El resto de las iteraciones que se ejecute el salto se usará el predictor dinámico, que no
introduce penalización en caso de acertar. Sin embargo, en la última iteración el predictor dinámico
falla. El fallo se detecta en la etapa de ejecución del salto, por lo que se introduce una penalización de
tres ciclos.

INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 11 12 13 14
lw r1, N IF ID EX EX ROB WB
lw r2, X IF ID EX EX ROB WB
add r3, r0, r0 IF ID EX ROB WB
add r3, r3, r2 IF ID EX ROB WB
add r4, r3, r3 IF ID EX ROB WB
subi r1, r1, #1 IF ID EX ROB WB
bnez r1, bucle IF ID EX ROB WB
sw R, r4 IF ID Flush
trap #0 IF Flush
Sig. instrucción IF Flush
Sig. instrucción IF Flush
Sig. instrucción IF Flush
add r3, r3, r2 IF ID EX ROB WB
add r4, r3, r3 IF ID EX ROB WB
subi r1, r1, #1 IF ID EX ROB WB
bnez r1, bucle IF ID EX ROB WB
add r3, r3, r2 IF ID EX ROB WB
add r4, r3, r3 IF ID EX ROB WB
subi r1, r1, #1 IF ID EX ROB WB
bnez r1, bucle IF ID EX ROB WB
add r3, r3, r2 IF ID EX Flush
add r4, r3, r3 IF ID Flush
subi r1, r1, #1 IF ID EX Flush
bnez r1, bucle IF ID Flush
add r3, r3, r2 IF ID Flush
add r4, r3, r3 IF ID Flush
subi r1, r1, #1 IF ID Flush
bnez r1, bucle IF ID Flush
add r3, r3, r2 IF Flush
add r4, r3, r3 IF Flush
subi r1, r1, #1 IF Flush
bnez r1, bucle IF Flush
sw R, r4 IF ID EX EX ROB WB
trap #0 IF ID EX ROB WB
PENALIZACIÓN P P P P

TLI MLM MLM FIN

Figura 29. Traza de la ejecución del código del problema 24.

Por último, para calcular el tiempo de ejecución para N iteraciones hay que tener en cuenta que
transcurren 8 ciclos hasta que se termina la primera iteración, que cada iteración termina un ciclo
después de la anterior, y que tras la última iteración hay que añadir 4 ciclos para almacenar el resultado
final, es decir, que el tiempo para ejecutar N iteraciones se puede calcular mediante las expresión:

T N   TLI  N  1 MLM FIN  8  N  11  4  N  11ciclos

Por tanto, para ejecutar N = 500 iteraciones serían necesarios 511 ciclos.

25. Se dispone de un procesador superescalar en el que se pueden captar y decodificar hasta dos
instrucciones por ciclo. Este ordenador cuenta con dos sumadores de latencia 2 ciclos, un
multiplicador de latencia 4 ciclos, y una unidad de carga con una latencia de 1 ciclo si se
produce un acierto en la cache o 3 ciclos si el dato solicitado no se encuentra en la cache.
Cada unidad de ejecución cuenta con su propia estación de reserva de 3 entradas. Para
mantener la consistencia secuencial y garantizar un tratamiento preciso de las interrupciones,
las instrucciones se introducen en un búfer de reordenamiento en la etapa de decodificación,
del que se retiran de dos en dos de manera ordenada una vez han terminado su ejecución. En
dicho procesador se pretende ejecutar el siguiente fragmento de código (que ya está alojado
en la cache de instrucciones):

multd f4, f1, f2 ; (1)


ld f5, X(r3) ; (2)
addd f2, f3, f1 ; (3)
addd f3, f4, f2 ; (4)
subd f2, f3, f5 ; (5)

Al intentar cargar la variable X, se produce un fallo de página porque dicha variable no se


encuentra ni en la cache ni en memoria principal. Dicho fallo se detecta en el ciclo 2 de la
ejecución de la instrucción ld, cuando se consulta la tabla de páginas de SO. En ese
momento, se genera una excepción para indicar el problema.

a) ¿Qué contenido tiene el búfer de reordenamiento en ese ciclo?

b) ¿En qué ciclo se comenzará a ejecutar la rutina de servicio de la


interrupción?

c) Si la rutina de servicio de interrupción tarda 237 ciclos en traer la página a la


memoria principal y retornar el control al programa, ¿Qué instrucción del
programa se ejecutará y en qué ciclo comenzará a ejecutarse?

d) ¿Cuántos ciclos tardará en terminar la ejecución completa del fragmento de


código?

Solución
La Figura 30 muestra una traza de la ejecución del programa. Hasta el ciclo 4, la ejecución del
programa es normal, las instrucciones se van captando, decodificando, etc., pero justo en este ciclo (el
segundo ciclo de la ejecución de la carga) se produce una excepción, por lo que se marca la instrucción
(2) con el campo excep = 1 y las instrucciones (2) – (5) con el campo flush = 1 como muestra la Tabla
21. A partir de este momento se dejan de captar instrucciones y se continúa la ejecución de las
instrucciones que hay en el cauce hasta que la instrucción que ha provocado la excepción alcance el
tope del búfer de reordenamiento.

En el ciclo 9, tras retirar todas las instrucciones marcadas con flush = 1, se salvará la dirección de la
instrucción load para poder reiniciar la ejecución del programa una vez se haya traído la página a
memoria, y se comenzará a captar instrucciones de la Rutina de Servicio de Interrupción (RSI),
suponiendo que no hay ningún retardo para obtener la su dirección. Como la RSI tarda 237 ciclos,
habrá terminado en el ciclo 245. Su última instrucción será un retorno de interrupción, que modifica el
registro PC con la dirección previamente guardada, así que en el ciclo 246 se volverá a captar a partir
de la instrucción load, que ahora no cometerá la excepción porque el dato que quiere leer ya está en
memoria. Por tanto, al final el código tarda en ejecutarse 253 ciclos.

CICLO # CÓDIGO REGISTRO VALOR VALOR EXCEP FLUSH


OPERACIÓN DESTINO VÁLIDO
4 0 mult f4 – 0 0 0
1 ld f5 – 0 1 1
2 add f2 – 0 0 1
3 add f3 – 0 0 1
4 sub f2 – 0 0 1

Tabla 21. Estado del ROB en el momento en el que se produce la excepción en el problema 25.
INSTRUCCIÓN 1 2 3 4 5 6 7 8 9 10 … 246 247 248 249 250 251 252 253
multd f4, f1, f2 IF ID EX ROB WB
ld f5, X(r3) IF ID EX Excepción
addd f2, f3, f1 IF ID Flush
addd f3, f4, f2 IF ID Flush
subd f2, f3, f5 IF Flush
Sig. instrucción IF Flush
1ª instr. RSI IF ID
2ª instr. RSI IF ID
3ª instr. RSI IF
4ª instr. RSI IF
...
ld f5, X(r3) IF ID EX ROB WB
addd f2, f3, f1 IF ID EX ROB WB
addd f3, f4, f2 IF ID EX ROB WB
subd f2, f3, f5 IF ID EX ROB WB

Figura 30. Traza de la ejecución del código del problema 25.

Вам также может понравиться