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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [testsuite/] [test-code/] [lib-inttest/] [lib-inttest.c] - Blame information for rev 433

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 433 jeremybenn
/* lib-inttest.c. Test of Or1ksim library interrupt funcs.
2
 
3
   Copyright (C) 1999-2006 OpenCores
4
   Copyright (C) 2010 Embecosm Limited
5
 
6
   Contributors various OpenCores participants
7
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8
 
9
   This file is part of OpenRISC 1000 Architectural Simulator.
10
 
11
   This program is free software; you can redistribute it and/or modify it
12
   under the terms of the GNU General Public License as published by the Free
13
   Software Foundation; either version 3 of the License, or (at your option)
14
   any later version.
15
 
16
   This program is distributed in the hope that it will be useful, but WITHOUT
17
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19
   more details.
20
 
21
   You should have received a copy of the GNU General Public License along
22
   with this program.  If not, see <http:  www.gnu.org/licenses/>.  */
23
 
24
/* ----------------------------------------------------------------------------
25
   This code is commented throughout for use with Doxygen.
26
   --------------------------------------------------------------------------*/
27
 
28
#include <stddef.h>
29
#include <stdlib.h>
30
#include <stdio.h>
31
#include <string.h>
32
 
33
#include "or1ksim.h"
34
 
35
 
36
/*! Number of interrupts in PIC */
37
#define  NUM_INTS  32
38
 
39
/*! Number of the PICSR SPR. */
40
#define  SPR_PICSR  0x4802
41
 
42
/*! Flag indicating if we are using level sensitive interrupts */
43
static int  level_sensitive_p;
44
 
45
/*! Vector of interrupt numbers. */
46
static int *intv;
47
 
48
/*! Count of interrupts. */
49
static int  intc = 0;
50
 
51
/*! Next interrupt */
52
static int  next_int = 0;
53
 
54
 
55
/* --------------------------------------------------------------------------*/
56
/*!Read upcall
57
 
58
   Upcall from Or1ksim to read a word from an external peripheral. If called
59
   this will trigger an interrupt.
60
 
61
   We may get an end case where we are asked for an interrupt, but have no
62
   more to give. We silently ignore this - it is just due to allowing the
63
   target program enough time to finish.
64
 
65
   @param[in]  class_ptr  A handle pass back from the initalization. Intended
66
                          for C++ callers, not used here.
67
   @param[in]  addr       Address to read from. Ignored here.
68
   @param[in]  mask       Byte mask for the read. Ignored here.
69
   @param[out] rdata      Buffer for the data read. Ignored here.
70
   @param[in]  data_len   Number of bytes in mask and rdata.
71
 
72
   @return  Zero on success, non-zero on failure. Always zero here.          */
73
/* --------------------------------------------------------------------------*/
74
static int
75
read_upcall (void              *class_ptr,
76
             unsigned long int  addr,
77
             unsigned char      mask[],
78
             unsigned char      rdata[],
79
             int                data_len)
80
{
81
  if (next_int < intc)
82
    {
83
      int  inum = intv[next_int++];
84
 
85
      printf ("Triggering interrupt %d\n", inum);
86
 
87
      if (level_sensitive_p)
88
        {
89
          or1ksim_interrupt_set (inum);
90
        }
91
      else
92
        {
93
          or1ksim_interrupt (inum);
94
        }
95
    }
96
 
97
  return  0;                     /* Success */
98
 
99
}       /* read_upcall () */
100
 
101
 
102
/* --------------------------------------------------------------------------*/
103
/*!Write upcall
104
 
105
   Upcall from Or1ksim to write a word to an external peripheral. If called
106
   this will clear an interrupt. The data is the number of the interrupt to
107
   clear.
108
 
109
   @param[in] class_ptr  A handle pass back from the initalization. Intended
110
                         for C++ callers, not used here.
111
   @param[in] addr       Address to write to. Ignored here.
112
   @param[in] mask       Byte mask for the write. Ignored here.
113
   @param[in] wdata      The data to write. Ignored here.
114
   @param[in] data_len   Number of bytes in mask and rdata.
115
 
116
   @return  Zero on success, non-zero on failure. Always zero here.          */
117
/* --------------------------------------------------------------------------*/
118
static int
119
write_upcall (void              *class_ptr,
120
              unsigned long int  addr,
121
              unsigned char      mask[],
122
              unsigned char      wdata[],
123
              int                data_len)
