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

Subversion Repositories or1k

[/] [or1k/] [branches/] [oc/] [gdb-5.0/] [sim/] [common/] [sim-events.c] - Blame information for rev 106

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

Line No. Rev Author Line
1 106 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
STATIC_INLINE_SIM_EVENTS\
383
(void)
384
update_time_from_event (SIM_DESC sd)
385
{
386
  sim_events *events = STATE_EVENTS (sd);
387
  signed64 current_time = sim_events_time (sd);
388
  if (events->queue != NULL)
389
    {
390
      events->time_of_event = events->queue->time_of_event;
391
      events->time_from_event = (events->queue->time_of_event - current_time);
392
    }
393
  else
394
    {
395
      events->time_of_event = current_time - 1;
396
      events->time_from_event = -1;
397
    }
398
  SIM_ASSERT (current_time == sim_events_time (sd));
399
}
400
 
401
 
402
#if EXTERN_SIM_EVENTS_P
403
static void
404
insert_sim_event (SIM_DESC sd,
405
                  sim_event *new_event,
406
                  signed64 delta)
407
{
408
  sim_events *events = STATE_EVENTS (sd);
409
  sim_event *curr;
410
  sim_event **prev;
411
  signed64 time_of_event;
412
 
413
  if (delta < 0)
414
    sim_io_error (sd, "what is past is past!\n");
415
 
416
  /* compute when the event should occure */
417
  time_of_event = sim_events_time (sd) + delta;
418
 
419
  /* find the queue insertion point - things are time ordered */
420
  prev = &events->queue;
421
  curr = events->queue;
422
  while (curr != NULL && time_of_event >= curr->time_of_event)
423
    {
424
      SIM_ASSERT (curr->next == NULL
425
                  || curr->time_of_event <= curr->next->time_of_event);
426
      prev = &curr->next;
427
      curr = curr->next;
428
    }
429
  SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
430
 
431
  /* insert it */
432
  new_event->next = curr;
433
  *prev = new_event;
434
  new_event->time_of_event = time_of_event;
435
 
436
  /* adjust the time until the first event */
437
  update_time_from_event (sd);
438
}
439
#endif
440
 
441
 
442
#if EXTERN_SIM_EVENTS_P
443
sim_event *
444
sim_events_schedule (SIM_DESC sd,
445
                     signed64 delta_time,
446
                     sim_event_handler *handler,
447
                     void *data)
448
{
449
  va_list dummy;
450
  return sim_events_schedule_vtracef (sd, delta_time, handler, data,
451
                                      NULL, dummy);
452
}
453
#endif
454
 
455
 
456
#if EXTERN_SIM_EVENTS_P
457
sim_event *
458
sim_events_schedule_tracef (SIM_DESC sd,
459
                            signed64 delta_time,
460
                            sim_event_handler *handler,
461
                            void *data,
462
                            const char *fmt,
463
                            ...)
464
{
465
  sim_event *new_event;
466
  va_list ap;
467
  va_start (ap, fmt);
468
  new_event = sim_events_schedule_vtracef (sd, delta_time, handler, data, fmt, ap);
469
  va_end (ap);
470
  return new_event;
471
}
472
#endif
473
 
474
 
475
#if EXTERN_SIM_EVENTS_P
476
sim_event *
477
sim_events_schedule_vtracef (SIM_DESC sd,
478
                             signed64 delta_time,
479
                             sim_event_handler *handler,
480
                             void *data,
481
                             const char *fmt,
482
                             va_list ap)
483
{
484
  sim_event *new_event = sim_events_zalloc (sd);
485
  new_event->data = data;
486
  new_event->handler = handler;
487
  new_event->watching = watch_timer;
488
  if (fmt == NULL || !ETRACE_P || vasprintf (&new_event->trace, fmt, ap) < 0)
489
    new_event->trace = NULL;
490
  insert_sim_event(sd, new_event, delta_time);
491
  ETRACE((_ETRACE,
492
          "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
493
          (long)sim_events_time(sd),
494
          (long)new_event,
495
          (long)new_event->time_of_event,
496
          (long)new_event->handler,
497
          (long)new_event->data,
498
          (new_event->trace != NULL) ? ", " : "",
499
          (new_event->trace != NULL) ? new_event->trace : ""));
500
  return new_event;
501
}
502
#endif
503
 
504
 
