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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [common/] [sim-events.c] - Blame information for rev 1771

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

Line No. Rev Author Line
1 578 markom
/*  This file is part of the program psim.
2
 
3
    Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
4
 
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 
19
    */
20
 
21
 
22
#ifndef _SIM_EVENTS_C_
23
#define _SIM_EVENTS_C_
24
 
25
#include "sim-main.h"
26
#include "sim-assert.h"
27
 
28
#ifdef HAVE_STRING_H
29
#include <string.h>
30
#else
31
#ifdef HAVE_STRINGS_H
32
#include <strings.h>
33
#endif
34
#endif
35
 
36
#ifdef HAVE_STDLIB_H
37
#include <stdlib.h>
38
#endif
39
 
40
#include <signal.h> /* For SIGPROCMASK et.al. */
41
 
42
typedef enum {
43
  watch_invalid,
44
 
45
  /* core - target byte order */
46
  watch_core_targ_1,
47
  watch_core_targ_2,
48
  watch_core_targ_4,
49
  watch_core_targ_8,
50
  /* core - big-endian */
51
  watch_core_be_1,
52
  watch_core_be_2,
53
  watch_core_be_4,
54
  watch_core_be_8,
55
  /* core - little-endian */
56
  watch_core_le_1,
57
  watch_core_le_2,
58
  watch_core_le_4,
59
  watch_core_le_8,
60
 
61
  /* sim - host byte order */
62
  watch_sim_host_1,
63
  watch_sim_host_2,
64
  watch_sim_host_4,
65
  watch_sim_host_8,
66
  /* sim - big-endian */
67
  watch_sim_be_1,
68
  watch_sim_be_2,
69
  watch_sim_be_4,
70
  watch_sim_be_8,
71
  /* sim - little-endian */
72
  watch_sim_le_1,
73
  watch_sim_le_2,
74
  watch_sim_le_4,
75
  watch_sim_le_8,
76
 
77
  /* wallclock */
78
  watch_clock,
79
 
80
  /* timer */
81
  watch_timer,
82
} sim_event_watchpoints;
83
 
84
 
85
struct _sim_event {
86
  sim_event_watchpoints watching;
87
  void *data;
88
  sim_event_handler *handler;
89
  /* timer event */
90
  signed64 time_of_event;
91
  /* watch wallclock event */
92
  unsigned wallclock;
93
  /* watch core address */
94
  address_word core_addr;
95
  unsigned core_map;
96
  /* watch sim addr */
97
  void *host_addr;
98
  /* watch core/sim range */
99
  int is_within; /* 0/1 */
100
  unsigned ub;
101
  unsigned lb;
102
  unsigned64 ub64;
103
  unsigned64 lb64;
104
  /* trace info (if any) */
105
  char *trace;
106
  /* list */
107
  sim_event *next;
108
};
109
 
110
 
111
/* The event queue maintains a single absolute time using two
112
   variables.
113
 
114
   TIME_OF_EVENT: this holds the time at which the next event is ment
115
   to occure.  If no next event it will hold the time of the last
116
   event.
117
 
118
   TIME_FROM_EVENT: The current distance from TIME_OF_EVENT.  A value
119
   <= 0 (except when poll-event is being processed) indicates that
120
   event processing is due.  This variable is decremented once for
121
   each iteration of a clock cycle.
122
 
123
   Initially, the clock is started at time one (0) with TIME_OF_EVENT
124
   == 0 and TIME_FROM_EVENT == 0 and with NR_TICKS_TO_PROCESS == 1.
125
 
126
   Clearly there is a bug in that this code assumes that the absolute
127
   time counter will never become greater than 2^62.
128
 
129
   To avoid the need to use 64bit arithmetic, the event queue always
130
   contains at least one event scheduled every 16 000 ticks.  This
131
   limits the time from event counter to values less than
132
   16 000. */
133
 
134
 
135
#if !defined (SIM_EVENTS_POLL_RATE)
136
#define SIM_EVENTS_POLL_RATE 0x1000
137
#endif
138
 
139
 
140
#define _ETRACE sd, NULL
141
 
142
#undef ETRACE_P
143
#define ETRACE_P (WITH_TRACE && STATE_EVENTS (sd)->trace)
144
 
145
#undef ETRACE
146
#define ETRACE(ARGS) \
147
do \
148
  { \
149
    if (ETRACE_P) \
150
      { \
151
        if (STRACE_DEBUG_P (sd)) \
152
          { \
153
            const char *file; \
154
            SIM_FILTER_PATH (file, __FILE__); \
155
            trace_printf (sd, NULL, "%s:%d: ", file, __LINE__); \
156
          } \
157
        trace_printf  ARGS; \
158
      } \
159
  } \
160
while (0)
161
 
162
 
163
/* event queue iterator - don't iterate over the held queue. */
164
 
165
#if EXTERN_SIM_EVENTS_P
166
static sim_event **
167
next_event_queue (SIM_DESC sd,
168
                  sim_event **queue)
169
{
170
  if (queue == NULL)
171
    return &STATE_EVENTS (sd)->queue;
172
  else if (queue == &STATE_EVENTS (sd)->queue)
173
    return &STATE_EVENTS (sd)->watchpoints;
174
  else if (queue == &STATE_EVENTS (sd)->watchpoints)
175
    return &STATE_EVENTS (sd)->watchedpoints;
176
  else if (queue == &STATE_EVENTS (sd)->watchedpoints)
177
    return NULL;
178
  else
179
    sim_io_error (sd, "next_event_queue - bad queue");
180
  return NULL;
181
}
182
#endif
183
 
184
 
185
STATIC_INLINE_SIM_EVENTS\
186
(void)
187
sim_events_poll (SIM_DESC sd,
188
                 void *data)
189
{
190
  /* just re-schedule in 1000 million ticks time */
191
  sim_events_schedule (sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
192
  sim_io_poll_quit (sd);
193
}
194
 
195
 
196
/* "events" module install handler.
197
   This is called via sim_module_install to install the "events" subsystem
198
   into the simulator.  */
199
 
200
#if EXTERN_SIM_EVENTS_P
201
STATIC_SIM_EVENTS (MODULE_UNINSTALL_FN) sim_events_uninstall;
202
STATIC_SIM_EVENTS (MODULE_INIT_FN) sim_events_init;
203
STATIC_SIM_EVENTS (MODULE_RESUME_FN) sim_events_resume;
204
STATIC_SIM_EVENTS (MODULE_SUSPEND_FN) sim_events_suspend;
205
#endif
206
 
207
#if EXTERN_SIM_EVENTS_P
208
SIM_RC
209
sim_events_install (SIM_DESC sd)
210
{
211
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
212
  sim_module_add_uninstall_fn (sd, sim_events_uninstall);
213
  sim_module_add_init_fn (sd, sim_events_init);
214
  sim_module_add_resume_fn (sd, sim_events_resume);
215
  sim_module_add_suspend_fn (sd, sim_events_suspend);
216
  return SIM_RC_OK;
217
}
218
#endif
219
 
220
 
221
/* Suspend/resume the event queue manager when the simulator is not
222
   running */
223
 
224
#if EXTERN_SIM_EVENTS_P
225
static SIM_RC
226
sim_events_resume (SIM_DESC sd)
227
{
228
  sim_events *events = STATE_EVENTS (sd);
229
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
230
  SIM_ASSERT (events->resume_wallclock == 0);
231
  events->resume_wallclock = sim_elapsed_time_get ();
232
  return SIM_RC_OK;
233
}
234
#endif
235
 
236
#if EXTERN_SIM_EVENTS_P
237
static SIM_RC
238
sim_events_suspend (SIM_DESC sd)
239
{
240
  sim_events *events = STATE_EVENTS (sd);
241
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
242
  SIM_ASSERT (events->resume_wallclock != 0);
243
  events->elapsed_wallclock += sim_elapsed_time_since (events->resume_wallclock);
244
  events->resume_wallclock = 0;
245
  return SIM_RC_OK;
246
}
247
#endif
248
 
249
 
250
/* Uninstall the "events" subsystem from the simulator.  */
251
 
252
#if EXTERN_SIM_EVENTS_P
253
static void
254
sim_events_uninstall (SIM_DESC sd)
255
{
256
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
257
  /* FIXME: free buffers, etc. */
258
}
259
#endif
260
 
261
 
262
/* malloc/free */
263
 
264
#if EXTERN_SIM_EVENTS_P
265
static sim_event *
266
sim_events_zalloc (SIM_DESC sd)
267
{
268
  sim_events *events = STATE_EVENTS (sd);
269
  sim_event *new = events->free_list;
270
  if (new != NULL)
271
    {
272
      events->free_list = new->next;
273
      memset (new, 0, sizeof (*new));
274
    }
275
  else
276
    {
277
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
278
      /*-LOCK-*/
279
      sigset_t old_mask;
280
      sigset_t new_mask;
281
      sigfillset(&new_mask);
282
      sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
283
#endif
284
      new = ZALLOC (sim_event);
285
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
286
      /*-UNLOCK-*/
287
      sigprocmask (SIG_SETMASK, &old_mask, NULL);
288
#endif
289
    }
290
  return new;
291
}
292
#endif
293
 
294
STATIC_INLINE_SIM_EVENTS\
295
(void)
296
sim_events_free (SIM_DESC sd,
297
                 sim_event *dead)
298
{
299
  sim_events *events = STATE_EVENTS (sd);
300
  dead->next = events->free_list;
301
  events->free_list = dead;
302
  if (dead->trace != NULL)
303
    {
304
      free (dead->trace); /* NB: asprintf returns a `free' buf */
305
      dead->trace = NULL;
306
    }
307
}
308
 
309
 
310
/* Initialize the simulator event manager */
311
 
312
#if EXTERN_SIM_EVENTS_P
313
SIM_RC
314
sim_events_init (SIM_DESC sd)
315
{
316
  sim_events *events = STATE_EVENTS (sd);
317
 
318
  /* drain the interrupt queue */
319
  events->nr_held = 0;
320
  if (events->held == NULL)
321
    events->held = NZALLOC (sim_event, MAX_NR_SIGNAL_SIM_EVENTS);
322
 
323
  /* drain the normal queues */
324
  {
325
    sim_event **queue = NULL;
326
    while ((queue = next_event_queue (sd, queue)) != NULL)
327
      {
328
        if (queue == NULL) break;
329
        while (*queue != NULL)
330
          {
331
            sim_event *dead = *queue;
332
            *queue = dead->next;
333
            sim_events_free (sd, dead);
334
          }
335
        *queue = NULL;
336
      }
337
  }
338
 
339
  /* wind time back to zero */
340
  events->nr_ticks_to_process = 1; /* start by doing queue */
341
  events->time_of_event = 0;
342
  events->time_from_event = 0;
343
  events->elapsed_wallclock = 0;
344
  events->resume_wallclock = 0;
345
 
346
  /* schedule our initial counter event */
347
  sim_events_schedule (sd, 0, sim_events_poll, sd);
348
 
349
  /* from now on, except when the large-int event is being processed
350
     the event queue is non empty */
351
  SIM_ASSERT (events->queue != NULL);
352
 
353
  return SIM_RC_OK;
354
}
355
#endif
356
 
357
 
358
INLINE_SIM_EVENTS\
359
(signed64)
360
sim_events_time (SIM_DESC sd)
361
{
362
  sim_events *events = STATE_EVENTS (sd);
363
  return (events->time_of_event - events->time_from_event);
364
}
365
 
366
 
367
INLINE_SIM_EVENTS\
368
(unsigned long)
369
sim_events_elapsed_time (SIM_DESC sd)
370
{
371
  unsigned long elapsed = STATE_EVENTS (sd)->elapsed_wallclock;
372
 
373
  /* Are we being called inside sim_resume?
374
     (Is there a simulation in progress?)  */
375
  if (STATE_EVENTS (sd)->resume_wallclock != 0)
376
     elapsed += sim_elapsed_time_since (STATE_EVENTS (sd)->resume_wallclock);
377
 
378
  return elapsed;
379
}
380
 
381
 
382
/* Returns the time that remains before the event is raised. */
383
INLINE_SIM_EVENTS\
384
(signed64)
385
sim_events_remain_time (SIM_DESC sd, sim_event *event)
386
{
387
  if (event == 0)
388
    return 0;
389
 
390
  return (event->time_of_event - sim_events_time (sd));
391
}
392
 
393
 
394
 
395
STATIC_INLINE_SIM_EVENTS\
396
(void)
397
update_time_from_event (SIM_DESC sd)
398
{
399
  sim_events *events = STATE_EVENTS (sd);
400
  signed64 current_time = sim_events_time (sd);
401
  if (events->queue != NULL)
402
    {
403
      events->time_of_event = events->queue->time_of_event;
404
      events->time_from_event = (events->queue->time_of_event - current_time);
405
    }
406
  else
407
    {
408
      events->time_of_event = current_time - 1;
409
      events->time_from_event = -1;
410
    }
411
  if (ETRACE_P)
412
    {
413
      sim_event *event;
414
      int i;
415
      for (event = events->queue, i = 0;
416
           event != NULL;
417
           event = event->next, i++)
418
        {
419
          ETRACE ((_ETRACE,
420
                   "event time-from-event - time %ld, delta %ld - event %d, tag 0x%lx, time %ld, handler 0x%lx, data 0x%lx%s%s\n",
421
                   (long)current_time,
422
                   (long)events->time_from_event,
423
                   i,
424
                   (long)event,
425
                   (long)event->time_of_event,
426
                   (long)event->handler,
427
                   (long)event->data,
428
                   (event->trace != NULL) ? ", " : "",
429
                   (event->trace != NULL) ? event->trace : ""));
430
        }
431
    }
432
  SIM_ASSERT (current_time == sim_events_time (sd));
433
}
434
 
435
 
436
#if EXTERN_SIM_EVENTS_P
437
static void
438
insert_sim_event (SIM_DESC sd,
439
                  sim_event *new_event,
440
                  signed64 delta)
441
{
442
  sim_events *events = STATE_EVENTS (sd);
443
  sim_event *curr;
444
  sim_event **prev;
445
  signed64 time_of_event;
446
 
447
  if (delta < 0)
448
    sim_io_error (sd, "what is past is past!\n");
449
 
450
  /* compute when the event should occure */
451
  time_of_event = sim_events_time (sd) + delta;
452
 
453
  /* find the queue insertion point - things are time ordered */
454
  prev = &events->queue;
455
  curr = events->queue;
456
  while (curr != NULL && time_of_event >= curr->time_of_event)
457
    {
458
      SIM_ASSERT (curr->next == NULL
459
                  || curr->time_of_event <= curr->next->time_of_event);
460
      prev = &curr->next;
461
      curr = curr->next;
462
    }
463
  SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
464
 
465
  /* insert it */
466
  new_event->next = curr;
467
  *prev = new_event;
468
  new_event->time_of_event = time_of_event;
469
 
470
  /* adjust the time until the first event */
471
  update_time_from_event (sd);
472
}
473
#endif
474
 
475
 
476
#if EXTERN_SIM_EVENTS_P
477
sim_event *
478
sim_events_schedule (SIM_DESC sd,
479
                     signed64 delta_time,
480
                     sim_event_handler *handler,
481
                     void *data)
482
{
483
  va_list dummy;
484
  return sim_events_schedule_vtracef (sd, delta_time, handler, data,
485
                                      NULL, dummy);
486
}
487
#endif
488
 
489
 
490
#if EXTERN_SIM_EVENTS_P
491
sim_event *
492
sim_events_schedule_tracef (SIM_DESC sd,
493
                            signed64 delta_time,
494
                            sim_event_handler *handler,
495
                            void *data,
496
                            const char *fmt,
497
                            ...)
498
{
499
  sim_event *new_event;
500
  va_list ap;
501
  va_start (ap, fmt);
502
  new_event = sim_events_schedule_vtracef (sd, delta_time, handler, data, fmt, ap);
503
  va_end (ap);
504
  return new_event;
505
}
506
#endif
507
 
508
 
509
#if EXTERN_SIM_EVENTS_P
510
sim_event *
511
sim_events_schedule_vtracef (SIM_DESC sd,
512
                             signed64 delta_time,
513
                             sim_event_handler *handler,
514
                             void *data,
515
                             const char *fmt,
516
                             va_list ap)
517
{
518
  sim_event *new_event = sim_events_zalloc (sd);
519
  new_event->data = data;
520
  new_event->handler = handler;
521
  new_event->watching = watch_timer;
522
  if (fmt == NULL || !ETRACE_P || vasprintf (&new_event->trace, fmt, ap) < 0)
523
    new_event->trace = NULL;
524
  insert_sim_event(sd, new_event, delta_time);
525
  ETRACE((_ETRACE,
526
          "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
527
          (long)sim_events_time(sd),
528
          (long)new_event,
529
          (long)new_event->time_of_event,
530
          (long)new_event->handler,
531
          (long)new_event->data,
532
          (new_event->trace != NULL) ? ", " : "",
533
          (new_event->trace != NULL) ? new_event->trace : ""));
534
  return new_event;
535
}
536
#endif
537
 
538
 
539
#if EXTERN_SIM_EVENTS_P
540
void
541
sim_events_schedule_after_signal (SIM_DESC sd,
542
                                  signed64 delta_time,
543
                                  sim_event_handler *handler,
544
                                  void *data)
545
{
546
  sim_events *events = STATE_EVENTS (sd);
547
  sim_event *new_event;
548
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
549
  /*-LOCK-*/
550
  sigset_t old_mask;
551
  sigset_t new_mask;
552
  sigfillset(&new_mask);
553
  sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
554
#endif
555
 
556
  /* allocate an event entry from the signal buffer */
557
  new_event = &events->held [events->nr_held];
558
  events->nr_held ++;
559
  if (events->nr_held > MAX_NR_SIGNAL_SIM_EVENTS)
560
    {
561
      sim_engine_abort (NULL, NULL, NULL_CIA,
562
                        "sim_events_schedule_after_signal - buffer oveflow");
563
    }
564
 
565
  new_event->data = data;
566
  new_event->handler = handler;
567
  new_event->time_of_event = delta_time; /* work it out later */
568
  new_event->next = NULL;
569
 
570
  events->work_pending = 1; /* notify main process */
571
 
572
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
573
  /*-UNLOCK-*/
574
  sigprocmask (SIG_SETMASK, &old_mask, NULL);
575
#endif
576
 
577
  ETRACE ((_ETRACE,
578
           "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
579
           (long)sim_events_time(sd),
580
           (long)new_event,
581
           (long)new_event->time_of_event,
582
           (long)new_event->handler,
583
           (long)new_event->data));
584
}
585
#endif
586
 
587
 
588
#if EXTERN_SIM_EVENTS_P
589
sim_event *
590
sim_events_watch_clock (SIM_DESC sd,
591
                        unsigned delta_ms_time,
592
                        sim_event_handler *handler,
593
                        void *data)
594
{
595
  sim_events *events = STATE_EVENTS (sd);
596
  sim_event *new_event = sim_events_zalloc (sd);
597
  /* type */
598
  new_event->watching = watch_clock;
599
  /* handler */
600
  new_event->data = data;
601
  new_event->handler = handler;
602
  /* data */
603
  if (events->resume_wallclock == 0)
604
    new_event->wallclock = (events->elapsed_wallclock + delta_ms_time);
605
  else
606
    new_event->wallclock = (events->elapsed_wallclock
607
                            + sim_elapsed_time_since (events->resume_wallclock)
608
                            + delta_ms_time);
609
  /* insert */
610
  new_event->next = events->watchpoints;
611
  events->watchpoints = new_event;
612
  events->work_pending = 1;
613
  ETRACE ((_ETRACE,
614
          "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
615
           (long)sim_events_time (sd),
616
           (long)new_event,
617
           (long)new_event->wallclock,
618
           (long)new_event->handler,
619
           (long)new_event->data));
620
  return new_event;
621
}
622
#endif
623
 
624
 
625
#if EXTERN_SIM_EVENTS_P
626
sim_event *
627
sim_events_watch_sim (SIM_DESC sd,
628
                      void *host_addr,
629
                      int nr_bytes,
630
                      int byte_order,
631
                      int is_within,
632
                      unsigned64 lb,
633
                      unsigned64 ub,
634
                      sim_event_handler *handler,
635
                      void *data)
636
{
637
  sim_events *events = STATE_EVENTS (sd);
638
  sim_event *new_event = sim_events_zalloc (sd);
639
  /* type */
640
  switch (byte_order)
641
    {
642
    case 0:
643
      switch (nr_bytes)
644
        {
645
        case 1: new_event->watching = watch_sim_host_1; break;
646
        case 2: new_event->watching = watch_sim_host_2; break;
647
        case 4: new_event->watching = watch_sim_host_4; break;
648
        case 8: new_event->watching = watch_sim_host_8; break;
649
        default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
650
        }
651
      break;
652
    case BIG_ENDIAN:
653
      switch (nr_bytes)
654
        {
655
        case 1: new_event->watching = watch_sim_be_1; break;
656
        case 2: new_event->watching = watch_sim_be_2; break;
657
        case 4: new_event->watching = watch_sim_be_4; break;
658
        case 8: new_event->watching = watch_sim_be_8; break;
659
        default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
660
        }
661
      break;
662
    case LITTLE_ENDIAN:
663
      switch (nr_bytes)
664
        {
665
        case 1: new_event->watching = watch_sim_le_1; break;
666
        case 2: new_event->watching = watch_sim_le_2; break;
667
        case 4: new_event->watching = watch_sim_le_4; break;
668
        case 8: new_event->watching = watch_sim_le_8; break;
669
        default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
670
        }
671
      break;
672
    default:
673
      sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
674
    }
675
  /* handler */
676
  new_event->data = data;
677
  new_event->handler = handler;
678
  /* data */
679
  new_event->host_addr = host_addr;
680
  new_event->lb = lb;
681
  new_event->lb64 = lb;
682
  new_event->ub = ub;
683
  new_event->ub64 = ub;
684
  new_event->is_within = (is_within != 0);
685
  /* insert */
686
  new_event->next = events->watchpoints;
687
  events->watchpoints = new_event;
688
  events->work_pending = 1;
689
  ETRACE ((_ETRACE,
690
           "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
691
           (long)sim_events_time (sd),
692
           (long)new_event,
693
           (long)new_event->host_addr,
694
           (long)new_event->lb,
695
           (long)new_event->ub,
696
           (long)new_event->handler,
697
           (long)new_event->data));
698
  return new_event;
699
}
700
#endif
701
 
702
 
703
#if EXTERN_SIM_EVENTS_P
704
sim_event *
705
sim_events_watch_core (SIM_DESC sd,
706
                       address_word core_addr,
707
                       unsigned core_map,
708
                       int nr_bytes,
709
                       int byte_order,
710
                       int is_within,
711
                       unsigned64 lb,
712
                       unsigned64 ub,
713
                       sim_event_handler *handler,
714
                       void *data)
715
{
716
  sim_events *events = STATE_EVENTS (sd);
717
  sim_event *new_event = sim_events_zalloc (sd);
718
  /* type */
719
  switch (byte_order)
720
    {
721
    case 0:
722
      switch (nr_bytes)
723
        {
724
        case 1: new_event->watching = watch_core_targ_1; break;
725
        case 2: new_event->watching = watch_core_targ_2; break;
726
        case 4: new_event->watching = watch_core_targ_4; break;
727
        case 8: new_event->watching = watch_core_targ_8; break;
728
        default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
729
        }
730
      break;
731
    case BIG_ENDIAN:
732
      switch (nr_bytes)
733
        {
734
        case 1: new_event->watching = watch_core_be_1; break;
735
        case 2: new_event->watching = watch_core_be_2; break;
736
        case 4: new_event->watching = watch_core_be_4; break;
737
        case 8: new_event->watching = watch_core_be_8; break;
738
        default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
739
        }
740
      break;
741
    case LITTLE_ENDIAN:
742
      switch (nr_bytes)
743
        {
744
        case 1: new_event->watching = watch_core_le_1; break;
745
        case 2: new_event->watching = watch_core_le_2; break;
746
        case 4: new_event->watching = watch_core_le_4; break;
747
        case 8: new_event->watching = watch_core_le_8; break;
748
        default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
749
        }
750
      break;
751
    default:
752
      sim_io_error (sd, "sim_events_watch_core - invalid byte order");
753
    }
754
  /* handler */
755
  new_event->data = data;
756
  new_event->handler = handler;
757
  /* data */
758
  new_event->core_addr = core_addr;
759
  new_event->core_map = core_map;
760
  new_event->lb = lb;
761
  new_event->lb64 = lb;
762
  new_event->ub = ub;
763
  new_event->ub64 = ub;
764
  new_event->is_within = (is_within != 0);
765
  /* insert */
766
  new_event->next = events->watchpoints;
767
  events->watchpoints = new_event;
768
  events->work_pending = 1;
769
  ETRACE ((_ETRACE,
770
           "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
771
           (long)sim_events_time (sd),
772
           (long)new_event,
773
           (long)new_event->host_addr,
774
           (long)new_event->lb,
775
           (long)new_event->ub,
776
           (long)new_event->handler,
777
           (long)new_event->data));
778
  return new_event;
779
}
780
#endif
781
 
782
 
783
#if EXTERN_SIM_EVENTS_P
784
void
785
sim_events_deschedule (SIM_DESC sd,
786
                       sim_event *event_to_remove)
787
{
788
  sim_events *events = STATE_EVENTS (sd);
789
  sim_event *to_remove = (sim_event*)event_to_remove;
790
  if (event_to_remove != NULL)
791
    {
792
      sim_event **queue = NULL;
793
      while ((queue = next_event_queue (sd, queue)) != NULL)
794
        {
795
          sim_event **ptr_to_current;
796
          for (ptr_to_current = queue;
797
               *ptr_to_current != NULL && *ptr_to_current != to_remove;
798
               ptr_to_current = &(*ptr_to_current)->next);
799
          if (*ptr_to_current == to_remove)
800
            {
801
              sim_event *dead = *ptr_to_current;
802
              *ptr_to_current = dead->next;
803
              ETRACE ((_ETRACE,
804
                       "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
805
                       (long) sim_events_time (sd),
806
                       (long) event_to_remove,
807
                       (long) dead->time_of_event,
808
                       (long) dead->handler,
809
                       (long) dead->data,
810
                       (dead->trace != NULL) ? ", " : "",
811
                       (dead->trace != NULL) ? dead->trace : ""));
812
              sim_events_free (sd, dead);
813
              update_time_from_event (sd);
814
              SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
815
              return;
816
            }
817
        }
818
    }
819
  ETRACE ((_ETRACE,
820
           "event/watch descheduled at %ld - tag 0x%lx - not found\n",
821
           (long) sim_events_time (sd),
822
           (long) event_to_remove));
823
}
824
#endif
825
 
826
 
827
STATIC_INLINE_SIM_EVENTS\
828
(int)
829
sim_watch_valid (SIM_DESC sd,
830
                 sim_event *to_do)
831
{
832
  switch (to_do->watching)
833
    {
834
 
835
#define WATCH_CORE(N,OP,EXT) \
836
      int ok; \
837
      unsigned_##N word = 0; \
838
      int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \
839
                                          to_do->core_addr, sizeof (word)); \
840
      OP (word); \
841
      ok = (nr_read == sizeof (unsigned_##N) \
842
            && (to_do->is_within \
843
                == (word >= to_do->lb##EXT \
844
                    && word <= to_do->ub##EXT)));
845
 
846
    case watch_core_targ_1:
847
      {
848
        WATCH_CORE (1, T2H,);
849
        return ok;
850
      }
851
    case watch_core_targ_2:
852
      {
853
        WATCH_CORE (2, T2H,);
854
        return ok;
855
      }
856
    case watch_core_targ_4:
857
      {
858
        WATCH_CORE (4, T2H,);
859
        return ok;
860
      }
861
    case watch_core_targ_8:
862
      {
863
        WATCH_CORE (8, T2H,64);
864
        return ok;
865
      }
866
 
867
    case watch_core_be_1:
868
      {
869
        WATCH_CORE (1, BE2H,);
870
        return ok;
871
      }
872
    case watch_core_be_2:
873
      {
874
        WATCH_CORE (2, BE2H,);
875
        return ok;
876
      }
877
    case watch_core_be_4:
878
      {
879
        WATCH_CORE (4, BE2H,);
880
        return ok;
881
      }
882
    case watch_core_be_8:
883
      {
884
        WATCH_CORE (8, BE2H,64);
885
        return ok;
886
      }
887
 
888
    case watch_core_le_1:
889
      {
890
        WATCH_CORE (1, LE2H,);
891
        return ok;
892
      }
893
    case watch_core_le_2:
894
      {
895
        WATCH_CORE (2, LE2H,);
896
        return ok;
897
      }
898
    case watch_core_le_4:
899
      {
900
        WATCH_CORE (4, LE2H,);
901
        return ok;
902
      }
903
    case watch_core_le_8:
904
      {
905
        WATCH_CORE (8, LE2H,64);
906
        return ok;
907
      }
908
#undef WATCH_CORE
909
 
910
#define WATCH_SIM(N,OP,EXT) \
911
      int ok; \
912
      unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
913
      OP (word); \
914
      ok = (to_do->is_within \
915
            == (word >= to_do->lb##EXT \
916
                && word <= to_do->ub##EXT));
917
 
918
    case watch_sim_host_1:
919
      {
920
        WATCH_SIM (1, word = ,);
921
        return ok;
922
      }
923
    case watch_sim_host_2:
924
      {
925
        WATCH_SIM (2, word = ,);
926
        return ok;
927
      }
928
    case watch_sim_host_4:
929
      {
930
        WATCH_SIM (4, word = ,);
931
        return ok;
932
      }
933
    case watch_sim_host_8:
934
      {
935
        WATCH_SIM (8, word = ,64);
936
        return ok;
937
      }
938
 
939
    case watch_sim_be_1:
940
      {
941
        WATCH_SIM (1, BE2H,);
942
        return ok;
943
      }
944
    case watch_sim_be_2:
945
      {
946
        WATCH_SIM (2, BE2H,);
947
        return ok;
948
      }
949
    case watch_sim_be_4:
950
      {
951
        WATCH_SIM (4, BE2H,);
952
        return ok;
953
      }
954
    case watch_sim_be_8:
955
      {
956
        WATCH_SIM (8, BE2H,64);
957
        return ok;
958
      }
959
 
960
    case watch_sim_le_1:
961
      {
962
        WATCH_SIM (1, LE2H,);
963
        return ok;
964
      }
965
    case watch_sim_le_2:
966
      {
967
        WATCH_SIM (1, LE2H,);
968
        return ok;
969
      }
970
    case watch_sim_le_4:
971
      {
972
        WATCH_SIM (1, LE2H,);
973
        return ok;
974
      }
975
    case watch_sim_le_8:
976
      {
977
        WATCH_SIM (1, LE2H,64);
978
        return ok;
979
      }
980
#undef WATCH_SIM
981
 
982
    case watch_clock: /* wallclock */
983
      {
984
        unsigned long elapsed_time = sim_events_elapsed_time (sd);
985
        return (elapsed_time >= to_do->wallclock);
986
      }
987
 
988
    default:
989
      sim_io_error (sd, "sim_watch_valid - bad switch");
990
      break;
991
 
992
    }
993
  return 1;
994
}
995
 
996
 
997
INLINE_SIM_EVENTS\
998
(int)
999
sim_events_tick (SIM_DESC sd)
1000
{
1001
  sim_events *events = STATE_EVENTS (sd);
1002
 
1003
  /* this should only be called after the previous ticks have been
1004
     fully processed */
1005
 
1006
  /* Advance the time but *only* if there is nothing to process */
1007
  if (events->work_pending
1008
      || events->time_from_event == 0)
1009
    {
1010
      events->nr_ticks_to_process += 1;
1011
      return 1;
1012
    }
1013
  else
1014
    {
1015
      events->time_from_event -= 1;
1016
      return 0;
1017
    }
1018
}
1019
 
1020
 
1021
INLINE_SIM_EVENTS\
1022
(int)
1023
sim_events_tickn (SIM_DESC sd,
1024
                  int n)
1025
{
1026
  sim_events *events = STATE_EVENTS (sd);
1027
  SIM_ASSERT (n > 0);
1028
 
1029
  /* this should only be called after the previous ticks have been
1030
     fully processed */
1031
 
1032
  /* Advance the time but *only* if there is nothing to process */
1033
  if (events->work_pending || events->time_from_event < n)
1034
    {
1035
      events->nr_ticks_to_process += n;
1036
      return 1;
1037
    }
1038
  else
1039
    {
1040
      events->time_from_event -= n;
1041
      return 0;
1042
    }
1043
}
1044
 
1045
 
1046
INLINE_SIM_EVENTS\
1047
(void)
1048
sim_events_slip (SIM_DESC sd,
1049
                 int slip)
1050
{
1051
  sim_events *events = STATE_EVENTS (sd);
1052
  SIM_ASSERT (slip > 0);
1053
 
1054
  /* Flag a ready event with work_pending instead of number of ticks
1055
     to process so that the time continues to be correct */
1056
  if (events->time_from_event < slip)
1057
    {
1058
      events->work_pending = 1;
1059
    }
1060
  events->time_from_event -= slip;
1061
}
1062
 
1063
 
1064
INLINE_SIM_EVENTS\
1065
(void)
1066
sim_events_preprocess (SIM_DESC sd,
1067
                       int events_were_last,
1068
                       int events_were_next)
1069
{
1070
  sim_events *events = STATE_EVENTS(sd);
1071
  if (events_were_last)
1072
    {
1073
      /* Halted part way through event processing */
1074
      ASSERT (events->nr_ticks_to_process != 0);
1075
      /* The external world can't tell if the event that stopped the
1076
         simulator was the last event to process. */
1077
      ASSERT (events_were_next);
1078
      sim_events_process (sd);
1079
    }
1080
  else if (events_were_next)
1081
    {
1082
      /* Halted by the last processor */
1083
      if (sim_events_tick (sd))
1084
        sim_events_process (sd);
1085
    }
1086
}
1087
 
1088
 
1089
INLINE_SIM_EVENTS\
1090
(void)
1091
sim_events_process (SIM_DESC sd)
1092
{
1093
  sim_events *events = STATE_EVENTS(sd);
1094
  signed64 event_time = sim_events_time(sd);
1095
 
1096
  /* Clear work_pending before checking nr_held.  Clearing
1097
     work_pending after nr_held (with out a lock could loose an
1098
     event). */
1099
  events->work_pending = 0;
1100
 
1101
  /* move any events that were asynchronously queued by any signal
1102
     handlers onto the real event queue.  */
1103
  if (events->nr_held > 0)
1104
    {
1105
      int i;
1106
 
1107
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1108
      /*-LOCK-*/
1109
      sigset_t old_mask;
1110
      sigset_t new_mask;
1111
      sigfillset(&new_mask);
1112
      sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
1113
#endif
1114
 
1115
      for (i = 0; i < events->nr_held; i++)
1116
        {
1117
          sim_event *entry = &events->held [i];
1118
          sim_events_schedule (sd,
1119
                               entry->time_of_event,
1120
                               entry->handler,
1121
                               entry->data);
1122
        }
1123
      events->nr_held = 0;
1124
 
1125
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1126
      /*-UNLOCK-*/
1127
      sigprocmask(SIG_SETMASK, &old_mask, NULL);
1128
#endif
1129
 
1130
    }
1131
 
1132
  /* Process any watchpoints. Be careful to allow a watchpoint to
1133
     appear/disappear under our feet.
1134
     To ensure that watchpoints are processed only once per cycle,
1135
     they are moved onto a watched queue, this returned to the
1136
     watchpoint queue when all queue processing has been
1137
     completed. */
1138
  while (events->watchpoints != NULL)
1139
    {
1140
      sim_event *to_do = events->watchpoints;
1141
      events->watchpoints = to_do->next;
1142
      if (sim_watch_valid (sd, to_do))
1143
        {
1144
          sim_event_handler *handler = to_do->handler;
1145
          void *data = to_do->data;
1146
          ETRACE((_ETRACE,
1147
                  "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
1148
                  (long) event_time,
1149
                  (long) to_do,
1150
                  (long) handler,
1151
                  (long) data,
1152
                  (to_do->trace != NULL) ? ", " : "",
1153
                  (to_do->trace != NULL) ? to_do->trace : ""));
1154
          sim_events_free (sd, to_do);
1155
          handler (sd, data);
1156
        }
1157
      else
1158
        {
1159
          to_do->next = events->watchedpoints;
1160
          events->watchedpoints = to_do;
1161
        }
1162
    }
1163
 
1164
  /* consume all events for this or earlier times.  Be careful to
1165
     allow an event to appear/disappear under our feet */
1166
  while (events->queue->time_of_event <
1167
         (event_time + events->nr_ticks_to_process))
1168
    {
1169
      sim_event *to_do = events->queue;
1170
      sim_event_handler *handler = to_do->handler;
1171
      void *data = to_do->data;
1172
      events->queue = to_do->next;
1173
      update_time_from_event (sd);
1174
      ETRACE((_ETRACE,
1175
              "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
1176
              (long) event_time,
1177
              (long) to_do,
1178
              (long) handler,
1179
              (long) data,
1180
              (to_do->trace != NULL) ? ", " : "",
1181
              (to_do->trace != NULL) ? to_do->trace : ""));
1182
      sim_events_free (sd, to_do);
1183
      handler (sd, data);
1184
    }
1185
 
1186
  /* put things back where they belong ready for the next iteration */
1187
  events->watchpoints = events->watchedpoints;
1188
  events->watchedpoints = NULL;
1189
  if (events->watchpoints != NULL)
1190
    events->work_pending = 1;
1191
 
1192
  /* advance the time */
1193
  SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
1194
  SIM_ASSERT (events->queue != NULL); /* always poll event */
1195
  events->time_from_event -= events->nr_ticks_to_process;
1196
 
1197
  /* this round of processing complete */
1198
  events->nr_ticks_to_process = 0;
1199
}
1200
 
1201
#endif

powered by: WebSVN 2.1.0

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