1 (RICHIAMI) INTRODUZIONE ALLA PROGRAMMAZIONE ASSEMBLY DI PROCESSORI MIPS COS'E' UN PROCESSORE IL PROCESSORE MIPS ISA RIDOTTO eMIPS PROGRAMMAZIONE ASSEMBLY DELL’ eMIPS Architetture dei Sistemi Embedded 2007/08 S.M. Carta 2 COSA E' UN PROCESSORE Architetture dei Sistemi Embedded 2007/08 S.M. Carta 3 INSTRUCTION SET ARCHITECTURE IL PROCESSORE È UNA MACCHINA SEQUENZIALE CHE ESEGUE DELLE ISTRUZIONI RESIDENTI IN MEMORIA ALLO SCOPO DI MANIPOLARE DEI DATI A LORO VOLTA RESIDENTI IN MEMORIA. L’INSTRUCTION SET ARCHITECTURE (ISA) SPECIFICA L’INSIEME DELLE CARATTERISTICHE DEL PROCESSORE VISIBILI AL PROGRAMMATORE. ESSO DEFINISCE L’INTERFACCIA TRA HARDWARE E SOFTWARE. L'ISA SPECIFICA LA FUNZIONALITA' DEL PROCESSORE IN TERMINI DI: DATI GESTITI REGISTRI INTERNI DESTINATI A CONTENERE I DATI DA MANIPOLARE ISTRUZIONI CHE PRELEVANO DALLA MEMORIA E MANIPOLANO QUESTI DATI ISTRUZIONI DI "SALTO" MODALITA' DI FUNZIONAMENTO SPECIALI ISTRUZIONI SPECIALI Architetture dei Sistemi Embedded 2007/08 S.M. Carta 4 C - ASSEMBLY - CODICE MACCHINA CODICE AD ALTO LIVELLO (C) COMPILER CODICE ASSEMBLY ASSEMBLER CODICE MACCHINA MEMORIA ISTRUZIONI (MODELLO VERILOG) UN PROCESSORE È L'ESECUTORE DI ISTRUZIONI DEL PROPRIO INSTRUCTION SET TRAMITE LE ISTRUZIONI MACCHINA È POSSIBILE ESEGUIRE UN QUALUNQUE ALGORITMO SPECIFICATO IN UN LINGUAGGIO AD ALTO LIVELLO IL PROCESSORE PUÒ ESEGUIRE LE ISTRUZIONI DEL PROPRIO IS SOLO UNA VOLTA CHE LE STESSE SONO STATE CONVERTITE IN FORMATO BINARIO (CODICE MACCHINA) LA TRASFORMAZIONE DA UNA RAPPRESENTAZIONE ALL'ALTRA VIENE ESEGUITA DA DEI SW DI SUPPORTO, IL COMPILATORE E L'ASSEMBLER INSTRUCTIONS DATA BUS BUS PROCESSORE INSTR ADDRESSES DATA ADDRESSES BUS BUS Architetture dei Sistemi Embedded 2007/08 MEMORIA DATI S.M. Carta INSTRUCTION SET ARCHITECTURE FETCH DELLE ISTRUZIONI (I) ALLO SCOPO DI ESEGUIRE UN ALGORITMO IL PROCESSORE ESEGUE DELLE ISTRUZIONI DEL PROPRIO IS ALL'ISTANTE 0 DELL'ESECUZIONE LE ISTRUZIONI CHE CODIFICANO IL PROGRAMMA DA ESEGUIRE RISIEDONO NELLA MEMORIA ISTRUZIONI PER POTER ESSERE ESEGUITA DAL PROCESSORE CIASCUNA ISTRUZIONE DEVE ESSERE CARICATA IN UN REGISTRO INTERNO DEL PROCESSORE (FETCH DELL'ISTRUZIONE) SOLITAMENTE IL REGISTRO DESTINATO A CONTENERE L'ISTRUZIONE CORRENTE E' DENOMINATO INSTRUCTION REGISTER (IR) IL FLUSSO DI ESECUZIONE DELLE ISTRUZIONI VIENE DEFINITO DALLA DISLOCAZIONE IN MEMORIA DELLE ISTRUZIONI STESSE E DALLA TECNICA DI FETCH UTILIZZATA IL FLUSSO NORMALE DI ESECUZIONE (CHE NON FA USO DELLE ISTRUZIONI DEDICATE CHE SI OCCUPANO DI MODIFICARE TALE FLUSSO) PREVEDE LA ESECUZIONE SEQUENZIALE DELLE ISTRUZIONI SECONDO L'ORDINE DI SALVATAGGIO IN MEMORIA Architetture dei Sistemi Embedded 2007/08 S.M. Carta 5 INSTRUCTION SET ARCHITECTURE FETCH DELLE ISTRUZIONI (II) UN REGISTRO INTERNO DEL PROCESSORE CONTIENE L'INDIRIZZO DELLA LOCAZIONE DI MEMORIA ALL'INTERNO DELLA QUALE E' CONTENUTA LA PROSSIMA ISTRUZIONE DA ESEGUIRE. TALE REGISTRO PRENDE IL NOME DI PROGRAM COUNTER (PC) OGNI QUALVOLTA VIENE CARICATA ED ESEGUITA UNA ISTRUZIONE CHE NON PREVEDA LA MODIFICA DEL FLUSSO DI ESECUZIONE IL PC VIENE INCREMENTATO IN AUTOMATICO IN MODO CHE LA PROSSIMA ISTRUZIONE CARICATA SULL'IR E QUINDI ESEGUITA SIA LA SUCCESSIVA A QUELLA ATTUALMENTE ESEGUITA (SEQUENZA DI ESECUZIONE NORMALE) LA MODIFICA DEL FLUSSO DI ESECUZIONE SEQUENZIALE VIENE GESTITA TRAMITE LE ISTRUZIONI DI SALTO. SUPPONENDO CHE LA PRIMA ISTRUZ SIA MEMORIZZATA ALLA LOCAZIONE DI MEMORIA 0, CHE CIASCUINA ISTRUZIONE OCCUPI UNA SOLA LOCAZIONE, E CHE NESSUNA DELLE PRIME 10 ISTRUZIONI SIA UNA ISTRUZIONE DI SALTO, LA SEQUENZA DI ESECUZIONE SAREBBE LA SEGUENTE: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ... SUPPONENDO CHE LA ISTRUZIONE 3 SIA UNA ISTRUZIONE DI SALTO (JUMP 7) LA SEQUENZA DI ESECUZIONE SAREBBE: 0, 1, 2, 3, 7, 8, 9, ... Architetture dei Sistemi Embedded 2007/08 S.M. Carta 6 INSTRUCTION SET ARCHITECTURE TIPOLOGIE DI ISTRUZIONI LE PRINCIPALI TIPOLOGIE DI ISTRUZIONI SONO 3, A CUI VANNO AGGIUNTE ISTRUZIONI DI TIPO ETEROGENEO NON CLASSIFICABILI IN MANIERA SINTETICA, E CHE PER ORA NON VEDIAMO. 1. ISTRUZIONI DI SPOSTAMENTO DATI: SI OCCUPANO DI SPOSTARE I DATI DALLA MEMORIA AI REGISTRI INTERNI DEL PROCESSORE E VICEVERSA, ESISTONO INOLTRE ISTRUZIONI CHE SPOSTANO I DATI FRA REGISTRI INTERNI E PIU' RARAMENTE ISTRUZIONI CHE SPOSTANO I DATI FRA LOCAZIONI DI MEMORIA 2. ISTRUZIONI DI MANIPOLAZIONE DATI: SI OCCUPANO DI PRELEVARE I DATI DA LOCAZIONI (DI SOLITO DAI REGISTRI INTERNI), DI UTILIZZARLI COME OPERANDI SORGENTE PER DELLE OPERAZIONI LOGICO/ARITMETICHE E DI SALVARE IL RISULTAO IN ALTRE LOCAZIONI (DI SOLITO DAI REGISTRI INTERNI). 2. ISTRUZIONI DI MODIFICA DEL FLUSSO DI ESECUZIONE (SALTO): SI OCCUPANO DI MODIFICARE IL CONTENUTO DEL PC IN MODO DA MODIFICARE IL FLUSSO DI ESECUZIONE DEFINITO DALL'INCREMENTO AUTOMATICO DEL PC STESSO Architetture dei Sistemi Embedded 2007/08 S.M. Carta 7 8 LA FAMIGLIA DI PROCESSORI MIPS Architetture dei Sistemi Embedded 2007/08 S.M. Carta 9 LA FAMIGLIA MIPS La prima versione dell’ISA MIPS è una delle prime architetture di tipo RISC (Reduced Instruction Set Compnent) ed è stata sviluppata da John L. Hennessy. L’ISA si è quindi evoluta in innumerevoli versioni ciascuna delle quali è stata implementata da diverse microarchitetture. Si parla di famiglia di processori Mips. Le più evolute versioni di processori MIPS sono attualmente integrate in dispositivi elettronici embedded di largo utilizzo. Consolle per l’intrattenimento (la Playstation!!) Stampanti Laser Decoder TV Satellitare Router Navigatori satellitari per automobili Macchine fotografiche digitali Architetture dei Sistemi Embedded 2007/08 S.M. Carta 10 MIPS ISA: GENERALITA’ L’architettura dei processori della famiglia Mips è di tipo load/store: non è possibile operare direttamente sui dati residenti in memoria ma è necessario prima copiarli nei registri interni tramite istruzioni dedicate. E’ prevista la presenza di un moltiplicare integrato per dati a 32 bit con risultato a 64 bit. I registri interni visibili del Mips sono: 32 registri general purpose a 32 bit, il registro zero contiene 0 e non può essere modificato due registri a 32 bit, Hi e Lo, per memorizzare rispettivamente i 32 bit più significativi e i 32 bit meno significativi del risultato di moltiplicazione un registro Program Counter a 32 bit, che contiene l’indirizzo dell’istruzione da eseguire un registro Interrupt Address Register Registri per elaborazione Floating Point Architetture dei Sistemi Embedded 2007/08 S.M. Carta 11 MIPS R2000 ISA : ISTRUZIONI Il documento che specifica l'Instruction Set completo è disponibile sul sito Architetture dei Sistemi Embedded 2007/08 S.M. Carta 12 INSTRUCTION SET MIPS R2000 Architetture dei Sistemi Embedded 2007/08 S.M. Carta 13 INSTRUCTION SET MIPS R2000 ISTRUZIONI DI ACCESSO ALLA MEMORIA (8) 5 load e 3 store. L’indirizzo di accesso (addr) è sempre la somma dell’immediato e del contenuto del registro puntato da rs Nome Sintassi Descrizione Load word lw rt, imm(rs) Regs[rt]<={mem[addr],mem[addr+1],mem[addr+2],mem[addr+3]} Load half word lh rt, imm(rs) Regs[rt]<={{16{mem[addr]31}},mem[addr],mem[addr+1]} Load byte lb rt, imm(rs) Regs[rt]<={{24{mem[addr]31}},mem[addr]} Load half word unsigned lhu rt, imm(rs) Regs[rt]<={{16{1’b0}},mem[addr]} Load byte unsigned lbu rt, imm(rs) Regs[rt]<={{24{1’b0}}mem[addr]} Store word sw rt, imm(rs) Mem[addr]<=Regs[rt] Store half word sh rt, imm(rs) Mem[addr]<=Regs[rt][15:0] Store byte sb rt, imm(rs) Mem[addr]<=Regs[rt][7:0] Architetture dei Sistemi Embedded 2007/08 S.M. Carta 14 INSTRUCTION SET MIPS R2000 ISTRUZIONI LOGICO-ARITMETICHE CON INDIRIZZAMENTO IMMEDIATO (10) Nome Sintassi Descrizione Addition Immediate (with overflow) addi rt, rs, imm Regs[rt]<=Regs[rs]+imm Addition Immediate (without overflow) addiu rt, rs, imm Regs[rt]<=Regs[rs]+imm And Immediate andi rt, rs, imm Regs[rt]<=Regs[rs] and imm Or Immediate ori rt, rs, imm Regs[rt]<=Regs[rs] or imm Xor Immediate xori rt, rs, imm Regs[rt]<=Regs[rs] xor imm Sub Immediate(with overflow) sub rt, rs, imm Regs[rt]<=Regs[rs]-imm Sub Immediatte(without overflow) subu rt, rs, imm Regs[rt]<=Regs[rs]-imm Shift left logical sll rd, rt, shamt Regs[rd]<=Regs[rs]<<shamt Shift right aritmetic sra rd, rt, shamt Regs[rd]=(Regs[rt]>>shamt)|({32{Regs[rs][31]}}<<( 32-shamt)) Shift right logical srl rd, rt, shamt Regs[rd]<=Regs[rs]>>shamt Architetture dei Sistemi Embedded 2007/08 S.M. Carta 15 INSTRUCTION SET MIPS R2000 ISTRUZIONI LOGICO-ARITMETICHE CON INDIRIZZ. REGISTER (19) Nome Sintassi Descrizione Absolute value abs rt, rs Regs[rt]=abs(Regs[rs]) Addition (with overflow) add rd, rs, rt Regs[rt]=Regs[rs]+Regs[rt] Addition (without overflow) addu rd, rs, rt Regs[rt]=Regs[rs]+Regs[rt] And and rd, rs, rt Regs[rt]=Regs[rs] and Regs[rt] Multiply mult rs, rt Unsigned Multiply multu rs, rt Come mult senza tener conto del segno degli operandi Negate (with overflow) neg rd, rs Regs[rd]=-Regs[rs] Negate (without overflow) negu rd, rs Regs[rd]=-Regs[rs] Nor nor rd, rs, rt Regs[rt]=Regs[rs] nor Regs[rt] Not not rt, rs Regs[rd]=~Regs[rs] Or or rd, rs, rt Regs[rt]=Regs[rs] or Regs[rt] Shift left logical variable sllv rd, rs, rt Regs[rt]=Regs[rs]<<Regs[rt] Shift right logical variable srlv rd, rs, rt Regs[rt]=Regs[rs]>>Regs[rt] Shift right aritmetic variable srav rd, rs, rt Regs[rd]=(Regs[rt]>>Regs[rs]) | ({32{Regs[rs][31]}}<<(32-Regs[rs])) Rotate left rol rd, rs, rt Regs[rt]=Regs[rs]+Regs[rt] Rotate right ror rd, rs, rt Regs[rt]=Regs[rs]+Regs[rt] Subtract(with overflow) sub rd, rs, rt Regs[rt]=Regs[rs]-Regs[rt] Subtract(without overflow) subu rd, rs, rt Regs[rt]=Regs[rs]-Regs[rt] Exclusive or xor rd, rs, rt Regs[rt]=Regs[rs] xor Regs[rt] Architetture dei Sistemi Embedded 2007/08 Regs[hi]=(Regs[rs]*Regs[rt])[63:32] Regs[lo]=(Regs[rs]*Regs[rt])[31:0] S.M. Carta INSTRUCTION SET MIPS R2000 ISTRUZIONI DI COMPARAZIONE (12) 2 con indirizzamento immediato e 10 con indirizzamento register Nome Sintassi Descrizione Set on less than slt rd, rs, rt If(Regs[rs]<Regs[rt]) Regs[rd]=1 else Regs[rd]=0 Set on less than unsigned sltu rd, rs, rt Come slt senza tenere conto del segno degli operandi Set on less than immediate slti rt, rs, imm If(Regs[rs]<imm) Regs[rd]=1 else Regs[rd]=0 Set on less than immediate unsigned sltiu rt, rs, imm Come slti senza tenere conto del segno degli operandi Set on equal seq rd, rs, rt If(Regs[rs]=Regs[rt]) Regs[rd]=1 else Regs[rd]=0 Set on greater than or equal sge rd, rs, rt If(Regs[rs]>=Regs[rt]) Regs[rd]=1 else Regs[rd]=0 Set on greater than or equal unsigned sgeu rd, rs, rt Come sge senza tenere conto del segno degli operandi Set on greater than sgt rd, rs, rt If(Regs[rs]>Regs[rt]) Regs[rd]=1 else Regs[rd]=0 Set on greater than unsigned sgtu rd, rs, rt Come sgt senza tenere conto del segno degli operandi Set on less than or equal sle rd, rs, rt If(Regs[rs]<=Regs[rt]) Regs[rd]=1 else Regs[rd]=0 Set on less than or equal unsigned sleu rd, rs, rt Come sle senza tenere conto del segno degli operandi Set on not equal sne rd, rs, rt If(Regs[rs]!=Regs[rt]) Regs[rd]=1 else Regs[rd]=0 Architetture dei Sistemi Embedded 2007/08 S.M. Carta 16 INSTRUCTION SET MIPS R2000 ISTRUZIONI DI SALTO CONDIZIONATO (17) LABEL indica l'istruzione alla quale saltare Nome Sintassi Descrizione Branch on equal beq rs, rt, LABEL Salta se Regs[rs]=Regs[rt] Branch on greater than equal zero bgez rs, LABEL Salta se Regs[rs]>=0 Branch on greater than equal zero and link bgezal rs, LABEL Salta e Regs[31]<=PC+4 se Regs[rs]>=0 Branch on greater than zero bgtz rs, LABEL Salta se Regs[rs]>0 Branch on less than equal zero blez rs, LABEL Salta se Regs[rs]<=0 Branch on less than and link bltzal rs, LABEL Salta e Regs[31]<=PC+4 se Regs[rs]<0 Branch on less than zero bltz rs, LABEL Salta se Regs[rs]<0 Branch on not equal bne rs, rt, LABEL Salta se Regs[rs]!=Regs[rt] Branch on greater than equal bge rs, rt, LABEL Salta se Regs[rs]>=Regs[rt] Branch on greater than equal unsigned bgeu rs, rt, LABEL Come bge senza tenere conto del segno degli operandi Branch on greater than bgt rs, rt, LABEL Salta se Regs[rs]>Regs[rt] Branch on greater than unsigned bgtu rs, rt, LABEL Come bgt senza tenere conto del segno degli operandi Branch on less than equal ble rs, rt, LABEL Salta se Regs[rs]<=Regs[rt] Branch on less than equal unsigned bleu rs, rt, LABEL Come ble senza tenere conto del segno degli operandi Branch on less than blt rs, rt, LABEL Salta se Regs[rs]<Regs[rt] Branch on less than unsigned bltu rs, rt, LABEL Come blt senza tenere conto del segno degli operandi Branch on not equal zero bnez rs, rt, LABEL Salta se Regs[rs]!=0 Architetture dei Sistemi Embedded 2007/08 S.M. Carta 17 INSTRUCTION SET MIPS R2000 ISTRUZIONI DI SALTO INCONDIZIONATO (4) Nome Sintassi Descrizione Jump j target PC={{(PC+4)[31:28]},{target},{2’b00}} Jump and link jal target Regs[31]<=PC+4 e PC={{(PC+4)[31:28]},{target},{2’b00}} Jump register jr rs PC=Regs[rs] Jump and link register jalr rs, rd Regs[rd]<=PC+4 e PC=Regs[rs] Architetture dei Sistemi Embedded 2007/08 S.M. Carta 18 INSTRUCTION SET MIPS R2000 ISTRUZIONI DI SPOSTAMENTO DATI FRA REGISTRI (4) Nome Sintassi Descrizione Move from hi mfhi rd Regs[rd]=Regs[hi] Move from lo mflo rd Regs[rd]=Regs[hi] Move to hi mthi rs Regs[hi]=Regs[rs] Move to lo mtlo rs Regs[lo]=Regs[rs] ISTRUZIONI DI MANIPOLAZIONI COSTANTI A 32 BIT (1) Nome Sintassi Descrizione Load upper immediate lui rt, imm Regs[rt]<= {imm,{16’h0 } } ISTRUZIONI SPECIALI (2) Nome Sintassi Descrizione No operation nop - Return from exeption rfe PC<=IAR e int_enable=1 Architetture dei Sistemi Embedded 2007/08 S.M. Carta 19 20 INSTRUCTION SET MIPS R2000 PSEUDO-ISTRUZIONI (2) Nome Sintassi Descrizione Implementazione move move Rs, Rd Regs[Rd]=Regs[Rs] add Rd, Rs, $0 load 32 bit immediate li Rd, imm32 Regs[Rd] = imm32 lui Rd, imm[31:16] ori Rd, Rd, imm[15:0] Architetture dei Sistemi Embedded 2007/08 S.M. Carta 21 MIPS R2000 ISA DEDICATO AGLI INTERI Ci occuperemo del sottoinsieme dell’ISA del MIPS R2000 (da ora in poi semplicemente MIPS ISA) dedicato agli interi. Trascureremo per motivi di tempo la gestione dell’elaborazione floating point (che è comunque opzionale nella maggior parte degli ISA per elaborazione embedded) Il sottoinsieme dedicato agli interi consta di 75 istruzioni, che possono essere classificate per funzionalità: Istruzioni di lettura e scrittura dalla memoria (8) Istruzioni aritmetico-logiche (40) Istruzioni di scambio dati fra registri interni (4) Istruzioni di modifica del flusso di esecuzione Salto incondizionato (4) Salto condizionato (17) Architetture dei Sistemi Embedded 2007/08 S.M. Carta 22 MIPS ISA: FORMATO DELLE ISTRUZIONI Le istruzioni sono a lunghezza fissa (32 bit), in tre possibili formati: 1. Immediate (I Type) opcode rs rt Immediate 6bit 5bit 5bit 16bit 2. Reg Type (R Type) opcode rs rt rd shamt function 6bit 5bit 5bit 5bit 5bit 6bit 3. Jump (J Type) opcode 6bit Architetture dei Sistemi Embedded 2007/08 target 26bit S.M. Carta 23 MIPS ISA RIDOTTO: eMIPS Architetture dei Sistemi Embedded 2007/08 S.M. Carta 24 INSTRUCTION SET eMIPS Inizieremo la trattazione analizzando un sottoinsieme minimo delle istruzioni, che chiameremo eMIPS Non è implementata la moltiplicazione, non vi sono quindi istruzioni di scambio fra registri interni. L’IS semplificato contiene almeno una istruzione per ciascuna delle categorie rimanenti: Istruzioni di lettura e scrittura dalla memoria (2 su 8) Istruzioni aritmetico-logiche (5 su 40) Istruzioni di scambio di dati tra registri interni (0 su 4) Istruzioni di modifica del flusso di esecuzione - Salto incondizionato (0 su 4) - Salto condizionato (1 su 17) Architetture dei Sistemi Embedded 2007/08 S.M. Carta 25 INSTRUCTION SET eMIPS load word (lw): carica su un registro interno un valore dalla memoria store word (sw): scrive in memoria il valore contenuto in un registro add : somma del valore di due registri subtract (sub): sottrazione tra il valore di due registri and: and logico bit a bit del contenuto di due registri or: or logico bit a bit del contenuto di due registri set on less than (slt): scrive 1 sul registro destinazione se il primo operando è minore del secondo, zero altrimenti. branch on equal (beq): salto condizionato all'uguaglianza dei valori contenuti nei 2 registri confrontati Architetture dei Sistemi Embedded 2007/08 S.M. Carta 26 INSTRUCTION SET eMIPS NOTAZIONE CON INDICAZIONE DI REGISTRI GENERICI DESCRIZIONE ASSEMBLY FUNZIONALITA’ Load word lw Rt, imm(Rs) REGS[Rt] = Mem(REGS[Rs]+imm) Store word sw Rt, imm(Rs) Mem(REGS[Rs] + imm) = REGS[Rt] Add add Rd, Rs, Rt REGS[Rd] = REGS[Rs] + REGS[Rt] Subtract sub Rd, Rs, Rt REGS[Rd] = REGS[Rs] – REGS[Rt] And and Rd, Rs, Rt REGS[Rd]= REGS[Rs] and REGS[Rt] Or or Rd, Rs, Rt REGS[Rd] = REGS[Rs] or REGS[Rt] Set on less than slt Rd, Rs, Rt if (REGS[Rs]<REGS[Rt]) REGS[Rd] = 1 Branch if equal beq Rs, Rt, label1 if (REGS[Rs]==REGS[Rt]) PC = PC+4+imm N.B. REGS[Rs] = contenuto del registro Rs del register file imm = valore che concorre a definire la locazione di memoria interessata al trasferimento Architetture dei Sistemi Embedded 2007/08 S.M. Carta 27 INSTRUCTION SET eMIPS NOTAZIONE CON INDICAZIONE DI REGISTRI DI ESEMPIO DESCRIZIONE ASSEMBLY FUNZIONALITA’ Load word lw $3, 0x0100($2) REGS[$3] = Mem(REGS[$2]+0x0100) Store word sw $3, 0x0100($2) Mem(REGS[$2] + 0x0100) = REGS[$3] Add add $4, $2, $3 REGS[$4] = REGS[$2] + REGS[$3] Subtract sub $4, $2, $3 REGS[$4] = REGS[$2] – REGS[$3] And and $4, $2, $3 REGS[$4]= REGS[$2] and REGS[$3] Or or $4, $2, $3 REGS[$4 = REGS[$2] or REGS[$3] Set on less than slt $4, $2, $3 if (REGS[$2]<REGS[$3]) REGS[$4] = 1 Branch if equal beq $2, $3, label1 if (REGS[$2]==REGS[$3]) PC = PC+4+imm N.B. $2 = REGISTRO 2 REGS[$2] = contenuto del registro $2 del register file Architetture dei Sistemi Embedded 2007/08 S.M. Carta INSTRUCTION SET eMIPS: GESTIONE DELLA MEMORIA L'ISA MIPS completo gestisce dati di 6 tipi diversi: a 8, 16, 32 bit in rappresentazione naturale o complemento a 2. Il sistema di memoria deve poter gestire tutti i tipi di dato esistenti, fornendo i dati in uscita nella maniera appropriata, a seconda del valore assunto dai bit di controllo associati (opType). Essendo il dato minimo a 8 bit, la locazione di memoria elementare deve essere di 8 bit @100 01 // Most significant byte del dato 1 @101 21 // byte 2 del dato 1 @102 AB // byte 3 del dato 1 @103 00 // Least significant byte del dato 1 @104 43 // Most significant byte del dato 2 @105 01 // Least significant byte del dato 2 @106 C1 // Dato 3 DATO 1, a 32 bit: 0121AB00 DATO 2, a 16 bit: 4301 DATO 3, a 8 bit: C1 always @(Addr) // MODELLO VERILOG DELLA MEMORIA DATI case (opType) (word) DataOut = {Data[Addr+0],Data[Addr+1],Data[Addr+2],Data[Addr+3]}; (halfword) DataOut = {16’h0000,Data[Addr+0],Data[Addr+1]}; (byte) DataOut = {24’h000000, Data[Addr] }; endcase Architetture dei Sistemi Embedded 2007/08 S.M. Carta 28 INSTRUCTION SET eMIPS: GESTIONE DELLA MEMORIA Per non escludere la possibilità che al processore sia associato un sistema di memoria con memoria dati ed istruzioni non separate (memoria unica, modello di Von Neumann) è necessario che anche la memoria istruzioni sia indirizzabile un byte alla volta, nonostante le istruzioni siano sempre di 4 byte Ciò implica che l'aggiornamento del PC sia di 4 in 4. @000 01 // Most significant byte dell’istr 1 @001 21 @002 AB @003 00 // Least significant byte dell’istr 1 @004 43 // Most significant byte dell’istr 2 @005 01 @006 C1 @007 01 // Least significant byte dell’istr 2 ISTRUZIONE 1:0121AB00 ISTRUZIONE 2: 4301C101 always @(Addr) // MODELLO VERILOG DELLA MEMORIA INSTRUZIONI DataOut = {Data[Addr+0],Data[Addr+1],Data[Addr+2],Data[Addr+3]}; Architetture dei Sistemi Embedded 2007/08 S.M. Carta 29 30 PROGRAMMAZIONE ASSEMBLY DEL PROCESSORE eMIPS-sc Architetture dei Sistemi Embedded 2007/08 S.M. Carta 31 PROGRAMMAZIONE ASSEMBLY: ISTRUZIONI DI ASSEGNAMENTO SIMULAZIONE eMIPS_S1 Specifica C integer A,B,C; // dati a 32 bit C = A + B; Specifica aggiuntiva 1: memoria dati (t=0) @0100 A @0104 B eMIPS assembly lw $1,0x0100($0) lw $2, 0x0104($0) add $3,$2,$1 sw $3, 0x0200($0) Specifica aggiuntiva 2: memoria dati (t=fine simulaz) @0200 C Architetture dei Sistemi Embedded 2007/08 S.M. Carta 32 PROGRAMMAZIONE ASSEMBLY: ESECUZIONE CONDIZIONALE (1) L'ESECUZIONE CONDIZIONALE PUÒ ESSERE GESTITA TRAMITE L'USO DI ISTRUZIONI DI SALTO CONDIZIONATO E DI SALTO INCONDIZIONATO. if (cond) A; else B; if (cond) A; Architetture dei Sistemi Embedded 2007/08 branch(cond==1),tagA; B; branch(1),end; tagA: A; end: branch(cond==1),tagA; branch(1),end; tagA: A; end: S.M. Carta 33 PROGRAMMAZIONE ASSEMBLY: ESECUZIONE CONDIZIONALE (2) SIMULAZIONE eMIPS_S2 Specifica C integer A,B,C; // dati a 32 bit if (A!=B) C = A + B; else C = A - B; Specifica aggiuntiva 1: memoria dati (t=0) @0100 A @0104 B eMIPS assembly lw $1,0x0100($0) lw $2, 0x0104($0) beq $1,$2, else_tag if_tag: add $3,$2,$1 beq $0,$0, store else_tag: sub $3,$2,$1 store: sw $3, 0x0200($0) Specifica aggiuntiva 2: memoria dati (t=fine simulaz) @0200 C Architetture dei Sistemi Embedded 2007/08 S.M. Carta PROGRAMMAZIONE ASSEMBLY: CICLI E VETTORI (1) SIMULAZIONI eMIPS_S3 ed eMIPS_S4: SPECIFICA C Specifica C integer acc; // dati a 32 bit integer a[16]; acc = 0; for( i=0; i<16;i++ ) acc=acc+a[i]; Specifica aggiuntiva 1: memoria dati (t=0) @100 a[0] @104 a[1] … @13C a[15] @400 0x1F @404 0x4 Specifica aggiuntiva 2: memoria dati (t=fine simulaz) @0200 acc Architetture dei Sistemi Embedded 2007/08 S.M. Carta 34 PROGRAMMAZIONE ASSEMBLY: CICLI E VETTORI (2) L'ESECUZIONE CICLICA (LOOP) VIENE GESTITA TRAMITE L'UTILIZZO DI UN REGISTRO DETTO INDICE CHE: VIENE INIZIALIZZATO ALL'ESTERNO DEL LOOP IN FUNZIONE DEL NUMERO DI ITERAZIONI DA ESEGUIRE VIENE AGGIORNATO AD OGNI ITERAZIONE DEL LOOP VIENE TESTATO AD OGNI ITERAZIONE DEL LOOP, IL TEST CHE VERIFICA LA FINE DEL CICLO NE INTERROMPE L'ESECUZIONE L'ACCESSO AGLI ELEMENTI DI UN VETTORE CON INDICE DIPENDENTE DALL'INDICE DEL LOOP PUO' ESSERE GESTITA TRAMITE UN REGISTRO DETTO PUNTATORE CHE: VIENE INIZIALIZZATO ALL'ESTERNO DEL LOOP VINE UTILIZZATO AD OGNI ITERAZIONE DEL LOOP PER COMPORRE L'INDIRIZZO DELLA LOCAZIONE CORRENTE VIENE AGGIORNATO AD OGNI ITERAZIONE DEL LOOP. L'AGGIORNAMENTO DIPENDE DAL NUMERO DI LOCAZIONI DI MEMORIA OCCUPATE DA CIASCUN ELEMENTO DEL VETTORE Architetture dei Sistemi Embedded 2007/08 S.M. Carta 35 PROGRAMMAZIONE ASSEMBLY: CICLI E VETTORI (3) SIMULAZIONE eMIPS_S3: CODIFICA ASSEMBLY UTILIZZO DEI REGISTRI $1 HA LA FUNZIONE DI REGISTRO ACCUMULATORE $2 HA LA FUNZIONE DI INDICE DEL LOOP $3 HA LA FUNZIONE DI PUNTATORE ALL'ELEMENTO CORRENTE DEL VETTORE $4 MEMORIZZA LA COSTANTE USATA PER AGGIORNARE IL REGISTRO INDICE $5 MEMORIZZA LA COSTANTE USATA PER AGGIORNARE IL REGISTRO PUNTATORE $6 MEMORIZZA LA COSTANTE USATA PER IL TEST DI FINE CICLO $7 HA LA FUNZIONE DI BUFFER TEMPORANEO LA SEQUENZA UTILIZZATA E' CRESCENTE, DALL'ELEMENTO 1 ALL'ELEMENTO 15. L'ELEMENTO 0 E' UTILIZZATO PER INIZIALIZZARE L'ACCUMULATORE Architetture dei Sistemi Embedded 2007/08 S.M. Carta 36 PROGRAMMAZIONE ASSEMBLY: CICLI E VETTORI (4) SIMULAZIONE eMIPS_S3: CODIFICA ASSEMBLY lw $1,0x100($0) ; inizializza il registro accumulatore $1 col dato a[0] add $2,$0,$0 ; inizializza il reg indice $2 a 0 add $3,$0,$0 ; inizializza il reg puntatore $3 a 0 lw $4,0x400($0) ; inizializza il reg $4 utilizzato per aggiornare il registro indice lw $5,0x404($0) ; inizializza il reg $5 utilizzato per aggiornare il reg puntatore lw $6,0x408($0) ; inizializza il registro utilizzato per il test di fine ciclo a 15=0xF loop: add $2,$2,$4 ; aggiorna il registro indice sommando 1 add $3,$3,$5 ; aggiorna il registro puntatore sommando 4 lw $7, 0x100($3); carica il dato a[i] sul registro buffer $7, la seq è 1,2,..,15. add $1,$1,$7 ; aggiorna l'accumulatore sommando il buffer beq $2,$6,store ; fa il test del registro indice, se $2=$6 interrompe il ciclo beq $0,$0, loop ; salta all'inizio del ciclo store: sw $1,0x200($0) ; scrive il risultato in memoria ;la coppia di istruzioni seguente provoca lo stop della simulazione lw $10, 0x500($0); sw $0, 0x0($10) ; Architetture dei Sistemi Embedded 2007/08 S.M. Carta 37 PROGRAMMAZIONE ASSEMBLY: CICLI E VETTORI (5) SIMULAZIONE eMIPS_S4: CODIFICA ASSEMBLY E' POSSIBILE UTILIZZARE UN SOLO REGISTRO CHE ACCORPI LE FUNZIONALITA' DI REGISTRO INDICE PER PER IL TEST DI FINE CICLO E DI REGISTRO PUNTATORE IN QUESTO CASO L'INIZIALIZZAZIONE E L'AGGIORNAMENTO DEL REGISTRO, NONCHE' IL TEST DI FINE CICLO, VANNO GESTITI IN FUNZIONE DEL FATTO CHE LA FUNZIONALITA' DI REGISTRO PUNTATORE RICHIEDE L'ACCESSO A DATI CHE POSSONO OCCUPARE PIU' LOCAZIONI DI MEMORIA Architetture dei Sistemi Embedded 2007/08 S.M. Carta 38 PROGRAMMAZIONE ASSEMBLY: CICLI E VETTORI (6) SIMULAZIONE eMIPS_S4: CODIFICA ASSEMBLY UTILIZZO DEI REGISTRI $1 HA LA FUNZIONE DI REGISTRO ACCUMULATORE $2 HA LA FUNZIONE DI INDICE DEL LOOP E ANCHE DI PUNTATORE ALL'ELEMENTO CORRENTE DEL VETTORE $3 HA LA FUNZIONE DI BUFFER TEMPORANEO $4 MEMORIZZA LA COSTANTE USATA PER AGGIORNARE IL REGISTRO INDICE-PUNTATORE LA SEQUENZA UTILIZZATA E' STAVOLTA DECRESCENTE, DALL'ELEMENTO 15 ALL'ELEMENTO 1. L'ELEMENTO 0 E' UTILIZZATO PER INIZIALIZZARE L'ACCUMULATORE Architetture dei Sistemi Embedded 2007/08 S.M. Carta 39 PROGRAMMAZIONE ASSEMBLY: CICLI E VETTORI (7) SIMULAZIONE eMIPS_S4: CODIFICA ASSEMBLY lw $1,0x100($0) ; inizializza l'accumulatore col dato a[0] lw $2,0x400($0) ; inizializza il reg indice/puntatore $2 lw $4,0x404($0) ; inizializza il reg utilizzato per aggiornare il reg indice/puntatore loop: lw $3, 0x100($2); carica il dato su $3, la seq è 15,14,..,1. sub $2,$2,$4 ; aggiorna il registro indice sottraendo 4 add $1,$1,$3 ; aggiorna l'accumulatore beq $2,$0,store ; fa il test del registro indice, se $2=0 interrompe il ciclo beq $0,$0, loop ; salta all'inizio del ciclo store: sw $1,0x200($0); scrive il risultato in memoria ;la coppia di istruzioni seguente provoca lo stop della simulazione lw $10, 0x500($0); sw $0, 0x0($10); Architetture dei Sistemi Embedded 2007/08 S.M. Carta 40 41 MIPS: TRADUZIONE ASSEMBLY -> LINGUAGGIO MACCHINA Architetture dei Sistemi Embedded 2007/08 S.M. Carta 42 MIPS: TRADUZIONE ASSEMBLY => LINGUAGGIO MACCHINA CODIFICA IN LINGUAGGIO MACCHINA: eMIPS_S2-ISTR #0 lw $1, 0x100($0) // inizializza l’accumulatore col dato a[0] Istruzioni I-type: lw Rt, Imm(Rs) ASM BIN BIN HEX HEX opcode Rs Rt Immediate 6 bit 5 bit 5 bit 16 bit Op=6h’23 Rs=$0 Rt=$1 Imm=16h’100 100011 00000 00001 0000000100000000 1000 1100 0000 0001 0000 0001 0000 0000 8 c 0 1 0 1 0 0 8c010100 Architetture dei Sistemi Embedded 2007/08 S.M. Carta 43 MIPS: TRADUZIONE ASSEMBLY => LINGUAGGIO MACCHINA CODIFICA IN LINGUAGGIO MACCHINA: eMIPS_S2-ISTR #1 lw $2, 0x104($0) // inizializza l’accumulatore col dato a[0] Istruzioni I-type: lw Rt, Imm(Rs) ASM BIN BIN HEX HEX opcode Rs Rt Immediate 6 bit 5 bit 5 bit 16 bit Op=6h’23 Rs=$0 Rt=$2 Imm=16h’104 100011 00000 00010 0000000100000100 1000 1100 0000 0010 0000 0001 0000 0100 8 c 0 2 0 1 0 4 8c020104 Architetture dei Sistemi Embedded 2007/08 S.M. Carta 44 FRAMEWORK PER L'ESECUZIONE DI APPLICAZIONI ASSEMBLY SUL MODELLO VERILOG DI UN SISTEMA DI ELABORAZIONE BASATO SUL PROCESSORE eMIPS-sc Architetture dei Sistemi Embedded 2007/08 S.M. Carta 45 MODELLO VERILOG DEL PROCESSORE MODELLO VERILOG DEL SISTEMA COMPLETO La gerarchia del modello verilog del sistema è la seguente: testbench.v (istanza testbench) instructions_ROM.v (istanza InstrROM) data_RAM.v (istanza DataRAM) eMIPS_sc.v (istanza MIPS) pc_reg.v (istanza PC) pc_adder.v (istanza NPC) .... Architetture dei Sistemi Embedded 2007/08 S.M. Carta 46 FRAMEWORK DI SVILUPPO (I) MIPS ASSEMBLER file instructions.hex MEMORIA ISTRUZIONI (MODELLO VERILOG) DATI INIZIALI CON CONVERSIONE IN UN FORMATO LEGGIBILE DAL SIMULATORE VERILOG (READMEMH) INSTRUCTIONS BUS INSTR ADDRESSES DATA MIPS (MODELLO VERILOG) BUS DATA ADDRESSES BUS BUS CONVERSIONE IN UN FORMATO LEGGIBILE DAL SIMULATORE VERILOG (READMEMH) Architetture dei Sistemi Embedded 2007/08 CODICE ASSEMBLY MEMORIA DATI (MODELLO VERILOG) SIMULATORE VERILOG (MODELSIM) file data_RAM.hex S.M. Carta 47 FRAMEWORK DI SVILUPPO (II) STRUTTURA DI FILE E DIRECTORY eMIPS-sc_S3 S1.mpf compila.bat eMIPS_S3.asm HEX instructions.hex data_ram.hex ASM file eseguibili dell'assembler..... VERILOG testbench_eMIPS_S3.v Memories eMIPS-sc Architetture dei Sistemi Embedded 2007/08 S.M. Carta 48 ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based SPECIFICA MISTA C-ASSEMBLY, UTILIZZO DELLA MEMORIA A BASSO LIVELLO, CONVENZIONI DI CHIAMATA A SUBROUTINE Architetture dei Sistemi Embedded 2007/08 S.M. Carta 49 INTERFACCIA HW/SW L’utilizzo di programmi scritti in linguaggi ad alto livello (c/c++) sul processore di un sistema embedded richiede la specifica di una serie di informazioni supplementari (dimensione della memoria, partizionamento e mappa della memoria, routine di boot, routine di interrupt, ecc.) che non possono essere definite a livello di software c stesso, ma vanno definite a livello assembly-sistema operativo. Si rende necessaria l’integrazione di specifiche scritte a livelli diversi: c e assembly Si rende inoltre necessario la conoscenza della strategia usata dal compilatore c utilizzato (nel nostro caso il gcc 2.95.3) per la gestione a basso livello della memoria Architetture dei Sistemi Embedded 2007/08 S.M. Carta 50 INTERFACCIA HW/SW Per fissare i primi concetti legati al funzionamento del compilatore e all'utilizzo dei tool di compilazione semplificati (compilatore + assembler) sviluppati per questo corso, utilizzeremo un semplice sistema processorememoria senza periferiche La microarchitettura MIPS che utilizzeremo è la MIPS-mc. L'architettura di memoria di Von Neumann: vi è una sola memoria condivisa da dati ed istruzioni WriteEnable Signal global clk MIPS-mc Instructions / Data Buses reset System Architetture dei Sistemi Embedded 2007/08 INSTRUCTIONS / DATA MEMORY Addresses Bus S.M. Carta 51 GESTIONE DELLA MEMORIA PER I SISTEMI MONOPROGRAMMATI IN MODALITA’ REALE Architetture dei Sistemi Embedded 2007/08 S.M. Carta 52 INTERFACCIA HW/SW CONVENZIONI PER LA GESTIONE DELLA MEMORIA Architetture dei Sistemi Embedded 2007/08 S.M. Carta 53 INTERFACCIA HW/SW UTILIZZO DELLA MEMORIA (VERSIONE SEMPLIFICATA) (I) Il compilatore utilizza la memoria dividendola in due parti: lo Stack e lo Heap. Lo stack è la porzione di memoria gestita automaticamente dal processore, inizia a partire dalle locazioni con indirizzo più alto e ha una dimensione variabile in funzione dello spazio di cui ha bisogno il programma. Lo heap è invece la zona di memoria gestita dinamicamente, con le funzioni malloc e calloc. Lo Heap inizia dalle locazioni di memoria più basse e si riempie verso locazioni di indirizzo più elevato. Non avendo a disposizione le funzioni di libreria malloc e calloc allocheremo i dati in memoria in maniera esplicita tramite i puntatori. Utilizzeremo inoltre una zona di memoria per il salvataggio dei dati relativi alle routine di interrupt o ad altre routine speciali. Chiameremo la memoria utilizzata in questo modo MEMORIA ALLOCATA MANUALMENTE (MAM) In un sistema di Von Neumann, la parte della memoria di indirizzi più bassi, da zero in poi, viene utilizzata per le istruzioni. Architetture dei Sistemi Embedded 2007/08 S.M. Carta 54 INTERFACCIA HW/SW UTILIZZO DELLA MEMORIA (VERSIONE SEMPLIFICATA) (II) A partire dagli indirizzi di memoria più alti sta la funzione main, il compilatore alloca ricorsivamente lo spazio per le procedure allocando e disallocando zone di memoria. Ogni procedura ha a disposizione una zona di memoria privata definita frame di attivazione. Lo spazio dei frame di attivazione è lo stack La memoria di tipo dinamico viene allocata a partire dagli indirizzi bassi e si espande verso quelli alti, a partire da un certo indirizzo in poi. La MAM si può allocare o fra lo heap (sotto lo heap) e la memoria istruzioni (sopra la mem istruzioni) oppure sopra lo stack Per sistemi a memoria condivisa fra dati ed istruzioni la parte più bassa della memoria è dedicata alle istruzioni. Architetture dei Sistemi Embedded 2007/08 TOP OF MEMORY main FP M.A.M. MAIN DATA FUNC 1 DATA MEMORIA DATI GESTITA DAL COMPILATORE STACK: MEMORIA AUTOMATICA ALLOCATA DAL COMPILATORE FUNC 2 DATA HEAP HEAP: MEMORIA DINAMICA ALLOCATA DAL COMPILATORE TRAMITE MALLOC O CALLOC M.A.M. SPAZIO ISTRUZIONI TEXT locazione 0 S.M. Carta INTERFACCIA HW/SW MECCANISMO DI CHIAMATA DI PROCEDURA Un opportuno sottoinsieme delle istruzioni dell'IS MIPS viene utilizzato per supportare la chiamata di una procedura (funzione), ed una volta terminata la sua esecuzione, il ritorno alla istruzione successiva alla chiamata Ogni volta che deve essere convertita in assembly una chiamata a funzione viene utilizzata una istruzione che forza il salto all'indirizzo della prima istruzione della procedura, e simultaneamente salva quello dell'istruzione successiva nel registro $31. Tale istruzione è jal label_procedura Ogni procedura deve terminare con una istruzione che forza il valore del PC all'indirizzo della istruzione successiva a quella di chiamata, cioè all'indirizzo salvato in $31. Tale istruzione è jr $31 Per gestire la possibilità che una funzione ne chiami a sua volta un'altra, sovrascrivendo l'indirizzo di ritorno in $31, è necessario che questo venga salvato in memoria E' necessaria una convenzione che definisca come salvare in memoria l'indirizzo di ritorno nonchè i parametri passati alla procedura, i dati locali, ecc. Architetture dei Sistemi Embedded 2007/08 S.M. Carta 55 56 INTERFACCIA HW-SW GESTIONE DELLO STACK (I) Quando viene eseguita una funzione viene riservata ad essa una porzione dello stack detta frame. La dimensione del frame dipende dal numero di dati relativi alla funzione che è necessario scrivere in memoria FRAME$30POINTER e può essere anche nulla se non ci sono dati da memorizzare. Le informazioni da memorizzare per ogni frame sono: parametri della funzione invocata oltre il quarto (i primi quattro parametri sono salvati nei registri da $4 a $7) indirizzo di ritorno dati locali della funzione registri temporanei che verranno sovrascritti durante l'esecuzione della funzione Architetture dei Sistemi Embedded 2007/08 $29 STACK POINTER PARAMETRO N PARAMETRO 5 PARAMETRI DELLA FUNZIONE (oltre il quarto) FP DELLA FUNZ CHIAMANTE INDIRIZZO DI RITORNO LOCAL DATA 1 DATI LOCALI DELLA FUNZIONE LOCAL DATA N VALORE SALVATO DI $8 VALORE SALVATO DI $n S.M. Carta VALORE SALVATO DEI REGISTRI UTILIZZATI DURANTE LA FUNZIONE 57 INTERFACCIA HW-SW CONVENZIONE DI CHIAMATA DI PROCEDURA PER MIPS Architetture dei Sistemi Embedded 2007/08 S.M. Carta 58 INTERFACCIA HW-SW GESTIONE DELLO STACK (II) ESEMPIO void _main( void ) { int a[2]; int i; int *pointer; pointer = (int*) 0x1000; for( i=0; i<2; i++) a[i] = i; *pointer = a[0]+a[1]; } Architetture dei Sistemi Embedded 2007/08 S.M. Carta 59 INTERFACCIA HW-SW GESTIONE DELLO STACK (III) ESEMPIO alloca la memoria per il frame di attivazione del main. La dim minima è di 16 locazioni. main: ;# vars= 16, regs= 0/0, args= 0, extra= 0 subu $sp,$sp,16 li $3,1 addu $2,$sp,4 $L6: sw addu addu bgez lw lw #nop addu sw addu j .end $3,0($2) $2,$2,-4 $3,$3,-1 $3,$L6 $2,0($sp) $3,4($sp) $2,$2,$3 $2,4096 $sp,$sp,16 $31 _main .. Architetture dei Sistemi Embedded 2007/08 inizializza i registri che utilizzerà come indici esegue il loop, usa $2 come puntatore alla locazione dell'elemento del vettore utilizzato ed $3 come indice per il conteggio. Calcola il valore degli elementi del vettore e li salva nello stack carica gli elementi del vettore dallo stack, calcola la somma e la salva nella MAM dealloca la memoria (frame di attivazione del main) e ripristina il PC S.M. Carta 60 INTERFACCIA HW-SW GESTIONE DELLO STACK (IV) Il frame viene gestito attraverso due registri che sono utilizzati come puntatori: lo Stack Pointer ($sp), che punta all’indirizzo della locazione più bassa del frame, e il Frame Pointer ($fp), che punta alla locazione più alta. Mentre il primo è indispensabile il secondo può in certi casi non essere utilizzato a seconda del compilatore, del livello di ottimizzazione utilizzato e del programma in esecuzione. Lo stack pointer serve da riferimento per accedere alle locazioni del frame: per esempio una scrittura su una locazione del frame verrà specificata con: sw $31,20($sp) Le informazioni sul numero di dati da salvare in memoria sono forniti dal compilatore come commenti nel programma assembly in uscita. #vars indica il numero di locazioni utilizzate per memorizzare le variabili locali. Se non sono dichiarati arrays questo numero è nullo. #regs indica il numero di registri che devono essere salvati in memoria. In genere non ce ne sono se non viene invocata una funzione. #args indica il numero di locazioni destinate ai parametri di una funzione invocata. Se non viene invocata nessuna funzione questo numero è zero ma se viene invocata una funzione questo numero è sempre maggiore o uguale a 16, anche se la funzione invocata non ha parametri. Architetture dei Sistemi Embedded 2007/08 S.M. Carta 61 INTERFACCIA HW-SW GESTIONE DELLO STACK (V) All’inizio dell’esecuzione del programma lo Stack Pointer punta all’indirizzo successivo a quello più alto in memoria, perché lo stack deve occupare la memoria a partire dagli indirizzi più alti. Le prime istruzioni prodotte dal compilatore riguardano la gestione automatica di memoria e registri. Ogni funzione, se ha bisogno di dati da memorizzare, inizia con l’istruzione che fa scendere lo Stack Pointer in modo da allocare lo spazio sufficiente. Seguono eventualmente i salvataggi dei registri che saranno sovrascritti. La chiamata a funzione inizia sempre con un istruzione jal che porta il processore ad eseguire la prima istruzione della funzione chiamata. A questo punto viene creato un altro frame e così via. Alla fine di ogni funzione l’eventuale valore restituito viene scritto sul registro $2 o $3, vengono ripristinati i registri sovrascritti con i valori salvati in memoria e viene deallocato il frame riportando lo stack pointer alla posizione che aveva prima della chiamata a funzione. Con l’istruzione Jr $ra si torna alla funzione chiamante. Architetture dei Sistemi Embedded 2007/08 S.M. Carta 62 INTERFACCIA HW-SW SPECIFICA C E BOOT FILE Anche il main viene gestito come una funzione qualunque. Ma come viene effettuata la chiamata al main? Nel caso di Sistema Operativo, vi saranno un assembler ed un linker che si occupano di gestire la cosa in maniera trasparente per il programmatore Nel nostro caso vogliamo che tutto sia gestito in maniera esplicita, non vi è un SO e neppure un vero linker. La chiamata del main viene eseguita tramite una specifica assembly separata codificata in un file detto file di boot Tale file verrà unito alla traduzione assembly della specifica c dando vita ad una specifica assembly completa, su singolo file, che può essere tradotta in linguaggio macchina (cioè nel file di codifica delle locazioni di memoria dedicate alle istruzioni) Architetture dei Sistemi Embedded 2007/08 S.M. Carta 63 INTERFACCIA HW-SW FILE DI BOOT Il file di boot che utilizzeremo inizialmente si occupa esclusivamente delle cose essenziali, vedremo in seguito delle specifiche più complete La prima istruzione salta sempre alla routine di inizializzazione del sistema, che in questo caso consiste solo nell'inizializzazione dello stack pointer Una volta inizializzato il sistema viene eseguita la chiamata del main Quando si vuole che lo stack allocato automaticamente dal compilatore si estenda a partire dalle locazioni di indirizzo massimo della memoria, il valore di inizializzazione dello stack pointer coincide con la dimensione della memoria J RESET_HANDLER RESET_HANDLER: ; routine di inizializzazione del sistema li $29,0x3000; ; inizializzazione dello stack pointer ; fine della routine di inizializzazione jal _main ; avvia l'esecuzione del programma principale ; La simulazione termina con il blocco del PC stop: j stop Architetture dei Sistemi Embedded 2007/08 S.M. Carta 64 ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based: FRAMEWORK UTILIZZATO PER COMPILAZIONE E SIMULAZIONE Architetture dei Sistemi Embedded 2007/08 S.M. Carta 65 ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based FRAMEWORK DI SVILUPPO (I) c_code.c mips_gcc.exe -o c_code.asm -O2 -fno-delayed-branch -S c_code.c c compiler c_code.asm boot.asm link instructions.asm c_code.asm boot.asm merge instructions.asm mips_asm instructions.asm instructions.hex instructions.hex Architetture dei Sistemi Embedded 2007/08 assembler Sono necessari 2 file sorgenti (c_code.c e boot.asm), vengono creati 2 file intermedi (c_code.asm e instructions.asm) per ottenere un file di codifica delle istruzioni (instructions.hex). Vengono utilizzati un compilatore c (gcc 2.95.3), un assembler (ad hoc) ed una piccola utility che fa il merge L’utility merge si limita ad unire i file assembly mettendo le istruzioni di ciascun file in sequenza in un unica file S.M. Carta 66 ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based FRAMEWORK DI SVILUPPO (II) Utilizzando la seguente struttura di file e cartelle La cartella principale contiene le 2 sottocartelle HEX e VERILOG e il file del progetto con allegata la sottocartella work La cartella HEX contiene i file sorgente (mips_S1.c e mips_S1_boot.asm), il file batch che esegue tutti i task (compila.bat), il file che codifica l'inizializzazione della la memoria istruzioni e le sottocartelle GCC e ASM I file eseguibili dell'assembler sono nella sottocartella HEX\ASM I file eseguibili del compilatore sono nella sottocartella HEX\GCC La cartella VERILOG contiene il modello verilog del sistema Architetture dei Sistemi Embedded 2007/08 S.M. Carta 67 ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based FRAMEWORK DI SVILUPPO (III): file compila.bat echi off set NOME_APPLICAZIONE=MIPS_s1 cd HEX copy %NOME_APPLICAZIONE%.c .\GCC\c_code.c copy %NOME_APPLICAZIONE%_boot.asm .\ASM\boot.asm cd GCC mips_gcc.exe -o c_code.asm -O2 -fno-delayed-branch -S c_code.c pause copy c_code.asm ..\ASM\ cd ..\ASM copy /B boot.asm + c_code.asm instructions.asm copy instructions.asm ..\ @bash -rcfile mipsprofile mipsAsm.sh %1 %2 instructions.asm instructions.hex pause copy instructions.hex ..\ cd ..\ type instructions.hex pause del .\GCC\c_code.c del .\GCC\c_code.asm .... Architetture dei Sistemi Embedded 2007/08 S.M. Carta 68 SIMULAZIONE 1: ASSEGNAMENTO DI VALORI AD UN VETTORE Architetture dei Sistemi Embedded 2007/08 S.M. Carta 69 ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based La memoria utilizzata (unica per dati ed istruzioni) è di 0x3000=12888 locazioni. Lo spazio riservato alle istruzioni è di 0x1000=4096 locazioni locazione 0x2FFC void _main( void ) { int a[2]; int i; int *pointer; pointer = (int*) 0x1000; STACK WriteEnable Signal global clk MIPS-mc Instructions / Data Buses reset System for( i=0; i<2; i++) a[i] = i; *pointer = a[0]+a[1]; } Architetture dei Sistemi Embedded 2007/08 INSTRUCTIONS / DATA MEMORY Addresses Bus MAM locazione 0x1000 ISTRUZIONI locazione 0x0000 S.M. Carta ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based J RESET_HANDLER RESET_HANDLER: ; routine di inizializzazione addi $29,$0,0x3000; ; inizializza lo stack pointer jal _main ; avvia l'esecuzione del main ; La simulazione termina con il blocco del PC stop: j stop _main: ;# vars= 16, regs= 0/0, args= 0, extra= 0 subu $sp,$sp,16 li $3,1 addu $2,$sp,4 $L6: sw addu addu bgez lw lw #nop addu sw addu j .end $3,0($2) $2,$2,-4 $3,$3,-1 $3,$L6 $2,0($sp) $3,4($sp) $2,$2,$3 $2,4096 $sp,$sp,16 $31 _main .. Architetture dei Sistemi Embedded 2007/08 inizializzazione e salto al main alloca la memoria per il frame di attivazione del main. La dim minima è di 16 locazioni. inizializza i registri che utilizzerà come indici esegue il loop, usa $2 come puntatore alla locazione dell'elemento del vettore utilizzato ed $3 come indice per il conteggio. Calcola il valore degli elementi del vettore e li salva nello stack carica gli elementi del vettore dallo stack, calcola la somma e la salva nella MAM dealloca la memoria (frame di attivazione del main) e ripristina il PC S.M. Carta 70 71 SIMULAZIONE 2: CHIAMATA A FUNZIONE Architetture dei Sistemi Embedded 2007/08 S.M. Carta 72 ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based La memoria (unica per dati ed istruzioni) utilizzata è di 0x3000=12888 locazioni. Lo spazio riservato alle istruzioni è di 0x1000=4096 locazioni #define dim 4 void _main( void ) { int a[dim]; int i, *max; for( i=0; i<dim; i++) a[i] = i; max = (int*) 0x1000; *max = max_func(a,dim); int max_func(int* vector, int size) { int max,i; max = 0; for( i=0; i<size; i++) if (vector[i] > max) max = vector[i]; return (max); } } Architetture dei Sistemi Embedded 2007/08 S.M. Carta 73 SIMULAZIONE 3: MEMORIA AUTOMATICA E MEMORIA ALLOCATA MANUALMENTE Architetture dei Sistemi Embedded 2007/08 S.M. Carta 74 ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based La memoria (unica per dati ed istruzioni) utilizzata è di 0x3000=12288 locazioni. Lo spazio riservato alle istruzioni è di 0x1000=4096 locazioni #define size 4 void _main( void ) { int *dinamic_v; int automatic_v[size]; int i; for( i=0; i<size; i++) automatic_v[i] = 10+i; dinamic_v = (int*) 0x1000; for( i=0; i<size; i++) dinamic_v[i] = automatic_v[i]; } Architetture dei Sistemi Embedded 2007/08 S.M. Carta 75 ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based: DEBUG DELLE APPLICAZIONI Architetture dei Sistemi Embedded 2007/08 S.M. Carta ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based76 DEBUG DI SOFTWARE EMBEDDED Il debug di software per sistemi embedded presenta delle difficoltà aggiuntive rispetto al debug di sw per piattaforma PC. E’ spesso impossibile definire le condizioni al contorno del SW in maniera puramente SW (gestione delle condizioni di interrupt, della mappa della memoria che è legata alla tipologia del sistema, ecc.). E’ indispensabile un sistema di sviluppo di tipo HW-SW che consenta al SW embedded di interagire in tempo reale con l’HW di contorno al processore. Nel caso di sistemi embedded di tipo SoB (System on Board) la fase finale dello sviluppo SW è basate su sistemi di In-Circuit Emulation (ICE). Nel caso di sistemi embedded di tipo SoC (System on Chip) si usa l’evoluzione dei sistemi ICE. Si parla di sistemi embedded ICE I sistemi ICE sono basati su un dispositivo hardware (emulatore) che implementa la funzionalità del processore (e può quindi venire inserito nel sistema) ma in aggiunta manda in output tutta una serie di informazioni sul suo funzionamento interno (valore dei registri, valori sui bus e sulle porte di I/O, ecc.). L'emulatore è collegato ad una stazione di debug (un PC o una workstation) che può memorizzare tutte le informazioni utili per il debug Il programmatore può monitorare le informazioni relative all'esecuzione, in modo da rilevare e correggere eventuali (!) malfunzionamenti Architetture dei Sistemi Embedded 2007/08 S.M. Carta ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based77 DEBUG DI SOFTWARE EMBEDDED Nel nostro caso, abbiamo a disposizione un simulatore verilog che emula il funzionamento del processore e di tutto il sistema (quindi un emulatore completo. Utilizzeremo una tecnica che sfrutta l’inserimento di routine C dedicate che cooperano con processi verilog ad-hoc situati nel testbench. Anche i sistemi ICE funzionano con tecniche di questo tipo Utilizzeremo degli strumenti (breakpoints) inseribili a livello di codice c che consentono di stoppare la simulazione e di visualizzare : Il valore assunto da segnali, bus, porte di moduli, registri, ecc. (controllo a livello HW) Il contenuto dei registri interni del processore, delle locazioni mappate in memoria, dei segnali di interrupt, e dei segnali di I/O (controllo a livello FW) Il valore assunto dalle variabili, dalle locazioni mappate in memoria, dai segnali di interrupt, e dai segnali di I/O (controllo a livello SW) Architetture dei Sistemi Embedded 2007/08 S.M. Carta ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based78 DEBUG DI SOFTWARE EMBEDDED: BREAKPONTS L'inserimento di un breakpoint consente di stoppare la simulazione Questa funzionalità è stata implementata tramite una funzione c che accoppiata ad un processo verilog nel testbench che stoppa la simulazione eseguendo una istruzione $stop. La funzione c (denominata breakpoint()) scrive il valore 0x1 sulla locazione 0x7FFF. La scrittura non ha alcun esito poichè non vi è alcuna locazione di memoria a quell'indirizzo (E' vero per il nostro sistema. Per altri sistemi si possono usare altre locazioni o altri tipi di tecniche) Il processo dedicato esegue la funzione stop ogni volta che si verifica questo tentativo di scrittura C LEVEL - descrizione della routine void breakpoint(void) { int *p_out; p_out = (int*) 0x7FFF ; *p_out = 0x1 ; } C LEVEL - FRAMMENTO DI CODICE ... breakpoint(); ... VERILOG LEVEL - PROCESSO DEDICATO PER IL BREAKPOINT always @(posedge clk) if ( (addr_bus == (32'h7FFF)) && (MemWrite == 1)) $stop; Architetture dei Sistemi Embedded 2007/08 S.M. Carta ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based79 DEBUG DI SOFTWARE EMBEDDED: WATCH FIRMWARE I sistemi di sviluppo dei compilatori mettono a disposizione la possibilità di visualizzare il contenuto di registri interni, locazioni della memoria, ecc. Questa funzionalità è stata implementata tramite una funzione c che accoppiata ad un processo verilog nel testbench che esegue una serie di display e stoppa la simulazione eseguendo una istruzione $stop. La funzione c (denominata watch_fw()) scrive il valore 0x2 sulla locazione 0x7FFF. La scrittura non ha alcun esito poichè non vi è alcuna locazione di memoria a quell'indirizzo (..) Il processo dedicato esegue la funzione stop e visualizza le locazioni ed i registri di interesse (da definire di volta in volta) ogni volta che si verifica questo tentativo di scrittura C LEVEL - descrizione della routine void watch_fw(void) { int *p_out; p_out = (int*) 0x7FFF ; *p_out = 0x2 ; } C LEVEL - FRAMMENTO DI CODICE ... watch_fw(); ... VERILOG LEVEL - PROCESSO DEDICATO PER IL BREAKPOINT always @(posedge clk) if ( (addr_bus == (32'h7FFF)) && (MemWrite == 1)) begin $display(" $1 = 0x%x =%d",MIPS.REGFILE.data[1], MIPS.REGFILE.data[1]); $display(" $2 = 0x%x =%d",MIPS.REGFILE.data[2], MIPS.REGFILE.data[2]); $stop; end Architetture dei Sistemi Embedded 2007/08 S.M. Carta ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based80 DEBUG DI SOFTWARE EMBEDDED: WATCH SOFTWARE I sistemi di sviluppo dei compilatori mettono a disposizione la possibilità di visualizzare il assunto dalle variabili nel corso dell'esecuzione. Questa funzionalità è stata implementata tramite una funzione c che accoppiata ad un processo verilog nel testbench che esegue un display e stoppa la simulazione eseguendo una istruzione $stop. La funzione c (denominata watch_sw()) scrive il valore della variabile sulla locazione 0x7FF0 codice della variabile. La scrittura non ha alcun esito poichè non vi è alcuna locazione di memoria a quell'indirizzo (..) Il processo dedicato esegue la funzione stop e visualizza il valore della variabile di interesse (da definire di volta in volta) ogni volta che si verifica questo tentativo di scrittura C LEVEL - descrizione della routine void watch_sw(int var, int var_code) { int *p_out; p_out = (int*) (0x7FF0 - var_code); *p_out = var; } C LEVEL - FRAMMENTO DI CODICE (p.e. variabile con codice 3) ... watch_sw(pippo,3); ... watch_sw(pluto,2); VERILOG LEVEL - PROCESSO DEDICATO PER LA VISUALIZZAZIONE DELLA VAR CON CODICE 3 always @(posedge clk) if ( (addr_bus == (32'h7FF0 - 3 )) && (MemWrite == 1)) begin $display(" var #3 = 0x%x =%d", proc_dout_bus, proc_dout_bus); $stop; end Architetture dei Sistemi Embedded 2007/08 S.M. Carta ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based81 DEBUG DI SOFTWARE EMBEDDED Quelli illustrati sono solo 3 possibili esempi di tecniche utilizzabili per il debug in un sistema di emulazione come il nostro E' possibile mischiare le modalità di visualizzazione, di stop della simulazione, il salvataggio delle grandezze temporanee della simulazione di interesse su file, associare alle grandezze il tempo di simulazione o altre grandezze stesse ecc. Disponendo di un modello del processore a basso livello ed avendo la possibilità di visualizzare qualunque segnale, siamo simo infatti in grado di monitorare qualunque grandezza in qualunque condizione o insieme di condizioni ci interessi. Utilizzando sistemi ICE reali le possibilità sono più limitate. In questi casi comunque si tratta di debuggare solo l'applicazione e al limite le periferiche, mai il processore stesso. Il sistema da noi adottato ha permesso il debug anzitutto del processore Architetture dei Sistemi Embedded 2007/08 S.M. Carta 82 SIMULAZIONE 4: CALCOLO DEL MASSIMO CON INSERIMENTO DI FUNZIONE DI DEBUG PER IL MONITORAGGIO DEL MASSIMO TEMPORANEO Architetture dei Sistemi Embedded 2007/08 S.M. Carta 83 ESECUZIONE DI APPLICAZIONI SU SISTEMI EMBEDDED MIPS-based La memoria (unica per dati ed istruzioni) utilizzata è di 0x3000=12888 locazioni. Lo spazio riservato alle istruzioni è di 0x1000=4096 locazioni #define size 16 void _main( void ) { int a[size]; int i, *max; dim = 4; for( i=0; i<dim; i++) a[i] = (i-5)*(i-5); max = (int*) 0x1000; *max = max_func(a,dim); } Architetture dei Sistemi Embedded 2007/08 void watch_sw(int var, int var_code) { int *p_out; p_out = (int*) (0x7FF0 - var_code); *p_out = var; } int max_func(int* vector, int dim) { int max,i; max = 0; for( i=0; i<dim; i++) { if (vector[i] > max) { max = vector[i]; watch_sw(max, 1)} } return (max); } S.M. Carta