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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [sim/] [common/] [dv-glue.c] - Blame information for rev 1778

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

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

powered by: WebSVN 2.1.0

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