Você está na página 1de 70

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
instruccione
(IF) s

Registros de Emisión Ventana de instrucciones, Decodificac


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

Registros Registros Registros


UF UF UF

Escritura Unidad Unidad Unidad Ejecuci


funcional funcional funcional ón
(WB)
(EX)
Registro Registro Registro
UF UF 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.

# ENTRAD ÍNDICE # VALOR VÁLIDO


A BÚFER
VÁLIDA
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 No
fuerte débil tomado tomado
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 ENTRAD ÍNDICE VALOR VÁLIDO


A BÚFER
VÁLIDA
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 ENTRAD ÍNDICE VALOR VÁLIDO


A BÚFER
VÁLIDA
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 ENTRAD ÍNDICE VALOR VÁLIDO


A BÚFER
VÁLIDA
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,
ID EX
f2
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, EX
ID
f2
addd f2, f3, f1 ID EX

subd f3, f3, f1 ID EX

multd f5, f1, ID EX


f4
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, EX
ID
f2
addd f2, f3, f1 ID EX

subd f3, f3, f1 ID EX

multd f5, f1, ID EX


f4
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, IF ID EX ROB WB
f2
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, IF
ID EX ROB WB
f3, f2
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,
IF ID EX ROB WB
#128
add r1, r0,
IF ID EX ROB WB
0x0a
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,
IF ID EX ROB WB
#16

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,
IF ID EX ROB WB
#128
add r1, r0,
IF ID EX ROB WB
0x0a
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,
IF ID EX ROB WB
#16
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,
IF ID EX ROB WB
#128
add r1, r0,
IF ID EX ROB WB
0x0a
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,
IF ID EX ROB WB
#16

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,
IF ID EX ROB WB
#128
add r1, r0,
IF ID EX ROB WB
0x0a
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,
IF ID EX ROB WB
#16

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 r5 [0x0a – 1
lw
8]
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,
IF ID EX ROB WB
f2, f3
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,
IF ID EX ROB WB
f2, f3
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,
IF ID EX ROB WB
f5
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,
IF ID EX ROB WB
f2
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
deciclos 9
T   4.5ns
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:

V pico  tasa  F  2 2 109  4 109 instrucci


deretirada ones/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,
IF ID EX ROB WB
f2
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
deciclos 9
T   4.5ns
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:

V pico  tasa  F  3 2 109  6 109 instrucci


deretirada ones/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Ó
1 2 3 4 5 6 7 8 9 10 11 12
N
multd f1, f1,
IF ID EX ROB WB
f5
addd f2, f2,
IF ID EX ROB WB
f5
divd f4, f1,
IF ID EX ROB WB
f2
addd f6, f1,
IF ID EX ROB WB
f5
multd f5, f2,
IF ID EX ROB WB
f2
subd f6, f2,
IF ID EX ROB WB
f1

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
deciclos 12
T   6ns
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:

V pico  tasa  F  2 2 109  4 109 instrucci


deretirada ones/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,
IF ID EX ROB WB
f1, f2
addd f3, f3, f2 IF ID EX ROB WB
multd f4,
IF ID EX ROB WB
f1, f3
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
deciclos 15
T   5ns
F 3 109

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

V pico  tasa  F  2 3 109  6 109 instrucci


deretirada ones/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),
IF ID EX ROB WB
f4
lf f5,
IF ID EX ROB WB
16(r2)
addf f6, f5, f2 IF ID EX ROB WB
multf f6,
IF ID EX ROB WB
f6, f4
sf 8(r2), f6 IF ID EX ROB WB
addi r3, r2,
IF ID EX ROB WB
#32
lf f7, 0(r3) IF ID EX ROB WB
multf f8,
IF ID EX ROB WB
f7, f3
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  55ciclos

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 Nestático
 P  7 5  35ciclos

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:

P2bits  F2bits P  11 5  55ciclos

1 1 1 1 0 0 0 1 0 1 0 1 0 1 1 1 1 1
ESTADO
1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 1 1 1
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:

P3bits  F3bits P  10 5  50ciclos

1 1 1 0 0 0 1 1 0 1 0 1 0 1 1 1 1 1
ESTADO 1 1 1 1 0 0 0 1 1 0 1 0 1 0 1 1 1 1
1 1 1 1 1 0 0 0 1 1 0 1 0 1 0 1 1 1
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  28ciclos

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:

 N1S2  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 ÚLTIMAS ITERACIONES 000 000 000 000 000


1
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 ÚLTIMAS ITERACIONES 000 100 110 111 111
2
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:

 N1S2  8d N1
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):

 N1S2  9 N1N2
2. 1 ≤ c < 10:

 Si c = 9: N1S2S1

 Si c = 8:  N1S2  2S1
 …

 Si c = 1:  N1S2  9S1
