aboutsummaryrefslogtreecommitdiff
path: root/sim/common/sim-events.h
diff options
context:
space:
mode:
Diffstat (limited to 'sim/common/sim-events.h')
-rw-r--r--sim/common/sim-events.h271
1 files changed, 271 insertions, 0 deletions
diff --git a/sim/common/sim-events.h b/sim/common/sim-events.h
new file mode 100644
index 0000000..3bae3df
--- /dev/null
+++ b/sim/common/sim-events.h
@@ -0,0 +1,271 @@
+/* This file is part of the program psim.
+
+ Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+
+
+#ifndef SIM_EVENTS_H
+#define SIM_EVENTS_H
+
+
+/* Notes:
+
+ When scheduling an event, the a delta of zero/one refers to the
+ timeline as follows:
+
+ epoch 0|1 1|2 2|3 3|
+ **queue**|--insn--|*queue*|--insn--|*queue*|--insn--|*queue*|
+ | ^ ^ | ^ ^
+ `- +0 ------------ +1 --.. `----- +0 ------------- +1 --..
+
+ When the queue is initialized, the time is set to zero with a
+ number of initialization events scheduled. Consequently, as also
+ illustrated above, the event queue should be processed before the
+ first instruction. That instruction being executed during tick 1.
+
+ The simulator main loop may take a form similar to:
+
+ if (halt-/restart-setjmp)
+ {
+
+ .... // Determine who should go next
+ last-cpu-nr = get-last-cpu-nr (sd);
+ next-cpu-nr = get-next-cpu-nr (sd);
+ events-were-last? = (last-cpu-nr >= nr-cpus);
+ events-were-next? = (next-cpu-nr >= nr-cpus);
+
+ .... // process any outstanding events
+ sim_events_preprocess (sd, events-were-last?, events-were-next?);
+ if (events-were-next)
+ next-cpu-nr = 0;
+
+ .... // prime main loop
+
+ while (1)
+ {
+ .... // model one insn of next-cpu-nr .. nr-cpus
+ if (sim_events_tick (sd))
+ sim_events_process (sd);
+ next-cpu-nr = 0
+ }
+ }
+
+ NB. In the above pseudo code it is assumed that any cpu-nr >=
+ nr-cpus is a marker for the event queue. */
+
+
+typedef void sim_event_handler(SIM_DESC sd, void *data);
+
+typedef struct _sim_event sim_event;
+
+typedef struct _sim_events sim_events;
+struct _sim_events {
+ int nr_ticks_to_process;
+ sim_event *queue;
+ sim_event *watchpoints;
+ sim_event *watchedpoints;
+ sim_event *free_list;
+ /* flag additional work needed */
+ volatile int work_pending;
+ /* the asynchronous event queue */
+#ifndef MAX_NR_SIGNAL_SIM_EVENTS
+#define MAX_NR_SIGNAL_SIM_EVENTS 2
+#endif
+ sim_event *held;
+ volatile int nr_held;
+ /* timekeeping */
+ unsigned long elapsed_wallclock;
+ SIM_ELAPSED_TIME resume_wallclock;
+ signed64 time_of_event;
+ int time_from_event;
+ int trace;
+};
+
+
+
+/* Install the "events" module. */
+
+extern SIM_RC sim_events_install (SIM_DESC sd);
+
+
+/* Schedule an event DELTA_TIME ticks into the future */
+
+extern sim_event *sim_events_schedule
+(SIM_DESC sd,
+ signed64 delta_time,
+ sim_event_handler *handler,
+ void *data);
+
+extern sim_event *sim_events_schedule_tracef
+(SIM_DESC sd,
+ signed64 delta_time,
+ sim_event_handler *handler,
+ void *data,
+ const char *fmt,
+ ...) __attribute__ ((format (printf, 5, 6)));
+
+extern sim_event *sim_events_schedule_vtracef
+(SIM_DESC sd,
+ signed64 delta_time,
+ sim_event_handler *handler,
+ void *data,
+ const char *fmt,
+ va_list ap);
+
+
+extern void sim_events_schedule_after_signal
+(SIM_DESC sd,
+ signed64 delta_time,
+ sim_event_handler *handler,
+ void *data);
+
+/* NB: signal level events can't have trace strings as malloc isn't
+ available */
+
+
+
+/* Schedule an event milli-seconds from NOW. The exact interpretation
+ of wallclock is host dependant. */
+
+extern sim_event *sim_events_watch_clock
+(SIM_DESC sd,
+ unsigned delta_ms_time,
+ sim_event_handler *handler,
+ void *data);
+
+
+/* Schedule an event when the test (IS_WITHIN == (VAL >= LB && VAL <=
+ UB)) of the NR_BYTES value at HOST_ADDR with BYTE_ORDER endian is
+ true.
+
+ HOST_ADDR: pointer into the host address space.
+ BYTE_ORDER: 0 - host endian; BIG_ENDIAN; LITTLE_ENDIAN */
+
+extern sim_event *sim_events_watch_sim
+(SIM_DESC sd,
+ void *host_addr,
+ int nr_bytes,
+ int byte_order,
+ int is_within,
+ unsigned64 lb,
+ unsigned64 ub,
+ sim_event_handler *handler,
+ void *data);
+
+
+/* Schedule an event when the test (IS_WITHIN == (VAL >= LB && VAL <=
+ UB)) of the NR_BYTES value at CORE_ADDR in BYTE_ORDER endian is
+ true.
+
+ CORE_ADDR/MAP: pointer into the target address space.
+ BYTE_ORDER: 0 - current target endian; BIG_ENDIAN; LITTLE_ENDIAN */
+
+extern sim_event *sim_events_watch_core
+(SIM_DESC sd,
+ address_word core_addr,
+ unsigned map,
+ int nr_bytes,
+ int byte_order,
+ int is_within,
+ unsigned64 lb,
+ unsigned64 ub,
+ sim_event_handler *handler,
+ void *data);
+
+/* Deschedule the specified event */
+
+extern void sim_events_deschedule
+(SIM_DESC sd,
+ sim_event *event_to_remove);
+
+
+/* Prepare for main simulator loop. Ensure that the next thing to do
+ is not event processing.
+
+ If the simulator halted part way through event processing then both
+ EVENTS_WERE_LAST and EVENTS_WERE_NEXT shall be true.
+
+ If the simulator halted after processing the last cpu, then only
+ EVENTS_WERE_NEXT shall be true. */
+
+INLINE_SIM_EVENTS\
+(void) sim_events_preprocess
+(SIM_DESC sd,
+ int events_were_last,
+ int events_were_next);
+
+
+/* Progress time.
+
+ Separated into two parts so that the main loop can save its context
+ before the event queue is processed. When sim_events_tick*()
+ returns true, any simulation context should be saved and
+ sim_events_process() called.
+
+ SIM_EVENTS_TICK advances the clock by 1 cycle.
+
+ SIM_EVENTS_TICKN advances the clock by N cycles (1..MAXINT). */
+
+INLINE_SIM_EVENTS\
+(int) sim_events_tick
+(SIM_DESC sd);
+
+INLINE_SIM_EVENTS\
+(int) sim_events_tickn
+(SIM_DESC sd,
+ int n);
+
+INLINE_SIM_EVENTS\
+(void) sim_events_process
+(SIM_DESC sd);
+
+
+/* Advance the clock by an additional SLIP cycles at the next call to
+ sim_events_tick*(). For multiple calls, the effect is
+ accumulative. */
+
+INLINE_SIM_EVENTS\
+(void) sim_events_slip
+(SIM_DESC sd,
+ int slip);
+
+
+/* Progress time such that an event shall occure upon the next call to
+ sim_events tick */
+
+#if 0
+INLINE_SIM_EVENTS\
+(void) sim_events_timewarp
+(SIM_DESC sd);
+#endif
+
+
+/* local concept of elapsed target time */
+
+INLINE_SIM_EVENTS\
+(signed64) sim_events_time
+(SIM_DESC sd);
+
+
+/* local concept of elapsed host time (milliseconds) */
+
+INLINE_SIM_EVENTS\
+(unsigned long) sim_events_elapsed_time
+(SIM_DESC sd);
+
+#endif