OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [sim/] [common/] [sim-events.c] - Diff between revs 827 and 840

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 827 Rev 840
/* The common simulator framework for GDB, the GNU Debugger.
/* The common simulator framework for GDB, the GNU Debugger.
 
 
   Copyright 2002, 2007, 2008 Free Software Foundation, Inc.
   Copyright 2002, 2007, 2008 Free Software Foundation, Inc.
 
 
   Contributed by Andrew Cagney and Red Hat.
   Contributed by Andrew Cagney and Red Hat.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   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
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
 
 
#ifndef _SIM_EVENTS_C_
#ifndef _SIM_EVENTS_C_
#define _SIM_EVENTS_C_
#define _SIM_EVENTS_C_
 
 
#include "sim-main.h"
#include "sim-main.h"
#include "sim-assert.h"
#include "sim-assert.h"
 
 
#ifdef HAVE_STRING_H
#ifdef HAVE_STRING_H
#include <string.h>
#include <string.h>
#else
#else
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRINGS_H
#include <strings.h>
#include <strings.h>
#endif
#endif
#endif
#endif
 
 
#ifdef HAVE_STDLIB_H
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#include <stdlib.h>
#endif
#endif
 
 
#include <signal.h> /* For SIGPROCMASK et al. */
#include <signal.h> /* For SIGPROCMASK et al. */
 
 
typedef enum {
typedef enum {
  watch_invalid,
  watch_invalid,
 
 
  /* core - target byte order */
  /* core - target byte order */
  watch_core_targ_1,
  watch_core_targ_1,
  watch_core_targ_2,
  watch_core_targ_2,
  watch_core_targ_4,
  watch_core_targ_4,
  watch_core_targ_8,
  watch_core_targ_8,
  /* core - big-endian */
  /* core - big-endian */
  watch_core_be_1,
  watch_core_be_1,
  watch_core_be_2,
  watch_core_be_2,
  watch_core_be_4,
  watch_core_be_4,
  watch_core_be_8,
  watch_core_be_8,
  /* core - little-endian */
  /* core - little-endian */
  watch_core_le_1,
  watch_core_le_1,
  watch_core_le_2,
  watch_core_le_2,
  watch_core_le_4,
  watch_core_le_4,
  watch_core_le_8,
  watch_core_le_8,
 
 
  /* sim - host byte order */
  /* sim - host byte order */
  watch_sim_host_1,
  watch_sim_host_1,
  watch_sim_host_2,
  watch_sim_host_2,
  watch_sim_host_4,
  watch_sim_host_4,
  watch_sim_host_8,
  watch_sim_host_8,
  /* sim - big-endian */
  /* sim - big-endian */
  watch_sim_be_1,
  watch_sim_be_1,
  watch_sim_be_2,
  watch_sim_be_2,
  watch_sim_be_4,
  watch_sim_be_4,
  watch_sim_be_8,
  watch_sim_be_8,
  /* sim - little-endian */
  /* sim - little-endian */
  watch_sim_le_1,
  watch_sim_le_1,
  watch_sim_le_2,
  watch_sim_le_2,
  watch_sim_le_4,
  watch_sim_le_4,
  watch_sim_le_8,
  watch_sim_le_8,
 
 
  /* wallclock */
  /* wallclock */
  watch_clock,
  watch_clock,
 
 
  /* timer */
  /* timer */
  watch_timer,
  watch_timer,
} sim_event_watchpoints;
} sim_event_watchpoints;
 
 
 
 
struct _sim_event {
struct _sim_event {
  sim_event_watchpoints watching;
  sim_event_watchpoints watching;
  void *data;
  void *data;
  sim_event_handler *handler;
  sim_event_handler *handler;
  /* timer event */
  /* timer event */
  signed64 time_of_event;
  signed64 time_of_event;
  /* watch wallclock event */
  /* watch wallclock event */
  unsigned wallclock;
  unsigned wallclock;
  /* watch core address */
  /* watch core address */
  address_word core_addr;
  address_word core_addr;
  unsigned core_map;
  unsigned core_map;
  /* watch sim addr */
  /* watch sim addr */
  void *host_addr;
  void *host_addr;
  /* watch core/sim range */
  /* watch core/sim range */
  int is_within; /* 0/1 */
  int is_within; /* 0/1 */
  unsigned ub;
  unsigned ub;
  unsigned lb;
  unsigned lb;
  unsigned64 ub64;
  unsigned64 ub64;
  unsigned64 lb64;
  unsigned64 lb64;
  /* trace info (if any) */
  /* trace info (if any) */
  char *trace;
  char *trace;
  /* list */
  /* list */
  sim_event *next;
  sim_event *next;
};
};
 
 
 
 
/* The event queue maintains a single absolute time using two
/* The event queue maintains a single absolute time using two
   variables.
   variables.
 
 
   TIME_OF_EVENT: this holds the time at which the next event is ment
   TIME_OF_EVENT: this holds the time at which the next event is ment
   to occur.  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.
   event.
 
 
   TIME_FROM_EVENT: The current distance from TIME_OF_EVENT.  A value
   TIME_FROM_EVENT: The current distance from TIME_OF_EVENT.  A value
   <= 0 (except when poll-event is being processed) indicates that
   <= 0 (except when poll-event is being processed) indicates that
   event processing is due.  This variable is decremented once for
   event processing is due.  This variable is decremented once for
   each iteration of a clock cycle.
   each iteration of a clock cycle.
 
 
   Initially, the clock is started at time one (0) with TIME_OF_EVENT
   Initially, the clock is started at time one (0) with TIME_OF_EVENT
   == 0 and TIME_FROM_EVENT == 0 and with NR_TICKS_TO_PROCESS == 1.
   == 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
   Clearly there is a bug in that this code assumes that the absolute
   time counter will never become greater than 2^62.
   time counter will never become greater than 2^62.
 
 
   To avoid the need to use 64bit arithmetic, the event queue always
   To avoid the need to use 64bit arithmetic, the event queue always
   contains at least one event scheduled every 16 000 ticks.  This
   contains at least one event scheduled every 16 000 ticks.  This
   limits the time from event counter to values less than
   limits the time from event counter to values less than
   16 000. */
   16 000. */
 
 
 
 
#if !defined (SIM_EVENTS_POLL_RATE)
#if !defined (SIM_EVENTS_POLL_RATE)
#define SIM_EVENTS_POLL_RATE 0x1000
#define SIM_EVENTS_POLL_RATE 0x1000
#endif
#endif
 
 
 
 
#define _ETRACE sd, NULL
#define _ETRACE sd, NULL
 
 
#undef ETRACE_P
#undef ETRACE_P
#define ETRACE_P (WITH_TRACE && STATE_EVENTS (sd)->trace)
#define ETRACE_P (WITH_TRACE && STATE_EVENTS (sd)->trace)
 
 
#undef ETRACE
#undef ETRACE
#define ETRACE(ARGS) \
#define ETRACE(ARGS) \
do \
do \
  { \
  { \
    if (ETRACE_P) \
    if (ETRACE_P) \
      { \
      { \
        if (STRACE_DEBUG_P (sd)) \
        if (STRACE_DEBUG_P (sd)) \
          { \
          { \
            const char *file; \
            const char *file; \
            SIM_FILTER_PATH (file, __FILE__); \
            SIM_FILTER_PATH (file, __FILE__); \
            trace_printf (sd, NULL, "%s:%d: ", file, __LINE__); \
            trace_printf (sd, NULL, "%s:%d: ", file, __LINE__); \
          } \
          } \
        trace_printf  ARGS; \
        trace_printf  ARGS; \
      } \
      } \
  } \
  } \
