• Non ci sono risultati.

Università degli Studi dell’Insubria Dipartimento di Scienze Teoriche e Applicate

N/A
N/A
Protected

Academic year: 2021

Condividi "Università degli Studi dell’Insubria Dipartimento di Scienze Teoriche e Applicate"

Copied!
5
0
0

Testo completo

(1)

Università degli Studi dell’Insubria

Dipartimento di Scienze Teoriche e Applicate Architettura degli Elaboratori

Cognome e nome Matricola

Esercizio 1 (6 pts)

Qui a fianco è riportata la tabella di verità di una funzione booleana F a quattro variabili. Le X denotano input che non fanno parte del dominio di F.

(a) Scrivere un’espressione booleana, ottimizzata col metodo di Karnaugh, in prima forma canonica.

(b) Ripetere, per la seconda forma canonica.

(c) Se una porta AND (a due ingressi) costa quanto 2 porte NOT, e una porta OR (a due ingressi) costa quanto 3 porte NOT (e non è disponibile nessun altro tipo di porta), quale delle due espressioni risulterà nel circuito meno caro? (giustificare la risposta)

(a) \B \D + BD + CD (b) ( \B + D ) (B + C + \D )

(c) 1a forma: 2 NOT + 3 AND + 2 OR = 2 + 3x2 + 2x3 = 12  meno cara 2a forma: 2 NOT + 1 AND + 3 OR = 2 + 1x2 + 3x3 = 13

(Altri raggruppamenti sono possibili, ma quelli risultano in un numero maggiore di gruppi, o in gruppi di dimensione minore, non sono ottimali )

Esercizio 2 (6 pts)

Una architettura con words di 8 bits dispone di un formato in virgola mobile con 4 bit di esponente (memorizzato con spiazzamento 8) seguiti da 3 bit di mantissa. Descrivere il valore memorizzato nei seguenti floats:

(le risposte devono essere fornite in base 10, come numero con virgola oppure come frazione, cioè come rapporto di interi; non è sufficiente fornire le risposte in notazione scientifica).

(a) 00101100 (c) 11101010 (e) 00000000

(b) 10101100 (d) 00001000 (f) 01000010

(a) 0 0101 100  + 1.100b x 2^(0101b – 8) = 1.1b x 2^(–3) = 11b x 2^(–4) = 3/16 (b) 1 0101 100  come sopra ma con segno invertito, quindi –3/16

(c) 1 1101 010  - 1.010b x 2^(1101b – 8) = -1.01b x 2^5 = -101b x 2^3 = -5x8 = -40 (d) 0 0001 000  + 1.000b x 2^(0001b – 8) = 1 x 2^(-7) = 1/128

(e) 0 0000 000  rappresentazione speciale di +0

(f) 0 1000 010  + 1.010b x 2^(1000b – 8) = 1.01b x 2^0 = 1.01b = 1 + ¼

a b c d F 0 0 0 0 1 0 0 0 1 0 0 0 1 0 1 0 0 1 1 1 0 1 0 0 0 0 1 0 1 1 0 1 1 0 0 0 1 1 1 1 1 0 0 0 1 1 0 0 1 0 1 0 1 0 1 1 0 1 1 1 1 1 0 0 X 1 1 0 1 X 1 1 1 0 0 1 1 1 1 X

(2)

Esercizio 3 (6 pts)

Si supponga di avere a disposizione il datapath mostrato sotto (è uno di quelli visti a lezione). L’ALU dispone delle comuni funzioni (ADD, SUB, PASSA, PASSB, eccetera).

Si scriva un microprogramma che realizza la nuova istruzione, avente opcode = 39:

DBLIND regA regB

“Double Indirection”, cioè doppia indirezione(*).

L’effetto di questa istruzione è quello di memorizzare nel registro A il valore in RAM presente alla locazione registrata in RAM all’indirizzo regB. Cioè:

regA = RAM[

RAM [ regB ]

]

Non è necessario includere la fase di fetch: il microprogramma parte dal passo 3, dopo tale fase.

