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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [testsuite/] [test-code-or1k/] [int-logger/] [int-logger.c] - Blame information for rev 867

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

Line No. Rev Author Line
1 433 jeremybenn
/* int-logger.c. Test of Or1ksim handling of interrupts
2
 
3
   Copyright (C) 2010 Embecosm Limited
4
 
5
   Contributors various OpenCores participants
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
/* ----------------------------------------------------------------------------
24
   This code is commented throughout for use with Doxygen.
25
   --------------------------------------------------------------------------*/
26
 
27
#include "support.h"
28
#include "spr-defs.h"
29
#include "board.h"
30
 
31
 
32
/* --------------------------------------------------------------------------*/
33
/*!Write a memory mapped register
34
 
35
   @param[in] addr   Memory mapped address
36
   @param[in] value  Value to set                                            */
37
/* --------------------------------------------------------------------------*/
38
static void
39
setreg (unsigned long addr,
40
        unsigned char value)
41
{
42
  *((volatile unsigned char *) addr) = value;
43
 
44
}       /* setreg () */
45
 
46
 
47
/* --------------------------------------------------------------------------*/
48
/*!Read a memory mapped register
49
 
50
   @param[in] addr   Memory mapped address
51
 
52
   @return  Value read                                                       */
53
/* --------------------------------------------------------------------------*/
54
unsigned long
55
getreg (unsigned long addr)
56
{
57
  return *((volatile unsigned char *) addr);
58
 
59
}       /* getreg () */
60
 
61
 
62
/* --------------------------------------------------------------------------*/
63
/*!Count the number of ones in a register
64
 
65
   SIMD Within A Register (SWAR) algorithm from Aggregate Magic Algorithms
66
   (http://aggregate.org/MAGIC/) from the University of Kentucky.
67
 
68
   32-bit recursive reduction using SWAR. First step is mapping 2-bit
69
   values into sum of 2 1-bit values in sneaky way.
70
 
71
   @param[in] x  The 32-bit register whose bits are to be counted.
72
 
73
   @return  The number of bits that are set to 1.                             */
74
/* --------------------------------------------------------------------------*/
75
static int
76
ones32 (unsigned long int  x)
77
{
78
  x -=  ((x >>  1)      & 0x55555555);
79
  x  = (((x >>  2)      & 0x33333333) + (x & 0x33333333));
80
  x  = (((x >>  4) + x) & 0x0f0f0f0f);
81
  x +=   (x >>  8);
82
  x +=   (x >> 16);
83
 
84
  return (x & 0x0000003f);
85
 
86
}       /* ones32 () */
87
 
88
/* --------------------------------------------------------------------------*/
89
/*!Count the number of ones in a register
90
 
91
   SIMD Within A Register (SWAR) algorithm from Aggregate Magic Algorithms
92
   (http://aggregate.org/MAGIC/) from the University of Kentucky.
93
 
94
   Compute the log to base 2 of a supplied numger. In this case we know it will
95
   be an exact power of 2. We return -1 if asked for log (0).
96
 
97
   @param[in] x  The 32-bit register whose log to base 2 we want.
98
 
99
   @return  The log to base 2 of the argument, or -1 if the argument was
100
            zero.                                                            */
101
/* --------------------------------------------------------------------------*/
102
static int
103
int_log2 (unsigned int  x)
104
{
105
  x |= (x >> 1);
106
  x |= (x >> 2);
107
  x |= (x >> 4);
108
  x |= (x >> 8);
109
  x |= (x >> 16);
110
 
111
  return  ones32 (x) - 1;
112
 
113
}       /* int_log2 () */
114
 
115
 
116
/* --------------------------------------------------------------------------*/
117
/*!Generic interrupt handler
118
 
119
   This should receive the interrupt exception. Report the value in PICSR.
120
 
121
   Potentially PICSR has multiple bits set, so we report the least significant
122
   bit. This is consistent with an approach which gives highest priority to
123
   any NMI lines (0 or 1).
124
 
125
   It is up to the external agent to clear the interrupt. We prompt it by
126
   writing the number of the interrupt we have just received.                */
127
/* --------------------------------------------------------------------------*/
128
static void
129
interrupt_handler ()
130
{
131
  unsigned long int  picsr = mfspr (SPR_PICSR);
132
 
133
  printf ("PICSR = 0x%08lx\n", picsr);
134
  setreg (GENERIC_BASE, int_log2 (picsr & -picsr));
135
 
136
}       /* interrupt_handler () */
137
 
138
 
139
/* --------------------------------------------------------------------------*/
140
/*!Main program to set up interrupt handler
141
 
142
   We make a series of read upcalls, after 500 us and then every 1000us, which
143
   prompt some interrupts being set and cleared. By doing this, our upcalls
144
   should always be well clear of any calling function interrupt generation,
145
   which is on millisecond boundaries.
146
 
147
   A read upcall is a request to trigger an interrupt. We will subsequently
148
   use a write upcall in the interrupt handler to request clearing of the
149
   interrupt.
150
 
151
   @return  The return code from the program (always zero).                  */
152
/* --------------------------------------------------------------------------*/
153
int
154
main ()
155
{
156
  printf ("Starting interrupt handler\n");
157
  excpt_int = (unsigned long)interrupt_handler;
158
 
159
  /* Enable interrupts */
160
  printf ("Enabling interrupts.\n");
161
  mtspr (SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE);
162
  mtspr (SPR_PICMR, 0xffffffff);
163
 
164
  /* Loop forever, upcalling at the desired intervals. */
165
  unsigned long int  start = read_timer ();
166
 
167
  while (1)
168
    {
169
      static long int  end_time  = 500;
170
 
171
      while ((read_timer () - start) < end_time)
172
        {
173
        }
174
 
175
      /* Read to request an interrupt */
176
      (void)getreg (GENERIC_BASE);
177
 
178
      /* Wait 1000us before next upcall. */
179
      end_time += 1000;
180
    }
181
 
182
  /* We don't actually ever return */
183
  return 0;
184
 
185
}       /* main () */

powered by: WebSVN 2.1.0

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