-/* This file is part of the program psim.
+/* The common simulator framework for GDB, the GNU Debugger.
- Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
+ Copyright 2002, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
- 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.
+ Contributed by Andrew Cagney and Red Hat.
- 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.
-
- */
+ This file is part of GDB.
+
+ 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 3 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, see <http://www.gnu.org/licenses/>. */
#ifndef _SIM_EVENTS_C_
#endif
#endif
-#include <signal.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <signal.h> /* For SIGPROCMASK et al. */
typedef enum {
watch_invalid,
unsigned wallclock;
/* watch core address */
address_word core_addr;
- sim_core_maps core_map;
+ unsigned core_map;
/* watch sim addr */
void *host_addr;
/* watch core/sim range */
+ int is_within; /* 0/1 */
unsigned ub;
unsigned lb;
unsigned64 ub64;
unsigned64 lb64;
+ /* trace info (if any) */
+ char *trace;
/* list */
sim_event *next;
};
variables.
TIME_OF_EVENT: this holds the time at which the next event is ment
- to occure. If no next event it will hold the time of the last
+ to occur. If no next event it will hold the time of the last
event.
- TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. If an
- event is pending, this will be positive. If no future event is
- pending (eg when poll-event is being processed) this will be
- negative. This variable is decremented once for each iteration of
- a clock cycle.
+ TIME_FROM_EVENT: The current distance from TIME_OF_EVENT. A value
+ <= 0 (except when poll-event is being processed) indicates that
+ event processing is due. This variable is decremented once for
+ each iteration of a clock cycle.
Initially, the clock is started at time one (0) with TIME_OF_EVENT
- == 0 and TIME_FROM_EVENT == 0.
+ == 0 and TIME_FROM_EVENT == 0 and with NR_TICKS_TO_PROCESS == 1.
Clearly there is a bug in that this code assumes that the absolute
time counter will never become greater than 2^62.
#if !defined (SIM_EVENTS_POLL_RATE)
-#define SIM_EVENTS_POLL_RATE 0x100000
+#define SIM_EVENTS_POLL_RATE 0x1000
#endif
-#define _ETRACE sd
+#define _ETRACE sd, NULL
+
+#undef ETRACE_P
+#define ETRACE_P (WITH_TRACE && STATE_EVENTS (sd)->trace)
#undef ETRACE
#define ETRACE(ARGS) \
do \
{ \
- if (WITH_TRACE) \
+ if (ETRACE_P) \
{ \
- if (STATE_EVENTS (sd)->trace) \
- { \
- const char *file; \
- SIM_FILTER_PATH (file, __FILE__); \
- sim_io_printf (sd, "%s:%d: ", file, __LINE__); \
- sim_io_printf ARGS; \
- } \
+ if (STRACE_DEBUG_P (sd)) \
+ { \
+ const char *file; \
+ SIM_FILTER_PATH (file, __FILE__); \
+ trace_printf (sd, NULL, "%s:%d: ", file, __LINE__); \
+ } \
+ trace_printf ARGS; \
} \
} \
while (0)
/* event queue iterator - don't iterate over the held queue. */
-STATIC_INLINE_SIM_EVENTS\
-(sim_event **)
+#if EXTERN_SIM_EVENTS_P
+static sim_event **
next_event_queue (SIM_DESC sd,
sim_event **queue)
{
sim_io_error (sd, "next_event_queue - bad queue");
return NULL;
}
+#endif
STATIC_INLINE_SIM_EVENTS\
This is called via sim_module_install to install the "events" subsystem
into the simulator. */
-EXTERN_SIM_EVENTS\
-(SIM_RC)
+#if EXTERN_SIM_EVENTS_P
+STATIC_SIM_EVENTS (MODULE_UNINSTALL_FN) sim_events_uninstall;
+STATIC_SIM_EVENTS (MODULE_INIT_FN) sim_events_init;
+STATIC_SIM_EVENTS (MODULE_RESUME_FN) sim_events_resume;
+STATIC_SIM_EVENTS (MODULE_SUSPEND_FN) sim_events_suspend;
+#endif
+
+#if EXTERN_SIM_EVENTS_P
+SIM_RC
sim_events_install (SIM_DESC sd)
{
SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
sim_module_add_uninstall_fn (sd, sim_events_uninstall);
sim_module_add_init_fn (sd, sim_events_init);
+ sim_module_add_resume_fn (sd, sim_events_resume);
+ sim_module_add_suspend_fn (sd, sim_events_suspend);
+ return SIM_RC_OK;
+}
+#endif
+
+
+/* Suspend/resume the event queue manager when the simulator is not
+ running */
+
+#if EXTERN_SIM_EVENTS_P
+static SIM_RC
+sim_events_resume (SIM_DESC sd)
+{
+ sim_events *events = STATE_EVENTS (sd);
+ SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
+ SIM_ASSERT (events->resume_wallclock == 0);
+ events->resume_wallclock = sim_elapsed_time_get ();
+ return SIM_RC_OK;
+}
+#endif
+
+#if EXTERN_SIM_EVENTS_P
+static SIM_RC
+sim_events_suspend (SIM_DESC sd)
+{
+ sim_events *events = STATE_EVENTS (sd);
+ SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
+ SIM_ASSERT (events->resume_wallclock != 0);
+ events->elapsed_wallclock += sim_elapsed_time_since (events->resume_wallclock);
+ events->resume_wallclock = 0;
return SIM_RC_OK;
}
+#endif
/* Uninstall the "events" subsystem from the simulator. */
-EXTERN_SIM_EVENTS\
-(void)
+#if EXTERN_SIM_EVENTS_P
+static void
sim_events_uninstall (SIM_DESC sd)
{
+ SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
/* FIXME: free buffers, etc. */
}
+#endif
/* malloc/free */
-STATIC_INLINE_SIM_EVENTS\
-(sim_event *)
+#if EXTERN_SIM_EVENTS_P
+static sim_event *
sim_events_zalloc (SIM_DESC sd)
{
sim_events *events = STATE_EVENTS (sd);
}
return new;
}
+#endif
STATIC_INLINE_SIM_EVENTS\
(void)
sim_events *events = STATE_EVENTS (sd);
dead->next = events->free_list;
events->free_list = dead;
+ if (dead->trace != NULL)
+ {
+ free (dead->trace); /* NB: asprintf returns a `free' buf */
+ dead->trace = NULL;
+ }
}
/* Initialize the simulator event manager */
-EXTERN_SIM_EVENTS\
-(SIM_RC)
+#if EXTERN_SIM_EVENTS_P
+SIM_RC
sim_events_init (SIM_DESC sd)
{
sim_events *events = STATE_EVENTS (sd);
/* drain the interrupt queue */
events->nr_held = 0;
if (events->held == NULL)
- events->held = zalloc (sizeof (sim_event) * MAX_NR_SIGNAL_SIM_EVENTS);
+ events->held = NZALLOC (sim_event, MAX_NR_SIGNAL_SIM_EVENTS);
/* drain the normal queues */
{
events->nr_ticks_to_process = 1; /* start by doing queue */
events->time_of_event = 0;
events->time_from_event = 0;
- events->initial_wallclock = sim_elapsed_time_get ();
+ events->elapsed_wallclock = 0;
+ events->resume_wallclock = 0;
/* schedule our initial counter event */
sim_events_schedule (sd, 0, sim_events_poll, sd);
return SIM_RC_OK;
}
+#endif
INLINE_SIM_EVENTS\
sim_events_time (SIM_DESC sd)
{
sim_events *events = STATE_EVENTS (sd);
- return events->time_of_event - events->time_from_event;
+ return (events->time_of_event - events->time_from_event);
}
+INLINE_SIM_EVENTS\
+(unsigned long)
+sim_events_elapsed_time (SIM_DESC sd)
+{
+ unsigned long elapsed = STATE_EVENTS (sd)->elapsed_wallclock;
+
+ /* Are we being called inside sim_resume?
+ (Is there a simulation in progress?) */
+ if (STATE_EVENTS (sd)->resume_wallclock != 0)
+ elapsed += sim_elapsed_time_since (STATE_EVENTS (sd)->resume_wallclock);
+
+ return elapsed;
+}
+
+
+/* Returns the time that remains before the event is raised. */
+INLINE_SIM_EVENTS\
+(signed64)
+sim_events_remain_time (SIM_DESC sd, sim_event *event)
+{
+ if (event == 0)
+ return 0;
+
+ return (event->time_of_event - sim_events_time (sd));
+}
+
+
+
STATIC_INLINE_SIM_EVENTS\
(void)
update_time_from_event (SIM_DESC sd)
signed64 current_time = sim_events_time (sd);
if (events->queue != NULL)
{
- events->time_from_event = (events->queue->time_of_event - current_time);
events->time_of_event = events->queue->time_of_event;
+ events->time_from_event = (events->queue->time_of_event - current_time);
}
else
{
events->time_of_event = current_time - 1;
events->time_from_event = -1;
}
+ if (ETRACE_P)
+ {
+ sim_event *event;
+ int i;
+ for (event = events->queue, i = 0;
+ event != NULL;
+ event = event->next, i++)
+ {
+ ETRACE ((_ETRACE,
+ "event time-from-event - time %ld, delta %ld - event %d, tag 0x%lx, time %ld, handler 0x%lx, data 0x%lx%s%s\n",
+ (long)current_time,
+ (long)events->time_from_event,
+ i,
+ (long)event,
+ (long)event->time_of_event,
+ (long)event->handler,
+ (long)event->data,
+ (event->trace != NULL) ? ", " : "",
+ (event->trace != NULL) ? event->trace : ""));
+ }
+ }
SIM_ASSERT (current_time == sim_events_time (sd));
- SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
}
-STATIC_INLINE_SIM_EVENTS\
-(void)
+#if EXTERN_SIM_EVENTS_P
+static void
insert_sim_event (SIM_DESC sd,
sim_event *new_event,
signed64 delta)
if (delta < 0)
sim_io_error (sd, "what is past is past!\n");
- /* compute when the event should occure */
+ /* compute when the event should occur */
time_of_event = sim_events_time (sd) + delta;
/* find the queue insertion point - things are time ordered */
/* adjust the time until the first event */
update_time_from_event (sd);
}
+#endif
-EXTERN_SIM_EVENTS\
-(sim_event *)
+#if EXTERN_SIM_EVENTS_P
+sim_event *
sim_events_schedule (SIM_DESC sd,
signed64 delta_time,
sim_event_handler *handler,
void *data)
+{
+ va_list dummy;
+ memset (&dummy, 0, sizeof dummy);
+ return sim_events_schedule_vtracef (sd, delta_time, handler, data,
+ NULL, dummy);
+}
+#endif
+
+
+#if EXTERN_SIM_EVENTS_P
+sim_event *
+sim_events_schedule_tracef (SIM_DESC sd,
+ signed64 delta_time,
+ sim_event_handler *handler,
+ void *data,
+ const char *fmt,
+ ...)
+{
+ sim_event *new_event;
+ va_list ap;
+ va_start (ap, fmt);
+ new_event = sim_events_schedule_vtracef (sd, delta_time, handler, data, fmt, ap);
+ va_end (ap);
+ return new_event;
+}
+#endif
+
+
+#if EXTERN_SIM_EVENTS_P
+sim_event *
+sim_events_schedule_vtracef (SIM_DESC sd,
+ signed64 delta_time,
+ sim_event_handler *handler,
+ void *data,
+ const char *fmt,
+ va_list ap)
{
sim_event *new_event = sim_events_zalloc (sd);
new_event->data = data;
new_event->handler = handler;
new_event->watching = watch_timer;
+ if (fmt == NULL || !ETRACE_P || vasprintf (&new_event->trace, fmt, ap) < 0)
+ new_event->trace = NULL;
insert_sim_event(sd, new_event, delta_time);
ETRACE((_ETRACE,
- "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
+ "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
(long)sim_events_time(sd),
(long)new_event,
(long)new_event->time_of_event,
(long)new_event->handler,
- (long)new_event->data));
+ (long)new_event->data,
+ (new_event->trace != NULL) ? ", " : "",
+ (new_event->trace != NULL) ? new_event->trace : ""));
return new_event;
}
+#endif
-EXTERN_SIM_EVENTS\
-(void)
+#if EXTERN_SIM_EVENTS_P
+void
sim_events_schedule_after_signal (SIM_DESC sd,
signed64 delta_time,
sim_event_handler *handler,
/* allocate an event entry from the signal buffer */
new_event = &events->held [events->nr_held];
events->nr_held ++;
- if (events->nr_held >= MAX_NR_SIGNAL_SIM_EVENTS)
+ if (events->nr_held > MAX_NR_SIGNAL_SIM_EVENTS)
{
sim_engine_abort (NULL, NULL, NULL_CIA,
"sim_events_schedule_after_signal - buffer oveflow");
(long)new_event->handler,
(long)new_event->data));
}
+#endif
-EXTERN_SIM_EVENTS\
-(sim_event *)
+#if EXTERN_SIM_EVENTS_P
+sim_event *
sim_events_watch_clock (SIM_DESC sd,
unsigned delta_ms_time,
sim_event_handler *handler,
new_event->data = data;
new_event->handler = handler;
/* data */
- new_event->wallclock = (sim_elapsed_time_since (events->initial_wallclock) + delta_ms_time);
+ if (events->resume_wallclock == 0)
+ new_event->wallclock = (events->elapsed_wallclock + delta_ms_time);
+ else
+ new_event->wallclock = (events->elapsed_wallclock
+ + sim_elapsed_time_since (events->resume_wallclock)
+ + delta_ms_time);
/* insert */
new_event->next = events->watchpoints;
events->watchpoints = new_event;
(long)new_event->data));
return new_event;
}
+#endif
-EXTERN_SIM_EVENTS\
-(sim_event *)
+#if EXTERN_SIM_EVENTS_P
+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,
new_event->lb64 = lb;
new_event->ub = ub;
new_event->ub64 = ub;
+ new_event->is_within = (is_within != 0);
/* insert */
new_event->next = events->watchpoints;
events->watchpoints = new_event;
(long)new_event->data));
return new_event;
}
+#endif
-EXTERN_SIM_EVENTS\
-(sim_event *)
+#if EXTERN_SIM_EVENTS_P
+sim_event *
sim_events_watch_core (SIM_DESC sd,
address_word core_addr,
- sim_core_maps core_map,
+ unsigned core_map,
int nr_bytes,
int byte_order,
+ int is_within,
unsigned64 lb,
unsigned64 ub,
sim_event_handler *handler,
new_event->lb64 = lb;
new_event->ub = ub;
new_event->ub64 = ub;
+ new_event->is_within = (is_within != 0);
/* insert */
new_event->next = events->watchpoints;
events->watchpoints = new_event;
(long)new_event->data));
return new_event;
}
+#endif
-EXTERN_SIM_EVENTS\
-(void)
+#if EXTERN_SIM_EVENTS_P
+void
sim_events_deschedule (SIM_DESC sd,
sim_event *event_to_remove)
{
sim_events *events = STATE_EVENTS (sd);
sim_event *to_remove = (sim_event*)event_to_remove;
- SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
if (event_to_remove != NULL)
{
sim_event **queue = NULL;
sim_event *dead = *ptr_to_current;
*ptr_to_current = dead->next;
ETRACE ((_ETRACE,
- "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
+ "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\n",
(long) sim_events_time (sd),
(long) event_to_remove,
(long) dead->time_of_event,
(long) dead->handler,
- (long) dead->data));
+ (long) dead->data,
+ (dead->trace != NULL) ? ", " : "",
+ (dead->trace != NULL) ? dead->trace : ""));
sim_events_free (sd, dead);
update_time_from_event (sd);
SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
(long) sim_events_time (sd),
(long) event_to_remove));
}
+#endif
STATIC_INLINE_SIM_EVENTS\
{
#define WATCH_CORE(N,OP,EXT) \
- { \
- unsigned_##N word; \
- sim_core_read_buffer (sd, to_do->core_map, &word, to_do->core_addr, sizeof (word)); \
- OP (word); \
- return (word >= to_do->lb##EXT && word <= to_do->ub##EXT); \
+ int ok; \
+ unsigned_##N word = 0; \
+ int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \
+ to_do->core_addr, sizeof (word)); \
+ OP (word); \
+ ok = (nr_read == sizeof (unsigned_##N) \
+ && (to_do->is_within \
+ == (word >= to_do->lb##EXT \
+ && word <= to_do->ub##EXT)));
+
+ case watch_core_targ_1:
+ {
+ WATCH_CORE (1, T2H,);
+ return ok;
+ }
+ case watch_core_targ_2:
+ {
+ WATCH_CORE (2, T2H,);
+ return ok;
+ }
+ case watch_core_targ_4:
+ {
+ WATCH_CORE (4, T2H,);
+ return ok;
+ }
+ case watch_core_targ_8:
+ {
+ WATCH_CORE (8, T2H,64);
+ return ok;
+ }
+
+ case watch_core_be_1:
+ {
+ WATCH_CORE (1, BE2H,);
+ return ok;
+ }
+ case watch_core_be_2:
+ {
+ WATCH_CORE (2, BE2H,);
+ return ok;
+ }
+ case watch_core_be_4:
+ {
+ WATCH_CORE (4, BE2H,);
+ return ok;
+ }
+ case watch_core_be_8:
+ {
+ WATCH_CORE (8, BE2H,64);
+ return ok;
+ }
+
+ case watch_core_le_1:
+ {
+ WATCH_CORE (1, LE2H,);
+ return ok;
+ }
+ case watch_core_le_2:
+ {
+ WATCH_CORE (2, LE2H,);
+ return ok;
+ }
+ case watch_core_le_4:
+ {
+ WATCH_CORE (4, LE2H,);
+ return ok;
+ }
+ case watch_core_le_8:
+ {
+ WATCH_CORE (8, LE2H,64);
+ return ok;
}
- case watch_core_targ_1: WATCH_CORE (1, T2H,);
- case watch_core_targ_2: WATCH_CORE (2, T2H,);
- case watch_core_targ_4: WATCH_CORE (4, T2H,);
- case watch_core_targ_8: WATCH_CORE (8, T2H,64);
-
- case watch_core_be_1: WATCH_CORE (1, BE2H,);
- case watch_core_be_2: WATCH_CORE (2, BE2H,);
- case watch_core_be_4: WATCH_CORE (4, BE2H,);
- case watch_core_be_8: WATCH_CORE (8, BE2H,64);
-
- case watch_core_le_1: WATCH_CORE (1, LE2H,);
- case watch_core_le_2: WATCH_CORE (2, LE2H,);
- case watch_core_le_4: WATCH_CORE (4, LE2H,);
- case watch_core_le_8: WATCH_CORE (8, LE2H,64);
#undef WATCH_CORE
#define WATCH_SIM(N,OP,EXT) \
- { \
- unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
- OP (word); \
- return (word >= to_do->lb##EXT && word <= to_do->ub##EXT); \
+ int ok; \
+ unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
+ OP (word); \
+ ok = (to_do->is_within \
+ == (word >= to_do->lb##EXT \
+ && word <= to_do->ub##EXT));
+
+ case watch_sim_host_1:
+ {
+ WATCH_SIM (1, word = ,);
+ return ok;
+ }
+ case watch_sim_host_2:
+ {
+ WATCH_SIM (2, word = ,);
+ return ok;
+ }
+ case watch_sim_host_4:
+ {
+ WATCH_SIM (4, word = ,);
+ return ok;
+ }
+ case watch_sim_host_8:
+ {
+ WATCH_SIM (8, word = ,64);
+ return ok;
}
- case watch_sim_host_1: WATCH_SIM (1, word = ,);
- case watch_sim_host_2: WATCH_SIM (2, word = ,);
- case watch_sim_host_4: WATCH_SIM (4, word = ,);
- case watch_sim_host_8: WATCH_SIM (8, word = ,64);
-
- case watch_sim_be_1: WATCH_SIM (1, BE2H,);
- case watch_sim_be_2: WATCH_SIM (2, BE2H,);
- case watch_sim_be_4: WATCH_SIM (4, BE2H,);
- case watch_sim_be_8: WATCH_SIM (8, BE2H,64);
+ case watch_sim_be_1:
+ {
+ WATCH_SIM (1, BE2H,);
+ return ok;
+ }
+ case watch_sim_be_2:
+ {
+ WATCH_SIM (2, BE2H,);
+ return ok;
+ }
+ case watch_sim_be_4:
+ {
+ WATCH_SIM (4, BE2H,);
+ return ok;
+ }
+ case watch_sim_be_8:
+ {
+ WATCH_SIM (8, BE2H,64);
+ return ok;
+ }
- case watch_sim_le_1: WATCH_SIM (1, LE2H,);
- case watch_sim_le_2: WATCH_SIM (1, LE2H,);
- case watch_sim_le_4: WATCH_SIM (1, LE2H,);
- case watch_sim_le_8: WATCH_SIM (1, LE2H,64);
+ case watch_sim_le_1:
+ {
+ WATCH_SIM (1, LE2H,);
+ return ok;
+ }
+ case watch_sim_le_2:
+ {
+ WATCH_SIM (1, LE2H,);
+ return ok;
+ }
+ case watch_sim_le_4:
+ {
+ WATCH_SIM (1, LE2H,);
+ return ok;
+ }
+ case watch_sim_le_8:
+ {
+ WATCH_SIM (1, LE2H,64);
+ return ok;
+ }
#undef WATCH_SIM
case watch_clock: /* wallclock */
{
- unsigned long elapsed_time = sim_elapsed_time_since (STATE_EVENTS (sd)->initial_wallclock);
+ unsigned long elapsed_time = sim_events_elapsed_time (sd);
return (elapsed_time >= to_do->wallclock);
}
/* this should only be called after the previous ticks have been
fully processed */
- SIM_ASSERT (events->nr_ticks_to_process == 0);
/* Advance the time but *only* if there is nothing to process */
if (events->work_pending
|| events->time_from_event == 0)
{
- events->nr_ticks_to_process = 1;
+ events->nr_ticks_to_process += 1;
return 1;
}
- else {
- events->time_from_event -= 1;
- return 0;
- }
+ else
+ {
+ events->time_from_event -= 1;
+ return 0;
+ }
}
INLINE_SIM_EVENTS\
(int)
sim_events_tickn (SIM_DESC sd,
- unsigned n)
+ int n)
{
sim_events *events = STATE_EVENTS (sd);
+ SIM_ASSERT (n > 0);
/* this should only be called after the previous ticks have been
fully processed */
- SIM_ASSERT (events->nr_ticks_to_process == 0);
- SIM_ASSERT (n > 0);
/* Advance the time but *only* if there is nothing to process */
- if (events->work_pending
- || events->time_from_event < n)
+ if (events->work_pending || events->time_from_event < n)
{
- events->nr_ticks_to_process = n;
+ events->nr_ticks_to_process += n;
return 1;
}
- else {
- events->time_from_event -= n;
- return 0;
- }
+ else
+ {
+ events->time_from_event -= n;
+ return 0;
+ }
+}
+
+
+INLINE_SIM_EVENTS\
+(void)
+sim_events_slip (SIM_DESC sd,
+ int slip)
+{
+ sim_events *events = STATE_EVENTS (sd);
+ SIM_ASSERT (slip > 0);
+
+ /* Flag a ready event with work_pending instead of number of ticks
+ to process so that the time continues to be correct */
+ if (events->time_from_event < slip)
+ {
+ events->work_pending = 1;
+ }
+ events->time_from_event -= slip;
}
int events_were_next)
{
sim_events *events = STATE_EVENTS(sd);
- if (events->nr_ticks_to_process != 0)
+ if (events_were_last)
{
- /* Halted midway through event processing */
- ASSERT (events_were_last && events_were_next);
+ /* Halted part way through event processing */
+ ASSERT (events->nr_ticks_to_process != 0);
+ /* The external world can't tell if the event that stopped the
+ simulator was the last event to process. */
+ ASSERT (events_were_next);
sim_events_process (sd);
}
else if (events_were_next)
{
/* Halted by the last processor */
- ASSERT (events->nr_ticks_to_process == 0 && !events_were_last);
if (sim_events_tick (sd))
sim_events_process (sd);
}
sim_events *events = STATE_EVENTS(sd);
signed64 event_time = sim_events_time(sd);
- ASSERT (events->nr_ticks_to_process != 0);
+ /* Clear work_pending before checking nr_held. Clearing
+ work_pending after nr_held (with out a lock could loose an
+ event). */
+ events->work_pending = 0;
- /* move any events that were queued by any signal handlers onto
- the real event queue. */
+ /* move any events that were asynchronously queued by any signal
+ handlers onto the real event queue. */
if (events->nr_held > 0)
{
int i;
sigfillset(&new_mask);
sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
#endif
-
+
for (i = 0; i < events->nr_held; i++)
{
sim_event *entry = &events->held [i];
{
sim_event_handler *handler = to_do->handler;
void *data = to_do->data;
- events->queue = to_do->next;
ETRACE((_ETRACE,
- "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
+ "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
(long) event_time,
(long) to_do,
(long) handler,
- (long) data));
+ (long) data,
+ (to_do->trace != NULL) ? ", " : "",
+ (to_do->trace != NULL) ? to_do->trace : ""));
sim_events_free (sd, to_do);
handler (sd, data);
}
sim_event_handler *handler = to_do->handler;
void *data = to_do->data;
events->queue = to_do->next;
+ update_time_from_event (sd);
ETRACE((_ETRACE,
- "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx\n",
+ "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
(long) event_time,
(long) to_do,
(long) handler,
- (long) data));
+ (long) data,
+ (to_do->trace != NULL) ? ", " : "",
+ (to_do->trace != NULL) ? to_do->trace : ""));
sim_events_free (sd, to_do);
handler (sd, data);
}
if (events->watchpoints != NULL)
events->work_pending = 1;
- /* re-caculate time for new events then advance the time */
- update_time_from_event(sd);
+ /* advance the time */
SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
SIM_ASSERT (events->queue != NULL); /* always poll event */
events->time_from_event -= events->nr_ticks_to_process;