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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [common/] [sim-events.c] - Blame information for rev 280

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

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

powered by: WebSVN 2.1.0

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