Home | History | Annotate | Line # | Download | only in cris
      1   1.1  christos /* The CRIS interrupt framework for GDB, the GNU Debugger.
      2   1.1  christos 
      3  1.11  christos    Copyright 2006-2024 Free Software Foundation, Inc.
      4   1.1  christos 
      5   1.1  christos    This file is part of GDB.
      6   1.1  christos 
      7   1.1  christos    This program is free software; you can redistribute it and/or modify
      8   1.1  christos    it under the terms of the GNU General Public License as published by
      9   1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10   1.1  christos    (at your option) any later version.
     11   1.1  christos 
     12   1.1  christos    This program is distributed in the hope that it will be useful,
     13   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15   1.1  christos    GNU General Public License for more details.
     16   1.1  christos 
     17   1.1  christos    You should have received a copy of the GNU General Public License
     18   1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19   1.1  christos 
     20  1.10  christos /* This must come before any other includes.  */
     21  1.10  christos #include "defs.h"
     22  1.10  christos 
     23   1.1  christos #include "sim-main.h"
     24   1.1  christos #include "hw-main.h"
     25   1.1  christos 
     26   1.1  christos /* DEVICE
     27   1.1  christos 
     28   1.1  christos    CRIS cpu virtual device (very rudimental; generic enough for all
     29   1.1  christos    currently used CRIS versions).
     30   1.1  christos 
     31   1.1  christos 
     32   1.1  christos    DESCRIPTION
     33   1.1  christos 
     34   1.1  christos    Implements the external CRIS functionality.  This includes the
     35   1.1  christos    delivery of interrupts generated from other devices.
     36   1.1  christos 
     37   1.1  christos 
     38   1.1  christos    PROPERTIES
     39   1.1  christos 
     40   1.1  christos    vec-for-int = <int-a> <vec-a> <int-b> <vec-b> ...
     41   1.1  christos    These are the translations to interrupt vector for values appearing
     42   1.1  christos    on the "int" port, as pairs of the value and the corresponding
     43   1.1  christos    vector.  Defaults to no translation.  All values that may appear on
     44   1.1  christos    the "int" port must be defined, or the device aborts.
     45   1.1  christos 
     46   1.1  christos    multiple-int = ("abort" | "ignore_previous" | <vector>)
     47   1.1  christos    If multiple interrupt values are dispatched, this property decides
     48   1.1  christos    what to do.  The value is either a number corresponding to the
     49   1.1  christos    vector to use, or the string "abort" to cause a hard abort, or the
     50   1.1  christos    string "ignore_previous", to silently use the new vector instead.
     51   1.1  christos    The default is "abort".
     52   1.1  christos 
     53   1.1  christos 
     54   1.1  christos    PORTS
     55   1.1  christos 
     56   1.1  christos    int (input)
     57   1.1  christos    Interrupt port.  An event with a non-zero value on this port causes
     58   1.1  christos    an interrupt.  If, after an event but before the interrupt has been
     59   1.1  christos    properly dispatched, a non-zero value appears that is different
     60   1.1  christos    after mapping than the previous, then the property multiple_int
     61   1.1  christos    decides what to do.
     62   1.1  christos 
     63   1.1  christos    FIXME: reg port so internal registers can be read.  Requires
     64   1.1  christos    chip-specific versions, though.  Ports "nmi" and "reset".
     65   1.1  christos 
     66   1.1  christos 
     67   1.1  christos    BUGS
     68   1.1  christos    When delivering an interrupt, this code assumes that there is only
     69   1.1  christos    one processor (number 0).
     70   1.1  christos 
     71   1.1  christos    This code does not attempt to be efficient at handling pending
     72   1.1  christos    interrupts.  It simply schedules the interrupt delivery handler
     73   1.1  christos    every instruction cycle until all pending interrupts go away.
     74   1.1  christos    It also works around a bug in sim_events_process when doing so.
     75   1.1  christos    */
     76   1.1  christos 
     77   1.1  christos /* Keep this an enum for simple addition of "reset" and "nmi".  */
     78   1.1  christos enum
     79   1.1  christos  {
     80   1.1  christos    INT_PORT,
     81   1.1  christos  };
     82   1.1  christos 
     83   1.1  christos static const struct hw_port_descriptor cris_ports[] =
     84   1.1  christos  {
     85   1.1  christos    { "int", INT_PORT, 0, input_port },
     86   1.1  christos    { NULL, 0, 0, 0 }
     87   1.1  christos  };
     88   1.1  christos 
     89   1.1  christos struct cris_vec_tr
     90   1.1  christos  {
     91  1.10  christos    uint32_t portval, vec;
     92   1.1  christos  };
     93   1.1  christos 
     94   1.1  christos enum cris_multiple_ints
     95   1.1  christos   {
     96   1.1  christos     cris_multint_abort,
     97   1.1  christos     cris_multint_ignore_previous,
     98   1.1  christos     cris_multint_vector
     99   1.1  christos   };
    100   1.1  christos 
    101   1.1  christos struct cris_hw
    102   1.1  christos  {
    103   1.1  christos    struct hw_event *pending_handler;
    104  1.10  christos    uint32_t pending_vector;
    105   1.1  christos    struct cris_vec_tr *int_to_vec;
    106   1.1  christos    enum cris_multiple_ints multi_int_action;
    107  1.10  christos    uint32_t multiple_int_vector;
    108   1.1  christos  };
    109   1.1  christos 
    110   1.1  christos /* An event function, calling the actual CPU-model-specific
    111   1.1  christos    interrupt-delivery function.  */
    112   1.1  christos 
    113   1.1  christos static void
    114   1.1  christos deliver_cris_interrupt (struct hw *me, void *data)
    115   1.1  christos {
    116   1.1  christos   struct cris_hw *crishw = hw_data (me);
    117   1.1  christos   SIM_DESC simulator = hw_system (me);
    118   1.1  christos   sim_cpu *cpu = STATE_CPU (simulator, 0);
    119   1.1  christos   unsigned int intno = crishw->pending_vector;
    120   1.1  christos 
    121   1.1  christos  if (CPU_CRIS_DELIVER_INTERRUPT (cpu) (cpu, CRIS_INT_INT, intno))
    122   1.1  christos     {
    123   1.1  christos       crishw->pending_vector = 0;
    124   1.1  christos       crishw->pending_handler = NULL;
    125   1.1  christos       return;
    126   1.1  christos     }
    127   1.1  christos 
    128   1.1  christos  {
    129   1.1  christos    /* Bug workaround: at time T with a pending number of cycles N to
    130   1.1  christos       process, if re-scheduling an event at time T+M, M < N,
    131   1.1  christos       sim_events_process gets stuck at T (updating the "time" to
    132   1.1  christos       before the event rather than after the event, or somesuch).
    133   1.1  christos 
    134   1.1  christos       Hacking this locally is thankfully easy: if we see the same
    135   1.1  christos       simulation time, increase the number of cycles.  Do this every
    136   1.1  christos       time we get here, until a new time is seen (supposedly unstuck
    137   1.1  christos       re-delivery).  (Fixing in SIM/GDB source will hopefully then
    138   1.1  christos       also be easier, having a tangible test-case.)  */
    139  1.10  christos    static int64_t last_events_time = 0;
    140  1.10  christos    static int64_t delta = 1;
    141  1.10  christos    int64_t this_events_time = hw_event_queue_time (me);
    142   1.1  christos 
    143   1.1  christos    if (this_events_time == last_events_time)
    144   1.1  christos      delta++;
    145   1.1  christos    else
    146   1.1  christos      {
    147   1.1  christos        delta = 1;
    148   1.1  christos        last_events_time = this_events_time;
    149   1.1  christos      }
    150   1.1  christos 
    151   1.1  christos    crishw->pending_handler
    152   1.1  christos      = hw_event_queue_schedule (me, delta, deliver_cris_interrupt, NULL);
    153   1.1  christos  }
    154   1.1  christos }
    155   1.1  christos 
    156   1.1  christos 
    157   1.1  christos /* A port-event function for events arriving to an interrupt port.  */
    158   1.1  christos 
    159   1.1  christos static void
    160   1.1  christos cris_port_event (struct hw *me,
    161   1.1  christos 		 int my_port,
    162   1.1  christos 		 struct hw *source,
    163   1.1  christos 		 int source_port,
    164   1.1  christos 		 int intparam)
    165   1.1  christos {
    166   1.1  christos   struct cris_hw *crishw = hw_data (me);
    167  1.10  christos   uint32_t vec;
    168   1.1  christos 
    169   1.1  christos   /* A few placeholders; only the INT port is implemented.  */
    170   1.1  christos   switch (my_port)
    171   1.1  christos     {
    172   1.1  christos     case INT_PORT:
    173   1.1  christos       HW_TRACE ((me, "INT value=0x%x", intparam));
    174   1.1  christos       break;
    175   1.1  christos 
    176   1.1  christos     default:
    177   1.1  christos       hw_abort (me, "bad switch");
    178   1.1  christos       break;
    179   1.1  christos     }
    180   1.1  christos 
    181   1.1  christos   if (intparam == 0)
    182   1.1  christos     return;
    183   1.1  christos 
    184   1.1  christos   if (crishw->int_to_vec != NULL)
    185   1.1  christos     {
    186   1.1  christos       unsigned int i;
    187   1.1  christos       for (i = 0; crishw->int_to_vec[i].portval != 0; i++)
    188   1.1  christos 	if (crishw->int_to_vec[i].portval == intparam)
    189   1.1  christos 	  break;
    190   1.1  christos 
    191   1.1  christos       if (crishw->int_to_vec[i].portval == 0)
    192   1.1  christos 	hw_abort (me, "unsupported value for int port: 0x%x", intparam);
    193   1.1  christos 
    194   1.1  christos       vec = crishw->int_to_vec[i].vec;
    195   1.1  christos     }
    196   1.1  christos   else
    197  1.10  christos     vec = (uint32_t) intparam;
    198   1.1  christos 
    199   1.1  christos   if (crishw->pending_vector != 0)
    200   1.1  christos     {
    201   1.1  christos       if (vec == crishw->pending_vector)
    202   1.1  christos 	return;
    203   1.1  christos 
    204   1.1  christos       switch (crishw->multi_int_action)
    205   1.1  christos 	{
    206   1.1  christos 	case cris_multint_abort:
    207   1.1  christos 	  hw_abort (me, "int 0x%x (0x%x) while int 0x%x hasn't been delivered",
    208   1.1  christos 		    vec, intparam, crishw->pending_vector);
    209   1.1  christos 	  break;
    210   1.1  christos 
    211   1.1  christos 	case cris_multint_ignore_previous:
    212   1.1  christos 	  break;
    213   1.1  christos 
    214   1.1  christos 	case cris_multint_vector:
    215   1.1  christos 	  vec = crishw->multiple_int_vector;
    216   1.1  christos 	  break;
    217   1.1  christos 
    218   1.1  christos 	default:
    219   1.1  christos 	  hw_abort (me, "bad switch");
    220   1.1  christos 	}
    221   1.1  christos     }
    222   1.1  christos 
    223   1.1  christos   crishw->pending_vector = vec;
    224   1.1  christos 
    225   1.1  christos   /* Schedule our event handler *now*.  */
    226   1.1  christos   if (crishw->pending_handler == NULL)
    227   1.1  christos     crishw->pending_handler
    228   1.1  christos       = hw_event_queue_schedule (me, 0, deliver_cris_interrupt, NULL);
    229   1.1  christos }
    230   1.1  christos 
    231   1.1  christos /* Instance initializer function.  */
    232   1.1  christos 
    233   1.1  christos static void
    234   1.1  christos cris_finish (struct hw *me)
    235   1.1  christos {
    236   1.1  christos   struct cris_hw *crishw;
    237   1.1  christos   const struct hw_property *vec_for_int;
    238   1.1  christos   const struct hw_property *multiple_int;
    239   1.1  christos 
    240   1.1  christos   crishw = HW_ZALLOC (me, struct cris_hw);
    241   1.1  christos   set_hw_data (me, crishw);
    242   1.1  christos   set_hw_ports (me, cris_ports);
    243   1.1  christos   set_hw_port_event (me, cris_port_event);
    244   1.1  christos 
    245   1.1  christos   vec_for_int = hw_find_property (me, "vec-for-int");
    246   1.1  christos   if (vec_for_int != NULL)
    247   1.1  christos     {
    248  1.10  christos       uint32_t vecsize;
    249  1.10  christos       uint32_t i;
    250   1.1  christos 
    251   1.1  christos       if (hw_property_type (vec_for_int) != array_property)
    252   1.1  christos 	hw_abort (me, "property \"vec-for-int\" has the wrong type");
    253   1.1  christos 
    254   1.1  christos       vecsize = hw_property_sizeof_array (vec_for_int) / sizeof (signed_cell);
    255   1.1  christos 
    256   1.1  christos       if ((vecsize % 2) != 0)
    257   1.1  christos 	hw_abort (me, "translation vector does not consist of even pairs");
    258   1.1  christos 
    259   1.1  christos       crishw->int_to_vec
    260   1.1  christos 	= hw_malloc (me, (vecsize/2 + 1) * sizeof (crishw->int_to_vec[0]));
    261   1.1  christos 
    262   1.1  christos       for (i = 0; i < vecsize/2; i++)
    263   1.1  christos 	{
    264   1.1  christos 	  signed_cell portval_sc;
    265   1.1  christos 	  signed_cell vec_sc;
    266   1.1  christos 
    267   1.1  christos 	  if (!hw_find_integer_array_property (me, "vec-for-int", i*2,
    268   1.1  christos 					       &portval_sc)
    269   1.1  christos 	      || !hw_find_integer_array_property (me, "vec-for-int", i*2 + 1,
    270   1.1  christos 						  &vec_sc)
    271   1.1  christos 	      || portval_sc < 0
    272   1.1  christos 	      || vec_sc < 0)
    273   1.1  christos 	    hw_abort (me, "no valid vector translation pair %u", i);
    274   1.1  christos 
    275  1.10  christos 	  crishw->int_to_vec[i].portval = (uint32_t) portval_sc;
    276  1.10  christos 	  crishw->int_to_vec[i].vec = (uint32_t) vec_sc;
    277   1.1  christos 	}
    278   1.1  christos 
    279   1.1  christos       crishw->int_to_vec[i].portval = 0;
    280   1.1  christos       crishw->int_to_vec[i].vec = 0;
    281   1.1  christos     }
    282   1.1  christos 
    283   1.1  christos   multiple_int = hw_find_property (me, "multiple-int");
    284   1.1  christos   if (multiple_int != NULL)
    285   1.1  christos     {
    286   1.1  christos       if (hw_property_type (multiple_int) == integer_property)
    287   1.1  christos 	{
    288   1.1  christos 	  crishw->multiple_int_vector
    289   1.1  christos 	    = hw_find_integer_property (me, "multiple-int");
    290   1.1  christos 	  crishw->multi_int_action = cris_multint_vector;
    291   1.1  christos 	}
    292   1.1  christos       else
    293   1.1  christos 	{
    294   1.1  christos 	  const char *action = hw_find_string_property (me, "multiple-int");
    295   1.1  christos 
    296   1.1  christos 	  if (action == NULL)
    297   1.1  christos 	    hw_abort (me, "property \"multiple-int\" has the wrong type");
    298   1.1  christos 
    299   1.1  christos 	  if (strcmp (action, "abort") == 0)
    300   1.1  christos 	    crishw->multi_int_action = cris_multint_abort;
    301   1.1  christos 	  else if (strcmp (action, "ignore_previous") == 0)
    302   1.1  christos 	    crishw->multi_int_action = cris_multint_ignore_previous;
    303   1.1  christos 	  else
    304   1.1  christos 	    hw_abort (me, "property \"multiple-int\" must be one of <vector number>\n"
    305   1.1  christos 		      "\"abort\" and \"ignore_previous\", not \"%s\"", action);
    306   1.1  christos 	}
    307   1.1  christos     }
    308   1.1  christos   else
    309   1.1  christos     crishw->multi_int_action = cris_multint_abort;
    310   1.1  christos }
    311   1.1  christos 
    312   1.1  christos const struct hw_descriptor dv_cris_descriptor[] = {
    313   1.1  christos   { "cris", cris_finish, },
    314   1.1  christos   { NULL },
    315   1.1  christos };
    316