ESERCIZIO 1 Il set di istruzioni del DLX viene esteso con le seguenti due istruzioni FOR Ri, Rx, Ry NEXT Ri, IMM Che

verranno sempre utilizzate in coppia come mostrato nel seguente frammento di codice ADDI FOR LW SW NEXT R4, R0, 4 R1, R0, R4 R4, 1000H(R1) 2000H(R1), R4 R1, 4

Queste due nuove istruzioni devono comportarsi come segue: FOR Ri, Rx, Ry Rx e R29 Rx (indici per il ciclo for) Ri R30 Ry (il significato di Ry è spiegato nell’istruzione NEXT. Si suppone che valga la relazione Rx < Ry e che Rx ≥ 0) PC + 4 (indirizzo dell’istruzione successiva all’istruzione FOR) R31 NEXT Ri, IMM Ri Ri + IMM (IMM è un operando immediato senza segno) R29 R29 + 1 Confronta il valore di R29 aggiornato col valore di R30. Se (R29 ≥ R30) allora l’esecuzione del programma continua con l’istruzione che segue l’istruzione NEXT. Se (R29 < R30) allora la prossima istruzione da eseguire sarà l’istruzione successiva all’istruzione FOR (l’indirizzo di tale istruzione si trova già in R31). NB: Si suppone inoltre che le istruzioni presenti tra un’istruzione FOR e la corrispondente NEXT non modifichino i registri Ri, R29, R30 e R31. Si indichi una possibile codifica binaria nel linguaggio macchina del DLX delle due nuove istruzioni. Per l’istruzione FOR serve il formato con tre registri, cioè il formato R. FOR Rx Ry Ri Op. code

Per l’istruzione NEXT serve un formato che abbia l’operando immediato, cioè il formato I. NEXT Ri R29 IMMEDIATE

Con riferimento all’implementazione sequenziale del DLX, si disegni il diagramma degli stati delle istruzioni FOR e NEXT. FOR IR A B PC + 4* Rx Ry M[PC] (c’è Rx) (c’è Ry) (incremento contatore) C A

PC

Ri Ri R29 C R29 R30 C R30 R31 R31

C Rx C B Rx C PC Ry C PC + 4*

NEXT IR A B PC C M[PC] Ri R29 PC + 4

A + (0)16 ## IR15…0 Ri Ri C R29 R29 A B C Ri + IMM C B + 1 R29 + 1 C R29 R30

((R29

≥ R30)

A – B A R31 per C maggiore o uguale a zero, salta a dopo la NEXT)

PC A Se (R29 < R30) allora la prossima istruzione da eseguire sarà l’istruzione successiva all’istruzione FOR (l’indirizzo di tale istruzione si trova già in R31) Considerando il frammento di codice riportato all’inizio del testo, si mostri con un esempio quale risultato si ottiene dall’esecuzione di detto codice. ADDI FOR R4, R0, 4 R1, R0, R4 Si inizializza R4 a 4 Viene invocata la FOR con parametri R1, R0, R4. 0 viene messo in Ri. 0 viene messo in R29. R4 (= 4) viene messo in R30. In R31 viene messo l’indirizzo dell’istruzione successiva al FOR. In R4 viene messo M[R1+1000H] Viene caricato in M[R1+2000H] il valore appena spostato. Viene invocata la NEXT con parametri R1 e 4. R1 viene incrementato di 4. In R29 viene aggiunto 1 (quindi si va a 0+1 = 1).

LW SW NEXT

R4, 1000H(R1) 2000H(R1), R4 R1, 4

Si confronta R29 con R30: se sono uguali, o se R29 è maggiore, si salta a dopo NEXT. Altrimenti si ricomincia dalla LW. Vengono in pratica all’indirizzo 2000H. spostate 4 word (4 x 4 byte) dall’indirizzo 1000H

Si indichi il numero di periodi di clock necessari ad eseguire le istruzioni nell’ipotesi che la memoria richieda 2 stati di wait per ogni accesso. FOR = 7 + wait = 9 NEXT = (taken) 8 + wait = 10 (not-taken) 7 + wait = 9 Nelle ipotesi del punto 4, supponendo una frequenza di clock di 100 Mhz, quale valore occorre assegnare ad N affinché l’esecuzione del frammento di codice che segue avvenga in un tempo il più prossimo possibile a 20 nsec. ADDI FOR NEXT R3, R0, N R1, R0, R3 R1, 1

ESERCIZIO 1 Come si potrebbe codificare l’istruzione utilizzando uno dei tre formati che ci mette a disposizione il DLX? Non è difficile accorgersi che, nella nuova istruzione, fanno la loro comparsa 3 registri: Rx, Ry, Rz. Dunque, l’unica codifica possibile è quella di tipo R: LBUR Ry Rz Rx LBUR

L’istruzione che abbiamo definito trasferisce in Rx il dato di tipo unsigned-byte situato all’indirizzo di memoria ottenuto sommando i registri Ry e Rz. FETCH: DECODE: IR PC A B MAR MDR C WRITE BACK: RD M[PC] PC + 4 RS1 (che sarebbe Ry) RS2 (che sarebbe Rz) A+B M[MAR] MDR0..7 ## (0)24 C accesso in memoria (wait) si inserisce tutto in C stati di wait

MEMORY:

Vengono utilizzati 6 + altri 2 aggiuntivi dovuti agli accessi alla memoria Nell’ipotesi di voler aggiungere all’indirizzo di memoria usato dall’istruzione LBUR anche una costante con segno (cioè accedere alla cella M[Ry + Rz + IMMEDIATE]) e si indichi come dev’essere modificata la codifica precedente. Quale ulteriore accorgimento dovrebbe essere adottato nella codifica per rendere la LBUR distinguibile senza ambiguità dalle altre istruzioni codificate nello stesso formato. LBUR Ry Rz Rx IMMEDIATE

Ad IMMEDIATE vengono riservati 11 bit, quindi può essere codificato con un range di [-1024, 1023]. Per poter distinguere questa codifica dalle altre senza generare confusione, l’unico campo che può essere modificato è quello del codice operativo LBUR. Si deve infatti modificare affinché sia diverso da quello di tutte le altre istruzioni di tipo R. ESERCIZIO 2 Si consideri la seguente sequenza di istruzioni del DLX ADDI LBU LB SB ADDI R1, R0, 400H R2, 0(R1) R3, 0(R2) 0(R1), R3 R1, R1, 1

