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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [libtoplevel.c] - Blame information for rev 82

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 jeremybenn
/* libtoplevel.c -- Top level simulator library 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 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 <signal.h>
34
 
35
/* Package includes */
36
#include "or1ksim.h"
37
#include "sim-config.h"
38
#include "toplevel-support.h"
39
#include "sched.h"
40
#include "execute.h"
41
#include "pic.h"
42 82 jeremybenn
#include "jtag.h"
43 19 jeremybenn
 
44
 
45
/*---------------------------------------------------------------------------*/
46
/*!Initialize the simulator.
47
 
48
   Allows specification of an (optional) config file and an image file. Builds
49
   up dummy argc/argv to pass to the existing argument parser.
50
 
51
   @param[in] config_file  Or1ksim configuration file name
52
   @param[in] image_file   The program image to execute
53
   @param[in] class_ptr    Pointer to a C++ class instance (for use when
54
                           called by C++)
55
   @param[in] upr          Upcall routine for reads
56
   @param[in] upw          Upcall routine for writes
57
 
58
   @return  0 on success and an error code on failure                        */
59
/*---------------------------------------------------------------------------*/
60
int
61
or1ksim_init (const char *config_file,
62
              const char *image_file,
63
              void       *class_ptr,
64
              unsigned long int (*upr) (void *class_ptr,
65
                                        unsigned long int addr,
66
                                        unsigned long int mask),
67
              void (*upw) (void *class_ptr,
68
                           unsigned long int addr,
69
                           unsigned long int mask, unsigned long int wdata))
70
{
71
  int   dummy_argc;
72
  char *dummy_argv[4];
73
 
74
  /* Dummy argv array. Varies depending on whether an image file is
75
     specified. */
76
  dummy_argv[0] = "libsim";
77
  dummy_argv[1] = "-f";
78
  dummy_argv[2] = (char *) ((NULL != config_file) ? config_file : "sim.cfg");
79
  dummy_argv[3] = (char *) image_file;
80
 
81
  dummy_argc = (NULL == image_file) ? 3 : 4;
82
 
83
  /* Initialization copied from existing main() */
84
  srand (getpid ());
85
  init_defconfig ();
86
  reg_config_secs ();
87
 
88
  if (parse_args (dummy_argc, dummy_argv))
89
    {
90
      return OR1KSIM_RC_BADINIT;
91
    }
92
 
93
  config.sim.profile   = 0;      /* No profiling */
94
  config.sim.mprofile  = 0;
95
 
96
  config.ext.class_ptr = class_ptr;     /* SystemC linkage */
97
  config.ext.read_up   = upr;
98
  config.ext.write_up  = upw;
99
 
100
  print_config ();              /* Will go eventually */
101
  signal (SIGINT, ctrl_c);      /* Not sure we want this really */
102
 
103
  runtime.sim.hush = 1;         /* Not sure if this is needed */
104
  do_stats = config.cpu.superscalar ||
105
             config.cpu.dependstats ||
106
             config.sim.history     ||
107
             config.sim.exe_log;
108
 
109
  sim_init ();
110
 
111
  runtime.sim.ext_int_set = 0;   /* No interrupts pending to be set */
112
  runtime.sim.ext_int_clr = 0;   /* No interrupts pending to be cleared */
113
 
114
  return OR1KSIM_RC_OK;
115
 
116
}       /* or1ksim_init() */
117
 
118
 
119
/*---------------------------------------------------------------------------*/
120
/*!Run the simulator
121
 
122
   The argument is a time in seconds, which is converted to a number of
123
   cycles, if positive. A negative value means "run for ever".
124
 
125
   The semantics are that the duration for which the run may occur may be
126
   changed mid-run by a call to or1ksim_reset_duration(). This is to allow for
127
   the upcalls to generic components adding time, and reducing the time
128
   permitted for ISS execution before synchronization of the parent SystemC
129
   wrapper.
130
 
131
   This is over-ridden if the call was for a negative duration, which means
132
   run forever!
133
 
134
   Uses a simplified version of the old main program loop. Returns success if
135
   the requested number of cycles were run and an error code otherwise.
136
 
137
   @param[in] duration  Time to execute for (seconds)
138
 
139
   @return  OR1KSIM_RC_OK if we run to completion, OR1KSIM_RC_BRKPT if we hit
140
            a breakpoint (not clear how this can be set without CLI access)  */
