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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [toplevel-support.c] - Blame information for rev 483

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 jeremybenn
/* toplevel.c -- Top level simulator support source file
2
 
3
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7
 
8
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9
 
10
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14
 
15
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19
 
20
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
 
27
/* Autoconf and/or portability configuration */
28
#include "config.h"
29
 
30
/* System includes */
31
#include <stdlib.h>
32
#include <unistd.h>
33
#include <stdarg.h>
34
#include <stdio.h>
35
#include <errno.h>
36
#include <signal.h>
37 483 jeremybenn
#include <sys/types.h>
38
#include <sys/stat.h>
39
#include <fcntl.h>
40 19 jeremybenn
 
41
/* Package includes */
42
#include "toplevel-support.h"
43
#include "sim-config.h"
44
#include "debug-unit.h"
45
#include "sim-cmd.h"
46
#include "sched.h"
47
#include "tick.h"
48
#include "pm.h"
49
#include "pic.h"
50
#include "execute.h"
51
#include "labels.h"
52
#include "stats.h"
53
#include "opcode/or32.h"
54
#include "parse.h"
55
#include "rsp-server.h"
56
#include "vapi.h"
57
#include "abstract.h"
58
#include "mc.h"
59
#include "except.h"
60
 
61
 
62
/*! Struct for list of reset hooks */
63
struct sim_reset_hook
64
{
65
  void *dat;
66
  void (*reset_hook) (void *);
67
  struct sim_reset_hook *next;
68
};
69
 
70
/*! The list of reset hooks. Local to this source file */
71
static struct sim_reset_hook *sim_reset_hooks = NULL;
72
 
73
 
74
/*---------------------------------------------------------------------------*/
75 483 jeremybenn
/*!Random number initialization
76
 
77
   This has become more important, since we rely on randomness to generate
78
   different MACs in Linux running on Or1ksim.
79
 
80
   We take our seed from /dev/urandom.
81
 
82
   If /dev/urandom is not available, we use srandom with the PID instead.    */
83
/*---------------------------------------------------------------------------*/
84
void
85
init_randomness ()
86
{
87
  unsigned int   seed;
88
  int            fd;
89
 
90
  fd = open ("/dev/urandom", O_RDONLY);
91
 
92
  if (fd >= 0)
93
    {
94
      if (sizeof (seed) != read (fd, (void *) &seed, sizeof (seed)))
95
        {
96
          fprintf (stderr, "Warning: Unable to read /dev/random, using PID.\n");
97
          seed = getpid ();
98
        }
99
    }
100
  else
101
    {
102
      fprintf (stderr, "Warning: Unable to open /dev/random, using PID.\n");
103
      seed = getpid ();
104
    }
105
 
106
  srandom (seed);
107
 
108
  /* Print out the seed just in case we ever need to debug. Note that we
109
     cannot use PRINTF here, since the file handle will not yet have been set
110
     up. */
111
  printf ("Seeding random generator with value 0x%08x\n", seed);
112
 
113
}       /* init_randomness () */
114
 
115
 
116
/*---------------------------------------------------------------------------*/
117 19 jeremybenn
/*!Signal handler for ctrl-C
118
 
119
   Sets the iprompt flag, so the simulator will stop next time round the
120
   loop. If the iprompt flag is set when we enter here, that means the
121
   simulator has not reacted since the last ctrl-C, so we kill the simulation.
122
 
123
   @param[in] signum  The signal which triggered this handler                */
124
/*---------------------------------------------------------------------------*/
125
void
126
ctrl_c (signum)
127
     int signum;
128
{
129
  /* Incase the user pressed ctrl+c twice without the sim reacting kill it.
130
   * This is incase the sim locks up in a high level routine, without executeing
131
   * any (or) code */
132
  if (runtime.sim.iprompt && !runtime.sim.iprompt_run)
133
    {
134
      sim_done ();
135
      exit (-1);
136
    }
137
 
138
  /* Mark the simulator to stop next time and reinstall the handler */
139
  runtime.sim.iprompt = 1;
140
  signal (SIGINT, ctrl_c);
141
 
142
}       /* ctrl_c() */
143
 
