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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [sim-config.c] - Diff between revs 472 and 483

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

Rev 472 Rev 483
/* sim-config.c -- Simulator configuration
/* sim-config.c -- Simulator configuration
 
 
   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. */
 
 
/* Simulator configuration. Eventually this one will be a lot bigger. Updated
/* Simulator configuration. Eventually this one will be a lot bigger. Updated
   to use argtable2 for argument parsing. */
   to use argtable2 for argument parsing. */
 
 
 
 
/* Autoconf and/or portability configuration */
/* Autoconf and/or portability configuration */
#include "config.h"
#include "config.h"
#include "port.h"
#include "port.h"
 
 
/* System includes */
/* System includes */
#include <stdlib.h>
#include <stdlib.h>
 
 
/* Package includes */
/* Package includes */
#include "sim-config.h"
#include "sim-config.h"
#include "vapi.h"
#include "vapi.h"
#include "cuc.h"
#include "cuc.h"
#include "cpu-config.h"
#include "cpu-config.h"
#include "memory.h"
#include "memory.h"
#include "dmmu.h"
#include "dmmu.h"
#include "immu.h"
#include "immu.h"
#include "dcache-model.h"
#include "dcache-model.h"
#include "icache-model.h"
#include "icache-model.h"
#include "pic.h"
#include "pic.h"
#include "pm.h"
#include "pm.h"
#include "branch-predict.h"
#include "branch-predict.h"
#include "debug-unit.h"
#include "debug-unit.h"
#include "mc.h"
#include "mc.h"
#include "16450.h"
#include "16450.h"
#include "dma.h"
#include "dma.h"
#include "eth.h"
#include "eth.h"
#include "gpio.h"
#include "gpio.h"
#include "vga.h"
#include "vga.h"
#include "fb.h"
#include "fb.h"
#include "ps2kbd.h"
#include "ps2kbd.h"
#include "atahost.h"
#include "atahost.h"
#include "generic.h"
#include "generic.h"
#include "execute.h"
#include "execute.h"
#include "spr-defs.h"
#include "spr-defs.h"
#include "debug.h"
#include "debug.h"
#include "jtag.h"
#include "jtag.h"
#include "misc.h"
#include "misc.h"
#include "argtable2.h"
#include "argtable2.h"
 
 
 
 
/*! A structure used to represent possible parameters in a section. */
/*! A structure used to represent possible parameters in a section. */
struct config_param
struct config_param
{
{
  char                 *name;                           /* param name */
  char                 *name;                           /* param name */
  enum param_t          type;                           /* param type */
  enum param_t          type;                           /* param type */
  void                (*func) (union param_val  val,    /* Setter function */
  void                (*func) (union param_val  val,    /* Setter function */
                               void            *dat);
                               void            *dat);
  struct config_param  *next;                           /* Next param in list */
  struct config_param  *next;                           /* Next param in list */
 
 
};      /* struct config_param */
};      /* struct config_param */
 
 
 
 
/*! Config file line count */
/*! Config file line count */
static int  line_number;
static int  line_number;
 
 
/*! The global configuration data structure */
/*! The global configuration data structure */
struct config config;
struct config config;
 
 
/*! The global runtime status data structure */
/*! The global runtime status data structure */
struct runtime runtime;
struct runtime runtime;
 
 
/*! Master list of sections it is possible to configure. */
/*! Master list of sections it is possible to configure. */
static struct config_section *section_master_list = NULL;
static struct config_section *section_master_list = NULL;
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Register a parameter for a section
/*!Register a parameter for a section
 
 
   Add a new parameter to the list of parameters that may be set for a given
   Add a new parameter to the list of parameters that may be set for a given
   section.
   section.
 
 
   @param[in] sec       The section containing the parameter.
   @param[in] sec       The section containing the parameter.
   @param[in] param     Name of the parameter
   @param[in] param     Name of the parameter
   @param[in] type      Type of the parameter
   @param[in] type      Type of the parameter
   @param[in] param_cb  Call back function to set this parameter.             */
   @param[in] param_cb  Call back function to set this parameter.             */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void
void
reg_config_param (struct config_section  *sec,
reg_config_param (struct config_section  *sec,
                  const char             *param,
                  const char             *param,
                  enum param_t            type,
                  enum param_t            type,
                  void                  (*param_cb) (union param_val,
                  void                  (*param_cb) (union param_val,
                                                     void *))
                                                     void *))
{
{
  struct config_param *new = malloc (sizeof (struct config_param));
  struct config_param *new = malloc (sizeof (struct config_param));
 
 
  if (!new)
  if (!new)
    {
    {
      fprintf (stderr, "ERROR: Out-of-memory allocating parameter: exiting,\n");
      fprintf (stderr, "ERROR: Out-of-memory allocating parameter: exiting,\n");
      exit (1);
      exit (1);
    }
    }
 
 
  if (!(new->name = strdup (param)))
  if (!(new->name = strdup (param)))
    {
    {
      fprintf (stderr, "ERROR: Out-of-memory allocating parameter name: "
      fprintf (stderr, "ERROR: Out-of-memory allocating parameter name: "
               "exiting,\n");
               "exiting,\n");
      exit (1);
      exit (1);
    }
    }
 
 
  /* Set up the parameter */
  /* Set up the parameter */
  new->func = param_cb;
  new->func = param_cb;
  new->type = type;
  new->type = type;
 
 
  /* Insert on head of list */
  /* Insert on head of list */
  new->next = sec->params;
  new->next = sec->params;
  sec->params = new;
  sec->params = new;
 
 
}       /* reg_config_param () */
}       /* reg_config_param () */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Register a new section.
/*!Register a new section.
 
 
   Add a new section to the list of sections that may be found in a config
   Add a new section to the list of sections that may be found in a config
   file.
   file.
 
 
   @param[in] section    The name of the new section.
   @param[in] section    The name of the new section.
   @param[in] sec_start  Function to call at start of section configuration
   @param[in] sec_start  Function to call at start of section configuration
                         (or NULL if none)
                         (or NULL if none)
   @param[in] sec_end    Function to call at end of section configuration
   @param[in] sec_end    Function to call at end of section configuration
                         (or NULL if none). Returns pointer to an arbitrary
                         (or NULL if none). Returns pointer to an arbitrary
                         data structure.
                         data structure.
 
 
   @return  A pointer to the section data structure for the new section.      */
   @return  A pointer to the section data structure for the new section.      */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
struct config_section *
struct config_section *
reg_config_sec (const char   *section,
reg_config_sec (const char   *section,
                void       *(*sec_start) (void),
                void       *(*sec_start) (void),
                void        (*sec_end) (void *))
                void        (*sec_end) (void *))
{
{
  struct config_section *new = malloc (sizeof (struct config_section));
  struct config_section *new = malloc (sizeof (struct config_section));
 
 
  if (!new)
  if (!new)
    {
    {
      fprintf (stderr, "ERROR: Out-of-memory allocating section: exiting,\n");
      fprintf (stderr, "ERROR: Out-of-memory allocating section: exiting,\n");
      exit (1);
      exit (1);
    }
    }
 
 
  if (!(new->name = strdup (section)))
  if (!(new->name = strdup (section)))
    {
    {
      fprintf (stderr, "ERROR: Out-of-memory allocating section name: "
      fprintf (stderr, "ERROR: Out-of-memory allocating section name: "
               "exiting,\n");
               "exiting,\n");
      exit (1);
      exit (1);
    }
    }
 
 
  /* Set up the section */
  /* Set up the section */
  new->next      = section_master_list;
  new->next      = section_master_list;
  new->sec_start = sec_start;
  new->sec_start = sec_start;
  new->sec_end   = sec_end;
  new->sec_end   = sec_end;
  new->params    = NULL;
  new->params    = NULL;
 
 
  /* Insert the section */
  /* Insert the section */
  section_master_list = new;
  section_master_list = new;
 
 
  return new;
  return new;
 
 
}       /* reg_config_sec () */
}       /* reg_config_sec () */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Look up a section
/*!Look up a section
 
 
   Given a section name, return the data structure describing that section.
   Given a section name, return the data structure describing that section.
 
 
   @param[in] name  The section to look for.
   @param[in] name  The section to look for.
 
 
   @return  A pointer to the section config data structure, or NULL if the
   @return  A pointer to the section config data structure, or NULL if the
            section is not found                                              */
            section is not found                                              */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static struct config_section *
static struct config_section *
lookup_section (char *name)
lookup_section (char *name)
{
{
  struct config_section *cur = NULL;
  struct config_section *cur = NULL;
 
 
  for (cur = section_master_list; NULL != cur; cur = cur->next)
  for (cur = section_master_list; NULL != cur; cur = cur->next)
    {
    {
      if (strcmp (cur->name, name) == 0)
      if (strcmp (cur->name, name) == 0)
        {
        {
          break;
          break;
        }
        }
    }
    }
 
 
  return  cur;
  return  cur;
 
 
}       /* lookup_section () */
}       /* lookup_section () */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Look up a parameter for a section
/*!Look up a parameter for a section
 
 
   Given a parameter name and a section data structure, return the data
   Given a parameter name and a section data structure, return the data
   structure describing that parameter
   structure describing that parameter
 
 
   @param[in] name  The parameter to look for.
   @param[in] name  The parameter to look for.
   @param[in] sec   The section containing the parameter.
   @param[in] sec   The section containing the parameter.
 
 
   @return  A pointer to the parameter config data structure, or NULL if the
   @return  A pointer to the parameter config data structure, or NULL if the
            parameter is not found                                            */
            parameter is not found                                            */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static struct config_param *
static struct config_param *
lookup_param (char                  *name,
lookup_param (char                  *name,
              struct config_section *sec)
              struct config_section *sec)
{
{
  struct config_param *param = NULL;
  struct config_param *param = NULL;
 
 
  for (param = sec->params; NULL != param; param = param->next)
  for (param = sec->params; NULL != param; param = param->next)
    {
    {
      if (strcmp (param->name, name) == 0)
      if (strcmp (param->name, name) == 0)
        {
        {
          break;
          break;
        }
        }
    }
    }
 
 
  return  param;
  return  param;
 
 
}       /* lookup_param () */
}       /* lookup_param () */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Set default configuration parameters for fixed components
/*!Set default configuration parameters for fixed components
 
 
   These values are held in the global config variable. Parameter orders
   These values are held in the global config variable. Parameter orders
   match the order in the corresponding section registration function and
   match the order in the corresponding section registration function and
   documentation.
   documentation.
 
 
   Also set some starting values for runtime elements.                        */
   Also set some starting values for runtime elements.                        */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void
