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

Subversion Repositories openrisc_me

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

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

powered by: WebSVN 2.1.0

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