OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [tags/] [rel-0-3-0-rc3/] [or1ksim/] [libtoplevel.c] - Diff between revs 1748 and 1751

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 1748 Rev 1751
/* libtoplevel.c -- Top level simulator library source file
/* libtoplevel.c -- Top level simulator library 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 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 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 <signal.h>
#include <signal.h>
 
 
/* Package includes */
/* Package includes */
#include "or1ksim.h"
#include "or1ksim.h"
#include "sim-config.h"
#include "sim-config.h"
#include "toplevel-support.h"
#include "toplevel-support.h"
#include "sched.h"
#include "sched.h"
#include "execute.h"
#include "execute.h"
#include "pic.h"
#include "pic.h"
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Initialize the simulator.
/*!Initialize the simulator.
 
 
   Allows specification of an (optional) config file and an image file. Builds
   Allows specification of an (optional) config file and an image file. Builds
   up dummy argc/argv to pass to the existing argument parser.
   up dummy argc/argv to pass to the existing argument parser.
 
 
   @param[in] config_file  Or1ksim configuration file name
   @param[in] config_file  Or1ksim configuration file name
   @param[in] image_file   The program image to execute
   @param[in] image_file   The program image to execute
   @param[in] class_ptr    Pointer to a C++ class instance (for use when
   @param[in] class_ptr    Pointer to a C++ class instance (for use when
                           called by C++)
                           called by C++)
   @param[in] upr          Upcall routine for reads
   @param[in] upr          Upcall routine for reads
   @param[in] upw          Upcall routine for writes
   @param[in] upw          Upcall routine for writes
 
 
   @return  0 on success and an error code on failure                        */
   @return  0 on success and an error code on failure                        */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
int
int
or1ksim_init (const char *config_file,
or1ksim_init (const char *config_file,
              const char *image_file,
              const char *image_file,
              void       *class_ptr,
              void       *class_ptr,
              unsigned long int (*upr) (void *class_ptr,
              unsigned long int (*upr) (void *class_ptr,
                                        unsigned long int addr,
                                        unsigned long int addr,
                                        unsigned long int mask),
                                        unsigned long int mask),
              void (*upw) (void *class_ptr,
              void (*upw) (void *class_ptr,
                           unsigned long int addr,
                           unsigned long int addr,
                           unsigned long int mask, unsigned long int wdata))
                           unsigned long int mask, unsigned long int wdata))
{
{
  int   dummy_argc = 4;
  int   dummy_argc = 4;
  char *dummy_argv[4];
  char *dummy_argv[4];
 
 
  /* Dummy argv array */
  /* Dummy argv array */
  dummy_argv[0] = "libsim";
  dummy_argv[0] = "libsim";
  dummy_argv[1] = "-f";
  dummy_argv[1] = "-f";
  dummy_argv[2] = (char *) ((NULL != config_file) ? config_file : "sim.cfg");
  dummy_argv[2] = (char *) ((NULL != config_file) ? config_file : "sim.cfg");
  dummy_argv[3] = (char *) image_file;
  dummy_argv[3] = (char *) image_file;
 
 
  /* Initialization copied from existing main() */
  /* Initialization copied from existing main() */
  srand (getpid ());
  srand (getpid ());
  init_defconfig ();
  init_defconfig ();
  reg_config_secs ();
  reg_config_secs ();
 
 
  if (parse_args (dummy_argc, dummy_argv))
  if (parse_args (dummy_argc, dummy_argv))
    {
    {
      return OR1KSIM_RC_BADINIT;
      return OR1KSIM_RC_BADINIT;
    }
    }
 
 
  config.sim.profile   = 0;      /* No profiling */
  config.sim.profile   = 0;      /* No profiling */
  config.sim.mprofile  = 0;
  config.sim.mprofile  = 0;
 
 
  config.ext.class_ptr = class_ptr;     /* SystemC linkage */
  config.ext.class_ptr = class_ptr;     /* SystemC linkage */
  config.ext.read_up   = upr;
  config.ext.read_up   = upr;
  config.ext.write_up  = upw;
  config.ext.write_up  = upw;
 
 
  print_config ();              /* Will go eventually */
  print_config ();              /* Will go eventually */
  signal (SIGINT, ctrl_c);      /* Not sure we want this really */
  signal (SIGINT, ctrl_c);      /* Not sure we want this really */
 
 
  runtime.sim.hush = 1;         /* Not sure if this is needed */
  runtime.sim.hush = 1;         /* Not sure if this is needed */
  do_stats = config.cpu.superscalar ||
  do_stats = config.cpu.superscalar ||
             config.cpu.dependstats ||
             config.cpu.dependstats ||
             config.sim.history     ||
             config.sim.history     ||
             config.sim.exe_log;
             config.sim.exe_log;
 
 
  sim_init ();
  sim_init ();
 
 
  runtime.sim.ext_int = 0;       /* No interrupts pending */
  runtime.sim.ext_int = 0;       /* No interrupts pending */
 
 
  return OR1KSIM_RC_OK;
  return OR1KSIM_RC_OK;
 
 
}       /* or1ksim_init() */
}       /* or1ksim_init() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Run the simulator
/*!Run the simulator
 
 
   The argument is a time in seconds, which is converted to a number of
   The argument is a time in seconds, which is converted to a number of
   cycles, if positive. A negative value means "run for ever".
   cycles, if positive. A negative value means "run for ever".
 
 
   The semantics are that the duration for which the run may occur may be
   The semantics are that the duration for which the run may occur may be
   changed mid-run by a call to or1ksim_reset_duration(). This is to allow for
   changed mid-run by a call to or1ksim_reset_duration(). This is to allow for
   the upcalls to generic components adding time, and reducing the time
   the upcalls to generic components adding time, and reducing the time
   permitted for ISS execution before synchronization of the parent SystemC
   permitted for ISS execution before synchronization of the parent SystemC
   wrapper.
   wrapper.
 
 
   This is over-ridden if the call was for a negative duration, which means
   This is over-ridden if the call was for a negative duration, which means
   run forever!
   run forever!
 
 
   Uses a simplified version of the old main program loop. Returns success if
   Uses a simplified version of the old main program loop. Returns success if
   the requested number of cycles were run and an error code otherwise.
   the requested number of cycles were run and an error code otherwise.
 
 
   @param[in] duration  Time to execute for (seconds)
   @param[in] duration  Time to execute for (seconds)
 
 
   @return  OR1KSIM_RC_OK if we run to completion, OR1KSIM_RC_BRKPT if we hit
   @return  OR1KSIM_RC_OK if we run to completion, OR1KSIM_RC_BRKPT if we hit
            a breakpoint (not clear how this can be set without CLI access)  */
            a breakpoint (not clear how this can be set without CLI access)  */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