CICLO:

SLTI R2, R1, 500H BNEZ R2, CICLO Si indichi il numero totale di cicli di bus relativo rispettivamente al “fetch” e all’esecuzione delle istruzioni. Anzitutto esaminiamo il codice: ADDI LBU LB SB ADDI SLTI R1, R0, 400H R2, 0(R1) R3, 0(R2) 0(R1), R3 R1, R1, 1 R2, R1, 500H R1 viene a messo 400H (cioè 1024) Viene messo in R2 il contenuto di M[R1] Viene messo in R3 il contenuto di M[R2] Viene messo in R1 il contenuto di M[R3] R1 viene incrementato di 1 Se R1 è < 500H (cioè 1280) allora R2 viene messo a 1, altrimenti a 0 Se R2 è diverso da zero ciclo

CICLO:

BNEZ R2, CICLO

Dunque questo mini-programmino assembler mette 400H In R1 in R2 in R3 Poi R1 viene incrementato di uno e si controlla se è minore di 500H: in tal caso si ricomincia da CICLO. Si esegue dunque il blocco CICLO (di 6 istruzioni) 1280 – 1024 = 256 volte; per questo motivo la fase di fetch viene invocata 1 (per la prima ADDI) + 256 ⋅ 6 = 1537 volte. Questo numero è pari a quello delle volte in cui dev’essere invocato il ciclo di BUS relativo al Fetch (1 volta/istruzione). Per quanto riguarda l’esecuzione delle istruzioni, solo le prime 3 (in rosso) prevedono l’accesso alla memoria: quindi il numero totale di accessi è di 256 ⋅ 3 = 768. Si consideri la struttura sequenziale del DLX ed, ipotizzando che tutti gli accessi in memoria siano completati in 2 clock, si calcolino il numero totale di cicli di clock necessario all’esecuzione della sequenza ed il CPI-medio. Vengono fatte: 256 + 1 256 ⋅ 2 256 256 255 1 ALU (6 clock ciascuna) LOAD (6+2 clock ciascuna) STORE (5+2 clock ciascuna) SET (5 clock ciascuna) BRANCH (not-taken) (3+2 clock ciascuna) BRANCH (taken) (4 clock)

Il numero totale di periodi di clock è quindi 10501. Il CPI medio, di conseguenza, risulta pari a 10501/1537 = 6,83

ESERCIZIO 1 Si supponga di voler estendere il set di istruzioni del DLX con l’istruzione: BNEQ++ (Rx), (Ry), IMMEDIATE Dove gli operandi Rx, Ry rappresentano due registri generali ed IMMEDIATE è una costante signed a 16 bit. L’istruzione confronta la word situata in memoria all’indirizzo Rx con la word situata in memoria all’indirizzo Ry: se i valori risultano diversi somma la costante IMMEDIATE al valore corrente del PC. Inoltre, indipendentemente dall’esito del confronto, l’istruzione incrementa il registro Ry (sommando il valore +4). Una possibile descrizione RTL delle operazioni svolte dalla nuova istruzione è data da If Ry (M[Rx] ≠ M[Ry) Ry + 4 then PC PC + IMMEDIATE

Si mostri come potrebbe essere codificata la nuova istruzione utilizzando il più idoneo fra i 3 formati delle istruzioni DLX. Il formato più idoneo è quello di tipo I, perché abbiamo a disposizione lo spazio per due registri e per l’operando immediato. BNEQ++ Rx Ry IMMEDIATE

Con riferimento al datapath del DLX sequenziale visto a lezione si disegni il diagramma degli stati che controlla l’esecuzione della nuova istruzione inserendo anche gli stati necessari al fetch ed alla decodifica. 1) FETCH 2) DECODE IR M[PC] Accesso in memoria (le solite due fasi)

PC PC + 4 A RS1 (Rx) B RS2 (Ry) MAR B (Ry)

3) MEMORY 4)

MDR M[MAR] C MAR + 4

Accesso in memoria Approfittiamone per farlo (bisogna effettuare questa operazione in ogni caso) Ry (com’era all’inizio) è in TEMP, mentre l’Ry aggiornato viene deposto in B Ora è necessario andare a prendere l’altro registro per effettuare il confronto L’accesso (solito) in memoria Ora possiamo effettuare il confronto

5)

TEMP MDR RS2 C MAR A

6)

7) 8)

MDR

M[MAR]

MDR != TEMP

SE è TRUE 9a) SE è FALSE --)

PC

PC + (IR15)16 ## (IR15..0) Aggiorniamo il PC con l’immediato (16 bit)

Si torna daccapo

Nell’ipotesi che tutti gli accessi alla memoria possano essere completati in 2 clock, si calcoli il numero di cicli di clock (CPI) necessari per l’esecuzione dell’istruzione. CASO Branch-TAKEN (risposta TRUE al punto 8) CPI = 6 + 2 (IF) + 2 (MEM1) + 2 (MEM2) = 12 CASO Branch-NOT-TAKEN (risposta FALSE al punto 8) CPI = [caso precedente] – 1 = 11 Utilizzando la nuova istruzione BNEQ++ si scriva un frammento di codice assembler DLX che, dato un vettore V1 di 10 word (32 bit) memorizzato a partire dell’indirizzo 200H ed una variabile alfa memorizzata all’indirizzo 4000H, ritorna nel registro R1 il numero di elementi di V1 che risultano uguali ad alfa e memorizza in ordine crescente in un secondo vettore (V2, adiacente al primo in memoria) gli indirizzi di tali elementi. ADD R1, R0, R0 ADDI R2, R0, 200H ADDI R3, R0, 228H Inizializziamo R1: è il contatore degli elementi uguali ad alfa Inizializziamo R2 a 200H (dove inizia V1) Inizializziamo R3 a 228H (distante 40 celle da 8 bit da 200H, ovvero le celle dove contenere le 10 word). Qui inizia il secondo vettore, che è adiacente al primo. Mettiamo in R4 l’indirizzo della variabile alfa Se V[i] è diverso da alfa, vai a SKIP Aggiungiamo 1 ad R1: abbiamo trovato una word uguale ad alfa Mettiamo, in R5, R2 – 4; esso è l’indice di V1 aggiornato Memorizziamo nel secondo vettore (R3 ne è l’indice) l’indirizzo di V1 aggiornato. Incrementiamo l’indice di V2 (sempre R3) Se R2 è uguale a 228H, allora metti R5 a 1 R5 è uguale a zero? Vuol dire che non abbiamo finito di scorrere il vettore: si ritorna a loop.

