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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [libtoplevel.c] - Blame information for rev 1771

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

Line No. Rev Author Line
1 1745 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 1748 jeremybenn
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25 1745 jeremybenn
 
26
 
27 1748 jeremybenn
/* Autoconf and/or portability configuration */
28
#include "config.h"
29
 
30 1745 jeremybenn
/* System includes */
31 1748 jeremybenn
#include <stdlib.h>
32 1745 jeremybenn
#include <unistd.h>
33 1748 jeremybenn
#include <signal.h>
34 1745 jeremybenn
 
35 1748 jeremybenn
/* Package includes */
36
#include "or1ksim.h"
37 1745 jeremybenn
#include "sim-config.h"
38 1748 jeremybenn
#include "toplevel-support.h"
39
#include "sched.h"
40 1745 jeremybenn
#include "execute.h"
41 1748 jeremybenn
#include "pic.h"
42 1745 jeremybenn
 
43
 
44 1748 jeremybenn
/*---------------------------------------------------------------------------*/
45
/*!Initialize the simulator.
46 1745 jeremybenn
 
47 1748 jeremybenn
   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 1745 jeremybenn
 
50 1748 jeremybenn
   @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 1745 jeremybenn
 
57 1748 jeremybenn
   @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 1745 jeremybenn
{
70 1757 jeremybenn
  int   dummy_argc;
71 1745 jeremybenn
  char *dummy_argv[4];
72
 
73 1757 jeremybenn
  /* Dummy argv array. Varies depending on whether an image file is
74
     specified. */
75 1745 jeremybenn
  dummy_argv[0] = "libsim";
76
  dummy_argv[1] = "-f";
77 1748 jeremybenn
  dummy_argv[2] = (char *) ((NULL != config_file) ? config_file : "sim.cfg");
78
  dummy_argv[3] = (char *) image_file;
79 1745 jeremybenn
 
80 1757 jeremybenn
  dummy_argc = (NULL == image_file) ? 3 : 4;
81
 
82 1745 jeremybenn
  /* Initialization copied from existing main() */
83 1748 jeremybenn
  srand (getpid ());
84
  init_defconfig ();
85
  reg_config_secs ();
86 1745 jeremybenn
 
87 1748 jeremybenn
  if (parse_args (dummy_argc, dummy_argv))
88
    {
89
      return OR1KSIM_RC_BADINIT;
90
    }
91 1745 jeremybenn
 
92 1748 jeremybenn
  config.sim.profile   = 0;      /* No profiling */
93 1745 jeremybenn
  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 1748 jeremybenn
  print_config ();              /* Will go eventually */
100
  signal (SIGINT, ctrl_c);      /* Not sure we want this really */
101 1745 jeremybenn
 
102 1748 jeremybenn
  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 1745 jeremybenn
 
108
  sim_init ();
109
 
110 1756 jeremybenn
  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 1745 jeremybenn
 
113 1748 jeremybenn
  return OR1KSIM_RC_OK;
114 1745 jeremybenn
 
115
}       /* or1ksim_init() */
116
 
117
 
118 1748 jeremybenn
/*---------------------------------------------------------------------------*/
119
/*!Run the simulator
120 1745 jeremybenn
 
121 1748 jeremybenn
   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 1745 jeremybenn
 
124 1748 jeremybenn
   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 1745 jeremybenn
 
130 1748 jeremybenn
   This is over-ridden if the call was for a negative duration, which means
131
   run forever!
132 1745 jeremybenn
 
133 1748 jeremybenn
   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 1745 jeremybenn
{
144 1756 jeremybenn
  const int  num_ints = sizeof (runtime.sim.ext_int_set) * 8;
145
 
146 1748 jeremybenn
  or1ksim_reset_duration (duration);
147 1745 jeremybenn
 
148
  /* Loop until we have done enough cycles (or forever if we had a negative
149 1748 jeremybenn
     duration) */
150
  while (duration < 0.0 || (runtime.sim.cycles < runtime.sim.end_cycles))
151
    {
152 1745 jeremybenn
 
153 1748 jeremybenn
      long long int time_start = runtime.sim.cycles;
154
      int i;                    /* Interrupt # */
155 1745 jeremybenn
 
156 1748 jeremybenn
      /* 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 1745 jeremybenn
 
161 1748 jeremybenn
      runtime.sim.mem_cycles = 0;
162 1745 jeremybenn
 
163 1748 jeremybenn
      if (cpu_clock ())
164
        {
165
          return OR1KSIM_RC_BRKPT;      /* Hit a breakpoint */
166
        }
167 1745 jeremybenn
 
168 1748 jeremybenn
      runtime.sim.cycles += runtime.sim.mem_cycles;
169 1745 jeremybenn
 
170 1756 jeremybenn
      /* Take any external interrupts. Outer test is for the common case for
171 1748 jeremybenn
         efficiency. */
172 1756 jeremybenn
      if (0 != runtime.sim.ext_int_set)
