URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [branches/] [stable_0_2_x/] [or1ksim/] [toplevel.c] - Rev 1446
Go to most recent revision | Compare with Previous | Blame | View Log
/* toplevel.c -- Top level simulator source file Copyright (C) 1999 Damjan Lampret, lampret@opencores.org This file is part of OpenRISC 1000 Architectural Simulator. 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 Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Simulator commands. Help and version output. SIGINT processing. Stdout redirection is specific to linux (I need to fix this). */ #include <stdio.h> #include <ctype.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <stdarg.h> #include <fcntl.h> #include <limits.h> #include <time.h> #include "config.h" #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif #include "port.h" #include "arch.h" #include "parse.h" #include "abstract.h" #include "labels.h" #include "sim-config.h" #include "opcode/or32.h" #include "spr_defs.h" #include "execute.h" #include "sprs.h" #include "vapi.h" #include "gdbcomm.h" #include "debug_unit.h" #include "coff.h" #include "sched.h" #include "profiler.h" #include "mprofiler.h" #include "pm.h" #include "pic.h" #include "stats.h" #include "immu.h" #include "dmmu.h" #include "dcache_model.h" #include "icache_model.h" #include "branch_predict.h" #include "dumpverilog.h" #include "trace.h" #include "cuc.h" /* CVS revision number. */ const char rcsrev[] = "$Revision: 1.122 $"; inline void debug(int level, const char *format, ...) { char *p; va_list ap; if (config.sim.debug >= level) { if ((p = malloc(1000)) == NULL) return; va_start(ap, format); (void) vsnprintf(p, 1000, format, ap); va_end(ap); PRINTF("%s", p); fflush(stdout); free(p); } else { #if DEBUG if ((p = malloc(1000)) == NULL) return; va_start(ap, format); (void) vsnprintf(p, 1000, format, ap); va_end(ap); PRINTF("%s\n", p); fflush(stdout); free(p); #endif } } void ctrl_c(signum) int signum; { runtime.sim.cont_run = runtime.cpu.stalled ? 0 : 1; runtime.sim.iprompt = 1; set_stall_state (0); signal(SIGINT, ctrl_c); } void version() { PRINTF ("\n"); PRINTF ("OpenRISC 1000 (OR32) Architectural Simulator, %s\n", rcsrev); PRINTF ("Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n"); PRINTF ("Copyright (C) 2000 Damjan Lampret, lampret@opencores.org\n"); PRINTF (" Jimmy Chen-Min Chen, jimmy@ee.nctu.edu.tw\n"); PRINTF (" Johan Rydberg, johan.rydberg@insight.se\n"); PRINTF (" Marko Mlinar, markom@opencores.org\n"); PRINTF ("Copyright (C) 2001 Simon Srot, simons@opencores.org\n"); PRINTF (" Marko Mlinar, markom@opencores.org\n"); PRINTF ("Copyright (C) 2002 Marko Mlinar, markom@opencores.org\n"); PRINTF (" Simon Srot, simons@opencores.org\n"); PRINTF ("Visit http://www.opencores.org for more information about "); PRINTF ("OpenRISC 1000 and\nother open source cores.\n\n"); PRINTF ("This software comes with ABSOLUTELY NO WARRANTY; for "); PRINTF ("details see COPYING.\nThis is free software, and you "); PRINTF ("are welcome to redistribute it under certain\nconditions; "); PRINTF ("for details see COPYING.\n"); } struct sim_reset_hook { void *dat; void (*reset_hook)(void *); struct sim_reset_hook *next; }; struct sim_reset_hook *sim_reset_hooks = NULL; /* Registers a new reset hook, called when sim_reset below is called */ void reg_sim_reset(void (*reset_hook)(void *), void *dat) { struct sim_reset_hook *new = malloc(sizeof(struct sim_reset_hook)); if(!new) { fprintf(stderr, "reg_sim_reset: Out-of-memory\n"); exit(1); } new->dat = dat; new->reset_hook = reset_hook; new->next = sim_reset_hooks; sim_reset_hooks = new; } /* Resets all subunits */ void sim_reset (void) { struct sim_reset_hook *cur_reset = sim_reset_hooks; /* We absolutely MUST reset the scheduler first */ sched_reset(); while(cur_reset) { cur_reset->reset_hook(cur_reset->dat); cur_reset = cur_reset->next; } tick_reset(); pm_reset(); pic_reset(); du_reset (); cpu_reset(); } /* Initalizes all devices and sim */ void sim_init () { init_memory_table (); init_labels(); init_breakpoints(); initstats(); build_automata(); sched_init(); if (config.sim.profile) { runtime.sim.fprof = fopen(config.sim.prof_fn, "wt+"); if(!runtime.sim.fprof) { fprintf(stderr, "ERROR: Problems opening profile file.\n"); exit (1); } else fprintf(runtime.sim.fprof, "+00000000 FFFFFFFF FFFFFFFF [outside_functions]\n"); } if (config.sim.mprofile) { runtime.sim.fmprof = fopen(config.sim.mprof_fn, "wb+"); if(!runtime.sim.fmprof) { fprintf(stderr, "ERROR: Problems opening memory profile file.\n"); exit (1); } } if (config.sim.exe_log) { runtime.sim.fexe_log = fopen(config.sim.exe_log_fn, "wt+"); if(!runtime.sim.fexe_log) { PRINTF("ERROR: Problems opening exe_log file.\n"); exit (1); } } if (config.sim.spr_log) { PRINTF("OPENING SPRLOG\n"); runtime.sim.fspr_log = fopen(config.sim.spr_log_fn, "wt+"); if (!runtime.sim.fspr_log) { PRINTF("ERROR: Problems opening spr_log file.\n"); exit(1); } } /* Initialize memory */ { extern struct dev_memarea *dev_list; struct dev_memarea *area; int i; if (config.memory.type == MT_RANDOM) { unsigned int val = 0; if (config.memory.random_seed == -1) { runtime.memory.random_seed = time(NULL); /* Print out the seed just in case we ever need to debug */ PRINTF("Seeding random generator with value %d\n", config.memory.random_seed); } else runtime.memory.random_seed = config.memory.random_seed; srandom(runtime.memory.random_seed); for (area = dev_list; area; area = area->next) for(i = 0; i < area->size; i++) { val = random(); setsim_mem8(i + area->addr_compare, val & 0xFF); } } else if(config.memory.type == MT_PATTERN) { for (area = dev_list; area; area = area->next) for(i = 0; i < area->size; i++) setsim_mem8(i + area->addr_compare, config.memory.pattern); } else if (config.memory.type != MT_UNKNOWN) { fprintf(stderr, "Invalid memory configuration type.\n"); exit(1); } } if(runtime.sim.filename) { unsigned long endaddr = 0xFFFFFFFF; endaddr = loadcode(runtime.sim.filename, 0, 0); /* MM170901 always load at address zero. */ if (endaddr == -1) { fprintf(stderr, "Problems loading boot code.\n"); exit(1); } } /* Disable gdb debugging, if debug module is not available. */ if (config.debug.gdb_enabled && !config.debug.enabled) { config.debug.gdb_enabled = 0; if (config.sim.verbose) fprintf (stderr, "WARNING: Debug module not enabled, cannot start gdb.\n"); } if (config.debug.gdb_enabled) gdbcomm_init (); /* Enable dependency stats, if we want to do history analisis */ if (config.sim.history && !config.cpu.dependstats) { config.cpu.dependstats = 1; if (config.sim.verbose) fprintf (stderr, "WARNING: dependstats stats must be enabled to do history analisis.\n"); } /* Debug forces verbose */ if (config.sim.debug && !config.sim.verbose) { config.sim.verbose = 1; fprintf (stderr, "WARNING: verbose turned on.\n"); } /* Start VAPI before device initialization. */ if (config.vapi.enabled) { runtime.vapi.enabled = 1; vapi_init (); if (config.sim.verbose) PRINTF ("VAPI started, waiting for clients.\n"); } sim_reset (); lock_memory_table (); /* Wait till all test are connected. */ if (runtime.vapi.enabled) { int numu = vapi_num_unconnected (0); if (numu) { PRINTF ("\nWaiting for VAPI tests with ids:\n"); vapi_num_unconnected (1); PRINTF ("\n"); while ((numu = vapi_num_unconnected (0))) { vapi_check (); PRINTF ("\rStill waiting for %i VAPI test(s) to connect. ", numu); usleep (100); } PRINTF ("\n"); } PRINTF ("All devices connected \n"); } /* simulator is initialized */ runtime.sim.init = 0; } /* Cleanup */ void sim_done (void) { if (config.sim.profile) { fprintf(runtime.sim.fprof,"-%08llX FFFFFFFF\n", runtime.sim.cycles); fclose(runtime.sim.fprof); } if (config.sim.mprofile) fclose(runtime.sim.fmprof); if (config.sim.exe_log) fclose(runtime.sim.fexe_log); if (runtime.vapi.enabled) vapi_done (); done_memory_table (); exit(0); } /* Executes jobs in time queue */ static inline void do_scheduler (void) { struct sched_entry *tmp; /* Execute all jobs till now */ do { tmp = scheduler.job_queue; scheduler.job_queue = tmp->next; tmp->next = scheduler.free_job_queue; scheduler.free_job_queue = tmp; tmp->func (tmp->param); } while (scheduler.job_queue->time <= 0); } /* Main function */ int main(argc, argv) int argc; char *argv[]; { srand(getpid()); init_defconfig(); reg_config_secs(); if (parse_args(argc, argv)) { PRINTF("Usage: %s [options] <filename>\n", argv[0]); PRINTF("Options:\n"); PRINTF(" -v version and copyright note\n"); PRINTF(" -i enable interactive command prompt\n"); PRINTF(" --nosrv do not launch JTAG proxy server\n"); /* (CZ) */ PRINTF(" --srv <n> launch JTAG proxy server on port <n>; [random]\n"); /* (CZ) */ PRINTF(" -f or --file load script file [sim.cfg]\n"); PRINTF(" --enable-profile enable profiling.\n"); PRINTF(" --enable-mprofile enable memory profiling.\n"); PRINTF(" --output-cfg prints C structure of current\n"); PRINTF(" configuration to standard output\n"); PRINTF("\nor : %s ", argv[0]); mp_help (); PRINTF("\nor : %s ", argv[0]); prof_help (); exit(-1); } /* Read configuration file. */ if (!runtime.sim.script_file_specified) read_script_file ("sim.cfg"); /* Overide parameters with command line ones */ if (runtime.simcmd.profile) config.sim.profile = 1; if (runtime.simcmd.mprofile) config.sim.mprofile = 1; if (!runtime.sim.script_file_specified && config.sim.verbose) fprintf (stderr, "WARNING: No config file read, assuming default configuration.\n"); if (runtime.sim.output_cfg) { output_cfg (stdout); exit (0); } print_config(); sim_init (); signal(SIGINT, ctrl_c); runtime.sim.hush = 1; runtime.sim.cont_run = -1; while(1) { if (runtime.sim.iprompt) handle_sim_command(); { /* Needed by execution */ extern int do_stats; do_stats = config.cpu.dependstats || config.cpu.superscalar || config.cpu.dependstats || config.sim.history || config.sim.exe_log; } /* MM: 'run -1' means endless execution. */ while(runtime.sim.cont_run) { long long time_start = runtime.sim.cycles; if (config.debug.enabled) { du_clock(); // reset watchpoints if (runtime.cpu.stalled) { if(config.debug.gdb_enabled) { BlockJTAG(); HandleServerSocket(false); } else { fprintf (stderr, "WARNING: CPU stalled and gdb connection not enabled."); runtime.sim.cont_run = 0; } continue; } } /* Each cycle has counter of mem_cycles; this value is joined with cycles at the end of the cycle; no sim originated memory accesses should be performed inbetween. */ runtime.sim.mem_cycles = 0; if (!config.pm.enabled || !testsprbits(SPR_PMR, SPR_PMR_DME | SPR_PMR_SME)) { if (runtime.sim.cont_run > 0) runtime.sim.cont_run--; if (cpu_clock ()) break; } if (config.vapi.enabled && runtime.vapi.enabled) vapi_check(); if (config.debug.gdb_enabled) HandleServerSocket(false); /* block & check_stdin = false */ if(config.debug.enabled) if (testsprbits(SPR_DMR1, SPR_DMR1_ST)) set_stall_state (1); runtime.sim.cycles += runtime.sim.mem_cycles; scheduler.job_queue->time -= runtime.sim.cycles - time_start; if (scheduler.job_queue->time <= 0) do_scheduler (); if (!runtime.sim.hush) dumpreg(); } runtime.sim.hush = 0; fflush(stdout); runtime.sim.fout = stdout; if (!runtime.sim.iprompt) /* non-interactive quit */ sim_done(); } sim_done(); }
Go to most recent revision | Compare with Previous | Blame | View Log