Es decir:

 N1S2  10cS1
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


 N1S2  9 N1N2 y la predicción es  S1S2  10 , tendríamos un fallo por
cada salto que no se tome, es decir:

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

2. 1 ≤ c < 10: En este caso, el comportamiento es  N1S2  10cS1 , 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  0ciclos


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  N1S2  9 N1N2 ,


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

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

2. 1 ≤ c < 10: En este caso, el comportamiento es  N1S2  10cS1 , por lo


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

Pestático
2
 Festático
2
 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ático
3
 Festático
3
 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  N1S2  9 N1N2 , se debe separar para cada


salto, ya que cada salto tendrá un bit de historia independiente.

 Para el primer salto tendremos el comportamiento


 N1 10 y la predicción S1 N1 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


 S2  9 N2 y la predicción  S2  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ámico
1
  F1  F2   P   1 1  4  8ciclos
2. 1 ≤ c < 10:

 Para el primer salto tendremos el comportamiento


 N1 10cS1 y la predicción S1 N1 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


 S2  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ámico
2
  F1  F2   P   2 0  4  8ciclos

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ámico
3
  0 0  P  0ciclos

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 


  10 c  4 
c1
Pfijo  0.25 Pfijo1  0.45 Pfijo2  0.30 Pfijo3  0.25 44 0.45    0.30 0  20ciclo
 9 
 
 

Para el predictor estático tenemos:

Pestático 0.25 Pestático


1
 0.45 Pestático
2
 0.30 Pestático
3
 0.25 4  0.45 4  0.30 4  4 ciclos

Y para el predictor dinámico:

Pdinámico 0.25 Pdinámico


1
 0.45 Pdinámico
2
 0.30 Pdinámico
3
 0.25 8  0.45 8 0.30 0  5.6ciclo

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– N
1
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  5ciclos
  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:

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

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
Flus
add r3, r3, r2 IF
h
Flus
subi r1, r1, #1 IF
h
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_aciert
o   n 2  Pdin_aciert
o  Pdin_fallo 1  n 2  0 2  3ciclos

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,
IF ID EX ROB WB
f2, f5
subd f5, f1, f3 IF ID EX ROB WB

loop r2, bucle IF ID EX ROB WB

addd f7, f1, f5 IF Flush


Sig.
IF Flush
instrucción
addd f1, f1, f6 IF ID EX ROB WB
multd f6,
IF ID EX ROB WB
f2, f5
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,
IF ID EX ROB WB
f2, f5
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,
IF ID Flush
f2, f5
subd f5, f1, f3 IF ID Flush

loop r2, bucle IF ID Flush


addd f7, f1, f5 IF ID EX ROB WB
PENALIZACIÓ
P P P
N

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     2N  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 instrucci
ones/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:

r3 i   r3 i  1  X
r4 i   2 r3 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:

r3 i   i  X
r4 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  r4 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,
IF ID EX ROB WB
r0
add r3, r3,
IF ID EX ROB WB
r2
add r4, r3,
IF ID EX ROB WB
r3
subi r1, r1,
IF ID EX ROB WB
#1
bnez r1,
IF ID EX ROB WB
bucle
sw R, r4 IF ID Flush
trap #0 IF Flush
Sig.
IF Flush
instrucción
Sig.
IF Flush
instrucción
Sig.
IF Flush
instrucción
add r3, r3,
IF ID EX ROB WB
r2
add r4, r3,
IF ID EX ROB WB
r3
subi r1, r1,
IF ID EX ROB WB
#1
bnez r1,
IF ID EX ROB WB
bucle
add r3, r3,
IF ID EX ROB WB
r2
add r4, r3,
IF ID EX ROB WB
r3
subi r1, r1,
IF ID EX ROB WB
#1
bnez r1,
IF ID EX ROB WB
bucle
add r3, r3,
IF ID EX Flush
r2
add r4, r3,
IF ID Flush
r3
subi r1, r1,
IF ID EX Flush
#1
bnez r1,
IF ID Flush
bucle
add r3, r3,
IF ID Flush
r2
add r4, r3,
IF ID Flush
r3
subi r1, r1,
IF ID Flush
#1
bnez r1,
IF ID Flush
bucle
add r3, r3,
IF Flush
r2
add r4, r3,
IF Flush
r3
subi r1, r1,
IF Flush
#1
bnez r1,
IF Flush
bucle
sw R, r4 IF ID EX EX ROB WB
trap #0 IF ID EX ROB WB
PENALIZACIÓ
P P P P
N

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 FLUS


OPERACIÓN DESTINO VÁLIDO H

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,
IF ID EX ROB WB
f1, f2
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.
IF Flush
instrucción
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.

Você também pode gostar