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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [sim/] [common/] [sim-events.c] - Blame information for rev 1181

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

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

powered by: WebSVN 2.1.0

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