int
int
or1ksim_run (double duration)
or1ksim_run (double duration)
{
{
  or1ksim_reset_duration (duration);
  or1ksim_reset_duration (duration);
 
 
  /* Loop until we have done enough cycles (or forever if we had a negative
  /* Loop until we have done enough cycles (or forever if we had a negative
     duration) */
     duration) */
  while (duration < 0.0 || (runtime.sim.cycles < runtime.sim.end_cycles))
  while (duration < 0.0 || (runtime.sim.cycles < runtime.sim.end_cycles))
    {
    {
 
 
      long long int time_start = runtime.sim.cycles;
      long long int time_start = runtime.sim.cycles;
      int i;                    /* Interrupt # */
      int i;                    /* Interrupt # */
 
 
      /* 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 (cpu_clock ())
      if (cpu_clock ())
        {
        {
          return OR1KSIM_RC_BRKPT;      /* Hit a breakpoint */
          return OR1KSIM_RC_BRKPT;      /* Hit a breakpoint */
        }
        }
 
 
      runtime.sim.cycles += runtime.sim.mem_cycles;
      runtime.sim.cycles += runtime.sim.mem_cycles;
 
 
      /* Taken any external interrupts. Outer test is for the common case for
      /* Taken any external interrupts. Outer test is for the common case for
         efficiency. */
         efficiency. */
 
 
      if (0 != runtime.sim.ext_int)
      if (0 != runtime.sim.ext_int)
        {
        {
          for (i = 0; i < sizeof (runtime.sim.ext_int); i++)
          for (i = 0; i < sizeof (runtime.sim.ext_int); i++)
            {
            {
              if (0x1 == ((runtime.sim.ext_int >> i) & 0x1))
              if (0x1 == ((runtime.sim.ext_int >> i) & 0x1))
                {
                {
                  report_interrupt (i);
                  report_interrupt (i);
                  runtime.sim.ext_int &= ~(1 << i);     /* Clear int */
                  runtime.sim.ext_int &= ~(1 << i);     /* Clear int */
                }
                }
            }
            }
        }
        }
 
 
      /* Update the scheduler queue */
      /* Update the scheduler queue */
 
 
      scheduler.job_queue->time -= (runtime.sim.cycles - time_start);
      scheduler.job_queue->time -= (runtime.sim.cycles - time_start);
 
 
      if (scheduler.job_queue->time <= 0)
      if (scheduler.job_queue->time <= 0)
        {
        {
          do_scheduler ();
          do_scheduler ();
        }
        }
    }
    }
 
 
  return  OR1KSIM_RC_OK;
  return  OR1KSIM_RC_OK;
 
 
}       /* or1ksim_run() */
}       /* or1ksim_run() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Reset the run-time simulation end point
/*!Reset the run-time simulation end point
 
 
  Reset the time for which the simulation should run to the specified duration
  Reset the time for which the simulation should run to the specified duration
  from NOW (i.e. NOT from when the run started).
  from NOW (i.e. NOT from when the run started).
 
 
  @param[in] duration  Time to run for in seconds                            */
  @param[in] duration  Time to run for in seconds                            */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