505
#if EXTERN_SIM_EVENTS_P
506
void
507
sim_events_schedule_after_signal (SIM_DESC sd,
508
                                  signed64 delta_time,
509
                                  sim_event_handler *handler,
510
                                  void *data)
511
{
512
  sim_events *events = STATE_EVENTS (sd);
513
  sim_event *new_event;
514
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
515
  /*-LOCK-*/
516
  sigset_t old_mask;
517
  sigset_t new_mask;
518
  sigfillset(&new_mask);
519
  sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
520
#endif
521
 
522
  /* allocate an event entry from the signal buffer */
523
  new_event = &events->held [events->nr_held];
524
  events->nr_held ++;
525
  if (events->nr_held > MAX_NR_SIGNAL_SIM_EVENTS)
526
    {
527
      sim_engine_abort (NULL, NULL, NULL_CIA,
528
                        "sim_events_schedule_after_signal - buffer oveflow");
529
    }
530
 
531
  new_event->data = data;
532
  new_event->handler = handler;
533
  new_event->time_of_event = delta_time; /* work it out later */
534
  new_event->next = NULL;
535
 
536
  events->work_pending = 1; /* notify main process */
537
 
538
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
539
  /*-UNLOCK-*/
540
  sigprocmask (SIG_SETMASK, &old_mask, NULL);
541
#endif
542
 
543
  ETRACE ((_ETRACE,
544
           "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
545
           (long)sim_events_time(sd),
546
           (long)new_event,
547
           (long)new_event->time_of_event,
548
           (long)new_event->handler,
549
           (long)new_event->data));
550
}
551
#endif
552
 
553
 
554
#if EXTERN_SIM_EVENTS_P
555
sim_event *
556
sim_events_watch_clock (SIM_DESC sd,
557
                        unsigned delta_ms_time,
558
                        sim_event_handler *handler,
559
                        void *data)
560
{
561
  sim_events *events = STATE_EVENTS (sd);
562
  sim_event *new_event = sim_events_zalloc (sd);
563
  /* type */
564
  new_event->watching = watch_clock;
565
  /* handler */
566
  new_event->data = data;
567
  new_event->handler = handler;
568
  /* data */
569
  if (events->resume_wallclock == 0)
570
    new_event->wallclock = (events->elapsed_wallclock + delta_ms_time);
571
  else
572
    new_event->wallclock = (events->elapsed_wallclock
573
                            + sim_elapsed_time_since (events->resume_wallclock)
574
                            + delta_ms_time);
575
  /* insert */
576
  new_event->next = events->watchpoints;
577
  events->watchpoints = new_event;
578
  events->work_pending = 1;
579
  ETRACE ((_ETRACE,
580
          "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
581
           (long)sim_events_time (sd),
582
           (long)new_event,
583
           (long)new_event->wallclock,
584
           (long)new_event->handler,
585
           (long)new_event->data));
586
  return new_event;
587
}
588
#endif
589
 
590
 
591
#if EXTERN_SIM_EVENTS_P
592
sim_event *
593
sim_events_watch_sim (SIM_DESC sd,
594
                      void *host_addr,
595
                      int nr_bytes,
596
                      int byte_order,
597
                      int is_within,
598
                      unsigned64 lb,
599
                      unsigned64 ub,
600
                      sim_event_handler *handler,
601
                      void *data)
