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

Subversion Repositories openrisc

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

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
 
43
 
44
/*---------------------------------------------------------------------------*/
45
/*!Initialize the simulator.
46
 
47
   Allows specification of an (optional) config file and an image file. Builds
48
   up dummy argc/argv to pass to the existing argument parser.
49
 
50
   @param[in] config_file  Or1ksim configuration file name
51
   @param[in] image_file   The program image to execute
52
   @param[in] class_ptr    Pointer to a C++ class instance (for use when
53
                           called by C++)
54
   @param[in] upr          Upcall routine for reads
55
   @param[in] upw          Upcall routine for writes
56
 
57
   @return  0 on success and an error code on failure                        */
58
/*---------------------------------------------------------------------------*/
59
int
60
or1ksim_init (const char *config_file,
61
              const char *image_file,
62
              void       *class_ptr,
63
              unsigned long int (*upr) (void *class_ptr,
64
                                        unsigned long int addr,
65
                                        unsigned long int mask),
66
              void (*upw) (void *class_ptr,
67
                           unsigned long int addr,
68
                           unsigned long int mask, unsigned long int wdata))
69
{
70
  int   dummy_argc;
71
  char *dummy_argv[4];
72
 
73
  /* Dummy argv array. Varies depending on whether an image file is
74
     specified. */
75
  dummy_argv[0] = "libsim";
76
  dummy_argv[1] = "-f";
77
  dummy_argv[2] = (char *) ((NULL != config_file) ? config_file : "sim.cfg");
78
  dummy_argv[3] = (char *) image_file;
79
 
80
  dummy_argc = (NULL == image_file) ? 3 : 4;
81
 
82
  /* Initialization copied from existing main() */
83
  srand (getpid ());
84
  init_defconfig ();
85
  reg_config_secs ();
86
 
87
  if (parse_args (dummy_argc, dummy_argv))
88
    {
89
      return OR1KSIM_RC_BADINIT;
90
    }
91
 
92
  config.sim.profile   = 0;      /* No profiling */
93
  config.sim.mprofile  = 0;
94
 
95
  config.ext.class_ptr = class_ptr;     /* SystemC linkage */
96
  config.ext.read_up   = upr;
97
  config.ext.write_up  = upw;
98
 
99
  print_config ();              /* Will go eventually */
100
  signal (SIGINT, ctrl_c);      /* Not sure we want this really */
101
 
102
  runtime.sim.hush = 1;         /* Not sure if this is needed */
103
  do_stats = config.cpu.superscalar ||
104
             config.cpu.dependstats ||
105
             config.sim.history     ||
106
             config.sim.exe_log;
107
 
108
  sim_init ();
109
 
110
  runtime.sim.ext_int_set = 0;   /* No interrupts pending to be set */
111
  runtime.sim.ext_int_clr = 0;   /* No interrupts pending to be cleared */
112
 
113
  return OR1KSIM_RC_OK;
114
 
115
}       /* or1ksim_init() */
116
 
117
 
118
/*---------------------------------------------------------------------------*/
119
/*!Run the simulator
120
 
121
   The argument is a time in seconds, which is converted to a number of
122
   cycles, if positive. A negative value means "run for ever".
123
 
124
   The semantics are that the duration for which the run may occur may be
125
   changed mid-run by a call to or1ksim_reset_duration(). This is to allow for
126
   the upcalls to generic components adding time, and reducing the time
127
   permitted for ISS execution before synchronization of the parent SystemC
128
   wrapper.
129
 
130
   This is over-ridden if the call was for a negative duration, which means
131
   run forever!
132
 
133
   Uses a simplified version of the old main program loop. Returns success if
134
   the requested number of cycles were run and an error code otherwise.
135
 
136
   @param[in] duration  Time to execute for (seconds)
137
 
138
   @return  OR1KSIM_RC_OK if we run to completion, OR1KSIM_RC_BRKPT if we hit
139
            a breakpoint (not clear how this can be set without CLI access)  */