void
init_defconfig ()
init_defconfig ()
{
{
  int  set_bits;                /* Temporaries for computing bit fields */
  int  set_bits;                /* Temporaries for computing bit fields */
  int  way_bits;
  int  way_bits;
 
 
  memset (&config, 0, sizeof (config));
  memset (&config, 0, sizeof (config));
 
 
  /* External linkage disabled here. */
  /* External linkage disabled here. */
  config.ext.class_ptr = NULL;
  config.ext.class_ptr = NULL;
  config.ext.read_up   = NULL;
  config.ext.read_up   = NULL;
  config.ext.write_up  = NULL;
  config.ext.write_up  = NULL;
 
 
  /* Sim */
  /* Sim */
  config.sim.is_library          = 0;    /* Not library operation */
  config.sim.is_library          = 0;    /* Not library operation */
  config.sim.verbose             = 0;
  config.sim.verbose             = 0;
  config.sim.debug               = 0;
  config.sim.debug               = 0;
  config.sim.profile             = 0;
  config.sim.profile             = 0;
  config.sim.prof_fn             = strdup ("sim.profile");
  config.sim.prof_fn             = strdup ("sim.profile");
  config.sim.mprofile            = 0;
  config.sim.mprofile            = 0;
  config.sim.mprof_fn            = strdup ("sim.mprofile");
  config.sim.mprof_fn            = strdup ("sim.mprofile");
  config.sim.history             = 0;
  config.sim.history             = 0;
  config.sim.exe_log             = 0;
  config.sim.exe_log             = 0;
  config.sim.exe_log_type        = EXE_LOG_HARDWARE;
  config.sim.exe_log_type        = EXE_LOG_HARDWARE;
  config.sim.exe_log_start       = 0;
  config.sim.exe_log_start       = 0;
  config.sim.exe_log_end         = 0;
  config.sim.exe_log_end         = 0;
  config.sim.exe_log_marker      = 0;
  config.sim.exe_log_marker      = 0;
  config.sim.exe_log_fn          = strdup ("executed.log");
  config.sim.exe_log_fn          = strdup ("executed.log");
  config.sim.exe_bin_insn_log    = 0;
  config.sim.exe_bin_insn_log    = 0;
  config.sim.exe_bin_insn_log_fn = strdup ("exe-insn.bin");
  config.sim.exe_bin_insn_log_fn = strdup ("exe-insn.bin");
  config.sim.clkcycle_ps         = 4000;        /* 4000 for 4ns (250MHz) */
  config.sim.clkcycle_ps         = 4000;        /* 4000 for 4ns (250MHz) */
 
 
  /* Debug */
  /* Debug */
  config.debug.jtagcycle_ps = 40000;    /* 40000 for 40ns (25MHz) */
  config.debug.jtagcycle_ps = 40000;    /* 40000 for 40ns (25MHz) */
 
 
  /* VAPI */
  /* VAPI */
  config.vapi.enabled        = 0;
  config.vapi.enabled        = 0;
  config.vapi.server_port    = 50000;
  config.vapi.server_port    = 50000;
  config.vapi.log_enabled    = 0;
  config.vapi.log_enabled    = 0;
  config.vapi.hide_device_id = 0;
  config.vapi.hide_device_id = 0;
  config.vapi.vapi_fn        = strdup ("vapi.log");
  config.vapi.vapi_fn        = strdup ("vapi.log");
 
 
  /* CUC */
  /* CUC */
  config.cuc.calling_convention = 1;
  config.cuc.calling_convention = 1;
  config.cuc.enable_bursts      = 1;
  config.cuc.enable_bursts      = 1;
  config.cuc.no_multicycle      = 1;
  config.cuc.no_multicycle      = 1;
  config.cuc.memory_order       = MO_STRONG;
  config.cuc.memory_order       = MO_STRONG;
  config.cuc.timings_fn         = strdup ("virtex.tim");
  config.cuc.timings_fn         = strdup ("virtex.tim");
 
 
  /* CPU */
  /* CPU */
  cpu_state.sprs[SPR_VR]      = 0;
  cpu_state.sprs[SPR_VR]      = 0;
  cpu_state.sprs[SPR_UPR]     = SPR_UPR_UP | SPR_UPR_TTP;
  cpu_state.sprs[SPR_UPR]     = SPR_UPR_UP | SPR_UPR_TTP;
  cpu_state.sprs[SPR_SR]      = SPR_SR_FO  | SPR_SR_SM;
  cpu_state.sprs[SPR_SR]      = SPR_SR_FO  | SPR_SR_SM;
  cpu_state.sprs[SPR_CPUCFGR] = SPR_CPUCFGR_OB32S;
  cpu_state.sprs[SPR_CPUCFGR] = SPR_CPUCFGR_OB32S;
  config.cpu.superscalar      = 0;
  config.cpu.superscalar      = 0;
  config.cpu.hazards          = 0;
  config.cpu.hazards          = 0;
  config.cpu.dependstats      = 0;
  config.cpu.dependstats      = 0;
  config.cpu.sbuf_len         = 0;
  config.cpu.sbuf_len         = 0;
  config.cpu.hardfloat        = 0;
  config.cpu.hardfloat        = 0;
 
 
  /* Data cache (IC is set dynamically). Also set relevant SPR bits */
  /* Data cache (IC is set dynamically). Also set relevant SPR bits */
  config.dc.enabled         = 0;
  config.dc.enabled         = 0;
  config.dc.nsets           = 1;
  config.dc.nsets           = 1;
  config.dc.nways           = 1;
  config.dc.nways           = 1;
  config.dc.blocksize       = 1;
  config.dc.blocksize       = 1;
  config.dc.ustates         = 2;
  config.dc.ustates         = 2;
  config.dc.load_hitdelay   = 2;
  config.dc.load_hitdelay   = 2;
  config.dc.load_missdelay  = 2;
  config.dc.load_missdelay  = 2;
  config.dc.store_hitdelay  = 0;
  config.dc.store_hitdelay  = 0;
  config.dc.store_missdelay = 0;
  config.dc.store_missdelay = 0;
 
 
  if (config.dc.enabled)
  if (config.dc.enabled)
    {
    {
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_DCP;
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_DCP;
    }
    }
  else
  else
    {
    {
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_DCP;
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_DCP;
    }
    }
 
 
  set_bits = log2_int (config.dc.nsets);
  set_bits = log2_int (config.dc.nsets);
  cpu_state.sprs[SPR_DCCFGR] &= ~SPR_DCCFGR_NCS;
  cpu_state.sprs[SPR_DCCFGR] &= ~SPR_DCCFGR_NCS;
  cpu_state.sprs[SPR_DCCFGR] |= set_bits << SPR_DCCFGR_NCS_OFF;
  cpu_state.sprs[SPR_DCCFGR] |= set_bits << SPR_DCCFGR_NCS_OFF;
 
 
  way_bits = log2_int (config.dc.nways);
  way_bits = log2_int (config.dc.nways);
  cpu_state.sprs[SPR_DCCFGR] &= ~SPR_DCCFGR_NCW;
  cpu_state.sprs[SPR_DCCFGR] &= ~SPR_DCCFGR_NCW;
  cpu_state.sprs[SPR_DCCFGR] |= way_bits << SPR_DCCFGR_NCW_OFF;
  cpu_state.sprs[SPR_DCCFGR] |= way_bits << SPR_DCCFGR_NCW_OFF;
 
 
  if (MIN_DC_BLOCK_SIZE == config.dc.blocksize)
  if (MIN_DC_BLOCK_SIZE == config.dc.blocksize)
    {
    {
      cpu_state.sprs[SPR_DCCFGR] &= ~SPR_DCCFGR_CBS;
      cpu_state.sprs[SPR_DCCFGR] &= ~SPR_DCCFGR_CBS;
    }
    }
  else
  else
    {
    {
      cpu_state.sprs[SPR_DCCFGR] |= SPR_DCCFGR_CBS;
      cpu_state.sprs[SPR_DCCFGR] |= SPR_DCCFGR_CBS;
    }
    }
 
 
  /* Power management */
  /* Power management */
  config.pm.enabled = 0;
  config.pm.enabled = 0;
 
 
  if (config.pm.enabled)
  if (config.pm.enabled)
    {
    {
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_PMP;
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_PMP;
    }
    }
  else
  else
    {
    {
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_PMP;
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_PMP;
    }
    }
 
 
  /* Programmable Interrupt Controller */
  /* Programmable Interrupt Controller */
  config.pic.enabled      = 0;
  config.pic.enabled      = 0;
  config.pic.edge_trigger = 1;
  config.pic.edge_trigger = 1;
  config.pic.use_nmi      = 1;
  config.pic.use_nmi      = 1;
 
 
  if (config.pic.enabled)
  if (config.pic.enabled)
    {
    {
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_PICP;
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_PICP;
    }
    }
  else
  else
    {
    {
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_PICP;
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_PICP;
    }
    }
 
 
  /* Branch Prediction */
  /* Branch Prediction */
  config.bpb.enabled     = 0;
  config.bpb.enabled     = 0;
  config.bpb.btic        = 0;
  config.bpb.btic        = 0;
  config.bpb.sbp_bnf_fwd = 0;
  config.bpb.sbp_bnf_fwd = 0;
  config.bpb.sbp_bf_fwd  = 0;
  config.bpb.sbp_bf_fwd  = 0;
  config.bpb.missdelay   = 0;
  config.bpb.missdelay   = 0;
  config.bpb.hitdelay    = 0;
  config.bpb.hitdelay    = 0;
 
 
  /* Debug */
  /* Debug */
  config.debug.enabled     = 0;
  config.debug.enabled     = 0;
  config.debug.rsp_enabled = 0;
  config.debug.rsp_enabled = 0;
  config.debug.rsp_port    = 51000;
  config.debug.rsp_port    = 51000;
  config.debug.vapi_id     = 0;
  config.debug.vapi_id     = 0;
 
 
  cpu_state.sprs[SPR_DCFGR] = SPR_DCFGR_WPCI |
  cpu_state.sprs[SPR_DCFGR] = SPR_DCFGR_WPCI |
                              MATCHPOINTS_TO_NDP (MAX_MATCHPOINTS);
                              MATCHPOINTS_TO_NDP (MAX_MATCHPOINTS);
 
 
  if (config.debug.enabled)
  if (config.debug.enabled)
    {
    {
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_DUP;
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_DUP;
    }
    }
  else
  else
    {
    {
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_DUP;
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_DUP;
    }
    }
 
 
  /* Configure runtime */
  /* Configure runtime */
  memset (&runtime, 0, sizeof (runtime));
  memset (&runtime, 0, sizeof (runtime));
 
 
  /* Sim */
  /* Sim */
  runtime.sim.fexe_log              = NULL;
  runtime.sim.fexe_log              = NULL;
  runtime.sim.iprompt               = 0;
  runtime.sim.iprompt               = 0;
  runtime.sim.fprof                 = NULL;
  runtime.sim.fprof                 = NULL;
  runtime.sim.fmprof                = NULL;
  runtime.sim.fmprof                = NULL;
  runtime.sim.fout                  = stdout;
  runtime.sim.fout                  = stdout;
 
 
  /* Debug */
  /* Debug */
  runtime.debug.instr           = JI_UNDEFINED;
  runtime.debug.instr           = JI_UNDEFINED;
  runtime.debug.mod_id          = JM_UNDEFINED;
  runtime.debug.mod_id          = JM_UNDEFINED;
  runtime.debug.write_defined_p = 0;             /* No WRITE_COMMAND yet */
  runtime.debug.write_defined_p = 0;             /* No WRITE_COMMAND yet */
 
 
  /* NPC state. Set to 1 when NPC is changed while the processor is stalled. */
  /* NPC state. Set to 1 when NPC is changed while the processor is stalled. */
  cpu_state.npc_not_valid = 0;
  cpu_state.npc_not_valid = 0;
 
 
  /* VAPI */
  /* VAPI */
  runtime.vapi.vapi_file = NULL;
  runtime.vapi.vapi_file = NULL;
  runtime.vapi.enabled   = 0;
  runtime.vapi.enabled   = 0;
 
 
}       /* init_defconfig() */
}       /* init_defconfig() */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Set a configuration parameter.
/*!Set a configuration parameter.
 
 
   We have a string representing the value, and a data structure representing
   We have a string representing the value, and a data structure representing
   the particular parameter. Break out the value and call the setter function
   the particular parameter. Break out the value and call the setter function
   to set its value in the section.
   to set its value in the section.
 
 
   The value text is guaranteed to have no leading or trailing whitespace.
   The value text is guaranteed to have no leading or trailing whitespace.
 
 
   @param[in] cur_section  Spec of the section currently being configured.
   @param[in] cur_section  Spec of the section currently being configured.
   @param[in] param        Spec of the parameter we are setting.
   @param[in] param        Spec of the parameter we are setting.
   @param[in] val_text     The parameter value text                           */
   @param[in] val_text     The parameter value text                           */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static void
