/* 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 <unistd.h>
|
#include <unistd.h>
|
#include <signal.h>
|
#include <signal.h>
|
#include <stdarg.h>
|
#include <stdarg.h>
|
#include <fcntl.h>
|
#include <fcntl.h>
|
#include <limits.h>
|
#include <limits.h>
|
#include <time.h>
|
#include <time.h>
|
|
|
#include "config.h"
|
#include "config.h"
|
|
|
#ifdef HAVE_INTTYPES_H
|
#ifdef HAVE_INTTYPES_H
|
#include <inttypes.h>
|
#include <inttypes.h>
|
#endif
|
#endif
|
|
|
#include "port.h"
|
#include "port.h"
|
#include "arch.h"
|
#include "arch.h"
|
#include "parse.h"
|
#include "parse.h"
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "labels.h"
|
#include "labels.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "opcode/or32.h"
|
#include "opcode/or32.h"
|
#include "spr_defs.h"
|
#include "spr_defs.h"
|
#include "execute.h"
|
#include "execute.h"
|
#include "sprs.h"
|
#include "sprs.h"
|
#include "vapi.h"
|
#include "vapi.h"
|
#include "gdbcomm.h"
|
#include "gdbcomm.h"
|
#include "debug_unit.h"
|
#include "debug_unit.h"
|
#include "coff.h"
|
#include "coff.h"
|
#include "sched.h"
|
#include "sched.h"
|
#include "profiler.h"
|
#include "profiler.h"
|
#include "mprofiler.h"
|
#include "mprofiler.h"
|
#include "pm.h"
|
#include "pm.h"
|
#include "pic.h"
|
#include "pic.h"
|
#include "stats.h"
|
#include "stats.h"
|
#include "immu.h"
|
#include "immu.h"
|
#include "dmmu.h"
|
#include "dmmu.h"
|
#include "dcache_model.h"
|
#include "dcache_model.h"
|
#include "icache_model.h"
|
#include "icache_model.h"
|
#include "branch_predict.h"
|
#include "branch_predict.h"
|
#include "dumpverilog.h"
|
#include "dumpverilog.h"
|
#include "trace.h"
|
#include "trace.h"
|
#include "cuc.h"
|
#include "cuc.h"
|
|
|
/* CVS revision number. */
|
/* CVS revision number. */
|
const char rcsrev[] = "$Revision: 1.132 $";
|
const char rcsrev[] = "$Revision: 1.133 $";
|
|
|
inline void debug(int level, const char *format, ...)
|
inline void debug(int level, const char *format, ...)
|
{
|
{
|
char *p;
|
char *p;
|
va_list ap;
|
va_list ap;
|
|
|
if (config.sim.debug >= level) {
|
if (config.sim.debug >= level) {
|
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", p);
|
PRINTF("%s", p);
|
fflush(stdout);
|
fflush(stdout);
|
free(p);
|
free(p);
|
} else {
|
} else {
|
#if DEBUG
|
#if DEBUG
|
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
|
}
|
}
|
}
|
}
|
|
|
void ctrl_c(signum)
|
void ctrl_c(signum)
|
int signum;
|
int signum;
|
{
|
{
|
/* Incase the user pressed ctrl+c twice without the sim reacting kill it.
|
/* Incase the user pressed ctrl+c twice without the sim reacting kill it.
|
* This is incase the sim locks up in a high level routine, without executeing
|
* This is incase the sim locks up in a high level routine, without executeing
|
* any (or) code */
|
* any (or) code */
|
/* FIXME: Don't kill the sim in handle_sim_command */
|
/* FIXME: Don't kill the sim in handle_sim_command */
|
if(runtime.sim.iprompt)
|
if(runtime.sim.iprompt)
|
sim_done();
|
sim_done();
|
runtime.sim.iprompt = 1;
|
runtime.sim.iprompt = 1;
|
signal(SIGINT, ctrl_c);
|
signal(SIGINT, ctrl_c);
|
}
|
}
|
|
|
/* Periodically checks runtime.sim.iprompt to see if ctrl_c has been pressed */
|
/* Periodically checks runtime.sim.iprompt to see if ctrl_c has been pressed */
|
void check_int(void *dat)
|
void check_int(void *dat)
|
{
|
{
|
if(runtime.sim.iprompt) {
|
if(runtime.sim.iprompt) {
|
set_stall_state (0);
|
set_stall_state (0);
|
handle_sim_command();
|
handle_sim_command();
|
}
|
}
|
SCHED_ADD(check_int, NULL, CHECK_INT_TIME);
|
SCHED_ADD(check_int, NULL, CHECK_INT_TIME);
|
}
|
}
|
|
|
void version(void)
|
void version(void)
|
{
|
{
|
PRINTF ("\n");
|
PRINTF ("\n");
|
PRINTF ("OpenRISC 1000 (OR32) Architectural Simulator, %s\n", rcsrev);
|
PRINTF ("OpenRISC 1000 (OR32) Architectural Simulator, %s\n", rcsrev);
|
PRINTF ("Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n");
|
PRINTF ("Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n");
|
PRINTF ("Copyright (C) 2000 Damjan Lampret, lampret@opencores.org\n");
|
PRINTF ("Copyright (C) 2000 Damjan Lampret, lampret@opencores.org\n");
|
PRINTF (" Jimmy Chen-Min Chen, jimmy@ee.nctu.edu.tw\n");
|
PRINTF (" Jimmy Chen-Min Chen, jimmy@ee.nctu.edu.tw\n");
|
PRINTF (" Johan Rydberg, johan.rydberg@insight.se\n");
|
PRINTF (" Johan Rydberg, johan.rydberg@insight.se\n");
|
PRINTF (" Marko Mlinar, markom@opencores.org\n");
|
PRINTF (" Marko Mlinar, markom@opencores.org\n");
|
PRINTF ("Copyright (C) 2001 Simon Srot, simons@opencores.org\n");
|
PRINTF ("Copyright (C) 2001 Simon Srot, simons@opencores.org\n");
|
PRINTF (" Marko Mlinar, markom@opencores.org\n");
|
PRINTF (" Marko Mlinar, markom@opencores.org\n");
|
PRINTF ("Copyright (C) 2002 Marko Mlinar, markom@opencores.org\n");
|
PRINTF ("Copyright (C) 2002 Marko Mlinar, markom@opencores.org\n");
|
PRINTF (" Simon Srot, simons@opencores.org\n");
|
PRINTF (" Simon Srot, simons@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");
|
}
|
}
|
|
|
struct sim_reset_hook {
|
struct sim_reset_hook {
|
void *dat;
|
void *dat;
|
void (*reset_hook)(void *);
|
void (*reset_hook)(void *);
|
struct sim_reset_hook *next;
|
struct sim_reset_hook *next;
|
};
|
};
|
|
|
struct sim_reset_hook *sim_reset_hooks = NULL;
|
static struct sim_reset_hook *sim_reset_hooks = NULL;
|
|
|
/* Registers a new reset hook, called when sim_reset below is called */
|
/* Registers a new reset hook, called when sim_reset below is called */
|
void reg_sim_reset(void (*reset_hook)(void *), void *dat)
|
void reg_sim_reset(void (*reset_hook)(void *), void *dat)
|
{
|
{
|
struct sim_reset_hook *new = malloc(sizeof(struct sim_reset_hook));
|
struct sim_reset_hook *new = malloc(sizeof(struct sim_reset_hook));
|
|
|
if(!new) {
|
if(!new) {
|
fprintf(stderr, "reg_sim_reset: Out-of-memory\n");
|
fprintf(stderr, "reg_sim_reset: Out-of-memory\n");
|
exit(1);
|
exit(1);
|
}
|
}
|
|
|
new->dat = dat;
|
new->dat = dat;
|
new->reset_hook = reset_hook;
|
new->reset_hook = reset_hook;
|
new->next = sim_reset_hooks;
|
new->next = sim_reset_hooks;
|
sim_reset_hooks = new;
|
sim_reset_hooks = new;
|
}
|
}
|
|
|
/* Resets all subunits */
|
/* Resets all subunits */
|
void sim_reset (void)
|
void sim_reset (void)
|
{
|
{
|
struct sim_reset_hook *cur_reset = sim_reset_hooks;
|
struct sim_reset_hook *cur_reset = sim_reset_hooks;
|
|
|
/* We absolutely MUST reset the scheduler first */
|
/* We absolutely MUST reset the scheduler first */
|
sched_reset();
|
sched_reset();
|
|
|
while(cur_reset) {
|
while(cur_reset) {
|
cur_reset->reset_hook(cur_reset->dat);
|
cur_reset->reset_hook(cur_reset->dat);
|
cur_reset = cur_reset->next;
|
cur_reset = cur_reset->next;
|
}
|
}
|
|
|
tick_reset();
|
tick_reset();
|
pm_reset();
|
pm_reset();
|
pic_reset();
|
pic_reset();
|
du_reset ();
|
du_reset ();
|
|
|
/* Make sure that runtime.sim.iprompt is the first thing to get checked */
|
/* Make sure that runtime.sim.iprompt is the first thing to get checked */
|
SCHED_ADD(check_int, NULL, 1);
|
SCHED_ADD(check_int, NULL, 1);
|
|
|
/* FIXME: Lame-ass way to get runtime.sim.mem_cycles not going into overly
|
/* FIXME: Lame-ass way to get runtime.sim.mem_cycles not going into overly
|
* negative numbers. This happens because parse.c uses setsim_mem32 to load
|
* negative numbers. This happens because parse.c uses setsim_mem32 to load
|
* the program but set_mem32 calls dc_simulate_write, which inturn calls
|
* the program but set_mem32 calls dc_simulate_write, which inturn calls
|
* setsim_mem32. This mess of memory statistics needs to be sorted out for
|
* setsim_mem32. This mess of memory statistics needs to be sorted out for
|
* good one day */
|
* good one day */
|
runtime.sim.mem_cycles = 0;
|
runtime.sim.mem_cycles = 0;
|
cpu_reset();
|
cpu_reset();
|
}
|
}
|
|
|
/* Initalizes all devices and sim */
|
/* Initalizes all devices and sim */
|
void sim_init (void)
|
void sim_init (void)
|
{
|
{
|
init_dmmu();
|
init_dmmu();
|
init_immu();
|
init_immu();
|
init_labels();
|
init_labels();
|
init_breakpoints();
|
init_breakpoints();
|
initstats();
|
initstats();
|
build_automata();
|
build_automata();
|
|
|
#if DYNAMIC_EXECUTION
|
#if DYNAMIC_EXECUTION
|
/* Note: This must be called before the scheduler is used */
|
/* Note: This must be called before the scheduler is used */
|
init_dyn_recomp();
|
init_dyn_recomp();
|
#endif
|
#endif
|
|
|
sched_init();
|
sched_init();
|
|
|
if (config.sim.profile) {
|
if (config.sim.profile) {
|
runtime.sim.fprof = fopen(config.sim.prof_fn, "wt+");
|
runtime.sim.fprof = fopen(config.sim.prof_fn, "wt+");
|
if(!runtime.sim.fprof) {
|
if(!runtime.sim.fprof) {
|
fprintf(stderr, "ERROR: Problems opening profile file.\n");
|
fprintf(stderr, "ERROR: Problems opening profile file.\n");
|
exit (1);
|
exit (1);
|
} else
|
} else
|
fprintf(runtime.sim.fprof, "+00000000 FFFFFFFF FFFFFFFF [outside_functions]\n");
|
fprintf(runtime.sim.fprof, "+00000000 FFFFFFFF FFFFFFFF [outside_functions]\n");
|
}
|
}
|
|
|
if (config.sim.mprofile) {
|
if (config.sim.mprofile) {
|
runtime.sim.fmprof = fopen(config.sim.mprof_fn, "wb+");
|
runtime.sim.fmprof = fopen(config.sim.mprof_fn, "wb+");
|
if(!runtime.sim.fmprof) {
|
if(!runtime.sim.fmprof) {
|
fprintf(stderr, "ERROR: Problems opening memory profile file.\n");
|
fprintf(stderr, "ERROR: Problems opening memory profile file.\n");
|
exit (1);
|
exit (1);
|
}
|
}
|
}
|
}
|
|
|
if (config.sim.exe_log) {
|
if (config.sim.exe_log) {
|
runtime.sim.fexe_log = fopen(config.sim.exe_log_fn, "wt+");
|
runtime.sim.fexe_log = fopen(config.sim.exe_log_fn, "wt+");
|
if(!runtime.sim.fexe_log) {
|
if(!runtime.sim.fexe_log) {
|
PRINTF("ERROR: Problems opening exe_log file.\n");
|
PRINTF("ERROR: Problems opening exe_log file.\n");
|
exit (1);
|
exit (1);
|
}
|
}
|
}
|
}
|
|
|
if(runtime.sim.filename) {
|
if(runtime.sim.filename) {
|
unsigned long endaddr = 0xFFFFFFFF;
|
unsigned long endaddr = 0xFFFFFFFF;
|
endaddr = loadcode(runtime.sim.filename, 0, 0); /* MM170901 always load at address zero. */
|
endaddr = loadcode(runtime.sim.filename, 0, 0); /* MM170901 always load at address zero. */
|
if (endaddr == -1) {
|
if (endaddr == -1) {
|
fprintf(stderr, "Problems loading boot code.\n");
|
fprintf(stderr, "Problems loading boot code.\n");
|
exit(1);
|
exit(1);
|
}
|
}
|
}
|
}
|
|
|
/* Disable gdb debugging, if debug module is not available. */
|
/* Disable gdb debugging, if debug module is not available. */
|
if (config.debug.gdb_enabled && !config.debug.enabled) {
|
if (config.debug.gdb_enabled && !config.debug.enabled) {
|
config.debug.gdb_enabled = 0;
|
config.debug.gdb_enabled = 0;
|
if (config.sim.verbose)
|
if (config.sim.verbose)
|
fprintf (stderr, "WARNING: Debug module not enabled, cannot start gdb.\n");
|
fprintf (stderr, "WARNING: Debug module not enabled, cannot start gdb.\n");
|
}
|
}
|
|
|
if (config.debug.gdb_enabled)
|
if (config.debug.gdb_enabled)
|
gdbcomm_init ();
|
gdbcomm_init ();
|
|
|
/* Enable dependency stats, if we want to do history analisis */
|
/* Enable dependency stats, if we want to do history analisis */
|
if (config.sim.history && !config.cpu.dependstats) {
|
if (config.sim.history && !config.cpu.dependstats) {
|
config.cpu.dependstats = 1;
|
config.cpu.dependstats = 1;
|
if (config.sim.verbose)
|
if (config.sim.verbose)
|
fprintf (stderr, "WARNING: dependstats stats must be enabled to do history analisis.\n");
|
fprintf (stderr, "WARNING: dependstats stats must be enabled to do history analisis.\n");
|
}
|
}
|
|
|
/* Debug forces verbose */
|
/* Debug forces verbose */
|
if (config.sim.debug && !config.sim.verbose) {
|
if (config.sim.debug && !config.sim.verbose) {
|
config.sim.verbose = 1;
|
config.sim.verbose = 1;
|
fprintf (stderr, "WARNING: verbose turned on.\n");
|
fprintf (stderr, "WARNING: verbose turned on.\n");
|
}
|
}
|
|
|
/* Start VAPI before device initialization. */
|
/* Start VAPI before device initialization. */
|
if (config.vapi.enabled) {
|
if (config.vapi.enabled) {
|
runtime.vapi.enabled = 1;
|
runtime.vapi.enabled = 1;
|
vapi_init ();
|
vapi_init ();
|
if (config.sim.verbose)
|
if (config.sim.verbose)
|
PRINTF ("VAPI started, waiting for clients.\n");
|
PRINTF ("VAPI started, waiting for clients.\n");
|
}
|
}
|
|
|
sim_reset ();
|
sim_reset ();
|
|
|
/* Wait till all test are connected. */
|
/* Wait till all test are connected. */
|
if (runtime.vapi.enabled) {
|
if (runtime.vapi.enabled) {
|
int numu = vapi_num_unconnected (0);
|
int numu = vapi_num_unconnected (0);
|
if (numu) {
|
if (numu) {
|
PRINTF ("\nWaiting for VAPI tests with ids:\n");
|
PRINTF ("\nWaiting for VAPI tests with ids:\n");
|
vapi_num_unconnected (1);
|
vapi_num_unconnected (1);
|
PRINTF ("\n");
|
PRINTF ("\n");
|
while ((numu = vapi_num_unconnected (0))) {
|
while ((numu = vapi_num_unconnected (0))) {
|
vapi_check ();
|
vapi_check ();
|
PRINTF ("\rStill waiting for %i VAPI test(s) to connect. ", numu);
|
PRINTF ("\rStill waiting for %i VAPI test(s) to connect. ", numu);
|
usleep (100);
|
usleep (100);
|
}
|
}
|
PRINTF ("\n");
|
PRINTF ("\n");
|
}
|
}
|
PRINTF ("All devices connected \n");
|
PRINTF ("All devices connected \n");
|
}
|
}
|
/* simulator is initialized */
|
/* simulator is initialized */
|
runtime.sim.init = 0;
|
runtime.sim.init = 0;
|
}
|
}
|
|
|
/* Cleanup */
|
/* Cleanup */
|
void sim_done (void)
|
void sim_done (void)
|
{
|
{
|
if (config.sim.profile) {
|
if (config.sim.profile) {
|
fprintf(runtime.sim.fprof,"-%08llX FFFFFFFF\n", runtime.sim.cycles);
|
fprintf(runtime.sim.fprof,"-%08llX FFFFFFFF\n", runtime.sim.cycles);
|
fclose(runtime.sim.fprof);
|
fclose(runtime.sim.fprof);
|
}
|
}
|
|
|
if (config.sim.mprofile) fclose(runtime.sim.fmprof);
|
if (config.sim.mprofile) fclose(runtime.sim.fmprof);
|
if (config.sim.exe_log) fclose(runtime.sim.fexe_log);
|
if (config.sim.exe_log) fclose(runtime.sim.fexe_log);
|
if (runtime.vapi.enabled) vapi_done ();
|
if (runtime.vapi.enabled) vapi_done ();
|
done_memory_table ();
|
done_memory_table ();
|
exit(0);
|
exit(0);
|
}
|
}
|
|
|
/* Executes jobs in time queue */
|
/* Executes jobs in time queue */
|
#if !(DYNAMIC_EXECUTION)
|
#if !(DYNAMIC_EXECUTION)
|
static inline
|
static inline
|
#endif
|
#endif
|
void do_scheduler (void)
|
void do_scheduler (void)
|
{
|
{
|
struct sched_entry *tmp;
|
struct sched_entry *tmp;
|
|
|
/* Execute all jobs till now */
|
/* Execute all jobs till now */
|
do {
|
do {
|
tmp = scheduler.job_queue;
|
tmp = scheduler.job_queue;
|
scheduler.job_queue = tmp->next;
|
scheduler.job_queue = tmp->next;
|
tmp->next = scheduler.free_job_queue;
|
tmp->next = scheduler.free_job_queue;
|
scheduler.free_job_queue = tmp;
|
scheduler.free_job_queue = tmp;
|
|
|
#if DYNAMIC_EXECUTION
|
#if DYNAMIC_EXECUTION
|
/* This is done here and not after the loop has run because the job function
|
/* This is done here and not after the loop has run because the job function
|
* may raise an exception in which case set_sched_cycle would never be
|
* may raise an exception in which case set_sched_cycle would never be
|
* called. */
|
* called. */
|
set_sched_cycle(scheduler.job_queue->time);
|
set_sched_cycle(scheduler.job_queue->time);
|
#endif
|
#endif
|
TRACE_(sched)("Setting to-go cycles to %"PRIi32" at %lli\n",
|
TRACE_(sched)("Setting to-go cycles to %"PRIi32" at %lli\n",
|
scheduler.job_queue->time, runtime.sim.cycles);
|
scheduler.job_queue->time, runtime.sim.cycles);
|
|
|
tmp->func (tmp->param);
|
tmp->func (tmp->param);
|
} while (scheduler.job_queue->time <= 0);
|
} while (scheduler.job_queue->time <= 0);
|
}
|
}
|
|
|
void recalc_do_stats(void)
|
void recalc_do_stats(void)
|
{
|
{
|
extern int do_stats;
|
extern int do_stats;
|
do_stats = config.cpu.dependstats || config.cpu.superscalar ||
|
do_stats = config.cpu.superscalar || config.cpu.dependstats ||
|
config.cpu.dependstats || config.sim.history || config.sim.exe_log;
|
config.sim.history || config.sim.exe_log;
|
}
|
}
|
|
|
/* Main function */
|
/* Main function */
|
int main(argc, argv)
|
int main(argc, argv)
|
int argc;
|
int argc;
|
char *argv[];
|
char *argv[];
|
{
|
{
|
srand(getpid());
|
srand(getpid());
|
init_defconfig();
|
init_defconfig();
|
reg_config_secs();
|
reg_config_secs();
|
if (parse_args(argc, argv)) {
|
if (parse_args(argc, argv)) {
|
PRINTF("Usage: %s [options] <filename>\n", argv[0]);
|
PRINTF("Usage: %s [options] <filename>\n", argv[0]);
|
PRINTF("Options:\n");
|
PRINTF("Options:\n");
|
PRINTF(" -v version and copyright note\n");
|
PRINTF(" -v version and copyright note\n");
|
PRINTF(" -i enable interactive command prompt\n");
|
PRINTF(" -i enable interactive command prompt\n");
|
PRINTF(" --nosrv do not launch JTAG proxy server\n"); /* (CZ) */
|
PRINTF(" --nosrv do not launch JTAG proxy server\n"); /* (CZ) */
|
PRINTF(" --srv <n> launch JTAG proxy server on port <n>; [random]\n"); /* (CZ) */
|
PRINTF(" --srv <n> launch JTAG proxy server on port <n>; [random]\n"); /* (CZ) */
|
PRINTF(" -f or --file load script file [sim.cfg]\n");
|
PRINTF(" -f or --file load script file [sim.cfg]\n");
|
PRINTF(" -d <debug config> Enable debug channels\n");
|
PRINTF(" -d <debug config> Enable debug channels\n");
|
PRINTF(" --enable-profile enable profiling.\n");
|
PRINTF(" --enable-profile enable profiling.\n");
|
PRINTF(" --enable-mprofile enable memory profiling.\n");
|
PRINTF(" --enable-mprofile enable memory profiling.\n");
|
PRINTF("\nor : %s ", argv[0]);
|
PRINTF("\nor : %s ", argv[0]);
|
mp_help ();
|
mp_help ();
|
PRINTF("\nor : %s ", argv[0]);
|
PRINTF("\nor : %s ", argv[0]);
|
prof_help ();
|
prof_help ();
|
exit(-1);
|
exit(-1);
|
}
|
}
|
|
|
/* Read configuration file. */
|
/* Read configuration file. */
|
if (!runtime.sim.script_file_specified)
|
if (!runtime.sim.script_file_specified)
|
read_script_file ("sim.cfg");
|
read_script_file ("sim.cfg");
|
|
|
/* Overide parameters with command line ones */
|
/* Overide parameters with command line ones */
|
if (runtime.simcmd.profile) config.sim.profile = 1;
|
if (runtime.simcmd.profile) config.sim.profile = 1;
|
if (runtime.simcmd.mprofile) config.sim.mprofile = 1;
|
if (runtime.simcmd.mprofile) config.sim.mprofile = 1;
|
|
|
if (!runtime.sim.script_file_specified && config.sim.verbose)
|
if (!runtime.sim.script_file_specified && config.sim.verbose)
|
fprintf (stderr, "WARNING: No config file read, assuming default configuration.\n");
|
fprintf (stderr, "WARNING: No config file read, assuming default configuration.\n");
|
print_config();
|
print_config();
|
signal(SIGINT, ctrl_c);
|
signal(SIGINT, ctrl_c);
|
|
|
runtime.sim.hush = 1;
|
runtime.sim.hush = 1;
|
recalc_do_stats();
|
recalc_do_stats();
|
|
|
sim_init ();
|
sim_init ();
|
|
|
while(1) {
|
while(1) {
|
long long time_start = runtime.sim.cycles;
|
long long time_start = runtime.sim.cycles;
|
if (config.debug.enabled) {
|
if (config.debug.enabled) {
|
du_clock(); // reset watchpoints
|
du_clock(); // reset watchpoints
|
while (runtime.cpu.stalled) {
|
while (runtime.cpu.stalled) {
|
if(config.debug.gdb_enabled) {
|
if(config.debug.gdb_enabled) {
|
BlockJTAG();
|
BlockJTAG();
|
HandleServerSocket(false);
|
HandleServerSocket(false);
|
} else {
|
} else {
|
fprintf (stderr, "WARNING: CPU stalled and gdb connection not enabled.\n");
|
fprintf (stderr, "WARNING: CPU stalled and gdb connection not enabled.\n");
|
/* Dump the user into interactive mode. From there he can decide what
|
/* Dump the user into interactive mode. From there he can decide what
|
* to do. */
|
* to do. */
|
handle_sim_command();
|
handle_sim_command();
|
sim_done();
|
sim_done();
|
}
|
}
|
if(runtime.sim.iprompt)
|
if(runtime.sim.iprompt)
|
handle_sim_command();
|
handle_sim_command();
|
}
|
}
|
}
|
}
|
|
|
/* Each cycle has counter of mem_cycles; this value is joined with cycles
|
/* Each cycle has counter of mem_cycles; this value is joined with cycles
|
at the end of the cycle; no sim originated memory accesses should be
|
at the end of the cycle; no sim originated memory accesses should be
|
performed inbetween. */
|
performed inbetween. */
|
runtime.sim.mem_cycles = 0;
|
runtime.sim.mem_cycles = 0;
|
if (!config.pm.enabled ||
|
if (!config.pm.enabled ||
|
!(cpu_state.sprs[SPR_PMR] & (SPR_PMR_DME | SPR_PMR_SME)))
|
!(cpu_state.sprs[SPR_PMR] & (SPR_PMR_DME | SPR_PMR_SME)))
|
if (cpu_clock ())
|
if (cpu_clock ())
|
/* A breakpoint has been hit, drop to interactive mode */
|
/* A breakpoint has been hit, drop to interactive mode */
|
handle_sim_command();
|
handle_sim_command();
|
|
|
if (config.vapi.enabled && runtime.vapi.enabled) vapi_check();
|
if (config.vapi.enabled && runtime.vapi.enabled) vapi_check();
|
if (config.debug.gdb_enabled) HandleServerSocket(false); /* block & check_stdin = false */
|
if (config.debug.gdb_enabled) HandleServerSocket(false); /* block & check_stdin = false */
|
if(config.debug.enabled)
|
if(config.debug.enabled)
|
if (cpu_state.sprs[SPR_DMR1] & SPR_DMR1_ST) set_stall_state (1);
|
if (cpu_state.sprs[SPR_DMR1] & SPR_DMR1_ST) set_stall_state (1);
|
|
|
runtime.sim.cycles += runtime.sim.mem_cycles;
|
runtime.sim.cycles += runtime.sim.mem_cycles;
|
scheduler.job_queue->time -= runtime.sim.cycles - time_start;
|
scheduler.job_queue->time -= runtime.sim.cycles - time_start;
|
if (scheduler.job_queue->time <= 0) do_scheduler ();
|
if (scheduler.job_queue->time <= 0) do_scheduler ();
|
}
|
}
|
sim_done();
|
sim_done();
|
}
|
}
|
|
|