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

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [or1ksim/] [or1ksim-0.4.0/] [sim-config.c] - Diff between revs 100 and 135

Only display areas with differences | Details | Blame | View Log

Rev 100 Rev 135
/* 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"
 
 
 
 
struct config config;
struct config config;
struct runtime runtime;
struct runtime runtime;
 
 
struct config_section *cur_section;
struct config_section *cur_section;
 
 
struct config_section *sections = NULL;
struct config_section *sections = NULL;
 
 
/* Forward declarations */
/* Forward declarations */
static void read_script_file (const char *filename);
static void read_script_file (const char *filename);
 
 
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!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.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.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;
 
 
  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.gdb_enabled = 0;
  config.debug.gdb_enabled = 0;
  config.debug.rsp_enabled = 0;
  config.debug.rsp_enabled = 0;
  config.debug.server_port = 51000;
  config.debug.server_port = 51000;
  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() */
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*! 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 *dbg;
  struct arg_str *dbg;
  struct arg_lit *command;
  struct arg_lit *command;
  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;
 
 
  void *argtab[12];
  void *argtab[12];
  int nerrors;
  int nerrors;
 
 
  /* 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 JTAG proxy server");
  nosrv = arg_lit0 (NULL, "nosrv", "do not launch JTAG proxy server");
  srv = arg_int0 (NULL, "srv", "<n>", "port number (default random)");
  srv = arg_int0 (NULL, "srv", "<n>", "port number (default random)");
  srv->ival[0] = rand () % (65536 - 49152) + 49152;
  srv->ival[0] = rand () % (65536 - 49152) + 49152;
  srv->hdr.flag |= ARG_HASOPTVALUE;
  srv->hdr.flag |= ARG_HASOPTVALUE;
  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");
  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);
 
 
  /* Set up the argument table */
  /* Set up the argument table */
  argtab[ 0] = vercop;
  argtab[ 0] = vercop;
  argtab[ 1] = help;
  argtab[ 1] = help;
  argtab[ 2] = cfg_file;
  argtab[ 2] = cfg_file;
  argtab[ 3] = nosrv;
  argtab[ 3] = nosrv;
  argtab[ 4] = srv;
  argtab[ 4] = srv;
  argtab[ 5] = dbg;
  argtab[ 5] = dbg;
  argtab[ 6] = command;
  argtab[ 6] = command;
  argtab[ 7] = strict_npc;
  argtab[ 7] = strict_npc;
  argtab[ 8] = profile;
  argtab[ 8] = profile;
  argtab[ 9] = mprofile;
  argtab[ 9] = mprofile;
  argtab[10] = load_file;
  argtab[10] = load_file;
  argtab[11] = end;
  argtab[11] = end;
 
 
  /* Parse */
  /* Parse */
  nerrors = arg_parse (argc, argv, argtab);
  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;
    }
    }
 
 
  /* Process config file next, so any other command args will override */
  /* Process config file next, so any other command args will override */
  if (0 == cfg_file->count)
  if (0 == cfg_file->count)
    {
    {
      fprintf (stderr,
      fprintf (stderr,
               "Warning: No config file given, default configuration used\n");
               "Warning: No config file given, default configuration used\n");
    }
    }
 
 
  read_script_file (cfg_file->filename[0]);
  read_script_file (cfg_file->filename[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.gdb_enabled = 0;
          config.debug.gdb_enabled = 0;
        }
        }
    }
    }
 
 
  if (srv->count > 0)
  if (srv->count > 0)
    {
    {
      config.debug.enabled = 1;
      config.debug.enabled = 1;
      config.debug.gdb_enabled = 1;
      config.debug.gdb_enabled = 1;
      config.debug.server_port = srv->ival[0];
      config.debug.server_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");
    }
    }
}
}
 
 
struct config_param
struct config_param
{
{
  char *name;
  char *name;
  enum param_t type;
  enum param_t type;
  void (*func) (union param_val, void *dat);
  void (*func) (union param_val, void *dat);
  struct config_param *next;
  struct config_param *next;
};
};
 
 
void
void
base_include (union param_val val, void *dat)
base_include (union param_val val, void *dat)
{
{
  read_script_file (val.str_val);
  read_script_file (val.str_val);
  cur_section = NULL;
  cur_section = NULL;
}
}
 
 
/*---------------------------------------------[ Simulator configuration ]---*/
/*---------------------------------------------[ Simulator configuration ]---*/
 
 
 
 
void
void
sim_verbose (union param_val val, void *dat)
sim_verbose (union param_val val, void *dat)
{
{
  config.sim.verbose = val.int_val;
  config.sim.verbose = val.int_val;
}
}
 
 
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!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)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
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() */
 
 
 
 
void
void
sim_profile (union param_val val, void *dat)
sim_profile (union param_val val, void *dat)
{
{
  config.sim.profile = val.int_val;
  config.sim.profile = val.int_val;
}
}
 
 
void
void
sim_prof_fn (union param_val val, void *dat)
sim_prof_fn (union param_val val, 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);
}
}
 
 
void
void
sim_mprofile (union param_val val, void *dat)
sim_mprofile (union param_val val, void *dat)
{
{
  config.sim.mprofile = val.int_val;
  config.sim.mprofile = val.int_val;
}
}
 
 
void
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);
}
}
 
 
void
void
sim_history (union param_val val, void *dat)
sim_history (union param_val val, void *dat)
{
{
  config.sim.history = val.int_val;
  config.sim.history = val.int_val;
}
}
 
 
void
void
sim_exe_log (union param_val val, void *dat)
sim_exe_log (union param_val val, void *dat)
{
{
  config.sim.exe_log = val.int_val;
  config.sim.exe_log = val.int_val;
}
}
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!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)                 */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
void
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() */
 
 
 
 
void
void
sim_exe_log_start (union param_val val, void *dat)
sim_exe_log_start (union param_val val, void *dat)
{
{
  config.sim.exe_log_start = val.longlong_val;
  config.sim.exe_log_start = val.longlong_val;
}
}
 
 
void
void
sim_exe_log_end (union param_val val, void *dat)
sim_exe_log_end (union param_val val, void *dat)
{
{
  config.sim.exe_log_end = val.longlong_val;
  config.sim.exe_log_end = val.longlong_val;
}
}
 
 
void
void
sim_exe_log_marker (union param_val val, void *dat)
sim_exe_log_marker (union param_val val, void *dat)
{
{
  config.sim.exe_log_marker = val.int_val;
  config.sim.exe_log_marker = val.int_val;
}
}
 
 
void
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);
}
}
 
 
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*!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, "clkcycle",       paramt_word,     sim_clkcycle);
  reg_config_param (sec, "clkcycle",       paramt_word,     sim_clkcycle);
 
 
}       /* reg_sim_sec() */
}       /* reg_sim_sec() */
 
 
 
 
void
void
reg_config_secs (void)
reg_config_secs (void)
{
{
  reg_config_param (reg_config_sec ("base", NULL, NULL), "include",
  reg_config_param (reg_config_sec ("base", NULL, NULL), "include",
                    paramt_str, base_include);
                    paramt_str, base_include);
 
 
  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 ();
}
}
 
 
void
void
reg_config_param (struct config_section *sec, const char *param,
reg_config_param (struct config_section *sec, const char *param,
                  enum param_t type,
                  enum param_t type,
                  void (*param_cb) (union param_val, void *))
                  void (*param_cb) (union param_val, 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, "Out-of-memory\n");
      fprintf (stderr, "Out-of-memory\n");
      exit (1);
      exit (1);
    }
    }
 
 
  if (!(new->name = strdup (param)))
  if (!(new->name = strdup (param)))
    {
    {
      fprintf (stderr, "Out-of-memory\n");
      fprintf (stderr, "Out-of-memory\n");
      exit (1);
      exit (1);
    }
    }
 
 
  new->func = param_cb;
  new->func = param_cb;
  new->type = type;
  new->type = type;
 
 
  new->next = sec->params;
  new->next = sec->params;
  sec->params = new;
  sec->params = new;
}
}
 
 
struct config_section *
struct config_section *
reg_config_sec (const char *section,
reg_config_sec (const char *section,
                void *(*sec_start) (void), void (*sec_end) (void *))
                void *(*sec_start) (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, "Out-of-memory\n");
      fprintf (stderr, "Out-of-memory\n");
      exit (1);
      exit (1);
    }
    }
 
 
  if (!(new->name = strdup (section)))
  if (!(new->name = strdup (section)))
    {
    {
      fprintf (stderr, "Out-of-memory\n");
      fprintf (stderr, "Out-of-memory\n");
      exit (1);
      exit (1);
    }
    }
 
 
  new->next = sections;
  new->next = sections;
  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;
 
 
  sections = new;
  sections = new;
 
 
  return new;
  return new;
}
}
 
 
static void
static void
switch_param (char *param, struct config_param *cur_param)
switch_param (char *param, struct config_param *cur_param)
{
{
  char *end_p;
  char *end_p;
  union param_val val;
  union param_val val;
 
 
  /* Skip over an = sign if it exists */
  /* Skip over an = sign if it exists */
  if (*param == '=')
  if (*param == '=')
    {
    {
      param++;
      param++;
      while (*param && isspace (*param))
      while (*param && isspace (*param))
        param++;
        param++;
    }
    }
 
 
  switch (cur_param->type)
  switch (cur_param->type)
    {
    {
    case paramt_int:
    case paramt_int:
      val.int_val = strtol (param, NULL, 0);
      val.int_val = strtol (param, NULL, 0);
      break;
      break;
    case paramt_longlong:
    case paramt_longlong:
      val.longlong_val = strtoll (param, NULL, 0);
      val.longlong_val = strtoll (param, NULL, 0);
      break;
      break;
    case paramt_addr:
    case paramt_addr:
      val.addr_val = strtoul (param, NULL, 0);
      val.addr_val = strtoul (param, NULL, 0);
      break;
      break;
    case paramt_str:
    case paramt_str:
      if (*param != '"')
      if (*param != '"')
        {
        {
          fprintf (stderr,
          fprintf (stderr,
                   "Warning: String value for parameter expected: ignored\n");
                   "Warning: String value for parameter expected: ignored\n");
          return;
          return;
        }
        }
 
 
      param++;
      param++;
      end_p = param;
      end_p = param;
      while (*end_p && (*end_p != '"'))
      while (*end_p && (*end_p != '"'))
        end_p++;
        end_p++;
      *end_p = '\0';
      *end_p = '\0';
      val.str_val = param;
      val.str_val = param;
      break;
      break;
    case paramt_word:
    case paramt_word:
      end_p = param;
      end_p = param;
      while (*end_p && !isspace (*end_p))
      while (*end_p && !isspace (*end_p))
        end_p++;
        end_p++;
      *end_p = '\0';
      *end_p = '\0';
      val.str_val = param;
      val.str_val = param;
      break;
      break;
    case paramt_none:
    case paramt_none:
      break;
      break;
    }
    }
 
 
  cur_param->func (val, cur_section->dat);
  cur_param->func (val, cur_section->dat);
}
}
 
 
/* Read environment from a script file. Does not fail - assumes default configuration instead.
/* Read environment from a script file. Does not fail - assumes default configuration instead.
   The syntax of script file is:
   The syntax of script file is:
   param = value
   param = value
   section x
   section x
     data
     data
     param = value
     param = value
   end
   end
 
 
   Example:
   Example:
   section mc
   section mc
     memory_table_file = sim.mem
     memory_table_file = sim.mem
     enable = 1
     enable = 1
     POC = 0x47892344
     POC = 0x47892344
   end
   end
 
 
 */
 */
 
 
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 ctmp[STR_SIZE];
  char ctmp[STR_SIZE];
  int local = 1;
  int local = 1;
  cur_section = NULL;
  cur_section = NULL;
 
 
  sprintf (ctmp, "%s/.or1k/%s", home, filename);
  sprintf (ctmp, "%s/.or1k/%s", home, filename);
  if ((f = fopen (filename, "rt")) || (home && (f = fopen (ctmp, "rt"))))
  if ((f = fopen (filename, "rt")) || (home && (f = fopen (ctmp, "rt"))))
    {
    {
      if (config.sim.verbose)
      if (config.sim.verbose)
        PRINTF ("Reading script file from '%s'...\n",
        PRINTF ("Reading script file from '%s'...\n",
                local ? filename : ctmp);
                local ? filename : ctmp);
 
 
      while (!feof (f))
      while (!feof (f))
        {
        {
          char param[STR_SIZE];
          char param[STR_SIZE];
          if (fscanf (f, "%s ", param) != 1)
          if (fscanf (f, "%s ", param) != 1)
            break;
            break;
          /* Is this a section? */
          /* Is this a section? */
          if (strcmp (param, "section") == 0)
          if (strcmp (param, "section") == 0)
            {
            {
              struct config_section *cur;
              struct config_section *cur;
              cur_section = NULL;
              cur_section = NULL;
              if (fscanf (f, "%s\n", param) != 1)
              if (fscanf (f, "%s\n", param) != 1)
                {
                {
                  fprintf (stderr, "%s: ERROR: Section name required.\n",
                  fprintf (stderr, "%s: ERROR: Section name required.\n",
                           local ? filename : ctmp);
                           local ? filename : ctmp);
                  exit (1);
                  exit (1);
                }
                }
              for (cur = sections; cur; cur = cur->next)
              for (cur = sections; cur; cur = cur->next)
                if (strcmp (cur->name, param) == 0)
                if (strcmp (cur->name, param) == 0)
                  {
                  {
                    cur_section = cur;
                    cur_section = cur;
                    break;
                    break;
                  }
                  }
              if (!cur)
              if (!cur)
                {
                {
                  fprintf (stderr,
                  fprintf (stderr,
                           "Warning: Unknown config section: %s; ignoring.\n",
                           "Warning: Unknown config section: %s; ignoring.\n",
                           param);
                           param);
                  /* just skip section */
                  /* just skip section */
                  while (fscanf (f, "%s\n", param) == 1
                  while (fscanf (f, "%s\n", param) == 1
                         && strcmp (param, "end"));
                         && strcmp (param, "end"));
                }
                }
              else
              else
                {
                {
                  cur->dat = NULL;
                  cur->dat = NULL;
                  if (cur->sec_start)
                  if (cur->sec_start)
                    cur->dat = cur->sec_start ();
                    cur->dat = cur->sec_start ();
                }
                }
            }
            }
          else if (strcmp (param, "end") == 0)
          else if (strcmp (param, "end") == 0)
            {
            {
              if (cur_section->sec_end)
              if (cur_section->sec_end)
                cur_section->sec_end (cur_section->dat);
                cur_section->sec_end (cur_section->dat);
              cur_section = NULL;
              cur_section = NULL;
            }
            }
          else if (strncmp (param, "/*", 2) == 0)
          else if (strncmp (param, "/*", 2) == 0)
            {
            {
              char c0 = 0, c1 = 0;
              char c0 = 0, c1 = 0;
              while (c0 != '*' || c1 != '/')
              while (c0 != '*' || c1 != '/')
                {
                {
                  c0 = c1;
                  c0 = c1;
                  c1 = fgetc (f);
                  c1 = fgetc (f);
                  if (feof (f))
                  if (feof (f))
                    {
                    {
                      fprintf (stderr, "%s: ERROR: Comment reached EOF.\n",
                      fprintf (stderr, "%s: ERROR: Comment reached EOF.\n",
                               local ? filename : ctmp);
                               local ? filename : ctmp);
                      exit (1);
                      exit (1);
                    }
                    }
                }
                }
            }
            }
          else
          else
            {
            {
              struct config_param *cur_param = NULL;
              struct config_param *cur_param = NULL;
              char *cur_p;
              char *cur_p;
              /* If we have a corrupt file, this could be encountered outside
              /* If we have a corrupt file, this could be encountered outside
                 a section. So make sure cur_section is defined. */
                 a section. So make sure cur_section is defined. */
              if (cur_section)
              if (cur_section)
                {
                {
                  for (cur_param = cur_section->params; cur_param;
                  for (cur_param = cur_section->params; cur_param;
                       cur_param = cur_param->next)
                       cur_param = cur_param->next)
                    {
                    {
                      if (strcmp (cur_param->name, param) == 0)
                      if (strcmp (cur_param->name, param) == 0)
                        {
                        {
                          break;
                          break;
                        }
                        }
                    }
                    }
                }
                }
              if (!cur_param)
              if (!cur_param)
                {
                {
                  fprintf (stderr, "Warning: Invalid parameter: %s; ignored\n",
                  fprintf (stderr, "Warning: Invalid parameter: %s; ignored\n",
                           param);
                           param);
                  while (fgetc (f) != '\n' || feof (f));
                  while (fgetc (f) != '\n' || feof (f));
                  continue;
                  continue;
                }
                }
 
 
              if (cur_param->type == paramt_none)
              if (cur_param->type == paramt_none)
                continue;
                continue;
 
 
              /* Parse parameter value */
              /* Parse parameter value */
              cur_p = fgets (param, STR_SIZE, f);
              cur_p = fgets (param, STR_SIZE, f);
 
 
              while (*cur_p && isspace (*cur_p))
              while (*cur_p && isspace (*cur_p))
                cur_p++;
                cur_p++;
 
 
              switch_param (cur_p, cur_param);
              switch_param (cur_p, cur_param);
            }
            }
        }
        }
      fclose (f);
      fclose (f);
    }
    }
  else if (config.sim.verbose)
  else if (config.sim.verbose)
    fprintf (stderr,
    fprintf (stderr,
             "Warning: Cannot read script file from '%s' of '%s'.\n",
             "Warning: Cannot read script file from '%s' of '%s'.\n",
             filename, ctmp);
             filename, ctmp);
}
}
 
 
/* 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;
  struct config_section *cur;
  struct config_param *cur_param;
  struct config_param *cur_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 = NULL;
  cur_section = NULL;
  for (cur = sections; cur; cur = cur->next)
  for (cur = sections; cur; cur = cur->next)
    if (strcmp (cur->name, argv[1]) == 0)
    if (strcmp (cur->name, argv[1]) == 0)
      {
      {
        cur_section = cur;
        cur_section = cur;
        break;
        break;
      }
      }
 
 
  if (!cur_section)
  if (!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 (cur_param = cur->params; cur_param; cur_param = cur_param->next)
    for (cur_param = cur->params; cur_param; cur_param = cur_param->next)
      if (strcmp (cur_param->name, argv[2]) == 0)
      if (strcmp (cur_param->name, argv[2]) == 0)
        {
        {
          break;
          break;
        }
        }
    if (!cur_param)
    if (!cur_param)
      return 2;
      return 2;
 
 
    /* Parse parameter value */
    /* Parse parameter value */
    if (cur_param->type)
    if (cur_param->type)
      {
      {
        if (argc < 4)
        if (argc < 4)
          return 3;
          return 3;
        PRINTF ("params:%s\n", argv[3]);
        PRINTF ("params:%s\n", argv[3]);
      }
      }
 
 
    switch_param (argv[3], cur_param);
    switch_param (argv[3], cur_param);
  }
  }
  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 *cur_param;
  struct config_param *cur_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 = sections; cur; cur = cur->next)
      for (cur = sections; cur; cur = cur->next)
        PRINTF ("%s ", cur->name);
        PRINTF ("%s ", cur->name);
      PRINTF ("\n");
      PRINTF ("\n");
      break;
      break;
    case 2:
    case 2:
      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 (cur_param = cur_section->params; cur_param;
      for (cur_param = cur_section->params; cur_param;
           cur_param = cur_param->next)
           cur_param = cur_param->next)
        PRINTF ("%s ", cur_param->name);
        PRINTF ("%s ", cur_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.