144 443 jeremybenn
 
145 442 julius
/*---------------------------------------------------------------------------*/
146
/*!Signal handler for SIGUSR1
147 19 jeremybenn
 
148 442 julius
  Toggles state of trace generating while program is running.
149
 
150
   @param[in] signum  The signal which triggered this handler                */
151 19 jeremybenn
/*---------------------------------------------------------------------------*/
152 442 julius
void
153
toggle_trace (signum)
154
     int signum;
155
{
156
 
157
  runtime.sim.hush = !runtime.sim.hush;
158
 
159
  signal (SIGUSR1, toggle_trace);
160
 
161
}       /* toggle_trace() */
162
 
163
 
164
/*---------------------------------------------------------------------------*/
165 19 jeremybenn
/*!Routine poll to see if interaction is needed
166
 
167
   This is most likely to happen due to a ctrl-C. However when the -i flag is
168
   specified, the simulator starts up ready for interaction.
169
 
170
   The main simulator loop will stop for interaction if it hits a breakpoint.
171
 
172
   @param[in] dat  Data passed in by the Or1ksim scheduler. Not needed by this
173
   function.                                                                 */
174
/*---------------------------------------------------------------------------*/
175
void
176
check_int (void *dat)
177
{
178
  if (runtime.sim.iprompt)
179
    {
180
      set_stall_state (0);
181
      handle_sim_command ();
182
    }
183
 
184
  SCHED_ADD (check_int, NULL, CHECK_INT_TIME);
185
 
186
}       /* check_int() */
187
 
188
 
189
/*---------------------------------------------------------------------------*/
190
/*!Register a new reset hook
191
 
192
   The registered functions will be called in turn, whenever the simulation is
193
   reset by calling sim_reset().
194
 
195
   @param[in] reset_hook  The function to be called on reset
196
   @param[in] dat         The data structure to be passed as argument when the
197
                          reset_hook function is called.                     */
198
/*---------------------------------------------------------------------------*/
199
void
200
reg_sim_reset (void (*reset_hook) (void *), void *dat)
201
{
202
  struct sim_reset_hook *new = malloc (sizeof (struct sim_reset_hook));
203
 
204
  if (!new)
205
    {
206
      fprintf (stderr, "reg_sim_reset: Out-of-memory\n");
207
      exit (1);
208
    }
209
 
210
  new->dat = dat;
211
  new->reset_hook = reset_hook;
212
  new->next = sim_reset_hooks;
213
  sim_reset_hooks = new;
214
 
215
}       /* reg_sim_reset() */
216
 
217
 
218
/*---------------------------------------------------------------------------*/
219
/*!Reset the simulator
220
 
221
   The scheduler is reset, then all reset functions on the reset hook list
222
   (i.e. peripherals) are reset. Then standard core functions (which do not
223
   use reset hooks) are reset: tick timer, power management, programmable
224
   interrupt controller and debug unit.
225
 
226
   The scheduler queue is reinitialized with an immediate check for ctrl-C on
227
   its queue.
228
 
229
   Finally the count of simulated cycles is set to zero. and the CPU itself is
230
   reset.                                                                    */
231
/*---------------------------------------------------------------------------*/
232
void
233
sim_reset ()
234
{
235
  struct sim_reset_hook *cur_reset = sim_reset_hooks;
236
 
237
  /* We absolutely MUST reset the scheduler first */
238
  sched_reset ();
239
 
240
  while (cur_reset)
241
    {
242
      cur_reset->reset_hook (cur_reset->dat);
243
      cur_reset = cur_reset->next;
244
    }
245
 
246
  tick_reset ();
247
  pm_reset ();
248
  pic_reset ();
249
  du_reset ();
250
 
251
  /* Make sure that runtime.sim.iprompt is the first thing to get checked */
252
  SCHED_ADD (check_int, NULL, 1);
253
 
254
  /* FIXME: Lame-ass way to get runtime.sim.mem_cycles not going into overly
255
   * negative numbers.  This happens because parse.c uses setsim_mem32 to load
256
   * the program but set_mem32 calls dc_simulate_write, which inturn calls
257
   * setsim_mem32.  This mess of memory statistics needs to be sorted out for
258
   * good one day */
259
  runtime.sim.mem_cycles = 0;
260
  cpu_reset ();
261
 
262
}       /* sim_reset() */
263
 
