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, \
682 to_do->core_addr, sizeof (word)); \
684 ok = (nr_read == sizeof (unsigned_##N) \
685 && (to_do->is_within \
686 == (word >= to_do->lb##EXT \
687 && word <= to_do->ub##EXT)));
689 case watch_core_targ_1:
691 WATCH_CORE (1, T2H,);
694 case watch_core_targ_2:
696 WATCH_CORE (2, T2H,);
699 case watch_core_targ_4:
701 WATCH_CORE (4, T2H,);
704 case watch_core_targ_8:
706 WATCH_CORE (8, T2H,64);
710 case watch_core_be_1:
712 WATCH_CORE (1, BE2H,);
715 case watch_core_be_2:
717 WATCH_CORE (2, BE2H,);
720 case watch_core_be_4:
722 WATCH_CORE (4, BE2H,);
725 case watch_core_be_8:
727 WATCH_CORE (8, BE2H,64);
731 case watch_core_le_1:
733 WATCH_CORE (1, LE2H,);
736 case watch_core_le_2:
738 WATCH_CORE (2, LE2H,);
741 case watch_core_le_4:
743 WATCH_CORE (4, LE2H,);
746 case watch_core_le_8:
748 WATCH_CORE (8, LE2H,64);
753 #define WATCH_SIM(N,OP,EXT) \
755 unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
757 ok = (to_do->is_within \
758 == (word >= to_do->lb##EXT \
759 && word <= to_do->ub##EXT));
761 case watch_sim_host_1:
763 WATCH_SIM (1, word = ,);
766 case watch_sim_host_2:
768 WATCH_SIM (2, word = ,);
771 case watch_sim_host_4:
773 WATCH_SIM (4, word = ,);
776 case watch_sim_host_8:
778 WATCH_SIM (8, word = ,64);
784 WATCH_SIM (1, BE2H,);
789 WATCH_SIM (2, BE2H,);
794 WATCH_SIM (4, BE2H,);
799 WATCH_SIM (8, BE2H,64);
805 WATCH_SIM (1, LE2H,);
810 WATCH_SIM (1, LE2H,);
815 WATCH_SIM (1, LE2H,);
820 WATCH_SIM (1, LE2H,64);
825 case watch_clock: /* wallclock */
827 unsigned long elapsed_time = sim_elapsed_time_since (STATE_EVENTS (sd)->initial_wallclock);
828 return (elapsed_time >= to_do->wallclock);
832 sim_io_error (sd, "sim_watch_valid - bad switch");
842 sim_events_tick (SIM_DESC sd)
844 sim_events *events = STATE_EVENTS (sd);
846 /* this should only be called after the previous ticks have been
848 SIM_ASSERT (events->nr_ticks_to_process == 0);
850 /* Advance the time but *only* if there is nothing to process */
851 if (events->work_pending
852 || events->time_from_event == 0)
854 events->nr_ticks_to_process = 1;
858 events->time_from_event -= 1;
866 sim_events_tickn (SIM_DESC sd,
869 sim_events *events = STATE_EVENTS (sd);
871 /* this should only be called after the previous ticks have been
873 SIM_ASSERT (events->nr_ticks_to_process == 0);
876 /* Advance the time but *only* if there is nothing to process */
877 if (events->work_pending
878 || events->time_from_event < n)
880 events->nr_ticks_to_process = n;
884 events->time_from_event -= n;
892 sim_events_preprocess (SIM_DESC sd,
893 int events_were_last,
894 int events_were_next)
896 sim_events *events = STATE_EVENTS(sd);
897 if (events->nr_ticks_to_process != 0)
899 /* Halted midway through event processing */
900 ASSERT (events_were_last && events_were_next);
901 sim_events_process (sd);
903 else if (events_were_next)
905 /* Halted by the last processor */
906 ASSERT (events->nr_ticks_to_process == 0 && !events_were_last);
907 if (sim_events_tick (sd))
908 sim_events_process (sd);
915 sim_events_process (SIM_DESC sd)
917 sim_events *events = STATE_EVENTS(sd);
918 signed64 event_time = sim_events_time(sd);
920 ASSERT (events->nr_ticks_to_process != 0);
922 /* move any events that were queued by any signal handlers onto
923 the real event queue. */
924 if (events->nr_held > 0)
928 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
932 sigfillset(&new_mask);
933 sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
936 for (i = 0; i < events->nr_held; i++)
938 sim_event *entry = &events->held [i];
939 sim_events_schedule (sd,
940 entry->time_of_event,
946 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
948 sigprocmask(SIG_SETMASK, &old_mask, NULL);
953 /* Process any watchpoints. Be careful to allow a watchpoint to
954 appear/disappear under our feet.
955 To ensure that watchpoints are processed only once per cycle,
956 they are moved onto a watched queue, this returned to the
957 watchpoint queue when all queue processing has been
959 while (events->watchpoints != NULL)
961 sim_event *to_do = events->watchpoints;
962 events->watchpoints = to_do->next;
963 if (sim_watch_valid (sd, to_do))
965 sim_event_handler *handler = to_do->handler;
966 void *data = to_do->data;
968 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
973 sim_events_free (sd, to_do);
978 to_do->next = events->watchedpoints;
979 events->watchedpoints = to_do;
983 /* consume all events for this or earlier times. Be careful to
984 allow an event to appear/disappear under our feet */
985 while (events->queue->time_of_event <
986 (event_time + events->nr_ticks_to_process))
988 sim_event *to_do = events->queue;
989 sim_event_handler *handler = to_do->handler;
990 void *data = to_do->data;
991 events->queue = to_do->next;
993 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
998 sim_events_free (sd, to_do);
1002 /* put things back where they belong ready for the next iteration */
1003 events->watchpoints = events->watchedpoints;
1004 events->watchedpoints = NULL;
1005 if (events->watchpoints != NULL)
1006 events->work_pending = 1;
1008 /* re-caculate time for new events then advance the time */
1009 update_time_from_event(sd);
1010 SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
1011 SIM_ASSERT (events->queue != NULL); /* always poll event */
1012 events->time_from_event -= events->nr_ticks_to_process;
1014 /* this round of processing complete */
1015 events->nr_ticks_to_process = 0;