/* 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
|
|
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
(at your option) any later version.
|
(at your option) any later version.
|
|
|
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
GNU General Public License for more details.
|
GNU General Public License for more details.
|
|
|
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
/* Simulator configuration. Eventually this one will be a lot bigger. */
|
/* Simulator configuration. Eventually this one will be a lot bigger. */
|
|
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <limits.h>
|
#include <limits.h>
|
#include <string.h>
|
#include <string.h>
|
#include <ctype.h>
|
#include <ctype.h>
|
|
|
#include "config.h"
|
#include "config.h"
|
|
|
#ifdef HAVE_INTTYPES_H
|
#ifdef HAVE_INTTYPES_H
|
#include <inttypes.h>
|
#include <inttypes.h>
|
#endif
|
#endif
|
|
|
#include "port.h"
|
#include "port.h"
|
#include "arch.h"
|
#include "arch.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "sprs.h"
|
#include "sprs.h"
|
#include "spr_defs.h"
|
#include "spr_defs.h"
|
#include "pic.h"
|
#include "pic.h"
|
#include "opcode/or32.h"
|
#include "opcode/or32.h"
|
#include "stats.h"
|
#include "stats.h"
|
#include "icache_model.h"
|
#include "icache_model.h"
|
#include "dcache_model.h"
|
#include "dcache_model.h"
|
|
|
#include "profiler.h"
|
#include "profiler.h"
|
#include "mprofiler.h"
|
#include "mprofiler.h"
|
#include "cuc.h"
|
#include "cuc.h"
|
|
|
#include "debug.h"
|
#include "debug.h"
|
|
|
#define WARNING(s) fprintf (stderr, "WARNING: config.%s: %s\n", cur_section->name, (s))
|
#define WARNING(s) fprintf (stderr, "WARNING: config.%s: %s\n", cur_section->name, (s))
|
#define MERROR(s) {fprintf (stderr, "ERROR: %s\n", s); if (runtime.sim.init) exit (1);}
|
#define MERROR(s) {fprintf (stderr, "ERROR: %s\n", s); if (runtime.sim.init) exit (1);}
|
|
|
#if !FAST_SIM
|
#if !FAST_SIM
|
struct config config;
|
struct config config;
|
#endif
|
#endif
|
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;
|
|
|
void init_defconfig()
|
void init_defconfig()
|
{
|
{
|
int i;
|
int i;
|
|
|
#if !FAST_SIM
|
#if !FAST_SIM
|
memset(&config, 0, sizeof(config));
|
memset(&config, 0, sizeof(config));
|
/* Sim */
|
/* Sim */
|
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.spr_log = 0;
|
config.sim.spr_log = 0;
|
strcpy (config.sim.exe_log_fn, "executed.log");
|
strcpy (config.sim.exe_log_fn, "executed.log");
|
strcpy (config.sim.spr_log_fn, "spr.log");
|
strcpy (config.sim.spr_log_fn, "spr.log");
|
config.sim.profile = 0;
|
config.sim.profile = 0;
|
config.sim.mprofile = 0;
|
config.sim.mprofile = 0;
|
|
|
config.sim.debug = 0;
|
config.sim.debug = 0;
|
config.sim.verbose = 1;
|
config.sim.verbose = 1;
|
|
|
strcpy (config.sim.prof_fn, "sim.profile");
|
strcpy (config.sim.prof_fn, "sim.profile");
|
strcpy (config.sim.mprof_fn, "sim.mprofile");
|
strcpy (config.sim.mprof_fn, "sim.mprofile");
|
strcpy (config.sim.fstdout, "stdout.txt");
|
strcpy (config.sim.fstdout, "stdout.txt");
|
strcpy (runtime.sim.script_fn, "(default)");
|
strcpy (runtime.sim.script_fn, "(default)");
|
config.sim.clkcycle_ps = 4000; /* 4000 for 4ns (250MHz) */
|
config.sim.clkcycle_ps = 4000; /* 4000 for 4ns (250MHz) */
|
if (config.sim.clkcycle_ps) config.sim.system_kfreq = (long)((1000000000.0 / (double)config.sim.clkcycle_ps));
|
if (config.sim.clkcycle_ps) config.sim.system_kfreq = (long)((1000000000.0 / (double)config.sim.clkcycle_ps));
|
else config.sim.system_kfreq = INT_MAX;
|
else config.sim.system_kfreq = INT_MAX;
|
if (config.sim.system_kfreq <= 0) config.sim.system_kfreq = 1;
|
if (config.sim.system_kfreq <= 0) config.sim.system_kfreq = 1;
|
|
|
/* Memory */
|
/* Memory */
|
config.memory.type = MT_UNKNOWN;
|
config.memory.type = MT_UNKNOWN;
|
config.memory.pattern = 0;
|
config.memory.pattern = 0;
|
config.memory.random_seed = -1; /* Generate new seed */
|
config.memory.random_seed = -1; /* Generate new seed */
|
for (i = 0; i < MAX_MEMORIES; i++)
|
for (i = 0; i < MAX_MEMORIES; i++)
|
config.memory.table[i].ce = -1; /* memory is disabled by default */
|
config.memory.table[i].ce = -1; /* memory is disabled by default */
|
|
|
/* IMMU & DMMU*/
|
/* IMMU & DMMU*/
|
config.immu.enabled = 0;
|
config.immu.enabled = 0;
|
config.immu.hitdelay = 1;
|
config.immu.hitdelay = 1;
|
config.immu.missdelay = 1;
|
config.immu.missdelay = 1;
|
config.dmmu.enabled = 0;
|
config.dmmu.enabled = 0;
|
config.dmmu.hitdelay = 1;
|
config.dmmu.hitdelay = 1;
|
config.dmmu.missdelay = 1;
|
config.dmmu.missdelay = 1;
|
|
|
/* IC & DC */
|
/* IC & DC */
|
config.ic.enabled = 0;
|
config.ic.enabled = 0;
|
config.ic.hitdelay = 1;
|
config.ic.hitdelay = 1;
|
config.ic.missdelay = 1;
|
config.ic.missdelay = 1;
|
config.ic.nways = 0;
|
config.ic.nways = 0;
|
config.ic.nsets = 0;
|
config.ic.nsets = 0;
|
config.ic.ustates = 0;
|
config.ic.ustates = 0;
|
config.dc.enabled = 0;
|
config.dc.enabled = 0;
|
config.dc.load_hitdelay = 2;
|
config.dc.load_hitdelay = 2;
|
config.dc.load_missdelay = 2;
|
config.dc.load_missdelay = 2;
|
config.dc.nways = 0;
|
config.dc.nways = 0;
|
config.dc.nsets = 0;
|
config.dc.nsets = 0;
|
config.dc.ustates = 0;
|
config.dc.ustates = 0;
|
config.dc.store_hitdelay = 0;
|
config.dc.store_hitdelay = 0;
|
config.dc.store_missdelay = 0;
|
config.dc.store_missdelay = 0;
|
|
|
/* Memory Controller */
|
/* Memory Controller */
|
config.mc.enabled = 0;
|
config.mc.enabled = 0;
|
|
|
/* CPU */
|
/* CPU */
|
config.cpu.superscalar = 0;
|
config.cpu.superscalar = 0;
|
config.sim.history = 0;
|
config.sim.history = 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.upr = SPR_UPR_UP | SPR_UPR_DCP | SPR_UPR_ICP | SPR_UPR_DMP
|
config.cpu.upr = SPR_UPR_UP | SPR_UPR_DCP | SPR_UPR_ICP | SPR_UPR_DMP
|
| SPR_UPR_IMP | SPR_UPR_OB32P | SPR_UPR_DUP | SPR_UPR_PICP
|
| SPR_UPR_IMP | SPR_UPR_OB32P | SPR_UPR_DUP | SPR_UPR_PICP
|
| SPR_UPR_PMP | SPR_UPR_TTP;
|
| SPR_UPR_PMP | SPR_UPR_TTP;
|
config.cpu.sr = 0x00008001;
|
config.cpu.sr = 0x00008001;
|
|
|
/* Debug */
|
/* Debug */
|
config.debug.enabled = 0;
|
config.debug.enabled = 0;
|
config.debug.gdb_enabled = 0;
|
config.debug.gdb_enabled = 0;
|
config.debug.server_port = 0;
|
config.debug.server_port = 0;
|
|
|
/* VAPI */
|
/* VAPI */
|
config.vapi.enabled = 0;
|
config.vapi.enabled = 0;
|
strcpy (config.vapi.vapi_fn, "vapi.log");
|
strcpy (config.vapi.vapi_fn, "vapi.log");
|
|
|
/* Ethernet */
|
|
config.nethernets = 0;
|
|
|
|
/* GPIO */
|
/* GPIO */
|
config.ngpios = 0;
|
config.ngpios = 0;
|
|
|
/* PM */
|
/* PM */
|
config.pm.enabled = 0;
|
config.pm.enabled = 0;
|
|
|
/* CUC */
|
/* CUC */
|
strcpy (config.cuc.timings_fn, "virtex.tim");
|
strcpy (config.cuc.timings_fn, "virtex.tim");
|
config.cuc.memory_order = MO_STRONG;
|
config.cuc.memory_order = MO_STRONG;
|
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;
|
|
|
#endif
|
#endif
|
|
|
/* 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.fspr_log = NULL;
|
runtime.sim.fspr_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.init = 1;
|
runtime.sim.init = 1;
|
runtime.sim.fout = stdout;
|
runtime.sim.fout = stdout;
|
runtime.sim.script_file_specified = 0;
|
runtime.sim.script_file_specified = 0;
|
runtime.simcmd.profile = 0;
|
runtime.simcmd.profile = 0;
|
runtime.simcmd.mprofile = 0;
|
runtime.simcmd.mprofile = 0;
|
|
|
/* VAPI */
|
/* VAPI */
|
runtime.vapi.vapi_file = NULL;
|
runtime.vapi.vapi_file = NULL;
|
runtime.vapi.enabled = 0;
|
runtime.vapi.enabled = 0;
|
}
|
}
|
|
|
int parse_args(int argc, char *argv[])
|
int parse_args(int argc, char *argv[])
|
{
|
{
|
argv++; argc--;
|
argv++; argc--;
|
while (argc) {
|
while (argc) {
|
if (strcmp(*argv, "profiler") == 0) {
|
if (strcmp(*argv, "profiler") == 0) {
|
exit (main_profiler (argc, argv));
|
exit (main_profiler (argc, argv));
|
} else
|
} else
|
if (strcmp(*argv, "mprofiler") == 0) {
|
if (strcmp(*argv, "mprofiler") == 0) {
|
exit (main_mprofiler (argc, argv));
|
exit (main_mprofiler (argc, argv));
|
} else
|
} else
|
if (*argv[0] != '-') {
|
if (*argv[0] != '-') {
|
runtime.sim.filename = argv[0];
|
runtime.sim.filename = argv[0];
|
argc--;
|
argc--;
|
argv++;
|
argv++;
|
} else
|
} else
|
#if !FAST_SIM /* Constant cfg */
|
#if !FAST_SIM /* Constant cfg */
|
if (strcmp(*argv, "-f") == 0 || strcmp(*argv, "--file") == 0) {
|
if (strcmp(*argv, "-f") == 0 || strcmp(*argv, "--file") == 0) {
|
argv++; argc--;
|
argv++; argc--;
|
if (argv[0]) {
|
if (argv[0]) {
|
read_script_file(argv[0]);
|
read_script_file(argv[0]);
|
argv++; argc--;
|
argv++; argc--;
|
} else {
|
} else {
|
fprintf(stderr, "Configure filename not specified!\n");
|
fprintf(stderr, "Configure filename not specified!\n");
|
return 1;
|
return 1;
|
}
|
}
|
} else
|
} else
|
#endif
|
#endif
|
if (strcmp(*argv, "--nosrv") == 0) { /* (CZ) */
|
if (strcmp(*argv, "--nosrv") == 0) { /* (CZ) */
|
config.debug.gdb_enabled = 0;
|
config.debug.gdb_enabled = 0;
|
argv++; argc--;
|
argv++; argc--;
|
} else
|
} else
|
if (strcmp(*argv, "--srv") == 0) { /* (CZ) */
|
if (strcmp(*argv, "--srv") == 0) { /* (CZ) */
|
char *s;
|
char *s;
|
if(!--argc)
|
if(!--argc)
|
return 1;
|
return 1;
|
config.debug.enabled = 1;
|
config.debug.enabled = 1;
|
config.debug.gdb_enabled = 1;
|
config.debug.gdb_enabled = 1;
|
config.debug.server_port = strtol(*(++argv),&s,10);
|
config.debug.server_port = strtol(*(++argv),&s,10);
|
if(*s)
|
if(*s)
|
return 1;
|
return 1;
|
argv++; argc--;
|
argv++; argc--;
|
} else
|
} else
|
if (strcmp(*argv, "-i") == 0) {
|
if (strcmp(*argv, "-i") == 0) {
|
runtime.sim.iprompt = 1;
|
runtime.sim.iprompt = 1;
|
argv++; argc--;
|
argv++; argc--;
|
} else
|
} else
|
if (strcmp(*argv, "-v") == 0) {
|
if (strcmp(*argv, "-v") == 0) {
|
version();
|
version();
|
exit(0);
|
exit(0);
|
} else
|
} else
|
#if !FAST_SIM
|
#if !FAST_SIM
|
if (strcmp(*argv, "--enable-profile") == 0) {
|
if (strcmp(*argv, "--enable-profile") == 0) {
|
runtime.simcmd.profile = 1;
|
runtime.simcmd.profile = 1;
|
argv++; argc--;
|
argv++; argc--;
|
} else
|
} else
|
if (strcmp(*argv, "--enable-mprofile") == 0) {
|
if (strcmp(*argv, "--enable-mprofile") == 0) {
|
runtime.simcmd.mprofile = 1;
|
runtime.simcmd.mprofile = 1;
|
argv++; argc--;
|
argv++; argc--;
|
} else
|
} else
|
#endif
|
#endif
|
if (strcmp(*argv, "--output-cfg") == 0) {
|
if (strcmp(*argv, "--output-cfg") == 0) {
|
runtime.sim.output_cfg = 1;
|
runtime.sim.output_cfg = 1;
|
argv++; argc--;
|
argv++; argc--;
|
} else {
|
} else {
|
fprintf(stderr, "Unknown option: %s\n", *argv);
|
fprintf(stderr, "Unknown option: %s\n", *argv);
|
return 1;
|
return 1;
|
}
|
}
|
}
|
}
|
|
|
if (!argc)
|
if (!argc)
|
return 0;
|
return 0;
|
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
void print_config()
|
void 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 (testsprbits(SPR_UPR, SPR_UPR_DCP))
|
if (testsprbits(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 (testsprbits(SPR_UPR, SPR_UPR_ICP))
|
if (testsprbits(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");
|
}
|
}
|
}
|
}
|
|
|
#if !FAST_SIM
|
#if !FAST_SIM
|
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;
|
};
|
};
|
|
|
/* FIXME: These will be removed */
|
/* FIXME: These will be removed */
|
int current_device = -1;
|
int current_device = -1;
|
void change_device (union param_val val, void *dat) {
|
void change_device (union param_val val, void *dat) {
|
current_device = val.int_val;
|
current_device = val.int_val;
|
}
|
}
|
|
|
void end_device (union param_val val, void *dat) {
|
void end_device (union param_val val, void *dat) {
|
current_device = -1;
|
current_device = -1;
|
}
|
}
|
|
|
void base_include (union param_val val, void *dat) {
|
void 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 sim_debug (union param_val val, void *dat) {
|
void sim_debug (union param_val val, void *dat) {
|
config.sim.debug = val.int_val;
|
config.sim.debug = val.int_val;
|
}
|
}
|
|
|
void sim_verbose (union param_val val, void *dat) {
|
void sim_verbose (union param_val val, void *dat) {
|
config.sim.verbose = val.int_val;
|
config.sim.verbose = val.int_val;
|
}
|
}
|
|
|
void sim_profile (union param_val val, void *dat) {
|
void sim_profile (union param_val val, void *dat) {
|
config.sim.profile = val.int_val;
|
config.sim.profile = val.int_val;
|
}
|
}
|
|
|
void sim_prof_fn (union param_val val, void *dat) {
|
void sim_prof_fn (union param_val val, void *dat) {
|
strcpy(config.sim.prof_fn, val.str_val);
|
strcpy(config.sim.prof_fn, val.str_val);
|
}
|
}
|
|
|
void sim_mprofile (union param_val val, void *dat) {
|
void sim_mprofile (union param_val val, void *dat) {
|
config.sim.mprofile = val.int_val;
|
config.sim.mprofile = val.int_val;
|
}
|
}
|
|
|
void sim_mprof_fn (union param_val val, void *dat) {
|
void sim_mprof_fn (union param_val val, void *dat) {
|
strcpy(config.sim.mprof_fn, val.str_val);
|
strcpy(config.sim.mprof_fn, val.str_val);
|
}
|
}
|
|
|
void sim_history (union param_val val, void *dat) {
|
void sim_history (union param_val val, void *dat) {
|
config.sim.history = val.int_val;
|
config.sim.history = val.int_val;
|
}
|
}
|
|
|
void sim_exe_log (union param_val val, void *dat) {
|
void sim_exe_log (union param_val val, void *dat) {
|
config.sim.exe_log = val.int_val;
|
config.sim.exe_log = val.int_val;
|
}
|
}
|
|
|
void sim_exe_log_type (union param_val val, void *dat) {
|
void sim_exe_log_type (union param_val val, void *dat) {
|
if (strcmp (val.str_val, "default") == 0)
|
if (strcmp (val.str_val, "default") == 0)
|
config.sim.exe_log_type = EXE_LOG_HARDWARE;
|
config.sim.exe_log_type = EXE_LOG_HARDWARE;
|
else if (strcmp (val.str_val, "hardware") == 0)
|
else if (strcmp (val.str_val, "hardware") == 0)
|
config.sim.exe_log_type = EXE_LOG_HARDWARE;
|
config.sim.exe_log_type = EXE_LOG_HARDWARE;
|
else if (strcmp (val.str_val, "simple") == 0)
|
else if (strcmp (val.str_val, "simple") == 0)
|
config.sim.exe_log_type = EXE_LOG_SIMPLE;
|
config.sim.exe_log_type = EXE_LOG_SIMPLE;
|
else if (strcmp (val.str_val, "software") == 0) {
|
else if (strcmp (val.str_val, "software") == 0) {
|
config.sim.exe_log_type = EXE_LOG_SOFTWARE;
|
config.sim.exe_log_type = EXE_LOG_SOFTWARE;
|
} else {
|
} else {
|
char tmp[200];
|
char tmp[200];
|
sprintf (tmp, "invalid execute log type '%s'.\n", val.str_val);
|
sprintf (tmp, "invalid execute log type '%s'.\n", val.str_val);
|
CONFIG_ERROR(tmp);
|
CONFIG_ERROR(tmp);
|
}
|
}
|
}
|
}
|
|
|
void sim_exe_log_start (union param_val val, void *dat) {
|
void sim_exe_log_start (union param_val val, void *dat) {
|
config.sim.exe_log_start = val.int_val;
|
config.sim.exe_log_start = val.int_val;
|
}
|
}
|
|
|
void sim_exe_log_end (union param_val val, void *dat) {
|
void sim_exe_log_end (union param_val val, void *dat) {
|
config.sim.exe_log_end = val.int_val;
|
config.sim.exe_log_end = val.int_val;
|
}
|
}
|
|
|
void sim_exe_log_marker (union param_val val, void *dat) {
|
void 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 sim_exe_log_fn (union param_val val, void *dat) {
|
void sim_exe_log_fn (union param_val val, void *dat) {
|
strcpy(config.sim.exe_log_fn, val.str_val);
|
strcpy(config.sim.exe_log_fn, val.str_val);
|
}
|
}
|
|
|
void sim_clkcycle (union param_val val, void *dat) {
|
void sim_clkcycle (union param_val val, 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) goto err;
|
if (len < 2) goto err;
|
if (val.str_val[pos--] != 's') goto err;
|
if (val.str_val[pos--] != 's') goto err;
|
switch (val.str_val[pos--]) {
|
switch (val.str_val[pos--]) {
|
case 'p': time = 1; break;
|
case 'p': time = 1; break;
|
case 'n': time = 1000; break;
|
case 'n': time = 1000; break;
|
case 'u': time = 1000000; break;
|
case 'u': time = 1000000; break;
|
case 'm': time = 1000000000; break;
|
case 'm': time = 1000000000; break;
|
default:
|
default:
|
goto err;
|
goto err;
|
}
|
}
|
val.str_val[pos + 1] = 0;
|
val.str_val[pos + 1] = 0;
|
config.sim.clkcycle_ps = time * atol (val.str_val);
|
config.sim.clkcycle_ps = time * atol (val.str_val);
|
return;
|
return;
|
err:
|
err:
|
CONFIG_ERROR("invalid time format.");
|
CONFIG_ERROR("invalid time format.");
|
}
|
}
|
|
|
void sim_stdout (union param_val val, void *dat) {
|
void sim_stdout (union param_val val, void *dat) {
|
strcpy(config.sim.fstdout, val.str_val);
|
strcpy(config.sim.fstdout, val.str_val);
|
}
|
}
|
|
|
void sim_spr_log (union param_val val, void *dat) {
|
void sim_spr_log (union param_val val, void *dat) {
|
config.sim.spr_log = val.int_val;
|
config.sim.spr_log = val.int_val;
|
}
|
}
|
|
|
void sim_spr_log_fn (union param_val val, void *dat) {
|
void sim_spr_log_fn (union param_val val, void *dat) {
|
strcpy(config.sim.spr_log_fn, val.str_val);
|
strcpy(config.sim.spr_log_fn, val.str_val);
|
}
|
}
|
|
|
void reg_sim_sec (void) {
|
void reg_sim_sec (void) {
|
struct config_section *sec = reg_config_sec("sim", NULL, NULL);
|
struct config_section *sec = reg_config_sec("sim", NULL, NULL);
|
|
|
reg_config_param(sec, "debug", paramt_int, sim_debug);
|
reg_config_param(sec, "debug", paramt_int, sim_debug);
|
reg_config_param(sec, "verbose", paramt_int, sim_verbose);
|
reg_config_param(sec, "verbose", paramt_int, sim_verbose);
|
reg_config_param(sec, "profile", paramt_int, sim_profile);
|
reg_config_param(sec, "profile", paramt_int, sim_profile);
|
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_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_int, sim_exe_log_start);
|
reg_config_param(sec, "exe_log_start", paramt_int, sim_exe_log_start);
|
reg_config_param(sec, "exe_log_end", paramt_int, sim_exe_log_end);
|
reg_config_param(sec, "exe_log_end", paramt_int, 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_fn", paramt_str, sim_exe_log_fn);
|
reg_config_param(sec, "exe_log_fn", paramt_str, sim_exe_log_fn);
|
reg_config_param(sec, "spr_log", paramt_int, sim_spr_log);
|
reg_config_param(sec, "spr_log", paramt_int, sim_spr_log);
|
reg_config_param(sec, "spr_log_fn", paramt_str, sim_spr_log_fn);
|
reg_config_param(sec, "spr_log_fn", paramt_str, sim_spr_log_fn);
|
reg_config_param(sec, "clkcycle", paramt_word, sim_clkcycle);
|
reg_config_param(sec, "clkcycle", paramt_word, sim_clkcycle);
|
reg_config_param(sec, "stdout", paramt_str, sim_stdout);
|
reg_config_param(sec, "stdout", paramt_str, sim_stdout);
|
}
|
}
|
|
|
/*-------------------------------------------------[ Memory configuration ]---*/
|
/*-------------------------------------------------[ Memory configuration ]---*/
|
void memory_random_seed(union param_val val, void *dat) {
|
void memory_random_seed(union param_val val, void *dat) {
|
config.memory.random_seed = val.int_val;
|
config.memory.random_seed = val.int_val;
|
}
|
}
|
|
|
void memory_pattern(union param_val val, void *dat) {
|
void memory_pattern(union param_val val, void *dat) {
|
config.memory.pattern = val.int_val;
|
config.memory.pattern = val.int_val;
|
}
|
}
|
|
|
void memory_nmemories (union param_val val, void *dat) {
|
void memory_nmemories (union param_val val, void *dat) {
|
if (val.int_val >= 0 && val.int_val < MAX_MEMORIES)
|
if (val.int_val >= 0 && val.int_val < MAX_MEMORIES)
|
config.memory.nmemories = val.int_val;
|
config.memory.nmemories = val.int_val;
|
else
|
else
|
CONFIG_ERROR("invalid number of devices.");
|
CONFIG_ERROR("invalid number of devices.");
|
}
|
}
|
|
|
void memory_type (union param_val val, void *dat) {
|
void memory_type (union param_val val, void *dat) {
|
if (strcmp (val.str_val, "unknown") == 0)
|
if (strcmp (val.str_val, "unknown") == 0)
|
config.memory.type = MT_UNKNOWN;
|
config.memory.type = MT_UNKNOWN;
|
else if (strcmp (val.str_val, "random") == 0)
|
else if (strcmp (val.str_val, "random") == 0)
|
config.memory.type = MT_RANDOM;
|
config.memory.type = MT_RANDOM;
|
else if (strcmp (val.str_val, "pattern") == 0)
|
else if (strcmp (val.str_val, "pattern") == 0)
|
config.memory.type = MT_PATTERN;
|
config.memory.type = MT_PATTERN;
|
else if (strcmp (val.str_val, "zero") == 0) {
|
else if (strcmp (val.str_val, "zero") == 0) {
|
config.memory.type = MT_PATTERN;
|
config.memory.type = MT_PATTERN;
|
config.memory.pattern = 0;
|
config.memory.pattern = 0;
|
} else {
|
} else {
|
char tmp[200];
|
char tmp[200];
|
sprintf (tmp, "invalid memory type '%s'.\n", val.str_val);
|
sprintf (tmp, "invalid memory type '%s'.\n", val.str_val);
|
CONFIG_ERROR(tmp);
|
CONFIG_ERROR(tmp);
|
}
|
}
|
}
|
}
|
|
|
void memory_ce (union param_val val, void *dat) {
|
void memory_ce (union param_val val, void *dat) {
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
config.memory.table[current_device].ce = val.int_val;
|
config.memory.table[current_device].ce = val.int_val;
|
else
|
else
|
CONFIG_ERROR("invalid device number.");
|
CONFIG_ERROR("invalid device number.");
|
}
|
}
|
|
|
void memory_baseaddr (union param_val val, void *dat) {
|
void memory_baseaddr (union param_val val, void *dat) {
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
config.memory.table[current_device].baseaddr = val.addr_val;
|
config.memory.table[current_device].baseaddr = val.addr_val;
|
else
|
else
|
CONFIG_ERROR("invalid device number.");
|
CONFIG_ERROR("invalid device number.");
|
}
|
}
|
|
|
void memory_size (union param_val val, void *dat) {
|
void memory_size (union param_val val, void *dat) {
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
config.memory.table[current_device].size = val.int_val;
|
config.memory.table[current_device].size = val.int_val;
|
else
|
else
|
CONFIG_ERROR("invalid device number.");
|
CONFIG_ERROR("invalid device number.");
|
}
|
}
|
|
|
void memory_name (union param_val val, void *dat) {
|
void memory_name (union param_val val, void *dat) {
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
strcpy (config.memory.table[current_device].name, val.str_val);
|
strcpy (config.memory.table[current_device].name, val.str_val);
|
else
|
else
|
CONFIG_ERROR("invalid device number.");
|
CONFIG_ERROR("invalid device number.");
|
}
|
}
|
|
|
void memory_log (union param_val val, void *dat) {
|
void memory_log (union param_val val, void *dat) {
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
strcpy (config.memory.table[current_device].log, val.str_val);
|
strcpy (config.memory.table[current_device].log, val.str_val);
|
else
|
else
|
CONFIG_ERROR("invalid device number.");
|
CONFIG_ERROR("invalid device number.");
|
}
|
}
|
|
|
void memory_delayr (union param_val val, void *dat) {
|
void memory_delayr (union param_val val, void *dat) {
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
config.memory.table[current_device].delayr = val.int_val;
|
config.memory.table[current_device].delayr = val.int_val;
|
else
|
else
|
CONFIG_ERROR("invalid device number.");
|
CONFIG_ERROR("invalid device number.");
|
}
|
}
|
|
|
void memory_delayw (union param_val val, void *dat) {
|
void memory_delayw (union param_val val, void *dat) {
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
if (current_device >= 0 && current_device < config.memory.nmemories)
|
config.memory.table[current_device].delayw = val.int_val;
|
config.memory.table[current_device].delayw = val.int_val;
|
else
|
else
|
CONFIG_ERROR("invalid device number.");
|
CONFIG_ERROR("invalid device number.");
|
}
|
}
|
|
|
void reg_memory_sec(void) {
|
void reg_memory_sec(void) {
|
struct config_section *sec = reg_config_sec("memory", NULL, NULL);
|
struct config_section *sec = reg_config_sec("memory", NULL, NULL);
|
|
|
reg_config_param(sec, "random_seed", paramt_int, memory_random_seed);
|
reg_config_param(sec, "random_seed", paramt_int, memory_random_seed);
|
reg_config_param(sec, "pattern", paramt_int, memory_pattern);
|
reg_config_param(sec, "pattern", paramt_int, memory_pattern);
|
reg_config_param(sec, "type", paramt_word, memory_type);
|
reg_config_param(sec, "type", paramt_word, memory_type);
|
reg_config_param(sec, "nmemories", paramt_int, memory_nmemories);
|
reg_config_param(sec, "nmemories", paramt_int, memory_nmemories);
|
reg_config_param(sec, "device", paramt_int, change_device);
|
reg_config_param(sec, "device", paramt_int, change_device);
|
reg_config_param(sec, "enddevice", paramt_none, end_device);
|
reg_config_param(sec, "enddevice", paramt_none, end_device);
|
reg_config_param(sec, "ce", paramt_int, memory_ce);
|
reg_config_param(sec, "ce", paramt_int, memory_ce);
|
reg_config_param(sec, "baseaddr", paramt_addr, memory_baseaddr);
|
reg_config_param(sec, "baseaddr", paramt_addr, memory_baseaddr);
|
reg_config_param(sec, "size", paramt_int, memory_size);
|
reg_config_param(sec, "size", paramt_int, memory_size);
|
reg_config_param(sec, "name", paramt_str, memory_name);
|
reg_config_param(sec, "name", paramt_str, memory_name);
|
reg_config_param(sec, "log", paramt_str, memory_log);
|
reg_config_param(sec, "log", paramt_str, memory_log);
|
reg_config_param(sec, "delayr", paramt_int, memory_delayr);
|
reg_config_param(sec, "delayr", paramt_int, memory_delayr);
|
reg_config_param(sec, "delayw", paramt_int, memory_delayw);
|
reg_config_param(sec, "delayw", paramt_int, memory_delayw);
|
}
|
}
|
|
|
/*----------------------------------------------------[ CPU configuration ]---*/
|
/*----------------------------------------------------[ CPU configuration ]---*/
|
void cpu_ver (union param_val val, void *dat) {
|
void cpu_ver (union param_val val, void *dat) {
|
config.cpu.ver = val.int_val;
|
config.cpu.ver = val.int_val;
|
}
|
}
|
|
|
void cpu_rev (union param_val val, void *dat) {
|
void cpu_rev (union param_val val, void *dat) {
|
config.cpu.rev = val.int_val;
|
config.cpu.rev = val.int_val;
|
}
|
}
|
|
|
void cpu_upr (union param_val val, void *dat) {
|
void cpu_upr (union param_val val, void *dat) {
|
config.cpu.upr = val.int_val;
|
config.cpu.upr = val.int_val;
|
}
|
}
|
|
|
void cpu_sr (union param_val val, void *dat) {
|
void cpu_sr (union param_val val, void *dat) {
|
config.cpu.sr = val.int_val;
|
config.cpu.sr = val.int_val;
|
}
|
}
|
|
|
void cpu_hazards (union param_val val, void *dat) {
|
void cpu_hazards (union param_val val, void *dat) {
|
config.cpu.hazards = val.int_val;
|
config.cpu.hazards = val.int_val;
|
}
|
}
|
|
|
void cpu_superscalar (union param_val val, void *dat) {
|
void cpu_superscalar (union param_val val, void *dat) {
|
config.cpu.superscalar = val.int_val;
|
config.cpu.superscalar = val.int_val;
|
}
|
}
|
|
|
void cpu_dependstats (union param_val val, void *dat) {
|
void cpu_dependstats (union param_val val, void *dat) {
|
config.cpu.dependstats = val.int_val;
|
config.cpu.dependstats = val.int_val;
|
}
|
}
|
|
|
void cpu_sbuf_len (union param_val val, void *dat) {
|
void cpu_sbuf_len (union param_val val, void *dat) {
|
if (val.int_val >= MAX_SBUF_LEN) {
|
if (val.int_val >= MAX_SBUF_LEN) {
|
config.cpu.sbuf_len = MAX_SBUF_LEN - 1;
|
config.cpu.sbuf_len = MAX_SBUF_LEN - 1;
|
WARNING("sbuf_len too large; truncated.");
|
WARNING("sbuf_len too large; truncated.");
|
} else if (val.int_val < 0) {
|
} else if (val.int_val < 0) {
|
config.cpu.sbuf_len = 0;
|
config.cpu.sbuf_len = 0;
|
WARNING("sbuf_len negative; disabled.");
|
WARNING("sbuf_len negative; disabled.");
|
} else
|
} else
|
config.cpu.sbuf_len = val.int_val;
|
config.cpu.sbuf_len = val.int_val;
|
}
|
}
|
|
|
void reg_cpu_sec(void)
|
void reg_cpu_sec(void)
|
{
|
{
|
struct config_section *sec = reg_config_sec("cpu", NULL, NULL);
|
struct config_section *sec = reg_config_sec("cpu", NULL, NULL);
|
|
|
reg_config_param(sec, "ver", paramt_int, cpu_ver);
|
reg_config_param(sec, "ver", paramt_int, cpu_ver);
|
reg_config_param(sec, "rev", paramt_int, cpu_rev);
|
reg_config_param(sec, "rev", paramt_int, cpu_rev);
|
reg_config_param(sec, "upr", paramt_int, cpu_upr);
|
reg_config_param(sec, "upr", paramt_int, cpu_upr);
|
reg_config_param(sec, "sr", paramt_int, cpu_sr);
|
reg_config_param(sec, "sr", paramt_int, cpu_sr);
|
reg_config_param(sec, "hazards", paramt_int, cpu_hazards);
|
reg_config_param(sec, "hazards", paramt_int, cpu_hazards);
|
reg_config_param(sec, "superscalar", paramt_int, cpu_superscalar);
|
reg_config_param(sec, "superscalar", paramt_int, cpu_superscalar);
|
reg_config_param(sec, "dependstats", paramt_int, cpu_dependstats);
|
reg_config_param(sec, "dependstats", paramt_int, cpu_dependstats);
|
reg_config_param(sec, "sbuf_len", paramt_int, cpu_sbuf_len);
|
reg_config_param(sec, "sbuf_len", paramt_int, cpu_sbuf_len);
|
}
|
}
|
|
|
int is_power2 (int x) {
|
int is_power2 (int x) {
|
while (!(x & 1))
|
while (!(x & 1))
|
x >>= 1;
|
x >>= 1;
|
return x == 1;
|
return x == 1;
|
}
|
}
|
|
|
void reg_config_secs(void)
|
void reg_config_secs(void)
|
{
|
{
|
reg_config_param(reg_config_sec("base", NULL, NULL), "include", paramt_str,
|
reg_config_param(reg_config_sec("base", NULL, NULL), "include", paramt_str,
|
base_include);
|
base_include);
|
|
|
reg_sim_sec();
|
reg_sim_sec();
|
reg_cpu_sec();
|
reg_cpu_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();
|
reg_test_sec();
|
reg_test_sec();
|
}
|
}
|
|
|
void reg_config_param(struct config_section *sec, const char *param,
|
void 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 *reg_config_sec(const char *section,
|
struct config_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, "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 switch_param(char *param, struct config_param *cur_param)
|
static void 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)) param++;
|
while(*param && isspace(*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);
|
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 != '"') {
|
CONFIG_ERROR("String value expected\n");
|
CONFIG_ERROR("String value expected\n");
|
return;
|
return;
|
}
|
}
|
|
|
param++;
|
param++;
|
end_p = param;
|
end_p = param;
|
while(*end_p && (*end_p != '"')) end_p++;
|
while(*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)) end_p++;
|
while(*end_p && !isspace(*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
|
|
|
*/
|
*/
|
|
|
void read_script_file (char *filename)
|
void read_script_file (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")) != NULL
|
if ((f = fopen (filename, "rt")) != NULL
|
|| home != NULL && !(local = 0) && (f = fopen (ctmp, "rt")) != NULL) {
|
|| home != NULL && !(local = 0) && (f = fopen (ctmp, "rt")) != NULL) {
|
if (config.sim.verbose && !runtime.sim.output_cfg)
|
if (config.sim.verbose && !runtime.sim.output_cfg)
|
PRINTF ("Reading script file from '%s'...\n", local ? filename : ctmp);
|
PRINTF ("Reading script file from '%s'...\n", local ? filename : ctmp);
|
strcpy (runtime.sim.script_fn, local ? filename : ctmp);
|
strcpy (runtime.sim.script_fn, local ? filename : ctmp);
|
|
|
while (!feof(f)) {
|
while (!feof(f)) {
|
char param[STR_SIZE];
|
char param[STR_SIZE];
|
if (fscanf(f, "%s ", param) != 1) break;
|
if (fscanf(f, "%s ", param) != 1) 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", local ? filename : ctmp);
|
fprintf (stderr, "%s: ERROR: Section name required.\n", 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, "WARNING: config: Unknown section: %s; ignoring.", param);
|
fprintf (stderr, "WARNING: config: Unknown section: %s; ignoring.", param);
|
/* just skip section */
|
/* just skip section */
|
while (fscanf (f, "%s\n", param) != 1 && strcmp (param, "end"));
|
while (fscanf (f, "%s\n", param) != 1 && 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", local ? filename : ctmp);
|
fprintf (stderr, "%s: ERROR: Comment reached EOF.\n", local ? filename : ctmp);
|
exit (1);
|
exit (1);
|
}
|
}
|
}
|
}
|
} else {
|
} else {
|
struct config_param *cur_param;
|
struct config_param *cur_param;
|
char *cur_p;
|
char *cur_p;
|
for (cur_param = cur_section->params; cur_param; cur_param = cur_param->next)
|
for (cur_param = cur_section->params; cur_param; 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) {
|
char tmp[200];
|
char tmp[200];
|
sprintf (tmp, "Invalid parameter: %s; ignoring.\n", param);
|
sprintf (tmp, "Invalid parameter: %s; ignoring.\n", param);
|
WARNING(tmp);
|
WARNING(tmp);
|
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)) cur_p++;
|
while(*cur_p && isspace(*cur_p)) cur_p++;
|
|
|
switch_param(cur_p, cur_param);
|
switch_param(cur_p, cur_param);
|
}
|
}
|
}
|
}
|
fclose (f);
|
fclose (f);
|
runtime.sim.script_file_specified = 1;
|
runtime.sim.script_file_specified = 1;
|
} else
|
} else
|
if (config.sim.verbose)
|
if (config.sim.verbose)
|
fprintf (stderr, "WARNING: Cannot read script file from '%s',\nneither '%s'.\n", filename, ctmp);
|
fprintf (stderr, "WARNING: Cannot read script file from '%s',\nneither '%s'.\n", filename, ctmp);
|
}
|
}
|
|
|
/* Utility for execution of set sim command. */
|
/* Utility for execution of set sim command. */
|
static int set_config (int argc, char **argv)
|
static int 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) return 1;
|
if (argc < 2) 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) return 1;
|
if (!cur_section) return 1;
|
|
|
if (argc < 3) return 2;
|
if (argc < 3) 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) return 2;
|
if (!cur_param) return 2;
|
|
|
/* Parse parameter value */
|
/* Parse parameter value */
|
if (cur_param->type) {
|
if (cur_param->type) {
|
if (argc < 4) return 3;
|
if (argc < 4) 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 set_config_command(int argc, char **argv)
|
void 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 ("Invalid or missing section name. One of valid sections must be specified:\n");
|
PRINTF ("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 ("Invalid or missing item name. One of valid items must be specified:\n");
|
PRINTF ("Invalid or missing item name. One of valid items must be specified:\n");
|
for (cur_param = cur_section->params; cur_param; cur_param = cur_param->next)
|
for (cur_param = cur_section->params; cur_param; 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;
|
}
|
}
|
}
|
}
|
#endif /* !FAST_SIM */
|
#endif /* !FAST_SIM */
|
|
|
/* Outputs C structure of current config to file */
|
/* Outputs C structure of current config to file */
|
void output_cfg (FILE *f)
|
void output_cfg (FILE *f)
|
{
|
{
|
int i, comma;
|
int i, comma;
|
fprintf (f, "/* This file was automatically generated by or1ksim,\n"
|
fprintf (f, "/* This file was automatically generated by or1ksim,\n"
|
" using --output-cfg switch (cfg file '%s'). */\n"
|
" using --output-cfg switch (cfg file '%s'). */\n"
|
"const static struct config config = {\n", runtime.sim.script_fn);
|
"const static struct config config = {\n", runtime.sim.script_fn);
|
|
|
fprintf (f, " tick:{enabled:%i},\n", config.tick.enabled);
|
fprintf (f, " tick:{enabled:%i},\n", config.tick.enabled);
|
|
|
fprintf (f, " nethernets:%i, ethernets:{", config.nethernets);
|
|
comma = 0;
|
|
for (i = 0; i < config.nethernets; i++) {
|
|
fprintf (f, "%s\n {baseaddr:0x%08lx, dma:%i, tx_channel:0x%08x, rx_channel:0x%08x, rxfile:\"%s\", txfile:\"%s\", vapi_id:0x%08lx}",
|
|
comma ? "," :"", config.ethernets[i].baseaddr, config.ethernets[i].dma, config.ethernets[i].tx_channel, config.ethernets[i].rx_channel,
|
|
config.ethernets[i].rxfile, config.ethernets[i].txfile, config.ethernets[i].base_vapi_id);
|
|
comma = 1;
|
|
}
|
|
fprintf (f, "},\n");
|
|
|
|
fprintf (f, " ngpios:%i, gpios:{", config.ngpios);
|
fprintf (f, " ngpios:%i, gpios:{", config.ngpios);
|
comma = 0;
|
comma = 0;
|
for (i = 0; i < config.ngpios; i++) {
|
for (i = 0; i < config.ngpios; i++) {
|
fprintf (f, "%s\n {baseaddr:0x%08lx, irq:%i, base_vapi_id:0x%08lx}",
|
fprintf (f, "%s\n {baseaddr:0x%08lx, irq:%i, base_vapi_id:0x%08lx}",
|
comma ? "," :"", config.gpios[i].baseaddr, config.gpios[i].irq, config.gpios[i].base_vapi_id);
|
comma ? "," :"", config.gpios[i].baseaddr, config.gpios[i].irq, config.gpios[i].base_vapi_id);
|
comma = 1;
|
comma = 1;
|
}
|
}
|
fprintf (f, "},\n");
|
fprintf (f, "},\n");
|
|
|
fprintf (f, " mc:{enabled:%i, baseaddr:0x%08lx, POC:%i},\n", config.mc.enabled, config.mc.baseaddr, config.mc.POC);
|
fprintf (f, " mc:{enabled:%i, baseaddr:0x%08lx, POC:%i},\n", config.mc.enabled, config.mc.baseaddr, config.mc.POC);
|
fprintf (f, " memory:{pattern:%i, random_seed:%i, type:%s, nmemories:%i, table:{", config.memory.pattern, config.memory.random_seed,
|
fprintf (f, " memory:{pattern:%i, random_seed:%i, type:%s, nmemories:%i, table:{", config.memory.pattern, config.memory.random_seed,
|
config.memory.type == MT_UNKNOWN ? "MT_UNKNOWN" : config.memory.type == MT_PATTERN ? "MT_PATTERN" : "MT_RANDOM", config.memory.nmemories);
|
config.memory.type == MT_UNKNOWN ? "MT_UNKNOWN" : config.memory.type == MT_PATTERN ? "MT_PATTERN" : "MT_RANDOM", config.memory.nmemories);
|
comma = 0;
|
comma = 0;
|
for (i = 0; i < config.memory.nmemories; i++) {
|
for (i = 0; i < config.memory.nmemories; i++) {
|
fprintf (f, "%s\n {ce:%i, baseaddr:0x%08lx, size:0x%08lx, name:\"%s\", log:\"%s\", delayr:%i, delayw:%i}",
|
fprintf (f, "%s\n {ce:%i, baseaddr:0x%08lx, size:0x%08lx, name:\"%s\", log:\"%s\", delayr:%i, delayw:%i}",
|
comma ? "," :"", config.memory.table[i].ce, config.memory.table[i].baseaddr, config.memory.table[i].size, config.memory.table[i].name,
|
comma ? "," :"", config.memory.table[i].ce, config.memory.table[i].baseaddr, config.memory.table[i].size, config.memory.table[i].name,
|
config.memory.table[i].log, config.memory.table[i].delayr, config.memory.table[i].delayw);
|
config.memory.table[i].log, config.memory.table[i].delayr, config.memory.table[i].delayw);
|
comma = 1;
|
comma = 1;
|
}
|
}
|
fprintf (f, "}},\n");
|
fprintf (f, "}},\n");
|
|
|
fprintf (f, " immu:{enabled:%i, nways:%i, nsets:%i, pagesize:%i, entrysize:%i, ustates:%i, missdelay:%i, hitdelay:%i},\n",
|
fprintf (f, " immu:{enabled:%i, nways:%i, nsets:%i, pagesize:%i, entrysize:%i, ustates:%i, missdelay:%i, hitdelay:%i},\n",
|
config.immu.enabled, config.immu.nways, config.immu.nsets, config.immu.pagesize, config.immu.entrysize, config.immu.ustates,
|
config.immu.enabled, config.immu.nways, config.immu.nsets, config.immu.pagesize, config.immu.entrysize, config.immu.ustates,
|
config.immu.missdelay, config.immu.hitdelay);
|
config.immu.missdelay, config.immu.hitdelay);
|
|
|
fprintf (f, " dmmu:{enabled:%i, nways:%i, nsets:%i, pagesize:%i, entrysize:%i, ustates:%i, missdelay:%i, hitdelay:%i},\n",
|
fprintf (f, " dmmu:{enabled:%i, nways:%i, nsets:%i, pagesize:%i, entrysize:%i, ustates:%i, missdelay:%i, hitdelay:%i},\n",
|
config.dmmu.enabled, config.dmmu.nways, config.dmmu.nsets, config.dmmu.pagesize, config.dmmu.entrysize, config.dmmu.ustates,
|
config.dmmu.enabled, config.dmmu.nways, config.dmmu.nsets, config.dmmu.pagesize, config.dmmu.entrysize, config.dmmu.ustates,
|
config.dmmu.missdelay, config.dmmu.hitdelay);
|
config.dmmu.missdelay, config.dmmu.hitdelay);
|
|
|
fprintf (f, " ic:{enabled:%i, nways:%i, nsets:%i, blocksize:%i, ustates:%i, missdelay:%i, hitdelay:%i},\n",
|
fprintf (f, " ic:{enabled:%i, nways:%i, nsets:%i, blocksize:%i, ustates:%i, missdelay:%i, hitdelay:%i},\n",
|
config.ic.enabled, config.ic.nways, config.ic.nsets, config.ic.blocksize, config.ic.ustates,
|
config.ic.enabled, config.ic.nways, config.ic.nsets, config.ic.blocksize, config.ic.ustates,
|
config.ic.missdelay, config.ic.hitdelay);
|
config.ic.missdelay, config.ic.hitdelay);
|
|
|
fprintf (f, " dc:{enabled:%i, nways:%i, nsets:%i, blocksize:%i, ustates:%i,\n"
|
fprintf (f, " dc:{enabled:%i, nways:%i, nsets:%i, blocksize:%i, ustates:%i,\n"
|
" load_missdelay:%i, load_hitdelay:%i, store_missdelay:%i, store_hitdelay:%i},\n",
|
" load_missdelay:%i, load_hitdelay:%i, store_missdelay:%i, store_hitdelay:%i},\n",
|
config.dc.enabled, config.dc.nways, config.dc.nsets, config.dc.blocksize, config.dc.ustates,
|
config.dc.enabled, config.dc.nways, config.dc.nsets, config.dc.blocksize, config.dc.ustates,
|
config.dc.load_missdelay, config.dc.load_hitdelay, config.dc.store_missdelay, config.dc.store_hitdelay);
|
config.dc.load_missdelay, config.dc.load_hitdelay, config.dc.store_missdelay, config.dc.store_hitdelay);
|
|
|
fprintf (f, " bpb:{enabled:%i, sbp_bnf_fwd:%i, sbp_bf_fwd:%i, btic:%i, missdelay:%i, hitdelay:%i},\n",
|
fprintf (f, " bpb:{enabled:%i, sbp_bnf_fwd:%i, sbp_bf_fwd:%i, btic:%i, missdelay:%i, hitdelay:%i},\n",
|
config.bpb.enabled, config.bpb.sbp_bnf_fwd, config.bpb.sbp_bf_fwd, config.bpb.btic, config.bpb.missdelay, config.bpb.hitdelay);
|
config.bpb.enabled, config.bpb.sbp_bnf_fwd, config.bpb.sbp_bf_fwd, config.bpb.btic, config.bpb.missdelay, config.bpb.hitdelay);
|
|
|
fprintf (f, " cpu:{upr:0x%08lx, ver:0x%04lx, rev:0x%04lx, superscalar:%i, hazards:%i, dependstats:%i,\n"
|
fprintf (f, " cpu:{upr:0x%08lx, ver:0x%04lx, rev:0x%04lx, superscalar:%i, hazards:%i, dependstats:%i,\n"
|
" sr:0x%08x},\n",
|
" sr:0x%08x},\n",
|
config.cpu.upr, config.cpu.ver, config.cpu.rev, config.cpu.superscalar, config.cpu.hazards, config.cpu.dependstats,
|
config.cpu.upr, config.cpu.ver, config.cpu.rev, config.cpu.superscalar, config.cpu.hazards, config.cpu.dependstats,
|
config.cpu.sr);
|
config.cpu.sr);
|
|
|
fprintf (f, " sim:{debug:%i, verbose:%i, profile:%i, prof_fn:\"%s\", mprofile:%i, mprof_fn:\"%s\",\n",
|
fprintf (f, " sim:{debug:%i, verbose:%i, profile:%i, prof_fn:\"%s\", mprofile:%i, mprof_fn:\"%s\",\n",
|
config.sim.debug, config.sim.verbose, config.sim.profile, config.sim.prof_fn, config.sim.mprofile, config.sim.mprof_fn);
|
config.sim.debug, config.sim.verbose, config.sim.profile, config.sim.prof_fn, config.sim.mprofile, config.sim.mprof_fn);
|
|
|
fprintf (f, " history:%i, exe_log:%i, exe_log_fn:\"%s\", clkcycle_ps:%li,\n",
|
fprintf (f, " history:%i, exe_log:%i, exe_log_fn:\"%s\", clkcycle_ps:%li,\n",
|
config.sim.history, config.sim.exe_log, config.sim.exe_log_fn, config.sim.clkcycle_ps);
|
config.sim.history, config.sim.exe_log, config.sim.exe_log_fn, config.sim.clkcycle_ps);
|
|
|
fprintf (f, " spr_log:%i, spr_log_fn:\"%s\"},\n",
|
fprintf (f, " spr_log:%i, spr_log_fn:\"%s\"},\n",
|
config.sim.spr_log, config.sim.spr_log_fn);
|
config.sim.spr_log, config.sim.spr_log_fn);
|
|
|
fprintf (f, " debug:{enabled:%i, gdb_enabled:%i, server_port:%i, vapi_id:0x%08lx},\n",
|
fprintf (f, " debug:{enabled:%i, gdb_enabled:%i, server_port:%i, vapi_id:0x%08lx},\n",
|
config.debug.enabled, config.debug.gdb_enabled, config.debug.server_port, config.debug.vapi_id);
|
config.debug.enabled, config.debug.gdb_enabled, config.debug.server_port, config.debug.vapi_id);
|
|
|
fprintf (f, " vapi:{enabled:%i, server_port:%i, log_enabled:%i, hide_device_id:%i, vapi_fn:\"%s\"},\n",
|
fprintf (f, " vapi:{enabled:%i, server_port:%i, log_enabled:%i, hide_device_id:%i, vapi_fn:\"%s\"},\n",
|
config.vapi.enabled, config.vapi.server_port, config.vapi.log_enabled, config.vapi.hide_device_id, config.vapi.vapi_fn);
|
config.vapi.enabled, config.vapi.server_port, config.vapi.log_enabled, config.vapi.hide_device_id, config.vapi.vapi_fn);
|
|
|
fprintf (f, " pm:{enabled:%i}\n",
|
fprintf (f, " pm:{enabled:%i}\n",
|
config.pm.enabled);
|
config.pm.enabled);
|
|
|
fprintf (f, "};\n");
|
fprintf (f, "};\n");
|
}
|
}
|
|
|