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

Subversion Repositories openrisc

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

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
   The semantics are that the duration for which the run may occur may be
130
   changed mid-run by a call to or1ksim_reset_duration(). This is to allow for
131
   the upcalls to generic components adding time, and reducing the time
132
   permitted for ISS execution before synchronization of the parent SystemC
133
   wrapper.
134
 
135
   This is over-ridden if the call was for a negative duration, which means
136
   run forever!
137
 
138
   Uses a simplified version of the old main program loop. Returns success if
139
   the requested number of cycles were run and an error code otherwise.
140
 
141
   @param[in] duration  Time to execute for (seconds)
142
 
143
   @return  OR1KSIM_RC_OK if we run to completion, OR1KSIM_RC_BRKPT if we hit
144
            a breakpoint (not clear how this can be set without CLI access)  */
145
/*---------------------------------------------------------------------------*/
146
int
147
or1ksim_run (double duration)
148
{
149
  const int  num_ints = sizeof (runtime.sim.ext_int_set) * 8;
150
 
151
  or1ksim_reset_duration (duration);
152
 
153
  /* Loop until we have done enough cycles (or forever if we had a negative
154
     duration) */
155
  while (duration < 0.0 || (runtime.sim.cycles < runtime.sim.end_cycles))
156
    {
157
      long long int time_start = runtime.sim.cycles;
158
      int i;                    /* Interrupt # */
159
 
160
      /* Each cycle has counter of mem_cycles; this value is joined with cycles
161
       * at the end of the cycle; no sim originated memory accesses should be
162 82 jeremybenn
       * performed in between. */
163 19 jeremybenn
      runtime.sim.mem_cycles = 0;
164
 
165
      if (cpu_clock ())
166
        {
167
          return OR1KSIM_RC_BRKPT;      /* Hit a breakpoint */
168
        }
169
 
170
      runtime.sim.cycles += runtime.sim.mem_cycles;
171
 
172
      /* Take any external interrupts. Outer test is for the common case for
173
         efficiency. */
174
      if (0 != runtime.sim.ext_int_set)
175
        {
176
          for (i = 0; i < num_ints; i++)
177
            {
178
              if (0x1 == ((runtime.sim.ext_int_set >> i) & 0x1))
179
                {
180
                  report_interrupt (i);
181
                  runtime.sim.ext_int_set &= ~(1 << i); /* Clear req flag */
182
                }
183
            }
184
        }
185
 
186
      /* Clear any interrupts as requested. For edge triggered interrupts this
187
         will happen in the same cycle. For level triggered, it must be an
188
         explicit call. */
189
      if (0 != runtime.sim.ext_int_clr)
190
        {
191
          for (i = 0; i < num_ints; i++)
192
            {
193
              /* Only clear interrupts that have been explicitly cleared */
194
              if(0x1 == ((runtime.sim.ext_int_clr >> i) & 0x1))
195
                {
196
                  clear_interrupt(i);
197
                  runtime.sim.ext_int_clr &= ~(1 << i); /* Clear clr flag */
198
                }
199
            }
200
        }
201
 
202
      /* Update the scheduler queue */
203
      scheduler.job_queue->time -= (runtime.sim.cycles - time_start);
204
 
205
      if (scheduler.job_queue->time <= 0)
206
        {
207
          do_scheduler ();
208
        }
209
    }
210
 
211
  return  OR1KSIM_RC_OK;
212
 
213
}       /* or1ksim_run() */
214
 
215
 
216
/*---------------------------------------------------------------------------*/
217
/*!Reset the run-time simulation end point
218
 
219
  Reset the time for which the simulation should run to the specified duration
220
  from NOW (i.e. NOT from when the run started).
221
 
222
  @param[in] duration  Time to run for in seconds                            */
223
/*---------------------------------------------------------------------------*/
224
void
225
or1ksim_reset_duration (double duration)
226
{
227
  runtime.sim.end_cycles =
228
    runtime.sim.cycles +
229
    (long long int) (duration * 1.0e12 / (double) config.sim.clkcycle_ps);
230
 
231
}       /* or1ksim_reset_duration() */
232
 
233
 
234
/*---------------------------------------------------------------------------*/
235
/*!Return time executed so far
236
 
237
   Internal utility to return the time executed so far. Note that this is a
238
   re-entrant routine.
239
 
240
   @return  Time executed so far in seconds                                  */