264
 
265
/*---------------------------------------------------------------------------*/
266
/*!Initalize the simulator
267
 
268
  Reset internal data: symbol table (aka labels), breakpoints and
269
  stats. Rebuild the FSA's used for disassembly.
270
 
271
  Initialize the dynamic execution system if required.
272
 
273
  Initialize the scheduler.
274
 
275
  Open the various logs and statistics files requested by the configuration
276
  and/or command arguments.
277
 
278
  Initialize GDB and VAPI connections.
279
 
280
  Reset the simulator.
281
 
282
  Wait for VAPI to connect if configured.                                    */
283
/*---------------------------------------------------------------------------*/
284
void
285
sim_init ()
286
{
287 220 jeremybenn
  PRINTFQ ("Or1ksim " PACKAGE_VERSION "\n" );
288 19 jeremybenn
  init_labels ();
289
  init_breakpoints ();
290
  initstats ();
291 230 jeremybenn
  or1ksim_build_automata (config.sim.quiet);
292 19 jeremybenn
 
293
#if DYNAMIC_EXECUTION
294
  /* Note: This must be called before the scheduler is used */
295
  init_dyn_recomp ();
296
#endif
297
 
298
  sched_init ();
299
 
300
  sim_reset ();                 /* Must do this first - torches memory! */
301
 
302
  if (config.sim.profile)
303
    {
304
      runtime.sim.fprof = fopen (config.sim.prof_fn, "wt+");
305
      if (!runtime.sim.fprof)
306
        {
307
          fprintf (stderr, "ERROR: sim_init: cannot open profile file %s: ",
308
                   config.sim.prof_fn);
309
          perror (NULL);
310
          exit (1);
311
        }
312
      else
313
        fprintf (runtime.sim.fprof,
314
                 "+00000000 FFFFFFFF FFFFFFFF [outside_functions]\n");
315
    }
316
 
317
  if (config.sim.mprofile)
318
    {
319
      runtime.sim.fmprof = fopen (config.sim.mprof_fn, "wb+");
320
      if (!runtime.sim.fmprof)
321
        {
322
          fprintf (stderr, "ERROR: sim_init: cannot open memory profile "
323
                   "file %s: ", config.sim.mprof_fn);
324
          perror (NULL);
325
          exit (1);
326
        }
327
    }
328
 
329
  if (config.sim.exe_log)
330
    {
331
      runtime.sim.fexe_log = fopen (config.sim.exe_log_fn, "wt+");
332
      if (!runtime.sim.fexe_log)
333
        {
334
          fprintf (stderr, "sim_init: cannot open execution log file %s: ",
335
                   config.sim.exe_log_fn);
336
          perror (NULL);
337
          exit (1);
338
        }
339
    }
340
 
341 202 julius
  if (config.sim.exe_bin_insn_log)
342
    {
343
      runtime.sim.fexe_bin_insn_log = fopen (config.sim.exe_bin_insn_log_fn, "wb+");
344
      if (!runtime.sim.fexe_bin_insn_log)
345
        {
346
          fprintf (stderr, "sim_init: cannot open binary instruction execution log file %s: ",
347
                   config.sim.exe_bin_insn_log_fn);
348
          perror (NULL);
349
          exit (1);
350
        }
351
    }
352
 
353 19 jeremybenn
  /* MM170901 always load at address zero */
354
  if (runtime.sim.filename)
355
    {
356
      unsigned long endaddr = loadcode (runtime.sim.filename, 0, 0);
357
 
358
      if (endaddr == -1)
359
        {
360
          fprintf (stderr, "ERROR: sim_init: problem loading code from %s\n",
361
                   runtime.sim.filename);
362
          exit (1);
363
        }
364
    }
365
 
366 235 jeremybenn
  /* Disable RSP debugging, if debug unit is not available.  */
367
  if (config.debug.rsp_enabled && !config.debug.enabled)
368 19 jeremybenn
    {
369
      config.debug.rsp_enabled = 0;
370
 
371
      if (config.sim.verbose)
372
        {
373
          fprintf (stderr, "WARNING: sim_init: Debug module not enabled, "
374
                   "cannot start remote service to GDB\n");
375
        }
376
    }
377
 
378
  /* Start either RSP or legacy GDB debugging service */
379
  if (config.debug.rsp_enabled)
380
    {
381
      rsp_init ();
382
 
383
      /* RSP always starts stalled as though we have just reset the
384
         processor. */
385
      rsp_exception (EXCEPT_TRAP);
386
      set_stall_state (1);
387
    }
388
 
389
  /* Enable dependency stats, if we want to do history analisis */
390
  if (config.sim.history && !config.cpu.dependstats)
391
    {
392
      config.cpu.dependstats = 1;
393
      if (config.sim.verbose)
394
        {
395
          fprintf (stderr, "WARNING: sim_init: dependstats stats must be "
396
                   "enabled to do history analysis\n");
397
        }
398
    }
399
 
400
  /* Debug forces verbose */
401
  if (config.sim.debug && !config.sim.verbose)
402
    {
403
      config.sim.verbose = 1;
404
      fprintf (stderr, "WARNING: sim_init: verbose forced on by debug\n");
405
    }
406
 
407
  /* Start VAPI before device initialization.  */
408
  if (config.vapi.enabled)
409
    {
410
      runtime.vapi.enabled = 1;
411
      vapi_init ();
412
      if (config.sim.verbose)
413
        {
414
          PRINTF ("VAPI started, waiting for clients\n");
415
        }
416
    }
417
 
418
  /* Wait till all test are connected.  */
419
  if (runtime.vapi.enabled)
420
    {
421
      int numu = vapi_num_unconnected (0);
422
      if (numu)
423
        {
424
          PRINTF ("\nWaiting for VAPI tests with ids:\n");
425
          vapi_num_unconnected (1);
426
          PRINTF ("\n");
427
          while ((numu = vapi_num_unconnected (0)))
428
            {
429
              vapi_check ();
430
              PRINTF
431
                ("\rStill waiting for %i VAPI test(s) to connect",
432
                 numu);
433
              usleep (100);
434
            }
435
          PRINTF ("\n");
436
        }
437
      PRINTF ("All devices connected\n");
438
    }
439
}       /* sim_init() */
440
 