static void
set_config_param (struct config_section *cur_section,
set_config_param (struct config_section *cur_section,
                  struct config_param   *param,
                  struct config_param   *param,
                  char                  *val_text)
                  char                  *val_text)
{
{
  union param_val  val;
  union param_val  val;
 
 
  /* Break out the different parameter types */
  /* Break out the different parameter types */
  switch (param->type)
  switch (param->type)
    {
    {
    case PARAMT_NONE:
    case PARAMT_NONE:
      break;
      break;
 
 
    case PARAMT_INT:
    case PARAMT_INT:
      val.int_val = strtol (val_text, NULL, 0);
      val.int_val = strtol (val_text, NULL, 0);
      break;
      break;
 
 
    case PARAMT_LONGLONG:
    case PARAMT_LONGLONG:
      val.longlong_val = strtoll (val_text, NULL, 0);
      val.longlong_val = strtoll (val_text, NULL, 0);
      break;
      break;
 
 
    case PARAMT_ADDR:
    case PARAMT_ADDR:
      val.addr_val = strtoul (val_text, NULL, 0);
      val.addr_val = strtoul (val_text, NULL, 0);
      break;
      break;
 
 
    case PARAMT_WORD:
    case PARAMT_WORD:
    case PARAMT_STR:
    case PARAMT_STR:
      /* Word and string are the same thing by now. */
      /* Word and string are the same thing by now. */
      val.str_val = val_text;
      val.str_val = val_text;
      break;
      break;
    }
    }
 
 
  /* Call the setter function */
  /* Call the setter function */
  param->func (val, cur_section->dat);
  param->func (val, cur_section->dat);
 
 
}       /* set_config_param () */
}       /* set_config_param () */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Scan the next word, skipping any preceding space.
/*!Scan the next word, skipping any preceding space.
 
 
   A word is anything that is not white space, except where the white space is
   A word is anything that is not white space, except where the white space is
   within quotation marks. Return the number of newlines we have to skip.
   within quotation marks. Return the number of newlines we have to skip.
 
 
   @param[in] f     The file handle to read from
   @param[in] f     The file handle to read from
   @param[in] word  A buffer in which to store the word.
   @param[in] word  A buffer in which to store the word.
 
 
   @return  The text of the next entity or NULL at end of file. Note strings
   @return  The text of the next entity or NULL at end of file. Note strings
            have their quotation marks removed.                               */
            have their quotation marks removed.                               */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static char *
static char *
next_word (FILE *f,
next_word (FILE *f,
           char  word[])
           char  word[])
{
{
  int  c;
  int  c;
  int  i;
  int  i;
 
 
  /* Skip the whitespace */
  /* Skip the whitespace */
  do
  do
    {
    {
      c = fgetc (f);
      c = fgetc (f);
 
 
      line_number += ('\n' == c) ? 1: 0;
      line_number += ('\n' == c) ? 1: 0;
    }
    }
  while ((EOF != c) && isspace (c));
  while ((EOF != c) && isspace (c));
 
 
  /* Get the word> Special treatment if it is a string. */
  /* Get the word> Special treatment if it is a string. */
  if ('"' == c)
  if ('"' == c)
    {
    {
      /* We have a string. Skip the opening quote. */
      /* We have a string. Skip the opening quote. */
      c = fgetc (f);
      c = fgetc (f);
 
 
      for (i = 0; i < (STR_SIZE - 1); i++)
      for (i = 0; i < (STR_SIZE - 1); i++)
        {
        {
          if ('"' == c)
          if ('"' == c)
            {
            {
              c = fgetc (f);            /* So ungetc works */
              c = fgetc (f);            /* So ungetc works */
              break;                    /* End of the string */
              break;                    /* End of the string */
            }
            }
          else if ('\n' == c)
          else if ('\n' == c)
            {
            {
              line_number++;
              line_number++;
            }
            }
          else if (EOF == c)
          else if (EOF == c)
            {
            {
              fprintf (stderr, "ERROR: EOF in middle of string: exiting.\n");
              fprintf (stderr, "ERROR: EOF in middle of string: exiting.\n");
              exit (1);
              exit (1);
            }
            }
 
 
          word[i] = c;
          word[i] = c;
          c = fgetc (f);
          c = fgetc (f);
        }
        }
 
 
      /* Skip the closing quote */
      /* Skip the closing quote */
      c = fgetc (f);
      c = fgetc (f);
    }
    }
  else
  else
    {
    {
      /* We have a space delimited word */
      /* We have a space delimited word */
      for (i = 0; i < (STR_SIZE - 1); i++)
      for (i = 0; i < (STR_SIZE - 1); i++)
        {
        {
          if ((EOF == c) || isspace (c))
          if ((EOF == c) || isspace (c))
            {
            {
              break;                    /* End of the word */
              break;                    /* End of the word */
            }
            }
 
 
          word[i] = c;
          word[i] = c;
          c = fgetc (f);
          c = fgetc (f);
        }
        }
    }
    }
 
 
  word[i] = '\0';                       /* Terminate the word */
  word[i] = '\0';                       /* Terminate the word */
 
 
  if ((STR_SIZE - 1) == i)
  if ((STR_SIZE - 1) == i)
    {
    {
      word[10]= '\0';
      word[10]= '\0';
      fprintf (stderr,
      fprintf (stderr,
               "ERROR: Symbol beginning %s on line %d too long: exiting.\n",
               "ERROR: Symbol beginning %s on line %d too long: exiting.\n",
               word, line_number);
               word, line_number);
      exit (1);
      exit (1);
    }
    }
 
 
  ungetc (c, f);                        /* Ready for next time */
  ungetc (c, f);                        /* Ready for next time */
 
 
  return  (0 == i) ? NULL : word;
  return  (0 == i) ? NULL : word;
 
 
}       /* next_word () */
}       /* next_word () */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Read the next lexeme from the a config file.
/*!Read the next lexeme from the a config file.
 
 
   At this stage we are just breaking things out into space delimited
   At this stage we are just breaking things out into space delimited
   entities, stripping out comments.
   entities, stripping out comments.
 
 
   @param[in] f       The file handle to read from
   @param[in] f       The file handle to read from
   @param[in] lexeme  A buffer in which to store the lexeme.
   @param[in] lexeme  A buffer in which to store the lexeme.
 
 
   @return  The text of the next entity or NULL at end of file.               */
   @return  The text of the next entity or NULL at end of file.               */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static char *
static char *
next_lexeme (FILE *f,
next_lexeme (FILE *f,
             char  lexeme[])
             char  lexeme[])
{
{
  if (NULL == next_word (f, lexeme))
  if (NULL == next_word (f, lexeme))
    {
    {
      return  NULL;
      return  NULL;
    }
    }
 
 
  /* Skip any comments */
  /* Skip any comments */
  while (0 ==strncmp (lexeme, "/*", 2))
  while (0 ==strncmp (lexeme, "/*", 2))
    {
    {
      /* Look for the closing '*' and '/'. */
      /* Look for the closing '*' and '/'. */
      char  c0 = '\0';
      char  c0 = '\0';
      char  c1 = '\0';
      char  c1 = '\0';
 
 
      while (('*' != c0) || ('/' != c1))
      while (('*' != c0) || ('/' != c1))
        {
        {
          c0 = c1;
          c0 = c1;
          c1 = fgetc (f);
          c1 = fgetc (f);
 
 
          line_number += ('\n' == c1) ? 1 : 0;
          line_number += ('\n' == c1) ? 1 : 0;
 
 
          /* We assume if we hit EOF we have a serious problem and die. */
          /* We assume if we hit EOF we have a serious problem and die. */
          if (feof (f))
          if (feof (f))
            {
            {
              fprintf (stderr, "ERROR: Comment reached EOF.\n");
              fprintf (stderr, "ERROR: Comment reached EOF.\n");
              exit (1);
              exit (1);
            }
            }
        }
        }
 
 
      /* Get the next lexeme */
      /* Get the next lexeme */
      if (NULL == next_word (f, lexeme))
      if (NULL == next_word (f, lexeme))
        {
        {
          return  NULL;
          return  NULL;
        }
        }
    }
    }
 
 
  return  lexeme;
  return  lexeme;
 
 
}       /* next_lexeme () */
}       /* next_lexeme () */
 
 
 
 
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/*!Read configuration from a script file.
/*!Read configuration from a script file.
 
 
   The syntax of script file is:
   The syntax of script file is:
 
 
     [section x
     [section x
       [param [=] value]+
       [param [=] value]+
     end]*
     end]*
 
 
   Example:
   Example:
 
 
     section mc
     section mc
       enabled = 1
       enabled = 1
       POC     = 0x47892344
       POC     = 0x47892344
     end
     end
 
 
   The config file is searched for first in the local directory, then in
   The config file is searched for first in the local directory, then in
   ${HOME}/.or1ksim, then (for backwards compatibility) in ${HOME}/.or1ksim.
   ${HOME}/.or1ksim, then (for backwards compatibility) in ${HOME}/.or1ksim.
 
 
   If the file is not found, then a rude message is printed. The system will
   If the file is not found, then a rude message is printed. The system will
   just use default values.
   just use default values.
 
 
   @param[in] filename  The configuration file to use.                        */
   @param[in] filename  The configuration file to use.                        */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
