Line 19... |
Line 19... |
|
|
/* 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>
|
/* System includes */
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
#include <unistd.h>
|
#include <signal.h>
|
|
#include <stdarg.h>
|
/* All the autoconf includes */
|
#include <fcntl.h>
|
|
#include <limits.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
|
|
|
|
/* Package includes */
|
|
|
|
#include "or1ksim.h"
|
|
|
#include "port.h"
|
#include "port.h"
|
#include "arch.h"
|
#include "arch.h"
|
#include "parse.h"
|
|
#include "abstract.h"
|
#include "abstract.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 "debug_unit.h"
|
#include "vapi.h"
|
#include "vapi.h"
|
#include "gdbcomm.h"
|
#include "gdbcomm.h"
|
#include "debug_unit.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 "pic.h"
|
|
#include "stats.h"
|
|
#include "immu.h"
|
|
#include "dmmu.h"
|
|
#include "dcache_model.h"
|
|
#include "icache_model.h"
|
|
#include "branch_predict.h"
|
|
#include "dumpverilog.h"
|
|
#include "trace.h"
|
|
#include "cuc.h"
|
|
#include "tick.h"
|
|
|
|
const char *or1ksim_ver = "0.2.0";
|
|
|
|
inline void debug(int level, const char *format, ...)
|
|
{
|
|
char *p;
|
|
va_list ap;
|
|
|
|
if (config.sim.debug >= level) {
|
|
if ((p = malloc(1000)) == NULL)
|
|
return;
|
|
va_start(ap, format);
|
|
(void) vsnprintf(p, 1000, format, ap);
|
|
va_end(ap);
|
|
PRINTF("%s", p);
|
|
fflush(stdout);
|
|
free(p);
|
|
} else {
|
|
#if DEBUG
|
|
if ((p = malloc(1000)) == NULL)
|
|
return;
|
|
va_start(ap, format);
|
|
(void) vsnprintf(p, 1000, format, ap);
|
|
va_end(ap);
|
|
PRINTF("%s\n", p);
|
|
fflush(stdout);
|
|
free(p);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void ctrl_c(signum)
|
|
int signum;
|
|
{
|
|
/* 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
|
|
* any (or) code */
|
|
if(runtime.sim.iprompt && !runtime.sim.iprompt_run)
|
|
sim_done();
|
|
runtime.sim.iprompt = 1;
|
|
signal(SIGINT, ctrl_c);
|
|
}
|
|
|
|
/* Periodically checks runtime.sim.iprompt to see if ctrl_c has been pressed */
|
|
void check_int(void *dat)
|
|
{
|
|
if(runtime.sim.iprompt) {
|
|
set_stall_state (0);
|
|
handle_sim_command();
|
|
}
|
|
SCHED_ADD(check_int, NULL, CHECK_INT_TIME);
|
|
}
|
|
|
|
struct sim_reset_hook {
|
|
void *dat;
|
|
void (*reset_hook)(void *);
|
|
struct sim_reset_hook *next;
|
|
};
|
|
|
|
static struct sim_reset_hook *sim_reset_hooks = NULL;
|
|
|
|
/* Registers a new reset hook, called when sim_reset below is called */
|
|
void reg_sim_reset(void (*reset_hook)(void *), void *dat)
|
|
{
|
|
struct sim_reset_hook *new = malloc(sizeof(struct sim_reset_hook));
|
|
|
|
if(!new) {
|
|
fprintf(stderr, "reg_sim_reset: Out-of-memory\n");
|
|
exit(1);
|
|
}
|
|
|
|
new->dat = dat;
|
|
new->reset_hook = reset_hook;
|
|
new->next = sim_reset_hooks;
|
|
sim_reset_hooks = new;
|
|
}
|
|
|
|
/* Resets all subunits */
|
|
void sim_reset (void)
|
|
{
|
|
struct sim_reset_hook *cur_reset = sim_reset_hooks;
|
|
|
|
/* We absolutely MUST reset the scheduler first */
|
|
sched_reset();
|
|
|
|
while(cur_reset) {
|
|
cur_reset->reset_hook(cur_reset->dat);
|
|
cur_reset = cur_reset->next;
|
|
}
|
|
|
|
tick_reset();
|
|
pm_reset();
|
|
pic_reset();
|
|
du_reset ();
|
|
|
|
/* Make sure that runtime.sim.iprompt is the first thing to get checked */
|
|
SCHED_ADD(check_int, NULL, 1);
|
|
|
|
/* 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
|
|
* 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
|
|
* good one day */
|
|
runtime.sim.mem_cycles = 0;
|
|
cpu_reset();
|
|
}
|
|
|
|
/* Initalizes all devices and sim */
|
|
void sim_init (void)
|
|
{
|
|
init_labels();
|
|
init_breakpoints();
|
|
initstats();
|
|
build_automata();
|
|
|
|
#if DYNAMIC_EXECUTION
|
|
/* Note: This must be called before the scheduler is used */
|
|
init_dyn_recomp();
|
|
#endif
|
|
|
|
sched_init();
|
/* Support routines declared in toplevel_support.c */
|
|
|
if (config.sim.profile) {
|
extern void ctrl_c( int signum );
|
runtime.sim.fprof = fopen(config.sim.prof_fn, "wt+");
|
extern void recalc_do_stats( void );
|
if(!runtime.sim.fprof) {
|
extern void sim_init( void );
|
fprintf(stderr, "ERROR: Problems opening profile file.\n");
|
extern void sim_done( void );
|
exit (1);
|
extern void do_scheduler( void );
|
} else
|
|
fprintf(runtime.sim.fprof, "+00000000 FFFFFFFF FFFFFFFF [outside_functions]\n");
|
|
}
|
|
|
|
if (config.sim.mprofile) {
|
|
runtime.sim.fmprof = fopen(config.sim.mprof_fn, "wb+");
|
|
if(!runtime.sim.fmprof) {
|
|
fprintf(stderr, "ERROR: Problems opening memory profile file.\n");
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
if (config.sim.exe_log) {
|
|
runtime.sim.fexe_log = fopen(config.sim.exe_log_fn, "wt+");
|
|
if(!runtime.sim.fexe_log) {
|
|
PRINTF("ERROR: Problems opening exe_log file.\n");
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
if(runtime.sim.filename) {
|
|
unsigned long endaddr = 0xFFFFFFFF;
|
|
endaddr = loadcode(runtime.sim.filename, 0, 0); /* MM170901 always load at address zero. */
|
|
if (endaddr == -1) {
|
|
fprintf(stderr, "Problems loading boot code.\n");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
/* Disable gdb debugging, if debug module is not available. */
|
|
if (config.debug.gdb_enabled && !config.debug.enabled) {
|
|
config.debug.gdb_enabled = 0;
|
|
if (config.sim.verbose)
|
|
fprintf (stderr, "WARNING: Debug module not enabled, cannot start gdb.\n");
|
|
}
|
|
|
|
if (config.debug.gdb_enabled)
|
|
gdbcomm_init ();
|
|
|
|
/* Enable dependency stats, if we want to do history analisis */
|
|
if (config.sim.history && !config.cpu.dependstats) {
|
|
config.cpu.dependstats = 1;
|
|
if (config.sim.verbose)
|
|
fprintf (stderr, "WARNING: dependstats stats must be enabled to do history analisis.\n");
|
|
}
|
|
|
|
/* Debug forces verbose */
|
|
if (config.sim.debug && !config.sim.verbose) {
|
|
config.sim.verbose = 1;
|
|
fprintf (stderr, "WARNING: verbose turned on.\n");
|
|
}
|
|
|
|
/* Start VAPI before device initialization. */
|
|
if (config.vapi.enabled) {
|
|
runtime.vapi.enabled = 1;
|
|
vapi_init ();
|
|
if (config.sim.verbose)
|
|
PRINTF ("VAPI started, waiting for clients.\n");
|
|
}
|
|
|
|
sim_reset ();
|
|
|
|
/* Wait till all test are connected. */
|
|
if (runtime.vapi.enabled) {
|
|
int numu = vapi_num_unconnected (0);
|
|
if (numu) {
|
|
PRINTF ("\nWaiting for VAPI tests with ids:\n");
|
|
vapi_num_unconnected (1);
|
|
PRINTF ("\n");
|
|
while ((numu = vapi_num_unconnected (0))) {
|
|
vapi_check ();
|
|
PRINTF ("\rStill waiting for %i VAPI test(s) to connect. ", numu);
|
|
usleep (100);
|
|
}
|
|
PRINTF ("\n");
|
|
}
|
|
PRINTF ("All devices connected \n");
|
|
}
|
|
/* simulator is initialized */
|
|
runtime.sim.init = 0;
|
|
}
|
|
|
|
/* Cleanup */
|
|
void sim_done (void)
|
|
{
|
|
if (config.sim.profile) {
|
|
fprintf(runtime.sim.fprof,"-%08llX FFFFFFFF\n", runtime.sim.cycles);
|
|
fclose(runtime.sim.fprof);
|
|
}
|
|
|
|
if (config.sim.mprofile) fclose(runtime.sim.fmprof);
|
|
if (config.sim.exe_log) fclose(runtime.sim.fexe_log);
|
|
if (runtime.vapi.enabled) vapi_done ();
|
|
done_memory_table ();
|
|
exit(0);
|
|
}
|
|
|
|
void recalc_do_stats(void)
|
|
{
|
|
extern int do_stats;
|
|
do_stats = config.cpu.superscalar || config.cpu.dependstats ||
|
|
config.sim.history || config.sim.exe_log;
|
|
}
|
|
|
|
/* Main function */
|
/* Main function */
|
int main(argc, argv)
|
int main( 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)) {
|
Line 330... |
Line 91... |
|
|
/* 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");
|
|
}
|
|
|
|
config.ext.class_ptr = NULL; /* SystemC linkage disabled here. */
|
|
config.ext.read_up = NULL;
|
|
config.ext.write_up = NULL;
|
|
|
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();
|