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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [pic/] [pic.c] - Blame information for rev 440

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 jeremybenn
/* pic.c -- Simulation of OpenRISC 1000 programmable interrupt controller
2
 
3
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7
 
8
   This file is part of OpenRISC 1000 Architectural Simulator.
9
 
10
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14
 
15
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19
 
20
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>. */
22
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
 
27
/* Autoconf and/or portability configuration */
28
#include "config.h"
29
#include "port.h"
30
 
31
/* System includes */
32
#include <stdlib.h>
33
#include <stdio.h>
34
 
35
/* Package includes */
36
#include "arch.h"
37
#include "abstract.h"
38
#include "pic.h"
39
#include "opcode/or32.h"
40
#include "spr-defs.h"
41
#include "execute.h"
42
#include "except.h"
43
#include "sprs.h"
44
#include "sim-config.h"
45
#include "sched.h"
46
 
47
 
48 432 jeremybenn
/* -------------------------------------------------------------------------- */
49
/* Reset the PIC.
50 19 jeremybenn
 
51 432 jeremybenn
   Sets registers to consistent values.                                       */
52
/* -------------------------------------------------------------------------- */
53 19 jeremybenn
void
54
pic_reset (void)
55
{
56 220 jeremybenn
  PRINTFQ ("Resetting PIC.\n");
57 432 jeremybenn
  cpu_state.sprs[SPR_PICMR] = config.pic.use_nmi ? 0x00000003 : 0x00000000;
58
  cpu_state.sprs[SPR_PICSR] = 0x00000000;
59 19 jeremybenn
 
60 432 jeremybenn
}       /* pic_reset () */
61
 
62
 
63
/* -------------------------------------------------------------------------- */
64
/* Handle the reporting of an interrupt
65
 
66
   PIC interrupts are scheduled to take place after the current instruction
67
   has completed execution.
68
 
69
   @param[in] dat  Data associated with the exception (not used)              */
70
/* -------------------------------------------------------------------------- */
71 19 jeremybenn
static void
72
pic_rep_int (void *dat)
73
{
74 432 jeremybenn
  /* printf ("Handling interrupt PICSR: 0x%08x\n", cpu_state.sprs[SPR_PICSR]);
75
   */
76
 
77 19 jeremybenn
  if (cpu_state.sprs[SPR_PICSR])
78
    {
79
      except_handle (EXCEPT_INT, cpu_state.sprs[SPR_EEAR_BASE]);
80
    }
81 432 jeremybenn
}       /* pic_rep_int () */
82 19 jeremybenn
 
83 432 jeremybenn
 
84
/* -------------------------------------------------------------------------- */
85
/* Enable interrupts.
86
 
87
   Called whenever interrupts get enabled, or when PICMR is written.
88
 
89
   @todo Not sure if calling whenever PICMR is written is a good
90
         idea. However, so long as interrupts are properly cleared, it should
91
         not be a problem.                                                    */
92
/* -------------------------------------------------------------------------- */
93 19 jeremybenn
void
94
pic_ints_en (void)
95
{
96
  if ((cpu_state.sprs[SPR_PICMR] & cpu_state.sprs[SPR_PICSR]))
97 432 jeremybenn
    {
98
      SCHED_ADD (pic_rep_int, NULL, 0);
99
    }
100
}       /* pic_ints_en () */
101 19 jeremybenn
 
102 432 jeremybenn
 
103
/* -------------------------------------------------------------------------- */
104
/*!Assert an interrupt to the PIC
105
 
106
   OpenRISC supports both edge and level triggered interrupt. The only
107
   difference is how the interrupt is cleared. For edge triggered, it is by
108
   clearing the corresponding bit in PICSR. For level triggered it is by
109
   deasserting the interrupt line.
110
 
111
   For integrated peripherals, these amount to the same thing (using
112
   clear_interrupt ()). For external peripherals, the library provides two
113
   distinct interfaces.
114
 
115
   An interrupt disables any power management activity.
116
 
117
   We warn if an interrupt is received on a line that already has an interrupt
118
   pending.
119
 
120
   @note If this is called during a simulated instruction (ie. from a read/
121
         write mem callback), the interrupt will be delivered after the
122
         instruction has finished executing.
123
 
124
   @param[in] line  The interrupt being asserted.                             */