static void
static void
read_script_file (const char *filename)
read_script_file (const char *filename)
{
{
  FILE *f;
  FILE *f;
  char *home = getenv ("HOME");
  char *home = getenv ("HOME");
  char  ctmp1[STR_SIZE];
  char  ctmp1[STR_SIZE];
  char  ctmp2[STR_SIZE];
  char  ctmp2[STR_SIZE];
  char *dir;
  char *dir;
 
 
  /* Attempt to open the config file. If we fail, give up with a rude
  /* Attempt to open the config file. If we fail, give up with a rude
     message. */
     message. */
  sprintf (ctmp1, "%s/.or1ksim/%s", home, filename);
  sprintf (ctmp1, "%s/.or1ksim/%s", home, filename);
  sprintf (ctmp2, "%s/.or1k/%s", home, filename);
  sprintf (ctmp2, "%s/.or1k/%s", home, filename);
 
 
  if (NULL != (f = fopen (filename, "r")))
  if (NULL != (f = fopen (filename, "r")))
    {
    {
      dir = ".";
      dir = ".";
    }
    }
  else if (home && (NULL != (f = fopen (ctmp1, "r"))))
  else if (home && (NULL != (f = fopen (ctmp1, "r"))))
    {
    {
      dir = ctmp1;
      dir = ctmp1;
    }
    }
  else if (home && (NULL != (f = fopen (ctmp2, "r"))))
  else if (home && (NULL != (f = fopen (ctmp2, "r"))))
    {
    {
      dir = ctmp2;
      dir = ctmp2;
    }
    }
  else
  else
    {
    {
      fprintf (stderr, "Warning: Failed to open script file \"%s\". Ignored.\n",
      fprintf (stderr, "Warning: Failed to open script file \"%s\". Ignored.\n",
               filename);
               filename);
      return;
      return;
    }
    }
 
 
  /* Log the config file we have just opened if required. */
  /* Log the config file we have just opened if required. */
  if (config.sim.verbose)
  if (config.sim.verbose)
    {
    {
      PRINTF ("Reading script file from \"%s/%s\"...\n", dir, filename);
      PRINTF ("Reading script file from \"%s/%s\"...\n", dir, filename);
    }
    }
 
 
  /* Process the config file. */
  /* Process the config file. */
  char lexeme[STR_SIZE];                /* Next entity from the input */
  char lexeme[STR_SIZE];                /* Next entity from the input */
  int  in_section_p = 0;         /* Are we processing a section */
  int  in_section_p = 0;         /* Are we processing a section */
 
 
  struct config_section *cur_section = NULL;    /* Section being processed */
  struct config_section *cur_section = NULL;    /* Section being processed */
 
 
  line_number = 1;
  line_number = 1;
 
 
  while (NULL != next_lexeme (f, lexeme))
  while (NULL != next_lexeme (f, lexeme))
    {
    {
      /* Get the next symbol. Four possibilities.
      /* Get the next symbol. Four possibilities.
 
 
         1. It's "section". Only if we are not currently in a section. Process
         1. It's "section". Only if we are not currently in a section. Process
            the start of a section.
            the start of a section.
 
 
         2. It's "end". Only if we are currently in a section. Process the end
         2. It's "end". Only if we are currently in a section. Process the end
            of a section.
            of a section.
 
 
         3. Anything else while we are in a section. Assume it is a parameter
         3. Anything else while we are in a section. Assume it is a parameter
            for the current section.
            for the current section.
 
 
         4. Anything else. An error.
         4. Anything else. An error.
      */
      */
      if (!in_section_p && (0 == strcmp (lexeme, "section")))
      if (!in_section_p && (0 == strcmp (lexeme, "section")))
        {
        {
          /* We have the start of a section */
          /* We have the start of a section */
          if (NULL == next_lexeme (f, lexeme))
          if (NULL == next_lexeme (f, lexeme))
            {
            {
              fprintf (stderr, "ERROR: %s/%s: Section name required at line "
              fprintf (stderr, "ERROR: %s/%s: Section name required at line "
                       "%d. Exiting\n", dir, filename, line_number);
                       "%d. Exiting\n", dir, filename, line_number);
              exit (1);
              exit (1);
            }
            }
 
 
          cur_section = lookup_section (lexeme);
          cur_section = lookup_section (lexeme);
 
 
          if (NULL != cur_section)
          if (NULL != cur_section)
            {
            {
              /* Valid section, run its startup code, with any data saved. */
              /* Valid section, run its startup code, with any data saved. */
              cur_section->dat = NULL;
              cur_section->dat = NULL;
 
 
              if (cur_section->sec_start)
              if (cur_section->sec_start)
                {
                {
                  cur_section->dat = cur_section->sec_start ();
                  cur_section->dat = cur_section->sec_start ();
                }
                }
 
 
              in_section_p = 1;         /* Now in a section */
              in_section_p = 1;         /* Now in a section */
            }
            }
          else
          else
            {
            {
              /* Skip an unrecognized section with a warning. */
              /* Skip an unrecognized section with a warning. */
              fprintf (stderr, "Warning: %s/%s: Unrecognized section: %s at "
              fprintf (stderr, "Warning: %s/%s: Unrecognized section: %s at "
                       "line %d: ignoring.\n", dir, filename, lexeme,
                       "line %d: ignoring.\n", dir, filename, lexeme,
                       line_number);
                       line_number);
 
 
              /* just skip section */
              /* just skip section */
              while (NULL != next_lexeme (f, lexeme))
              while (NULL != next_lexeme (f, lexeme))
                {
                {
                  if (strcmp (lexeme, "end"))
                  if (strcmp (lexeme, "end"))
                    {
                    {
                      break;
                      break;
                    }
                    }
                }
                }
            }
            }
        }
        }
      else if (in_section_p && strcmp (lexeme, "end") == 0)
      else if (in_section_p && strcmp (lexeme, "end") == 0)
        {
        {
          /* End of section. Run the end of section code */
          /* End of section. Run the end of section code */
          if (cur_section->sec_end)
          if (cur_section->sec_end)
            {
            {
              cur_section->sec_end (cur_section->dat);
              cur_section->sec_end (cur_section->dat);
            }
            }
 
 
          in_section_p = 0;              /* Not in a section any more */
          in_section_p = 0;              /* Not in a section any more */
        }
        }
      else if (in_section_p)
      else if (in_section_p)
        {
        {
          /* We're in a section, so this must be a parameter. */
          /* We're in a section, so this must be a parameter. */
          struct config_param *param;
          struct config_param *param;
          char                *param_val;
          char                *param_val;
 
 
          param = lookup_param (lexeme, cur_section);
          param = lookup_param (lexeme, cur_section);
 
 
          /* If we didn't recognize, then warn and skip to end of line/file) */
          /* If we didn't recognize, then warn and skip to end of line/file) */
          if (NULL == param)
          if (NULL == param)
            {
            {
              fprintf (stderr, "Warning: %s/%s: Unrecognized parameter: %s at "
              fprintf (stderr, "Warning: %s/%s: Unrecognized parameter: %s at "
                       "line %d; ignored.\n", dir, filename, lexeme,
                       "line %d; ignored.\n", dir, filename, lexeme,
                       line_number);
                       line_number);
 
 
              /* Skip to end of line */
              /* Skip to end of line */
              while (( '\n' != fgetc (f)) || feof (f))
              while (( '\n' != fgetc (f)) || feof (f))
                ;
                ;
 
 
              line_number++;
              line_number++;
              continue;                 /* Start looking again */
              continue;                 /* Start looking again */
            }
            }
 
 
          /* Get the argument if one is expected. */
          /* Get the argument if one is expected. */
          if (PARAMT_NONE != param->type)
          if (PARAMT_NONE != param->type)
            {
            {
              param_val = next_lexeme (f, lexeme);
              param_val = next_lexeme (f, lexeme);
 
 
              if (NULL == param_val)
              if (NULL == param_val)
                {
                {
                  fprintf (stderr, "Warning: %s/%s: No argument to parameter "
                  fprintf (stderr, "Warning: %s/%s: No argument to parameter "
                           "%s at line %d; ignored.\n", dir, filename,
                           "%s at line %d; ignored.\n", dir, filename,
                           param->name, line_number);
                           param->name, line_number);
 
 
                  /* Skip to end of line */
                  /* Skip to end of line */
                  while (( '\n' != fgetc (f)) || feof (f))
                  while (( '\n' != fgetc (f)) || feof (f))
                    ;
                    ;
 
 
                  line_number++;
                  line_number++;
                  continue;                     /* Start looking again */
                  continue;                     /* Start looking again */
                }
                }
 
 
              /* We allow an optional '=' */
              /* We allow an optional '=' */
              if (0 == strcmp (lexeme, "="))
              if (0 == strcmp (lexeme, "="))
                {
                {
                  param_val = next_lexeme (f, lexeme);
                  param_val = next_lexeme (f, lexeme);
 
 
                  if (NULL == param_val)
                  if (NULL == param_val)
                    {
                    {
                      fprintf (stderr, "Warning: %s/%s: No argument to "
                      fprintf (stderr, "Warning: %s/%s: No argument to "
                               "parameter %s at line %d; ignored.\n", dir,
                               "parameter %s at line %d; ignored.\n", dir,
                               filename, param->name, line_number);
                               filename, param->name, line_number);
 
 
                      /* Skip to end of line */
                      /* Skip to end of line */
                      while (( '\n' != fgetc (f)) || feof (f))
                      while (( '\n' != fgetc (f)) || feof (f))
                        ;
                        ;
 
 
                      line_number++;
                      line_number++;
                      continue;                 /* Start looking again */
                      continue;                 /* Start looking again */
                    }
                    }
                }
                }
            }
            }
          else
          else
            {
            {
              /* No argument */
              /* No argument */
              param_val = NULL;
              param_val = NULL;
            }
            }
 
 
          /* Apply the parameter */
          /* Apply the parameter */
          set_config_param (cur_section, param, param_val);
          set_config_param (cur_section, param, param_val);
        }
        }
      else
      else
        {
        {
          /* We're not in a section, so we don't know what we have */
          /* We're not in a section, so we don't know what we have */
          fprintf (stderr, "Warning: %s/%s: Unrecognized config file contents "
          fprintf (stderr, "Warning: %s/%s: Unrecognized config file contents "
                   " at line %d: ignored.\n", dir, filename, line_number);
                   " at line %d: ignored.\n", dir, filename, line_number);
 
 
          /* Skip to end of line */
          /* Skip to end of line */
          while (( '\n' != fgetc (f)) || feof (f))
          while (( '\n' != fgetc (f)) || feof (f))
            ;
            ;
 
 
          line_number++;
          line_number++;
          continue;                     /* Start looking again */
          continue;                     /* Start looking again */
        }
        }
    }
    }
 
 
  fclose (f);           /* All done */
  fclose (f);           /* All done */
 
 
}       /* read_script_file () */
}       /* read_script_file () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Allocate a memory block
/*!Allocate a memory block
 
 
   We can request a block of memory be allocated from the command line, rather
   We can request a block of memory be allocated from the command line, rather
   than in a configuration file. It will be allocated, starting at address
   than in a configuration file. It will be allocated, starting at address
   zero.
   zero.
 
 
   The memory size may be presented in any format recognized by strtol,
   The memory size may be presented in any format recognized by strtol,
   optionally followed by "G" or "g", "M" or "m" or "K" or "k" for giga, mega
   optionally followed by "G" or "g", "M" or "m" or "K" or "k" for giga, mega
   and kilo bytes respectively, and leading to mutliplcation by 2^30, 2^20 and
   and kilo bytes respectively, and leading to mutliplcation by 2^30, 2^20 and
   2^10 respectively.
   2^10 respectively.
 
 
   This is intended for simple use of the simulator in tool chain
   This is intended for simple use of the simulator in tool chain
   verification, where the detailed memory behavior does not matter.
   verification, where the detailed memory behavior does not matter.
 
 
   @param[in] size  Memory size.                                             */
   @param[in] size  Memory size.                                             */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
