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"
33 /* core - target byte order */
38 /* core - big-endian */
43 /* core - little-endian */
49 /* sim - host byte order */
54 /* sim - big-endian */
59 /* sim - little-endian */
74 sim_watchpoints watching
;
76 sim_event_handler
*handler
;
78 signed64 time_of_event
;
79 /* watch wallclock event */
81 /* watch core address */
82 address_word core_addr
;
83 sim_core_maps core_map
;
86 /* watch core/sim range */
96 /* The event queue maintains a single absolute time using two
99 TIME_OF_EVENT: this holds the time at which the next event is ment
100 to occure. If no next event it will hold the time of the last
103 TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. If an
104 event is pending, this will be positive. If no future event is
105 pending this will be negative. This variable is decremented once
106 for each iteration of a clock cycle.
108 Initially, the clock is started at time one (0) with TIME_OF_EVENT
109 == 0 and TIME_FROM_EVENT == 0.
111 Clearly there is a bug in that this code assumes that the absolute
112 time counter will never become greater than 2^62.
114 To avoid the need to use 64bit arithmetic, the event queue always
115 contains at least one event scheduled every 16 000 ticks. This
116 limits the time from event counter to values less than
120 #if !defined (SIM_EVENTS_POLL_RATE)
121 #define SIM_EVENTS_POLL_RATE 0x4000
128 #define ETRACE(ARGS) \
133 if (STATE_EVENTS (sd)->trace) \
136 SIM_FILTER_PATH (file, __FILE__); \
137 sim_io_printf (sd, "%s:%d: ", file, __LINE__); \
138 sim_io_printf ARGS; \
145 /* event queue iterator */
146 STATIC_INLINE_SIM_EVENTS\
148 next_event_queue (SIM_DESC sd
,
152 return &STATE_EVENTS (sd
)->queue
;
153 else if (queue
== &STATE_EVENTS (sd
)->queue
)
154 return &STATE_EVENTS (sd
)->watchpoints
;
155 else if (queue
== &STATE_EVENTS (sd
)->watchpoints
)
156 return &STATE_EVENTS (sd
)->watchedpoints
;
157 else if (queue
== &STATE_EVENTS (sd
)->watchedpoints
)
160 sim_io_error (sd
, "next_event_queue - bad queue");
165 STATIC_INLINE_SIM_EVENTS\
167 sim_events_poll (SIM_DESC sd
,
170 /* just re-schedule in 1000 million ticks time */
171 sim_events_schedule (sd
, SIM_EVENTS_POLL_RATE
, sim_events_poll
, sd
);
172 sim_io_poll_quit (sd
);
176 /* "events" module install handler.
177 This is called via sim_module_install to install the "events" subsystem
178 into the simulator. */
182 sim_events_install (SIM_DESC sd
)
184 sim_module_add_uninstall_fn (sd
, sim_events_uninstall
);
185 sim_module_add_init_fn (sd
, sim_events_init
);
190 /* Uninstall the "events" subsystem from the simulator. */
194 sim_events_uninstall (SIM_DESC sd
)
196 /* FIXME: free buffers, etc. */
200 /* Initialize the simulator event manager */
204 sim_events_init (SIM_DESC sd
)
206 sim_events
*events
= STATE_EVENTS (sd
);
208 /* drain the interrupt queue */
211 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
214 sigfillset(&new_mask
);
215 /*-LOCK-*/ sigprocmask(SIG_SETMASK
, &new_mask
, &old_mask
);
217 event
= events
->held
;
218 while (event
!= NULL
) {
219 sim_event
*dead
= event
;
224 events
->held_end
= &events
->held
;
225 events
->work_pending
= 0;
226 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
227 /*-UNLOCK-*/ sigprocmask(SIG_SETMASK
, &old_mask
, NULL
);
231 /* drain the normal queues */
233 sim_event
**queue
= NULL
;
234 while ((queue
= next_event_queue (sd
, queue
)) != NULL
)
236 if (queue
== NULL
) break;
237 while (*queue
!= NULL
)
239 sim_event
*dead
= *queue
;
247 /* wind time back to zero */
248 events
->processing
= 1; /* start by doing queue */
249 events
->time_of_event
= 0;
250 events
->time_from_event
= 0;
251 events
->initial_wallclock
= sim_elapsed_time_get ();
253 /* schedule our initial counter event */
254 sim_events_schedule (sd
, 0, sim_events_poll
, sd
);
256 /* from now on, except when the large-int event is being processed
257 the event queue is non empty */
258 SIM_ASSERT (events
->queue
!= NULL
);
266 sim_events_time (SIM_DESC sd
)
268 sim_events
*events
= STATE_EVENTS (sd
);
269 return events
->time_of_event
- events
->time_from_event
;
273 STATIC_INLINE_SIM_EVENTS\
275 update_time_from_event (SIM_DESC sd
)
277 sim_events
*events
= STATE_EVENTS (sd
);
278 signed64 current_time
= sim_events_time (sd
);
279 if (events
->queue
!= NULL
)
281 events
->time_from_event
= (events
->queue
->time_of_event
- current_time
);
282 events
->time_of_event
= events
->queue
->time_of_event
;
286 events
->time_of_event
= current_time
- 1;
287 events
->time_from_event
= -1;
289 SIM_ASSERT (current_time
== sim_events_time (sd
));
290 SIM_ASSERT ((events
->time_from_event
>= 0) == (events
->queue
!= NULL
));
294 STATIC_INLINE_SIM_EVENTS\
296 insert_sim_event (SIM_DESC sd
,
297 sim_event
*new_event
,
300 sim_events
*events
= STATE_EVENTS (sd
);
303 signed64 time_of_event
;
306 sim_io_error (sd
, "what is past is past!\n");
308 /* compute when the event should occure */
309 time_of_event
= sim_events_time (sd
) + delta
;
311 /* find the queue insertion point - things are time ordered */
312 prev
= &events
->queue
;
313 curr
= events
->queue
;
314 while (curr
!= NULL
&& time_of_event
>= curr
->time_of_event
)
316 SIM_ASSERT (curr
->next
== NULL
317 || curr
->time_of_event
<= curr
->next
->time_of_event
);
321 SIM_ASSERT (curr
== NULL
|| time_of_event
< curr
->time_of_event
);
324 new_event
->next
= curr
;
326 new_event
->time_of_event
= time_of_event
;
328 /* adjust the time until the first event */
329 update_time_from_event (sd
);
335 sim_events_schedule (SIM_DESC sd
,
337 sim_event_handler
*handler
,
340 sim_event
*new_event
= ZALLOC(sim_event
);
341 new_event
->data
= data
;
342 new_event
->handler
= handler
;
343 new_event
->watching
= watch_timer
;
344 insert_sim_event(sd
, new_event
, delta_time
);
346 "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
347 (long)sim_events_time(sd
),
349 (long)new_event
->time_of_event
,
350 (long)new_event
->handler
,
351 (long)new_event
->data
));
358 sim_events_schedule_after_signal(SIM_DESC sd
,
360 sim_event_handler
*handler
,
363 sim_events
*events
= STATE_EVENTS (sd
);
364 sim_event
*new_event
= ZALLOC (sim_event
);
366 new_event
->data
= data
;
367 new_event
->handler
= handler
;
368 new_event
->time_of_event
= delta_time
; /* work it out later */
369 new_event
->next
= NULL
;
372 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
376 sigfillset(&new_mask
);
377 sigprocmask (SIG_SETMASK
, &new_mask
, &old_mask
);
379 if (events
->held
== NULL
) {
380 events
->held
= new_event
;
383 *events
->held_end
= new_event
;
385 events
->held_end
= &new_event
->next
;
386 events
->work_pending
= 1; /* notify main process */
387 #if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
389 sigprocmask (SIG_SETMASK
, &old_mask
, NULL
);
394 "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
395 (long)sim_events_time(sd
),
397 (long)new_event
->time_of_event
,
398 (long)new_event
->handler
,
399 (long)new_event
->data
));
407 sim_events_watch_clock (SIM_DESC sd
,
408 unsigned wallclock_ms_time
,
409 sim_event_handler
*handler
,
412 sim_events
*events
= STATE_EVENTS (sd
);
413 sim_event
*new_event
= ZALLOC (sim_event
);
415 new_event
->watching
= watch_clock
;
417 new_event
->data
= data
;
418 new_event
->handler
= handler
;
420 new_event
->wallclock
= wallclock_ms_time
;
422 new_event
->next
= events
->watchpoints
;
423 events
->watchpoints
= new_event
;
424 events
->work_pending
= 1;
426 "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
427 (long)sim_events_time (sd
),
429 (long)new_event
->wallclock
,
430 (long)new_event
->handler
,
431 (long)new_event
->data
));
438 sim_events_watch_sim (SIM_DESC sd
,
444 sim_event_handler
*handler
,
447 sim_events
*events
= STATE_EVENTS (sd
);
448 sim_event
*new_event
= ZALLOC (sim_event
);
455 case 1: new_event
->watching
= watch_sim_host_1
; break;
456 case 2: new_event
->watching
= watch_sim_host_2
; break;
457 case 4: new_event
->watching
= watch_sim_host_4
; break;
458 case 8: new_event
->watching
= watch_sim_host_8
; break;
459 default: sim_io_error (sd
, "sim_events_watch_sim - invalid nr bytes");
465 case 1: new_event
->watching
= watch_sim_be_1
; break;
466 case 2: new_event
->watching
= watch_sim_be_2
; break;
467 case 4: new_event
->watching
= watch_sim_be_4
; break;
468 case 8: new_event
->watching
= watch_sim_be_8
; break;
469 default: sim_io_error (sd
, "sim_events_watch_sim - invalid nr bytes");
475 case 1: new_event
->watching
= watch_sim_le_1
; break;
476 case 2: new_event
->watching
= watch_sim_le_2
; break;
477 case 4: new_event
->watching
= watch_sim_le_4
; break;
478 case 8: new_event
->watching
= watch_sim_le_8
; break;
479 default: sim_io_error (sd
, "sim_events_watch_sim - invalid nr bytes");
483 sim_io_error (sd
, "sim_events_watch_sim - invalid byte order");
486 new_event
->data
= data
;
487 new_event
->handler
= handler
;
489 new_event
->host_addr
= host_addr
;
491 new_event
->lb64
= lb
;
493 new_event
->ub64
= ub
;
495 new_event
->next
= events
->watchpoints
;
496 events
->watchpoints
= new_event
;
497 events
->work_pending
= 1;
499 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
500 (long)sim_events_time (sd
),
502 (long)new_event
->host_addr
,
505 (long)new_event
->handler
,
506 (long)new_event
->data
));
513 sim_events_watch_core (SIM_DESC sd
,
514 address_word core_addr
,
515 sim_core_maps core_map
,
520 sim_event_handler
*handler
,
523 sim_events
*events
= STATE_EVENTS (sd
);
524 sim_event
*new_event
= ZALLOC (sim_event
);
531 case 1: new_event
->watching
= watch_core_targ_1
; break;
532 case 2: new_event
->watching
= watch_core_targ_2
; break;
533 case 4: new_event
->watching
= watch_core_targ_4
; break;
534 case 8: new_event
->watching
= watch_core_targ_8
; break;
535 default: sim_io_error (sd
, "sim_events_watch_core - invalid nr bytes");
541 case 1: new_event
->watching
= watch_core_be_1
; break;
542 case 2: new_event
->watching
= watch_core_be_2
; break;
543 case 4: new_event
->watching
= watch_core_be_4
; break;
544 case 8: new_event
->watching
= watch_core_be_8
; break;
545 default: sim_io_error (sd
, "sim_events_watch_core - invalid nr bytes");
551 case 1: new_event
->watching
= watch_core_le_1
; break;
552 case 2: new_event
->watching
= watch_core_le_2
; break;
553 case 4: new_event
->watching
= watch_core_le_4
; break;
554 case 8: new_event
->watching
= watch_core_le_8
; break;
555 default: sim_io_error (sd
, "sim_events_watch_core - invalid nr bytes");
559 sim_io_error (sd
, "sim_events_watch_core - invalid byte order");
562 new_event
->data
= data
;
563 new_event
->handler
= handler
;
565 new_event
->core_addr
= core_addr
;
566 new_event
->core_map
= core_map
;
568 new_event
->lb64
= lb
;
570 new_event
->ub64
= ub
;
572 new_event
->next
= events
->watchpoints
;
573 events
->watchpoints
= new_event
;
574 events
->work_pending
= 1;
576 "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
577 (long)sim_events_time (sd
),
579 (long)new_event
->host_addr
,
582 (long)new_event
->handler
,
583 (long)new_event
->data
));
590 sim_events_deschedule (SIM_DESC sd
,
591 sim_event
*event_to_remove
)
593 sim_events
*events
= STATE_EVENTS (sd
);
594 sim_event
*to_remove
= (sim_event
*)event_to_remove
;
595 SIM_ASSERT ((events
->time_from_event
>= 0) == (events
->queue
!= NULL
));
596 if (event_to_remove
!= NULL
)
598 sim_event
**queue
= NULL
;
599 while ((queue
= next_event_queue (sd
, queue
)) != NULL
)
601 sim_event
**ptr_to_current
;
602 for (ptr_to_current
= queue
;
603 *ptr_to_current
!= NULL
&& *ptr_to_current
!= to_remove
;
604 ptr_to_current
= &(*ptr_to_current
)->next
);
605 if (*ptr_to_current
== to_remove
)
607 sim_event
*dead
= *ptr_to_current
;
608 *ptr_to_current
= dead
->next
;
610 "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
611 (long) sim_events_time (sd
),
612 (long) event_to_remove
,
613 (long) dead
->time_of_event
,
614 (long) dead
->handler
,
617 update_time_from_event (sd
);
618 SIM_ASSERT ((events
->time_from_event
>= 0) == (events
->queue
!= NULL
));
624 "event/watch descheduled at %ld - tag 0x%lx - not found\n",
625 (long) sim_events_time (sd
),
626 (long) event_to_remove
));
630 STATIC_INLINE_SIM_EVENTS\
632 sim_watch_valid (SIM_DESC sd
,
635 switch (to_do
->watching
)
638 #define WATCH_CORE(N,OP) \
641 sim_core_read_buffer (sd, to_do->core_map, &word, to_do->core_addr, sizeof (word)); \
643 return (word >= to_do->lb && word <= to_do->ub); \
646 case watch_core_targ_1
: WATCH_CORE (1, T2H
);
647 case watch_core_targ_2
: WATCH_CORE (2, T2H
);
648 case watch_core_targ_4
: WATCH_CORE (4, T2H
);
649 case watch_core_targ_8
: WATCH_CORE (8, T2H
);
651 case watch_core_be_1
: WATCH_CORE (1, BE2H
);
652 case watch_core_be_2
: WATCH_CORE (2, BE2H
);
653 case watch_core_be_4
: WATCH_CORE (4, BE2H
);
654 case watch_core_be_8
: WATCH_CORE (8, BE2H
);
656 case watch_core_le_1
: WATCH_CORE (1, LE2H
);
657 case watch_core_le_2
: WATCH_CORE (2, LE2H
);
658 case watch_core_le_4
: WATCH_CORE (4, LE2H
);
659 case watch_core_le_8
: WATCH_CORE (8, LE2H
);
663 #define WATCH_SIM(N,OP) \
665 unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
667 return (word >= to_do->lb && word <= to_do->ub); \
670 case watch_sim_host_1
: WATCH_SIM (1, word
= );
671 case watch_sim_host_2
: WATCH_SIM (2, word
= );
672 case watch_sim_host_4
: WATCH_SIM (4, word
= );
673 case watch_sim_host_8
: WATCH_SIM (8, word
= );
675 case watch_sim_be_1
: WATCH_SIM (1, BE2H
);
676 case watch_sim_be_2
: WATCH_SIM (2, BE2H
);
677 case watch_sim_be_4
: WATCH_SIM (4, BE2H
);
678 case watch_sim_be_8
: WATCH_SIM (8, BE2H
);
680 case watch_sim_le_1
: WATCH_SIM (1, LE2H
);
681 case watch_sim_le_2
: WATCH_SIM (1, LE2H
);
682 case watch_sim_le_4
: WATCH_SIM (1, LE2H
);
683 case watch_sim_le_8
: WATCH_SIM (1, LE2H
);
686 case watch_clock
: /* wallclock */
687 return (sim_elapsed_time_since (STATE_EVENTS (sd
)->initial_wallclock
)
692 sim_io_error (sd
, "sim_watch_valid - bad switch");
702 sim_events_tick (SIM_DESC sd
)
704 sim_events
*events
= STATE_EVENTS (sd
);
706 /* this should only be called after the previous tick has been fully
708 SIM_ASSERT (!events
->processing
);
710 /* Advance the time but *only* if there is nothing to process */
711 if (events
->work_pending
712 || events
->time_from_event
== 0)
714 events
->processing
= 1;
718 events
->time_from_event
-= 1;
726 sim_events_preprocess (SIM_DESC sd
,
727 int events_were_last
,
728 int events_were_next
)
730 sim_events
*events
= STATE_EVENTS(sd
);
731 if (events
->processing
)
733 /* Halted midway through event processing */
734 ASSERT (events_were_last
&& events_were_next
);
735 sim_events_process (sd
);
737 else if (events_were_next
)
739 /* Halted by the last processor */
740 ASSERT (!events
->processing
&& !events_were_last
);
741 if (sim_events_tick (sd
))
742 sim_events_process (sd
);
749 sim_events_process (SIM_DESC sd
)
751 sim_events
*events
= STATE_EVENTS(sd
);
752 signed64 event_time
= sim_events_time(sd
);
754 ASSERT (events
->processing
);
756 /* move any events that were queued by any signal handlers onto
757 the real event queue. */
758 if (events
->held
!= NULL
)
760 sim_event
*held_events
;
761 sim_event
*curr_event
;
763 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
767 sigfillset(&new_mask
);
768 sigprocmask(SIG_SETMASK
, &new_mask
, &old_mask
);
771 held_events
= events
->held
;
773 events
->held_end
= &events
->held
;
774 events
->work_pending
= 0;
776 #if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
778 sigprocmask(SIG_SETMASK
, &old_mask
, NULL
);
783 curr_event
= held_events
;
784 held_events
= curr_event
->next
;
785 insert_sim_event (sd
, curr_event
,
786 curr_event
->time_of_event
);
788 while (held_events
!= NULL
);
791 /* Process any watchpoints. Be careful to allow a watchpoint to
792 appear/disappear under our feet.
793 To ensure that watchpoints are processed only once per cycle,
794 they are moved onto a watched queue, this returned to the
795 watchpoint queue when all queue processing has been
797 while (events
->watchpoints
!= NULL
)
799 sim_event
*to_do
= events
->watchpoints
;
800 events
->watchpoints
= to_do
->next
;
801 if (sim_watch_valid (sd
, to_do
))
803 sim_event_handler
*handler
= to_do
->handler
;
804 void *data
= to_do
->data
;
805 events
->queue
= to_do
->next
;
807 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
817 to_do
->next
= events
->watchedpoints
;
818 events
->watchedpoints
= to_do
;
822 /* consume all events for this or earlier times. Be careful to
823 allow an event to appear/disappear under our feet */
824 while (events
->queue
->time_of_event
<= event_time
)
826 sim_event
*to_do
= events
->queue
;
827 sim_event_handler
*handler
= to_do
->handler
;
828 void *data
= to_do
->data
;
829 events
->queue
= to_do
->next
;
831 "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
840 /* put things back where they belong ready for the next iteration */
841 events
->watchpoints
= events
->watchedpoints
;
842 events
->watchedpoints
= NULL
;
843 if (events
->watchpoints
!= NULL
)
844 events
->work_pending
= 1;
846 /* this round of processing complete */
847 events
->processing
= 0;
849 /* re-caculate time for new events - advance the time */
850 update_time_from_event(sd
);
851 SIM_ASSERT(events
->time_from_event
> 0 && events
->queue
!= NULL
);
852 events
->time_from_event
-= 1;