Individuare gli Hazard
Data Hazard
- Hazard 1: L'istruzione
and $t1, $s5, $s0utilizza $s5 che potrebbe non essere pronto sesltilo modifica. - Hazard 2: L'istruzione
beq $s2, $zero, END_WHILEdipende dasltiche scrive $s2. - Hazard 3: L'istruzione
sub $t1, $t1, $s5dipende dai risultati diaddi $s5, $s5, 1eand $t1, $s5, $s0.
Control Hazard
- Hazard: L'istruzione
beq $s2, $zero, END_WHILEpotrebbe causare un hazard di controllo se il branch è preso.
Risolvere gli Hazard
Data Hazard
- Stalling: Introduci cicli di attesa (NOP) per risolvere i RAW hazard.
- Forwarding: Utilizza il 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 data hazard tra slti e beq. Questa tabella rappresenta un esempio semplificato e non esaustivo. La risoluzione esatta può variare a seconda dell'implementazione specifica della pipeline.
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;
Assegnazione dei registri
- Base C[]: $t2
- new: $s0
- k: $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: 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: 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
lwper 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
swper salvare il valore di new in C[k+4].
Ecco come tradurre questa parte:
# Calcolo dell'indirizzo di C[k+4] add $t0, $s1, 4 # Incrementa k di 4 sll $t0, $t0, 2 # Moltiplica (k+4) per 4 add $t1, $t0, $t2 # Somma la base dell'array C[] ($t2) e (k+4)*4 ($t0), salva in $t1 sw $s0, 0($t1) # Salva new in C[k+4]