125
/* -------------------------------------------------------------------------- */
126 19 jeremybenn
void
127
report_interrupt (int line)
128
{
129
  uint32_t lmask = 1 << line;
130
 
131 432 jeremybenn
  /* printf ("Interrupt reported on line %d\n", line); */
132
 
133 19 jeremybenn
  /* Disable doze and sleep mode */
134
  cpu_state.sprs[SPR_PMR] &= ~(SPR_PMR_DME | SPR_PMR_SME);
135
 
136
  /* If PIC is disabled, don't set any register, just raise EXCEPT_INT */
137
  if (!config.pic.enabled)
138
    {
139
      if (cpu_state.sprs[SPR_SR] & SPR_SR_IEE)
140
        except_handle (EXCEPT_INT, cpu_state.sprs[SPR_EEAR_BASE]);
141
      return;
142
    }
143
 
144 432 jeremybenn
  /* We can't take another interrupt if the previous one has not been
145
     cleared. */
146 430 julius
  if (cpu_state.sprs[SPR_PICSR] & lmask)
147 19 jeremybenn
    {
148 430 julius
      /* Interrupt already signaled and pending */
149 440 jeremybenn
      PRINTF ("Warning: Int on line %d pending: ignored\n", line);
150 19 jeremybenn
      return;
151
    }
152 436 julius
 
153 19 jeremybenn
  cpu_state.sprs[SPR_PICSR] |= lmask;
154
 
155 432 jeremybenn
  /* If we are enabled in the mask, and interrupts are globally enabled in the
156
     SR, schedule the interrupt to take place after the next instruction. */
157
  if ((cpu_state.sprs[SPR_PICMR] & lmask) &&
158
      (cpu_state.sprs[SPR_SR] & SPR_SR_IEE))
159
    {
160 440 jeremybenn
      /* printf ("Scheduling interrupt on line %d\n", line); */
161 19 jeremybenn
      SCHED_ADD (pic_rep_int, NULL, 0);
162 432 jeremybenn
    }
163
}       /* report_interrupt () */
164 19 jeremybenn
 
165 432 jeremybenn
 
166
/* -------------------------------------------------------------------------- */
167
/* Clear an interrupt on a PIC line.
168
 
169
   Logically this is different for a level sensitive interrupt (it lowers the
170
   input line) and an edge sensitive interrupt (it clears the PICSR bit).
171
 
172
   However within Or1ksim, these are implemented through the same operation -
173
   clearing the bit in PICSR.
174
 
175
   @param[in] line  The interrupt being cleared.                              */
176
/* -------------------------------------------------------------------------- */
177 19 jeremybenn
void
178
clear_interrupt (int line)
179
{
180 440 jeremybenn
  cpu_state.sprs[SPR_PICSR] &= ~(1 << line);
181 19 jeremybenn
 
182 432 jeremybenn
}       /* clear_interrupt */
183
 
184
 
185 19 jeremybenn
/*----------------------------------------------------[ PIC configuration ]---*/
186
 
187
 
188
/*---------------------------------------------------------------------------*/
189
/*!Enable or disable the programmable interrupt controller
190
 
191
   Set the corresponding field in the UPR
192
 
193
   @param[in] val  The value to use
194
   @param[in] dat  The config data structure (not used here)                 */
195
/*---------------------------------------------------------------------------*/
196
static void
197
pic_enabled (union param_val  val,
198
             void            *dat)
199
{
200
  if (val.int_val)
201
    {
202
      cpu_state.sprs[SPR_UPR] |= SPR_UPR_PICP;
203
    }
204
  else
205
    {
206
      cpu_state.sprs[SPR_UPR] &= ~SPR_UPR_PICP;
207
    }
208
 
209
  config.pic.enabled = val.int_val;
210
 
211
}       /* pic_enabled() */
212
 
213
 
214
/*---------------------------------------------------------------------------*/
215
/*!Enable or disable edge triggering of interrupts
216
 
217
   @param[in] val  The value to use
218
   @param[in] dat  The config data structure (not used here)                 */
219
/*---------------------------------------------------------------------------*/
220
static void
221
pic_edge_trigger (union param_val  val,
222
                  void            *dat)
223
{
224
  config.pic.edge_trigger = val.int_val;
225
 
226
}       /* pic_edge_trigger() */
227
 
228
 
229
/*---------------------------------------------------------------------------*/
230 432 jeremybenn
/*!Enable or disable non-maskable interrupts
231
 
232
   @param[in] val  The value to use
233
   @param[in] dat  The config data structure (not used here)                 */
234
/*---------------------------------------------------------------------------*/
235
static void
236
pic_use_nmi (union param_val  val,
237
                  void            *dat)
238
{
239
  config.pic.use_nmi = val.int_val;
240
 
241
}       /* pic_use_nmi() */
242
 
243
 
244
/*---------------------------------------------------------------------------*/
245 19 jeremybenn
/*!Initialize a new interrupt controller configuration
246
 
247
   ALL parameters are set explicitly to default values in init_defconfig()   */
248
/*---------------------------------------------------------------------------*/
249
void
250
reg_pic_sec ()
251
{
252
  struct config_section *sec = reg_config_sec ("pic", NULL, NULL);
253
 
254 224 jeremybenn
  reg_config_param (sec, "enabled",      PARAMT_INT, pic_enabled);
255
  reg_config_param (sec, "edge_trigger", PARAMT_INT, pic_edge_trigger);
256 432 jeremybenn
  reg_config_param (sec, "use_nmi",      PARAMT_INT, pic_use_nmi);
257 19 jeremybenn
 
258
}       /* reg_pic_sec() */

powered by: WebSVN 2.1.0

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