1 /* The common simulator framework for GDB, the GNU Debugger.
3 Copyright 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
5 Contributed by Andrew Cagney and Red Hat.
7 This file is part of GDB.
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.
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.
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/>. */
36 glue - glue to interconnect and test hardware ports
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.
47 Glue devices have a variable number of big endian <<output>>
48 registers. Each register is target-word sized. The registers can
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.
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
60 At present the following sub device types are available:
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.
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.
75 reg = <address> <size> (required)
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
82 interrupt-ranges = <int-number> <range> (optional)
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.
92 int[0..] (input, output)
94 Both an input and an output port.
100 Enable tracing of the device:
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.
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' \
115 Wire the two source interrupts to the AND device:
117 | -o '/iobus@0xf0000000/glue@0x10000 > 0 0 /iobus/glue-and' \
118 | -o '/iobus@0xf0000000/glue@0x10000 > 1 1 /iobus/glue-and' \
121 Wire the AND device up to the sink so that the and's output is not
124 | -o '/iobus@0xf0000000/glue-and > 0 0 /iobus/glue@0x30000' \
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
131 | unsigned *input = (void*)0xf0010000;
132 | unsigned *output = (void*)0xf0030000;
134 | input[0] = htonl(1);
135 | input[1] = htonl(0);
136 | ans = ntohl(*output);
137 | write_string("AND is ");
145 A future implementation of this device may support multiple
148 Some of the devices listed may not yet be fully implemented.
150 Additional devices such as a D flip-flop (DFF), an inverter (INV)
151 or a latch (LAT) may prove useful.
175 enum hw_glue_type type
;
179 unsigned sizeof_input
;
180 /* our output registers */
182 unsigned_word address
;
183 unsigned sizeof_output
;
189 static hw_io_read_buffer_method hw_glue_io_read_buffer
;
190 static hw_io_write_buffer_method hw_glue_io_write_buffer
;
191 static hw_port_event_method hw_glue_port_event
;
192 static const struct hw_port_descriptor hw_glue_ports
[];
195 hw_glue_finish (struct hw
*me
)
197 struct hw_glue
*glue
= HW_ZALLOC (me
, struct hw_glue
);
199 /* establish our own methods */
200 set_hw_data (me
, glue
);
201 set_hw_io_read_buffer (me
, hw_glue_io_read_buffer
);
202 set_hw_io_write_buffer (me
, hw_glue_io_write_buffer
);
203 set_hw_ports (me
, hw_glue_ports
);
204 set_hw_port_event (me
, hw_glue_port_event
);
206 /* attach to our parent bus */
207 do_hw_attach_regs (me
);
209 /* establish the output registers */
211 reg_property_spec unit
;
214 /* find a relevant reg entry */
216 while (hw_find_reg_array_property (me
, "reg", reg_nr
, &unit
)
217 && !hw_unit_size_to_attach_size (hw_parent (me
),
219 &glue
->sizeof_output
,
223 /* check out the size */
224 if (glue
->sizeof_output
== 0)
225 hw_abort (me
, "at least one reg property size must be nonzero");
226 if (glue
->sizeof_output
% sizeof (unsigned_word
) != 0)
227 hw_abort (me
, "reg property size must be %ld aligned",
228 (long) sizeof (unsigned_word
));
230 /* and the address */
231 hw_unit_address_to_attach_address (hw_parent (me
),
236 if (glue
->address
% (sizeof (unsigned_word
) * max_nr_ports
) != 0)
237 hw_abort (me
, "reg property address must be %ld aligned",
238 (long) (sizeof (unsigned_word
) * max_nr_ports
));
240 glue
->nr_outputs
= glue
->sizeof_output
/ sizeof (unsigned_word
);
241 glue
->output
= hw_zalloc (me
, glue
->sizeof_output
);
244 /* establish the input ports */
246 const struct hw_property
*ranges
;
248 ranges
= hw_find_property (me
, "interrupt-ranges");
251 glue
->int_number
= 0;
252 glue
->nr_inputs
= glue
->nr_outputs
;
254 else if (ranges
->sizeof_array
!= sizeof (unsigned_cell
) * 2)
256 hw_abort (me
, "invalid interrupt-ranges property (incorrect size)");
260 const unsigned_cell
*int_range
= ranges
->array
;
262 glue
->int_number
= BE2H_cell (int_range
[0]);
263 glue
->nr_inputs
= BE2H_cell (int_range
[1]);
265 glue
->sizeof_input
= glue
->nr_inputs
* sizeof (unsigned);
266 glue
->input
= hw_zalloc (me
, glue
->sizeof_input
);
269 /* determine our type */
271 const char *name
= hw_name(me
);
273 if (strcmp (name
, "glue") == 0)
274 glue
->type
= glue_io
;
275 else if (strcmp (name
, "glue-and") == 0)
276 glue
->type
= glue_and
;
278 hw_abort (me
, "unimplemented glue type");
281 HW_TRACE ((me
, "int-number %d, nr_inputs %d, nr_outputs %d",
282 glue
->int_number
, glue
->nr_inputs
, glue
->nr_outputs
));
286 hw_glue_io_read_buffer (struct hw
*me
,
292 struct hw_glue
*glue
= (struct hw_glue
*) hw_data (me
);
293 int reg
= ((addr
- glue
->address
) / sizeof (unsigned_word
)) % glue
->nr_outputs
;
295 if (nr_bytes
!= sizeof (unsigned_word
)
296 || (addr
% sizeof (unsigned_word
)) != 0)
297 hw_abort (me
, "missaligned read access (%d:0x%lx:%d) not supported",
298 space
, (unsigned long)addr
, nr_bytes
);
300 *(unsigned_word
*)dest
= H2BE_4 (glue
->output
[reg
]);
302 HW_TRACE ((me
, "read - port %d (0x%lx), level %d",
303 reg
, (unsigned long) addr
, glue
->output
[reg
]));
310 hw_glue_io_write_buffer (struct hw
*me
,
316 struct hw_glue
*glue
= (struct hw_glue
*) hw_data (me
);
317 int reg
= ((addr
- glue
->address
) / sizeof (unsigned_word
)) % max_nr_ports
;
319 if (nr_bytes
!= sizeof (unsigned_word
)
320 || (addr
% sizeof (unsigned_word
)) != 0)
321 hw_abort (me
, "missaligned write access (%d:0x%lx:%d) not supported",
322 space
, (unsigned long) addr
, nr_bytes
);
324 glue
->output
[reg
] = H2BE_4 (*(unsigned_word
*)source
);
326 HW_TRACE ((me
, "write - port %d (0x%lx), level %d",
327 reg
, (unsigned long) addr
, glue
->output
[reg
]));
329 hw_port_event (me
, reg
, glue
->output
[reg
]);
335 hw_glue_port_event (struct hw
*me
,
341 struct hw_glue
*glue
= (struct hw_glue
*) hw_data (me
);
344 if (my_port
< glue
->int_number
345 || my_port
>= glue
->int_number
+ glue
->nr_inputs
)
346 hw_abort (me
, "port %d outside of valid range", my_port
);
348 glue
->input
[my_port
- glue
->int_number
] = level
;
353 int port
= my_port
% glue
->nr_outputs
;
355 glue
->output
[port
] = level
;
357 HW_TRACE ((me
, "input - port %d (0x%lx), level %d",
359 (unsigned long) glue
->address
+ port
* sizeof (unsigned_word
),
365 glue
->output
[0] = glue
->input
[0];
366 for (i
= 1; i
< glue
->nr_inputs
; i
++)
367 glue
->output
[0] &= glue
->input
[i
];
369 HW_TRACE ((me
, "and - port %d, level %d arrived - output %d",
370 my_port
, level
, glue
->output
[0]));
372 hw_port_event (me
, 0, glue
->output
[0]);
377 hw_abort (me
, "operator not implemented");
384 static const struct hw_port_descriptor hw_glue_ports
[] =
386 { "int", 0, max_nr_ports
, 0 },
391 const struct hw_descriptor dv_glue_descriptor
[] =
393 { "glue", hw_glue_finish
, },
394 { "glue-and", hw_glue_finish
, },
395 { "glue-nand", hw_glue_finish
, },
396 { "glue-or", hw_glue_finish
, },
397 { "glue-xor", hw_glue_finish
, },
398 { "glue-nor", hw_glue_finish
, },
399 { "glue-not", hw_glue_finish
, },