alloc_memory_block (const char *size)
alloc_memory_block (const char *size)
{
{
  /* Sort out the memory size. */
  /* Sort out the memory size. */
  unsigned long int  multiplier;
  unsigned long int  multiplier;
  int                last_ch = strlen (size) - 1;
  int                last_ch = strlen (size) - 1;
 
 
  switch (size[last_ch])
  switch (size[last_ch])
    {
    {
    case 'G': case 'g': multiplier = 0x40000000UL; break;
    case 'G': case 'g': multiplier = 0x40000000UL; break;
    case 'M': case 'm': multiplier =   0x100000UL; break;
    case 'M': case 'm': multiplier =   0x100000UL; break;
    case 'K': case 'k': multiplier =      0x400UL; break;
    case 'K': case 'k': multiplier =      0x400UL; break;
    default:            multiplier =        0x1UL; break;
    default:            multiplier =        0x1UL; break;
    }
    }
 
 
  unsigned long int  mem_size = strtoul (size, NULL, 0) * multiplier;
  unsigned long int  mem_size = strtoul (size, NULL, 0) * multiplier;
 
 
  if (0 == mem_size)
  if (0 == mem_size)
    {
    {
      fprintf (stderr, "Warning: Memory size %s not recognized: ignored.\n",
      fprintf (stderr, "Warning: Memory size %s not recognized: ignored.\n",
               size);
               size);
      return;
      return;
    }
    }
 
 
  if (mem_size > 0xffffffff)
  if (mem_size > 0xffffffff)
    {
    {
      fprintf (stderr, "Warning: Memory size %s too large: ignored.\n",
      fprintf (stderr, "Warning: Memory size %s too large: ignored.\n",
               size);
               size);
      return;
      return;
    }
    }
 
 
  /* Turn the memory size back into a decimal string and allocate it */
  /* Turn the memory size back into a decimal string and allocate it */
  char str_size[11];
  char str_size[11];
  sprintf (str_size, "%lu\n", mem_size);
  sprintf (str_size, "%lu\n", mem_size);
 
 
  struct config_section *sec = lookup_section ("memory");
  struct config_section *sec = lookup_section ("memory");
 
 
  sec->dat = sec->sec_start ();
  sec->dat = sec->sec_start ();
 
 
  set_config_param (sec, lookup_param ("name", sec),     "Default RAM");
  set_config_param (sec, lookup_param ("name", sec),     "Default RAM");
  set_config_param (sec, lookup_param ("type", sec),     "unknown");
  set_config_param (sec, lookup_param ("type", sec),     "unknown");
  set_config_param (sec, lookup_param ("baseaddr", sec), "0");
  set_config_param (sec, lookup_param ("baseaddr", sec), "0");
  set_config_param (sec, lookup_param ("size", sec),     str_size);
  set_config_param (sec, lookup_param ("size", sec),     str_size);
 
 
  sec->sec_end (sec->dat);
  sec->sec_end (sec->dat);
 
 
  if (config.sim.verbose)
  if (config.sim.verbose)
    {
    {
      PRINTF ("Memory block of 0x%lx bytes allocated\n", mem_size);
      PRINTF ("Memory block of 0x%lx bytes allocated\n", mem_size);
    }
    }
}       /* alloc_memory_block () */
}       /* alloc_memory_block () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*! Parse the arguments for the standalone simulator
/*! Parse the arguments for the standalone simulator
 
 
    Updated by Jeremy Bennett to use argtable2.
    Updated by Jeremy Bennett to use argtable2.
 
 
    @param[in] argc  Number of command args
    @param[in] argc  Number of command args
    @param[in] argv  Vector of the command args
    @param[in] argv  Vector of the command args
 
 
    @return  0 on success, 1 on failure                                      */
    @return  0 on success, 1 on failure                                      */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