ADDI R4, R0, 4000H LOOP: BNEQ++ (R4), (R2), SKIP ADDI R1, R1, 1 SUBI R5, R2, 4 SW 0(R3), R5

SKIP:

ADDI R3, R3, 4 SEQI R5, R2, 228H BEQZ R5, LOOP

Sempre con riferimento al DLX sequenziale si calcoli il CPI medio del codice scritto al punto precedente nell’ipotesi che il numero di elementi di V1 che risultano uguali ad alfa sia pari all’ultima cifra del proprio numero di matricola. Per l’istruzione BNEQ++ si utilizzi il CPI precedentemente calcolato e per le altre istruzioni i valori visti a lezione e deducibili dai diagrammi degli stati del controllo (si mantenga l’ipotesi che ogni accesso alla memoria richieda 2 clock). IPOTESI: Numero di elementi di V1 uguali ad alfa = 7 [ultima cifra del numero di matricola].

Dividiamo il codice in tre fasi: 1) INIZIALIZZAZIONE (4 istruzioni) Si tratta di 4 ALU 4 + 2 (wait) 2) UGUALE AD ALFA (5 istruzioni) Ci sono 3 ALU 4 + 2 (wait) C’è una STORE 3 + 2 + 2 (wait) La BNEQ++ TAKEN NOT-TAKEN

24 clock

18 clock 7 clock 12 clock 11 clock

3) FINALE / DIVERSO DA ALFA (2 istruzioni) C’è la SET 4 + 2 (wait) 6 clock Infine, la BRANCH TAKEN 5 clock NOT-TAKEN 4 clock L’inizializzazione si fa una volta sola. Poi, se si verifica che l’elemento del vettore è uguale ad alfa allora si fanno sia la fase 2 (con la BNEQ++ “Not-taken”) che la fase 3. Altrimenti si fa solo la BNEQ++ “Taken” e la 3. La BRANCH finale si fa sempre not-taken tranne l’ultima volta. Per 7 volte ci troviamo nella prima situazione, per 3 volte nella seconda. Numero totale di clock: 24 + (3 x [12+6+5+4]) + (7 x [11 + 7 + 18 + 6 + 5]) – 1 = 433 (il -1 è per l’ultima branch, che è not-taken). Numero totale di operazioni: 4 + (3 x 3) + (7 x 7) = 62 CPI MEDIO = 433/62 = 6,78

ESERCIZIO 1 Si supponga di voler estendere il set di istruzioni del DLX con l’istruzione: BNEQ++ (Rx), (Ry), IMMEDIATE Dove gli operandi Rx, Ry rappresentano due registri generali ed IMMEDIATE è una costante signed a 16 bit. L’istruzione confronta la word situata in memoria all’indirizzo Rx con la word situata in memoria all’indirizzo Ry: se i valori risultano diversi somma la costante IMMEDIATE al valore corrente del PC. Inoltre, indipendentemente dall’esito del confronto, l’istruzione incrementa il registro Ry (sommando il valore +4). Una possibile descrizione RTL delle operazioni svolte dalla nuova istruzione è data da If Ry (M[Rx] ≠ M[Ry) Ry + 4 then PC PC + IMMEDIATE

Si mostri come potrebbe essere codificata la nuova istruzione utilizzando il più idoneo fra i 3 formati delle istruzioni DLX. Il formato più idoneo è quello di tipo I, perché abbiamo a disposizione lo spazio per due registri e per l’operando immediato. BNEQ++ Rx Ry IMMEDIATE

Con riferimento al datapath del DLX sequenziale visto a lezione si disegni il diagramma degli stati che controlla l’esecuzione della nuova istruzione inserendo anche gli stati necessari al fetch ed alla decodifica. 1) FETCH 2) DECODE IR M[PC] Accesso in memoria (le solite due fasi)

PC PC + 4 A RS1 (Rx) B RS2 (Ry) MAR B (Ry)

3) MEMORY 4)

MDR M[MAR] C MAR + 4

Accesso in memoria Approfittiamone per farlo (bisogna effettuare questa operazione in ogni caso) Ry (com’era all’inizio) è in TEMP, mentre l’Ry aggiornato viene deposto in B Ora è necessario andare a prendere l’altro registro per effettuare il confronto L’accesso (solito) in memoria Ora possiamo effettuare il confronto

5)

TEMP MDR RS2 C MAR A

6)

7) 8)

MDR

M[MAR]

MDR != TEMP

SE è TRUE 9a) SE è FALSE --)

PC

PC + (IR15)16 ## (IR15..0) Aggiorniamo il PC con l’immediato (16 bit)

Si torna daccapo

Nell’ipotesi che tutti gli accessi alla memoria possano essere completati in 2 clock, si calcoli il numero di cicli di clock (CPI) necessari per l’esecuzione dell’istruzione. CASO Branch-TAKEN (risposta TRUE al punto 8) CPI = 6 + 2 (IF) + 2 (MEM1) + 2 (MEM2) = 12 CASO Branch-NOT-TAKEN (risposta FALSE al punto 8) CPI = [caso precedente] – 1 = 11 Utilizzando la nuova istruzione BNEQ++ si scriva un frammento di codice assembler DLX che, dato un vettore V1 di 10 word (32 bit) memorizzato a partire dell’indirizzo 200H ed una variabile alfa memorizzata all’indirizzo 4000H, ritorna nel registro R1 il numero di elementi di V1 che risultano uguali ad alfa e memorizza in ordine crescente in un secondo vettore (V2, adiacente al primo in memoria) gli indirizzi di tali elementi. ADD R1, R0, R0 ADDI R2, R0, 200H ADDI R3, R0, 228H Inizializziamo R1: è il contatore degli elementi uguali ad alfa Inizializziamo R2 a 200H (dove inizia V1) Inizializziamo R3 a 228H (distante 40 celle da 8 bit da 200H, ovvero le celle dove contenere le 10 word). Qui inizia il secondo vettore, che è adiacente al primo. Mettiamo in R4 l’indirizzo della variabile alfa Se V[i] è diverso da alfa, vai a SKIP Aggiungiamo 1 ad R1: abbiamo trovato una word uguale ad alfa Mettiamo, in R5, R2 – 4; esso è l’indice di V1 aggiornato Memorizziamo nel secondo vettore (R3 ne è l’indice) l’indirizzo di V1 aggiornato. Incrementiamo l’indice di V2 (sempre R3) Se R2 è uguale a 228H, allora metti R5 a 1 R5 è uguale a zero? Vuol dire che non abbiamo finito di scorrere il vettore: si ritorna a loop.

