1. El siguiente fragmento de código se ejecuta en un DLX con

Anuncio
1. El siguiente fragmento de código se ejecuta en un DLX con segmentación:
loop:
add
ld
ld
ned
bfpf
subd
divd
sd
addi
sgti
beqz
;
r2, r2, r1
;
f0, 0(r1)
;
f2, 0(r2)
;
f0, f2
;
#4
;
f2, f2, f0
;
f0, f0, f2 ;
0(r1), f0
;
r1, r1, #8
;
r3, r1, #1000 ;
r3, loop
;
inicialmente r1 = 0
modificar indice Y
cargar X(i)
cargar Y(i)
X(i) ≠ Y(i)?
saltar resta si no se cumple la condición
Y(i) = Y(i) - X(i)
X(i) = X(i) / Y(i)
salvar X(i)
incrementar indice X
final?
Suponiendo que:
·
un dato se puede escribir en un registro y leer su valor en el mismo ciclo
·
no se dispone de lógica de cortocircuito
·
los saltos se resuelven en la etapa de decodificación (DE)
·
las unidades funcionales tienen las siguientes características:
UF
FP ADD
FP MUL/DIV
Int ALU
Cantidad
1
1
1
Latencia
2
3
1
Segmentación
No
No
No
a) Determinar el CPI teniendo en cuenta que la resta se ejecuta tan solo una de cada ocho iteraciones.
b) Indicar que cortocircuitos serian necesarios y cual sería su influencia en el CPI.
c) Suponiendo ahora además que se dispone de salto retardado, modificar el código para que el CPI sea
mínimo.
Nota: La instrucción ned modifica el bit de estado de punto flotante (fps) que posteriormente es leído por la
instrucción bfpf . Esta dependencia sin embargo no produce penalización alguna en la resolución del salto.
2. Sea un computador superescalar similar a la versión Tomasulo del DLX capaz de lanzar a ejecución dos
instrucciones independientes por ciclo de reloj. El siguiente fragmento de programa aplica un filtro lineal
sobre un vector A y almacena el resultado en un vector B:
for (i = 1; i < 100; i = i +1)
{
b[i] = coef*a[i-1] + a[i] + coef*a[i+1];
}
El compilador lo traduce al siguiente código DLX:
; r1 almacena la dirección de a
; r2 almacena la dirección de b
addi r3,r1,#800 ; condicion de final
addi r1,r1,#8
; inicialización de los indices
addi r2,r2,#8
;
ld
f0,coef
; cargar coeficiente
loop: ld
f2,#-8(r1) ; cargar a[i-1]
ld
f4,0(r1)
; cargar a[i]
ld
f6,#8(r1)
; cargar a[i+1]
muld f8,f2,f0
; a[i-1]*coef
muld f10,f6,f0
; a[i+1]*coef
addd f4,f8,f4
; a[i-1]*coef + a[i]
addd f4,f10,f4
; a[i-1]*coef + a[i] + a[i+1]*coef
sd
0(r2),f4
; almacenar b[i]
addi r1,r1,#8
; incrementar indices
addi r2,r2,#8
slt
r4,r1,r3
bnez r4,loop
Las unidades funcionales están segmentadas y tienen las siguientes características (para las operaciones en
punto flotante si la instrucción dependiente es de almacenamiento, se puede disponer del dato un ciclo antes
mediante anticipación de operandos):
Unidad
Funcional
FP mul/div
FP add
ALU int
Load/Store
Cantida
d
2
2
2
2
Latencia
4
2
1
2
(EA+MEM)
a)
Desenrollar el bucle de manera a obtener 3 copias del cuerpo y planificarlo asumiendo las latencias
anteriores (haciendo especial hincapié en eliminar los computos redundantes).
b) ¿Cuántos ciclos emplea cada iteración del bucle original?
c) ¿Cuántos ciclos emplearía cada iteración del bucle desenrollado en un DLX segmentado sin
planificación dinámica?
d) ¿Qué combinación resulta más interesante desde el punto de visto de la relación coste/prestaciones,
un compilador capaz de realizar las modificaciones del apartado a) junto con un DLX segmentado
sin planificación dinámica, o bien un DLX superescalar junto con el compilador original? Justifica la
respuesta.
Nota: Las instrucciones de salto no pueden lanzarse a ejecución junto con una instrucción posterior a
este.
Descargar