140
/*---------------------------------------------------------------------------*/
141
int
142
or1ksim_run (double duration)
143
{
144
  const int  num_ints = sizeof (runtime.sim.ext_int_set) * 8;
145
 
146
  or1ksim_reset_duration (duration);
147
 
148
  /* Loop until we have done enough cycles (or forever if we had a negative
149
     duration) */
150
  while (duration < 0.0 || (runtime.sim.cycles < runtime.sim.end_cycles))
151
    {
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
       * performed inbetween.
159
       */
160
 
161
      runtime.sim.mem_cycles = 0;
162
 
163
      if (cpu_clock ())
164
        {
165
          return OR1KSIM_RC_BRKPT;      /* Hit a breakpoint */
166
        }
167
 
168
      runtime.sim.cycles += runtime.sim.mem_cycles;
169
 
170
      /* Take any external interrupts. Outer test is for the common case for
171
         efficiency. */
172
      if (0 != runtime.sim.ext_int_set)
173
        {
174
          for (i = 0; i < num_ints; i++)
175
            {
176
              if (0x1 == ((runtime.sim.ext_int_set >> i) & 0x1))
177
                {
178
                  report_interrupt (i);
179
                  runtime.sim.ext_int_set &= ~(1 << i); /* Clear req flag */
180
                }
181
            }
182
        }
183
 
184
      /* Clear any interrupts as requested. For edge triggered interrupts this
185
         will happen in the same cycle. For level triggered, it must be an
186
         explicit call. */
187
      if (0 != runtime.sim.ext_int_clr)
188
        {
189
          for (i = 0; i < num_ints; i++)
190
            {
191
              /* Only clear interrupts that have been explicitly cleared */
192
              if(0x1 == ((runtime.sim.ext_int_clr >> i) & 0x1))
193
                {
194
                  clear_interrupt(i);
195
                  runtime.sim.ext_int_clr &= ~(1 << i); /* Clear clr flag */
196
                }
197
            }
198
        }
199
 
200
      /* Update the scheduler queue */
201
 
202
      scheduler.job_queue->time -= (runtime.sim.cycles - time_start);
203
 
204
      if (scheduler.job_queue->time <= 0)
205
        {
206
          do_scheduler ();
207
        }
208
    }
209
 
210
  return  OR1KSIM_RC_OK;
211
 
212
}       /* or1ksim_run() */
213
 
214
 
215
/*---------------------------------------------------------------------------*/
216
/*!Reset the run-time simulation end point
217
 
218
  Reset the time for which the simulation should run to the specified duration
219
  from NOW (i.e. NOT from when the run started).
220
 
221
  @param[in] duration  Time to run for in seconds                            */
222
/*---------------------------------------------------------------------------*/
223
void
224
or1ksim_reset_duration (double duration)
225
{
226
  runtime.sim.end_cycles =
227
    runtime.sim.cycles +
228
    (long long int) (duration * 1.0e12 / (double) config.sim.clkcycle_ps);
229
 
230
}       /* or1ksim_reset_duration() */
231
 
232
 
233
/*---------------------------------------------------------------------------*/
234
/*!Return time executed so far
235
 
236
   Internal utility to return the time executed so far. Note that this is a
237
   re-entrant routine.
238
 
239
   @return  Time executed so far in seconds                                  */
240
/*---------------------------------------------------------------------------*/
241
static double
242
internal_or1ksim_time ()
243
{
244
  return (double) runtime.sim.cycles * (double) config.sim.clkcycle_ps /
245
    1.0e12;
246
 
247
}       // or1ksim_cycle_count()
248
 
249
 
250
/*---------------------------------------------------------------------------*/
251
/*!Mark a time point in the simulation
252
 
253
   Sets the internal parameter recording this point in the simulation        */
254
/*---------------------------------------------------------------------------*/
255
void
256
or1ksim_set_time_point ()
257
{
258
  runtime.sim.time_point = internal_or1ksim_time ();
259
 
260
}       /* or1ksim_set_time_point() */
261
 
262
 
263
/*---------------------------------------------------------------------------*/
264
/*!Return the time since the time point was set
265
 
266
  Get the value from the internal parameter                                  */
