vuoi
o PayPal
tutte le volte che vuoi
Passo 3: Individuare gli Hazard
Data Hazard
1. and $t1, $s5, $s0 utilizza $s5 che potrebbe non essere pronto se slti lo modifica.
2. beq $s2, $zero, END_WHILE dipende da slti che scrive $s2.
3. sub $t1, $t1, $s5 dipende dai risultati di addi $s5, $s5, 1 e and $t1, $s5, $s0.
Control Hazard
1. beq $s2, $zero, END_WHILE potrebbe causare un hazard di controllo se il branch
è preso.
Passo 4: Risolvere gli Hazard
Data Hazard
Stalling: Introduci cicli di attesa (NOP) per risolvere i RAW hazard.
Forwarding: Utilizza forwarding per risolvere RAW hazard.
Control Hazard
Branch Prediction: Utilizza una previsione se il branch sarà preso o no.
Delayed Branch: Inserisci istruzioni indipendenti nelle slot di ritardo.
Esempio di Pipeline Risolta Consideriamo l'introduzione di cicli di attesa per il
Questa tabella
rappresenta un
esempio
semplificato e
non esaustivo.
La risoluzione
esatta può
variare a
seconda
dell'implementa
zione specifica
della pipeline.
data hazard tra slti e beq.
RISOLVERE ESERCIZI: ARCHITETTURE E RETI
DI CALCOLATORI
1° Tipologia: Traduzione istruzioni Linguaggio C in
istruzioni Assembly MIPS
ISTRUZIONE IN LINGUAGGIO C
Int C[30], k, new ;
new = new – C[K] ;
C[K+4] = new ;
assegnando i registri
Base C[] new k
$t2 $s0 $s1
Int C[30], k, new ;
new = new – C[K] ;
Istruzione C
C[K+4] = new ;
asegnando i registri
Base C[] new k
$t2 $s0 $s1
Passaggi per tradurlo in Assembly MIPS:
1. Dichiarazione delle variabili
Nel linguaggio C, hai dichiarato un array C[30] e due variabili k e
new. In MIPS, ogni variabile verrà mappata su un registro. Dato che si
tratta di variabili che userai spesso, puoi usare i registri salvati:
Array C[]: Viene memorizzato in memoria, quindi useremo un
puntatore base, che è il registro $t2.
Variabile k: Usata come indice dell'array, memorizzata in $s1.
Variabile new: La variabile new sarà memorizzata nel registro $s0.
2. Traduzione dell'istruzione new = new - C[k];
Calcolo dell'indirizzo dell'elemento C[k]: L'array C[] è un array di
interi, quindi ogni elemento occupa 4 byte in memoria. Dato che k è
l'indice, dobbiamo moltiplicare k per 4 per ottenere l'indirizzo
corretto di C[k].
Somma con la base dell'array: La base dell'array è memorizzata
in $t2, quindi sommiamo l'offset calcolato a $t2.
Caricamento di C[k]: Una volta che abbiamo l'indirizzo di C[k],
possiamo usare l'istruzione lw per caricare C[k] in un registro
temporaneo.
Sottrazione: Ora possiamo eseguire la sottrazione tra new e C[k]
e salvare il risultato in new.
Ecco la traduzione passo-passo:
sll $t0, $s1, 2 # Moltiplica k per 4 (sll: shift left
logical di 2 bit, che equivale a moltiplicare per 4)
add $t1, $t0, $t2 # Somma la base dell'array C[] ($t2) e
k*4 ($t0), salva in $t1 (indirizzo di C[k])
lw $t5, 0($t1) # Carica il valore di C[k] dall'indirizzo
calcolato in $t5
sub $s0, $s0, $t5 # new = new - C[k], salva in $s0
3. Traduzione dell'istruzione C[k+4] = new;
Ora dobbiamo memorizzare new in C[k+4]. La logica è simile a
quella precedente:
Calcolo dell'indirizzo di C[k+4] : Dobbiamo calcolare l'indirizzo di
C[k+4]. Poiché ogni elemento è lungo 4 byte, C[k+4] sarà situato
a k*4 + 16 byte dall'inizio dell'array.
Memorizzazione del valore di new : Una volta che abbiamo
calcolato l'indirizzo di C[k+4], possiamo usare l'istruzione sw per
salvare il valore di new in C[k+4].
Ecco come tradurre questa parte: