OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [sim/] [common/] [dv-glue.c] - Blame information for rev 404

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

Line No. Rev Author Line
1 24 jeremybenn
/* The common simulator framework for GDB, the GNU Debugger.
2
 
3
   Copyright 2002, 2007, 2008 Free Software Foundation, Inc.
4
 
5
   Contributed by Andrew Cagney and Red Hat.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
 
22
 
23
#include "hw-main.h"
24
 
25
#ifdef HAVE_STRING_H
26
#include <string.h>
27
#else
28
#ifdef HAVE_STRINGS_H
29
#include <strings.h>
30
#endif
31
#endif
32
 
33
/* DEVICE
34
 
35
 
36
   glue - glue to interconnect and test hardware ports
37
 
38
 
39
   DESCRIPTION
40
 
41
 
42
   The glue device provides two functions.  Firstly, it provides a
43
   mechanism for inspecting and driving the port network.  Secondly,
44
   it provides a set of boolean primitives that can be used to apply
45
   combinatorial operations to the port network.
46
 
47
   Glue devices have a variable number of big endian <<output>>
48
   registers.  Each register is target-word sized.  The registers can
49
   be read and written.
50
 
51
   Writing to an output register results in an event being driven
52
   (level determined by the value written) on the devices
53
   corresponding output port.
54
 
55
   Reading an <<output>> register returns either the last value
56
   written or the most recently computed value (for that register) as
57
   a result of an event ariving on that port (which ever was computed
58
   last).
59
 
60
   At present the following sub device types are available:
61
 
62
   <<glue>>: In addition to driving its output interrupt port with any
63
   value written to an interrupt input port is stored in the
64
   corresponding <<output>> register.  Such input interrupts, however,
65
   are not propogated to an output interrupt port.
66
 
67
   <<glue-and>>: The bit-wise AND of the interrupt inputs is computed
68
   and then both stored in <<output>> register zero and propogated to
69
   output interrupt output port zero.
70
 
71
 
72
   PROPERTIES
73
 
74
 
75
   reg = <address> <size> (required)
76
 
77
   Specify the address (within the parent bus) that this device is to
78
   live.  The address must be 2048 * sizeof (word) (8k in a 32bit
79
   simulation) aligned.
80
 
81
 
82
   interrupt-ranges = <int-number> <range> (optional)
83
 
84
   If present, this specifies the number of valid interrupt inputs (up
85
   to the maximum of 2048).  By default, <<int-number>> is zero and
86
   range is determined by the <<reg>> size.
87
 
88
 
89
   PORTS
90
 
91
 
92
   int[0..] (input, output)
93
 
94
   Both an input and an output port.
95
 
96
 
97
   EXAMPLES
98
 
99
 
100
   Enable tracing of the device:
101
 
102
   | -t glue-device \
103
 
104
 
105
   Create source, bitwize-and, and sink glue devices.  Since the
106
   device at address <<0x10000>> is of size <<8>> it will have two
107
   output interrupt ports.
108
 
109
   | -o '/iobus@0xf0000000/glue@0x10000/reg 0x10000 8' \
110
   | -o '/iobus@0xf0000000/glue-and@0x20000/reg 0x20000 4' \
111
   | -o '/iobus@0xf0000000/glue-and/interrupt-ranges 0 2' \
112
   | -o '/iobus@0xf0000000/glue@0x30000/reg 0x30000 4' \
113
 
114
 
115
   Wire the two source interrupts to the AND device:
116
 
117
   | -o '/iobus@0xf0000000/glue@0x10000 > 0 0 /iobus/glue-and' \
118
   | -o '/iobus@0xf0000000/glue@0x10000 > 1 1 /iobus/glue-and' \
119
 
120
 
121
   Wire the AND device up to the sink so that the and's output is not
122
   left open.
123
 
124
   | -o '/iobus@0xf0000000/glue-and > 0 0 /iobus/glue@0x30000' \
125
 
126
 
127
   With the above configuration.  The client program is able to
128
   compute a two bit AND.  For instance the <<C>> stub below prints 1
129
   AND 0.
130
 
131
   |  unsigned *input = (void*)0xf0010000;
132
   |  unsigned *output = (void*)0xf0030000;
133
   |  unsigned ans;
134
   |  input[0] = htonl(1);
135
   |  input[1] = htonl(0);
136
   |  ans = ntohl(*output);
137
   |  write_string("AND is ");
138
   |  write_int(ans);
139
   |  write_line();
140
 
141
 
142
   BUGS
143
 
144
 
145
   A future implementation of this device may support multiple
146
   interrupt ranges.
147
 
148
   Some of the devices listed may not yet be fully implemented.
149
 
150
   Additional devices such as a D flip-flop (DFF), an inverter (INV)
151
   or a latch (LAT) may prove useful.
152
 
153
   */
