OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gdb/] [gdb-6.8/] [gdb-6.8.openrisc-2.1/] [sim/] [mips/] [dv-tx3904cpu.c] - Diff between revs 24 and 33

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

Rev 24 Rev 33
/*  This file is part of the program GDB, the GNU debugger.
/*  This file is part of the program GDB, the GNU debugger.
 
 
    Copyright (C) 1998, 2007, 2008 Free Software Foundation, Inc.
    Copyright (C) 1998, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Cygnus Solutions.
    Contributed by Cygnus Solutions.
 
 
    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/>.
 
 
    */
    */
 
 
 
 
#include "sim-main.h"
#include "sim-main.h"
#include "hw-main.h"
#include "hw-main.h"
 
 
/* DEVICE
/* DEVICE
 
 
 
 
   tx3904cpu - tx3904 cpu virtual device
   tx3904cpu - tx3904 cpu virtual device
 
 
 
 
   DESCRIPTION
   DESCRIPTION
 
 
 
 
   Implements the external tx3904 functionality.  This includes the
   Implements the external tx3904 functionality.  This includes the
   delivery of of interrupts generated from other devices and the
   delivery of of interrupts generated from other devices and the
   handling of device specific registers.
   handling of device specific registers.
 
 
 
 
   PROPERTIES
   PROPERTIES
 
 
   none
   none
 
 
 
 
   PORTS
   PORTS
 
 
 
 
   reset (input)
   reset (input)
 
 
   Currently ignored.
   Currently ignored.
 
 
 
 
   nmi (input)
   nmi (input)
 
 
   Deliver a non-maskable interrupt to the processor.
   Deliver a non-maskable interrupt to the processor.
 
 
 
 
   level (input)
   level (input)
 
 
   Deliver a maskable interrupt of given level, corresponding to
   Deliver a maskable interrupt of given level, corresponding to
   IP[5:0], to processor.
   IP[5:0], to processor.
 
 
 
 
 
 
   BUGS
   BUGS
 
 
 
 
   When delivering an interrupt, this code assumes that there is only
   When delivering an interrupt, this code assumes that there is only
   one processor (number 0).
   one processor (number 0).
 
 
   This code does not attempt to be efficient at handling pending
   This code does not attempt to be efficient at handling pending
   interrupts.  It simply schedules the interrupt delivery handler
   interrupts.  It simply schedules the interrupt delivery handler
   every instruction cycle until all pending interrupts go away.  An
   every instruction cycle until all pending interrupts go away.  An
   alternative implementation might modify instructions that change
   alternative implementation might modify instructions that change
   the PSW and have them check to see if the change makes an interrupt
   the PSW and have them check to see if the change makes an interrupt
   delivery possible.
   delivery possible.
 
 
   */
   */
 
 
 
 
 
 
struct tx3904cpu {
struct tx3904cpu {
  /* Pending interrupts for delivery by event handler */
  /* Pending interrupts for delivery by event handler */
  int pending_reset, pending_nmi, pending_level;
  int pending_reset, pending_nmi, pending_level;
  struct hw_event* event;
  struct hw_event* event;
};
};
 
 
 
 
 
 
/* input port ID's */
/* input port ID's */
 
 
enum {
enum {
  RESET_PORT,
  RESET_PORT,
  NMI_PORT,
  NMI_PORT,
  LEVEL_PORT,
  LEVEL_PORT,
};
};
 
 
 
 
static const struct hw_port_descriptor tx3904cpu_ports[] = {
static const struct hw_port_descriptor tx3904cpu_ports[] = {
 
 
  /* interrupt inputs */
  /* interrupt inputs */
  { "reset", RESET_PORT, 0, input_port, },
  { "reset", RESET_PORT, 0, input_port, },
  { "nmi", NMI_PORT, 0, input_port, },
  { "nmi", NMI_PORT, 0, input_port, },
  { "level", LEVEL_PORT, 0, input_port, },
  { "level", LEVEL_PORT, 0, input_port, },
 
 
  { NULL, },
  { NULL, },
};
};
 
 
 
 
/* Finish off the partially created hw device.  Attach our local
/* Finish off the partially created hw device.  Attach our local
   callbacks.  Wire up our port names etc */
   callbacks.  Wire up our port names etc */
 
 