int
int
parse_args (int argc, char *argv[])
parse_args (int argc, char *argv[])
{
{
  struct arg_lit  *vercop;
  struct arg_lit  *vercop;
  struct arg_lit  *help;
  struct arg_lit  *help;
  struct arg_file *cfg_file;
  struct arg_file *cfg_file;
  struct arg_lit  *nosrv;
  struct arg_lit  *nosrv;
  struct arg_int  *srv;
  struct arg_int  *srv;
  struct arg_str  *mem;
  struct arg_str  *mem;
  struct arg_str  *dbg;
  struct arg_str  *dbg;
  struct arg_lit  *command;
  struct arg_lit  *command;
  struct arg_lit  *quiet;
  struct arg_lit  *quiet;
  struct arg_lit  *verbose;
  struct arg_lit  *verbose;
  struct arg_lit  *trace;
  struct arg_lit  *trace;
  struct arg_lit  *trace_phy;
  struct arg_lit  *trace_phy;
  struct arg_lit  *trace_virt;
  struct arg_lit  *trace_virt;
  struct arg_lit  *report_mem_errs;
  struct arg_lit  *report_mem_errs;
  struct arg_lit  *strict_npc;
  struct arg_lit  *strict_npc;
  struct arg_lit  *profile;
  struct arg_lit  *profile;
  struct arg_lit  *mprofile;
  struct arg_lit  *mprofile;
  struct arg_file *load_file;
  struct arg_file *load_file;
  struct arg_end  *end;
  struct arg_end  *end;
 
 
  /* Specify each argument, with fall back values */
  /* Specify each argument, with fall back values */
  vercop = arg_lit0 ("v", "version", "version and copyright notice");
  vercop = arg_lit0 ("v", "version", "version and copyright notice");
  help = arg_lit0 ("h", "help", "print this help message");
  help = arg_lit0 ("h", "help", "print this help message");
  cfg_file = arg_file0 ("f", "file", "<file>",
  cfg_file = arg_file0 ("f", "file", "<file>",
                        "config file (default \"sim.cfg\")");
                        "config file (default \"sim.cfg\")");
  cfg_file->filename[0] = "sim.cfg";
  cfg_file->filename[0] = "sim.cfg";
  nosrv = arg_lit0 (NULL, "nosrv", "do not launch debug server");
  nosrv = arg_lit0 (NULL, "nosrv", "do not launch debug server");
  srv = arg_int0 (NULL, "srv", "<n>",
  srv = arg_int0 (NULL, "srv", "<n>",
                  "launch debug server on port (default random)");
                  "launch debug server on port (default random)");
  srv->ival[0] = rand () % (65536 - 49152) + 49152;
  srv->ival[0] = random () % (65536 - 49152) + 49152;
  srv->hdr.flag |= ARG_HASOPTVALUE;
  srv->hdr.flag |= ARG_HASOPTVALUE;
  mem = arg_str0 ("m", "memory", "<n>", "add memory block of <n> bytes");
  mem = arg_str0 ("m", "memory", "<n>", "add memory block of <n> bytes");
  dbg = arg_str0 ("d", "debug-config", "<str>", "Debug config string");
  dbg = arg_str0 ("d", "debug-config", "<str>", "Debug config string");
  command = arg_lit0 ("i", "interactive", "launch interactive prompt");
  command = arg_lit0 ("i", "interactive", "launch interactive prompt");
  quiet = arg_lit0 ("q", "quiet", "minimal message output");
  quiet = arg_lit0 ("q", "quiet", "minimal message output");
  verbose = arg_lit0 ("V", "verbose", "verbose message output");
  verbose = arg_lit0 ("V", "verbose", "verbose message output");
  trace = arg_lit0 ("t", "trace", "trace each instruction");
  trace = arg_lit0 ("t", "trace", "trace each instruction");
  trace_phy = arg_lit0 (NULL, "trace-physical",
  trace_phy = arg_lit0 (NULL, "trace-physical",
                        "show physical instruction address when tracing");
                        "show physical instruction address when tracing");
  trace_virt = arg_lit0 (NULL, "trace-virtual",
  trace_virt = arg_lit0 (NULL, "trace-virtual",
                        "show virtual instruction address when tracing");
                        "show virtual instruction address when tracing");
  report_mem_errs = arg_lit0 (NULL, "report-memory-errors",
  report_mem_errs = arg_lit0 (NULL, "report-memory-errors",
                              "Report out of memory accesses");
                              "Report out of memory accesses");
  strict_npc = arg_lit0 (NULL, "strict-npc", "setting NPC flushes pipeline");
  strict_npc = arg_lit0 (NULL, "strict-npc", "setting NPC flushes pipeline");
  profile = arg_lit0 (NULL, "enable-profile", "enable profiling");
  profile = arg_lit0 (NULL, "enable-profile", "enable profiling");
  mprofile = arg_lit0 (NULL, "enable-mprofile", "enable memory profiling");
  mprofile = arg_lit0 (NULL, "enable-mprofile", "enable memory profiling");
  load_file = arg_file0 (NULL, NULL, "<file>", "OR32 executable");
  load_file = arg_file0 (NULL, NULL, "<file>", "OR32 executable");
  end = arg_end (20);
  end = arg_end (20);
 
 
  /* The argument table */
  /* The argument table */
  void *argtab[] = {
  void *argtab[] = {
    vercop,
    vercop,
    help,
    help,
    cfg_file,
    cfg_file,
    nosrv,
    nosrv,
    srv,
    srv,
    mem,
    mem,
    dbg,
    dbg,
    command,
    command,
    quiet,
    quiet,
    verbose,
    verbose,
    trace,
    trace,
    trace_phy,
    trace_phy,
    trace_virt,
    trace_virt,
    report_mem_errs,
    report_mem_errs,
    strict_npc,
    strict_npc,
    profile,
    profile,
    mprofile,
    mprofile,
    load_file,
    load_file,
    end };
    end };
 
 
  /* Parse */
  /* Parse */
  int  nerrors = arg_parse (argc, argv, argtab);
  int  nerrors = arg_parse (argc, argv, argtab);
 
 
  /* Special case here is if help or version is specified, we ignore any other
  /* Special case here is if help or version is specified, we ignore any other
     errors and just print the help or version information and then give up. */
     errors and just print the help or version information and then give up. */
  if (vercop->count > 0)
  if (vercop->count > 0)
    {
    {
      PRINTF ("OpenRISC 1000 Architectural Simulator, version %s\n",
      PRINTF ("OpenRISC 1000 Architectural Simulator, version %s\n",
              PACKAGE_VERSION);
              PACKAGE_VERSION);
 
 
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
      return 1;
      return 1;
    }
    }
 
 
  if (help->count > 0)
  if (help->count > 0)
    {
    {
      printf ("Usage:\n  %s ", argv[0]);
      printf ("Usage:\n  %s ", argv[0]);
      arg_print_syntax (stdout, argtab, "\n\n");
      arg_print_syntax (stdout, argtab, "\n\n");
      arg_print_glossary (stdout, argtab, "  %-25s %s\n");
      arg_print_glossary (stdout, argtab, "  %-25s %s\n");
 
 
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
      return 1;
      return 1;
    }
    }
 
 
  /* Deal with any errors */
  /* Deal with any errors */
  if (0 != nerrors)
  if (0 != nerrors)
    {
    {
      arg_print_errors (stderr, end, "or1ksim");
      arg_print_errors (stderr, end, "or1ksim");
      printf ("\nUsage:\n  %s ", argv[0]);
      printf ("\nUsage:\n  %s ", argv[0]);
      arg_print_syntaxv (stderr, argtab, "\n");
      arg_print_syntaxv (stderr, argtab, "\n");
 
 
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
      arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
      return 1;
      return 1;
    }
    }
 
 
  /* Request for quiet running */
  /* Request for quiet running */
  config.sim.quiet = quiet->count;
  config.sim.quiet = quiet->count;
 
 
  /* Request for verbose running. Not sensible to use with quiet as well. */
  /* Request for verbose running. Not sensible to use with quiet as well. */
  if (quiet->count && verbose->count)
  if (quiet->count && verbose->count)
    {
    {
      fprintf (stderr, "Warning: Cannot specify both --verbose and --quiet: "
      fprintf (stderr, "Warning: Cannot specify both --verbose and --quiet: "
               "--vervose ignored.\n");
               "--vervose ignored.\n");
      config.sim.verbose = 0;
      config.sim.verbose = 0;
    }
    }
  else
  else
    {
    {
      config.sim.verbose = verbose->count;
      config.sim.verbose = verbose->count;
    }
    }
 
 
  /* Request for tracing. We may ask for instructions to be recorded with
  /* Request for tracing. We may ask for instructions to be recorded with
     either the physical or virtual address. */
     either the physical or virtual address. */
  runtime.sim.hush       = trace->count ? 0 : 1;
  runtime.sim.hush       = trace->count ? 0 : 1;
  runtime.sim.trace_phy  = trace_phy->count  ? 1 : 0;
  runtime.sim.trace_phy  = trace_phy->count  ? 1 : 0;
  runtime.sim.trace_virt = trace_virt->count ? 1 : 0;
  runtime.sim.trace_virt = trace_virt->count ? 1 : 0;
 
 
  /* Ensure we have a least one address type in use. */
  /* Ensure we have a least one address type in use. */
  if (!runtime.sim.trace_phy && !runtime.sim.trace_virt)
  if (!runtime.sim.trace_phy && !runtime.sim.trace_virt)
    {
    {
      runtime.sim.trace_virt = 1;
      runtime.sim.trace_virt = 1;
    }
    }
 
 
  /* Request for memory errors */
  /* Request for memory errors */
  config.sim.report_mem_errs = report_mem_errs->count;
  config.sim.report_mem_errs = report_mem_errs->count;
 
 
  /* Process config file next (if given), so any other command args will
  /* Process config file next (if given), so any other command args will
     override */
     override */
  if (0 == cfg_file->count)
  if (0 == cfg_file->count)
    {
    {
      if (config.sim.verbose)
      if (config.sim.verbose)
        {
        {
          fprintf (stderr, "Default configuration used\n");
          fprintf (stderr, "Default configuration used\n");
        }
        }
    }
    }
  else
  else
    {
    {
      read_script_file (cfg_file->filename[0]);
      read_script_file (cfg_file->filename[0]);
    }
    }
 
 
  /* Allocate a memory block */
  /* Allocate a memory block */
  if (mem->count > 0)
  if (mem->count > 0)
    {
    {
      alloc_memory_block (mem->sval[0]);
      alloc_memory_block (mem->sval[0]);
    }
    }
 
 
  /* Remote debug server */
  /* Remote debug server */
  if (nosrv->count > 0)
  if (nosrv->count > 0)
    {
    {
      if (srv->count > 0)
      if (srv->count > 0)
        {
        {
          fprintf (stderr,
          fprintf (stderr,
                   "%s: cannot specify --nosrv with --srv. Ignoring --nosrv\n",
                   "%s: cannot specify --nosrv with --srv. Ignoring --nosrv\n",
                   argv[0]);
                   argv[0]);
        }
        }
      else
      else
        {
        {
          config.debug.enabled = 0;
          config.debug.enabled = 0;
          config.debug.rsp_enabled = 0;
          config.debug.rsp_enabled = 0;
        }
        }
    }
    }
 
 
  if (srv->count > 0)
  if (srv->count > 0)
    {
    {
      config.debug.enabled     = 1;
      config.debug.enabled     = 1;
      config.debug.rsp_enabled = 1;
      config.debug.rsp_enabled = 1;
      config.debug.rsp_port    = srv->ival[0];
      config.debug.rsp_port    = srv->ival[0];
    }
    }
 
 
  /* Runtime debug messages */
  /* Runtime debug messages */
  if (dbg->count > 0)
  if (dbg->count > 0)
    {
    {
      parse_dbchs (dbg->sval[0]);
      parse_dbchs (dbg->sval[0]);
    }
    }
 
 
  /* Interactive operation */
  /* Interactive operation */
  runtime.sim.iprompt = command->count;
  runtime.sim.iprompt = command->count;
 
 
  /* Request for strict NPC behavior (flush the pipeline on change) */
  /* Request for strict NPC behavior (flush the pipeline on change) */
  config.sim.strict_npc = strict_npc->count;
  config.sim.strict_npc = strict_npc->count;
 
 
  /* Profiling requests */
  /* Profiling requests */
  config.sim.profile = profile->count;
  config.sim.profile = profile->count;
  config.sim.mprofile = mprofile->count;
  config.sim.mprofile = mprofile->count;
 
 
  /* Executable file */
  /* Executable file */
  if (load_file->count > 0)
  if (load_file->count > 0)
    {
    {
      runtime.sim.filename = strdup (load_file->filename[0]);
      runtime.sim.filename = strdup (load_file->filename[0]);
    }
    }
  else
  else
    {
    {
      runtime.sim.filename = NULL;
      runtime.sim.filename = NULL;
    }
    }
 
 
  arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
  arg_freetable (argtab, sizeof (argtab) / sizeof (argtab[0]));
  return 0;                      /* Success */
  return 0;                      /* Success */
 
 
}       /* parse_args() */
}       /* parse_args() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Print the current configuration                                           */
/*!Print the current configuration                                           */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
void
print_config ()
print_config ()
{
{
  if (config.sim.verbose)
  if (config.sim.verbose)
    {
    {
      char temp[20];
      char temp[20];
      PRINTF ("Verbose on, ");
      PRINTF ("Verbose on, ");
      if (config.sim.debug)
      if (config.sim.debug)
        PRINTF ("simdebug on, ");
        PRINTF ("simdebug on, ");
      else
      else
        PRINTF ("simdebug off, ");
        PRINTF ("simdebug off, ");
      if (runtime.sim.iprompt)
      if (runtime.sim.iprompt)
        PRINTF ("interactive prompt on\n");
        PRINTF ("interactive prompt on\n");
      else
      else
        PRINTF ("interactive prompt off\n");
        PRINTF ("interactive prompt off\n");
 
 
      PRINTF ("Machine initialization...\n");
      PRINTF ("Machine initialization...\n");
      generate_time_pretty (temp, config.sim.clkcycle_ps);
      generate_time_pretty (temp, config.sim.clkcycle_ps);
      PRINTF ("Clock cycle: %s\n", temp);
      PRINTF ("Clock cycle: %s\n", temp);
      if (cpu_state.sprs[SPR_UPR] & SPR_UPR_DCP)
      if (cpu_state.sprs[SPR_UPR] & SPR_UPR_DCP)
        PRINTF ("Data cache present.\n");
        PRINTF ("Data cache present.\n");
      else
      else
        PRINTF ("No data cache.\n");
        PRINTF ("No data cache.\n");
      if (cpu_state.sprs[SPR_UPR] & SPR_UPR_ICP)
      if (cpu_state.sprs[SPR_UPR] & SPR_UPR_ICP)
        PRINTF ("Insn cache tag present.\n");
        PRINTF ("Insn cache tag present.\n");
      else
      else
        PRINTF ("No instruction cache.\n");
        PRINTF ("No instruction cache.\n");
      if (config.bpb.enabled)
      if (config.bpb.enabled)
        PRINTF ("BPB simulation on.\n");
        PRINTF ("BPB simulation on.\n");
      else
      else
        PRINTF ("BPB simulation off.\n");
        PRINTF ("BPB simulation off.\n");
      if (config.bpb.btic)
      if (config.bpb.btic)
        PRINTF ("BTIC simulation on.\n");
        PRINTF ("BTIC simulation on.\n");
      else
      else
        PRINTF ("BTIC simulation off.\n");
        PRINTF ("BTIC simulation off.\n");
    }
    }
}
}
 
 
/* Simulator configuration */
/* Simulator configuration */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Turn on verbose messages.
/*!Turn on verbose messages.
 
 
   @param[in] val  Non-zero (TRUE) to turn on verbose messages, zero (FALSE)
   @param[in] val  Non-zero (TRUE) to turn on verbose messages, zero (FALSE)
                   otherwise.
                   otherwise.
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_verbose (union param_val  val,
sim_verbose (union param_val  val,
             void            *dat)
             void            *dat)
{
{
  config.sim.verbose = val.int_val;
  config.sim.verbose = val.int_val;
 
 
}       /* sim_verbose () */
}       /* sim_verbose () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Set the simulator debug message level
/*!Set the simulator debug message level
 
 
   Value must be in the range 0 (no messages) to 9. Values outside this range
   Value must be in the range 0 (no messages) to 9. Values outside this range
   are converted to the nearer end of the range with a warning.
   are converted to the nearer end of the range with a warning.
 
 
   @param[in] val  The value to use
   @param[in] val  The value to use
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_debug (union param_val  val,
sim_debug (union param_val  val,
           void            *dat)
           void            *dat)
{
{
  if (val.int_val < 0)
  if (val.int_val < 0)
    {
    {
      fprintf (stderr,
      fprintf (stderr,
               "Warning: Config debug value negative: 0 substituted\n");
               "Warning: Config debug value negative: 0 substituted\n");
      config.sim.debug = 0;
      config.sim.debug = 0;
    }
    }
  else if (val.int_val > 9)
  else if (val.int_val > 9)
    {
    {
      fprintf (stderr,
      fprintf (stderr,
               "Warning: Config debug value too large: 9 substituted\n");
               "Warning: Config debug value too large: 9 substituted\n");
      config.sim.debug = 9;
      config.sim.debug = 9;
    }
    }
  else
  else
    {
    {
      config.sim.debug = val.int_val;
      config.sim.debug = val.int_val;
    }
    }
}       /* sim_debug() */
}       /* sim_debug() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Turn on profiling
/*!Turn on profiling
 
 
   @param[in] val  Non-zero (TRUE) to turn on profiling, zero (FALSE) otherwise.
   @param[in] val  Non-zero (TRUE) to turn on profiling, zero (FALSE) otherwise.
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_profile (union param_val  val,
sim_profile (union param_val  val,
             void            *dat)
             void            *dat)
{
{
  config.sim.profile = val.int_val;
  config.sim.profile = val.int_val;
 
 
}       /* sim_profile () */
}       /* sim_profile () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Specify the profiling file name.
/*!Specify the profiling file name.
 
 
   @param[in] val  The profiling file name
   @param[in] val  The profiling file name
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_prof_fn (union param_val  val,
sim_prof_fn (union param_val  val,
             void            *dat)
             void            *dat)
{
{
  if (NULL != config.sim.prof_fn)
  if (NULL != config.sim.prof_fn)
    {
    {
      free (config.sim.prof_fn);
      free (config.sim.prof_fn);
    }
    }
 
 
  config.sim.prof_fn = strdup(val.str_val);
  config.sim.prof_fn = strdup(val.str_val);
 
 
}       /* sim_prof_fn () */
}       /* sim_prof_fn () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Turn on memory profiling
/*!Turn on memory profiling
 
 
   @param[in] val  Non-zero (TRUE) to turn on memory profiling, zero (FALSE)
   @param[in] val  Non-zero (TRUE) to turn on memory profiling, zero (FALSE)
                   otherwise.
                   otherwise.
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_mprofile (union param_val  val,
sim_mprofile (union param_val  val,
              void            *dat)
              void            *dat)
{
{
  config.sim.mprofile = val.int_val;
  config.sim.mprofile = val.int_val;
 
 
}       /* sim_mprofile () */
}       /* sim_mprofile () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Specify the memory profiling file name.
/*!Specify the memory profiling file name.
 
 
   @param[in] val  The memory profiling file name
   @param[in] val  The memory profiling file name
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_mprof_fn (union param_val val, void *dat)
sim_mprof_fn (union param_val val, void *dat)
{
{
  if (NULL != config.sim.mprof_fn)
  if (NULL != config.sim.mprof_fn)
    {
    {
      free (config.sim.mprof_fn);
      free (config.sim.mprof_fn);
    }
    }
 
 
  config.sim.mprof_fn = strdup (val.str_val);
  config.sim.mprof_fn = strdup (val.str_val);
 
 
}       /* sim_mprof_fn () */
}       /* sim_mprof_fn () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Turn on execution tracking.
/*!Turn on execution tracking.
 
 
   @param[in] val  Non-zero (TRUE) to turn on tracking, zero (FALSE) otherwise.
   @param[in] val  Non-zero (TRUE) to turn on tracking, zero (FALSE) otherwise.
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_history (union param_val  val,
sim_history (union param_val  val,
             void            *dat)
             void            *dat)
{
{
  config.sim.history = val.int_val;
  config.sim.history = val.int_val;
}
}
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Record an execution log
/*!Record an execution log
 
 
   @param[in] val  Non-zero (TRUE) to turn on logging, zero (FALSE) otherwise.
   @param[in] val  Non-zero (TRUE) to turn on logging, zero (FALSE) otherwise.
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_exe_log (union param_val  val,
sim_exe_log (union param_val  val,
             void            *dat)
             void            *dat)
{
{
  config.sim.exe_log = val.int_val;
  config.sim.exe_log = val.int_val;
 
 
}       /* sim_exe_log () */
}       /* sim_exe_log () */
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Set the execution log type
/*!Set the execution log type
 
 
   Value must be one of default, hardware, simple or software. Invalid values
   Value must be one of default, hardware, simple or software. Invalid values
   are ignored with a warning.
   are ignored with a warning.
 
 
   @param[in] val  The value to use
   @param[in] val  The value to use
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_exe_log_type (union param_val  val,
sim_exe_log_type (union param_val  val,
                  void            *dat)
                  void            *dat)
{
{
  if (strcasecmp (val.str_val, "default") == 0)
  if (strcasecmp (val.str_val, "default") == 0)
    {
    {
      config.sim.exe_log_type = EXE_LOG_HARDWARE;
      config.sim.exe_log_type = EXE_LOG_HARDWARE;
    }
    }
  else if (strcasecmp (val.str_val, "hardware") == 0)
  else if (strcasecmp (val.str_val, "hardware") == 0)
    {
    {
      config.sim.exe_log_type = EXE_LOG_HARDWARE;
      config.sim.exe_log_type = EXE_LOG_HARDWARE;
    }
    }
  else if (strcasecmp (val.str_val, "simple") == 0)
  else if (strcasecmp (val.str_val, "simple") == 0)
    {
    {
      config.sim.exe_log_type = EXE_LOG_SIMPLE;
      config.sim.exe_log_type = EXE_LOG_SIMPLE;
    }
    }
  else if (strcasecmp (val.str_val, "software") == 0)
  else if (strcasecmp (val.str_val, "software") == 0)
    {
    {
      config.sim.exe_log_type = EXE_LOG_SOFTWARE;
      config.sim.exe_log_type = EXE_LOG_SOFTWARE;
    }
    }
  else
  else
    {
    {
      fprintf (stderr, "Warning: Execution log type %s invalid. Ignored",
      fprintf (stderr, "Warning: Execution log type %s invalid. Ignored",
               val.str_val);
               val.str_val);
    }
    }
}       /* sim_exe_log_type() */
}       /* sim_exe_log_type() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Set the execution log start address
/*!Set the execution log start address
 
 
   Address at which to start logging.
   Address at which to start logging.
 
 
   @param[in] val  The value to use
   @param[in] val  The value to use
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_exe_log_start (union param_val  val,
sim_exe_log_start (union param_val  val,
                   void            *dat)
                   void            *dat)
{
{
  config.sim.exe_log_start = val.longlong_val;
  config.sim.exe_log_start = val.longlong_val;
 
 
}       /* sim_exe_log_start () */
}       /* sim_exe_log_start () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Set the execution log end address
/*!Set the execution log end address
 
 
   Address at which to end logging.
   Address at which to end logging.
 
 
   @param[in] val  The value to use
   @param[in] val  The value to use
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_exe_log_end (union param_val  val,
sim_exe_log_end (union param_val  val,
                 void            *dat)
                 void            *dat)
{
{
  config.sim.exe_log_end = val.longlong_val;
  config.sim.exe_log_end = val.longlong_val;
 
 
}       /* sim_exe_log_end () */
}       /* sim_exe_log_end () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Specify number of instruction between printing horizontal markers
/*!Specify number of instruction between printing horizontal markers
 
 
   Control of log format
   Control of log format
 
 
   @param[in] val  The value to use
   @param[in] val  The value to use
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_exe_log_marker (union param_val  val,
sim_exe_log_marker (union param_val  val,
                    void            *dat)
                    void            *dat)
{
{
  config.sim.exe_log_marker = val.int_val;
  config.sim.exe_log_marker = val.int_val;
 
 
}       /* sim_exe_log_marker () */
}       /* sim_exe_log_marker () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Specify the execution log file name.
/*!Specify the execution log file name.
 
 
   @param[in] val  The execution log file name
   @param[in] val  The execution log file name
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_exe_log_fn (union param_val val, void *dat)
sim_exe_log_fn (union param_val val, void *dat)
{
{
  if (NULL != config.sim.exe_log_fn)
  if (NULL != config.sim.exe_log_fn)
    {
    {
      free (config.sim.exe_log_fn);
      free (config.sim.exe_log_fn);
    }
    }
 
 
  config.sim.exe_log_fn = strdup (val.str_val);
  config.sim.exe_log_fn = strdup (val.str_val);
 
 
}       /* sim_exe_log_fn () */
}       /* sim_exe_log_fn () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Turn on binary instruction logging
/*!Turn on binary instruction logging
 
 
   @param[in] val  Non-zero (TRUE) to turn on logging, zero (FALSE) otherwise.
   @param[in] val  Non-zero (TRUE) to turn on logging, zero (FALSE) otherwise.
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_exe_bin_insn_log (union param_val val, void *dat)
sim_exe_bin_insn_log (union param_val val, void *dat)
{
{
  config.sim.exe_bin_insn_log = val.int_val;
  config.sim.exe_bin_insn_log = val.int_val;
 
 
}       /* sim_exe_bin_insn_log () */
}       /* sim_exe_bin_insn_log () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Specify the binary instruction log file name.
/*!Specify the binary instruction log file name.
 
 
   @param[in] val  The binary instruction log file name
   @param[in] val  The binary instruction log file name
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
sim_exe_bin_insn_log_fn (union param_val val, void *dat)
sim_exe_bin_insn_log_fn (union param_val val, void *dat)
{
{
  if (NULL != config.sim.exe_bin_insn_log_fn)
  if (NULL != config.sim.exe_bin_insn_log_fn)
    {
    {
      free (config.sim.exe_bin_insn_log_fn);
      free (config.sim.exe_bin_insn_log_fn);
    }
    }
 
 
  config.sim.exe_bin_insn_log_fn = strdup (val.str_val);
  config.sim.exe_bin_insn_log_fn = strdup (val.str_val);
 
 
}       /* sim_exe_bin_insn_log_fn () */
}       /* sim_exe_bin_insn_log_fn () */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Set the clock cycle time.
/*!Set the clock cycle time.
 
 
   Value must be an integer followed by one of ps, ns, us or ms.
   Value must be an integer followed by one of ps, ns, us or ms.
 
 
   If a valid time is not presented, the value is unchanged.
   If a valid time is not presented, the value is unchanged.
 
 
   @param[in] val  The value to use
   @param[in] val  The value to use
   @param[in] dat  The config data structure (not used here)                 */
   @param[in] dat  The config data structure (not used here)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