141
/*---------------------------------------------------------------------------*/
142
int
143
or1ksim_run (double duration)
144
{
145
  const int  num_ints = sizeof (runtime.sim.ext_int_set) * 8;
146
 
147
  or1ksim_reset_duration (duration);
148
 
149
  /* Loop until we have done enough cycles (or forever if we had a negative
150
     duration) */
151
  while (duration < 0.0 || (runtime.sim.cycles < runtime.sim.end_cycles))
152
    {
153
      long long int time_start = runtime.sim.cycles;
154
      int i;                    /* Interrupt # */
155
 
156
      /* Each cycle has counter of mem_cycles; this value is joined with cycles
157
       * at the end of the cycle; no sim originated memory accesses should be
158 82 jeremybenn
       * performed in between. */
159 19 jeremybenn
      runtime.sim.mem_cycles = 0;
160
 
161
      if (cpu_clock ())
162
        {
163
          return OR1KSIM_RC_BRKPT;      /* Hit a breakpoint */
164
        }
165
 
166
      runtime.sim.cycles += runtime.sim.mem_cycles;
167
 
168
      /* Take any external interrupts. Outer test is for the common case for
169
         efficiency. */
170
      if (0 != runtime.sim.ext_int_set)
171
        {
172
          for (i = 0; i < num_ints; i++)
173
            {
174
              if (0x1 == ((runtime.sim.ext_int_set >> i) & 0x1))
175
                {
176
                  report_interrupt (i);
177
                  runtime.sim.ext_int_set &= ~(1 << i); /* Clear req flag */
178
                }
179
            }
180
        }
181
 
182
      /* Clear any interrupts as requested. For edge triggered interrupts this
183
         will happen in the same cycle. For level triggered, it must be an
184
         explicit call. */
185
      if (0 != runtime.sim.ext_int_clr)
186
        {
187
          for (i = 0; i < num_ints; i++)
188
            {
189
              /* Only clear interrupts that have been explicitly cleared */
190
              if(0x1 == ((runtime.sim.ext_int_clr >> i) & 0x1))
191
                {
192
                  clear_interrupt(i);
193
                  runtime.sim.ext_int_clr &= ~(1 << i); /* Clear clr flag */
194
                }
195
            }
196
        }
197
 
198
      /* Update the scheduler queue */
199
      scheduler.job_queue->time -= (runtime.sim.cycles - time_start);
200
 
201
      if (scheduler.job_queue->time <= 0)
202
        {
203
          do_scheduler ();
204
        }
205
    }
206
 
207
  return  OR1KSIM_RC_OK;
208
 
209
}       /* or1ksim_run() */
210
 
211
 
212
/*---------------------------------------------------------------------------*/
213
/*!Reset the run-time simulation end point
214
 
215
  Reset the time for which the simulation should run to the specified duration
216
  from NOW (i.e. NOT from when the run started).
217
 
218
  @param[in] duration  Time to run for in seconds                            */
219
/*---------------------------------------------------------------------------*/
220
void
221
or1ksim_reset_duration (double duration)
222
{
223
  runtime.sim.end_cycles =
224
    runtime.sim.cycles +
225
    (long long int) (duration * 1.0e12 / (double) config.sim.clkcycle_ps);
226
 
227
}       /* or1ksim_reset_duration() */
228
 
229
 
230
/*---------------------------------------------------------------------------*/
231
/*!Return time executed so far
232
 
233
   Internal utility to return the time executed so far. Note that this is a
234
   re-entrant routine.
235
 
236
   @return  Time executed so far in seconds                                  */
237
/*---------------------------------------------------------------------------*/
238
static double
239
internal_or1ksim_time ()
240
{
241
  return (double) runtime.sim.cycles * (double) config.sim.clkcycle_ps /
242
    1.0e12;
243
 
244
}       // or1ksim_cycle_count()
245
 
246
 
247
/*---------------------------------------------------------------------------*/
248
/*!Mark a time point in the simulation
249
 
250
   Sets the internal parameter recording this point in the simulation        */