ADDI R4, R0, 4000H LOOP: BNEQ++ (R4), (R2), SKIP ADDI R1, R1, 1 SUBI R5, R2, 4 SW 0(R3), R5

SKIP:

ADDI R3, R3, 4 SEQI R5, R2, 228H BEQZ R5, LOOP

Sempre con riferimento al DLX sequenziale si calcoli il CPI medio del codice scritto al punto precedente nell’ipotesi che il numero di elementi di V1 che risultano uguali ad alfa sia pari all’ultima cifra del proprio numero di matricola. Per l’istruzione BNEQ++ si utilizzi il CPI precedentemente calcolato e per le altre istruzioni i valori visti a lezione e deducibili dai diagrammi degli stati del controllo (si mantenga l’ipotesi che ogni accesso alla memoria richieda 2 clock). IPOTESI: Numero di elementi di V1 uguali ad alfa = 7 [ultima cifra del numero di matricola].

Dividiamo il codice in tre fasi: 1) INIZIALIZZAZIONE (4 istruzioni) Si tratta di 4 ALU 4 + 2 (wait) 2) UGUALE AD ALFA (5 istruzioni) Ci sono 3 ALU 4 + 2 (wait) C’è una STORE 3 + 2 + 2 (wait) La BNEQ++ TAKEN NOT-TAKEN

24 clock

18 clock 7 clock 12 clock 11 clock

3) FINALE / DIVERSO DA ALFA (2 istruzioni) C’è la SET 4 + 2 (wait) 6 clock Infine, la BRANCH TAKEN 5 clock NOT-TAKEN 4 clock L’inizializzazione si fa una volta sola. Poi, se si verifica che l’elemento del vettore è uguale ad alfa allora si fanno sia la fase 2 (con la BNEQ++ “Not-taken”) che la fase 3. Altrimenti si fa solo la BNEQ++ “Taken” e la 3. La BRANCH finale si fa sempre not-taken tranne l’ultima volta. Per 7 volte ci troviamo nella prima situazione, per 3 volte nella seconda. Numero totale di clock: 24 + (3 x [12+6+5+4]) + (7 x [11 + 7 + 18 + 6 + 5]) – 1 = 433 (il -1 è per l’ultima branch, che è not-taken). Numero totale di operazioni: 4 + (3 x 3) + (7 x 7) = 62 CPI MEDIO = 433/62 = 6,78

ESERCIZIO 1
Si supponga di voler estendere il set di istruzioni del DLX con l’istruzione: SCANVW Rx, Ry, Rz

Dove gli operandi Rx, Ry, Rz, rappresentano tre registri generali. L’istruzione confronta la word situata in memoria all’indirizzo Rx con il valore di Ry: se i valori risultano uguali il registro Rz viene posto a 1, viceversa viene posto a 0. Effettuato il confronto, l’istruzione incrementa il registro Rx (sommando il valore +4). Una possibile descrizione RTL delle operazioni svolta dalla nuova istruzione è data da: if (M[Rx] = Ry) then Rz 1 else Rz 0 Rx Rx + 4 Si mostri come potrebbe essere codificata la nuova istruzione utilizzando il più idoneo fra i tre formati delle istruzioni del DLX. Senza troppo scervellarci: ci sono tre registri, dunque la codifica appropriata è quella di tipo R. SCANWV Rx,Ry,Rz Ry Rx Rz … Con riferimento al datapath del DLX sequenziale (cioè non-pipelined) visto a lezione si disegni il diagramma degli stati che controlla l’esecuzione della nuova istruzione inserendo anche gli stati necessari al fetch e alla decodifica. FETCH DECODE IR A B PC MAR M[PC] RS1 (Ry) RS2 (Rx) PC + 4 B (mettiamo in MAR l’indirizzo del registro da confrontare) (stati di wait) (confronto: e qui discriminiamo) NO C 0 (stati di wait)

MDR

M[MAR]

MDR == A ? SI C RD RS2 C 1 B + 4 C C

(dobbiamo incrementare Rx)

Nell’ipotesi che tutti gli accessi alla memoria possano essere completati in 3 clock, si calcoli il numero di cicli di clock (CPI) necessari per l’esecuzione delle istruzioni. CPI = 6 + 3 (FETCH) + 3 (MEMORY) = 12 Utilizzando la nuova istruzione SCANVW si scriva un frammento di codice assmebler DLX che, dato un vettore di 256 word (32 bit) memorizzato a partire dall’indirizzo 0000 0400H, ritorna nel registro R1 l’indirizzo di memoria del primo elemento del vettore che risulta uguale a 100 (se nessun elemento del vettore è uguale a 100 in R1 deve essere ritornato il valore 0).

Inizializziamo la variabile R2 (indirizzo del vettore) Valore confrontando Contatore delle iterazioni Usiamo l’istruzione SCANVW Se l’elemento è uguale a = R3 allora salta alla label FOUND Decremento del contatore delle iterazioni Se il contatore delle iterazioni è diverso da 0, salta a NEXT Se arriviamo qui significa che nessun elemento del vettore è R3, quindi azzeriamo R2 Se abbiamo trovato un elemento = 100 allora R1 = indirizzo di tale elemento. Altrimenti R1 = 0 Quindi: R2 R3 R4 400H 100 256

ADDI ADDI ADDI SCANWV

R2, R0, 0400H R3, R0, 100 R4, R0, 256 R3, R2, R1 (NEXT)

BNEZ

R1, FOUND

SUBI

R4, R4, 1

BNEZ

R4, NEXT

ADDI

R2, R0, 4

SUBI

R1, R2, 4

(FOUND)

M[400H] è = 100 ? Se sì R1 1 Altrimenti R1 In ogni caso R2 404H

(NEXT) 0

R1 è diverso da 0 (abbiamo trovato un valore = 100)? Se sì, salta a FOUND Altrimenti prosegui. R4 255

R4 è diverso da 0 (abbiamo finito)? Se no, torna a NEXT. Altrimenti, prosegui. Nessun elemento del vettore è = 3. Dunque R2 Abbiamo trovato un elemento = 100 R1 404H – 4H = 400H 4 (FOUND)