(*) si ricorda che “indirezione”, o “deferenziazione”, è il procedimento di ottenere un valore registrato in memoria a partire dal suo indirizzo.

Input: Output:

OP code

Step Esiti Comandi Next

Step

Effetti:

39 3 X RegBout , MARin , Read , WMFC 4 MDR  MEM[ Reg B ] 39 4 X MDRout , MARin , Read , WMFC 5 MDR  MEM[ MDR ]

39 5 X MDRout , RegBout 0 RegB  MDR , goto 0

Note:

Gli esiti della ALU, in questo esempio, non influiscono sul comportamento della Control Unit.

La ALU non prende parte a nessun passo.

Nei passi (o microistruzioni) 3 e 4, si manda il comando alla RAM e si stalla subito la Control Unit in attesa del completamento dell’accesso in RAM (con WMFC). Infatti il risultato della lettura è, in entrambi i casi, necessario da subito, al passo successivo. Non è dunque ottimizzare rimandando la WFMC di alcun passo.

Nel passo 4, il valore letto dalla RAM (ora dentro MDR) viene passato direttamente a MAR, che contiene l’indirizzo a cui effettuare la lettura successiva.

Entrambi gli accessi alla RAM sono LETTURE (comando READ).

(3)

(a) dire quanti bit di uscita ha un decoder a 4 ingressi, e specificare l’uscita per l’ingresso 0010 2^4 = 16 bits.

Con 0010, solo bit n.2 (il terzo, partendo dal n. 0) è settato, quindi: 0000 0000 0000 0100.

(b) disegnare il circuito di un latch SR usando solo le comuni porte logiche

vedi lucidi, o varianti (servono due NOR, oppure due NAND, oppure OR e due NOT) (c) disegnare il circuito di un Multiplexer a due segnali di ingresso (da un bit ciascuno)

per es: (note: S = 0  U = A. S = 1  U = B)

Esercizio 5 (6 pts)

(a) Si ha a disposizione un Clock con frequenza 1MHz, e lo si vuole impegnare per implementare un Clock con frequenza 0.5Hz. Si possono usare tutti i comuni blocchi funzionali, come quelli visti a lezione. Suggerimento: prima di procedere allo svolgimento, ci si accerti di aver capito bene quale comportamento è richiesto dal circuito realizzato; nel proprio elaborato, specificare esplicitamente la durata: del ciclo, dell’intervallo basso, e alto del clock che si vuole ottenere.

(b) Per ciascun blocco funzionale usato, specificare se si tratta di un circuito combinatorio oppure sequenziale.

Durata del ciclo del clock da realizzare: 1/(0.5Hx)= 2 secondi. (1 sec int. Basso, e 1 sec int. alto) Durata del ciclo del clock di partenza: 1/(1MHz) = 1/(1,000,000Hz) = 0.000001 sec.

Idea (ma altre soluz sono possibili): vogliamo cambiare stato nell’output ogni 1,000,000 cicli.

 usiamo registro R per contare i cicli trascorsi.

 usiamo un flip-flop F per determinare l’uscita del clock (1 nell’intervallo alto, 0 nel basso).

 quando sono stati contati 1,000,000 cicli… (1) resettiamo R e (2) flippiamo F.

 nel registro ci bastano 20 bit, perché 2^20 = 2^10 x 2^10 > 1,000 x 1,000 = 1,000,000.

 per incrementare il contatore, possiamo usare un addizionatore (anche se è sprecato).

 per paragonare il valore del contatore, possiamo usare un circuito comparatore Quindi:

b) i 2 blocchi dello schema sopra con i triangoli sono sequenziali, gli altri 4 sono combinatori

(4)

Esercizio 6 (5+1 pts)

Completare il programma Assembly MIPS qui sotto, fornendo il codice da sostituire alla parte indicata.

La sezione dati contiene una variabile n intera, seguita da un array 1 di n numeri interi, e un array 2 di altri n numeri interi.

Lo scopo del programma è scoprire se almeno uno dei due array contiene uno o più elementi strettamente negativi ( < 0 ). In questo caso, si deve eseguire il codice contrassegnato dall’ etichetta “casoA”;

