/* toplevel.c -- Top level simulator support source file
|
/* toplevel.c -- Top level simulator support source file
|
|
|
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
|
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
|
Copyright (C) 2008 Embecosm Limited
|
Copyright (C) 2008 Embecosm Limited
|
|
|
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
|
|
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
|
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
|
|
|
This program is free software; you can redistribute it and/or modify it
|
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 the Free
|
under the terms of the GNU General Public License as published by the Free
|
Software Foundation; either version 3 of the License, or (at your option)
|
Software Foundation; either version 3 of the License, or (at your option)
|
any later version.
|
any later version.
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
more details.
|
more details.
|
|
|
You should have received a copy of the GNU General Public License along
|
You should have received a copy of the GNU General Public License along
|
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
/* This program is commented throughout in a fashion suitable for processing
|
/* This program is commented throughout in a fashion suitable for processing
|
with Doxygen. */
|
with Doxygen. */
|
|
|
|
|
/* Autoconf and/or portability configuration */
|
/* Autoconf and/or portability configuration */
|
#include "config.h"
|
#include "config.h"
|
|
|
/* System includes */
|
/* System includes */
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <unistd.h>
|
#include <unistd.h>
|
#include <stdarg.h>
|
#include <stdarg.h>
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <errno.h>
|
#include <errno.h>
|
#include <signal.h>
|
#include <signal.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
/* Package includes */
|
/* Package includes */
|
#include "toplevel-support.h"
|
#include "toplevel-support.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "debug-unit.h"
|
#include "debug-unit.h"
|
#include "sim-cmd.h"
|
#include "sim-cmd.h"
|
#include "sched.h"
|
#include "sched.h"
|
#include "tick.h"
|
#include "tick.h"
|
#include "pm.h"
|
#include "pm.h"
|
#include "pic.h"
|
#include "pic.h"
|
#include "execute.h"
|
#include "execute.h"
|
#include "labels.h"
|
#include "labels.h"
|
#include "stats.h"
|
#include "stats.h"
|
#include "opcode/or32.h"
|
#include "opcode/or32.h"
|
#include "parse.h"
|
#include "parse.h"
|
#include "rsp-server.h"
|
#include "rsp-server.h"
|
#include "vapi.h"
|
#include "vapi.h"
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "mc.h"
|
#include "mc.h"
|
#include "except.h"
|
#include "except.h"
|
|
|
|
|
/*! Struct for list of reset hooks */
|
/*! Struct for list of reset hooks */
|
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;
|
};
|
};
|
|
|
/*! The list of reset hooks. Local to this source file */
|
/*! The list of reset hooks. Local to this source file */
|
static struct sim_reset_hook *sim_reset_hooks = NULL;
|
static struct sim_reset_hook *sim_reset_hooks = NULL;
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Random number initialization
|
|
|
|
This has become more important, since we rely on randomness to generate
|
|
different MACs in Linux running on Or1ksim.
|
|
|
|
We take our seed from /dev/urandom.
|
|
|
|
If /dev/urandom is not available, we use srandom with the PID instead. */
|
|
/*---------------------------------------------------------------------------*/
|
|
void
|
|
init_randomness ()
|
|
{
|
|
unsigned int seed;
|
|
int fd;
|
|
|
|
fd = open ("/dev/urandom", O_RDONLY);
|
|
|
|
if (fd >= 0)
|
|
{
|
|
if (sizeof (seed) != read (fd, (void *) &seed, sizeof (seed)))
|
|
{
|
|
fprintf (stderr, "Warning: Unable to read /dev/random, using PID.\n");
|
|
seed = getpid ();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf (stderr, "Warning: Unable to open /dev/random, using PID.\n");
|
|
seed = getpid ();
|
|
}
|
|
|
|
srandom (seed);
|
|
|
|
/* Print out the seed just in case we ever need to debug. Note that we
|
|
cannot use PRINTF here, since the file handle will not yet have been set
|
|
up. */
|
|
printf ("Seeding random generator with value 0x%08x\n", seed);
|
|
|
|
} /* init_randomness () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Signal handler for ctrl-C
|
/*!Signal handler for ctrl-C
|
|
|
Sets the iprompt flag, so the simulator will stop next time round the
|
Sets the iprompt flag, so the simulator will stop next time round the
|
loop. If the iprompt flag is set when we enter here, that means the
|
loop. If the iprompt flag is set when we enter here, that means the
|
simulator has not reacted since the last ctrl-C, so we kill the simulation.
|
simulator has not reacted since the last ctrl-C, so we kill the simulation.
|
|
|
@param[in] signum The signal which triggered this handler */
|
@param[in] signum The signal which triggered this handler */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
ctrl_c (signum)
|
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 */
|
if (runtime.sim.iprompt && !runtime.sim.iprompt_run)
|
if (runtime.sim.iprompt && !runtime.sim.iprompt_run)
|
{
|
{
|
sim_done ();
|
sim_done ();
|
exit (-1);
|
exit (-1);
|
}
|
}
|
|
|
/* Mark the simulator to stop next time and reinstall the handler */
|
/* Mark the simulator to stop next time and reinstall the handler */
|
runtime.sim.iprompt = 1;
|
runtime.sim.iprompt = 1;
|
signal (SIGINT, ctrl_c);
|
signal (SIGINT, ctrl_c);
|
|
|
} /* ctrl_c() */
|
} /* ctrl_c() */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Signal handler for SIGUSR1
|
/*!Signal handler for SIGUSR1
|
|
|
Toggles state of trace generating while program is running.
|
Toggles state of trace generating while program is running.
|
|
|
@param[in] signum The signal which triggered this handler */
|
@param[in] signum The signal which triggered this handler */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
toggle_trace (signum)
|
toggle_trace (signum)
|
int signum;
|
int signum;
|
{
|
{
|
|
|
runtime.sim.hush = !runtime.sim.hush;
|
runtime.sim.hush = !runtime.sim.hush;
|
|
|
signal (SIGUSR1, toggle_trace);
|
signal (SIGUSR1, toggle_trace);
|
|
|
} /* toggle_trace() */
|
} /* toggle_trace() */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Routine poll to see if interaction is needed
|
/*!Routine poll to see if interaction is needed
|
|
|
This is most likely to happen due to a ctrl-C. However when the -i flag is
|
This is most likely to happen due to a ctrl-C. However when the -i flag is
|
specified, the simulator starts up ready for interaction.
|
specified, the simulator starts up ready for interaction.
|
|
|
The main simulator loop will stop for interaction if it hits a breakpoint.
|
The main simulator loop will stop for interaction if it hits a breakpoint.
|
|
|
@param[in] dat Data passed in by the Or1ksim scheduler. Not needed by this
|
@param[in] dat Data passed in by the Or1ksim scheduler. Not needed by this
|
function. */
|
function. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
check_int (void *dat)
|
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);
|
|
|
} /* check_int() */
|
} /* check_int() */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Register a new reset hook
|
/*!Register a new reset hook
|
|
|
The registered functions will be called in turn, whenever the simulation is
|
The registered functions will be called in turn, whenever the simulation is
|
reset by calling sim_reset().
|
reset by calling sim_reset().
|
|
|
@param[in] reset_hook The function to be called on reset
|
@param[in] reset_hook The function to be called on reset
|
@param[in] dat The data structure to be passed as argument when the
|
@param[in] dat The data structure to be passed as argument when the
|
reset_hook function is called. */
|
reset_hook function is called. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
reg_sim_reset (void (*reset_hook) (void *), void *dat)
|
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;
|
|
|
} /* reg_sim_reset() */
|
} /* reg_sim_reset() */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Reset the simulator
|
/*!Reset the simulator
|
|
|
The scheduler is reset, then all reset functions on the reset hook list
|
The scheduler is reset, then all reset functions on the reset hook list
|
(i.e. peripherals) are reset. Then standard core functions (which do not
|
(i.e. peripherals) are reset. Then standard core functions (which do not
|
use reset hooks) are reset: tick timer, power management, programmable
|
use reset hooks) are reset: tick timer, power management, programmable
|
interrupt controller and debug unit.
|
interrupt controller and debug unit.
|
|
|
The scheduler queue is reinitialized with an immediate check for ctrl-C on
|
The scheduler queue is reinitialized with an immediate check for ctrl-C on
|
its queue.
|
its queue.
|
|
|
Finally the count of simulated cycles is set to zero. and the CPU itself is
|
Finally the count of simulated cycles is set to zero. and the CPU itself is
|
reset. */
|
reset. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
sim_reset ()
|
sim_reset ()
|
{
|
{
|
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 ();
|
|
|
} /* sim_reset() */
|
} /* sim_reset() */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Initalize the simulator
|
/*!Initalize the simulator
|
|
|
Reset internal data: symbol table (aka labels), breakpoints and
|
Reset internal data: symbol table (aka labels), breakpoints and
|
stats. Rebuild the FSA's used for disassembly.
|
stats. Rebuild the FSA's used for disassembly.
|
|
|
Initialize the dynamic execution system if required.
|
Initialize the dynamic execution system if required.
|
|
|
Initialize the scheduler.
|
Initialize the scheduler.
|
|
|
Open the various logs and statistics files requested by the configuration
|
Open the various logs and statistics files requested by the configuration
|
and/or command arguments.
|
and/or command arguments.
|
|
|
Initialize GDB and VAPI connections.
|
Initialize GDB and VAPI connections.
|
|
|
Reset the simulator.
|
Reset the simulator.
|
|
|
Wait for VAPI to connect if configured. */
|
Wait for VAPI to connect if configured. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
sim_init ()
|
sim_init ()
|
{
|
{
|
PRINTFQ ("Or1ksim " PACKAGE_VERSION "\n" );
|
PRINTFQ ("Or1ksim " PACKAGE_VERSION "\n" );
|
init_labels ();
|
init_labels ();
|
init_breakpoints ();
|
init_breakpoints ();
|
initstats ();
|
initstats ();
|
or1ksim_build_automata (config.sim.quiet);
|
or1ksim_build_automata (config.sim.quiet);
|
|
|
#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 ();
|
|
|
sim_reset (); /* Must do this first - torches memory! */
|
sim_reset (); /* Must do this first - torches memory! */
|
|
|
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: sim_init: cannot open profile file %s: ",
|
fprintf (stderr, "ERROR: sim_init: cannot open profile file %s: ",
|
config.sim.prof_fn);
|
config.sim.prof_fn);
|
perror (NULL);
|
perror (NULL);
|
exit (1);
|
exit (1);
|
}
|
}
|
else
|
else
|
fprintf (runtime.sim.fprof,
|
fprintf (runtime.sim.fprof,
|
"+00000000 FFFFFFFF FFFFFFFF [outside_functions]\n");
|
"+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: sim_init: cannot open memory profile "
|
fprintf (stderr, "ERROR: sim_init: cannot open memory profile "
|
"file %s: ", config.sim.mprof_fn);
|
"file %s: ", config.sim.mprof_fn);
|
perror (NULL);
|
perror (NULL);
|
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)
|
{
|
{
|
fprintf (stderr, "sim_init: cannot open execution log file %s: ",
|
fprintf (stderr, "sim_init: cannot open execution log file %s: ",
|
config.sim.exe_log_fn);
|
config.sim.exe_log_fn);
|
perror (NULL);
|
perror (NULL);
|
exit (1);
|
exit (1);
|
}
|
}
|
}
|
}
|
|
|
if (config.sim.exe_bin_insn_log)
|
if (config.sim.exe_bin_insn_log)
|
{
|
{
|
runtime.sim.fexe_bin_insn_log = fopen (config.sim.exe_bin_insn_log_fn, "wb+");
|
runtime.sim.fexe_bin_insn_log = fopen (config.sim.exe_bin_insn_log_fn, "wb+");
|
if (!runtime.sim.fexe_bin_insn_log)
|
if (!runtime.sim.fexe_bin_insn_log)
|
{
|
{
|
fprintf (stderr, "sim_init: cannot open binary instruction execution log file %s: ",
|
fprintf (stderr, "sim_init: cannot open binary instruction execution log file %s: ",
|
config.sim.exe_bin_insn_log_fn);
|
config.sim.exe_bin_insn_log_fn);
|
perror (NULL);
|
perror (NULL);
|
exit (1);
|
exit (1);
|
}
|
}
|
}
|
}
|
|
|
/* MM170901 always load at address zero */
|
/* MM170901 always load at address zero */
|
if (runtime.sim.filename)
|
if (runtime.sim.filename)
|
{
|
{
|
unsigned long endaddr = loadcode (runtime.sim.filename, 0, 0);
|
unsigned long endaddr = loadcode (runtime.sim.filename, 0, 0);
|
|
|
if (endaddr == -1)
|
if (endaddr == -1)
|
{
|
{
|
fprintf (stderr, "ERROR: sim_init: problem loading code from %s\n",
|
fprintf (stderr, "ERROR: sim_init: problem loading code from %s\n",
|
runtime.sim.filename);
|
runtime.sim.filename);
|
exit (1);
|
exit (1);
|
}
|
}
|
}
|
}
|
|
|
/* Disable RSP debugging, if debug unit is not available. */
|
/* Disable RSP debugging, if debug unit is not available. */
|
if (config.debug.rsp_enabled && !config.debug.enabled)
|
if (config.debug.rsp_enabled && !config.debug.enabled)
|
{
|
{
|
config.debug.rsp_enabled = 0;
|
config.debug.rsp_enabled = 0;
|
|
|
if (config.sim.verbose)
|
if (config.sim.verbose)
|
{
|
{
|
fprintf (stderr, "WARNING: sim_init: Debug module not enabled, "
|
fprintf (stderr, "WARNING: sim_init: Debug module not enabled, "
|
"cannot start remote service to GDB\n");
|
"cannot start remote service to GDB\n");
|
}
|
}
|
}
|
}
|
|
|
/* Start either RSP or legacy GDB debugging service */
|
/* Start either RSP or legacy GDB debugging service */
|
if (config.debug.rsp_enabled)
|
if (config.debug.rsp_enabled)
|
{
|
{
|
rsp_init ();
|
rsp_init ();
|
|
|
/* RSP always starts stalled as though we have just reset the
|
/* RSP always starts stalled as though we have just reset the
|
processor. */
|
processor. */
|
rsp_exception (EXCEPT_TRAP);
|
rsp_exception (EXCEPT_TRAP);
|
set_stall_state (1);
|
set_stall_state (1);
|
}
|
}
|
|
|
/* 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: sim_init: dependstats stats must be "
|
fprintf (stderr, "WARNING: sim_init: dependstats stats must be "
|
"enabled to do history analysis\n");
|
"enabled to do history analysis\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: sim_init: verbose forced on by debug\n");
|
fprintf (stderr, "WARNING: sim_init: verbose forced on by debug\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");
|
}
|
}
|
}
|
}
|
|
|
/* 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
|
PRINTF
|
("\rStill waiting for %i VAPI test(s) to connect",
|
("\rStill waiting for %i VAPI test(s) to connect",
|
numu);
|
numu);
|
usleep (100);
|
usleep (100);
|
}
|
}
|
PRINTF ("\n");
|
PRINTF ("\n");
|
}
|
}
|
PRINTF ("All devices connected\n");
|
PRINTF ("All devices connected\n");
|
}
|
}
|
} /* sim_init() */
|
} /* sim_init() */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Clean up
|
/*!Clean up
|
|
|
Close an profile or log files, disconnect VAPI. Call any memory mapped
|
Close an profile or log files, disconnect VAPI. Call any memory mapped
|
peripheral close down function. Exit with rc 0. */
|
peripheral close down function. Exit with rc 0. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
sim_done ()
|
sim_done ()
|
{
|
{
|
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)
|
if (config.sim.mprofile)
|
{
|
{
|
fclose (runtime.sim.fmprof);
|
fclose (runtime.sim.fmprof);
|
}
|
}
|
|
|
if (config.sim.exe_log)
|
if (config.sim.exe_log)
|
{
|
{
|
fclose (runtime.sim.fexe_log);
|
fclose (runtime.sim.fexe_log);
|
}
|
}
|
|
|
if (config.sim.exe_bin_insn_log)
|
if (config.sim.exe_bin_insn_log)
|
{
|
{
|
fclose (runtime.sim.fexe_bin_insn_log);
|
fclose (runtime.sim.fexe_bin_insn_log);
|
}
|
}
|
|
|
if (runtime.vapi.enabled)
|
if (runtime.vapi.enabled)
|
{
|
{
|
vapi_done ();
|
vapi_done ();
|
}
|
}
|
|
|
done_memory_table ();
|
done_memory_table ();
|
mc_done ();
|
mc_done ();
|
|
|
exit (0);
|
exit (0);
|
|
|
} /* sim_done() */
|
} /* sim_done() */
|
|
|