Sempre con riferimento al DLX sequenziale (cioè non-pipelined), si calcoli il CPI medio del codice scritto al punto precedente nell’ipotesi che l’unico elemento del vettore che risulta uguale a 100 sia il decimo (cioè quello di indice 9). Per l’istruzione SCANVW si utilizzi il CPI precedentemente calcolato e per le altre istruzioni i valori visti a lezione e deducibili dai diagrammi degli stati del controllo (si mantenga l’ipotesi che ogni accesso alla memoria richieda 3 clock). L’inizializzazione consiste in 3 ALU L’unico elemento = 100 è il decimo, inizializzazione vengono eseguiti 9 da SCANVW alla BNEZ-R4 (con BNEZ-R1 (4 + 3 = 7 clock ciascuna). quindi dopo queste prime tre istruzioni di loop costituiti dalle istruzioni che vanno not-taken e BNEZ-R4 taken). La decima volta

si fa invece dalla SCANVW alla successiva BNEZ-R1 (taken), quindi si salta alla FOUND. QUINDI 9 volte: SCANVW BNEZ-R1 (n.t.) SUBI BNEZ-R4 (t.) 1 volta: SCANVW BNEZ-R1 (t.) FOUND (SUBI)

12 clock 5 clock 7 clock 6 clock

12 clock 6 clock 7 clock

NUMERO TOTALE DI ISTRUZIONI: 3 (init) + 4 x 9 + 2 x 1 + 1 = 42 NUMERO TOTALE DI CLOCK: 13 x 7 (ALU) + 10 x 12 (SCANVW) + 10 x 6 (BRANCH TAKEN) + 9 x 5 (B. NOT TAKEN) = 316 CPI medio: 316 / 42 = 7,5 circa

ESERCIZIO 1 Si supponga di voler estendere il Set di Istruzioni del DLX con la seguente istruzione NEG IMMEDIATE(Rx) Dove Rx è un registro generale ed IMMEDIATE è una costante di 16 bit con segno. L’istruzione deve eseguire il cambiamento del segno della word (32 bit) situata all’indirizzo di memoria Rx + IMMEDIATE. Si mostri come potrebbe essere codificata la nuova istruzione utilizzando uno dei 3 formati delle istruzioni DLX. C’è soltanto un registro sufficiente la codifica I: NEG di cui tenere conto (Rx), dunque è largamente

Rx

indifferente

IMMEDIATE (16 bit)

Con riferimento al datapath del DLX sequenziale (cioè non-pipelined) visto a lezione si disegni il diagramma degli stati che controlla l’esecuzione della nuova istruzione inserendo anche gli stati necessari al fetch ed alla decodifica. IR A B PC MAR MDR MDR M[MAR] M[PC] RS1 (Rx) RS2 (nulla) PC + 4 A + (IR15)16 ## IR15..0 M[MAR] 0 – MDR MDR (sommiamo A all’operando immediato) (stati di wait)

(stati di wait) (creiamo in questo modo il complemento a due) (stati di wait, depositiamo il nuovo valore dove stava prima)

Nell’ipotesi che tutti gli accessi alla memoria possano essere completati in 2 clock, si calcoli il numero di cicli di clock (CPI) necessari per l’esecuzione dell’istruzione. CPI: 3 + 2 (fetch) + 2 (primo accesso in memoria) + 2 (secondo accesso) = 9 ESERCIZIO 2 Si consideri il codice della seguente procedura in Assembler DLX. PROC: LOOP: SUBUI SW NEG ADDI SUBI BNEZ LW ADDUI JR R30, R30, 4 0(R30), R31 0(R1) R1, R1, 4 R2, R2, 1 R2, LOOP R31, 0(R30) R30, R30, 4 R31

Che fa uso dell’istruzione NEG definite nell’esercizio precedente.

Si spieghi procedura.

in

modo

preciso

e

sintetico

qual

è

l’operazione

svolta

dalla

Si sottrae 4 dal registro R30 Si deposita R31 in R30 Viene cambiato di segno di ciò che c’è nel registro R1 Viene aggiunto 4 ad R1 (si cerca la prossima word) Viene sottratto 1 da R2 R2 è uguale a zero? Se sì torna a LOOP, sennò prosegui. Viene messo in R31 ciò che viene preso in R30 Si aggiunge 4 ad R30 Si salta ad R31

R30 R30

R30 - 4 R31

( LOOP) R1 -R1 R1 R1 + 4 R2 R2 - 1

R31 R30 R30 R30 + 4 Salta

Cosa fa questo benedetto programmino? All’interno del loop (eseguito R2 volte) cambia segno a ciò che c’è nel registro R1 poi, a scalare, negli altri elementi del vettore che parte – appunto – da R1. Si consideri la struttura sequenziale del DLX. Ipotizzando che tutti gli accessi in memoria siano completati in 2 clock e che prima di trasferire il controllo alla procedura il registro R2 sia stato posto al valore 1000, si calcolino il numero totale di cicli di clock necessario per l’esecuzione della procedura ed il relativo CPImedio. Se R2 è stato posto a 1000 significa che il LOOP (testo in verde) verrà eseguito 1000 volte. Il numero totale di istruzioni è dunque: 2 (inizializzazione) + 4 x 1000 (loop) + 3 (fine) = 4005 ISTRUZIONI TIPO DI ISTRUZIONE Load Store Alu Jump Branch (taken) Branch (not-taken) Neg QUANTE E QUANDO 1 (fine) 1 (init) 1 (init) + 2000 (loop) + 1 (fine) 1 (fine) 999 (loop) 1 (loop) 1000 (loop) CLOCK 8 7 6 4 5 4 9

TOTALE = 8 + 7 + 6 x 2002 + 4 + 5 x 999 + 4 + 9 x 1000 = 20630 CPI medio = 26030 / 4005 = 6,5 Si mostri come dovrebbe essere modificato il codice della procedura al fine di garantire che essa non alteri il contesto del chiamante (cioè non modifichi alcun registro ad eccezione di quelli eventualmente utilizzati per restituire dei risultati). Cosa bisogna fare? Prima di entrare nel loop è necessario salvare i valori dei registri R1 ed R2, perché durante la procedura questi verranno modificati. Poi, all’uscita dal loop, dovranno essere ripristinati. Dobbiamo quindi introdurre una SW preceduta da una SUBUI (all’inizio) e una LW seguita da una ADDUI (alla fine), in più.