154
 
155
 
156
enum {
157
  max_nr_ports = 2048,
158
};
159
 
160
enum hw_glue_type {
161
  glue_undefined = 0,
162
  glue_io,
163
  glue_and,
164
  glue_nand,
165
  glue_or,
166
  glue_xor,
167
  glue_nor,
168
  glue_not,
169
};
170
 
171
struct hw_glue {
172
  enum hw_glue_type type;
173
  int int_number;
174
  int *input;
175
  int nr_inputs;
176
  unsigned sizeof_input;
177
  /* our output registers */
178
  int space;
179
  unsigned_word address;
180
  unsigned sizeof_output;
181
  int *output;
182
  int nr_outputs;
183
};
184
 
185
 
186
static hw_io_read_buffer_method hw_glue_io_read_buffer;
187
static hw_io_write_buffer_method hw_glue_io_write_buffer;
188
static hw_port_event_method hw_glue_port_event;
189
const static struct hw_port_descriptor hw_glue_ports[];
190
 
191
static void
192
hw_glue_finish (struct hw *me)
193
{
194
  struct hw_glue *glue = HW_ZALLOC (me, struct hw_glue);
195
 
196
  /* establish our own methods */
197
  set_hw_data (me, glue);
198
  set_hw_io_read_buffer (me, hw_glue_io_read_buffer);
199
  set_hw_io_write_buffer (me, hw_glue_io_write_buffer);
200
  set_hw_ports (me, hw_glue_ports);
201
  set_hw_port_event (me, hw_glue_port_event);
202
 
203
  /* attach to our parent bus */
204
  do_hw_attach_regs (me);
205
 
206
  /* establish the output registers */
207
  {
208
    reg_property_spec unit;
209
    int reg_nr;
210
    /* find a relevant reg entry */
211
    reg_nr = 0;
212
    while (hw_find_reg_array_property (me, "reg", reg_nr, &unit)
213
           && !hw_unit_size_to_attach_size (hw_parent (me),
214
                                            &unit.size,
215
                                            &glue->sizeof_output,
216
                                            me))
217
      reg_nr++;
218
    /* check out the size */
219
    if (glue->sizeof_output == 0)
220
      hw_abort (me, "at least one reg property size must be nonzero");
221
    if (glue->sizeof_output % sizeof (unsigned_word) != 0)
222
      hw_abort (me, "reg property size must be %ld aligned",
223
                (long) sizeof (unsigned_word));
224
    /* and the address */
225
    hw_unit_address_to_attach_address (hw_parent (me),
226
                                       &unit.address,
227
                                       &glue->space,
228
                                       &glue->address,
229
                                       me);
230
    if (glue->address % (sizeof (unsigned_word) * max_nr_ports) != 0)
231
      hw_abort (me, "reg property address must be %ld aligned",
232
                (long) (sizeof (unsigned_word) * max_nr_ports));
233
    glue->nr_outputs = glue->sizeof_output / sizeof (unsigned_word);
234
    glue->output = hw_zalloc (me, glue->sizeof_output);
235
  }
236
 
237
  /* establish the input ports */
238
  {
239
    const struct hw_property *ranges;
240
    ranges = hw_find_property (me, "interrupt-ranges");
241
    if (ranges == NULL)
242
      {
243
        glue->int_number = 0;
244
        glue->nr_inputs = glue->nr_outputs;
245
      }
246
    else if (ranges->sizeof_array != sizeof (unsigned_cell) * 2)
247
      {
248
        hw_abort (me, "invalid interrupt-ranges property (incorrect size)");
249
      }
250
    else
251
      {
252
        const unsigned_cell *int_range = ranges->array;
253
        glue->int_number = BE2H_cell (int_range[0]);
254
        glue->nr_inputs = BE2H_cell (int_range[1]);
255
      }
256
    glue->sizeof_input = glue->nr_inputs * sizeof (unsigned);
257
    glue->input = hw_zalloc (me, glue->sizeof_input);
258
  }
259
 
260
  /* determine our type */
261
  {
262
    const char *name = hw_name(me);
263
    if (strcmp (name, "glue") == 0)
264
      glue->type = glue_io;
265
    else if (strcmp (name, "glue-and") == 0)
266
      glue->type = glue_and;
267
    else
268
      hw_abort (me, "unimplemented glue type");
269
  }
270
 
271
  HW_TRACE ((me, "int-number %d, nr_inputs %d, nr_outputs %d",
272
             glue->int_number, glue->nr_inputs, glue->nr_outputs));
273
}
274
 