441
 
442
/*---------------------------------------------------------------------------*/
443
/*!Clean up
444
 
445
   Close an profile or log files, disconnect VAPI. Call any memory mapped
446
   peripheral close down function. Exit with rc 0.                           */
447
/*---------------------------------------------------------------------------*/
448
void
449
sim_done ()
450
{
451
  if (config.sim.profile)
452
    {
453
      fprintf (runtime.sim.fprof, "-%08llX FFFFFFFF\n", runtime.sim.cycles);
454
      fclose (runtime.sim.fprof);
455
    }
456
 
457
  if (config.sim.mprofile)
458
    {
459
      fclose (runtime.sim.fmprof);
460
    }
461
 
462
  if (config.sim.exe_log)
463
    {
464
      fclose (runtime.sim.fexe_log);
465
    }
466
 
467 202 julius
  if (config.sim.exe_bin_insn_log)
468
    {
469
      fclose (runtime.sim.fexe_bin_insn_log);
470
    }
471
 
472 19 jeremybenn
  if (runtime.vapi.enabled)
473
    {
474
      vapi_done ();
475
    }
476
 
477
  done_memory_table ();
478
  mc_done ();
479
 
480
  exit (0);
481
 
482
}       /* sim_done() */

powered by: WebSVN 2.1.0

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