602
{
603
  sim_events *events = STATE_EVENTS (sd);
604
  sim_event *new_event = sim_events_zalloc (sd);
605
  /* type */
606
  switch (byte_order)
607
    {
608
    case 0:
609
      switch (nr_bytes)
610
        {
611
        case 1: new_event->watching = watch_sim_host_1; break;
612
        case 2: new_event->watching = watch_sim_host_2; break;
613
        case 4: new_event->watching = watch_sim_host_4; break;
614
        case 8: new_event->watching = watch_sim_host_8; break;
615
        default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
616
        }
617
      break;
618
    case BIG_ENDIAN:
619
      switch (nr_bytes)
620
        {
621
        case 1: new_event->watching = watch_sim_be_1; break;
622
        case 2: new_event->watching = watch_sim_be_2; break;
623
        case 4: new_event->watching = watch_sim_be_4; break;
624
        case 8: new_event->watching = watch_sim_be_8; break;
625
        default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
626
        }
627
      break;
628
    case LITTLE_ENDIAN:
629
      switch (nr_bytes)
630
        {
631
        case 1: new_event->watching = watch_sim_le_1; break;
632
        case 2: new_event->watching = watch_sim_le_2; break;
633
        case 4: new_event->watching = watch_sim_le_4; break;
634
        case 8: new_event->watching = watch_sim_le_8; break;
635
        default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
636
        }
637
      break;
638
    default:
639
      sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
640
    }
641
  /* handler */
642
  new_event->data = data;
643
  new_event->handler = handler;
644
  /* data */
645
  new_event->host_addr = host_addr;
646
  new_event->lb = lb;
647
  new_event->lb64 = lb;
648
  new_event->ub = ub;
649
  new_event->ub64 = ub;
650
  new_event->is_within = (is_within != 0);
651
  /* insert */
652
  new_event->next = events->watchpoints;
653
  events->watchpoints = new_event;
654
  events->work_pending = 1;
655
  ETRACE ((_ETRACE,
656
           "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
657
           (long)sim_events_time (sd),
658
           (long)new_event,
659
           (long)new_event->host_addr,
660
           (long)new_event->lb,
661
           (long)new_event->ub,
662
           (long)new_event->handler,
663
           (long)new_event->data));
664
  return new_event;
665
}
666
#endif
667
 
668
 
669
#if EXTERN_SIM_EVENTS_P
670
sim_event *
671
sim_events_watch_core (SIM_DESC sd,
672
                       address_word core_addr,
673
                       unsigned core_map,
674
                       int nr_bytes,
675
                       int byte_order,
676
                       int is_within,
677
                       unsigned64 lb,
678
                       unsigned64 ub,
679
                       sim_event_handler *handler,
680
                       void *data)
681
{
682
  sim_events *events = STATE_EVENTS (sd);
683
  sim_event *new_event = sim_events_zalloc (sd);
684
  /* type */
685
  switch (byte_order)
686
    {
687
    case 0:
688
      switch (nr_bytes)
689
        {
690
        case 1: new_event->watching = watch_core_targ_1; break;
691
        case 2: new_event->watching = watch_core_targ_2; break;
692
        case 4: new_event->watching = watch_core_targ_4; break;
693
        case 8: new_event->watching = watch_core_targ_8; break;
694
        default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
695
        }
696
      break;
697
    case BIG_ENDIAN:
698
      switch (nr_bytes)
699
        {
700
        case 1: new_event->watching = watch_core_be_1; break;
701
        case 2: new_event->watching = watch_core_be_2; break;
702
        case 4: new_event->watching = watch_core_be_4; break;
703
        case 8: new_event->watching = watch_core_be_8; break;
704
        default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
705
        }
706
      break;
707
    case LITTLE_ENDIAN:
708
      switch (nr_bytes)
709
        {
710
        case 1: new_event->watching = watch_core_le_1; break;
711
        case 2: new_event->watching = watch_core_le_2; break;
712
        case 4: new_event->watching = watch_core_le_4; break;
713
        case 8: new_event->watching = watch_core_le_8; break;
714
        default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
715
        }
716
      break;
717
    default:
718
      sim_io_error (sd, "sim_events_watch_core - invalid byte order");
719
    }
720
  /* handler */
721
  new_event->data = data;
722
  new_event->handler = handler;
723
  /* data */
724
  new_event->core_addr = core_addr;
725
  new_event->core_map = core_map;
726
  new_event->lb = lb;
727
  new_event->lb64 = lb;
728
  new_event->ub = ub;
729
  new_event->ub64 = ub;
730
  new_event->is_within = (is_within != 0);
731
  /* insert */
732
  new_event->next = events->watchpoints;
733
  events->watchpoints = new_event;
734
  events->work_pending = 1;
735
  ETRACE ((_ETRACE,
736
           "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
737
           (long)sim_events_time (sd),
738
           (long)new_event,
739
           (long)new_event->host_addr,
740
           (long)new_event->lb,
741
           (long)new_event->ub,
742
           (long)new_event->handler,
743
           (long)new_event->data));
744
  return new_event;
745
}
746
#endif
747
 
748
 
749
#if EXTERN_SIM_EVENTS_P
750
void
751
sim_events_deschedule (SIM_DESC sd,
752
                       sim_event *event_to_remove)