241
/*---------------------------------------------------------------------------*/
242
static double
243
internal_or1ksim_time ()
244
{
245
  return (double) runtime.sim.cycles * (double) config.sim.clkcycle_ps /
246
    1.0e12;
247
 
248
}       // or1ksim_cycle_count()
249
 
250
 
251
/*---------------------------------------------------------------------------*/
252
/*!Mark a time point in the simulation
253
 
254
   Sets the internal parameter recording this point in the simulation        */
255
/*---------------------------------------------------------------------------*/
256
void
257
or1ksim_set_time_point ()
258
{
259
  runtime.sim.time_point = internal_or1ksim_time ();
260
 
261
}       /* or1ksim_set_time_point() */
262
 
263
 
264
/*---------------------------------------------------------------------------*/
265
/*!Return the time since the time point was set
266
 
267
  Get the value from the internal parameter                                  */
268
/*---------------------------------------------------------------------------*/
269
double
270
or1ksim_get_time_period ()
271
{
272
  return internal_or1ksim_time () - runtime.sim.time_point;
273
 
274
}       /* or1ksim_get_time_period() */
275
 
276
 
277
/*---------------------------------------------------------------------------*/
278
/*!Return the endianism of the model
279
 
280
   Note that this is a re-entrant routine.
281
 
282
   @return 1 if the model is little endian, 0 otherwise.                     */
283
/*---------------------------------------------------------------------------*/
284
int
285
or1ksim_is_le ()
286
{
287
#ifdef OR32_BIG_ENDIAN
288
  return 0;
289
#else
290
  return 1;
291
#endif
292
 
293
}       /* or1ksim_is_le() */
294
 
295
 
296
/*---------------------------------------------------------------------------*/
297
/*!Return the clock rate
298
 
299
   Value is part of the configuration
300
 
301
   @return  Clock rate in Hz.                                                */
302
/*---------------------------------------------------------------------------*/
303
unsigned long int
304
or1ksim_clock_rate ()
305
{
306
  return (unsigned long int) (1000000000000ULL /
307
                              (unsigned long long int) (config.sim.
308
                                                        clkcycle_ps));
309
}       /* or1ksim_clock_rate() */
310
 
311
 
312
/*---------------------------------------------------------------------------*/
313
/*!Trigger an edge triggered interrupt
314
 
315
   This function is appropriate for edge triggered interrupts, which are taken
316
   and then immediately cleared.
317
 
318
   @note There is no check that the specified interrupt number is reasonable
319
   (i.e. <= 31).
320
 
321
   @param[in] i  The interrupt number                                        */
322
/*---------------------------------------------------------------------------*/
323
void
324
or1ksim_interrupt (int i)
325
{
326
  if (!config.pic.edge_trigger)
327
    {
328
      fprintf (stderr, "Warning: or1ksim_interrupt should not be used for "
329 93 jeremybenn
               "level triggered interrupts. Ignored\n");
330 19 jeremybenn
    }
331
  else
332
    {
333
      runtime.sim.ext_int_set |= 1 << i;        // Better not be > 31!
334
      runtime.sim.ext_int_clr |= 1 << i;        // Better not be > 31!
335
    }
336
}       /* or1ksim_interrupt() */
337
 
338
 
339
/*---------------------------------------------------------------------------*/
340
/*!Set a level triggered interrupt
341
 
342
   This function is appropriate for level triggered interrupts, which must be
343
   explicitly cleared in a separate call.
344
 
345
   @note There is no check that the specified interrupt number is reasonable
346
   (i.e. <= 31).
347
 
348
   @param[in] i  The interrupt number to set                                 */
349
/*---------------------------------------------------------------------------*/
350
void
351
or1ksim_interrupt_set (int i)
352
{
353
  if (config.pic.edge_trigger)
354
    {
355
      fprintf (stderr, "Warning: or1ksim_interrupt_set should not be used for "
356 93 jeremybenn
               "edge triggered interrupts. Ignored\n");
357 19 jeremybenn
    }
358
  else
359
    {
360
      runtime.sim.ext_int_set |= 1 << i;        // Better not be > 31!
361
    }
362
}       /* or1ksim_interrupt() */
363
 
364
 
365
/*---------------------------------------------------------------------------*/
366
/*!Clear a level triggered interrupt
367
 
368
   This function is appropriate for level triggered interrupts, which must be
369
   explicitly set first in a separate call.
370
 
371
   @note There is no check that the specified interrupt number is reasonable
372
   (i.e. <= 31).
373
 
374
   @param[in] i  The interrupt number to clear                               */