void
or1ksim_reset_duration (double duration)
or1ksim_reset_duration (double duration)
{
{
  runtime.sim.end_cycles =
  runtime.sim.end_cycles =
    runtime.sim.cycles +
    runtime.sim.cycles +
    (long long int) (duration * 1.0e12 / (double) config.sim.clkcycle_ps);
    (long long int) (duration * 1.0e12 / (double) config.sim.clkcycle_ps);
 
 
}       /* or1ksim_reset_duration() */
}       /* or1ksim_reset_duration() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Return time executed so far
/*!Return time executed so far
 
 
   Internal utility to return the time executed so far. Note that this is a
   Internal utility to return the time executed so far. Note that this is a
   re-entrant routine.
   re-entrant routine.
 
 
   @return  Time executed so far in seconds                                  */
   @return  Time executed so far in seconds                                  */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static double
static double
internal_or1ksim_time ()
internal_or1ksim_time ()
{
{
  return (double) runtime.sim.cycles * (double) config.sim.clkcycle_ps /
  return (double) runtime.sim.cycles * (double) config.sim.clkcycle_ps /
    1.0e12;
    1.0e12;
 
 
}       // or1ksim_cycle_count()
}       // or1ksim_cycle_count()
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Mark a time point in the simulation
/*!Mark a time point in the simulation
 
 
   Sets the internal parameter recording this point in the simulation        */
   Sets the internal parameter recording this point in the simulation        */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
void
or1ksim_set_time_point ()
or1ksim_set_time_point ()
{
{
  runtime.sim.time_point = internal_or1ksim_time ();
  runtime.sim.time_point = internal_or1ksim_time ();
 
 
}       /* or1ksim_set_time_point() */
}       /* or1ksim_set_time_point() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Return the time since the time point was set
/*!Return the time since the time point was set
 
 
  Get the value from the internal parameter                                  */
  Get the value from the internal parameter                                  */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
double
double
or1ksim_get_time_period ()
or1ksim_get_time_period ()
{
{
  return internal_or1ksim_time () - runtime.sim.time_point;
  return internal_or1ksim_time () - runtime.sim.time_point;
 
 
}       /* or1ksim_get_time_period() */
}       /* or1ksim_get_time_period() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Return the endianism of the model
/*!Return the endianism of the model
 
 
   Note that this is a re-entrant routine.
   Note that this is a re-entrant routine.
 
 
   @return 1 if the model is little endian, 0 otherwise.                     */
   @return 1 if the model is little endian, 0 otherwise.                     */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
int
int
or1ksim_is_le ()
or1ksim_is_le ()
{
{
#ifdef WORDS_BIGENDIAN
#ifdef OR32_BIG_ENDIAN
  return 0;
  return 0;
#else
#else
  return 1;
  return 1;
#endif
#endif
 
 
}       /* or1ksim_is_le() */
}       /* or1ksim_is_le() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Return the clock rate
/*!Return the clock rate
 
 
   Value is part of the configuration
   Value is part of the configuration
 
 
   @return  Clock rate in Hz.                                                */
   @return  Clock rate in Hz.                                                */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
unsigned long int
unsigned long int
or1ksim_clock_rate ()
or1ksim_clock_rate ()
{
{
  return (unsigned long int) (1000000000000ULL /
  return (unsigned long int) (1000000000000ULL /
                              (unsigned long long int) (config.sim.
                              (unsigned long long int) (config.sim.
                                                        clkcycle_ps));
                                                        clkcycle_ps));
}       /* or1ksim_clock_rate() */
}       /* or1ksim_clock_rate() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Take an interrupt
/*!Take an interrupt
 
 
  @note There is no check that the specified interrupt number is reasonable
  @note There is no check that the specified interrupt number is reasonable
  (i.e. <= 31).
  (i.e. <= 31).
 
 
   @param[in] i  The interrupt number                                        */
   @param[in] i  The interrupt number                                        */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
void
or1ksim_interrupt (int i)
or1ksim_interrupt (int i)
{
{
  runtime.sim.ext_int |= 1 << i;        // Better not be > 31!
  runtime.sim.ext_int |= 1 << i;        // Better not be > 31!
 
 
}       /* or1ksim_interrupt() */
}       /* or1ksim_interrupt() */
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.