275
static unsigned
276
hw_glue_io_read_buffer (struct hw *me,
277
                        void *dest,
278
                        int space,
279
                        unsigned_word addr,
280
                        unsigned nr_bytes)
281
{
282
  struct hw_glue *glue = (struct hw_glue *) hw_data (me);
283
  int reg = ((addr - glue->address) / sizeof (unsigned_word)) % glue->nr_outputs;
284
  if (nr_bytes != sizeof (unsigned_word)
285
      || (addr % sizeof (unsigned_word)) != 0)
286
    hw_abort (me, "missaligned read access (%d:0x%lx:%d) not supported",
287
              space, (unsigned long)addr, nr_bytes);
288
  *(unsigned_word*)dest = H2BE_4(glue->output[reg]);
289
  HW_TRACE ((me, "read - port %d (0x%lx), level %d",
290
             reg, (unsigned long) addr, glue->output[reg]));
291
  return nr_bytes;
292
}
293
 
294
 
295
static unsigned
296
hw_glue_io_write_buffer (struct hw *me,
297
                         const void *source,
298
                         int space,
299
                         unsigned_word addr,
300
                         unsigned nr_bytes)
301
{
302
  struct hw_glue *glue = (struct hw_glue *) hw_data (me);
303
  int reg = ((addr - glue->address) / sizeof (unsigned_word)) % max_nr_ports;
304
  if (nr_bytes != sizeof (unsigned_word)
305
      || (addr % sizeof (unsigned_word)) != 0)
306
    hw_abort (me, "missaligned write access (%d:0x%lx:%d) not supported",
307
              space, (unsigned long) addr, nr_bytes);
308
  glue->output[reg] = H2BE_4 (*(unsigned_word*)source);
309
  HW_TRACE ((me, "write - port %d (0x%lx), level %d",
310
             reg, (unsigned long) addr, glue->output[reg]));
311
  hw_port_event (me, reg, glue->output[reg]);
312
  return nr_bytes;
313
}
314
 
315
static void
316
hw_glue_port_event (struct hw *me,
317
                    int my_port,
318
                    struct hw *source,
319
                    int source_port,
320
                    int level)
321
{
322
  struct hw_glue *glue = (struct hw_glue *) hw_data (me);
323
  int i;
324
  if (my_port < glue->int_number
325
      || my_port >= glue->int_number + glue->nr_inputs)
326
    hw_abort (me, "port %d outside of valid range", my_port);
327
  glue->input[my_port - glue->int_number] = level;
328
  switch (glue->type)
329
    {
330
    case glue_io:
331
      {
332
        int port = my_port % glue->nr_outputs;
333
        glue->output[port] = level;
334
        HW_TRACE ((me, "input - port %d (0x%lx), level %d",
335
                   my_port,
336
                   (unsigned long) glue->address + port * sizeof (unsigned_word),
337
                   level));
338
        break;
339
      }
340
    case glue_and:
341
      {
342
        glue->output[0] = glue->input[0];
343
        for (i = 1; i < glue->nr_inputs; i++)
344
          glue->output[0] &= glue->input[i];
345
        HW_TRACE ((me, "and - port %d, level %d arrived - output %d",
346
                   my_port, level, glue->output[0]));
347
        hw_port_event (me, 0, glue->output[0]);
348
        break;
349
      }
350
    default:
351
      {
352
        hw_abort (me, "operator not implemented");
353
        break;
354
      }
355
    }
356
}
357
 
358
 
359
static const struct hw_port_descriptor hw_glue_ports[] = {
360
  { "int", 0, max_nr_ports },
361
  { NULL }
362
};
363
 
364
 
365
const struct hw_descriptor dv_glue_descriptor[] = {
366
  { "glue", hw_glue_finish, },
367
  { "glue-and", hw_glue_finish, },
368
  { "glue-nand", hw_glue_finish, },
369
  { "glue-or", hw_glue_finish, },
370
  { "glue-xor", hw_glue_finish, },
371
  { "glue-nor", hw_glue_finish, },
372
  { "glue-not", hw_glue_finish, },
373
  { NULL },
374
};

powered by: WebSVN 2.1.0

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