NUMBERS_WITH_SUFFIX *doesn't* want to handle 'x', since that is valid
[deliverable/binutils-gdb.git] / sim / common / sim-events.c
index 3d2d005266d76c80592e5232f86c9d7db9706afc..fc211644e85acbbb10c68c078556996dff99b5c6 100644 (file)
 #endif
 #endif
 
-#include <signal.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
 
+#include <signal.h> /* For SIGPROCMASK et.al. */
 
 typedef enum {
   watch_invalid,
@@ -89,7 +92,7 @@ struct _sim_event {
   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 */
@@ -98,6 +101,8 @@ struct _sim_event {
   unsigned lb;
   unsigned64 ub64;
   unsigned64 lb64;
+  /* trace info (if any) */
+  char *trace;
   /* list */
   sim_event *next;
 };
@@ -110,14 +115,13 @@ struct _sim_event {
    to occure.  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.
@@ -129,25 +133,28 @@ struct _sim_event {
 
 
 #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)
@@ -155,8 +162,8 @@ 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)
 {
@@ -172,6 +179,7 @@ next_event_queue (SIM_DESC sd,
     sim_io_error (sd, "next_event_queue - bad queue");
   return NULL;
 }
+#endif
 
 
 STATIC_INLINE_SIM_EVENTS\
@@ -189,31 +197,72 @@ sim_events_poll (SIM_DESC sd,
    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);
@@ -240,6 +289,7 @@ sim_events_zalloc (SIM_DESC sd)
     }
   return new;
 }
+#endif
 
 STATIC_INLINE_SIM_EVENTS\
 (void)
@@ -249,13 +299,18 @@ sim_events_free (SIM_DESC sd,
   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);
@@ -263,7 +318,7 @@ sim_events_init (SIM_DESC 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 */
   {
@@ -285,7 +340,8 @@ sim_events_init (SIM_DESC sd)
   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);
@@ -296,6 +352,7 @@ sim_events_init (SIM_DESC sd)
 
   return SIM_RC_OK;
 }
+#endif
 
 
 INLINE_SIM_EVENTS\
@@ -303,7 +360,22 @@ 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;
 }
 
 
@@ -315,8 +387,8 @@ 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
     {
@@ -324,12 +396,11 @@ update_time_from_event (SIM_DESC sd)
       events->time_from_event = -1;
     }
   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)
@@ -365,33 +436,74 @@ insert_sim_event (SIM_DESC sd,
   /* 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;
+  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,
@@ -410,7 +522,7 @@ sim_events_schedule_after_signal (SIM_DESC sd,
   /* 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");
@@ -436,10 +548,11 @@ sim_events_schedule_after_signal (SIM_DESC sd,
           (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,
@@ -453,7 +566,12 @@ sim_events_watch_clock (SIM_DESC sd,
   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;
@@ -467,10 +585,11 @@ sim_events_watch_clock (SIM_DESC sd,
           (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,
@@ -544,13 +663,14 @@ sim_events_watch_sim (SIM_DESC sd,
           (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,
@@ -623,16 +743,16 @@ sim_events_watch_core (SIM_DESC sd,
           (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;
@@ -647,12 +767,14 @@ sim_events_deschedule (SIM_DESC sd,
              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));
@@ -665,6 +787,7 @@ sim_events_deschedule (SIM_DESC sd,
           (long) sim_events_time (sd),
           (long) event_to_remove));
 }
+#endif
 
 
 STATIC_INLINE_SIM_EVENTS\
@@ -676,59 +799,155 @@ sim_watch_valid (SIM_DESC sd,
     {
 
 #define WATCH_CORE(N,OP,EXT) \
-      { \
-       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); \
-       return (nr_read == sizeof (unsigned_##N) \
-               && (to_do->is_within \
-                   == (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 (to_do->is_within \
-               == (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);
       }
 
@@ -749,45 +968,62 @@ sim_events_tick (SIM_DESC sd)
 
   /* 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;
 }
 
 
@@ -798,16 +1034,18 @@ sim_events_preprocess (SIM_DESC sd,
                       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);
     }
@@ -821,10 +1059,13 @@ sim_events_process (SIM_DESC 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;
@@ -836,7 +1077,7 @@ sim_events_process (SIM_DESC sd)
       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];
@@ -868,13 +1109,14 @@ sim_events_process (SIM_DESC sd)
        {
          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);
        }
@@ -894,12 +1136,15 @@ sim_events_process (SIM_DESC sd)
       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);
     }
@@ -910,8 +1155,7 @@ sim_events_process (SIM_DESC sd)
   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;
This page took 0.03232 seconds and 4 git commands to generate.