altrimenti, se entrambi gli array sono costituiti solo da elementi positivi (o nulli), va eseguito il codice

contrassegnato dall’etichetta “casoB”.

Ci si sforzi di scrivere un programma il più possibile efficiente e coinciso. Bonus di 1 punto al programma corretto che usi numero minore di istruzioni.

Si forniscono a fianco le sintassi di alcune istruzioni.

.data .word

n: < qui un valore >

array_1: < qui dei valori >

array_2: < qui dei valori >

.text main:

<il tuo codice qui>

casoB:

< qui il trattamento del caso B, e uscita.>

casoA:

< qui il trattamento del caso A, e uscita.>

SOLUZIONE 1: due cicli separati (quasi identici…), uno per array

la $t5 , n # $t5 = locazione dove e’ memorizzato n

lw $t2 , ($t5) # $t2 = valore di n = num di elementi da leggere la $t1 , array_1 # $t1 = locaz da leggere nell’array_1

ciclo1:

beqz $t2, fine_ciclo1 # se $t2 = 0, esci dal ciclo

lw $t3, ($t1) # $t3 = valore letto dall’array 1

bltz $t3, casoA # se $t3 e’ negativo, vai dirett. al caso A addi $t1, $t1, 4 # incrementa la locaz da leggere di 4 byte addi $t2, $t2, -1 # decrementa $t2 di uno

j ciclo1 fine_ciclo1:

la $t1 , array_2 # $t1 = locaz da leggere nell’array_2

lw $t2 , ($t5) # il numero di elementi da leggere viene resettato ciclo2:

beqz $t2, casoB # se anche il secondo array e’ finito, caso B lw $t3, ($t1) # $t3 = valore letto dall’array 2

bltz $t3, casoA # se $t3 e’ negativo, vai al caso A

addi $t1, $t1, 4 # incrementa la locaz da leggere di 4 byte addi $t2, $t2, -1 # decrementa $t2 di uno

j ciclo2

la reg , etichetta load address li reg , valore load immediate move regA , regB copia il registro B nel

registro A lw reg , offset(reg) load word

(l’offset è opzionale) sw reg , offset(reg) store word

(l’offset è opzionale) add reg , reg , reg add (somma) addi reg , reg , val add immediate sub reg , reg , reg subtract (differenza) sll reg , reg , val Shift left logical srl reg , reg , val Shift right logical

j etichetta jump

bgez reg , etichetta branch on greater than or equal to zero bgtz reg , etichetta branch on greater than

zero

bnez reg , etichetta branch on not equal zero

beqz reg , etichetta branch on equal zero bltz reg , etichetta branch on less than

zero

bltz reg , etichetta branch on less than or equal to zero

(5)

poi leggere da questa locazione con un LW.

Nota che il codice funziona anche se gli array sono vuoti (n = 0). Si salta fuori dal ciclo appena entrati (questo vale anche per le altre soluzioni fornite qui sotto). Questo è un vantaggio del testare la terminazione dell’array (con uscita dal ciclo) come prima cosa di ogni iterazione.

La soluzione 1 non è molto ottimizzata. Risparmiamo qualche istruzione eseguendo invece un solo ciclo: in ogni iterazione, analizziamo prima un elemento dell’array_1, poi l’elemento corrispondente dell’array_2. Questo è corretto perché i due array hanno lo stesso numero di elementi.

SOLUZIONE 2: un solo ciclo per controllare due array

la $t5 , n # $t5 = locazione dove e’ memorizzato n

lw $t5 , ($t5) # $t5 = num di elementi da leggere (da ciascun array) la $t1 , array_1 # $t1 = locaz da leggere nell’array_1

la $t2 , array_2 # $t2 = locaz da leggere nell’array_2 ciclo:

beqz $t5, casoB # se $t5 = 0 (nessun elemento rimane da leggere), caso B lw $t3, ($t1) # $t3 = valore letto dall’array 1

bltz $t3, casoA # se $t3 e’ negativo, vai al caso A

lw $t3, ($t2) # $t3 = valore letto dall’array 2 (sovrascrittura) bltz $t3, casoA # se $t3 e’ negativo, vai al caso A