267
/*---------------------------------------------------------------------------*/
268
double
269
or1ksim_get_time_period ()
270
{
271
  return internal_or1ksim_time () - runtime.sim.time_point;
272
 
273
}       /* or1ksim_get_time_period() */
274
 
275
 
276
/*---------------------------------------------------------------------------*/
277
/*!Return the endianism of the model
278
 
279
   Note that this is a re-entrant routine.
280
 
281
   @return 1 if the model is little endian, 0 otherwise.                     */
282
/*---------------------------------------------------------------------------*/
283
int
284
or1ksim_is_le ()
285
{
286
#ifdef OR32_BIG_ENDIAN
287
  return 0;
288
#else
289
  return 1;
290
#endif
291
 
292
}       /* or1ksim_is_le() */
293
 
294
 
295
/*---------------------------------------------------------------------------*/
296
/*!Return the clock rate
297
 
298
   Value is part of the configuration
299
 
300
   @return  Clock rate in Hz.                                                */
301
/*---------------------------------------------------------------------------*/
302
unsigned long int
303
or1ksim_clock_rate ()
304
{
305
  return (unsigned long int) (1000000000000ULL /
306
                              (unsigned long long int) (config.sim.
307
                                                        clkcycle_ps));
308
}       /* or1ksim_clock_rate() */
309
 
310
 
311
/*---------------------------------------------------------------------------*/
312
/*!Trigger an edge triggered interrupt
313
 
314
   This function is appropriate for edge triggered interrupts, which are taken
315
   and then immediately cleared.
316
 
317
   @note There is no check that the specified interrupt number is reasonable
318
   (i.e. <= 31).
319
 
320
   @param[in] i  The interrupt number                                        */
321
/*---------------------------------------------------------------------------*/
322
void
323
or1ksim_interrupt (int i)
324
{
325
  if (!config.pic.edge_trigger)
326
    {
327
      fprintf (stderr, "Warning: or1ksim_interrupt should not be used for "
328
               "edge triggered interrupts. Ignored\n");
329
    }
330
  else
331
    {
332
      runtime.sim.ext_int_set |= 1 << i;        // Better not be > 31!
333
      runtime.sim.ext_int_clr |= 1 << i;        // Better not be > 31!
334
    }
335
}       /* or1ksim_interrupt() */
336
 
337
 
338
/*---------------------------------------------------------------------------*/
339
/*!Set a level triggered interrupt
340
 
341
   This function is appropriate for level triggered interrupts, which must be
342
   explicitly cleared in a separate call.
343
 
344
   @note There is no check that the specified interrupt number is reasonable
345
   (i.e. <= 31).
346
 
347
   @param[in] i  The interrupt number to set                                 */
348
/*---------------------------------------------------------------------------*/
349
void
350
or1ksim_interrupt_set (int i)
351
{
352
  if (config.pic.edge_trigger)
353
    {
354
      fprintf (stderr, "Warning: or1ksim_interrupt_set should not be used for "
355
               "level triggered interrupts. Ignored\n");
356
    }
357
  else
358
    {
359
      runtime.sim.ext_int_set |= 1 << i;        // Better not be > 31!
360
    }
361
}       /* or1ksim_interrupt() */
362
 
363
 
364
/*---------------------------------------------------------------------------*/
365
/*!Clear a level triggered interrupt
366
 
367
   This function is appropriate for level triggered interrupts, which must be
368
   explicitly set first in a separate call.
369
 
370
   @note There is no check that the specified interrupt number is reasonable
371
   (i.e. <= 31).
372
 
373
   @param[in] i  The interrupt number to clear                               */
374
/*---------------------------------------------------------------------------*/
375
void
376
or1ksim_interrupt_clear (int i)
377
{
378
  if (config.pic.edge_trigger)
379
    {
380
      fprintf (stderr, "Warning: or1ksim_interrupt_clear should not be used "
381
               "for level triggered interrupts. Ignored\n");
382
    }
383
  else
384
    {
385
      runtime.sim.ext_int_clr |= 1 << i;        // Better not be > 31!
386
    }
387
}       /* or1ksim_interrupt() */

powered by: WebSVN 2.1.0

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