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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.2/] [sim/] [lm32/] [dv-lm32cpu.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
/*  Lattice Mico32 CPU model.
2
    Contributed by Jon Beniston <jon@beniston.com>
3
 
4
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
5
 
6
   This file is part of GDB.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
 
21
#include "hw-main.h"
22
#include "sim-main.h"
23
 
24
 
25
struct lm32cpu
26
{
27
  struct hw_event *event;
28
};
29
 
30
/* input port ID's.  */
31
 
32
enum
33
{
34
  INT0_PORT,
35
  INT1_PORT,
36
  INT2_PORT,
37
  INT3_PORT,
38
  INT4_PORT,
39
  INT5_PORT,
40
  INT6_PORT,
41
  INT7_PORT,
42
  INT8_PORT,
43
  INT9_PORT,
44
  INT10_PORT,
45
  INT11_PORT,
46
  INT12_PORT,
47
  INT13_PORT,
48
  INT14_PORT,
49
  INT15_PORT,
50
  INT16_PORT,
51
  INT17_PORT,
52
  INT18_PORT,
53
  INT19_PORT,
54
  INT20_PORT,
55
  INT21_PORT,
56
  INT22_PORT,
57
  INT23_PORT,
58
  INT24_PORT,
59
  INT25_PORT,
60
  INT26_PORT,
61
  INT27_PORT,
62
  INT28_PORT,
63
  INT29_PORT,
64
  INT30_PORT,
65
  INT31_PORT,
66
};
67
 
68
static const struct hw_port_descriptor lm32cpu_ports[] = {
69
  /* interrupt inputs.  */
70
  {"int0", INT0_PORT, 0, input_port,},
71
  {"int1", INT1_PORT, 0, input_port,},
72
  {"int2", INT2_PORT, 0, input_port,},
73
  {"int3", INT3_PORT, 0, input_port,},
74
  {"int4", INT4_PORT, 0, input_port,},
75
  {"int5", INT5_PORT, 0, input_port,},
76
  {"int6", INT6_PORT, 0, input_port,},
77
  {"int7", INT7_PORT, 0, input_port,},
78
  {"int8", INT8_PORT, 0, input_port,},
79
  {"int9", INT9_PORT, 0, input_port,},
80
  {"int10", INT10_PORT, 0, input_port,},
81
  {"int11", INT11_PORT, 0, input_port,},
82
  {"int12", INT12_PORT, 0, input_port,},
83
  {"int13", INT13_PORT, 0, input_port,},
84
  {"int14", INT14_PORT, 0, input_port,},
85
  {"int15", INT15_PORT, 0, input_port,},
86
  {"int16", INT16_PORT, 0, input_port,},
87
  {"int17", INT17_PORT, 0, input_port,},
88
  {"int18", INT18_PORT, 0, input_port,},
89
  {"int19", INT19_PORT, 0, input_port,},
90
  {"int20", INT20_PORT, 0, input_port,},
91
  {"int21", INT21_PORT, 0, input_port,},
92
  {"int22", INT22_PORT, 0, input_port,},
93
  {"int23", INT23_PORT, 0, input_port,},
94
  {"int24", INT24_PORT, 0, input_port,},
95
  {"int25", INT25_PORT, 0, input_port,},
96
  {"int26", INT26_PORT, 0, input_port,},
97
  {"int27", INT27_PORT, 0, input_port,},
98
  {"int28", INT28_PORT, 0, input_port,},
99
  {"int29", INT29_PORT, 0, input_port,},
100
  {"int30", INT30_PORT, 0, input_port,},
101
  {"int31", INT31_PORT, 0, input_port,},
102
  {NULL,},
103
};
104
 
105
 
106
 
107
/*
108
 * Finish off the partially created hw device.  Attach our local
109
 * callbacks.  Wire up our port names etc.
110
 */
111
static hw_port_event_method lm32cpu_port_event;
112
 
113
 
114
static void
115
lm32cpu_finish (struct hw *me)
116
{
117
  struct lm32cpu *controller;
118
 
119
  controller = HW_ZALLOC (me, struct lm32cpu);
120
  set_hw_data (me, controller);
121
  set_hw_ports (me, lm32cpu_ports);
122
  set_hw_port_event (me, lm32cpu_port_event);
123
 
124
  /* Initialize the pending interrupt flags.  */
125
  controller->event = NULL;
126
}
127
 
128
 
129
/* An event arrives on an interrupt port.  */
130
static unsigned int s_ui_ExtIntrs = 0;
131
 
132
 
133
static void
134
deliver_lm32cpu_interrupt (struct hw *me, void *data)
135
{
136
  static unsigned int ip, im, im_and_ip_result;
137
  struct lm32cpu *controller = hw_data (me);
138
  SIM_DESC sd = hw_system (me);
139
  sim_cpu *cpu = STATE_CPU (sd, 0);      /* NB: fix CPU 0.  */
140
  address_word cia = CIA_GET (cpu);
141
  int interrupt = (int) data;
142
 
143
 
144
  HW_TRACE ((me, "interrupt-check event"));
145
 
146
 
147
  /*
148
   * Determine if an external interrupt is active
149
   * and needs to cause an exception.
150
   */
151
  im = lm32bf_h_csr_get (cpu, LM32_CSR_IM);
152
  ip = lm32bf_h_csr_get (cpu, LM32_CSR_IP);
153
  im_and_ip_result = im & ip;
154
 
155
 
156
  if ((lm32bf_h_csr_get (cpu, LM32_CSR_IE) & 1) && (im_and_ip_result != 0))
157
    {
158
      /* Save PC in exception address register.  */
159
      lm32bf_h_gr_set (cpu, 30, lm32bf_h_pc_get (cpu));
160
      /* Restart at interrupt offset in handler exception table.  */
161
      lm32bf_h_pc_set (cpu,
162
                       lm32bf_h_csr_get (cpu,
163
                                         LM32_CSR_EBA) +
164
                       LM32_EID_INTERRUPT * 32);
165
      /* Save interrupt enable and then clear.  */
166
      lm32bf_h_csr_set (cpu, LM32_CSR_IE, 0x2);
167
    }
168
 
169
  /* reschedule soon.  */
170
  if (controller->event != NULL)
171
    hw_event_queue_deschedule (me, controller->event);
172
  controller->event = NULL;
173
 
174
 
175
  /* if there are external interrupts, schedule an interrupt-check again.
176
   * NOTE: THIS MAKES IT VERY INEFFICIENT. INSTEAD, TRIGGER THIS
177
   * CHECk_EVENT WHEN THE USER ENABLES IE OR USER MODIFIES IM REGISTERS.
178
   */
179
  if (s_ui_ExtIntrs != 0)
180
    controller->event =
181
      hw_event_queue_schedule (me, 1, deliver_lm32cpu_interrupt, data);
182
}
183
 
184
 
185
 
186
/* Handle an event on one of the CPU's ports.  */
187
static void
188
lm32cpu_port_event (struct hw *me,
189
                    int my_port,
190
                    struct hw *source, int source_port, int level)
191
{
192
  struct lm32cpu *controller = hw_data (me);
193
  SIM_DESC sd = hw_system (me);
194
  sim_cpu *cpu = STATE_CPU (sd, 0);      /* NB: fix CPU 0.  */
195
  address_word cia = CIA_GET (cpu);
196
 
197
 
198
  HW_TRACE ((me, "interrupt event on port %d, level %d", my_port, level));
199
 
200
 
201
 
202
  /*
203
   * Activate IP if the interrupt's activated; don't do anything if
204
   * the interrupt's deactivated.
205
   */
206
  if (level == 1)
207
    {
208
      /*
209
       * save state of external interrupt.
210
       */
211
      s_ui_ExtIntrs |= (1 << my_port);
212
 
213
      /* interrupt-activated so set IP.  */
214
      lm32bf_h_csr_set (cpu, LM32_CSR_IP,
215
                        lm32bf_h_csr_get (cpu, LM32_CSR_IP) | (1 << my_port));
216
 
217
      /*
218
       * Since interrupt is activated, queue an immediate event
219
       * to check if this interrupt is serviceable.
220
       */
221
      if (controller->event != NULL)
222
        hw_event_queue_deschedule (me, controller->event);
223
 
224
 
225
      /*
226
       * Queue an immediate event to check if this interrupt must be serviced;
227
       * this will happen after the current instruction is complete.
228
       */
229
      controller->event = hw_event_queue_schedule (me,
230
                                                   0,
231
                                                   deliver_lm32cpu_interrupt,
232
                                                   0);
233
    }
234
  else
235
    {
236
      /*
237
       * save state of external interrupt.
238
       */
239
      s_ui_ExtIntrs &= ~(1 << my_port);
240
    }
241
}
242
 
243
 
244
const struct hw_descriptor dv_lm32cpu_descriptor[] = {
245
  {"lm32cpu", lm32cpu_finish,},
246
  {NULL},
247
};

powered by: WebSVN 2.1.0

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