static hw_port_event_method tx3904cpu_port_event;
static hw_port_event_method tx3904cpu_port_event;
 
 
 
 
 
 
static void
static void
tx3904cpu_finish (struct hw *me)
tx3904cpu_finish (struct hw *me)
{
{
  struct tx3904cpu *controller;
  struct tx3904cpu *controller;
 
 
  controller = HW_ZALLOC (me, struct tx3904cpu);
  controller = HW_ZALLOC (me, struct tx3904cpu);
  set_hw_data (me, controller);
  set_hw_data (me, controller);
  set_hw_ports (me, tx3904cpu_ports);
  set_hw_ports (me, tx3904cpu_ports);
  set_hw_port_event (me, tx3904cpu_port_event);
  set_hw_port_event (me, tx3904cpu_port_event);
 
 
  /* Initialize the pending interrupt flags */
  /* Initialize the pending interrupt flags */
  controller->pending_level = 0;
  controller->pending_level = 0;
  controller->pending_reset = 0;
  controller->pending_reset = 0;
  controller->pending_nmi = 0;
  controller->pending_nmi = 0;
  controller->event = NULL;
  controller->event = NULL;
}
}
 
 
 
 
 
 
/* An event arrives on an interrupt port */
/* An event arrives on an interrupt port */
 
 
static void
static void
deliver_tx3904cpu_interrupt (struct hw *me,
deliver_tx3904cpu_interrupt (struct hw *me,
                            void *data)
                            void *data)
{
{
  struct tx3904cpu *controller = hw_data (me);
  struct tx3904cpu *controller = hw_data (me);
  SIM_DESC sd = hw_system (me);
  SIM_DESC sd = hw_system (me);
  sim_cpu *cpu = STATE_CPU (sd, 0); /* NB: fix CPU 0. */
  sim_cpu *cpu = STATE_CPU (sd, 0); /* NB: fix CPU 0. */
  address_word cia = CIA_GET (cpu);
  address_word cia = CIA_GET (cpu);
 
 
#define CPU cpu
#define CPU cpu
#define SD current_state
#define SD current_state
 
 
  if (controller->pending_reset)
  if (controller->pending_reset)
    {
    {
      controller->pending_reset = 0;
      controller->pending_reset = 0;
      HW_TRACE ((me, "reset pc=0x%08lx", (long) CIA_GET (cpu)));
      HW_TRACE ((me, "reset pc=0x%08lx", (long) CIA_GET (cpu)));
      SignalExceptionNMIReset();
      SignalExceptionNMIReset();
    }
    }
  else if (controller->pending_nmi)
  else if (controller->pending_nmi)
    {
    {
      controller->pending_nmi = 0;
      controller->pending_nmi = 0;
      HW_TRACE ((me, "nmi pc=0x%08lx", (long) CIA_GET (cpu)));
      HW_TRACE ((me, "nmi pc=0x%08lx", (long) CIA_GET (cpu)));
      SignalExceptionNMIReset();
      SignalExceptionNMIReset();
    }
    }
  else if (controller->pending_level)
  else if (controller->pending_level)
    {
    {
      HW_TRACE ((me, "interrupt level=%d pc=0x%08lx sr=0x%08lx",
      HW_TRACE ((me, "interrupt level=%d pc=0x%08lx sr=0x%08lx",
                 controller->pending_level,
                 controller->pending_level,
                 (long) CIA_GET (cpu), (long) SR));
                 (long) CIA_GET (cpu), (long) SR));
 
 
      /* Clear CAUSE register.  It may stay this way if the interrupt
      /* Clear CAUSE register.  It may stay this way if the interrupt
         was cleared with a negative pending_level. */
         was cleared with a negative pending_level. */
      CAUSE &= ~ (cause_IP_mask << cause_IP_shift);
      CAUSE &= ~ (cause_IP_mask << cause_IP_shift);
 
 
      if(controller->pending_level > 0) /* interrupt set */
      if(controller->pending_level > 0) /* interrupt set */
        {
        {
          /* set hardware-interrupt subfields of CAUSE register */
          /* set hardware-interrupt subfields of CAUSE register */
          CAUSE |= (controller->pending_level & cause_IP_mask) << cause_IP_shift;
          CAUSE |= (controller->pending_level & cause_IP_mask) << cause_IP_shift;
 
 
          /* check for enabled / unmasked interrupts */
          /* check for enabled / unmasked interrupts */
          if((SR & status_IEc) &&
          if((SR & status_IEc) &&
             (controller->pending_level & ((SR >> status_IM_shift) & status_IM_mask)))
             (controller->pending_level & ((SR >> status_IM_shift) & status_IM_mask)))
            {
            {
              controller->pending_level = 0;
              controller->pending_level = 0;
              SignalExceptionInterrupt(0 /* dummy value */);
              SignalExceptionInterrupt(0 /* dummy value */);
            }
            }
          else
          else
            {
            {
              /* reschedule soon */
              /* reschedule soon */
              if(controller->event != NULL)
              if(controller->event != NULL)
                hw_event_queue_deschedule(me, controller->event);
                hw_event_queue_deschedule(me, controller->event);
              controller->event =
              controller->event =
                hw_event_queue_schedule (me, 1, deliver_tx3904cpu_interrupt, NULL);
                hw_event_queue_schedule (me, 1, deliver_tx3904cpu_interrupt, NULL);
            }
            }
        } /* interrupt set */
        } /* interrupt set */
    }
    }
#undef CPU cpu
#undef CPU cpu
#undef SD current_state
#undef SD current_state
}
}
 
 
 
 
static void
static void
tx3904cpu_port_event (struct hw *me,
tx3904cpu_port_event (struct hw *me,
                     int my_port,
                     int my_port,
                     struct hw *source,
                     struct hw *source,
                     int source_port,
                     int source_port,
                     int level)
                     int level)
{
{
  struct tx3904cpu *controller = hw_data (me);
  struct tx3904cpu *controller = hw_data (me);
 
 
  switch (my_port)
  switch (my_port)
    {
    {
    case RESET_PORT:
    case RESET_PORT:
      controller->pending_reset = 1;
      controller->pending_reset = 1;
      HW_TRACE ((me, "port-in reset"));
      HW_TRACE ((me, "port-in reset"));
      break;
      break;
 
 
    case NMI_PORT:
    case NMI_PORT:
      controller->pending_nmi = 1;
      controller->pending_nmi = 1;
      HW_TRACE ((me, "port-in nmi"));
      HW_TRACE ((me, "port-in nmi"));
      break;
      break;
 
 
    case LEVEL_PORT:
    case LEVEL_PORT:
      /* level == 0 means that the interrupt was cleared */
      /* level == 0 means that the interrupt was cleared */
      if(level == 0)
      if(level == 0)
        controller->pending_level = -1; /* signal end of interrupt */
        controller->pending_level = -1; /* signal end of interrupt */
      else
      else
        controller->pending_level = level;
        controller->pending_level = level;
      HW_TRACE ((me, "port-in level=%d", level));
      HW_TRACE ((me, "port-in level=%d", level));
      break;
      break;
 
 
    default:
    default:
      hw_abort (me, "bad switch");
      hw_abort (me, "bad switch");
      break;
      break;
    }
    }
 
 
  /* Schedule an event to be delivered immediately after current
  /* Schedule an event to be delivered immediately after current
     instruction. */
     instruction. */
  if(controller->event != NULL)
  if(controller->event != NULL)
    hw_event_queue_deschedule(me, controller->event);
    hw_event_queue_deschedule(me, controller->event);
  controller->event =
  controller->event =
    hw_event_queue_schedule (me, 0, deliver_tx3904cpu_interrupt, NULL);
    hw_event_queue_schedule (me, 0, deliver_tx3904cpu_interrupt, NULL);
}
}
 
 
 
 
const struct hw_descriptor dv_tx3904cpu_descriptor[] = {
const struct hw_descriptor dv_tx3904cpu_descriptor[] = {
  { "tx3904cpu", tx3904cpu_finish, },
  { "tx3904cpu", tx3904cpu_finish, },
  { NULL },
  { NULL },
};
};
 
 

powered by: WebSVN 2.1.0

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