124
{
125
  /* Extract the inum */
126
  int inum = wdata[0];
127
 
128
  printf ("Clearing interrupt %d\n", inum);
129
 
130
  if (level_sensitive_p)
131
    {
132
      or1ksim_interrupt_clear (inum);
133
    }
134
  else
135
    {
136
      unsigned long int  picsr;
137
 
138
      if (!or1ksim_read_spr (SPR_PICSR, &picsr))
139
        {
140
          fprintf (stderr, "ERROR failed to read PICSR: Exiting.\n");
141
          exit (1);
142
        }
143
 
144
      picsr &= ~(1UL << inum);
145
      printf ("Cleared PICSR is 0x%08lx\n", picsr);
146
 
147
      if (!or1ksim_write_spr (SPR_PICSR, picsr))
148
        {
149
          fprintf (stderr, "ERROR failed to write PICSR: Exiting.\n");
150
          exit (1);
151
        }
152
    }
153
 
154
  return  0;                     /* Success */
155
 
156
}       /* write_upcall () */
157
 
158
 
159
/* --------------------------------------------------------------------------*/
160
/*!Main program
161
 
162
   Build an or1ksim program using the library which loads a program and config
163
   from the command line, and then drives interrupts. Usage:
164
 
165
   lib-inttest <config-file> <image> -l|-e <int #> <int #> ...
166
 
167
   <image> is run continuously. It requests that the next interrupt event be
168
   triggered by a read upcall. Clearing an interrupt occurs when a write
169
   upcall is received.
170
 
171
   The third argument specifies whether the level senstive (-l) or edge
172
   triggered (-e) mechanism should be used for setting and clearing
173
   interrupts.
174
 
175
   @param[in] argc  Number of elements in argv
176
   @param[in] argv  Vector of program name and arguments
177
 
178
   @return  Return code for the program.                                     */
179
/* --------------------------------------------------------------------------*/
180
int
181
main (int   argc,
182
      char *argv[])
183
{
184
  const int  INT_OFF = 4;               /* Offset in argv of interrupts */
185
  int        i;                         /* General counter */
186
 
187
  /* Parse args */
188
  if (argc < (INT_OFF + 1))
189
    {
190
      fprintf (stderr,
191
               "usage: lib-inttest-level <config-file> <image> -l|-e "
192
               "<int #> <int #> ...\n");
193
      return  1;
194
    }
195
 
196
  /* What type of interrupt? */
197
  if (0 == strcmp ("-l", argv[3]))
198
    {
199
      level_sensitive_p = 1;
200
    }
201
  else if (0 == strcmp ("-e", argv[3]))
202
    {
203
      level_sensitive_p = 0;
204
    }
205
  else
206
    {
207
      fprintf (stderr, "ERROR: Must specify -l or -e: exiting\n");
208
      exit (1);
209
    }
210
 
211
  /* Get all the interrupts sorted out into the vector. We hold them with one
212
     greater than absolute value, so we can distinguish between +0 and -0. */
213
  intv = malloc ((argc - INT_OFF) * sizeof (int));
214
 
215
  for (i = INT_OFF; i < argc; i++)
216
    {
217
      int  inum = atoi (argv[i]);
218
 
219
      if ((inum <= 0) || (NUM_INTS <= inum))
220
      {
221
        printf ("Warning: Invalid interrupt # %d to raise: Exiting.\n", inum);
222
        exit (1);
223
      }
224
 
225
      intv[i - INT_OFF] = inum;
226
    }
227
 
228
  /* Global counters */
229
  intc     = argc - INT_OFF;
230
  next_int = 0;
231
 
232
  /* Dummy argv array to pass arguments to or1ksim_init. Varies depending on
233
     whether an image file is specified. */
234
  int   dummy_argc;
235
  char *dummy_argv[5];
236
 
237
  dummy_argv[0] = "libsim";
238
  dummy_argv[1] = "-q";
239
  dummy_argv[2] = "-f";
240
  dummy_argv[3] = argv[1];
241
  dummy_argv[4] = argv[2];
242
 
243
  dummy_argc = 5;
244
 
245
  /* Initialize the program. Put the initialization message afterwards, or it
246
     will get swamped by the Or1ksim header. */
247
  if (0 == or1ksim_init (dummy_argc, dummy_argv, NULL, &read_upcall,
248
                         &write_upcall))
249
    {
250
      printf ("Initalization succeeded.\n");
251
    }
252
  else
253
    {
254
      printf ("ERROR: Initalization failed.\n");
255
      free (intv);
256
      exit (1);
257
    }
258
 
259
  /* Run in bursts of 1ms until all interrupts have been set and cleared. */
260
  do
261
    {
262
      if (OR1KSIM_RC_OK != or1ksim_run (1.0e-3))
263
        {
264
          printf ("ERROR: run failed\n");
265
          free (intv);
266
          exit (1);
267
        }
268
    }
269
  while (next_int < intc);
270
 
271
  /* One more burst to allow the device driver time to complete. */
272
  if (OR1KSIM_RC_OK != or1ksim_run (1.0e-3))
273
    {
274
      printf ("ERROR: run failed\n");
275
      free (intv);
276
      exit (1);
277
    }
278
 
279
  /* All interrupts should have been handled. */
280
  free (intv);
281
 
282
  printf ("Test completed successfully.\n");
283
  return  0;
284
 
285
}       /* main () */

powered by: WebSVN 2.1.0

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