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 */
105 /* The event queue maintains a single absolute time using two
108 TIME_OF_EVENT: this holds the time at which the next event is ment
109 to occure. If no next event it will hold the time of the last
112 TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. If an
113 event is pending, this will be positive. If no future event is
114 pending (eg when poll-event is being processed) this will be
115 negative. This variable is decremented once for each iteration of
118 Initially, the clock is started at time one (0) with TIME_OF_EVENT
119 == 0 and TIME_FROM_EVENT == 0.
121 Clearly there is a bug in that this code assumes that the absolute
122 time counter will never become greater than 2^62.
124 To avoid the need to use 64bit arithmetic, the event queue always
125 contains at least one event scheduled every 16 000 ticks. This
126 limits the time from event counter to values less than
130 #if !defined (SIM_EVENTS_POLL_RATE)
131 #define SIM_EVENTS_POLL_RATE 0x100000
138 #define ETRACE(ARGS) \
143 if (STATE_EVENTS (sd)->trace) \
146 SIM_FILTER_PATH (file, __FILE__); \
147 sim_io_printf (sd, "%s:%d: ", file, __LINE__); \
148 sim_io_printf ARGS; \
155 /* event queue iterator - don't iterate over the held queue. */
157 STATIC_INLINE_SIM_EVENTS\
159 next_event_queue (SIM_DESC sd,
163 return &STATE_EVENTS (sd)->queue;
164 else if (queue == &STATE_EVENTS (sd)->queue)
165 return &STATE_EVENTS (sd)->watchpoints;
166 else if (queue == &STATE_EVENTS (sd)->watchpoints)
167 return &STATE_EVENTS (sd)->watchedpoints;
168 else if (queue == &STATE_EVENTS (sd)->watchedpoints)
171 sim_io_error (sd, "next_event_queue - bad queue");
176 STATIC_INLINE_SIM_EVENTS\
178 sim_events_poll (SIM_DESC sd,
181 /* just re-schedule in 1000 million ticks time */
182 sim_events_schedule (sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
183 sim_io_poll_quit (sd);
187 /* "events" module install handler.
188 This is called via sim_module_install to install the "events" subsystem
189 into the simulator. */
193 sim_events_install (SIM_DESC sd)
195 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
196 sim_module_add_uninstall_fn (sd, sim_events_uninstall);
197 sim_module_add_init_fn (sd, sim_events_init);
202 /* Uninstall the "events" subsystem from the simulator. */
206 sim_events_uninstall (SIM_DESC sd)
208 /* FIXME: free buffers, etc. */
214 STATIC_INLINE_SIM_EVENTS\
216 sim_events_zalloc (SIM_DESC sd)
218 sim_events *events = STATE_EVENTS (sd);
219 sim_event *new = events->free_list;
222 events->free_list = new->next;
223 memset (new, 0, sizeof (*new));
227 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
231 sigfillset(&new_mask);
232 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
234 new = ZALLOC (sim_event);
235 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
237 sigprocmask (SIG_SETMASK, &old_mask, NULL);
243 STATIC_INLINE_SIM_EVENTS\
245 sim_events_free (SIM_DESC sd,
248 sim_events *events = STATE_EVENTS (sd);
249 dead->next = events->free_list;
250 events->free_list = dead;
254 /* Initialize the simulator event manager */
258 sim_events_init (SIM_DESC sd)
260 sim_events *events = STATE_EVENTS (sd);
262 /* drain the interrupt queue */
264 if (events->held == NULL)
265 events->held = zalloc (sizeof (sim_event) * MAX_NR_SIGNAL_SIM_EVENTS);
267 /* drain the normal queues */
269 sim_event **queue = NULL;
270 while ((queue = next_event_queue (sd, queue)) != NULL)
272 if (queue == NULL) break;
273 while (*queue != NULL)
275 sim_event *dead = *queue;
277 sim_events_free (sd, dead);
283 /* wind time back to zero */
284 events->nr_ticks_to_process = 1; /* start by doing queue */
285 events->time_of_event = 0;
286 events->time_from_event = 0;
287 events->initial_wallclock = sim_elapsed_time_get ();
289 /* schedule our initial counter event */
290 sim_events_schedule (sd, 0, sim_events_poll, sd);
292 /* from now on, except when the large-int event is being processed
293 the event queue is non empty */
294 SIM_ASSERT (events->queue != NULL);
302 sim_events_time (SIM_DESC sd)
304 sim_events *events = STATE_EVENTS (sd);
305 return events->time_of_event - events->time_from_event;
309 STATIC_INLINE_SIM_EVENTS\
311 update_time_from_event (SIM_DESC sd)
313 sim_events *events = STATE_EVENTS (sd);
314 signed64 current_time = sim_events_time (sd);
315 if (events->queue != NULL)
317 events->time_from_event = (events->queue->time_of_event - current_time);
318 events->time_of_event = events->queue->time_of_event;
322 events->time_of_event = current_time - 1;
323 events->time_from_event = -1;
325 SIM_ASSERT (current_time == sim_events_time (sd));
326 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
330 STATIC_INLINE_SIM_EVENTS\
332 insert_sim_event (SIM_DESC sd,
333 sim_event *new_event,
336 sim_events *events = STATE_EVENTS (sd);
339 signed64 time_of_event;
342 sim_io_error (sd, "what is past is past!\n");
344 /* compute when the event should occure */
345 time_of_event = sim_events_time (sd) + delta;
347 /* find the queue insertion point - things are time ordered */
348 prev = &events->queue;
349 curr = events->queue;
350 while (curr != NULL && time_of_event >= curr->time_of_event)
352 SIM_ASSERT (curr->next == NULL
353 || curr->time_of_event <= curr->next->time_of_event);
357 SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
360 new_event->next = curr;
362 new_event->time_of_event = time_of_event;
364 /* adjust the time until the first event */
365 update_time_from_event (sd);
371 sim_events_schedule (SIM_DESC sd,
373 sim_event_handler *handler,
376 sim_event *new_event = sim_events_zalloc (sd);
377 new_event->data = data;
378 new_event->handler = handler;
379 new_event->watching = watch_timer;
380 insert_sim_event(sd, new_event, delta_time);
382 "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
383 (long)sim_events_time(sd),
385 (long)new_event->time_of_event,
386 (long)new_event->handler,
387 (long)new_event->data));
394 sim_events_schedule_after_signal (SIM_DESC sd,
396 sim_event_handler *handler,
399 sim_events *events = STATE_EVENTS (sd);
400 sim_event *new_event;
401 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
405 sigfillset(&new_mask);
406 sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
409 /* allocate an event entry from the signal buffer */
410 new_event = &events->held [events->nr_held];
412 if (events->nr_held >= MAX_NR_SIGNAL_SIM_EVENTS)
414 sim_engine_abort (NULL, NULL, NULL_CIA,
415 "sim_events_schedule_after_signal - buffer oveflow");
418 new_event->data = data;
419 new_event->handler = handler;
420 new_event->time_of_event = delta_time; /* work it out later */
421 new_event->next = NULL;
423 events->work_pending = 1; /* notify main process */
425 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
427 sigprocmask (SIG_SETMASK, &old_mask, NULL);
431 "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
432 (long)sim_events_time(sd),
434 (long)new_event->time_of_event,
435 (long)new_event->handler,
436 (long)new_event->data));
442 sim_events_watch_clock (SIM_DESC sd,
443 unsigned delta_ms_time,
444 sim_event_handler *handler,
447 sim_events *events = STATE_EVENTS (sd);
448 sim_event *new_event = sim_events_zalloc (sd);
450 new_event->watching = watch_clock;
452 new_event->data = data;
453 new_event->handler = handler;
455 new_event->wallclock = (sim_elapsed_time_since (events->initial_wallclock) + delta_ms_time);
457 new_event->next = events->watchpoints;
458 events->watchpoints = new_event;
459 events->work_pending = 1;
461 "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
462 (long)sim_events_time (sd),
464 (long)new_event->wallclock,
465 (long)new_event->handler,
466 (long)new_event->data));
473 sim_events_watch_sim (SIM_DESC sd,
479 sim_event_handler *handler,
482 sim_events *events = STATE_EVENTS (sd);
483 sim_event *new_event = sim_events_zalloc (sd);
490 case 1: new_event->watching = watch_sim_host_1; break;
491 case 2: new_event->watching = watch_sim_host_2; break;
492 case 4: new_event->watching = watch_sim_host_4; break;
493 case 8: new_event->watching = watch_sim_host_8; break;
494 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
500 case 1: new_event->watching = watch_sim_be_1; break;
501 case 2: new_event->watching = watch_sim_be_2; break;
502 case 4: new_event->watching = watch_sim_be_4; break;
503 case 8: new_event->watching = watch_sim_be_8; break;
504 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
510 case 1: new_event->watching = watch_sim_le_1; break;
511 case 2: new_event->watching = watch_sim_le_2; break;
512 case 4: new_event->watching = watch_sim_le_4; break;
513 case 8: new_event->watching = watch_sim_le_8; break;
514 default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
518 sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
521 new_event->data = data;
522 new_event->handler = handler;
524 new_event->host_addr = host_addr;
526 new_event->lb64 = lb;
528 new_event->ub64 = ub;
530 new_event->next = events->watchpoints;
531 events->watchpoints = new_event;
532 events->work_pending = 1;
534 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
535 (long)sim_events_time (sd),
537 (long)new_event->host_addr,
540 (long)new_event->handler,
541 (long)new_event->data));
548 sim_events_watch_core (SIM_DESC sd,
549 address_word core_addr,
550 sim_core_maps core_map,
555 sim_event_handler *handler,
558 sim_events *events = STATE_EVENTS (sd);
559 sim_event *new_event = sim_events_zalloc (sd);
566 case 1: new_event->watching = watch_core_targ_1; break;
567 case 2: new_event->watching = watch_core_targ_2; break;
568 case 4: new_event->watching = watch_core_targ_4; break;
569 case 8: new_event->watching = watch_core_targ_8; break;
570 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
576 case 1: new_event->watching = watch_core_be_1; break;
577 case 2: new_event->watching = watch_core_be_2; break;
578 case 4: new_event->watching = watch_core_be_4; break;
579 case 8: new_event->watching = watch_core_be_8; break;
580 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
586 case 1: new_event->watching = watch_core_le_1; break;
587 case 2: new_event->watching = watch_core_le_2; break;
588 case 4: new_event->watching = watch_core_le_4; break;
589 case 8: new_event->watching = watch_core_le_8; break;
590 default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
594 sim_io_error (sd, "sim_events_watch_core - invalid byte order");
597 new_event->data = data;
598 new_event->handler = handler;
600 new_event->core_addr = core_addr;
601 new_event->core_map = core_map;
603 new_event->lb64 = lb;
605 new_event->ub64 = ub;
607 new_event->next = events->watchpoints;
608 events->watchpoints = new_event;
609 events->work_pending = 1;
611 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
612 (long)sim_events_time (sd),
614 (long)new_event->host_addr,
617 (long)new_event->handler,
618 (long)new_event->data));
625 sim_events_deschedule (SIM_DESC sd,
626 sim_event *event_to_remove)
628 sim_events *events = STATE_EVENTS (sd);
629 sim_event *to_remove = (sim_event*)event_to_remove;
630 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
631 if (event_to_remove != NULL)
633 sim_event **queue = NULL;
634 while ((queue = next_event_queue (sd, queue)) != NULL)
636 sim_event **ptr_to_current;
637 for (ptr_to_current = queue;
638 *ptr_to_current != NULL && *ptr_to_current != to_remove;
639 ptr_to_current = &(*ptr_to_current)->next);
640 if (*ptr_to_current == to_remove)
642 sim_event *dead = *ptr_to_current;
643 *ptr_to_current = dead->next;
645 "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
646 (long) sim_events_time (sd),
647 (long) event_to_remove,
648 (long) dead->time_of_event,
649 (long) dead->handler,
651 sim_events_free (sd, dead);
652 update_time_from_event (sd);
653 SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
659 "event/watch descheduled at %ld - tag 0x%lx - not found\n",
660 (long) sim_events_time (sd),
661 (long) event_to_remove));
665 STATIC_INLINE_SIM_EVENTS\
667 sim_watch_valid (SIM_DESC sd,
670 switch (to_do->watching)
673 #define WATCH_CORE(N,OP,EXT) \
676 sim_core_read_buffer (sd, to_do->core_map, &word, to_do->core_addr, sizeof (word)); \
678 return (word >= to_do->lb##EXT && word <= to_do->ub##EXT); \
680 case watch_core_targ_1: WATCH_CORE (1, T2H,);
681 case watch_core_targ_2: WATCH_CORE (2, T2H,);
682 case watch_core_targ_4: WATCH_CORE (4, T2H,);
683 case watch_core_targ_8: WATCH_CORE (8, T2H,64);
685 case watch_core_be_1: WATCH_CORE (1, BE2H,);
686 case watch_core_be_2: WATCH_CORE (2, BE2H,);
687 case watch_core_be_4: WATCH_CORE (4, BE2H,);
688 case watch_core_be_8: WATCH_CORE (8, BE2H,64);
690 case watch_core_le_1: WATCH_CORE (1, LE2H,);
691 case watch_core_le_2: WATCH_CORE (2, LE2H,);
692 case watch_core_le_4: WATCH_CORE (4, LE2H,);
693 case watch_core_le_8: WATCH_CORE (8, LE2H,64);
696 #define WATCH_SIM(N,OP,EXT) \
698 unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
700 return (word >= to_do->lb##EXT && word <= to_do->ub##EXT); \
703 case watch_sim_host_1: WATCH_SIM (1, word = ,);
704 case watch_sim_host_2: WATCH_SIM (2, word = ,);
705 case watch_sim_host_4: WATCH_SIM (4, word = ,);
706 case watch_sim_host_8: WATCH_SIM (8, word = ,64);
708 case watch_sim_be_1: WATCH_SIM (1, BE2H,);
709 case watch_sim_be_2: WATCH_SIM (2, BE2H,);
710 case watch_sim_be_4: WATCH_SIM (4, BE2H,);
711 case watch_sim_be_8: WATCH_SIM (8, BE2H,64);
713 case watch_sim_le_1: WATCH_SIM (1, LE2H,);
714 case watch_sim_le_2: WATCH_SIM (1, LE2H,);
715 case watch_sim_le_4: WATCH_SIM (1, LE2H,);
716 case watch_sim_le_8: WATCH_SIM (1, LE2H,64);
719 case watch_clock: /* wallclock */
721 unsigned long elapsed_time = sim_elapsed_time_since (STATE_EVENTS (sd)->initial_wallclock);
722 return (elapsed_time >= to_do->wallclock);
726 sim_io_error (sd, "sim_watch_valid - bad switch");
736 sim_events_tick (SIM_DESC sd)
738 sim_events *events = STATE_EVENTS (sd);
740 /* this should only be called after the previous ticks have been
742 SIM_ASSERT (events->nr_ticks_to_process == 0);
744 /* Advance the time but *only* if there is nothing to process */
745 if (events->work_pending
746 || events->time_from_event == 0)
748 events->nr_ticks_to_process = 1;
752 events->time_from_event -= 1;
760 sim_events_tickn (SIM_DESC sd,
763 sim_events *events = STATE_EVENTS (sd);
765 /* this should only be called after the previous ticks have been
767 SIM_ASSERT (events->nr_ticks_to_process == 0);
770 /* Advance the time but *only* if there is nothing to process */
771 if (events->work_pending
772 || events->time_from_event < n)
774 events->nr_ticks_to_process = n;
778 events->time_from_event -= n;
786 sim_events_preprocess (SIM_DESC sd,
787 int events_were_last,
788 int events_were_next)
790 sim_events *events = STATE_EVENTS(sd);
791 if (events->nr_ticks_to_process != 0)
793 /* Halted midway through event processing */
794 ASSERT (events_were_last && events_were_next);
795 sim_events_process (sd);
797 else if (events_were_next)
799 /* Halted by the last processor */
800 ASSERT (events->nr_ticks_to_process == 0 && !events_were_last);
801 if (sim_events_tick (sd))
802 sim_events_process (sd);
809 sim_events_process (SIM_DESC sd)
811 sim_events *events = STATE_EVENTS(sd);
812 signed64 event_time = sim_events_time(sd);
814 ASSERT (events->nr_ticks_to_process != 0);
816 /* move any events that were queued by any signal handlers onto
817 the real event queue. */
818 if (events->nr_held > 0)
822 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
826 sigfillset(&new_mask);
827 sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
830 for (i = 0; i < events->nr_held; i++)
832 sim_event *entry = &events->held [i];
833 sim_events_schedule (sd,
834 entry->time_of_event,
840 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
842 sigprocmask(SIG_SETMASK, &old_mask, NULL);
847 /* Process any watchpoints. Be careful to allow a watchpoint to
848 appear/disappear under our feet.
849 To ensure that watchpoints are processed only once per cycle,
850 they are moved onto a watched queue, this returned to the
851 watchpoint queue when all queue processing has been
853 while (events->watchpoints != NULL)
855 sim_event *to_do = events->watchpoints;
856 events->watchpoints = to_do->next;
857 if (sim_watch_valid (sd, to_do))
859 sim_event_handler *handler = to_do->handler;
860 void *data = to_do->data;
861 events->queue = to_do->next;
863 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
868 sim_events_free (sd, to_do);
873 to_do->next = events->watchedpoints;
874 events->watchedpoints = to_do;
878 /* consume all events for this or earlier times. Be careful to
879 allow an event to appear/disappear under our feet */
880 while (events->queue->time_of_event <
881 (event_time + events->nr_ticks_to_process))
883 sim_event *to_do = events->queue;
884 sim_event_handler *handler = to_do->handler;
885 void *data = to_do->data;
886 events->queue = to_do->next;
888 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
893 sim_events_free (sd, to_do);
897 /* put things back where they belong ready for the next iteration */
898 events->watchpoints = events->watchedpoints;
899 events->watchedpoints = NULL;
900 if (events->watchpoints != NULL)
901 events->work_pending = 1;
903 /* re-caculate time for new events then advance the time */
904 update_time_from_event(sd);
905 SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
906 SIM_ASSERT (events->queue != NULL); /* always poll event */
907 events->time_from_event -= events->nr_ticks_to_process;
909 /* this round of processing complete */
910 events->nr_ticks_to_process = 0;