753
{
754
  sim_events *events = STATE_EVENTS (sd);
755
  sim_event *to_remove = (sim_event*)event_to_remove;
756
  if (event_to_remove != NULL)
757
    {
758
      sim_event **queue = NULL;
759
      while ((queue = next_event_queue (sd, queue)) != NULL)
760
        {
761
          sim_event **ptr_to_current;
762
          for (ptr_to_current = queue;
763
               *ptr_to_current != NULL && *ptr_to_current != to_remove;
764
               ptr_to_current = &(*ptr_to_current)->next);
765
          if (*ptr_to_current == to_remove)
766
            {
767
              sim_event *dead = *ptr_to_current;
768
              *ptr_to_current = dead->next;
769
              ETRACE ((_ETRACE,
770
                       "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
771
                       (long) sim_events_time (sd),
772
                       (long) event_to_remove,
773
                       (long) dead->time_of_event,
774
                       (long) dead->handler,
775
                       (long) dead->data,
776
                       (dead->trace != NULL) ? ", " : "",
777
                       (dead->trace != NULL) ? dead->trace : ""));
778
              sim_events_free (sd, dead);
779
              update_time_from_event (sd);
780
              SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
781
              return;
782
            }
783
        }
784
    }
785
  ETRACE ((_ETRACE,
786
           "event/watch descheduled at %ld - tag 0x%lx - not found\n",
787
           (long) sim_events_time (sd),
788
           (long) event_to_remove));
789
}
790
#endif
791
 
792
 
793
STATIC_INLINE_SIM_EVENTS\
794
(int)
795
sim_watch_valid (SIM_DESC sd,
796
                 sim_event *to_do)
