Framework and debug

Transcript

Framework and debug
64
ESECUZIONE DI APPLICAZIONI SU
SISTEMI EMBEDDED MIPS-based:
FRAMEWORK UTILIZZATO PER
COMPILAZIONE E SIMULAZIONE
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
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
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
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
....
68
SIMULAZIONE 1:
ASSEGNAMENTO DI
VALORI AD UN VETTORE
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
reset
System
for( i=0; i<2; i++)
a[i] = i;
*pointer = a[0]+a[1];
}
Instructions / Data
Buses
INSTRUCTIONS
/ DATA
MEMORY
Addresses
Bus
MAM
locazione 0x1000
ISTRUZIONI
locazione 0x0000
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
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
70
71
SIMULAZIONE 2:
CHIAMATA A FUNZIONE
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);
}
73
SIMULAZIONE 3:
MEMORIA AUTOMATICA
E
MEMORIA ALLOCATA
MANUALMENTE
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
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
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)
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;
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
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
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
82
SIMULAZIONE 4:
CALCOLO DEL MASSIMO CON
INSERIMENTO DI
FUNZIONE DI DEBUG PER IL
MONITORAGGIO DEL MASSIMO
TEMPORANEO
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);
}
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);
}