void
sim_clkcycle (union param_val  val,
sim_clkcycle (union param_val  val,
              void            *dat)
              void            *dat)
{
{
  int len = strlen (val.str_val);
  int len = strlen (val.str_val);
  int pos = len - 1;
  int pos = len - 1;
  long time;
  long time;
  if ((len < 2) || (val.str_val[pos--] != 's'))
  if ((len < 2) || (val.str_val[pos--] != 's'))
    {
    {
      fprintf (stderr, "Warning: Clock cycle time %s invalid: ignored\n",
      fprintf (stderr, "Warning: Clock cycle time %s invalid: ignored\n",
               val.str_val);
               val.str_val);
      return;
      return;
    }
    }
 
 
  switch (val.str_val[pos--])
  switch (val.str_val[pos--])
    {
    {
    case 'p':
    case 'p':
      time = 1;
      time = 1;
      break;
      break;
    case 'n':
    case 'n':
      time = 1000;
      time = 1000;
      break;
      break;
    case 'u':
    case 'u':
      time = 1000000;
      time = 1000000;
      break;
      break;
    case 'm':
    case 'm':
      time = 1000000000;
      time = 1000000000;
      break;
      break;
    default:
    default:
      fprintf (stderr, "Warning: Clock cycle time %s invalid: ignored\n",
      fprintf (stderr, "Warning: Clock cycle time %s invalid: ignored\n",
               val.str_val);
               val.str_val);
      return;
      return;
    }
    }
 
 
  val.str_val[pos + 1] = 0;
  val.str_val[pos + 1] = 0;
  time = time * atol (val.str_val);
  time = time * atol (val.str_val);
 
 
  if (0 == time)
  if (0 == time)
    {
    {
      fprintf (stderr, "Warning: Clock cycle time of zero invalid: ignored\n");
      fprintf (stderr, "Warning: Clock cycle time of zero invalid: ignored\n");
      return;
      return;
    }
    }
 
 
  config.sim.clkcycle_ps = time;
  config.sim.clkcycle_ps = time;
 
 
}       /* sim_clkcycle() */
}       /* sim_clkcycle() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Register the functions to handle a section sim
/*!Register the functions to handle a section sim
 
 
   This section does not allocate dynamically a data structure holding its
   This section does not allocate dynamically a data structure holding its
   config information. It's all in the global config.sim data
   config information. It's all in the global config.sim data
   structure. Therefore it does not need a start and end function to
   structure. Therefore it does not need a start and end function to
   initialize default values (although it might be clearer to do so). The
   initialize default values (although it might be clearer to do so). The
   default values are set in init_defconfig().
   default values are set in init_defconfig().
 
 
   New preferred parameter names are introduced (_file for filenames), but
   New preferred parameter names are introduced (_file for filenames), but
   the legacy names (_fn) are also present for backwards compatibility       */
   the legacy names (_fn) are also present for backwards compatibility       */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static void