addi $t1, $t1, 4 # incrementa la locaz da cui leggere nell’array 1 (di 4 bytes) addi $t2, $t2, 4 # incrementa la locaz da cui leggere nell’array 2 (di 4 bytes) addi $t5, $t5, -1 # decrementa il numero degli el da leggere (di uno)

j ciclo

Siamo passati da 17 a 13 istruzioni (volendo, se ne può limare via un’altra). E’ un codice anche più veloce da eseguire, perché si effettuano meno controlli di fine-array.

Ma la soluzione più compatta è un'altra ancora. Infatti, osservando il segmento “data”, possiamo notare che i due array sono contigui in memoria (*). Quindi possiamo considerarlo come un solo array, con il doppio degli elementi! Scandiamo il doppio degli elementi a partire dal primo array:

quando questo sarà finito, “sforeremo” direttamente nel secondo array. Se troviamo un solo negativo (non importa in quale dei due array), allora saltiamo al casoA. Altrimenti, se arriviamo in fondo al secondo (dopo 2n elementi), saltiamo al caso B.

(*) Nota importante: quest’ipotesi non potremmo farla in un linguaggio ad alto livello, es Java, perché non potremmo sapere dove in RAM il compilatore decida di allocare le variabili. Ma a basso livello, in MIPS, siamo noi a decidere dove e in che ordine vengano allocate le variabili.

SOLUZIONE 3: un solo ciclo per controllare un solo array (ma lungo il doppio)

la $t5 , n # $t5 = locazione dove e’ memorizzato n

lw $t5 , ($t5) # $t5 = num di elementi dell’array (el da leggere)

add $t5 , $t5, $t5 # raddoppio di $t5 (oppure con lo shift: sll $t5, $t5, 1 ) la $t1 , array_1 # $t1 = locaz da leggere (dal primo dei due array)

ciclo:

beqz $t5, casoB # se $t5 = 0 (nessun elemento rimane da leggere), caso B lw $t2, ($t1) # $t3 = valore letto dall’array

bltz $t2, casoA # se $t3 e’ negativo, vai al caso A

addi $t2, $t2, 4 # incrementa la locaz da cui leggere nell’array (di 4 bytes) addi $t5, $t5, -1 # decrementa il numero di el da leggere di 1

j ciclo

Siamo passati da 13 a 10 istruzioni. Fino a prova contraria, questa soluzione è la più corta possibile. E’ anche almeno tanto efficiente quanto Soluz.2, perché vengono effettuati lo stesso numero di controlli. Inoltre, questa soluzione potrebbe essere applicata anche se i due array fossero stati di dimensione diversa (a differenza della Soluz. 2).

(Ovviamente, in uno scritto basta fornire UNA soluzione, e anche molti dei commenti qui esposti sono superflui).

Riferimenti

Documenti correlati

Ricorda: per fare il doppio devi disegnare due volte la stessa quantità, devi cioè moltiplicare per

Se non so la tabellina del due faccio l’addizione, cioè sommo due

A single standard for informed consent to treatment would require all patients to be told the rationale for selecting the treatments offered to them. “I was told at medical

L'effetto «occulto» (nel senso di non manifesto) del racconto del sogno, mi sembra così relativo al fatto che il processo di ricerca e di decodificazione (o di codificazione), si

La nostra piccola paziente presenta alcune caratteristi- che sia del diabete tipo 1 (età, modalità di comparsa, familiarità per patologie autoimmunitarie), sia del dia- bete tipo

Premere il tasto Start ha l’effetto di riazzerare il timer e farlo partire (il timer continua a scorrere, anche se il tasto Start viene rilasciato, fino alla pressione del

(c) Se una porta AND (a due ingressi) costa quanto 2 porte NOT, e una porta OR (a due ingressi) costa quanto 3 porte NOT (e non è disponibile nessun altro tipo di porta), quale

dove numero_elementi deve essere o un valore intero, o un’espressione costante oppure una variabile che sia stata però istanziata prima della definizione dell'array; ad esempio,