797
{
798
  switch (to_do->watching)
799
    {
800
 
801
#define WATCH_CORE(N,OP,EXT) \
802
      int ok; \
803
      unsigned_##N word = 0; \
804
      int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \
805
                                          to_do->core_addr, sizeof (word)); \
806
      OP (word); \
807
      ok = (nr_read == sizeof (unsigned_##N) \
808
            && (to_do->is_within \
809
                == (word >= to_do->lb##EXT \
810
                    && word <= to_do->ub##EXT)));
811
 
812
    case watch_core_targ_1:
813
      {
814
        WATCH_CORE (1, T2H,);
815
        return ok;
816
      }
817
    case watch_core_targ_2:
818
      {
819
        WATCH_CORE (2, T2H,);
820
        return ok;
821
      }
822
    case watch_core_targ_4:
823
      {
824
        WATCH_CORE (4, T2H,);
825
        return ok;
826
      }
827
    case watch_core_targ_8:
828
      {
829
        WATCH_CORE (8, T2H,64);
830
        return ok;
831
      }
832
 
833
    case watch_core_be_1:
834
      {
835
        WATCH_CORE (1, BE2H,);
836
        return ok;
837
      }
838
    case watch_core_be_2:
839
      {
840
        WATCH_CORE (2, BE2H,);
841
        return ok;
842
      }
843
    case watch_core_be_4:
844
      {
845
        WATCH_CORE (4, BE2H,);
846
        return ok;
847
      }
848
    case watch_core_be_8:
849
      {
850
        WATCH_CORE (8, BE2H,64);
851
        return ok;
852
      }
853
 
854
    case watch_core_le_1:
855
      {
856
        WATCH_CORE (1, LE2H,);
857
        return ok;
858
      }
859
    case watch_core_le_2:
860
      {
861
        WATCH_CORE (2, LE2H,);
862
        return ok;
863
      }
864
    case watch_core_le_4:
865
      {
866
        WATCH_CORE (4, LE2H,);
867
        return ok;
868
      }
869
    case watch_core_le_8:
870
      {
871
        WATCH_CORE (8, LE2H,64);
872
        return ok;
873
      }
874
#undef WATCH_CORE
875
 
876
#define WATCH_SIM(N,OP,EXT) \
877
      int ok; \
878
      unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
879
      OP (word); \
880
      ok = (to_do->is_within \
881
            == (word >= to_do->lb##EXT \
882
                && word <= to_do->ub##EXT));
883
 
884
    case watch_sim_host_1:
885
      {
886
        WATCH_SIM (1, word = ,);
887
        return ok;
888
      }
889
    case watch_sim_host_2:
890
      {
891
        WATCH_SIM (2, word = ,);
892
        return ok;
893
      }
894
    case watch_sim_host_4:
895
      {
896
        WATCH_SIM (4, word = ,);
897
        return ok;
898
      }
899
    case watch_sim_host_8:
900
      {
901
        WATCH_SIM (8, word = ,64);
902
        return ok;
903
      }
904
 
905
    case watch_sim_be_1:
906
      {
907
        WATCH_SIM (1, BE2H,);
908
        return ok;
909
      }
910
    case watch_sim_be_2:
911
      {
912
        WATCH_SIM (2, BE2H,);
913
        return ok;
914
      }
915
    case watch_sim_be_4:
916
      {
917
        WATCH_SIM (4, BE2H,);
918
        return ok;
919
      }
920
    case watch_sim_be_8:
921
      {
922
        WATCH_SIM (8, BE2H,64);
923
        return ok;
924
      }
925
 
926
    case watch_sim_le_1:
927
      {
928
        WATCH_SIM (1, LE2H,);
929
        return ok;
930
      }
931
    case watch_sim_le_2:
932
      {
933
        WATCH_SIM (1, LE2H,);
934
        return ok;
935
      }
936
    case watch_sim_le_4:
937
      {
938
        WATCH_SIM (1, LE2H,);
939
        return ok;
940
      }
941
    case watch_sim_le_8:
942
      {
943
        WATCH_SIM (1, LE2H,64);
944
        return ok;
945
      }
946
#undef WATCH_SIM
947
 
948
    case watch_clock: /* wallclock */
949
      {
950
        unsigned long elapsed_time = sim_events_elapsed_time (sd);
951
        return (elapsed_time >= to_do->wallclock);
952
      }
953
 
954
    default:
955
      sim_io_error (sd, "sim_watch_valid - bad switch");
956
      break;
957
 
958
    }
959
  return 1;
960
}
961
 
962
 
963
INLINE_SIM_EVENTS\
964
(int)
965
sim_events_tick (SIM_DESC sd)
966
{
967
  sim_events *events = STATE_EVENTS (sd);
968
 
969
  /* this should only be called after the previous ticks have been
970
     fully processed */
971
 
972
  /* Advance the time but *only* if there is nothing to process */
973
  if (events->work_pending
974
      || events->time_from_event == 0)
975
    {
976
      events->nr_ticks_to_process += 1;
977
      return 1;
978
    }
979
  else
980
    {
981
      events->time_from_event -= 1;
982
      return 0;
983
    }
984
}
985
 
986
 
987
INLINE_SIM_EVENTS\
988
(int)
989
sim_events_tickn (SIM_DESC sd,
990
                  int n)
991
{
992
  sim_events *events = STATE_EVENTS (sd);
993
  SIM_ASSERT (n > 0);
994
 
995
  /* this should only be called after the previous ticks have been
996
     fully processed */
997
 
998
  /* Advance the time but *only* if there is nothing to process */
999
  if (events->work_pending || events->time_from_event < n)
1000
    {
1001
      events->nr_ticks_to_process += n;
1002
      return 1;
1003
    }
1004
  else
1005
    {
1006
      events->time_from_event -= n;
1007
      return 0;
1008
    }
1009
}
1010
 
1011
 
1012
INLINE_SIM_EVENTS\
1013
(void)
1014
sim_events_slip (SIM_DESC sd,
1015
                 int slip)
1016
{
1017
  sim_events *events = STATE_EVENTS (sd);
1018
  SIM_ASSERT (slip > 0);
1019
 
1020
  /* Flag a ready event with work_pending instead of number of ticks
1021
     to process so that the time continues to be correct */
1022
  if (events->time_from_event < slip)
1023
    {
1024
      events->work_pending = 1;
1025
    }
1026
  events->time_from_event -= slip;
1027
}
1028
 
1029
 
1030
INLINE_SIM_EVENTS\
1031
(void)
1032
sim_events_preprocess (SIM_DESC sd,
1033
                       int events_were_last,
1034
                       int events_were_next)
1035
{
1036
  sim_events *events = STATE_EVENTS(sd);
1037
  if (events_were_last)
1038
    {
1039
      /* Halted part way through event processing */
1040
      ASSERT (events->nr_ticks_to_process != 0);
1041
      /* The external world can't tell if the event that stopped the
1042
         simulator was the last event to process. */
1043
      ASSERT (events_were_next);
1044
      sim_events_process (sd);
1045
    }
1046
  else if (events_were_next)
1047
    {
1048
      /* Halted by the last processor */
1049
      if (sim_events_tick (sd))
1050
        sim_events_process (sd);
1051
    }
1052
}
1053
 
1054
 
1055
INLINE_SIM_EVENTS\
1056
(void)
1057
sim_events_process (SIM_DESC sd)
1058
{
1059
  sim_events *events = STATE_EVENTS(sd);
1060
  signed64 event_time = sim_events_time(sd);
1061
 
1062
  /* Clear work_pending before checking nr_held.  Clearing
1063
     work_pending after nr_held (with out a lock could loose an
1064
     event). */
1065
  events->work_pending = 0;
1066
 
1067
  /* move any events that were asynchronously queued by any signal
1068
     handlers onto the real event queue.  */
1069
  if (events->nr_held > 0)
1070
    {
1071
      int i;
1072
 
1073
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1074
      /*-LOCK-*/
1075
      sigset_t old_mask;
1076
      sigset_t new_mask;
1077
      sigfillset(&new_mask);
1078
      sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
1079
#endif
1080
 
1081
      for (i = 0; i < events->nr_held; i++)
1082
        {
1083
          sim_event *entry = &events->held [i];
1084
          sim_events_schedule (sd,
1085
                               entry->time_of_event,
1086
                               entry->handler,
1087
                               entry->data);
1088
        }
1089
      events->nr_held = 0;
1090
 
1091
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
1092
      /*-UNLOCK-*/
1093
      sigprocmask(SIG_SETMASK, &old_mask, NULL);
1094
#endif
1095
 
1096
    }
1097
 
1098
  /* Process any watchpoints. Be careful to allow a watchpoint to
1099
     appear/disappear under our feet.
1100
     To ensure that watchpoints are processed only once per cycle,
1101
     they are moved onto a watched queue, this returned to the
1102
     watchpoint queue when all queue processing has been
1103
     completed. */
1104
  while (events->watchpoints != NULL)
1105
    {
1106
      sim_event *to_do = events->watchpoints;
1107
      events->watchpoints = to_do->next;
1108
      if (sim_watch_valid (sd, to_do))
1109
        {
1110
          sim_event_handler *handler = to_do->handler;
1111
          void *data = to_do->data;
1112
          ETRACE((_ETRACE,
1113
                  "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
1114
                  (long) event_time,
1115
                  (long) to_do,
1116
                  (long) handler,
1117
                  (long) data,
1118
                  (to_do->trace != NULL) ? ", " : "",
1119
                  (to_do->trace != NULL) ? to_do->trace : ""));
1120
          sim_events_free (sd, to_do);
1121
          handler (sd, data);
1122
        }
1123
      else
1124
        {
1125
          to_do->next = events->watchedpoints;
1126
          events->watchedpoints = to_do;
1127
        }
1128
    }
1129
 
1130
  /* consume all events for this or earlier times.  Be careful to
1131
     allow an event to appear/disappear under our feet */
1132
  while (events->queue->time_of_event <
1133
         (event_time + events->nr_ticks_to_process))
1134
    {
1135
      sim_event *to_do = events->queue;
1136
      sim_event_handler *handler = to_do->handler;
1137
      void *data = to_do->data;
1138
      events->queue = to_do->next;
1139
      update_time_from_event (sd);
1140
      ETRACE((_ETRACE,
1141
              "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
1142
              (long) event_time,
1143
              (long) to_do,
1144
              (long) handler,
1145
              (long) data,
1146
              (to_do->trace != NULL) ? ", " : "",
1147
              (to_do->trace != NULL) ? to_do->trace : ""));
1148
      sim_events_free (sd, to_do);
1149
      handler (sd, data);
1150
    }
1151
 
1152
  /* put things back where they belong ready for the next iteration */
1153
  events->watchpoints = events->watchedpoints;
1154
  events->watchedpoints = NULL;
1155
  if (events->watchpoints != NULL)
1156
    events->work_pending = 1;
1157
 
1158
  /* advance the time */
1159
  SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
1160
  SIM_ASSERT (events->queue != NULL); /* always poll event */
1161
  events->time_from_event -= events->nr_ticks_to_process;
1162
 
1163
  /* this round of processing complete */
1164
  events->nr_ticks_to_process = 0;
1165
}
1166
 
1167
#endif

powered by: WebSVN 2.1.0

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