static void
reg_sim_sec ()
reg_sim_sec ()
{
{
  struct config_section *sec = reg_config_sec ("sim", NULL, NULL);
  struct config_section *sec = reg_config_sec ("sim", NULL, NULL);
 
 
  reg_config_param (sec, "verbose",        PARAMT_INT,      sim_verbose);
  reg_config_param (sec, "verbose",        PARAMT_INT,      sim_verbose);
  reg_config_param (sec, "debug",          PARAMT_INT,      sim_debug);
  reg_config_param (sec, "debug",          PARAMT_INT,      sim_debug);
  reg_config_param (sec, "profile",        PARAMT_INT,      sim_profile);
  reg_config_param (sec, "profile",        PARAMT_INT,      sim_profile);
  reg_config_param (sec, "prof_file",      PARAMT_STR,      sim_prof_fn);
  reg_config_param (sec, "prof_file",      PARAMT_STR,      sim_prof_fn);
  reg_config_param (sec, "prof_fn",        PARAMT_STR,      sim_prof_fn);
  reg_config_param (sec, "prof_fn",        PARAMT_STR,      sim_prof_fn);
  reg_config_param (sec, "mprofile",       PARAMT_INT,      sim_mprofile);
  reg_config_param (sec, "mprofile",       PARAMT_INT,      sim_mprofile);
  reg_config_param (sec, "mprof_file",     PARAMT_STR,      sim_mprof_fn);
  reg_config_param (sec, "mprof_file",     PARAMT_STR,      sim_mprof_fn);
  reg_config_param (sec, "mprof_fn",       PARAMT_STR,      sim_mprof_fn);
  reg_config_param (sec, "mprof_fn",       PARAMT_STR,      sim_mprof_fn);
  reg_config_param (sec, "history",        PARAMT_INT,      sim_history);
  reg_config_param (sec, "history",        PARAMT_INT,      sim_history);
  reg_config_param (sec, "exe_log",        PARAMT_INT,      sim_exe_log);
  reg_config_param (sec, "exe_log",        PARAMT_INT,      sim_exe_log);
  reg_config_param (sec, "exe_log_type",   PARAMT_WORD,     sim_exe_log_type);
  reg_config_param (sec, "exe_log_type",   PARAMT_WORD,     sim_exe_log_type);
  reg_config_param (sec, "exe_log_start",  PARAMT_LONGLONG, sim_exe_log_start);
  reg_config_param (sec, "exe_log_start",  PARAMT_LONGLONG, sim_exe_log_start);
  reg_config_param (sec, "exe_log_end",    PARAMT_LONGLONG, sim_exe_log_end);
  reg_config_param (sec, "exe_log_end",    PARAMT_LONGLONG, sim_exe_log_end);
  reg_config_param (sec, "exe_log_marker", PARAMT_INT,      sim_exe_log_marker);
  reg_config_param (sec, "exe_log_marker", PARAMT_INT,      sim_exe_log_marker);
  reg_config_param (sec, "exe_log_file",   PARAMT_STR,      sim_exe_log_fn);
  reg_config_param (sec, "exe_log_file",   PARAMT_STR,      sim_exe_log_fn);
  reg_config_param (sec, "exe_log_fn",     PARAMT_STR,      sim_exe_log_fn);
  reg_config_param (sec, "exe_log_fn",     PARAMT_STR,      sim_exe_log_fn);
 
 
  reg_config_param (sec, "exe_bin_insn_log",      PARAMT_INT,
  reg_config_param (sec, "exe_bin_insn_log",      PARAMT_INT,
                    sim_exe_bin_insn_log);
                    sim_exe_bin_insn_log);
  reg_config_param (sec, "exe_bin_insn_log_fn",   PARAMT_STR,
  reg_config_param (sec, "exe_bin_insn_log_fn",   PARAMT_STR,
                    sim_exe_bin_insn_log_fn);
                    sim_exe_bin_insn_log_fn);
  reg_config_param (sec, "exe_bin_insn_log_file", PARAMT_STR,
  reg_config_param (sec, "exe_bin_insn_log_file", PARAMT_STR,
                    sim_exe_bin_insn_log_fn);
                    sim_exe_bin_insn_log_fn);
 
 
  reg_config_param (sec, "clkcycle",       PARAMT_WORD,     sim_clkcycle);
  reg_config_param (sec, "clkcycle",       PARAMT_WORD,     sim_clkcycle);
 
 
}       /* reg_sim_sec() */
}       /* reg_sim_sec() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!Register all the possible sections which we support.
/*!Register all the possible sections which we support.
 
 
   Each section type provides a registration function. This returns a struct
   Each section type provides a registration function. This returns a struct
   config_section, which in turn contains a list of config_params.           */
   config_section, which in turn contains a list of config_params.           */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
void
reg_config_secs ()
reg_config_secs ()
{
{
  reg_generic_sec ();           /* JPB */
  reg_generic_sec ();           /* JPB */
  reg_sim_sec ();
  reg_sim_sec ();
  reg_cpu_sec ();
  reg_cpu_sec ();
  reg_pic_sec ();
  reg_pic_sec ();
  reg_memory_sec ();
  reg_memory_sec ();
  reg_mc_sec ();
  reg_mc_sec ();
  reg_uart_sec ();
  reg_uart_sec ();
  reg_dma_sec ();
  reg_dma_sec ();
  reg_debug_sec ();
  reg_debug_sec ();
  reg_vapi_sec ();
  reg_vapi_sec ();
  reg_ethernet_sec ();
  reg_ethernet_sec ();
  reg_immu_sec ();
  reg_immu_sec ();
  reg_dmmu_sec ();
  reg_dmmu_sec ();
  reg_ic_sec ();
  reg_ic_sec ();
  reg_dc_sec ();
  reg_dc_sec ();
  reg_gpio_sec ();
  reg_gpio_sec ();
  reg_bpb_sec ();
  reg_bpb_sec ();
  reg_pm_sec ();
  reg_pm_sec ();
  reg_vga_sec ();
  reg_vga_sec ();
  reg_fb_sec ();
  reg_fb_sec ();
  reg_kbd_sec ();
  reg_kbd_sec ();
  reg_ata_sec ();
  reg_ata_sec ();
  reg_cuc_sec ();
  reg_cuc_sec ();
}
}
 
 
/* Utility for execution of set sim command.  */
/* Utility for execution of set sim command.  */
static int
static int
set_config (int argc, char **argv)
set_config (int argc, char **argv)
{
{
  struct config_section *cur_section;
  struct config_section *cur_section;
  struct config_param *param;
  struct config_param *param;
 
 
  if (argc < 2)
  if (argc < 2)
    return 1;
    return 1;
 
 
  PRINTF ("sec:%s\n", argv[1]);
  PRINTF ("sec:%s\n", argv[1]);
  cur_section = lookup_section (argv[1]);
  cur_section = lookup_section (argv[1]);
 
 
  if (NULL == cur_section)
  if (NULL == cur_section)
    return 1;
    return 1;
 
 
  if (argc < 3)
  if (argc < 3)
    return 2;
    return 2;
 
 
  PRINTF ("item:%s\n", argv[2]);
  PRINTF ("item:%s\n", argv[2]);
  {
  {
    for (param = cur_section->params; param; param = param->next)
    for (param = cur_section->params; param; param = param->next)
      if (strcmp (param->name, argv[2]) == 0)
      if (strcmp (param->name, argv[2]) == 0)
        {
        {
          break;
          break;
        }
        }
    if (!param)
    if (!param)
      return 2;
      return 2;
 
 
    /* Parse parameter value */
    /* Parse parameter value */
    if (param->type)
    if (param->type)
      {
      {
        if (argc < 4)
        if (argc < 4)
          return 3;
          return 3;
        PRINTF ("params:%s\n", argv[3]);
        PRINTF ("params:%s\n", argv[3]);
      }
      }
 
 
    set_config_param (cur_section, param, argv[3]);
    set_config_param (cur_section, param, argv[3]);
  }
  }
  return 0;
  return 0;
}
}
 
 
/* Executes set sim command, displays error.  */
/* Executes set sim command, displays error.  */
void
void
set_config_command (int argc, char **argv)
set_config_command (int argc, char **argv)
{
{
  struct config_section *cur;
  struct config_section *cur;
  struct config_param *param;
  struct config_param *param;
 
 
  switch (set_config (argc, argv))
  switch (set_config (argc, argv))
    {
    {
    case 1:
    case 1:
      PRINTF
      PRINTF
        ("Invalid or missing section name.  One of valid sections must be specified:\n");
        ("Invalid or missing section name.  One of valid sections must be specified:\n");
      for (cur = section_master_list; cur; cur = cur->next)
      for (cur = section_master_list; cur; cur = cur->next)
        PRINTF ("%s ", cur->name);
        PRINTF ("%s ", cur->name);
      PRINTF ("\n");
      PRINTF ("\n");
      break;
      break;
    case 2:
    case 2:
      cur = lookup_section (argv[1]);
      cur = lookup_section (argv[1]);
      PRINTF
      PRINTF
        ("Invalid or missing item name.  One of valid items must be specified:\n");
        ("Invalid or missing item name.  One of valid items must be specified:\n");
      for (param = cur->params; param;
      for (param = cur->params; param;
           param = param->next)
           param = param->next)
        PRINTF ("%s ", param->name);
        PRINTF ("%s ", param->name);
      PRINTF ("\n");
      PRINTF ("\n");
      break;
      break;
    case 3:
    case 3:
      PRINTF ("Invalid parameters specified.\n");
      PRINTF ("Invalid parameters specified.\n");
      break;
      break;
    }
    }
}
}
 
 

powered by: WebSVN 2.1.0

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