173 1748 jeremybenn
        {
174 1756 jeremybenn
          for (i = 0; i < num_ints; i++)
175 1748 jeremybenn
            {
176 1756 jeremybenn
              if (0x1 == ((runtime.sim.ext_int_set >> i) & 0x1))
177 1748 jeremybenn
                {
178
                  report_interrupt (i);
179 1756 jeremybenn
                  runtime.sim.ext_int_set &= ~(1 << i); /* Clear req flag */
180 1748 jeremybenn
                }
181
            }
182 1745 jeremybenn
        }
183
 
184 1756 jeremybenn
      /* 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 1748 jeremybenn
      /* Update the scheduler queue */
201 1745 jeremybenn
 
202 1748 jeremybenn
      scheduler.job_queue->time -= (runtime.sim.cycles - time_start);
203 1745 jeremybenn
 
204 1748 jeremybenn
      if (scheduler.job_queue->time <= 0)
205
        {
206
          do_scheduler ();
207
        }
208 1745 jeremybenn
    }
209
 
210 1748 jeremybenn
  return  OR1KSIM_RC_OK;
211
 
212 1745 jeremybenn
}       /* or1ksim_run() */
213
 
214
 
215 1748 jeremybenn
/*---------------------------------------------------------------------------*/
216
/*!Reset the run-time simulation end point
217 1745 jeremybenn
 
218 1748 jeremybenn
  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 1745 jeremybenn
{
226 1748 jeremybenn
  runtime.sim.end_cycles =
227 1745 jeremybenn
    runtime.sim.cycles +
228 1748 jeremybenn
    (long long int) (duration * 1.0e12 / (double) config.sim.clkcycle_ps);
229 1745 jeremybenn
 
230
}       /* or1ksim_reset_duration() */
231
 
232
 
233 1748 jeremybenn
/*---------------------------------------------------------------------------*/
234
/*!Return time executed so far
235 1745 jeremybenn
 
236 1748 jeremybenn
   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 1745 jeremybenn
{
244 1748 jeremybenn
  return (double) runtime.sim.cycles * (double) config.sim.clkcycle_ps /
245
    1.0e12;
246 1745 jeremybenn
 
247
}       // or1ksim_cycle_count()
248
 
249
 
250 1748 jeremybenn
/*---------------------------------------------------------------------------*/
251
/*!Mark a time point in the simulation
252 1745 jeremybenn
 
253 1748 jeremybenn
   Sets the internal parameter recording this point in the simulation        */
254
/*---------------------------------------------------------------------------*/
255
void
256
or1ksim_set_time_point ()
257 1745 jeremybenn
{
258 1748 jeremybenn
  runtime.sim.time_point = internal_or1ksim_time ();
259 1745 jeremybenn
 
260
}       /* or1ksim_set_time_point() */
261
 
262
 
263 1748 jeremybenn
/*---------------------------------------------------------------------------*/
264
/*!Return the time since the time point was set
265 1745 jeremybenn
 
266 1748 jeremybenn
  Get the value from the internal parameter                                  */
267
/*---------------------------------------------------------------------------*/
268
double
269
or1ksim_get_time_period ()
270 1745 jeremybenn
{
271 1748 jeremybenn
  return internal_or1ksim_time () - runtime.sim.time_point;
272 1745 jeremybenn
 
273
}       /* or1ksim_get_time_period() */
274
 
275
 
276 1748 jeremybenn
/*---------------------------------------------------------------------------*/
277
/*!Return the endianism of the model
278 1745 jeremybenn
 
279 1748 jeremybenn
   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 1745 jeremybenn
{
286 1751 jeremybenn
#ifdef OR32_BIG_ENDIAN
287 1745 jeremybenn
  return 0;
288
#else
289
  return 1;
290
#endif
291
 
292 1748 jeremybenn
}       /* or1ksim_is_le() */
293 1745 jeremybenn
 
294
 
295 1748 jeremybenn
/*---------------------------------------------------------------------------*/
296
/*!Return the clock rate
297 1745 jeremybenn
 
298 1748 jeremybenn
   Value is part of the configuration
299
 
300
   @return  Clock rate in Hz.                                                */
301
/*---------------------------------------------------------------------------*/
302
unsigned long int
303
or1ksim_clock_rate ()
304 1745 jeremybenn
{
305 1748 jeremybenn
  return (unsigned long int) (1000000000000ULL /
306
                              (unsigned long long int) (config.sim.
307
                                                        clkcycle_ps));
308
}       /* or1ksim_clock_rate() */
309 1745 jeremybenn
 
310
 
311 1748 jeremybenn
/*---------------------------------------------------------------------------*/
312 1756 jeremybenn
/*!Trigger an edge triggered interrupt
313 1745 jeremybenn
 
314 1756 jeremybenn
   This function is appropriate for edge triggered interrupts, which are taken
315
   and then immediately cleared.
316 1745 jeremybenn
 
317 1756 jeremybenn
   @note There is no check that the specified interrupt number is reasonable
318
   (i.e. <= 31).
319
 
320 1748 jeremybenn
   @param[in] i  The interrupt number                                        */
321
/*---------------------------------------------------------------------------*/
322
void
323
or1ksim_interrupt (int i)
324 1745 jeremybenn
{
325 1756 jeremybenn
  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 1745 jeremybenn
 
337 1756 jeremybenn
 
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 1745 jeremybenn
}       /* or1ksim_interrupt() */
362 1756 jeremybenn
 
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.