251
/*---------------------------------------------------------------------------*/
252
void
253
or1ksim_set_time_point ()
254
{
255
  runtime.sim.time_point = internal_or1ksim_time ();
256
 
257
}       /* or1ksim_set_time_point() */
258
 
259
 
260
/*---------------------------------------------------------------------------*/
261
/*!Return the time since the time point was set
262
 
263
  Get the value from the internal parameter                                  */
264
/*---------------------------------------------------------------------------*/
265
double
266
or1ksim_get_time_period ()
267
{
268
  return internal_or1ksim_time () - runtime.sim.time_point;
269
 
270
}       /* or1ksim_get_time_period() */
271
 
272
 
273
/*---------------------------------------------------------------------------*/
274
/*!Return the endianism of the model
275
 
276
   Note that this is a re-entrant routine.
277
 
278
   @return 1 if the model is little endian, 0 otherwise.                     */
279
/*---------------------------------------------------------------------------*/
280
int
281
or1ksim_is_le ()
282
{
283
#ifdef OR32_BIG_ENDIAN
284
  return 0;
285
#else
286
  return 1;
287
#endif
288
 
289
}       /* or1ksim_is_le() */
290
 
291
 
292
/*---------------------------------------------------------------------------*/
293
/*!Return the clock rate
294
 
295
   Value is part of the configuration
296
 
297
   @return  Clock rate in Hz.                                                */
298
/*---------------------------------------------------------------------------*/
299
unsigned long int
300
or1ksim_clock_rate ()
301
{
302
  return (unsigned long int) (1000000000000ULL /
303
                              (unsigned long long int) (config.sim.
304
                                                        clkcycle_ps));
305
}       /* or1ksim_clock_rate() */
306
 
307
 
308
/*---------------------------------------------------------------------------*/
309
/*!Trigger an edge triggered interrupt
310
 
311
   This function is appropriate for edge triggered interrupts, which are taken
312
   and then immediately cleared.
313
 
314
   @note There is no check that the specified interrupt number is reasonable
315
   (i.e. <= 31).
316
 
317
   @param[in] i  The interrupt number                                        */
318
/*---------------------------------------------------------------------------*/
319
void
320
or1ksim_interrupt (int i)
321
{
322
  if (!config.pic.edge_trigger)
323
    {
324
      fprintf (stderr, "Warning: or1ksim_interrupt should not be used for "
325
               "edge triggered interrupts. Ignored\n");
326
    }
327
  else
328
    {
329
      runtime.sim.ext_int_set |= 1 << i;        // Better not be > 31!
330
      runtime.sim.ext_int_clr |= 1 << i;        // Better not be > 31!
331
    }
332
}       /* or1ksim_interrupt() */
333
 
334
 
335
/*---------------------------------------------------------------------------*/
336
/*!Set a level triggered interrupt
337
 
338
   This function is appropriate for level triggered interrupts, which must be
339
   explicitly cleared in a separate call.
340
 
341
   @note There is no check that the specified interrupt number is reasonable
342
   (i.e. <= 31).
343
 
344
   @param[in] i  The interrupt number to set                                 */
345
/*---------------------------------------------------------------------------*/
346
void
347
or1ksim_interrupt_set (int i)
348
{
349
  if (config.pic.edge_trigger)
350
    {
351
      fprintf (stderr, "Warning: or1ksim_interrupt_set should not be used for "
352
               "level triggered interrupts. Ignored\n");
353
    }
354
  else
355
    {
356
      runtime.sim.ext_int_set |= 1 << i;        // Better not be > 31!
357
    }
358
}       /* or1ksim_interrupt() */
359
 
360
 
361
/*---------------------------------------------------------------------------*/
362
/*!Clear a level triggered interrupt
363
 
364
   This function is appropriate for level triggered interrupts, which must be
365
   explicitly set first in a separate call.
366
 
367
   @note There is no check that the specified interrupt number is reasonable
368
   (i.e. <= 31).
369
 
370
   @param[in] i  The interrupt number to clear                               */