while (0)
while (0)
 
 
 
 
/* event queue iterator - don't iterate over the held queue. */
/* event queue iterator - don't iterate over the held queue. */
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
static sim_event **
static sim_event **
next_event_queue (SIM_DESC sd,
next_event_queue (SIM_DESC sd,
                  sim_event **queue)
                  sim_event **queue)
{
{
  if (queue == NULL)
  if (queue == NULL)
    return &STATE_EVENTS (sd)->queue;
    return &STATE_EVENTS (sd)->queue;
  else if (queue == &STATE_EVENTS (sd)->queue)
  else if (queue == &STATE_EVENTS (sd)->queue)
    return &STATE_EVENTS (sd)->watchpoints;
    return &STATE_EVENTS (sd)->watchpoints;
  else if (queue == &STATE_EVENTS (sd)->watchpoints)
  else if (queue == &STATE_EVENTS (sd)->watchpoints)
    return &STATE_EVENTS (sd)->watchedpoints;
    return &STATE_EVENTS (sd)->watchedpoints;
  else if (queue == &STATE_EVENTS (sd)->watchedpoints)
  else if (queue == &STATE_EVENTS (sd)->watchedpoints)
    return NULL;
    return NULL;
  else
  else
    sim_io_error (sd, "next_event_queue - bad queue");
    sim_io_error (sd, "next_event_queue - bad queue");
  return NULL;
  return NULL;
}
}
#endif
#endif
 
 
 
 
STATIC_INLINE_SIM_EVENTS\
STATIC_INLINE_SIM_EVENTS\
(void)
(void)
sim_events_poll (SIM_DESC sd,
sim_events_poll (SIM_DESC sd,
                 void *data)
                 void *data)
{
{
  /* just re-schedule in 1000 million ticks time */
  /* just re-schedule in 1000 million ticks time */
  sim_events_schedule (sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
  sim_events_schedule (sd, SIM_EVENTS_POLL_RATE, sim_events_poll, sd);
  sim_io_poll_quit (sd);
  sim_io_poll_quit (sd);
}
}
 
 
 
 
/* "events" module install handler.
/* "events" module install handler.
   This is called via sim_module_install to install the "events" subsystem
   This is called via sim_module_install to install the "events" subsystem
   into the simulator.  */
   into the simulator.  */
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
STATIC_SIM_EVENTS (MODULE_UNINSTALL_FN) sim_events_uninstall;
STATIC_SIM_EVENTS (MODULE_UNINSTALL_FN) sim_events_uninstall;
STATIC_SIM_EVENTS (MODULE_INIT_FN) sim_events_init;
STATIC_SIM_EVENTS (MODULE_INIT_FN) sim_events_init;
STATIC_SIM_EVENTS (MODULE_RESUME_FN) sim_events_resume;
STATIC_SIM_EVENTS (MODULE_RESUME_FN) sim_events_resume;
STATIC_SIM_EVENTS (MODULE_SUSPEND_FN) sim_events_suspend;
STATIC_SIM_EVENTS (MODULE_SUSPEND_FN) sim_events_suspend;
#endif
#endif
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
SIM_RC
SIM_RC
sim_events_install (SIM_DESC sd)
sim_events_install (SIM_DESC sd)
{
{
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
  sim_module_add_uninstall_fn (sd, sim_events_uninstall);
  sim_module_add_uninstall_fn (sd, sim_events_uninstall);
  sim_module_add_init_fn (sd, sim_events_init);
  sim_module_add_init_fn (sd, sim_events_init);
  sim_module_add_resume_fn (sd, sim_events_resume);
  sim_module_add_resume_fn (sd, sim_events_resume);
  sim_module_add_suspend_fn (sd, sim_events_suspend);
  sim_module_add_suspend_fn (sd, sim_events_suspend);
  return SIM_RC_OK;
  return SIM_RC_OK;
}
}
#endif
#endif
 
 
 
 
/* Suspend/resume the event queue manager when the simulator is not
/* Suspend/resume the event queue manager when the simulator is not
   running */
   running */
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
static SIM_RC
static SIM_RC
sim_events_resume (SIM_DESC sd)
sim_events_resume (SIM_DESC sd)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
  SIM_ASSERT (events->resume_wallclock == 0);
  SIM_ASSERT (events->resume_wallclock == 0);
  events->resume_wallclock = sim_elapsed_time_get ();
  events->resume_wallclock = sim_elapsed_time_get ();
  return SIM_RC_OK;
  return SIM_RC_OK;
}
}
#endif
#endif
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
static SIM_RC
static SIM_RC
sim_events_suspend (SIM_DESC sd)
sim_events_suspend (SIM_DESC sd)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
  SIM_ASSERT (events->resume_wallclock != 0);
  SIM_ASSERT (events->resume_wallclock != 0);
  events->elapsed_wallclock += sim_elapsed_time_since (events->resume_wallclock);
  events->elapsed_wallclock += sim_elapsed_time_since (events->resume_wallclock);
  events->resume_wallclock = 0;
  events->resume_wallclock = 0;
  return SIM_RC_OK;
  return SIM_RC_OK;
}
}
#endif
#endif
 
 
 
 
/* Uninstall the "events" subsystem from the simulator.  */
/* Uninstall the "events" subsystem from the simulator.  */
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
static void
static void
sim_events_uninstall (SIM_DESC sd)
sim_events_uninstall (SIM_DESC sd)
{
{
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
  SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
  /* FIXME: free buffers, etc. */
  /* FIXME: free buffers, etc. */
}
}
#endif
#endif
 
 
 
 
/* malloc/free */
/* malloc/free */
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
static sim_event *
static sim_event *
sim_events_zalloc (SIM_DESC sd)
sim_events_zalloc (SIM_DESC sd)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  sim_event *new = events->free_list;
  sim_event *new = events->free_list;
  if (new != NULL)
  if (new != NULL)
    {
    {
      events->free_list = new->next;
      events->free_list = new->next;
      memset (new, 0, sizeof (*new));
      memset (new, 0, sizeof (*new));
    }
    }
  else
  else
    {
    {
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
      /*-LOCK-*/
      /*-LOCK-*/
      sigset_t old_mask;
      sigset_t old_mask;
      sigset_t new_mask;
      sigset_t new_mask;
      sigfillset(&new_mask);
      sigfillset(&new_mask);
      sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
      sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
#endif
#endif
      new = ZALLOC (sim_event);
      new = ZALLOC (sim_event);
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
      /*-UNLOCK-*/
      /*-UNLOCK-*/
      sigprocmask (SIG_SETMASK, &old_mask, NULL);
      sigprocmask (SIG_SETMASK, &old_mask, NULL);
#endif
#endif
    }
    }
  return new;
  return new;
}
}
#endif
#endif
 
 
STATIC_INLINE_SIM_EVENTS\
STATIC_INLINE_SIM_EVENTS\
(void)
(void)
sim_events_free (SIM_DESC sd,
sim_events_free (SIM_DESC sd,
                 sim_event *dead)
                 sim_event *dead)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  dead->next = events->free_list;
  dead->next = events->free_list;
  events->free_list = dead;
  events->free_list = dead;
  if (dead->trace != NULL)
  if (dead->trace != NULL)
    {
    {
      free (dead->trace); /* NB: asprintf returns a `free' buf */
      free (dead->trace); /* NB: asprintf returns a `free' buf */
      dead->trace = NULL;
      dead->trace = NULL;
    }
    }
}
}
 
 
 
 
/* Initialize the simulator event manager */
/* Initialize the simulator event manager */
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
SIM_RC
SIM_RC
sim_events_init (SIM_DESC sd)
sim_events_init (SIM_DESC sd)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
 
 
  /* drain the interrupt queue */
  /* drain the interrupt queue */
  events->nr_held = 0;
  events->nr_held = 0;
  if (events->held == NULL)
  if (events->held == NULL)
    events->held = NZALLOC (sim_event, MAX_NR_SIGNAL_SIM_EVENTS);
    events->held = NZALLOC (sim_event, MAX_NR_SIGNAL_SIM_EVENTS);
 
 
  /* drain the normal queues */
  /* drain the normal queues */
  {
  {
    sim_event **queue = NULL;
    sim_event **queue = NULL;
    while ((queue = next_event_queue (sd, queue)) != NULL)
    while ((queue = next_event_queue (sd, queue)) != NULL)
      {
      {
        if (queue == NULL) break;
        if (queue == NULL) break;
        while (*queue != NULL)
        while (*queue != NULL)
          {
          {
            sim_event *dead = *queue;
            sim_event *dead = *queue;
            *queue = dead->next;
            *queue = dead->next;
            sim_events_free (sd, dead);
            sim_events_free (sd, dead);
          }
          }
        *queue = NULL;
        *queue = NULL;
      }
      }
  }
  }
 
 
  /* wind time back to zero */
  /* wind time back to zero */
  events->nr_ticks_to_process = 1; /* start by doing queue */
  events->nr_ticks_to_process = 1; /* start by doing queue */
  events->time_of_event = 0;
  events->time_of_event = 0;
  events->time_from_event = 0;
  events->time_from_event = 0;
  events->elapsed_wallclock = 0;
  events->elapsed_wallclock = 0;
  events->resume_wallclock = 0;
  events->resume_wallclock = 0;
 
 
  /* schedule our initial counter event */
  /* schedule our initial counter event */
  sim_events_schedule (sd, 0, sim_events_poll, sd);
  sim_events_schedule (sd, 0, sim_events_poll, sd);
 
 
  /* from now on, except when the large-int event is being processed
  /* from now on, except when the large-int event is being processed
     the event queue is non empty */
     the event queue is non empty */
  SIM_ASSERT (events->queue != NULL);
  SIM_ASSERT (events->queue != NULL);
 
 
  return SIM_RC_OK;
  return SIM_RC_OK;
}
}
#endif
#endif
 
 
 
 
INLINE_SIM_EVENTS\
INLINE_SIM_EVENTS\
(signed64)
(signed64)
sim_events_time (SIM_DESC sd)
sim_events_time (SIM_DESC sd)
{
{
  sim_events *events = STATE_EVENTS (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\
INLINE_SIM_EVENTS\
(unsigned long)
(unsigned long)
sim_events_elapsed_time (SIM_DESC sd)
sim_events_elapsed_time (SIM_DESC sd)
{
{
  unsigned long elapsed = STATE_EVENTS (sd)->elapsed_wallclock;
  unsigned long elapsed = STATE_EVENTS (sd)->elapsed_wallclock;
 
 
  /* Are we being called inside sim_resume?
  /* Are we being called inside sim_resume?
     (Is there a simulation in progress?)  */
     (Is there a simulation in progress?)  */
  if (STATE_EVENTS (sd)->resume_wallclock != 0)
  if (STATE_EVENTS (sd)->resume_wallclock != 0)
     elapsed += sim_elapsed_time_since (STATE_EVENTS (sd)->resume_wallclock);
     elapsed += sim_elapsed_time_since (STATE_EVENTS (sd)->resume_wallclock);
 
 
  return elapsed;
  return elapsed;
}
}
 
 
 
 
/* Returns the time that remains before the event is raised. */
/* Returns the time that remains before the event is raised. */
INLINE_SIM_EVENTS\
INLINE_SIM_EVENTS\
(signed64)
(signed64)
sim_events_remain_time (SIM_DESC sd, sim_event *event)
sim_events_remain_time (SIM_DESC sd, sim_event *event)
{
{
  if (event == 0)
  if (event == 0)
    return 0;
    return 0;
 
 
  return (event->time_of_event - sim_events_time (sd));
  return (event->time_of_event - sim_events_time (sd));
}
}
 
 
 
 
 
 
STATIC_INLINE_SIM_EVENTS\
STATIC_INLINE_SIM_EVENTS\
(void)
(void)
update_time_from_event (SIM_DESC sd)
update_time_from_event (SIM_DESC sd)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  signed64 current_time = sim_events_time (sd);
  signed64 current_time = sim_events_time (sd);
  if (events->queue != NULL)
  if (events->queue != NULL)
    {
    {
      events->time_of_event = events->queue->time_of_event;
      events->time_of_event = events->queue->time_of_event;
      events->time_from_event = (events->queue->time_of_event - current_time);
      events->time_from_event = (events->queue->time_of_event - current_time);
    }
    }
  else
  else
    {
    {
      events->time_of_event = current_time - 1;
      events->time_of_event = current_time - 1;
      events->time_from_event = -1;
      events->time_from_event = -1;
    }
    }
  if (ETRACE_P)
  if (ETRACE_P)
    {
    {
      sim_event *event;
      sim_event *event;
      int i;
      int i;
      for (event = events->queue, i = 0;
      for (event = events->queue, i = 0;
           event != NULL;
           event != NULL;
           event = event->next, i++)
           event = event->next, i++)
        {
        {
          ETRACE ((_ETRACE,
          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",
                   "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)current_time,
                   (long)events->time_from_event,
                   (long)events->time_from_event,
                   i,
                   i,
                   (long)event,
                   (long)event,
                   (long)event->time_of_event,
                   (long)event->time_of_event,
                   (long)event->handler,
                   (long)event->handler,
                   (long)event->data,
                   (long)event->data,
                   (event->trace != NULL) ? ", " : "",
                   (event->trace != NULL) ? ", " : "",
                   (event->trace != NULL) ? event->trace : ""));
                   (event->trace != NULL) ? event->trace : ""));
        }
        }
    }
    }
  SIM_ASSERT (current_time == sim_events_time (sd));
  SIM_ASSERT (current_time == sim_events_time (sd));
}
}
 
 
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
static void
static void
insert_sim_event (SIM_DESC sd,
insert_sim_event (SIM_DESC sd,
                  sim_event *new_event,
                  sim_event *new_event,
                  signed64 delta)
                  signed64 delta)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  sim_event *curr;
  sim_event *curr;
  sim_event **prev;
  sim_event **prev;
  signed64 time_of_event;
  signed64 time_of_event;
 
 
  if (delta < 0)
  if (delta < 0)
    sim_io_error (sd, "what is past is past!\n");
    sim_io_error (sd, "what is past is past!\n");
 
 
  /* compute when the event should occur */
  /* compute when the event should occur */
  time_of_event = sim_events_time (sd) + delta;
  time_of_event = sim_events_time (sd) + delta;
 
 
  /* find the queue insertion point - things are time ordered */
  /* find the queue insertion point - things are time ordered */
  prev = &events->queue;
  prev = &events->queue;
  curr = events->queue;
  curr = events->queue;
  while (curr != NULL && time_of_event >= curr->time_of_event)
  while (curr != NULL && time_of_event >= curr->time_of_event)
    {
    {
      SIM_ASSERT (curr->next == NULL
      SIM_ASSERT (curr->next == NULL
                  || curr->time_of_event <= curr->next->time_of_event);
                  || curr->time_of_event <= curr->next->time_of_event);
      prev = &curr->next;
      prev = &curr->next;
      curr = curr->next;
      curr = curr->next;
    }
    }
  SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
  SIM_ASSERT (curr == NULL || time_of_event < curr->time_of_event);
 
 
  /* insert it */
  /* insert it */
  new_event->next = curr;
  new_event->next = curr;
  *prev = new_event;
  *prev = new_event;
  new_event->time_of_event = time_of_event;
  new_event->time_of_event = time_of_event;
 
 
  /* adjust the time until the first event */
  /* adjust the time until the first event */
  update_time_from_event (sd);
  update_time_from_event (sd);
}
}
#endif
#endif
 
 
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
sim_event *
sim_event *
sim_events_schedule (SIM_DESC sd,
sim_events_schedule (SIM_DESC sd,
                     signed64 delta_time,
                     signed64 delta_time,
                     sim_event_handler *handler,
                     sim_event_handler *handler,
                     void *data)
                     void *data)
{
{
  va_list dummy;
  va_list dummy;
  memset (&dummy, 0, sizeof dummy);
  memset (&dummy, 0, sizeof dummy);
  return sim_events_schedule_vtracef (sd, delta_time, handler, data,
  return sim_events_schedule_vtracef (sd, delta_time, handler, data,
                                      NULL, dummy);
                                      NULL, dummy);
}
}
#endif
#endif
 
 
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
sim_event *
sim_event *
sim_events_schedule_tracef (SIM_DESC sd,
sim_events_schedule_tracef (SIM_DESC sd,
                            signed64 delta_time,
                            signed64 delta_time,
                            sim_event_handler *handler,
                            sim_event_handler *handler,
                            void *data,
                            void *data,
                            const char *fmt,
                            const char *fmt,
                            ...)
                            ...)
{
{
  sim_event *new_event;
  sim_event *new_event;
  va_list ap;
  va_list ap;
  va_start (ap, fmt);
  va_start (ap, fmt);
  new_event = sim_events_schedule_vtracef (sd, delta_time, handler, data, fmt, ap);
  new_event = sim_events_schedule_vtracef (sd, delta_time, handler, data, fmt, ap);
  va_end (ap);
  va_end (ap);
  return new_event;
  return new_event;
}
}
#endif
#endif
 
 
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
sim_event *
sim_event *
sim_events_schedule_vtracef (SIM_DESC sd,
sim_events_schedule_vtracef (SIM_DESC sd,
                             signed64 delta_time,
                             signed64 delta_time,
                             sim_event_handler *handler,
                             sim_event_handler *handler,
                             void *data,
                             void *data,
                             const char *fmt,
                             const char *fmt,
                             va_list ap)
                             va_list ap)
{
{
  sim_event *new_event = sim_events_zalloc (sd);
  sim_event *new_event = sim_events_zalloc (sd);
  new_event->data = data;
  new_event->data = data;
  new_event->handler = handler;
  new_event->handler = handler;
  new_event->watching = watch_timer;
  new_event->watching = watch_timer;
  if (fmt == NULL || !ETRACE_P || vasprintf (&new_event->trace, fmt, ap) < 0)
  if (fmt == NULL || !ETRACE_P || vasprintf (&new_event->trace, fmt, ap) < 0)
    new_event->trace = NULL;
    new_event->trace = NULL;
  insert_sim_event(sd, new_event, delta_time);
  insert_sim_event(sd, new_event, delta_time);
  ETRACE((_ETRACE,
  ETRACE((_ETRACE,
          "event scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\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)sim_events_time(sd),
          (long)new_event,
          (long)new_event,
          (long)new_event->time_of_event,
          (long)new_event->time_of_event,
          (long)new_event->handler,
          (long)new_event->handler,
          (long)new_event->data,
          (long)new_event->data,
          (new_event->trace != NULL) ? ", " : "",
          (new_event->trace != NULL) ? ", " : "",
          (new_event->trace != NULL) ? new_event->trace : ""));
          (new_event->trace != NULL) ? new_event->trace : ""));
  return new_event;
  return new_event;
}
}
#endif
#endif
 
 
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
void
void
sim_events_schedule_after_signal (SIM_DESC sd,
sim_events_schedule_after_signal (SIM_DESC sd,
                                  signed64 delta_time,
                                  signed64 delta_time,
                                  sim_event_handler *handler,
                                  sim_event_handler *handler,
                                  void *data)
                                  void *data)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  sim_event *new_event;
  sim_event *new_event;
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
  /*-LOCK-*/
  /*-LOCK-*/
  sigset_t old_mask;
  sigset_t old_mask;
  sigset_t new_mask;
  sigset_t new_mask;
  sigfillset(&new_mask);
  sigfillset(&new_mask);
  sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
  sigprocmask (SIG_SETMASK, &new_mask, &old_mask);
