1 /* This file is part of the program psim.
3 Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
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.
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.
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.
22 #ifndef _SIM_EVENTS_C_
23 #define _SIM_EVENTS_C_
26 #include "sim-assert.h"
42 /* core - target byte order */
47 /* core - big-endian */
52 /* core - little-endian */
58 /* sim - host byte order */
63 /* sim - big-endian */
68 /* sim - little-endian */
79 } sim_event_watchpoints
;
83 sim_event_watchpoints watching
;
85 sim_event_handler
*handler
;
87 signed64 time_of_event
;
88 /* watch wallclock event */
90 /* watch core address */
91 address_word core_addr
;
92 sim_core_maps core_map
;
95 /* watch core/sim range */
96 int is_within
; /* 0/1 */
106 /* The event queue maintains a single absolute time using two
109 TIME_OF_EVENT: this holds the time at which the next event is ment
110 to occure. If no next event it will hold the time of the last
113 TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. If an
114 event is pending, this will be positive. If no future event is
115 pending (eg when poll-event is being processed) this will be
116 negative. This variable is decremented once for each iteration of
119 Initially, the clock is started at time one (0) with TIME_OF_EVENT
120 == 0 and TIME_FROM_EVENT == 0.
122 Clearly there is a bug in that this code assumes that the absolute
123 time counter will never become greater than 2^62.
125 To avoid the need to use 64bit arithmetic, the event queue always
126 contains at least one event scheduled every 16 000 ticks. This
127 limits the time from event counter to values less than
131 #if !defined (SIM_EVENTS_POLL_RATE)
132 #define SIM_EVENTS_POLL_RATE 0x100000
139 #define ETRACE(ARGS) \
144 if (STATE_EVENTS (sd)->trace) \
147 SIM_FILTER_PATH (file, __FILE__); \
148 sim_io_printf (sd, "%s:%d: ", file, __LINE__); \
149 sim_io_printf ARGS; \
156 /* event queue iterator - don't iterate over the held queue. */
158 STATIC_INLINE_SIM_EVENTS\
160 next_event_queue (SIM_DESC sd
,
164 return &STATE_EVENTS (sd
)->queue
;
165 else if (queue
== &STATE_EVENTS (sd
)->queue
)
166 return &STATE_EVENTS (sd
)->watchpoints
;
167 else if (queue
== &STATE_EVENTS (sd
)->watchpoints
)
168 return &STATE_EVENTS (sd
)->watchedpoints
;
169 else if (queue
== &STATE_EVENTS (sd
)->watchedpoints
)
172 sim_io_error (sd
, "next_event_queue - bad queue");
177 STATIC_INLINE_SIM_EVENTS\
179 sim_events_poll (SIM_DESC sd
,
182 /* just re-schedule in 1000 million ticks time */
183 sim_events_schedule (sd
, SIM_EVENTS_POLL_RATE
, sim_events_poll
, sd
);
184 sim_io_poll_quit (sd
);
188 /* "events" module install handler.
189 This is called via sim_module_install to install the "events" subsystem
190 into the simulator. */
194 sim_events_install (SIM_DESC sd
)
196 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
197 sim_module_add_uninstall_fn (sd
, sim_events_uninstall
);
198 sim_module_add_init_fn (sd
, sim_events_init
);
203 /* Uninstall the "events" subsystem from the simulator. */
207 sim_events_uninstall (SIM_DESC sd
)
209 /* FIXME: free buffers, etc. */
215 STATIC_INLINE_SIM_EVENTS\
217 sim_events_zalloc (SIM_DESC sd
)
219 sim_events
*events
= STATE_EVENTS (sd
);
220 sim_event
*new = events
->free_list
;
223 events
->free_list
= new->next
;
224 memset (new, 0, sizeof (*new));
228 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
232 sigfillset(&new_mask
);
233 sigprocmask (SIG_SETMASK
, &new_mask
, &old_mask
);
235 new = ZALLOC (sim_event
);
236 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
238 sigprocmask (SIG_SETMASK
, &old_mask
, NULL
);
244 STATIC_INLINE_SIM_EVENTS\
246 sim_events_free (SIM_DESC sd
,
249 sim_events
*events
= STATE_EVENTS (sd
);
250 dead
->next
= events
->free_list
;
251 events
->free_list
= dead
;
255 /* Initialize the simulator event manager */
259 sim_events_init (SIM_DESC sd
)
261 sim_events
*events
= STATE_EVENTS (sd
);
263 /* drain the interrupt queue */
265 if (events
->held
== NULL
)
266 events
->held
= zalloc (sizeof (sim_event
) * MAX_NR_SIGNAL_SIM_EVENTS
);
268 /* drain the normal queues */
270 sim_event
**queue
= NULL
;
271 while ((queue
= next_event_queue (sd
, queue
)) != NULL
)
273 if (queue
== NULL
) break;
274 while (*queue
!= NULL
)
276 sim_event
*dead
= *queue
;
278 sim_events_free (sd
, dead
);
284 /* wind time back to zero */
285 events
->nr_ticks_to_process
= 1; /* start by doing queue */
286 events
->time_of_event
= 0;
287 events
->time_from_event
= 0;
288 events
->initial_wallclock
= sim_elapsed_time_get ();
290 /* schedule our initial counter event */
291 sim_events_schedule (sd
, 0, sim_events_poll
, sd
);
293 /* from now on, except when the large-int event is being processed
294 the event queue is non empty */
295 SIM_ASSERT (events
->queue
!= NULL
);
303 sim_events_time (SIM_DESC sd
)
305 sim_events
*events
= STATE_EVENTS (sd
);
306 return events
->time_of_event
- events
->time_from_event
;
310 STATIC_INLINE_SIM_EVENTS\
312 update_time_from_event (SIM_DESC sd
)
314 sim_events
*events
= STATE_EVENTS (sd
);
315 signed64 current_time
= sim_events_time (sd
);
316 if (events
->queue
!= NULL
)
318 events
->time_from_event
= (events
->queue
->time_of_event
- current_time
);
319 events
->time_of_event
= events
->queue
->time_of_event
;
323 events
->time_of_event
= current_time
- 1;
324 events
->time_from_event
= -1;
326 SIM_ASSERT (current_time
== sim_events_time (sd
));
327 SIM_ASSERT ((events
->time_from_event
>= 0) == (events
->queue
!= NULL
));
331 STATIC_INLINE_SIM_EVENTS\
333 insert_sim_event (SIM_DESC sd
,
334 sim_event
*new_event
,
337 sim_events
*events
= STATE_EVENTS (sd
);
340 signed64 time_of_event
;
343 sim_io_error (sd
, "what is past is past!\n");
345 /* compute when the event should occure */
346 time_of_event
= sim_events_time (sd
) + delta
;
348 /* find the queue insertion point - things are time ordered */
349 prev
= &events
->queue
;
350 curr
= events
->queue
;
351 while (curr
!= NULL
&& time_of_event
>= curr
->time_of_event
)
353 SIM_ASSERT (curr
->next
== NULL
354 || curr
->time_of_event
<= curr
->next
->time_of_event
);
358 SIM_ASSERT (curr
== NULL
|| time_of_event
< curr
->time_of_event
);
361 new_event
->next
= curr
;
363 new_event
->time_of_event
= time_of_event
;
365 /* adjust the time until the first event */
366 update_time_from_event (sd
);
372 sim_events_schedule (SIM_DESC sd
,
374 sim_event_handler
*handler
,
377 sim_event
*new_event
= sim_events_zalloc (sd
);
378 new_event
->data
= data
;
379 new_event
->handler
= handler
;
380 new_event
->watching
= watch_timer
;
381 insert_sim_event(sd
, new_event
, delta_time
);
383 "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
384 (long)sim_events_time(sd
),
386 (long)new_event
->time_of_event
,
387 (long)new_event
->handler
,
388 (long)new_event
->data
));
395 sim_events_schedule_after_signal (SIM_DESC sd
,
397 sim_event_handler
*handler
,
400 sim_events
*events
= STATE_EVENTS (sd
);
401 sim_event
*new_event
;
402 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
406 sigfillset(&new_mask
);
407 sigprocmask (SIG_SETMASK
, &new_mask
, &old_mask
);
410 /* allocate an event entry from the signal buffer */
411 new_event
= &events
->held
[events
->nr_held
];
413 if (events
->nr_held
>= MAX_NR_SIGNAL_SIM_EVENTS
)
415 sim_engine_abort (NULL
, NULL
, NULL_CIA
,
416 "sim_events_schedule_after_signal - buffer oveflow");
419 new_event
->data
= data
;
420 new_event
->handler
= handler
;
421 new_event
->time_of_event
= delta_time
; /* work it out later */
422 new_event
->next
= NULL
;
424 events
->work_pending
= 1; /* notify main process */
426 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
428 sigprocmask (SIG_SETMASK
, &old_mask
, NULL
);
432 "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
433 (long)sim_events_time(sd
),
435 (long)new_event
->time_of_event
,
436 (long)new_event
->handler
,
437 (long)new_event
->data
));
443 sim_events_watch_clock (SIM_DESC sd
,
444 unsigned delta_ms_time
,
445 sim_event_handler
*handler
,
448 sim_events
*events
= STATE_EVENTS (sd
);
449 sim_event
*new_event
= sim_events_zalloc (sd
);
451 new_event
->watching
= watch_clock
;
453 new_event
->data
= data
;
454 new_event
->handler
= handler
;
456 new_event
->wallclock
= (sim_elapsed_time_since (events
->initial_wallclock
) + delta_ms_time
);
458 new_event
->next
= events
->watchpoints
;
459 events
->watchpoints
= new_event
;
460 events
->work_pending
= 1;
462 "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
463 (long)sim_events_time (sd
),
465 (long)new_event
->wallclock
,
466 (long)new_event
->handler
,
467 (long)new_event
->data
));
474 sim_events_watch_sim (SIM_DESC sd
,
481 sim_event_handler
*handler
,
484 sim_events
*events
= STATE_EVENTS (sd
);
485 sim_event
*new_event
= sim_events_zalloc (sd
);
492 case 1: new_event
->watching
= watch_sim_host_1
; break;
493 case 2: new_event
->watching
= watch_sim_host_2
; break;
494 case 4: new_event
->watching
= watch_sim_host_4
; break;
495 case 8: new_event
->watching
= watch_sim_host_8
; break;
496 default: sim_io_error (sd
, "sim_events_watch_sim - invalid nr bytes");
502 case 1: new_event
->watching
= watch_sim_be_1
; break;
503 case 2: new_event
->watching
= watch_sim_be_2
; break;
504 case 4: new_event
->watching
= watch_sim_be_4
; break;
505 case 8: new_event
->watching
= watch_sim_be_8
; break;
506 default: sim_io_error (sd
, "sim_events_watch_sim - invalid nr bytes");
512 case 1: new_event
->watching
= watch_sim_le_1
; break;
513 case 2: new_event
->watching
= watch_sim_le_2
; break;
514 case 4: new_event
->watching
= watch_sim_le_4
; break;
515 case 8: new_event
->watching
= watch_sim_le_8
; break;
516 default: sim_io_error (sd
, "sim_events_watch_sim - invalid nr bytes");
520 sim_io_error (sd
, "sim_events_watch_sim - invalid byte order");
523 new_event
->data
= data
;
524 new_event
->handler
= handler
;
526 new_event
->host_addr
= host_addr
;
528 new_event
->lb64
= lb
;
530 new_event
->ub64
= ub
;
531 new_event
->is_within
= (is_within
!= 0);
533 new_event
->next
= events
->watchpoints
;
534 events
->watchpoints
= new_event
;
535 events
->work_pending
= 1;
537 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
538 (long)sim_events_time (sd
),
540 (long)new_event
->host_addr
,
543 (long)new_event
->handler
,
544 (long)new_event
->data
));
551 sim_events_watch_core (SIM_DESC sd
,
552 address_word core_addr
,
553 sim_core_maps core_map
,
559 sim_event_handler
*handler
,
562 sim_events
*events
= STATE_EVENTS (sd
);
563 sim_event
*new_event
= sim_events_zalloc (sd
);
570 case 1: new_event
->watching
= watch_core_targ_1
; break;
571 case 2: new_event
->watching
= watch_core_targ_2
; break;
572 case 4: new_event
->watching
= watch_core_targ_4
; break;
573 case 8: new_event
->watching
= watch_core_targ_8
; break;
574 default: sim_io_error (sd
, "sim_events_watch_core - invalid nr bytes");
580 case 1: new_event
->watching
= watch_core_be_1
; break;
581 case 2: new_event
->watching
= watch_core_be_2
; break;
582 case 4: new_event
->watching
= watch_core_be_4
; break;
583 case 8: new_event
->watching
= watch_core_be_8
; break;
584 default: sim_io_error (sd
, "sim_events_watch_core - invalid nr bytes");
590 case 1: new_event
->watching
= watch_core_le_1
; break;
591 case 2: new_event
->watching
= watch_core_le_2
; break;
592 case 4: new_event
->watching
= watch_core_le_4
; break;
593 case 8: new_event
->watching
= watch_core_le_8
; break;
594 default: sim_io_error (sd
, "sim_events_watch_core - invalid nr bytes");
598 sim_io_error (sd
, "sim_events_watch_core - invalid byte order");
601 new_event
->data
= data
;
602 new_event
->handler
= handler
;
604 new_event
->core_addr
= core_addr
;
605 new_event
->core_map
= core_map
;
607 new_event
->lb64
= lb
;
609 new_event
->ub64
= ub
;
610 new_event
->is_within
= (is_within
!= 0);
612 new_event
->next
= events
->watchpoints
;
613 events
->watchpoints
= new_event
;
614 events
->work_pending
= 1;
616 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
617 (long)sim_events_time (sd
),
619 (long)new_event
->host_addr
,
622 (long)new_event
->handler
,
623 (long)new_event
->data
));
630 sim_events_deschedule (SIM_DESC sd
,
631 sim_event
*event_to_remove
)
633 sim_events
*events
= STATE_EVENTS (sd
);
634 sim_event
*to_remove
= (sim_event
*)event_to_remove
;
635 SIM_ASSERT ((events
->time_from_event
>= 0) == (events
->queue
!= NULL
));
636 if (event_to_remove
!= NULL
)
638 sim_event
**queue
= NULL
;
639 while ((queue
= next_event_queue (sd
, queue
)) != NULL
)
641 sim_event
**ptr_to_current
;
642 for (ptr_to_current
= queue
;
643 *ptr_to_current
!= NULL
&& *ptr_to_current
!= to_remove
;
644 ptr_to_current
= &(*ptr_to_current
)->next
);
645 if (*ptr_to_current
== to_remove
)
647 sim_event
*dead
= *ptr_to_current
;
648 *ptr_to_current
= dead
->next
;
650 "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
651 (long) sim_events_time (sd
),
652 (long) event_to_remove
,
653 (long) dead
->time_of_event
,
654 (long) dead
->handler
,
656 sim_events_free (sd
, dead
);
657 update_time_from_event (sd
);
658 SIM_ASSERT ((events
->time_from_event
>= 0) == (events
->queue
!= NULL
));
664 "event/watch descheduled at %ld - tag 0x%lx - not found\n",
665 (long) sim_events_time (sd
),
666 (long) event_to_remove
));
670 STATIC_INLINE_SIM_EVENTS\
672 sim_watch_valid (SIM_DESC sd
,
675 switch (to_do
->watching
)
678 #define WATCH_CORE(N,OP,EXT) \
680 unsigned_##N word = 0; \
681 int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, to_do->core_addr, sizeof (word)); \
683 return (nr_read == sizeof (unsigned_##N) \
684 && (to_do->is_within \
685 == (word >= to_do->lb##EXT \
686 && word <= to_do->ub##EXT))); \
688 case watch_core_targ_1
: WATCH_CORE (1, T2H
,);
689 case watch_core_targ_2
: WATCH_CORE (2, T2H
,);
690 case watch_core_targ_4
: WATCH_CORE (4, T2H
,);
691 case watch_core_targ_8
: WATCH_CORE (8, T2H
,64);
693 case watch_core_be_1
: WATCH_CORE (1, BE2H
,);
694 case watch_core_be_2
: WATCH_CORE (2, BE2H
,);
695 case watch_core_be_4
: WATCH_CORE (4, BE2H
,);
696 case watch_core_be_8
: WATCH_CORE (8, BE2H
,64);
698 case watch_core_le_1
: WATCH_CORE (1, LE2H
,);
699 case watch_core_le_2
: WATCH_CORE (2, LE2H
,);
700 case watch_core_le_4
: WATCH_CORE (4, LE2H
,);
701 case watch_core_le_8
: WATCH_CORE (8, LE2H
,64);
704 #define WATCH_SIM(N,OP,EXT) \
706 unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
708 return (to_do->is_within \
709 == (word >= to_do->lb##EXT \
710 && word <= to_do->ub##EXT)); \
713 case watch_sim_host_1
: WATCH_SIM (1, word
= ,);
714 case watch_sim_host_2
: WATCH_SIM (2, word
= ,);
715 case watch_sim_host_4
: WATCH_SIM (4, word
= ,);
716 case watch_sim_host_8
: WATCH_SIM (8, word
= ,64);
718 case watch_sim_be_1
: WATCH_SIM (1, BE2H
,);
719 case watch_sim_be_2
: WATCH_SIM (2, BE2H
,);
720 case watch_sim_be_4
: WATCH_SIM (4, BE2H
,);
721 case watch_sim_be_8
: WATCH_SIM (8, BE2H
,64);
723 case watch_sim_le_1
: WATCH_SIM (1, LE2H
,);
724 case watch_sim_le_2
: WATCH_SIM (1, LE2H
,);
725 case watch_sim_le_4
: WATCH_SIM (1, LE2H
,);
726 case watch_sim_le_8
: WATCH_SIM (1, LE2H
,64);
729 case watch_clock
: /* wallclock */
731 unsigned long elapsed_time
= sim_elapsed_time_since (STATE_EVENTS (sd
)->initial_wallclock
);
732 return (elapsed_time
>= to_do
->wallclock
);
736 sim_io_error (sd
, "sim_watch_valid - bad switch");
746 sim_events_tick (SIM_DESC sd
)
748 sim_events
*events
= STATE_EVENTS (sd
);
750 /* this should only be called after the previous ticks have been
752 SIM_ASSERT (events
->nr_ticks_to_process
== 0);
754 /* Advance the time but *only* if there is nothing to process */
755 if (events
->work_pending
756 || events
->time_from_event
== 0)
758 events
->nr_ticks_to_process
= 1;
762 events
->time_from_event
-= 1;
770 sim_events_tickn (SIM_DESC sd
,
773 sim_events
*events
= STATE_EVENTS (sd
);
775 /* this should only be called after the previous ticks have been
777 SIM_ASSERT (events
->nr_ticks_to_process
== 0);
780 /* Advance the time but *only* if there is nothing to process */
781 if (events
->work_pending
782 || events
->time_from_event
< n
)
784 events
->nr_ticks_to_process
= n
;
788 events
->time_from_event
-= n
;
796 sim_events_preprocess (SIM_DESC sd
,
797 int events_were_last
,
798 int events_were_next
)
800 sim_events
*events
= STATE_EVENTS(sd
);
801 if (events
->nr_ticks_to_process
!= 0)
803 /* Halted midway through event processing */
804 ASSERT (events_were_last
&& events_were_next
);
805 sim_events_process (sd
);
807 else if (events_were_next
)
809 /* Halted by the last processor */
810 ASSERT (events
->nr_ticks_to_process
== 0 && !events_were_last
);
811 if (sim_events_tick (sd
))
812 sim_events_process (sd
);
819 sim_events_process (SIM_DESC sd
)
821 sim_events
*events
= STATE_EVENTS(sd
);
822 signed64 event_time
= sim_events_time(sd
);
824 ASSERT (events
->nr_ticks_to_process
!= 0);
826 /* move any events that were queued by any signal handlers onto
827 the real event queue. */
828 if (events
->nr_held
> 0)
832 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
836 sigfillset(&new_mask
);
837 sigprocmask(SIG_SETMASK
, &new_mask
, &old_mask
);
840 for (i
= 0; i
< events
->nr_held
; i
++)
842 sim_event
*entry
= &events
->held
[i
];
843 sim_events_schedule (sd
,
844 entry
->time_of_event
,
850 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
852 sigprocmask(SIG_SETMASK
, &old_mask
, NULL
);
857 /* Process any watchpoints. Be careful to allow a watchpoint to
858 appear/disappear under our feet.
859 To ensure that watchpoints are processed only once per cycle,
860 they are moved onto a watched queue, this returned to the
861 watchpoint queue when all queue processing has been
863 while (events
->watchpoints
!= NULL
)
865 sim_event
*to_do
= events
->watchpoints
;
866 events
->watchpoints
= to_do
->next
;
867 if (sim_watch_valid (sd
, to_do
))
869 sim_event_handler
*handler
= to_do
->handler
;
870 void *data
= to_do
->data
;
871 events
->queue
= to_do
->next
;
873 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
878 sim_events_free (sd
, to_do
);
883 to_do
->next
= events
->watchedpoints
;
884 events
->watchedpoints
= to_do
;
888 /* consume all events for this or earlier times. Be careful to
889 allow an event to appear/disappear under our feet */
890 while (events
->queue
->time_of_event
<
891 (event_time
+ events
->nr_ticks_to_process
))
893 sim_event
*to_do
= events
->queue
;
894 sim_event_handler
*handler
= to_do
->handler
;
895 void *data
= to_do
->data
;
896 events
->queue
= to_do
->next
;
898 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
903 sim_events_free (sd
, to_do
);
907 /* put things back where they belong ready for the next iteration */
908 events
->watchpoints
= events
->watchedpoints
;
909 events
->watchedpoints
= NULL
;
910 if (events
->watchpoints
!= NULL
)
911 events
->work_pending
= 1;
913 /* re-caculate time for new events then advance the time */
914 update_time_from_event(sd
);
915 SIM_ASSERT (events
->time_from_event
>= events
->nr_ticks_to_process
);
916 SIM_ASSERT (events
->queue
!= NULL
); /* always poll event */
917 events
->time_from_event
-= events
->nr_ticks_to_process
;
919 /* this round of processing complete */
920 events
->nr_ticks_to_process
= 0;