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.