#endif
#endif
 
 
  /* allocate an event entry from the signal buffer */
  /* allocate an event entry from the signal buffer */
  new_event = &events->held [events->nr_held];
  new_event = &events->held [events->nr_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_engine_abort (NULL, NULL, NULL_CIA,
                        "sim_events_schedule_after_signal - buffer oveflow");
                        "sim_events_schedule_after_signal - buffer oveflow");
    }
    }
 
 
  new_event->data = data;
  new_event->data = data;
  new_event->handler = handler;
  new_event->handler = handler;
  new_event->time_of_event = delta_time; /* work it out later */
  new_event->time_of_event = delta_time; /* work it out later */
  new_event->next = NULL;
  new_event->next = NULL;
 
 
  events->work_pending = 1; /* notify main process */
  events->work_pending = 1; /* notify main process */
 
 
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
#if defined (HAVE_SIGPROCMASK) && defined (SIG_SETMASK)
  /*-UNLOCK-*/
  /*-UNLOCK-*/
  sigprocmask (SIG_SETMASK, &old_mask, NULL);
  sigprocmask (SIG_SETMASK, &old_mask, NULL);
#endif
#endif
 
 
  ETRACE ((_ETRACE,
  ETRACE ((_ETRACE,
           "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
           "signal scheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx\n",
           (long)sim_events_time(sd),
           (long)sim_events_time(sd),
           (long)new_event,
           (long)new_event,
           (long)new_event->time_of_event,
           (long)new_event->time_of_event,
           (long)new_event->handler,
           (long)new_event->handler,
           (long)new_event->data));
           (long)new_event->data));
}
}
#endif
#endif
 
 
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
sim_event *
sim_event *
sim_events_watch_clock (SIM_DESC sd,
sim_events_watch_clock (SIM_DESC sd,
                        unsigned delta_ms_time,
                        unsigned delta_ms_time,
                        sim_event_handler *handler,
                        sim_event_handler *handler,
                        void *data)
                        void *data)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  sim_event *new_event = sim_events_zalloc (sd);
  sim_event *new_event = sim_events_zalloc (sd);
  /* type */
  /* type */
  new_event->watching = watch_clock;
  new_event->watching = watch_clock;
  /* handler */
  /* handler */
  new_event->data = data;
  new_event->data = data;
  new_event->handler = handler;
  new_event->handler = handler;
  /* data */
  /* data */
  if (events->resume_wallclock == 0)
  if (events->resume_wallclock == 0)
    new_event->wallclock = (events->elapsed_wallclock + delta_ms_time);
    new_event->wallclock = (events->elapsed_wallclock + delta_ms_time);
  else
  else
    new_event->wallclock = (events->elapsed_wallclock
    new_event->wallclock = (events->elapsed_wallclock
                            + sim_elapsed_time_since (events->resume_wallclock)
                            + sim_elapsed_time_since (events->resume_wallclock)
                            + delta_ms_time);
                            + delta_ms_time);
  /* insert */
  /* insert */
  new_event->next = events->watchpoints;
  new_event->next = events->watchpoints;
  events->watchpoints = new_event;
  events->watchpoints = new_event;
  events->work_pending = 1;
  events->work_pending = 1;
  ETRACE ((_ETRACE,
  ETRACE ((_ETRACE,
          "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
          "event watching clock at %ld - tag 0x%lx - wallclock %ld, handler 0x%lx, data 0x%lx\n",
           (long)sim_events_time (sd),
           (long)sim_events_time (sd),
           (long)new_event,
           (long)new_event,
           (long)new_event->wallclock,
           (long)new_event->wallclock,
           (long)new_event->handler,
           (long)new_event->handler,
           (long)new_event->data));
           (long)new_event->data));
  return new_event;
  return new_event;
}
}
#endif
#endif
 
 
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
sim_event *
sim_event *
sim_events_watch_sim (SIM_DESC sd,
sim_events_watch_sim (SIM_DESC sd,
                      void *host_addr,
                      void *host_addr,
                      int nr_bytes,
                      int nr_bytes,
                      int byte_order,
                      int byte_order,
                      int is_within,
                      int is_within,
                      unsigned64 lb,
                      unsigned64 lb,
                      unsigned64 ub,
                      unsigned64 ub,
                      sim_event_handler *handler,
                      sim_event_handler *handler,
                      void *data)
                      void *data)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  sim_event *new_event = sim_events_zalloc (sd);
  sim_event *new_event = sim_events_zalloc (sd);
  /* type */
  /* type */
  switch (byte_order)
  switch (byte_order)
    {
    {
    case 0:
    case 0:
      switch (nr_bytes)
      switch (nr_bytes)
        {
        {
        case 1: new_event->watching = watch_sim_host_1; break;
        case 1: new_event->watching = watch_sim_host_1; break;
        case 2: new_event->watching = watch_sim_host_2; break;
        case 2: new_event->watching = watch_sim_host_2; break;
        case 4: new_event->watching = watch_sim_host_4; break;
        case 4: new_event->watching = watch_sim_host_4; break;
        case 8: new_event->watching = watch_sim_host_8; break;
        case 8: new_event->watching = watch_sim_host_8; break;
        default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
        default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
        }
        }
      break;
      break;
    case BIG_ENDIAN:
    case BIG_ENDIAN:
      switch (nr_bytes)
      switch (nr_bytes)
        {
        {
        case 1: new_event->watching = watch_sim_be_1; break;
        case 1: new_event->watching = watch_sim_be_1; break;
        case 2: new_event->watching = watch_sim_be_2; break;
        case 2: new_event->watching = watch_sim_be_2; break;
        case 4: new_event->watching = watch_sim_be_4; break;
        case 4: new_event->watching = watch_sim_be_4; break;
        case 8: new_event->watching = watch_sim_be_8; break;
        case 8: new_event->watching = watch_sim_be_8; break;
        default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
        default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
        }
        }
      break;
      break;
    case LITTLE_ENDIAN:
    case LITTLE_ENDIAN:
      switch (nr_bytes)
      switch (nr_bytes)
        {
        {
        case 1: new_event->watching = watch_sim_le_1; break;
        case 1: new_event->watching = watch_sim_le_1; break;
        case 2: new_event->watching = watch_sim_le_2; break;
        case 2: new_event->watching = watch_sim_le_2; break;
        case 4: new_event->watching = watch_sim_le_4; break;
        case 4: new_event->watching = watch_sim_le_4; break;
        case 8: new_event->watching = watch_sim_le_8; break;
        case 8: new_event->watching = watch_sim_le_8; break;
        default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
        default: sim_io_error (sd, "sim_events_watch_sim - invalid nr bytes");
        }
        }
      break;
      break;
    default:
    default:
      sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
      sim_io_error (sd, "sim_events_watch_sim - invalid byte order");
    }
    }
  /* handler */
  /* handler */
  new_event->data = data;
  new_event->data = data;
  new_event->handler = handler;
  new_event->handler = handler;
  /* data */
  /* data */
  new_event->host_addr = host_addr;
  new_event->host_addr = host_addr;
  new_event->lb = lb;
  new_event->lb = lb;
  new_event->lb64 = lb;
  new_event->lb64 = lb;
  new_event->ub = ub;
  new_event->ub = ub;
  new_event->ub64 = ub;
  new_event->ub64 = ub;
  new_event->is_within = (is_within != 0);
  new_event->is_within = (is_within != 0);
  /* insert */
  /* insert */
  new_event->next = events->watchpoints;
  new_event->next = events->watchpoints;
  events->watchpoints = new_event;
  events->watchpoints = new_event;
  events->work_pending = 1;
  events->work_pending = 1;
  ETRACE ((_ETRACE,
  ETRACE ((_ETRACE,
           "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
           "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
           (long)sim_events_time (sd),
           (long)sim_events_time (sd),
           (long)new_event,
           (long)new_event,
           (long)new_event->host_addr,
           (long)new_event->host_addr,
           (long)new_event->lb,
           (long)new_event->lb,
           (long)new_event->ub,
           (long)new_event->ub,
           (long)new_event->handler,
           (long)new_event->handler,
           (long)new_event->data));
           (long)new_event->data));
  return new_event;
  return new_event;
}
}
#endif
#endif
 
 
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
sim_event *
sim_event *
sim_events_watch_core (SIM_DESC sd,
sim_events_watch_core (SIM_DESC sd,
                       address_word core_addr,
                       address_word core_addr,
                       unsigned core_map,
                       unsigned core_map,
                       int nr_bytes,
                       int nr_bytes,
                       int byte_order,
                       int byte_order,
                       int is_within,
                       int is_within,
                       unsigned64 lb,
                       unsigned64 lb,
                       unsigned64 ub,
                       unsigned64 ub,
                       sim_event_handler *handler,
                       sim_event_handler *handler,
                       void *data)
                       void *data)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  sim_event *new_event = sim_events_zalloc (sd);
  sim_event *new_event = sim_events_zalloc (sd);
  /* type */
  /* type */
  switch (byte_order)
  switch (byte_order)
    {
    {
    case 0:
    case 0:
      switch (nr_bytes)
      switch (nr_bytes)
        {
        {
        case 1: new_event->watching = watch_core_targ_1; break;
        case 1: new_event->watching = watch_core_targ_1; break;
        case 2: new_event->watching = watch_core_targ_2; break;
        case 2: new_event->watching = watch_core_targ_2; break;
        case 4: new_event->watching = watch_core_targ_4; break;
        case 4: new_event->watching = watch_core_targ_4; break;
        case 8: new_event->watching = watch_core_targ_8; break;
        case 8: new_event->watching = watch_core_targ_8; break;
        default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
        default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
        }
        }
      break;
      break;
    case BIG_ENDIAN:
    case BIG_ENDIAN:
      switch (nr_bytes)
      switch (nr_bytes)
        {
        {
        case 1: new_event->watching = watch_core_be_1; break;
        case 1: new_event->watching = watch_core_be_1; break;
        case 2: new_event->watching = watch_core_be_2; break;
        case 2: new_event->watching = watch_core_be_2; break;
        case 4: new_event->watching = watch_core_be_4; break;
        case 4: new_event->watching = watch_core_be_4; break;
        case 8: new_event->watching = watch_core_be_8; break;
        case 8: new_event->watching = watch_core_be_8; break;
        default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
        default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
        }
        }
      break;
      break;
    case LITTLE_ENDIAN:
    case LITTLE_ENDIAN:
      switch (nr_bytes)
      switch (nr_bytes)
        {
        {
        case 1: new_event->watching = watch_core_le_1; break;
        case 1: new_event->watching = watch_core_le_1; break;
        case 2: new_event->watching = watch_core_le_2; break;
        case 2: new_event->watching = watch_core_le_2; break;
        case 4: new_event->watching = watch_core_le_4; break;
        case 4: new_event->watching = watch_core_le_4; break;
        case 8: new_event->watching = watch_core_le_8; break;
        case 8: new_event->watching = watch_core_le_8; break;
        default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
        default: sim_io_error (sd, "sim_events_watch_core - invalid nr bytes");
        }
        }
      break;
      break;
    default:
    default:
      sim_io_error (sd, "sim_events_watch_core - invalid byte order");
      sim_io_error (sd, "sim_events_watch_core - invalid byte order");
    }
    }
  /* handler */
  /* handler */
  new_event->data = data;
  new_event->data = data;
  new_event->handler = handler;
  new_event->handler = handler;
  /* data */
  /* data */
  new_event->core_addr = core_addr;
  new_event->core_addr = core_addr;
  new_event->core_map = core_map;
  new_event->core_map = core_map;
  new_event->lb = lb;
  new_event->lb = lb;
  new_event->lb64 = lb;
  new_event->lb64 = lb;
  new_event->ub = ub;
  new_event->ub = ub;
  new_event->ub64 = ub;
  new_event->ub64 = ub;
  new_event->is_within = (is_within != 0);
  new_event->is_within = (is_within != 0);
  /* insert */
  /* insert */
  new_event->next = events->watchpoints;
  new_event->next = events->watchpoints;
  events->watchpoints = new_event;
  events->watchpoints = new_event;
  events->work_pending = 1;
  events->work_pending = 1;
  ETRACE ((_ETRACE,
  ETRACE ((_ETRACE,
           "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
           "event watching host at %ld - tag 0x%lx - host-addr 0x%lx, 0x%lx..0x%lx, handler 0x%lx, data 0x%lx\n",
           (long)sim_events_time (sd),
           (long)sim_events_time (sd),
           (long)new_event,
           (long)new_event,
           (long)new_event->host_addr,
           (long)new_event->host_addr,
           (long)new_event->lb,
           (long)new_event->lb,
           (long)new_event->ub,
           (long)new_event->ub,
           (long)new_event->handler,
           (long)new_event->handler,
           (long)new_event->data));
           (long)new_event->data));
  return new_event;
  return new_event;
}
}
#endif
#endif
 
 
 
 
#if EXTERN_SIM_EVENTS_P
#if EXTERN_SIM_EVENTS_P
void
void
sim_events_deschedule (SIM_DESC sd,
sim_events_deschedule (SIM_DESC sd,
                       sim_event *event_to_remove)
                       sim_event *event_to_remove)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  sim_event *to_remove = (sim_event*)event_to_remove;
  sim_event *to_remove = (sim_event*)event_to_remove;
  if (event_to_remove != NULL)
  if (event_to_remove != NULL)
    {
    {
      sim_event **queue = NULL;
      sim_event **queue = NULL;
      while ((queue = next_event_queue (sd, queue)) != NULL)
      while ((queue = next_event_queue (sd, queue)) != NULL)
        {
        {
          sim_event **ptr_to_current;
          sim_event **ptr_to_current;
          for (ptr_to_current = queue;
          for (ptr_to_current = queue;
               *ptr_to_current != NULL && *ptr_to_current != to_remove;
               *ptr_to_current != NULL && *ptr_to_current != to_remove;
               ptr_to_current = &(*ptr_to_current)->next);
               ptr_to_current = &(*ptr_to_current)->next);
          if (*ptr_to_current == to_remove)
          if (*ptr_to_current == to_remove)
            {
            {
              sim_event *dead = *ptr_to_current;
              sim_event *dead = *ptr_to_current;
              *ptr_to_current = dead->next;
              *ptr_to_current = dead->next;
              ETRACE ((_ETRACE,
              ETRACE ((_ETRACE,
                       "event/watch descheduled at %ld - tag 0x%lx - time %ld, handler 0x%lx, data 0x%lx%s%s\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) sim_events_time (sd),
                       (long) event_to_remove,
                       (long) event_to_remove,
                       (long) dead->time_of_event,
                       (long) dead->time_of_event,
                       (long) dead->handler,
                       (long) dead->handler,
                       (long) dead->data,
                       (long) dead->data,
                       (dead->trace != NULL) ? ", " : "",
                       (dead->trace != NULL) ? ", " : "",
                       (dead->trace != NULL) ? dead->trace : ""));
                       (dead->trace != NULL) ? dead->trace : ""));
              sim_events_free (sd, dead);
              sim_events_free (sd, dead);
              update_time_from_event (sd);
              update_time_from_event (sd);
              SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
              SIM_ASSERT ((events->time_from_event >= 0) == (events->queue != NULL));
              return;
              return;
            }
            }
        }
        }
    }
    }
  ETRACE ((_ETRACE,
  ETRACE ((_ETRACE,
           "event/watch descheduled at %ld - tag 0x%lx - not found\n",
           "event/watch descheduled at %ld - tag 0x%lx - not found\n",
           (long) sim_events_time (sd),
           (long) sim_events_time (sd),
           (long) event_to_remove));
           (long) event_to_remove));
}
}
#endif
#endif
 
 
 
 
STATIC_INLINE_SIM_EVENTS\
STATIC_INLINE_SIM_EVENTS\
(int)
(int)
sim_watch_valid (SIM_DESC sd,
sim_watch_valid (SIM_DESC sd,
                 sim_event *to_do)
                 sim_event *to_do)
{
{
  switch (to_do->watching)
  switch (to_do->watching)
    {
    {
 
 
#define WATCH_CORE(N,OP,EXT) \
#define WATCH_CORE(N,OP,EXT) \
      int ok; \
      int ok; \
      unsigned_##N word = 0; \
      unsigned_##N word = 0; \
      int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \
      int nr_read = sim_core_read_buffer (sd, NULL, to_do->core_map, &word, \
                                          to_do->core_addr, sizeof (word)); \
                                          to_do->core_addr, sizeof (word)); \
      OP (word); \
      OP (word); \
      ok = (nr_read == sizeof (unsigned_##N) \
      ok = (nr_read == sizeof (unsigned_##N) \
            && (to_do->is_within \
            && (to_do->is_within \
                == (word >= to_do->lb##EXT \
                == (word >= to_do->lb##EXT \
                    && word <= to_do->ub##EXT)));
                    && word <= to_do->ub##EXT)));
 
 
    case watch_core_targ_1:
    case watch_core_targ_1:
      {
      {
        WATCH_CORE (1, T2H,);
        WATCH_CORE (1, T2H,);
        return ok;
        return ok;
      }
      }
    case watch_core_targ_2:
    case watch_core_targ_2:
      {
      {
        WATCH_CORE (2, T2H,);
        WATCH_CORE (2, T2H,);
        return ok;
        return ok;
      }
      }
    case watch_core_targ_4:
    case watch_core_targ_4:
      {
      {
        WATCH_CORE (4, T2H,);
        WATCH_CORE (4, T2H,);
        return ok;
        return ok;
      }
      }
    case watch_core_targ_8:
    case watch_core_targ_8:
      {
      {
        WATCH_CORE (8, T2H,64);
        WATCH_CORE (8, T2H,64);
        return ok;
        return ok;
      }
      }
 
 
    case watch_core_be_1:
    case watch_core_be_1:
      {
      {
        WATCH_CORE (1, BE2H,);
        WATCH_CORE (1, BE2H,);
        return ok;
        return ok;
      }
      }
    case watch_core_be_2:
    case watch_core_be_2:
      {
      {
        WATCH_CORE (2, BE2H,);
        WATCH_CORE (2, BE2H,);
        return ok;
        return ok;
      }
      }
    case watch_core_be_4:
    case watch_core_be_4:
      {
      {
        WATCH_CORE (4, BE2H,);
        WATCH_CORE (4, BE2H,);
        return ok;
        return ok;
      }
      }
    case watch_core_be_8:
    case watch_core_be_8:
      {
      {
        WATCH_CORE (8, BE2H,64);
        WATCH_CORE (8, BE2H,64);
        return ok;
        return ok;
      }
      }
 
 
    case watch_core_le_1:
    case watch_core_le_1:
      {
      {
        WATCH_CORE (1, LE2H,);
        WATCH_CORE (1, LE2H,);
        return ok;
        return ok;
      }
      }
    case watch_core_le_2:
    case watch_core_le_2:
      {
      {
        WATCH_CORE (2, LE2H,);
        WATCH_CORE (2, LE2H,);
        return ok;
        return ok;
      }
      }
    case watch_core_le_4:
    case watch_core_le_4:
      {
      {
        WATCH_CORE (4, LE2H,);
        WATCH_CORE (4, LE2H,);
        return ok;
        return ok;
      }
      }
    case watch_core_le_8:
    case watch_core_le_8:
      {
      {
        WATCH_CORE (8, LE2H,64);
        WATCH_CORE (8, LE2H,64);
        return ok;
        return ok;
      }
      }
#undef WATCH_CORE
#undef WATCH_CORE
 
 
#define WATCH_SIM(N,OP,EXT) \
#define WATCH_SIM(N,OP,EXT) \
      int ok; \
      int ok; \
      unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
      unsigned_##N word = *(unsigned_##N*)to_do->host_addr; \
      OP (word); \
      OP (word); \
      ok = (to_do->is_within \
      ok = (to_do->is_within \
            == (word >= to_do->lb##EXT \
            == (word >= to_do->lb##EXT \
                && word <= to_do->ub##EXT));
                && word <= to_do->ub##EXT));
 
 
    case watch_sim_host_1:
    case watch_sim_host_1:
      {
      {
        WATCH_SIM (1, word = ,);
        WATCH_SIM (1, word = ,);
        return ok;
        return ok;
      }
      }
    case watch_sim_host_2:
    case watch_sim_host_2:
      {
      {
        WATCH_SIM (2, word = ,);
        WATCH_SIM (2, word = ,);
        return ok;
        return ok;
      }
      }
    case watch_sim_host_4:
    case watch_sim_host_4:
      {
      {
        WATCH_SIM (4, word = ,);
        WATCH_SIM (4, word = ,);
        return ok;
        return ok;
      }
      }
    case watch_sim_host_8:
    case watch_sim_host_8:
      {
      {
        WATCH_SIM (8, word = ,64);
        WATCH_SIM (8, word = ,64);
        return ok;
        return ok;
      }
      }
 
 
    case watch_sim_be_1:
    case watch_sim_be_1:
      {
      {
        WATCH_SIM (1, BE2H,);
        WATCH_SIM (1, BE2H,);
        return ok;
        return ok;
      }
      }
    case watch_sim_be_2:
    case watch_sim_be_2:
      {
      {
        WATCH_SIM (2, BE2H,);
        WATCH_SIM (2, BE2H,);
        return ok;
        return ok;
      }
      }
    case watch_sim_be_4:
    case watch_sim_be_4:
      {
      {
        WATCH_SIM (4, BE2H,);
        WATCH_SIM (4, BE2H,);
        return ok;
        return ok;
      }
      }
    case watch_sim_be_8:
    case watch_sim_be_8:
      {
      {
        WATCH_SIM (8, BE2H,64);
        WATCH_SIM (8, BE2H,64);
        return ok;
        return ok;
      }
      }
 
 
    case watch_sim_le_1:
    case watch_sim_le_1:
      {
      {
        WATCH_SIM (1, LE2H,);
        WATCH_SIM (1, LE2H,);
        return ok;
        return ok;
      }
      }
    case watch_sim_le_2:
    case watch_sim_le_2:
      {
      {
        WATCH_SIM (1, LE2H,);
        WATCH_SIM (1, LE2H,);
        return ok;
        return ok;
      }
      }
    case watch_sim_le_4:
    case watch_sim_le_4:
      {
      {
        WATCH_SIM (1, LE2H,);
        WATCH_SIM (1, LE2H,);
        return ok;
        return ok;
      }
      }
    case watch_sim_le_8:
    case watch_sim_le_8:
      {
      {
        WATCH_SIM (1, LE2H,64);
        WATCH_SIM (1, LE2H,64);
        return ok;
        return ok;
      }
      }
#undef WATCH_SIM
#undef WATCH_SIM
 
 
    case watch_clock: /* wallclock */
    case watch_clock: /* wallclock */
      {
      {
        unsigned long elapsed_time = sim_events_elapsed_time (sd);
        unsigned long elapsed_time = sim_events_elapsed_time (sd);
        return (elapsed_time >= to_do->wallclock);
        return (elapsed_time >= to_do->wallclock);
      }
      }
 
 
    default:
    default:
      sim_io_error (sd, "sim_watch_valid - bad switch");
      sim_io_error (sd, "sim_watch_valid - bad switch");
      break;
      break;
 
 
    }
    }
  return 1;
  return 1;
}
}
 
 
 
 
INLINE_SIM_EVENTS\
INLINE_SIM_EVENTS\
(int)
(int)
sim_events_tick (SIM_DESC sd)
sim_events_tick (SIM_DESC sd)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
 
 
  /* this should only be called after the previous ticks have been
  /* this should only be called after the previous ticks have been
     fully processed */
     fully processed */
 
 
  /* Advance the time but *only* if there is nothing to process */
  /* Advance the time but *only* if there is nothing to process */
  if (events->work_pending
  if (events->work_pending
      || events->time_from_event == 0)
      || events->time_from_event == 0)
    {
    {
      events->nr_ticks_to_process += 1;
      events->nr_ticks_to_process += 1;
      return 1;
      return 1;
    }
    }
  else
  else
    {
    {
      events->time_from_event -= 1;
      events->time_from_event -= 1;
      return 0;
      return 0;
    }
    }
}
}
 
 
 
 
INLINE_SIM_EVENTS\
INLINE_SIM_EVENTS\
(int)
(int)
sim_events_tickn (SIM_DESC sd,
sim_events_tickn (SIM_DESC sd,
                  int n)
                  int n)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  SIM_ASSERT (n > 0);
  SIM_ASSERT (n > 0);
 
 
  /* this should only be called after the previous ticks have been
  /* this should only be called after the previous ticks have been
     fully processed */
     fully processed */
 
 
  /* Advance the time but *only* if there is nothing to process */
  /* 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;
      return 1;
    }
    }
  else
  else
    {
    {
      events->time_from_event -= n;
      events->time_from_event -= n;
      return 0;
      return 0;
    }
    }
}
}
 
 
 
 
INLINE_SIM_EVENTS\
INLINE_SIM_EVENTS\
(void)
(void)
sim_events_slip (SIM_DESC sd,
sim_events_slip (SIM_DESC sd,
                 int slip)
                 int slip)
{
{
  sim_events *events = STATE_EVENTS (sd);
  sim_events *events = STATE_EVENTS (sd);
  SIM_ASSERT (slip > 0);
  SIM_ASSERT (slip > 0);
 
 
  /* Flag a ready event with work_pending instead of number of ticks
  /* Flag a ready event with work_pending instead of number of ticks
     to process so that the time continues to be correct */
     to process so that the time continues to be correct */
  if (events->time_from_event < slip)
  if (events->time_from_event < slip)
    {
    {
      events->work_pending = 1;
      events->work_pending = 1;
    }
    }
  events->time_from_event -= slip;
  events->time_from_event -= slip;
}
}
 
 
 
 
INLINE_SIM_EVENTS\
INLINE_SIM_EVENTS\
(void)
(void)
sim_events_preprocess (SIM_DESC sd,
sim_events_preprocess (SIM_DESC sd,
                       int events_were_last,
                       int events_were_last,
                       int events_were_next)
                       int events_were_next)
{
{
  sim_events *events = STATE_EVENTS(sd);
  sim_events *events = STATE_EVENTS(sd);
  if (events_were_last)
  if (events_were_last)
    {
    {
      /* Halted part way through event processing */
      /* Halted part way through event processing */
      ASSERT (events->nr_ticks_to_process != 0);
      ASSERT (events->nr_ticks_to_process != 0);
      /* The external world can't tell if the event that stopped the
      /* The external world can't tell if the event that stopped the
         simulator was the last event to process. */
         simulator was the last event to process. */
      ASSERT (events_were_next);
      ASSERT (events_were_next);
      sim_events_process (sd);
      sim_events_process (sd);
    }
    }
  else if (events_were_next)
  else if (events_were_next)
    {
    {
      /* Halted by the last processor */
      /* Halted by the last processor */
      if (sim_events_tick (sd))
      if (sim_events_tick (sd))
        sim_events_process (sd);
        sim_events_process (sd);
    }
    }
}
}
 
 
 
 
INLINE_SIM_EVENTS\
INLINE_SIM_EVENTS\
(void)
(void)
sim_events_process (SIM_DESC sd)
sim_events_process (SIM_DESC sd)
{
{
  sim_events *events = STATE_EVENTS(sd);
  sim_events *events = STATE_EVENTS(sd);
  signed64 event_time = sim_events_time(sd);
  signed64 event_time = sim_events_time(sd);
 
 
  /* Clear work_pending before checking nr_held.  Clearing
  /* Clear work_pending before checking nr_held.  Clearing
     work_pending after nr_held (with out a lock could loose an
     work_pending after nr_held (with out a lock could loose an
     event). */
     event). */
  events->work_pending = 0;
  events->work_pending = 0;
 
 
  /* move any events that were asynchronously queued by any signal
  /* move any events that were asynchronously queued by any signal
     handlers onto the real event queue.  */
     handlers onto the real event queue.  */
  if (events->nr_held > 0)
  if (events->nr_held > 0)
    {
    {
      int i;
      int i;
 
 
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
      /*-LOCK-*/
      /*-LOCK-*/
      sigset_t old_mask;
      sigset_t old_mask;
      sigset_t new_mask;
      sigset_t new_mask;
      sigfillset(&new_mask);
      sigfillset(&new_mask);
      sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
      sigprocmask(SIG_SETMASK, &new_mask, &old_mask);
#endif
#endif
 
 
      for (i = 0; i < events->nr_held; i++)
      for (i = 0; i < events->nr_held; i++)
        {
        {
          sim_event *entry = &events->held [i];
          sim_event *entry = &events->held [i];
          sim_events_schedule (sd,
          sim_events_schedule (sd,
                               entry->time_of_event,
                               entry->time_of_event,
                               entry->handler,
                               entry->handler,
                               entry->data);
                               entry->data);
        }
        }
      events->nr_held = 0;
      events->nr_held = 0;
 
 
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
#if defined(HAVE_SIGPROCMASK) && defined(SIG_SETMASK)
      /*-UNLOCK-*/
      /*-UNLOCK-*/
      sigprocmask(SIG_SETMASK, &old_mask, NULL);
      sigprocmask(SIG_SETMASK, &old_mask, NULL);
#endif
#endif
 
 
    }
    }
 
 
  /* Process any watchpoints. Be careful to allow a watchpoint to
  /* Process any watchpoints. Be careful to allow a watchpoint to
     appear/disappear under our feet.
     appear/disappear under our feet.
     To ensure that watchpoints are processed only once per cycle,
     To ensure that watchpoints are processed only once per cycle,
     they are moved onto a watched queue, this returned to the
     they are moved onto a watched queue, this returned to the
     watchpoint queue when all queue processing has been
     watchpoint queue when all queue processing has been
     completed. */
     completed. */
  while (events->watchpoints != NULL)
  while (events->watchpoints != NULL)
    {
    {
      sim_event *to_do = events->watchpoints;
      sim_event *to_do = events->watchpoints;
      events->watchpoints = to_do->next;
      events->watchpoints = to_do->next;
      if (sim_watch_valid (sd, to_do))
      if (sim_watch_valid (sd, to_do))
        {
        {
          sim_event_handler *handler = to_do->handler;
          sim_event_handler *handler = to_do->handler;
          void *data = to_do->data;
          void *data = to_do->data;
          ETRACE((_ETRACE,
          ETRACE((_ETRACE,
                  "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
                  "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
                  (long) event_time,
                  (long) event_time,
                  (long) to_do,
                  (long) to_do,
                  (long) handler,
                  (long) handler,
                  (long) data,
                  (long) data,
                  (to_do->trace != NULL) ? ", " : "",
                  (to_do->trace != NULL) ? ", " : "",
                  (to_do->trace != NULL) ? to_do->trace : ""));
                  (to_do->trace != NULL) ? to_do->trace : ""));
          sim_events_free (sd, to_do);
          sim_events_free (sd, to_do);
          handler (sd, data);
          handler (sd, data);
        }
        }
      else
      else
        {
        {
          to_do->next = events->watchedpoints;
          to_do->next = events->watchedpoints;
          events->watchedpoints = to_do;
          events->watchedpoints = to_do;
        }
        }
    }
    }
 
 
  /* consume all events for this or earlier times.  Be careful to
  /* consume all events for this or earlier times.  Be careful to
     allow an event to appear/disappear under our feet */
     allow an event to appear/disappear under our feet */
  while (events->queue->time_of_event <
  while (events->queue->time_of_event <
         (event_time + events->nr_ticks_to_process))
         (event_time + events->nr_ticks_to_process))
    {
    {
      sim_event *to_do = events->queue;
      sim_event *to_do = events->queue;
      sim_event_handler *handler = to_do->handler;
      sim_event_handler *handler = to_do->handler;
      void *data = to_do->data;
      void *data = to_do->data;
      events->queue = to_do->next;
      events->queue = to_do->next;
      update_time_from_event (sd);
      update_time_from_event (sd);
      ETRACE((_ETRACE,
      ETRACE((_ETRACE,
              "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
              "event issued at %ld - tag 0x%lx - handler 0x%lx, data 0x%lx%s%s\n",
              (long) event_time,
              (long) event_time,
              (long) to_do,
              (long) to_do,
              (long) handler,
              (long) handler,
              (long) data,
              (long) data,
              (to_do->trace != NULL) ? ", " : "",
              (to_do->trace != NULL) ? ", " : "",
              (to_do->trace != NULL) ? to_do->trace : ""));
              (to_do->trace != NULL) ? to_do->trace : ""));
      sim_events_free (sd, to_do);
      sim_events_free (sd, to_do);
      handler (sd, data);
      handler (sd, data);
    }
    }
 
 
  /* put things back where they belong ready for the next iteration */
  /* put things back where they belong ready for the next iteration */
  events->watchpoints = events->watchedpoints;
  events->watchpoints = events->watchedpoints;
  events->watchedpoints = NULL;
  events->watchedpoints = NULL;
  if (events->watchpoints != NULL)
  if (events->watchpoints != NULL)
    events->work_pending = 1;
    events->work_pending = 1;
 
 
  /* advance the time */
  /* advance the time */
  SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
  SIM_ASSERT (events->time_from_event >= events->nr_ticks_to_process);
  SIM_ASSERT (events->queue != NULL); /* always poll event */
  SIM_ASSERT (events->queue != NULL); /* always poll event */
  events->time_from_event -= events->nr_ticks_to_process;
  events->time_from_event -= events->nr_ticks_to_process;
 
 
  /* this round of processing complete */
  /* this round of processing complete */
  events->nr_ticks_to_process = 0;
  events->nr_ticks_to_process = 0;
}
}
 
 
#endif
#endif
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.