Esercitazione 7 Interruzioni in PCSPIM Input/Output Chiamate di procedure Claudia Raibulet raibulet@disco.unimib.it Interruzioni in PCSPIM Input/Output
Interrupt Sono tipicamente causati da dispositivi hardware esterni, e collegati al processore attraverso delle linee di controllo di bus, come ad esempio le periferiche I/0 Quando le periferiche sono pronte ad effettuare operazioni impostano una linea di interruzione collegata alla CPU Quando viene attivata una linea di interruzione, se il sistema ha abilitato le interruzioni della CPU, il normale flusso di esecuzione viene interrotto, e la CPU passa a gestire l interrupt Interrupt abilitati All interno del interrupt mask (del Status Register) ciascun bit corrisponde all abilitazione di una differente linea di interruzione collegata ad una periferica Se il bit è impostato a 1 il corrispondente interrupt è abilitato e la periferica può generare una eccezione Se il bit è impostato a 0 il corrispondente interrupt NON è abilitato e anche se la linea di interruzione è attivata dalla periferica, la CPU non genera l eccezione Quando viene sollevata una eccezione a seguito di un interruzione abilitata, nel registro Cause viene impostato a 1 il bit corrispondente all interruzione
Interrupt abilitati Registro Cause 15 8 6 2 Registro Status Interruzione interrupt pendenti codice eccezione 15 8 4 1 0 interrupt mask user mode interrupt enable exception level Input/Output PCSPIM simula un terminale/console (una periferica di I/O) che permette di visualizzare caratteri sul video e leggere caratteri dalla tastiera Il terminale è composto da due dispositivi distinti e indipendenti: Transmitter: visualizza caratteri ASCII sulla Console Receiver: accetta caratteri ASCII dalla tastiera Osservazione: essendo indipendenti, un tasto premuto sulla tastiera non viene automaticamente mostrato sulla console; un programma deve esplicitamente fare l eco di un carattere letto dal Receiver inviandolo al Transmitter
Input/Output In PCSPIM i dispositivi Receiver e Transmitter sono controllati tramite 4 registri i cui contenuti appaiano a specifici indirizzi di memoria: Receiver Control Receiver Data Transmitter Control Transmitter Data 0xFFFF0000 0xFFFF0004 0xFFFF0008 0xFFFF000c Per utilizzare i dispositivi di I/O memory-mapped è necessario abilitare l opzione relativa nel Settings di PCSPIM Il Receiver: Receiver Control Receiver Control Ready: 1 carattere ricevuto dal Receiver 0 nessun carattere ricevuto dal Receiver 1 0 Interrupt Enable: 1 Interrupt Receiver Abilitati 0 Interrupt Receiver Disabilitati Il bit di Ready è in sola lettura (le scritture vengono ignorate) Il bit di Ready passa da 0 a 1 quando un carattere è arrivato dalla tastiera, ma non è stato ancora prelevato dal Receiver Data
Il Receiver: Receiver Data Receiver Data 7 0 Codice ASCII del tasto premuto Il codice ASCII del tasto premuto è valido soltanto se Ready = 1 (nel Receiver Control) Il Transmitter: Transmitter Control Ready: 1 Transmitter pronto ad inviare il prossimo carattere 0 Transmitter occupato a scrivere il precedente carattere Trasmitter Control 1 0 Interrupt Enable: 1 Interrupt Transmitter Abilitati 0 Interrupt Transmitter Disabilitati Il bit di Ready è in sola lettura (le scritture vengono ignorate) Ready = 1 se il Transmitter è pronto a scrivere un nuovo carattere, e 0 se è occupato a scrivere il carattere precedente
Il Transmitter: Transmitter Data Transmitter Data 7 0 Codice ASCII del carattere da stampare È possibile stampare un carattere solo scrivendolo nel Transmitter Data quando il bit di Ready del Transmitter Control è 1; Altrimenti, se il bit di Ready è zero il carattere non sarà visualizzato e andrà perso Tastiera È collegata alla linea di interruzione che fa capo al bit 8 dei registri Status e Cause Per abilitare le interruzioni dalla tastiera si abilita il bit 8 del registro Status Per scoprire se l interruzione è stata provocata dalla tastiera si verifica il valore del bit 8 nel registro Cause
.kdata save0: word 0 save1: word 0 Esempio Exceptions.s.ktext 0x80000180 move $k1, $at sw $v0, save0 sw $a0, save1 # kernel text segment # used in pseudo-instructions # in the handler code mfc0 $k0, $13 # moves coprocessor 0 s # register 13 (Cause register) # into CPU register $k0 Esempio Exceptions.s # Riconosce e distingue tra le eccezioni e gli interrupt andi $a0, $k0, 0x007c # Excp mask: 0x007c = 0000 0000 0111 1100 bgtz $a0, Excp_ret # salta se e' una eccezione (XXXX XXXX X000 00XX) # Stampa Interrupt rilevato li $v0, 4 la $a0, m3_ # print " Interrupt # Gestione dell'interrupt da XXXX IntXXXX:... EndIntXXXX:
Esempio Exceptions.s # Rientro dalla gestione degli interrupt # Si resetta il Cause register mtc0 $0, $13 # Ripristino registri salvati lw $v0, save0 lw $a0, save1 move $at, $k1 # Si preleva l'indirizzo di ritorno # e salta all'indirizzo di ritorno mfc0 $k0, $14 # carica EPC in $k0 eret # Return from exception handler jr $k0 Esempio di uso Exceptions.s # Il programma scrive una successione infinita di 0 # Alla pressione di un tasto stampa una stringa di avviso # Interrupt.globl start.data car0:.asciiz 0.text start: # Abilita gli interrupt in generale mfc0 $t0, $12 # Leggi Status Register (12) ori $t0, $t0, 1 # Abilita in generale gli INT ori $t0, $t0, 0x100 # Abilita gli INT da Tastiera mtc0 $t0, $12 # Scrivi il nuovo Status Register
Esempio di uso Exceptions.s # Abilita gli interrupt dalla periferica I/O, dal Receiver lw $t1, 0xFFFF0000 # Leggi attuale Receiver Control ori $t1, $t1, 2 # Abilita gli INT da Receiver sw $t1, 0xFFFF0000 # Scrivi il nuovo Receiver Control Esempio di uso Exceptions.s # Stampa in un ciclo infinito il carattere 0 ciclo: la $a0, car0 # stringa "O" li $v0, 4 # print string li $t0, 0x00000fff # costante grande perdi_tempo: addi $t0, $t0, -1 # decrementa bnez $t0, perdi_tempo # gira a vuoto b ciclo # ciclo infinito
Esempio di uso Exceptions.s # DISABILITA Interruzioni dal Receiver (tastiera) lw $a0, 0xffff0000 # Leggi attuale Receiver Control andi $a0, $a0, 0xfffd # Azzera bit 1 = INT enable sw $a0, 0xffff0000 # Scrivi nuovo Receiver Control # DISABILITA Interrupt dalla tastiera nella CPU mfc0 $a0, $12 # Leggi il CPU Status Reg. andi $a0, $a0, 0xfeff # Azzera il bit INT della tastiera mtc0 $a0, $12 # Scrivi il nuovo CPU Status Reg. Esercizio 1 Si chiede di modificare il codice dell Exceptions.s precedente in modo tale da stampare a console il carattere inserito della tastiera dopo il messaggio Interrupt
Esercizio 2 Si chiede di utilizzare il Receiver Control and Data per leggere i caratteri inseriti dalla tastiera. Si chiede di stampare il carattere inserito utilizzando una. Esercizio 2 - Soluzione.data Fine:.ascii "q" # carattere da premere per finire Messaggio:.ascii "Il tasto premuto e':" # nota: questa stringa non e' terminata con byte 0! Carattere:.asciiz "\n\n" # due a capo (il primo verra' sovrascritto)
Esercizio 2 - Soluzione li $t0, 0xFFFF0000 # Receiver Control li $t2, 0xFFFF0004 # Receiver Data lb $t4, Fine # carattere per finire BusyWaitRead: # "busy wait" lw $t1, 0($t0) # Receiver Control Register andi $t1, $t1, 0x1 # tiene solo il bit 0 beqz $t1, BusyWaitRead # se e' 0, non e' ancora arrivato nulla # Ready = 1, e' arrivato un carattere lb $t3, 0($t2) # legge byte dal Receiver Data beq $t3, $t4, fine # se e' il tasto di fine, esci sb $t3, Carattere # e lo salva in memoria li $v0, 4 # Stampa il carattere con la la $a0, Messaggio # il carattere e' incorporato! # stampa con b BusyWaitRead fine: Esercizio 3 Si chiede di modificare l esercizio 2 utilizzando gli interrupt per evitare di fare busy wait. # Da inserire nel Exceptions.s nella gestione degli interrupt IntKbd: andi $a0, $k0, 0x0100 # Receiver mask: 0x0100 = 0000 0001 0000 0000 beq $a0, $0, EndIntKbd # branch se e' interrupt ma non di Receiver # E' interrupt del Receiver, quindi... # Stampa le info sull'interrupt li $v0, 4 la $a0, m5_ # print " by Receiver "
Exceptions.s - Interrupt dalla tastiera # DISABILITA Interruzioni dal Receiver (tastiera) lw $a0, 0xFFFF0000 # Leggi attuale Receiver Control andi $a0, $a0, 0xfffd # Azzera bit 1 = INT enable sw $a0, 0xFFFF0000 # Scrivi nuovo Receiver Control # DISABILITA Interrupt Receiver nella CPU mfc0 $a0, $12 # Leggi il CPU Status Reg. andi $a0, $a0, 0xfeff # Azzera il bit INT del Receiver mtc0 $a0, $12 # Scrivi il nuovo CPU Status Reg. # Gestione del char digitato lw $a0, 0xFFFF0004 # prelevo il carattere dal Data Reg. sw $a0, BuffKbd # e lo metto nel buffer comune EndIntKbd: Esempio uso Exceptions.s # Abilita interrupt della CPU mfc0 $t0, $12 # Leggi il CPU Status Reg. ori $t0, $t0, 1 # abilita in generale gli INT ori $t0, $t0, 0x100 # abilita il bit INT del Receiver mtc0 $t0, $12 # Scrivi il nuovo CPU Status Reg. # Abilitazione Interrupt dal Receiver (tastiera) lw $t1, 0xFFFF0000 # Leggi attuale Receiver Control Reg. ori $t1, $t1, 2 # bit 1 = INT enable sw $t1, 0xFFFF0000 # scrivi nuovo Receiver Control Reg.
Esercizio 4 Considerando che il programma è memorizzato partendo dall indirizzo 0x00400024 e i dati dall indirizzo 0x10010000 si chiede: Quale istruzione genera l eccezione? Cosa indica il registro Cause? Quali valori assumono i registri EPC e BadVAddr?.data dato:.word 33.text main: la $t0, dato lw $t1, 0($t0) li $t2, 1 add $t2, $t2, $t0 sw $t2, 0($t2) jr $ra Chiamate di procedure
Procedure Una procedura simile ad una spia che parte con un piano segreto, acquisisce risorse, svolge dei lavori, nasconde le tracce e torna al punto di partenza con dei risultati quando la missione è completata Osservazione: la spia opera soltanto in base a ciò che deve sapere e non può fare assunzioni di che l ha assoldata Scopo delle procedure Strutturare i programmi Rendere i programmi più facili da capire Permettere il riutilizzo del codice I parametri rappresentano una barriera fra la procedura e il resto del programma e permettono lo scambio dei dati
Passi per chiamare una procedura Per l esecuzione di una procedura, un programma deve eseguire i seguenti sei passi: 1. mettere i parametri in un posto dove la procedura possa recuperarli 2. trasferire il controllo alla procedura 3. allocare le risorse (di memorizzazione dei dati) necessarie alla procedura 4. effettuare la computazione della procedura 5. mettere i risultati in un posto accessibile al chiamante 6. restituire il controllo al chiamante Convenzione uso registri per il passaggio di parametri a procedure La procedura A, durante la sua esecuzione, chiama la procedura B. La procedura B esegue i suoi compiti senza chiamare nessuna altra procedura. L interfaccia tra A e B segue le convenzioni di uso dei registri per il passaggio parametri. Indicare qualli delle seguenti scelte sono necessarie per garantire un risultato corretto. La procedura B richiede 2 parametri in ingresso (scalari a 32 bit) e fornisce uno scalare a 32 in uscita. 1. il programmatore della procedura A non si deve interessare del passaggio dei parametri perchè questo viene gestito dall assemblatore 2. la procedura A, prima di effettuare la chiamata a B, imposta i parametri attuali nei registri $v0, $v1 3. la procedura A, prima di effettuare la chiamata a B, imposta i parametri attuali nei registri $t0, $t1 4. la procedura A, prima di effettuare la chiamata a B, imposta i parametri attuali nei registri $s0, $s1 5. la procedura A, prima di effettuare la chiamata a B, imposta i parametri attuali nei registri $a0, $a1
Convenzione uso registri per il passaggio di parametri a procedure La procedura A, durante la sua esecuzione, chiama la procedura B. La procedura B esegue i suoi compiti senza chiamare nessuna altra procedura. L interfaccia tra A e B segue le convenzioni di uso dei registri per il passaggio parametri. Indicare qualli delle seguenti scelte sono necessarie per garantire un risultato corretto.la procedura B richiede 2 parametri in ingresso (scalari a 32 bit) e fornisce uno scalare a 32 in uscita. 1. la procedura A, al termine della procedura B, trova i parametri di uscita nei registri $a0, $a1 2. la procedura A, al termine della procedura B, trova i parametri di uscita nei registri $t0, $t1 3. la procedura A, al termine della procedura B, trova i parametri di uscita nei registri $v0, $v1 4. la procedura A, al termine della procedura B, trova i parametri di uscita nei registri $s0, $s1 5. il programmatore della procedura B non si deve interessare del passaggio dei parametri perchè questo viene gestito dall assemblatore Convenzione uso registri per il passaggio di parametri a procedure $a0 - $a3 -> quattro registri argomento per il passaggio dei parametri $v0 - $v1 -> due registri valore per la restituzione dei valori $ra ->registro di ritorno per tornare al punto di origine Procedura chiamante A... //argomenti in $a0 - $a3 jal B //valore ritornato in $v0, $v1 Procedura chiamata B //leggi argomenti da $a0 - $a3... //salva valore calcolato in $v0, $v1 jr $ra
Esercizio 1 Si chiede di scrivere una procedura che incrementa il valore ricevuto come argomento di ingresso..globl start.data numero:.word 123.text start: lw $a0, numero jal proc move $a0, $v0 li $v0, 1 proc:.globl proc addi $a0, $a0, 1 move $v0, $a0 jr $ra Esercizio 2 Si chiede di scrivere una procedura che calcola il prodotto tra due numeri interi specificati come argomenti di ingresso..text start: la $a0, inmsg li $v0, 4 li $v0, 5 move $a0, $v0 li $v0, 5 move $a1, $v0 jal prodotto move $a0, $v0 li $v0, 1.globl prodotto prodotto: mul $t0, $a0, $a1 move $v0, $t0 jr $ra
Esercizio 3 Si chiede di scrivere una procedura che ricevendo come valori di ingresso l indirizzo di un array di 10 elementi, e un numero compreso tra 0 e 9, ritorna l elemento dell array che si trova nella posizione indicata dal secondo argomento della procedura..globl estraielemento estraielemento: muli $t0, $a1, 4 # calcolo spiazzamento add $t0, $t0, $a0 # calcolo indice assoluto lw $t1, 0($t0) # caricamento elemento move $v0, $t1 # metto il valore di ritorno in $v0 jr $ra # ritorno al chiamante.globl start.data vett:.word 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 in_msg:.asciiz "Inserisci l'indice dell'elemento che vuoi estrarre\n" out_msg:.asciiz "Elemento estratto: ".text start: li $v0, 4 # stampa messaggio per input la $a0, in_msg li $v0, 5 # leggi intero la $a0, vett move $a1, $v0 jal estraielemento move $s1, $v0 li $v0, 4 # stampa messaggio di output la $a0, out_msg li $v0, 1 # stampa l'elemento estratto move $a0, $s1
Esercizio 4 Si chiede di scrievere una procedura che riceve in ingresso 3 numeri interi e calcola il minimo di essi..globl calcolaminimo calcolaminimo: slt $t0, $a0, $a1 beq $t0, $0, label1 move $t7, $a0 j label2 label1: move $t7, $a1 label2: slt $t0, $a2, $t7 beq $t0, $0, exit move $t7, $a2 exit: move $v0, $t7 jr $ra.globl start.data in_msg:.asciiz "Inserisci tre numeri: \n" out_msg:.asciiz "Il numero minimo inserito: ".text start: li $v0,4 # stampa del messaggio per input la $a0,in_msg li $v0,5 # read_int move $a0, $v0 li $v0,5 # read_int move $a1, $v0 li $v0,5 # read_int move $a2, $v0 jal calcolaminimo # chiamata della procedura move $s0, $v0 li $v0, 4 # stampa messaggio di output la $a0, out_msg li $v0,1 # stampa dell'elemento estratto move $a0,$s0
Esercizio 5 Si chiede di scrivere una procedura che calcola la media degli elementi di un array..globl media media: move $t0, $a0 move $t1, $a1 move $t7, $0 ciclo: beq $t1, $0, EXIT lw $t2, 0($t0) addi $t0, $t0, 4 add $t7, $t7, $t2 addi $t1, $t1, -1 j ciclo EXIT: divu $v0, $t7, $a1 jr $ra.globl start.data vett:.word 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 dim:.word 10 outmsg:.asciiz "La media e': ".text start: la $a0, vett lw $a1, dim jal media move $s0, $v0 la $a0, outmsg li $v0, 4 move $a0, $s0 li $v0, 1 Prova di valutazione
Esercizio 1 Dato il seguente frammento di codice, in quale punto avviene un'eccezione di Overflow? li $t0, 0x7FFFFFFD li $t1, 1 add $t0, $t0, $t1 # riga 1 add $t0, $t0, $t1 # riga 2 add $t0, $t0, $t1 # riga 3 add $t0, $t0, $t1 # riga 4 lw $t2, 0($t0) # riga 5 break 2 # riga 6 1. Alla riga 1 2. Alla riga 2 3. Alla riga 3 4. Alla riga 4 5. Alla riga 5 6. Alla riga 6 7. Non avviene nessuna eccezione 8. Nessuna delle altre 9. Non rispondo Esercizio 2 Se il registro Cause assume il valore 0x0000 0024, quale eccezione si è verificata? 1. Break Exception 2. Syscall Exception 3. AdES (scrittura non allineata in memoria) 4. AdEL (lettura non allineata da memoria) 5. Interrupt Exception 6. Overflow Exception 7. Nessuna delle altre 8. Non rispondo
Esercizio 3 Dato il seguente frammento di codice di un Exceptions.s, specificare quale riga riconosce correttamente un'eccezione di tipo Interrupt.... mfc0 $k0, $13 # Cause register srl $k0, $k0, 2 andi $k0, $k0, 0x1f bnez $k0, is_irq # riga 1 bgtz $k0, is_irq # riga 2 bltz $k0, is_irq # riga 3 beqz $k0, is_irq # riga 4... is_irq: # gestione Interrupt 1. Alla riga 1 2. Alla riga 2 3. Alla riga 3 4. Alla riga 4 5. Nessuna delle altre 6. Non rispondo