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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.2/] [sim/] [cris/] [dv-cris.c] - Blame information for rev 438

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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