375
/*---------------------------------------------------------------------------*/
376
void
377
or1ksim_interrupt_clear (int i)
378
{
379
  if (config.pic.edge_trigger)
380
    {
381
      fprintf (stderr, "Warning: or1ksim_interrupt_clear should not be used "
382 93 jeremybenn
               "for edge triggered interrupts. Ignored\n");
383 19 jeremybenn
    }
384
  else
385
    {
386
      runtime.sim.ext_int_clr |= 1 << i;        // Better not be > 31!
387
    }
388
}       /* or1ksim_interrupt() */
389 82 jeremybenn
 
390
 
391
/*---------------------------------------------------------------------------*/
392
/*!Reset the JTAG interface
393
 
394
   @note Like all the JTAG interface functions, this must not be called
395
         re-entrantly while a call to any other function (e.g. or1kim_run ())
396
         is in progress. It is the responsibility of the caller to ensure this
397
         constraint is met, for example by use of a SystemC mutex.
398
 
399
   @return  The time in seconds which the reset took.                        */
400
/*---------------------------------------------------------------------------*/
401
double
402
or1ksim_jtag_reset ()
403
{
404
  return  (double) jtag_reset () * (double) config.debug.jtagcycle_ps / 1.0e12;
405
 
406
}       /* or1ksim_jtag_reset () */
407
 
408
 
409
/*---------------------------------------------------------------------------*/
410
/*!Shift a JTAG instruction register
411
 
412
   @note Like all the JTAG interface functions, this must not be called
413
         re-entrantly while a call to any other function (e.g. or1kim_run ())
414
         is in progress. It is the responsibility of the caller to ensure this
415
         constraint is met, for example by use of a SystemC mutex.
416
 
417
   The register is represented as a vector of bytes, with the byte at offset
418
   zero being shifted first, and the least significant bit in each byte being
419
   shifted first. Where the register will not fit in an exact number of bytes,
420
   the odd bits are in the highest numbered byte, shifted to the low end.
421
 
422
   The only JTAG instruction for which we have any significant behavior in
423
   this model is DEBUG. For completeness the register is parsed and a warning
424
   given if any register other than DEBUG is shifted.
425
 
426
   @param[in,out] jreg  The register to shift in, and the register shifted
427
                        back out.
428
 
429
   @return  The time in seconds which the shift took.                        */
430
/*---------------------------------------------------------------------------*/
431
double
432
or1ksim_jtag_shift_ir (unsigned char *jreg)
433
{
434
  return  (double) jtag_shift_ir (jreg) * (double) config.debug.jtagcycle_ps /
435
          1.0e12;
436
 
437
}       /* or1ksim_jtag_shift_ir () */
438
 
439
 
440
/*---------------------------------------------------------------------------*/
441
/*!Shift a JTAG data register
442
 
443
   @note Like all the JTAG interface functions, this must not be called
444
         re-entrantly while a call to any other function (e.g. or1kim_run ())
445
         is in progress. It is the responsibility of the caller to ensure this
446
         constraint is met, for example by use of a SystemC mutex.
447
 
448
   The register is represented as a vector of bytes, with the byte at offset
449
   zero being shifted first, and the least significant bit in each byte being
450
   shifted first. Where the register will not fit in an exact number of bytes,
451
   the odd bits are in the highest numbered byte, shifted to the low end.
452
 
453
   The register is parsed to determine which of the six possible register
454
   types it could be.
455
   - MODULE_SELECT
456
   - WRITE_COMMNAND
457
   - READ_COMMAND
458
   - GO_COMMAND
459
   - WRITE_CONTROL
460
   - READ_CONTROL
461
 
462
   @note In practice READ_COMMAND is not used. However the functionality is
463
         provided for future compatibility.
464
 
465
   @param[in,out] jreg  The register to shift in, and the register shifted
466
                        back out.
467
 
468
   @return  The time in seconds which the shift took.                        */
469
/*---------------------------------------------------------------------------*/
470
double
471
or1ksim_jtag_shift_dr (unsigned char *jreg)
472
{
473
  return  (double) jtag_shift_dr (jreg) * (double) config.debug.jtagcycle_ps /
474
          1.0e12;
475
 
476
}       /* or1ksim_jtag_shift_dr () */

powered by: WebSVN 2.1.0

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