PROC:

LOOP:

SUBUI SW SUBUI SW NEG ADDI SUBI BNEZ LW ADDUI LW ADDUI JR

R30, R30, 4 0(R30), R31 R30, R30, 4 0(R30), R2 0(R1) R1, R1, 4 R2, R2, 1 R2, LOOP R31, 0(R30) R30, R30, 4 R31, 0(R30) R30, R30, 4 R31

ESERCIZIO 1 Si supponga di voler estendere il Set di Istruzioni del DLX con la seguente istruzione: ADDM IMMEDIATE(Rx), Ry Dove Rx, Ry sono due registri generali e IMMEDIATE è una costante a 16 bit con segno. L’istruzione deve eseguire la somma fra la word (32 bit) situata all’indirizzo di memoria Rx + IMMEDIATE ed il registro Ry e poi scrivere il risultato nuovamente all’indirizzo di memoria Rx + IMMEDIATE (cioè, in notazione RTL, eseguire l’operazione: M[Rx + IMMEDIATE] M[Rx + IMMEDIATE] + Ry

Si mostri come potrebbe essere codificata la nuova istruzione utilizzando uno dei tre formati delle istruzioni DLX. Usiamo, in virtù della presenza dei due registri, il formato I. ADDM Rx Ry IMMEDIATE (16 bit)

Con riferimento al datapath del DLX sequenziale (non-pipelined) visto a lezione si disegni il diagramma degli stati che controlla l’esecuzione della nuova istruzione inserendo anche gli stati necessari al fetch ed alla decodifica. IR A B PC MAR MDR MDR M[MAR] M[PC] RS1 (Rx) RS2 (Ry) PC + 4 A + (IR15)16 ## IR15..0 M[MAR] MDR + B MDR (fase di FETCH, stati di wait) (fase di DECODE)

(aggiungiamo l’IMMEDIATE) (stati di wait) (aggiungiamo Ry) (stati di wait)

Nell’ipotesi che tutti gli accessi alla memoria possano essere completati in 3 clock, si calcoli il numero di cicli di clock (CPI) necessari per l’esecuzione dell’istruzione. Numero di clock: 3 + 3 (fetch) + 3 (memory 1) + 3 (memory 2) = 12 ESERCIZIO 2 Si consideri la seguente sequenza di istruzioni DLX ADDI LW LW ADD SW ADDI SLTI BNEZ R1, R0, R0 R2, V1(R1) R3, V2(R1) R2, R2, R3 V1(R1), R2 R1, R1, 4 R2, R1, 1000H R2, CICLO

CICLO:

Dove V1 e V2 sono due costanti che rappresentano gli indirizzi di base (cioè l’indirizzo del primo elemento) di due vettori di word (32 bit).

Cosa fa questo codice? ADDI R1, R0, R0 CICLO: LW R2, V1(R1) LW R3, V2(R1) ADD R2, R2, R3 SW V1(R1), R2 ADDI R1, R1, 4 SLTI R2, R1, 1000H BNEZ R2, CICLO Inizializziamo R1 a 0 Si carica in R2 il valore in V1[R1] Si carica in R3 il valore in V2[R1] Si somma: R2 R2 + R3 Si mette R2 in V1[R1] Togli 4 da R1 Se R1 < 1000H allora R2 1 (0 altrimenti) Se R2 non è uguale a zero, vai a CICLO

Il programma scorre due vettori (V1 e V2), somma fra loro gli elementi V1[i]+V2[i], poi si pone il risultato in posizione V1[i]. Si compie questa operazione 400H = 1024 volte. Si consideri la struttura sequenziale del DLX ed, ipotizzando che tutti gli accessi in memoria siano completati in 3 clock, si calcolino il numero totale di cicli di clock necessario per l’esecuzione della sequenza ed il CPI medio. TIPO DI ISTRUZIONE ALU LOAD STORE SET BRANCH (taken) BRANCH (not-taken) QUANTE E QUANDO 1 (init.) + 1024 x 2 (ciclo) 1024 x 2 (ciclo) 1024 x 1 (ciclo) 1024 x 1 (ciclo) 1023 x 1 (ciclo) 1 (ciclo) CLOCK 7 10 9 8 6 5

N° DI ISTRUZIONI ESEGUITE IN TOTALE: 1 + (1024 x 7) = 7169 N° CLOCK IN TOTALE: 2049 x 7 + 2048 x 10 + 1024 x 9 + 1024 x 8 + 6 x 1023 + 5 = 58374 CPI medio = 58374 / 7169 = 8,14 Si riscriva la precedente sequenza di istruzioni impiegando l’istruzione ADDM IMMEDIATE(Rx), Ry definita nell’Esercizio 1 al fine di sommare gli elementi corrispondenti dei due lettori V1 e V2. ADDI R1, R0, R0 CICLO: LW R2, V1(R1) ADDM V1(R1), R2 ADDI R1, R1, 4 SLTI R2, R1, 1000H BNEZ R2, CICLO Inizializziamo R1 a 0 Si carica in R2 il valore in V1[R1] 1 istruzione al posto di tre Togli 4 da R1 Se R1 < 1000H allora R2 1 (0 altrimenti) Se R2 non è uguale a zero, vai a CICLO

Sempre considerando la struttura sequenziale del DLX ed ipotizzando che tutti gli accessi in memoria siano completati in 3 clock, si calcolino per la nuova sequenza il numero totale di cicli di clock necessario per l’esecuzione ed il CPI medio. TIPO DI ISTRUZIONE ALU LOAD ADDM SET BRANCH (taken) BRANCH (not-taken) QUANTE E QUANDO 1 (init.) + 1024 x 1 (ciclo) 1024 x 1 (ciclo) 1024 x 1 (ciclo) 1024 x 1 (ciclo) 1023 x 1 (ciclo) 1 (ciclo) CLOCK 7 10 12 8 6 5

N° DI ISTRUZIONI ESEGUITE IN TOTALE: 1 + (1024 x 5) = 5121 N° CLOCK IN TOTALE: 1025 x 7 + 1024 x 10 + 1024 x 12 + 1024 x 8 + 6 x 1023 + 5 = 44038

CPI medio = 44038 / 5121 = 8,59 Come si nota, il CPI medio si è alzato. Tuttavia, ciò non significa che il nuovo codice sia più lento: abbiamo infatti un risparmio totale di 14336 cicli di clock. Considerando sia la struttura sequenziale sia quella “pipelined”, si discutano vantaggi e svantaggi dell’eventuale introduzione nell’ISA DLX della nuova istruzione ADDM IMMEDIATE(Rx), Ry. Semplicemente, non possiamo eseguire tale programma sulla pipeline a 5 stadi del DLX: la nuova istruzione è di tipo CISC.

ESERCIZIO 1 Si scriva in Assembler DLX una procedura che calcola il massimo di un vettore di unsigned word (32 bit). La procedura deve ricevere come parametri di ingresso l’indirizzo del vettore sul registro R1 e la dimensione del vettore (cioè il numero dei suoi elementi) sul registro R2. La procedura deve restituire il massimo del vettore sul registro R3. PROC: LOOP: ADD LW SGTU BEQZ ADD ADDI SUBI BNEZ JR R3, R0, R0 R4, 0(R1) R5, R4, R3 R5, SKIP R3, R4, R0 R1, R1, 4 R2, R2, 1 R2, LOOP R31 Inizializziamo R3: qua dentro ci finirà il massimo appena lo troveremo all’interno del vettore. Carichiamo ciò che c’è in R1 su R4. Se R4 > R3 allora R5 = 1 (se, cioè, abbiamo trovato un massimo, altrimenti R5 = 0. Non abbiamo trovato un nuovo massimo. Salta. Aggiornamento di R3 col nuovo massimo. Si prosegue nel vettore (nota l’operando immediato 4, dovuto all’elaborazione di word). Decrementiamo il contatore. Se non abbiamo finito, ricominciamo da LOOP. Se abbiamo finito, ritorniamo al programma chiamante.

SKIP:

Si scriva il codice Assembler DLX necessario ad invocare la procedura scritta al punto precedente in maniera tale che essa calcoli il massimo di un vettore di 10 elementi allocato all’indirizzo 8000H. Dobbiamo mettere in R1 l’indirizzo 8000H Dobbiamo mettere il contatore a 10 Chiamiamo la procedura ADDUI ADDI JAL R1, R0, 8000H R2, R0, 10 PROC

Si faccia riferimento alla struttura pipelined del DLX (con presenza di Forwarding Unit e Register File che ritorna il nuovo valore in caso lettura e scrittura simultanee sullo stesso registro) e si assuma che i “branch” siano gestiti con politica “predict-not-taken”. Nell’ipotesi che la procedura scritta sia invocata su un vettore di 10 elementi tutti nulli, si calcoli il CPI medio relativo all’esecuzione della procedura utilizzando la formula CPI medio = 1 + s Dimensione del vettore 10 elementi Tutti gli elementi sono nulli quindi la BEQZ è sempre taken, mentre la politica adottata è quella di not-taken. Numero di istruzioni: 6 (in rosso) x 2 + 2 = 62. Ora esaminiamo gli stalli: ISTRUZIONE STALLI LW R4, 0(R1) Uno stallo solo, per ritardare la fase di execute della SGTU. BEQZ R5, SKIP Siamo nel caso predict not-taken. Siccome, in realtà, la branch è sempre taken dobbiamo introdurre ogni volta 3 stati di stallo. BNEZ R2, LOOP Nelle prima 9 operazioni è taken. Quando abbiamo terminato il nostro processo, invece, essa diventa not-taken. JR R31 Nella jump si fanno sempre 3 stalli Numero di stalli = 10 + 30 + 27 + 3 = 70 Stalli / istruzione = 70 / 62 = circa 1.13 CPI medio = 1 + 1.13 = 2.13

TOTALE STALLI 10 3 x 10 = 30

3 x 9 = 27

3

ESERCIZIO 1 Si supponga di voler estendere il set di istruzioni del DLX con l’istruzione CMPS Rx, Ry, Rz Dove gli operandi Rx, Ry, Rz rappresentano tre registri generali. L’istruzione CMPS (CoMPareString) confronta il dato di tipo unsigned byte situato in memoria all’indirizzo Rx con il dato dello stesso tipo situato in memoria agli indirizzi Ry: se i due dati risultano uguali il registro Rz viene posto a 1, altrimenti viene posto a 0. Una possibile descrizione RTL delle operazioni svolte dalla nuova istruzione è data da: if(M[Rx] = M[Ry]) then Rz 1 else Rz 0 Si mostri come potrebbe essere codificata la nuova istruzione utilizzando il più idoneo fra i formati delle istruzioni del DLX. Ci sono tre registri, dunque siamo obbligati ad usare il formato R CMPS Rx, Ry, Rz Rx Ry Rz Non importanti Rx Primo registro sorgente Ry Secondo registro sorgente Rz Registro destinazione Con riferimento al datapath del DLX sequenziale visto a lezione, si disegni il diagramma degli stati che controlla l’esecuzione della nuova istruzione inserendo anche gli stati necessari al fetch ed alla decodifica. IR A B PC MAR MDR TEMP M[PC] RS1 RS2 PC + 4 A M[MAR] (0)24 ## MDR0..7 Abbiamo messo in TEMP (dobbiamo infatti caricare l’altro valore e dobbiamo disporre di MAR e MDR liberi) ciò che c’è in M[Rx] (è un byte, quindi 8 bit). (cioè Rx) (cioè Ry)

MAR MDR

B M[MAR] In temp c’è il valore di M[Rx], in MDR quello di M[Ry] Sono uguali? Mettiamo o 1 oppure 0 in Rz

TEMP == (0)24 ## MDR0..7 Sì No RD C C C 1 0

Nell’ipotesi che tutti gli accessi alla memoria possano essere completati in 2 clock, si calcoli il numero di cicli di clock (CPI) necessari per l’esecuzione dell’istruzione. In fucsia le fasi in cui dobbiamo accedere alla memoria.

CLOCK TOTALI: 7 + 2 x 3 = 13 Utilizzando la nuova istruzione CMPS si scriva un frammento di codice assembler DLX che confronta due stringe di 100 caratteri, memorizzate rispettivamente agli indirizzi 1000H e 2000H, e ritorna nel registro R3 il risultato del confronto (R3 = 1 se le stringe sono uguali, R3 = 0 se le stringhe sono diverse). ADDI ADDI ADDI LOOP: CMPS BEQZ ADDI ADDI SUBI BNEZ SKIP: … R1, R2, R4, R1, R3, R1, R2, R4, R4, R0, 1000H R0, 2000H R0, 100 R2, R3 SKIP R1, 1 R2, 1 R4, 1 LOOP Indirizzo del primo vettore Indirizzo del secondo vettore Contatore dei caratteri Confronta gli elementi Al primo elemento diverso, si salta a SKIP Incremento del puntatore della prima stringa Incremento del puntatore della seconda stringa Decremento del contatore Controllo del prossimo elemento

Sempre con riferimento al DLX sequenziale (cioè non-pipelined), si calcoli il CPImedio del codice scritto al punto precedente nell’ipotesi che le due stringhe siano uguali. Per l’istruzione CMPS si utilizzi il CPI precedentemente calcolato e per le altre istruzioni i valori visti a lezione e deducibili dai diagrammi degli stati del controllo (si mantenga l’ipotesi che ogni accesso alla memoria richieda 2 clock). ISTRUZIONE ALU BRANCH (taken) BRANCH (not-taken) CMPS QUANDO Nell’inizializzazione (3 ALU); nel loop (300 ALU) 99 volte la BNEZ R4, LOOP 100 volte la BEQZ R3, SKIP Perché tutti gli elementi sono uguali 1 volta la BNEZ R4, LOOP Per quando avremo finito il confronto 100 volte nel loop CLOCK 303 x 6 = 1818 99 x 5 = 495 101 x 4 = 404 100 x 13 = 1300

CLOCK TOTALI = 1818 + 495 + 404 + 1300 = 4017 N° ISTRUZIONI TOTALI = 303 + 99 + 101 + 100 = 603 CPI MEDIO = 4017 / 603 = circa 6.66 ESERCIZIO 2 Con riferimento al datapath del DLX sequenziale (cioè non-pipelined) visto a lezione, si consideri la micro-operazione: MAR A

Si specifichi quelli sono i segnali di controllo che devono essere attivati dal Controller per far sì che il Datapath esegua la micro-operazione precedente. Si disegnino le forme d’onda dei segnali di controllo nell’ipotesi che il datapath esegua nel clock i la micro-operazione precedente e nel clock i+1 la micro-operazione C A + MAR

ESERCIZIO 1 Si supponga di voler estendere il set di istruzioni del DLX con l’istruzione SWAP_RM Rx, IMMEDIATE (Ry) Dove Rx, Ry rappresentano due registri generali ed IMMEDIATE una costante signed a 16 bit. La nuova istruzione scambia fra loro il contenuto del registro Rx e della word situata in memoria all’indirizzo (Ry + IMMEDIATE). Si mostri come potrebbe essere codificata la nuova istruzione utilizzando il più idoneo fra i tre formati delle istruzioni del DLX. Il formato più idoneo è quello di tipo I SWAP_RM Rx

Ry

IMMEDIATE

Con riferimento al datapath del DLX sequenziale visto a lezione si disegni il diagramma degli stati che controlla l’esecuzione della nuova istruzione inserendo anche gli stati necessari al fetch e alla decodifica. IR A B PC MAR MDR C M[PC] RS1 RS2 PC + 4 (cioè Rx) (cioè Ry) STATI DI WAIT

B + (IR15)16 ## IR15.0 M[MAR] MDR Ora in C abbiamo M[Ry+Immediate] STATI DI WAIT Mettiamo in MDR il registro Rx Mettiamo Ry in Rx MDR Mettiamo in M[Ry+Immediate] Rx STATI DI WAIT

MDR RS1 M[MAR]

A C

Nell’ipotesi che tutti gli accesi alla memoria possano essere completati in 2 clock, si calcoli il numero di cicli di clock (CPI) necessari per l’esecuzione dell’istruzione. CPI = 4 + 3 x 2 = 10 Clock Si scriva la sequenza di istruzioni appartenenti all’ISA DLX studiato a lezione che consente di eseguire un’operazione il più possibile simile a quella svolta dalla SWAP_RM Rx, IMMEDIATE(Ry). In cosa differiscono le due operazioni? ADD LW SW Rx, Rx, R0 Rx, IMMEDIATE(Ry) IMMEDIATE(Ry), Rz Salvataggio di Rx in Rz Trasferimento di memoria da M[Ry+IMMEDIATE] a Rx Trasferimento da Rz a memoria

Le due istruzioni differiscono per l’uso del registro Rz, che resta modificato al termine della sequenza. ESERCIZIO 2 Si scriva il codice assembler DLX necessario all’esecuzione operazione descritta in un linguaggio di alto livello della seguente

For (i = 0; i < 100, i++) V1[i] = V2[V1[i]] Dove V1 e V2 sono due vettori di all’indirizzo 400H ed all’indirizzo 0. ADDI ADDI LOOP: LBU LBU SW ADDI SUBI BNEZ R1, R3, R2, R2, R0, 400H R0, 100 0(R1) 0(R2) unsigned-byte allocati rispettivamente

0(R1), R2 R1, R1, 1 R3, R3, 1 R3, LOOP

Indice del vettore V1 Contatore delle iterazioni R2 è ora l’indice del vettore V1, cioè V1[i] Ora mettiamo in R2 il contenuto riferito dall’indice trovato precedentemente Mettiamo ora tutto nel primo vettore Incremento dell’indice di V1 Decremento del contatore iterazioni Se non abbiamo ancora finito, continuiamo a looppare

Con riferimento al DLX sequenziale si calcoli il CPI medio relativo all’esecuzione del codice scritto al punto precedente nell’ipotesi che ogni accesso alla memoria richieda 4 cicli di clock. Calcolo del CPI MEDIO: ISTRUZIONE QUANDO ALU 2 (inizializzazione) + 2 x 100 (ciclo) LOAD 2 x 100 (ciclo) STORE 100 (ciclo) BRANCH (taken) 99 (ciclo) BRANCH (not-taken) 1 (ciclo) CLOCK TOTALI = 1616 + 2400 + 1100 + 693 + 6 = 5815 N° ISTRUZIONI TOTALI = 202 + 200 + 100 + 99 + 1 = 602 CPI MEDIO = 5815 / 602 = 9.66 circa

CLOCK 8 x 202 = 12 x 200 = 11 x 100 = 7 x 99 = 6 x 1 =

1616 2400 1100 693 6

Sign up to vote on this title
UsefulNot useful