diff options
author | Hans-Peter Nilsson <hp@axis.com> | 2006-04-03 03:01:45 +0000 |
---|---|---|
committer | Hans-Peter Nilsson <hp@axis.com> | 2006-04-03 03:01:45 +0000 |
commit | aad3b3cbc1391fb0091d03b252bd53fbd1d2dd84 (patch) | |
tree | d084f6526cd6241af91f2bb5c097a86b07a71a87 /sim/cris/rvdummy.c | |
parent | 4c3a323bb9b03802339b28311c228a5152829474 (diff) | |
download | gdb-aad3b3cbc1391fb0091d03b252bd53fbd1d2dd84.zip gdb-aad3b3cbc1391fb0091d03b252bd53fbd1d2dd84.tar.gz gdb-aad3b3cbc1391fb0091d03b252bd53fbd1d2dd84.tar.bz2 |
* cris/dv-cris.c, cris/dv-rv.c, cris/rvdummy.c: New files.
* cris/Makefile.in (CONFIG_DEVICES): Remove redundant setting.
(dv-cris.o, dv-rv.o rvdummy$(EXEEXT), rvdummy.o): New rules.
(all): Depend on rvdummy$(EXEEXT).
* cris/configure.ac: Call SIM_AC_OPTION_WARNINGS. Check for
sys/socket.h and sys/select.h. Call SIM_AC_OPTION_HARDWARE,
default off.
* cris/configure: Regenerate.
* cris/cris-sim.h (cris_have_900000xxif): Declare here.
(enum cris_interrupt_type, crisv10deliver_interrupt)
(crisv32deliver_interrupt: New declarations.
* cris/cris-tmpl.c [WITH_HW] (MY (f_model_insn_after)): Call
sim_events_tickn and set state-events member work_pending when it's
time for the next event.
[WITH_HW] (MY (f_specific_init)): Set CPU-model-specific
interrupt-delivery function.
* cris/crisv10f.c (MY (deliver_interrupt)): New function.
* cris/crisv32f.c (MY (deliver_interrupt)): New function.
* cris/devices.c: Include hw-device.h.
(device_io_read_buffer) [WITH_HW]: Call hw_io_read_buffer.
(device_io_write_buffer): Only perform 0x900000xx-functions if
cris_have_900000xxif is nonzero. Else if WITH_HW defined,
call hw_io_write_buffer. Add return 0 last in function.
* cris/sim-if.c (cris_have_900000xxif): Now global.
(sim_open) [WITH_HW]: Clear deliver_interrupt cpu member.
Force "-model" option, effectively.
* cris/sim-main.h (cris_interrupt_delivery_fn): New type.
(struct _sim_cpu) [WITH_HW]: New member deliver_interrupt.
Diffstat (limited to 'sim/cris/rvdummy.c')
-rw-r--r-- | sim/cris/rvdummy.c | 536 |
1 files changed, 536 insertions, 0 deletions
diff --git a/sim/cris/rvdummy.c b/sim/cris/rvdummy.c new file mode 100644 index 0000000..633eddb --- /dev/null +++ b/sim/cris/rvdummy.c @@ -0,0 +1,536 @@ +/* Test-driver for the remote-virtual-component simulator framework + for GDB, the GNU Debugger. + + Copyright 2006 Free Software Foundation, Inc. + + This file is part of GDB. + + 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. */ + +/* Avoid any problems whatsoever building this program if we're not + also building hardware support. */ + +#if !WITH_HW +int +main (int argc, char *argv[]) +{ + return 2; +} +#else + +#ifdef HAVE_CONFIG_H +#include "cconfig.h" +#include "tconfig.h" +#endif + +#include "getopt.h" +#include "libiberty.h" + +#define _GNU_SOURCE +#include <stdio.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +/* Not guarded in dv-sockser.c, so why here. */ +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <sys/socket.h> + +enum rv_command { + RV_READ_CMD = 0, + RV_WRITE_CMD = 1, + RV_IRQ_CMD = 2, + RV_MEM_RD_CMD = 3, + RV_MEM_WR_CMD = 4, + RV_MBOX_HANDLE_CMD = 5, + RV_MBOX_PUT_CMD = 6, + RV_WATCHDOG_CMD = 7 +}; + +enum opts { OPT_PORT = 1, OPT_TIMEOUT, OPT_VERBOSE }; + +struct option longopts[] = + { + {"port", required_argument, NULL, OPT_PORT}, + {"timeout", required_argument, NULL, OPT_TIMEOUT}, + {"verbose", no_argument, NULL, OPT_VERBOSE}, + {NULL, 0, NULL, 0} + }; + +int port = 10000; +time_t timeout = 30000; +char *progname = "(unknown)"; +int verbose = 0; + +/* Required forward-declarations. */ +static void handle_input_file (int, char *); + +/* Set up a "server" listening to the port in PORT for a raw TCP + connection. Return a file descriptor for the connection or -1 on + error. */ + +int setupsocket (void) +{ + int s; + socklen_t len; + int reuse = 1; + struct sockaddr_in sa_in; + struct sockaddr_in from; + + len = sizeof (from); + memset (&from, 0, len); + memset (&sa_in, 0, sizeof (sa_in)); + + s = socket (AF_INET, SOCK_STREAM, 0); + if (s < 0) + return -1; + + if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse) != 0) + return -1; + + sa_in.sin_port = htons (port); + sa_in.sin_family = AF_INET; + + if (bind (s, (struct sockaddr *) & sa_in, sizeof sa_in) < 0) + return -1; + + if (listen (s, 1) < 0) + return -1; + + return accept (s, (struct sockaddr *) &from, &len); +} + +/* Basic host-to-little-endian 32-bit value. Could use the BFD + machinery, but let's avoid it for this only dependency. */ + +static void +h2le32 (unsigned char *dest, unsigned int val) +{ + dest[0] = val & 255; + dest[1] = (val >> 8) & 255; + dest[2] = (val >> 16) & 255; + dest[3] = (val >> 24) & 255; +} + +/* Send a blob of data. */ + +static void +send_output (int fd, unsigned char *buf, int nbytes) +{ + while (nbytes > 0) + { + ssize_t written = write (fd, buf, nbytes); + if (written < 0) + { + fprintf (stderr, "%s: write to socket failed: %s\n", + progname, strerror (errno)); + exit (2); + } + nbytes -= written; + } +} + +/* Receive a blob of data, NBYTES large. Compare to the first NCOMP + bytes of BUF; if not a match, write error message to stderr and + exit (2). Else put it in buf. */ + +static void +expect_input (int fd, unsigned char *buf, int nbytes, int ncomp) +{ + unsigned char byt; + int i; + + for (i = 0; i < nbytes; i++) + { + int r; + + do + { + errno = 0; + r = read (fd, &byt, 1); + } + while (r <= 0 && (r == 0 || errno == EAGAIN)); + + if (r != 1) + { + fprintf (stderr, "%s: read from socket failed: %s", + progname, strerror (errno)); + exit (2); + } + + if (i < ncomp && byt != buf[i]) + { + int j; + fprintf (stderr, "%s: unexpected input,\n ", progname); + if (i == 0) + fprintf (stderr, "nothing,"); + else + for (j = 0; j < i; j++) + fprintf (stderr, "%02x", buf[j]); + fprintf (stderr, "\nthen %02x instead of %02x\n", byt, buf[i]); + exit (2); + } + else + buf[i] = byt; + } +} + +/* Handle everything about a nil-terminated line of input. + Call exit (2) on error with error text on stderr. */ + +static void +handle_input (int fd, char *buf, char *fname, int lineno) +{ + int nbytes = 0; + int n = -1; + char *s = buf + 2; + unsigned int data; + static unsigned char bytes[1024]; + int i; + + memset (bytes, 0, sizeof bytes); + lineno++; + + if (buf[1] != ',') + goto syntax_error; + + switch (buf[0]) + { + /* Comment characters and empty lines. */ + case 0: case '!': case '#': + break; + + /* Include another file. */ + case '@': + handle_input_file (fd, s); + break; + + /* Raw input (to be expected). */ + case 'i': + do + { + n = -1; + sscanf (s, "%02x%n", &data, &n); + s += n; + if (n > 0) + bytes[nbytes++] = data; + } + while (n > 0); + expect_input (fd, bytes, nbytes, nbytes); + if (verbose) + { + printf ("i,"); + for (i = 0; i < nbytes; i++) + printf ("%02x", bytes[i]); + printf ("\n"); + } + break; + + /* Raw output (to be written). */ + case 'o': + do + { + n = -1; + sscanf (s, "%02x%n", &data, &n); + if (n > 0) + { + s += n; + bytes[nbytes++] = data; + } + } + while (n > 0); + if (*s != 0) + goto syntax_error; + send_output (fd, bytes, nbytes); + if (verbose) + { + printf ("o,"); + for (i = 0; i < nbytes; i++) + printf ("%02x", bytes[i]); + printf ("\n"); + } + break; + + /* Read a register. */ + case 'r': + { + unsigned int addr; + sscanf (s, "%x,%x%n", &addr, &data, &n); + if (n < 0 || s[n] != 0) + goto syntax_error; + bytes[0] = 11; + bytes[1] = 0; + bytes[2] = RV_READ_CMD; + h2le32 (bytes + 3, addr); + expect_input (fd, bytes, 11, 7); + h2le32 (bytes + 7, data); + send_output (fd, bytes, 11); + if (verbose) + printf ("r,%x,%x\n", addr, data); + } + break; + + /* Write a register. */ + case 'w': + { + unsigned int addr; + sscanf (s, "%x,%x%n", &addr, &data, &n); + if (n < 0 || s[n] != 0) + goto syntax_error; + bytes[0] = 11; + bytes[1] = 0; + bytes[2] = RV_WRITE_CMD; + h2le32 (bytes + 3, addr); + h2le32 (bytes + 7, data); + expect_input (fd, bytes, 11, 11); + send_output (fd, bytes, 11); + if (verbose) + printf ("w,%x,%x\n", addr, data); + } + break; + + /* Wait for some milliseconds. */ + case 't': + { + int del = 0; + struct timeval to; + sscanf (s, "%d%n", &del, &n); + if (n < 0 || s[n] != 0 || del == 0) + goto syntax_error; + + to.tv_sec = del / 1000; + to.tv_usec = (del % 1000) * 1000; + + if (select (0, NULL, NULL, NULL, &to) != 0) + { + fprintf (stderr, "%s: problem waiting for %d ms:\n %s\n", + progname, del, strerror (errno)); + exit (2); + } + if (verbose) + printf ("t,%d\n", del); + } + break; + + /* Expect a watchdog command. */ + case 'W': + if (*s != 0) + goto syntax_error; + bytes[0] = 3; + bytes[1] = 0; + bytes[2] = RV_WATCHDOG_CMD; + expect_input (fd, bytes, 3, 3); + if (verbose) + printf ("W\n"); + break; + + /* Send an IRQ notification. */ + case 'I': + sscanf (s, "%x%n", &data, &n); + if (n < 0 || s[n] != 0) + goto syntax_error; + bytes[0] = 7; + bytes[1] = 0; + bytes[2] = RV_IRQ_CMD; + h2le32 (bytes + 3, data); + send_output (fd, bytes, 7); + if (verbose) + printf ("I,%x\n", data); + break; + + /* DMA store (to CPU). */ + case 's': + { + unsigned int addr; + sscanf (s, "%x,%n", &addr, &n); + + if (n < 0 || s[n] == 0) + goto syntax_error; + s += n; + do + { + n = -1; + sscanf (s, "%02x%n", &data, &n); + if (n > 0) + { + s += n; + bytes[11 + nbytes++] = data; + } + } + while (n > 0); + + if (*s != 0) + goto syntax_error; + h2le32 (bytes, nbytes + 11); + bytes[2] = RV_MEM_WR_CMD; + h2le32 (bytes + 3, addr); + h2le32 (bytes + 7, nbytes); + send_output (fd, bytes, nbytes + 11); + if (verbose) + { + printf ("s,%x,", addr); + for (i = 0; i < nbytes; i++) + printf ("%02x", bytes[i]); + printf ("\n"); + } + } + break; + + /* DMA load (from CPU). */ + case 'l': + { + unsigned int addr; + sscanf (s, "%x,%n", &addr, &n); + + if (n < 0 || s[n] == 0) + goto syntax_error; + s += n; + do + { + n = -1; + sscanf (s, "%02x%n", &data, &n); + if (n > 0) + { + s += n; + bytes[11 + nbytes++] = data; + } + } + while (n > 0); + + if (*s != 0) + goto syntax_error; + h2le32 (bytes, nbytes + 11); + bytes[0] = 11; + bytes[1] = 0; + bytes[2] = RV_MEM_RD_CMD; + h2le32 (bytes + 3, addr); + h2le32 (bytes + 7, nbytes); + send_output (fd, bytes, 11); + bytes[0] = (nbytes + 11) & 255; + bytes[1] = ((nbytes + 11) >> 8) & 255; + expect_input (fd, bytes, nbytes + 11, nbytes + 11); + if (verbose) + { + printf ("l,%x,", addr); + for (i = 0; i < nbytes; i++) + printf ("%02x", bytes[i]); + printf ("\n"); + } + } + break; + + syntax_error: + default: + fprintf (stderr, "%s: invalid command line in %s:%d:\n %s", + progname, fname, lineno, strerror (errno)); + exit (2); + } +} + +/* Loop over the contents of FNAME, using handle_input to parse each line. + Errors to stderr, exit (2). */ + +static void +handle_input_file (int fd, char *fname) +{ + static char buf[2048] = {0}; + int lineno = 0; + FILE *f = fopen (fname, "r"); + + if (f == NULL) + { + fprintf (stderr, "%s: problem opening %s: %s\n", + progname, fname, strerror (errno)); + exit (2); + } + + /* Let's cut the buffer short, so we always get a newline. */ + while (fgets (buf, sizeof (buf) - 1, f) != NULL) + { + buf[strlen (buf) - 1] = 0; + lineno++; + handle_input (fd, buf, fname, lineno); + } + + fclose (f); +} + +int +main (int argc, char *argv[]) +{ + int optc; + int fd; + FILE *f; + int i; + + progname = argv[0]; + while ((optc = getopt_long (argc, argv, "", longopts, NULL)) != -1) + switch (optc) + { + case OPT_PORT: + port = atoi (optarg); + break; + + case OPT_TIMEOUT: + timeout = (time_t) atoi (optarg); + break; + + case OPT_VERBOSE: + verbose = 1; + break; + } + + fd = setupsocket (); + if (fd < 0) + { + fprintf (stderr, "%s: problem setting up the connection: %s\n", + progname, strerror (errno)); + exit (2); + } + + for (i = optind; i < argc; i++) + handle_input_file (fd, argv[i]); + + /* FIXME: option-controlled test for remaining input? */ + close (fd); + return 1; +} +#endif |