/* toplevel.c -- Top level simulator source file
|
/* toplevel.c -- Top level simulator source file
|
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
|
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
|
|
|
This file is part of OpenRISC 1000 Architectural Simulator.
|
This file is part of OpenRISC 1000 Architectural Simulator.
|
|
|
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
(at your option) any later version.
|
(at your option) any later version.
|
|
|
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
GNU General Public License for more details.
|
GNU General Public License for more details.
|
|
|
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
/* Simulator commands. Help and version output. SIGINT processing.
|
/* Simulator commands. Help and version output. SIGINT processing.
|
Stdout redirection is specific to linux (I need to fix this). */
|
Stdout redirection is specific to linux (I need to fix this). */
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <ctype.h>
|
#include <ctype.h>
|
#include <string.h>
|
#include <string.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <signal.h>
|
#include <signal.h>
|
#include <stdarg.h>
|
#include <stdarg.h>
|
|
|
#include "arch.h"
|
#include "arch.h"
|
#include "parse.h"
|
#include "parse.h"
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "trace.h"
|
#include "trace.h"
|
#include "execute.h"
|
#include "execute.h"
|
|
|
/* CVS revision number. */
|
/* CVS revision number. */
|
static const char rcsrev[] = "$Revision: 1.1.1.1 $";
|
static const char rcsrev[] = "$Revision: 1.2 $";
|
|
|
/* Continuos run versus single step tracing switch. */
|
/* Continuos run versus single step tracing switch. */
|
int cont_run;
|
int cont_run;
|
|
|
/* History of execution */
|
/* History of execution */
|
int histexec[HISTEXEC_LEN];
|
int histexec[HISTEXEC_LEN];
|
|
|
void debug(const char *format, ...)
|
void debug(const char *format, ...)
|
{
|
{
|
#if DEBUG
|
#if DEBUG
|
char *p;
|
char *p;
|
va_list ap;
|
va_list ap;
|
|
|
if ((p = malloc(1000)) == NULL)
|
if ((p = malloc(1000)) == NULL)
|
return;
|
return;
|
va_start(ap, format);
|
va_start(ap, format);
|
(void) vsnprintf(p, 1000, format, ap);
|
(void) vsnprintf(p, 1000, format, ap);
|
va_end(ap);
|
va_end(ap);
|
printf("%s\n", p);
|
printf("%s\n", p);
|
fflush(stdout);
|
fflush(stdout);
|
free(p);
|
free(p);
|
#endif
|
#endif
|
return;
|
return;
|
}
|
}
|
|
|
void ctrl_c(int signum)
|
void ctrl_c(int signum)
|
{
|
{
|
cont_run = 1;
|
cont_run = 1;
|
signal(SIGINT, ctrl_c);
|
signal(SIGINT, ctrl_c);
|
}
|
}
|
|
|
void version()
|
void version()
|
{
|
{
|
printf("\n");
|
printf("\n");
|
printf("OpenRISC 1000 Architectural Simulator, revision %s\n", rcsrev);
|
printf("OpenRISC 1000 Architectural Simulator, revision %s\n", rcsrev);
|
printf("Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n");
|
printf("Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n");
|
printf("Visit http://www.opencores.org for more information about ");
|
printf("Visit http://www.opencores.org for more information about ");
|
printf("OpenRISC 1000 and\nother open source cores.\n\n");
|
printf("OpenRISC 1000 and\nother open source cores.\n\n");
|
printf("This software comes with ABSOLUTELY NO WARRANTY; for ");
|
printf("This software comes with ABSOLUTELY NO WARRANTY; for ");
|
printf("details see COPYING.\nThis is free software, and you ");
|
printf("details see COPYING.\nThis is free software, and you ");
|
printf("are welcome to redistribute it under certain\nconditions; ");
|
printf("are welcome to redistribute it under certain\nconditions; ");
|
printf("for details see COPYING.\n");
|
printf("for details see COPYING.\n");
|
}
|
}
|
|
|
void help()
|
void help()
|
{
|
{
|
printf("q - quit simulator\n");
|
printf("q - quit simulator\n");
|
printf("r - display all registers\n");
|
printf("r - display all registers\n");
|
printf("t - execute next instruction\n");
|
printf("t - execute next instruction\n");
|
printf("run <cycles> [<hush>] - execute <cycles> instructions, no reg dump if hush\n");
|
printf("run <cycles> [<hush>] - execute <cycles> instructions, no reg dump if hush\n");
|
printf("pr <r> <value> - patch register <r> with <value>\n");
|
printf("pr <r> <value> - patch register <r> with <value>\n");
|
printf("dm <fromaddr> [<toaddr>] - display memory from <fromaddr> to <toaddr>\n");
|
printf("dm <fromaddr> [<toaddr>] - display memory from <fromaddr> to <toaddr>\n");
|
printf("pm <addr> <value> - patch memory location <addr> with <value>\n");
|
printf("pm <addr> <value> - patch memory location <addr> with <value>\n");
|
printf("pc <value> - patch PC register with <value>\n");
|
printf("pc <value> - patch PC register with <value>\n");
|
printf("brk <addr> - toggle breakpoint at address <addr>\n");
|
printf("brk <addr> - toggle breakpoint at address <addr>\n");
|
printf("hist - execution history\n");
|
printf("hist - execution history\n");
|
|
printf("stats <num|clear> - execution statistics num or clear it.\n");
|
|
printf("info - configuration info (caches etc.)\n");
|
printf("<cmd> > <filename> - redirect simulator stdout to <filename> (and not emulated printf)\n");
|
printf("<cmd> > <filename> - redirect simulator stdout to <filename> (and not emulated printf)\n");
|
printf("help - available commands (this list)\n");
|
printf("help - available commands (this list)\n");
|
}
|
}
|
|
|
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
{
|
{
|
char linestr[500];
|
char linestr[500];
|
char item1[500];
|
char item1[500];
|
char *redirstr;
|
char *redirstr;
|
int hush;
|
int hush;
|
|
|
if (argc != 2) {
|
if (argc != 2) {
|
printf("Usage: %s <filename>\n", argv[0]);
|
printf("Usage: %s <filename>\n", argv[0]);
|
exit(-1);
|
exit(-1);
|
}
|
}
|
|
|
version();
|
version();
|
|
init_defconfig();
|
signal(SIGINT, ctrl_c);
|
signal(SIGINT, ctrl_c);
|
initstats();
|
initstats();
|
loadcode(argv[1]);
|
loadcode(argv[1]);
|
reset();
|
reset();
|
while(1) {
|
while(1) {
|
printf("\n# ");
|
printf("\n# ");
|
fgets(linestr, sizeof(linestr), stdin);
|
fgets(linestr, sizeof(linestr), stdin);
|
|
|
if (redirstr = strstr(linestr, ">")) {
|
if (redirstr = strstr(linestr, ">")) {
|
*redirstr = '\0';
|
*redirstr = '\0';
|
strtoken(&redirstr[1], item1, 1);
|
strtoken(&redirstr[1], item1, 1);
|
freopen(item1, "w+", stdout);
|
freopen(item1, "w+", stdout);
|
}
|
}
|
|
|
strtoken(linestr, item1, 1);
|
strtoken(linestr, item1, 1);
|
if (strcmp(item1, "q") == 0) /* quit */
|
if (strcmp(item1, "q") == 0) /* quit */
|
exit(0);
|
exit(0);
|
else
|
else
|
if (strcmp(item1, "help") == 0) /* help */
|
if (strcmp(item1, "help") == 0) /* help */
|
help();
|
help();
|
else
|
else
|
if (strcmp(item1, "t") == 0) { /* trace */
|
if (strcmp(item1, "t") == 0) { /* trace */
|
cont_run = 1;
|
cont_run = 1;
|
} else
|
} else
|
if (strcmp(item1, "dm") == 0) { /* dump memory */
|
if (strcmp(item1, "dm") == 0) { /* dump memory */
|
char item2[20];
|
char item2[20];
|
char item3[20];
|
char item3[20];
|
static int from = 0, to = 0;
|
static int from = 0, to = 0;
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item3, 3);
|
strtoken(linestr, item3, 3);
|
|
|
if (strlen(item2)) {
|
if (strlen(item2)) {
|
if (item2[0] == '_')
|
if (item2[0] == '_')
|
from = eval_label(item2);
|
from = eval_label(item2);
|
else
|
else
|
from = strtoul(item2, NULL, 0);
|
from = strtoul(item2, NULL, 0);
|
to = from + 0x40;
|
to = from + 0x40;
|
}
|
}
|
if (strlen(item3))
|
if (strlen(item3))
|
to = strtoul(item3, NULL, 0);
|
to = strtoul(item3, NULL, 0);
|
dumpmemory(from, to);
|
dumpmemory(from, to);
|
} else
|
} else
|
if (strcmp(item1, "pm") == 0) { /* patch memory */
|
if (strcmp(item1, "pm") == 0) { /* patch memory */
|
char item2[20];
|
char item2[20];
|
char item3[20];
|
char item3[20];
|
static int addr = 0;
|
static int addr = 0;
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item3, 3);
|
strtoken(linestr, item3, 3);
|
if (strlen(item2))
|
if (strlen(item2))
|
if (item2[0] == '_')
|
if (item2[0] == '_')
|
addr = eval_label(item2);
|
addr = eval_label(item2);
|
else
|
else
|
addr = strtoul(item2, NULL, 0);
|
addr = strtoul(item2, NULL, 0);
|
set_mem32(addr, strtoul(item3, NULL, 0));
|
set_mem32(addr, strtoul(item3, NULL, 0));
|
} else
|
} else
|
if (strcmp(item1, "pr") == 0) { /* patch regs */
|
if (strcmp(item1, "pr") == 0) { /* patch regs */
|
char item2[20];
|
char item2[20];
|
char item3[20];
|
char item3[20];
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item3, 3);
|
strtoken(linestr, item3, 3);
|
set_reg32(item2, strtoul(item3, NULL, 0));
|
set_reg32(item2, strtoul(item3, NULL, 0));
|
} else
|
} else
|
if (strcmp(item1, "pc") == 0) { /* patch PC */
|
if (strcmp(item1, "pc") == 0) { /* patch PC */
|
char item2[20];
|
char item2[20];
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
pctemp = strtoul(item2, NULL, 0);
|
pctemp = strtoul(item2, NULL, 0);
|
} else
|
} else
|
if (strcmp(item1, "brk") == 0) { /* set/clear breakpoint */
|
if (strcmp(item1, "brk") == 0) { /* set/clear breakpoint */
|
char item2[20];
|
char item2[20];
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
set_insnbrkpoint(strtoul(item2, NULL, 0));
|
set_insnbrkpoint(strtoul(item2, NULL, 0));
|
} else
|
} else
|
if (strcmp(item1, "r") == 0) { /* dump regs */
|
if (strcmp(item1, "r") == 0) { /* dump regs */
|
dumpreg();
|
dumpreg();
|
} else
|
} else
|
if (strcmp(item1, "hist") == 0) { /* dump history */
|
if (strcmp(item1, "hist") == 0) { /* dump history */
|
int i;
|
int i;
|
for(i = HISTEXEC_LEN; i; i--)
|
for(i = HISTEXEC_LEN; i; i--)
|
dumpmemory(histexec[i - 1], histexec[i - 1] + 4);
|
dumpmemory(histexec[i - 1], histexec[i - 1] + 4);
|
} else
|
} else
|
if (strcmp(item1, "run") == 0) { /* run */
|
if (strcmp(item1, "run") == 0) { /* run */
|
char item2[20];
|
char item2[20];
|
char item3[20];
|
char item3[20];
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item3, 3);
|
strtoken(linestr, item3, 3);
|
if (strcmp(item3, "hush") == 0)
|
if (strcmp(item3, "hush") == 0)
|
hush = 1;
|
hush = 1;
|
else
|
else
|
hush = 0;
|
hush = 0;
|
cont_run = strtoul(item2, NULL, 0);
|
cont_run = strtoul(item2, NULL, 0);
|
} else
|
} else
|
if (strcmp(item1, "stats") == 0) { /* stats */
|
if (strcmp(item1, "stats") == 0) { /* stats */
|
printstats();
|
char item2[20];
|
|
int i = 0;
|
|
|
|
strtoken(linestr, item2, 2);
|
|
if (strcmp(item2, "clear") == 0) {
|
|
initstats();
|
|
printf("Cleared.\n");
|
|
} else {
|
|
i = strtoul(item2, NULL, 0);
|
|
printstats(i);
|
|
}
|
|
} else
|
|
if (strcmp(item1, "info") == 0) { /* configuration info */
|
|
bpb_info();
|
|
btic_info();
|
|
ic_info();
|
|
dc_info();
|
}
|
}
|
|
|
while(cont_run) {
|
while(cont_run) {
|
cont_run--;
|
cont_run--;
|
fetch();
|
fetch();
|
decode(&iqueue[0]);
|
decode(&iqueue[0]);
|
execute();
|
execute();
|
if (!hush)
|
if (!hush)
|
dumpreg();
|
dumpreg();
|
}
|
}
|
|
|
hush = 0;
|
hush = 0;
|
fflush(stdout);
|
fflush(stdout);
|
freopen("/dev/fd/0", "w+", stdout);
|
freopen("/dev/fd/0", "w+", stdout);
|
|
|
}
|
}
|
exit(0);
|
exit(0);
|
}
|
}
|
|
|