371
/*---------------------------------------------------------------------------*/
372
void
373
or1ksim_interrupt_clear (int i)
374
{
375
  if (config.pic.edge_trigger)
376
    {
377
      fprintf (stderr, "Warning: or1ksim_interrupt_clear should not be used "
378
               "for level triggered interrupts. Ignored\n");
379
    }
380
  else
381
    {
382
      runtime.sim.ext_int_clr |= 1 << i;        // Better not be > 31!
383
    }
384
}       /* or1ksim_interrupt() */
385 82 jeremybenn
 
386
 
387
/*---------------------------------------------------------------------------*/
388
/*!Reset the JTAG interface
389
 
390
   @note Like all the JTAG interface functions, this must not be called
391
         re-entrantly while a call to any other function (e.g. or1kim_run ())
392
         is in progress. It is the responsibility of the caller to ensure this
393
         constraint is met, for example by use of a SystemC mutex.
394
 
395
   @return  The time in seconds which the reset took.                        */
396
/*---------------------------------------------------------------------------*/
397
double
398
or1ksim_jtag_reset ()
399
{
400
  return  (double) jtag_reset () * (double) config.debug.jtagcycle_ps / 1.0e12;
401
 
402
}       /* or1ksim_jtag_reset () */
403
 
404
 
405
/*---------------------------------------------------------------------------*/
406
/*!Shift a JTAG instruction register
407
 
408
   @note Like all the JTAG interface functions, this must not be called
409
         re-entrantly while a call to any other function (e.g. or1kim_run ())
410
         is in progress. It is the responsibility of the caller to ensure this
411
         constraint is met, for example by use of a SystemC mutex.
412
 
413
   The register is represented as a vector of bytes, with the byte at offset
414
   zero being shifted first, and the least significant bit in each byte being
415
   shifted first. Where the register will not fit in an exact number of bytes,
416
   the odd bits are in the highest numbered byte, shifted to the low end.
417
 
418
   The only JTAG instruction for which we have any significant behavior in
419
   this model is DEBUG. For completeness the register is parsed and a warning
420
   given if any register other than DEBUG is shifted.
421
 
422
   @param[in,out] jreg  The register to shift in, and the register shifted
423
                        back out.
424
 
425
   @return  The time in seconds which the shift took.                        */
426
/*---------------------------------------------------------------------------*/
427
double
428
or1ksim_jtag_shift_ir (unsigned char *jreg)
429
{
430
  return  (double) jtag_shift_ir (jreg) * (double) config.debug.jtagcycle_ps /
431
          1.0e12;
432
 
433
}       /* or1ksim_jtag_shift_ir () */
434
 
435
 
436
/*---------------------------------------------------------------------------*/
437
/*!Shift a JTAG data register
438
 
439
   @note Like all the JTAG interface functions, this must not be called
440
         re-entrantly while a call to any other function (e.g. or1kim_run ())
441
         is in progress. It is the responsibility of the caller to ensure this
442
         constraint is met, for example by use of a SystemC mutex.
443
 
444
   The register is represented as a vector of bytes, with the byte at offset
445
   zero being shifted first, and the least significant bit in each byte being
446
   shifted first. Where the register will not fit in an exact number of bytes,
447
   the odd bits are in the highest numbered byte, shifted to the low end.
448
 
449
   The register is parsed to determine which of the six possible register
450
   types it could be.
451
   - MODULE_SELECT
452
   - WRITE_COMMNAND
453
   - READ_COMMAND
454
   - GO_COMMAND
455
   - WRITE_CONTROL
456
   - READ_CONTROL
457
 
458
   @note In practice READ_COMMAND is not used. However the functionality is
459
         provided for future compatibility.
460
 
461
   @param[in,out] jreg  The register to shift in, and the register shifted
462
                        back out.
463
 
464
   @return  The time in seconds which the shift took.                        */
465
/*---------------------------------------------------------------------------*/
466
double
467
or1ksim_jtag_shift_dr (unsigned char *jreg)
468
{
469
  return  (double) jtag_shift_dr (jreg) * (double) config.debug.jtagcycle_ps /
470
          1.0e12;
471
 
472
}       /* or1ksim_jtag_shift_dr () */

powered by: WebSVN 2.1.0

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