diff options
author | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 1999-04-16 01:34:07 +0000 |
commit | 071ea11e85eb9d529cc5eb3d35f6247466a21b99 (patch) | |
tree | 5deda65b8d7b04d1f4cbc534c3206d328e1267ec /sim/common/dv-glue.c | |
parent | 1730ec6b1848f0f32154277f788fb29f88d8475b (diff) | |
download | gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.zip gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.gz gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.bz2 |
Initial creation of sourceware repository
Diffstat (limited to 'sim/common/dv-glue.c')
-rw-r--r-- | sim/common/dv-glue.c | 380 |
1 files changed, 0 insertions, 380 deletions
diff --git a/sim/common/dv-glue.c b/sim/common/dv-glue.c deleted file mode 100644 index 070b638..0000000 --- a/sim/common/dv-glue.c +++ /dev/null @@ -1,380 +0,0 @@ -/* This file is part of the program psim. - - Copyright (C) 1994-1996,1998 Andrew Cagney <cagney@highland.com.au> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - */ - - -#include "sim-main.h" -#include "hw-base.h" - -#ifdef HAVE_STRING_H -#include <string.h> -#else -#ifdef HAVE_STRINGS_H -#include <strings.h> -#endif -#endif - -/* DEVICE - - - glue - glue to interconnect and test hardware ports - - - DESCRIPTION - - - The glue device provides two functions. Firstly, it provides a - mechanism for inspecting and driving the port network. Secondly, - it provides a set of boolean primitives that can be used to apply - combinatorial operations to the port network. - - Glue devices have a variable number of big endian <<output>> - registers. Each register is target-word sized. The registers can - be read and written. - - Writing to an output register results in an event being driven - (level determined by the value written) on the devices - corresponding output port. - - Reading an <<output>> register returns either the last value - written or the most recently computed value (for that register) as - a result of an event ariving on that port (which ever was computed - last). - - At present the following sub device types are available: - - <<glue>>: In addition to driving its output interrupt port with any - value written to an interrupt input port is stored in the - corresponding <<output>> register. Such input interrupts, however, - are not propogated to an output interrupt port. - - <<glue-and>>: The bit-wise AND of the interrupt inputs is computed - and then both stored in <<output>> register zero and propogated to - output interrupt output port zero. - - - PROPERTIES - - - reg = <address> <size> (required) - - Specify the address (within the parent bus) that this device is to - live. The address must be 2048 * sizeof (word) (8k in a 32bit - simulation) aligned. - - - interrupt-ranges = <int-number> <range> (optional) - - If present, this specifies the number of valid interrupt inputs (up - to the maximum of 2048). By default, <<int-number>> is zero and - range is determined by the <<reg>> size. - - - PORTS - - - int[0..] (input, output) - - Both an input and an output port. - - - EXAMPLES - - - Enable tracing of the device: - - | -t glue-device \ - - - Create source, bitwize-and, and sink glue devices. Since the - device at address <<0x10000>> is of size <<8>> it will have two - output interrupt ports. - - | -o '/iobus@0xf0000000/glue@0x10000/reg 0x10000 8' \ - | -o '/iobus@0xf0000000/glue-and@0x20000/reg 0x20000 4' \ - | -o '/iobus@0xf0000000/glue-and/interrupt-ranges 0 2' \ - | -o '/iobus@0xf0000000/glue@0x30000/reg 0x30000 4' \ - - - Wire the two source interrupts to the AND device: - - | -o '/iobus@0xf0000000/glue@0x10000 > 0 0 /iobus/glue-and' \ - | -o '/iobus@0xf0000000/glue@0x10000 > 1 1 /iobus/glue-and' \ - - - Wire the AND device up to the sink so that the and's output is not - left open. - - | -o '/iobus@0xf0000000/glue-and > 0 0 /iobus/glue@0x30000' \ - - - With the above configuration. The client program is able to - compute a two bit AND. For instance the <<C>> stub below prints 1 - AND 0. - - | unsigned *input = (void*)0xf0010000; - | unsigned *output = (void*)0xf0030000; - | unsigned ans; - | input[0] = htonl(1); - | input[1] = htonl(0); - | ans = ntohl(*output); - | write_string("AND is "); - | write_int(ans); - | write_line(); - - - BUGS - - - A future implementation of this device may support multiple - interrupt ranges. - - Some of the devices listed may not yet be fully implemented. - - Additional devices such as a D flip-flop (DFF), an inverter (INV) - or a latch (LAT) may prove useful. - - */ - - -enum { - max_nr_ports = 2048, -}; - -enum hw_glue_type { - glue_undefined = 0, - glue_io, - glue_and, - glue_nand, - glue_or, - glue_xor, - glue_nor, - glue_not, -}; - -struct hw_glue { - enum hw_glue_type type; - int int_number; - int *input; - int nr_inputs; - unsigned sizeof_input; - /* our output registers */ - int space; - unsigned_word address; - unsigned sizeof_output; - int *output; - int nr_outputs; -}; - - -static hw_io_read_buffer_callback hw_glue_io_read_buffer; -static hw_io_write_buffer_callback hw_glue_io_write_buffer; -static hw_port_event_callback hw_glue_port_event; -const static struct hw_port_descriptor hw_glue_ports[]; - -static void -hw_glue_finish (struct hw *me) -{ - struct hw_glue *glue = HW_ZALLOC (me, struct hw_glue); - - /* establish our own methods */ - set_hw_data (me, glue); - set_hw_io_read_buffer (me, hw_glue_io_read_buffer); - set_hw_io_write_buffer (me, hw_glue_io_write_buffer); - set_hw_ports (me, hw_glue_ports); - set_hw_port_event (me, hw_glue_port_event); - - /* attach to our parent bus */ - do_hw_attach_regs (me); - - /* establish the output registers */ - { - reg_property_spec unit; - int reg_nr; - /* find a relevant reg entry */ - reg_nr = 0; - while (hw_find_reg_array_property (me, "reg", reg_nr, &unit) - && !hw_unit_size_to_attach_size (hw_parent (me), - &unit.size, - &glue->sizeof_output, - me)) - reg_nr++; - /* check out the size */ - if (glue->sizeof_output == 0) - hw_abort (me, "at least one reg property size must be nonzero"); - if (glue->sizeof_output % sizeof (unsigned_word) != 0) - hw_abort (me, "reg property size must be %d aligned", - sizeof (unsigned_word)); - /* and the address */ - hw_unit_address_to_attach_address (hw_parent (me), - &unit.address, - &glue->space, - &glue->address, - me); - if (glue->address % (sizeof (unsigned_word) * max_nr_ports) != 0) - hw_abort (me, "reg property address must be %d aligned", - sizeof (unsigned_word) * max_nr_ports); - glue->nr_outputs = glue->sizeof_output / sizeof (unsigned_word); - glue->output = hw_zalloc (me, glue->sizeof_output); - } - - /* establish the input ports */ - { - const struct hw_property *ranges; - ranges = hw_find_property (me, "interrupt-ranges"); - if (ranges == NULL) - { - glue->int_number = 0; - glue->nr_inputs = glue->nr_outputs; - } - else if (ranges->sizeof_array != sizeof (unsigned_cell) * 2) - { - hw_abort (me, "invalid interrupt-ranges property (incorrect size)"); - } - else - { - const unsigned_cell *int_range = ranges->array; - glue->int_number = BE2H_cell (int_range[0]); - glue->nr_inputs = BE2H_cell (int_range[1]); - } - glue->sizeof_input = glue->nr_inputs * sizeof (unsigned); - glue->input = hw_zalloc (me, glue->sizeof_input); - } - - /* determine our type */ - { - const char *name = hw_name(me); - if (strcmp (name, "glue") == 0) - glue->type = glue_io; - else if (strcmp (name, "glue-and") == 0) - glue->type = glue_and; - else - hw_abort (me, "unimplemented glue type"); - } - - HW_TRACE ((me, "int-number %d, nr_inputs %d, nr_outputs %d", - glue->int_number, glue->nr_inputs, glue->nr_outputs)); -} - -static unsigned -hw_glue_io_read_buffer (struct hw *me, - void *dest, - int space, - unsigned_word addr, - unsigned nr_bytes, - sim_cpu *cpu, - sim_cia cia) -{ - struct hw_glue *glue = (struct hw_glue *) hw_data (me); - int reg = ((addr - glue->address) / sizeof (unsigned_word)) % glue->nr_outputs; - if (nr_bytes != sizeof (unsigned_word) - || (addr % sizeof (unsigned_word)) != 0) - hw_abort (me, "missaligned read access (%d:0x%lx:%d) not supported", - space, (unsigned long)addr, nr_bytes); - *(unsigned_word*)dest = H2BE_4(glue->output[reg]); - HW_TRACE ((me, "read - port %d (0x%lx), level %d", - reg, (unsigned long) addr, glue->output[reg])); - return nr_bytes; -} - - -static unsigned -hw_glue_io_write_buffer (struct hw *me, - const void *source, - int space, - unsigned_word addr, - unsigned nr_bytes, - sim_cpu *cpu, - sim_cia cia) -{ - struct hw_glue *glue = (struct hw_glue *) hw_data (me); - int reg = ((addr - glue->address) / sizeof (unsigned_word)) % max_nr_ports; - if (nr_bytes != sizeof (unsigned_word) - || (addr % sizeof (unsigned_word)) != 0) - hw_abort (me, "missaligned write access (%d:0x%lx:%d) not supported", - space, (unsigned long) addr, nr_bytes); - glue->output[reg] = H2BE_4 (*(unsigned_word*)source); - HW_TRACE ((me, "write - port %d (0x%lx), level %d", - reg, (unsigned long) addr, glue->output[reg])); - hw_port_event (me, reg, glue->output[reg], cpu, cia); - return nr_bytes; -} - -static void -hw_glue_port_event (struct hw *me, - int my_port, - struct hw *source, - int source_port, - int level, - sim_cpu *cpu, - sim_cia cia) -{ - struct hw_glue *glue = (struct hw_glue *) hw_data (me); - int i; - if (my_port < glue->int_number - || my_port >= glue->int_number + glue->nr_inputs) - hw_abort (me, "port %d outside of valid range", my_port); - glue->input[my_port - glue->int_number] = level; - switch (glue->type) - { - case glue_io: - { - int port = my_port % glue->nr_outputs; - glue->output[port] = level; - HW_TRACE ((me, "input - port %d (0x%lx), level %d", - my_port, - (unsigned long) glue->address + port * sizeof (unsigned_word), - level)); - break; - } - case glue_and: - { - glue->output[0] = glue->input[0]; - for (i = 1; i < glue->nr_inputs; i++) - glue->output[0] &= glue->input[i]; - HW_TRACE ((me, "and - port %d, level %d arrived - output %d", - my_port, level, glue->output[0])); - hw_port_event (me, 0, glue->output[0], cpu, cia); - break; - } - default: - { - hw_abort (me, "operator not implemented"); - break; - } - } -} - - -static const struct hw_port_descriptor hw_glue_ports[] = { - { "int", 0, max_nr_ports }, - { NULL } -}; - - -const struct hw_device_descriptor dv_glue_descriptor[] = { - { "glue", hw_glue_finish, }, - { "glue-and", hw_glue_finish, }, - { "glue-nand", hw_glue_finish, }, - { "glue-or", hw_glue_finish, }, - { "glue-xor", hw_glue_finish, }, - { "glue-nor", hw_glue_finish, }, - { "glue-not", hw_glue_finish, }, - { NULL }, -}; |