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

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1755 to Rev 1756
    Reverse comparison

Rev 1755 → Rev 1756

/trunk/or1ksim/configure
1,7 → 1,7
#! /bin/sh
# From configure.ac Id: configure.ac 239 2008-11-08 17:09:03Z jeremy using automake version AC_ACVERSION.
# From configure.ac Id: configure.ac 251 2008-11-20 16:21:06Z jeremy using automake version AC_ACVERSION.
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.61 for or1ksim 0.3.0rc2.
# Generated by GNU Autoconf 2.61 for or1ksim 0.3.0rc3.
#
# Report bugs to <openrisc@opencores.org>.
#
729,8 → 729,8
# Identity of this package.
PACKAGE_NAME='or1ksim'
PACKAGE_TARNAME='or1ksim'
PACKAGE_VERSION='0.3.0rc2'
PACKAGE_STRING='or1ksim 0.3.0rc2'
PACKAGE_VERSION='0.3.0rc3'
PACKAGE_STRING='or1ksim 0.3.0rc3'
PACKAGE_BUGREPORT='openrisc@opencores.org'
 
ac_unique_file="cpu/or32/execute.c"
1418,7 → 1418,7
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures or1ksim 0.3.0rc2 to adapt to many kinds of systems.
\`configure' configures or1ksim 0.3.0rc3 to adapt to many kinds of systems.
 
Usage: $0 [OPTION]... [VAR=VALUE]...
 
1489,7 → 1489,7
 
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of or1ksim 0.3.0rc2:";;
short | recursive ) echo "Configuration of or1ksim 0.3.0rc3:";;
esac
cat <<\_ACEOF
 
1598,7 → 1598,7
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
or1ksim configure 0.3.0rc2
or1ksim configure 0.3.0rc3
generated by GNU Autoconf 2.61
 
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
1612,7 → 1612,7
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
 
It was created by or1ksim $as_me 0.3.0rc2, which was
It was created by or1ksim $as_me 0.3.0rc3, which was
generated by GNU Autoconf 2.61. Invocation command line was
 
$ $0 $@
19044,7 → 19044,7
 
# Define the identity of the package.
PACKAGE='or1ksim'
VERSION='0.3.0rc2'
VERSION='0.3.0rc3'
 
 
cat >>confdefs.h <<_ACEOF
26008,7 → 26008,7
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by or1ksim $as_me 0.3.0rc2, which was
This file was extended by or1ksim $as_me 0.3.0rc3, which was
generated by GNU Autoconf 2.61. Invocation command line was
 
CONFIG_FILES = $CONFIG_FILES
26061,7 → 26061,7
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
or1ksim config.status 0.3.0rc2
or1ksim config.status 0.3.0rc3
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
 
/trunk/or1ksim/sim-config.h
82,6 → 82,7
/* each exe_log_marker instructions */
char *exe_log_fn; /* RTL state comparison filename */
long clkcycle_ps; /* Clock duration in ps */
int strict_npc; /* JPB. NPC flushes pipeline when changed */
} sim;
 
struct
170,7 → 171,8
long long cycles; /* Cycles counts fetch stages */
long long int end_cycles; /* JPB. Cycles to end of quantum */
double time_point; /* JPB. Time point in the simulation */
unsigned long int ext_int; /* JPB. External interrupt flags */
unsigned long int ext_int_set; /* JPB. External interrupts to set */
unsigned long int ext_int_clr; /* DXL. External interrupts ti clear */
 
int mem_cycles; /* Each cycle has counter of mem_cycles;
this value is joined with cycles
/trunk/or1ksim/toplevel-support.c
221,6 → 221,7
void
sim_init ()
{
printf ("Or1ksim " PACKAGE_VERSION "\n" );
init_labels ();
init_breakpoints ();
initstats ();
/trunk/or1ksim/debug/debug-unit.c
136,6 → 136,12
 
runtime.cpu.stalled = state;
 
/* If we unstall, any changed NPC becomes valid again */
 
if (!runtime.cpu.stalled)
{
cpu_state.npc_not_valid = 0;
}
} /* set_stall_state () */
 
 
/trunk/or1ksim/debug/rsp-server.c
39,6 → 39,7
#include <arpa/inet.h>
#include <poll.h>
#include <netinet/tcp.h>
#include <signal.h>
 
/* Package includes */
#include "sim-config.h"
48,6 → 49,7
#include "execute.h"
#include "debug-unit.h"
#include "sprs.h"
#include "toplevel-support.h"
 
 
/* Define to log each packet */
59,6 → 61,9
/*! Protocol used by Or1ksim */
#define OR1KSIM_RSP_PROTOCOL "tcp"
 
/*! Thread ID used by Or1ksim */
#define OR1KSIM_TID 1
 
/* Indices of GDB registers that are not GPRs. Must match GDB settings! */
#define PPC_REGNUM (MAX_GPRS + 0) /*!< Previous PC */
#define NPC_REGNUM (MAX_GPRS + 1) /*!< Next PC */
130,7 → 135,6
{
int client_waiting; /*!< Is client waiting a response? */
int proto_num; /*!< Number of the protocol used */
int server_fd; /*!< FD for new connections */
int client_fd; /*!< FD for talking to GDB */
int sigval; /*!< GDB signal for any exception */
unsigned long int start_addr; /*!< Start of last run */
138,9 → 142,8
} rsp;
 
/* Forward declarations of static functions */
static void rsp_server_request ();
static void rsp_get_client ();
static void rsp_client_request ();
static void rsp_server_close ();
static void rsp_client_close ();
static void put_packet (struct rsp_buf *buf);
static void put_str_packet (const char *str);
194,31 → 197,13
/*---------------------------------------------------------------------------*/
/*!Initialize the Remote Serial Protocol connection
 
This involves setting up a socket to listen on a socket for attempted
connections from a single GDB instance (we couldn't be talking to multiple
GDBs at once!).
 
The service is specified either as a port number in the Or1ksim configuration
(parameter rsp_port in section debug, default 51000) or as a service name
in the constant OR1KSIM_RSP_SERVICE.
 
The protocol used for communication is specified in OR1KSIM_RSP_PROTOCOL. */
Set up the central data structures. */
/*---------------------------------------------------------------------------*/
void
rsp_init ()
{
struct protoent *protocol; /* Protocol number */
struct hostent *host_entry; /* Our host entry */
struct sockaddr_in sock_addr; /* Socket address */
 
int optval; /* Socket options */
int flags; /* Socket flags */
char name[256]; /* Our name */
 
/* Clear out the central data structure */
rsp.client_waiting = 0; /* GDB client is not waiting for us */
rsp.proto_num = -1; /* i.e. invalid */
rsp.server_fd = -1; /* i.e. invalid */
rsp.client_fd = -1; /* i.e. invalid */
rsp.sigval = 0; /* No exception */
rsp.start_addr = EXCEPT_RESET; /* Default restart point */
226,118 → 211,6
/* Set up the matchpoint hash table */
mp_hash_init ();
 
/* Get the protocol number of TCP and save it for future use */
protocol = getprotobyname (OR1KSIM_RSP_PROTOCOL);
if (NULL == protocol)
{
fprintf (stderr, "Warning: RSP unable to load protocol \"%s\": %s\n",
OR1KSIM_RSP_PROTOCOL, strerror (errno));
return;
}
 
rsp.proto_num = protocol->p_proto; /* Saved for future client use */
 
/* 0 is used as the RSP port number to indicate that we should use the
service name instead. */
if (0 == config.debug.rsp_port)
{
struct servent *service =
getservbyname (OR1KSIM_RSP_SERVICE, protocol->p_name);
 
if (NULL == service)
{
fprintf (stderr, "Warning: RSP unable to find service \"%s\": %s\n",
OR1KSIM_RSP_SERVICE, strerror (errno));
return;
}
 
config.debug.rsp_port = ntohs (service->s_port);
}
 
/* Create the socket using the TCP protocol */
rsp.server_fd = socket (PF_INET, SOCK_STREAM, protocol->p_proto);
if (rsp.server_fd < 0)
{
fprintf (stderr, "Warning: RSP could not create server socket: %s\n",
strerror (errno));
return;
}
 
/* Set this socket to reuse its address. This allows the server to keep
trying before a GDB session has got going. */
optval = 1;
if (setsockopt(rsp.server_fd, SOL_SOCKET,
SO_REUSEADDR, &optval, sizeof (optval)) < 0)
{
fprintf (stderr, "Cannot set SO_REUSEADDR option on server socket %d: "
"%s\n", rsp.server_fd, strerror (errno));
rsp_server_close();
return;
}
 
/* The server should be non-blocking. Get the current flags and then set the
non-blocking flags */
flags = fcntl (rsp.server_fd, F_GETFL);
if (flags < 0)
{
fprintf (stderr, "Warning: Unable to get flags for RSP server socket "
"%d: %s\n", rsp.server_fd, strerror (errno));
rsp_server_close();
return;
}
 
flags |= O_NONBLOCK;
if (fcntl (rsp.server_fd, F_SETFL, flags) < 0)
{
fprintf (stderr, "Warning: Unable to set flags for RSP server socket "
"%d to 0x%08x: %s\n", rsp.server_fd, flags, strerror (errno));
rsp_server_close();
return;
}
 
/* Find out what our name is */
if (gethostname (name, sizeof (name)) < 0)
{
fprintf (stderr, "Warning: Unable to get hostname for RSP server: %s\n",
strerror (errno));
rsp_server_close();
return;
}
 
/* Find out what our address is */
host_entry = gethostbyname (name);
if (NULL == host_entry)
{
fprintf (stderr, "Warning: Unable to get host entry for RSP server: "
"%s\n", strerror (errno));
rsp_server_close();
return;
}
 
/* Bind our socket to the appropriate address */
memset (&sock_addr, 0, sizeof (sock_addr));
sock_addr.sin_family = host_entry->h_addrtype;
sock_addr.sin_port = htons (config.debug.rsp_port);
 
if (bind (rsp.server_fd,
(struct sockaddr *)&sock_addr, sizeof (sock_addr)) < 0)
{
fprintf (stderr, "Warning: Unable to bind RSP server socket %d to port "
"%d: %s\n", rsp.server_fd, config.debug.rsp_port,
strerror (errno));
rsp_server_close();
return;
}
 
/* Mark us as a passive port, with a maximum backlog of 1 connection (we
never connect simultaneously to more than one RSP client!) */
if (listen (rsp.server_fd, 1) < 0)
{
fprintf (stderr, "Warning: Unable to set RSP backlog on server socket "
"%d to %d: %s\n", rsp.server_fd, 1, strerror (errno));
rsp_server_close();
return;
}
} /* rsp_init () */
 
 
347,86 → 220,27
This function is called when the processor has stalled, which, except for
initialization, must be due to an interrupt.
 
If we have no RSP client, we poll the RSP server for a client requesting to
join. We can make no progress until the client is available.
If we have no RSP client, we get one. We can make no progress until the
client is available.
 
Then if the cause is an interrupt, and the interrupt not been notified to
GDB, a packet reporting the cause of the interrupt is sent.
Then if the cause is an exception following a step or continue command, and
the exception not been notified to GDB, a packet reporting the cause of the
exception is sent.
 
The function then polls the RSP client port (if open)
for available input. It then processes the GDB RSP request and return.
 
If an error occurs when polling the RSP server, other than an interrupt, a
warning message is printed out and the RSP server and client (if open)
connections are closed.
 
If an error occurs when polling the RSP client, other than an interrupt, a
warning message is printed out and the RSP client connection is closed.
 
Polling is always blocking (i.e. timeout -1). */
The next client request is then processed. */
/*---------------------------------------------------------------------------*/
void
handle_rsp ()
{
struct pollfd fds[1]; /* The FD to poll for */
 
/* Give up if no RSP server port (this should not occur) */
if (-1 == rsp.server_fd)
{
fprintf (stderr, "Warning: No RSP server port open\n");
return;
}
 
/* If we have no RSP client, poll the server until we get one. */
/* If we have no RSP client, wait until we get one. */
while (-1 == rsp.client_fd)
{
/* Poll for a client on the RSP server socket */
fds[0].fd = rsp.server_fd; /* FD for the server socket */
fds[0].events = POLLIN; /* Poll for input activity */
 
/* Poll is always blocking. We can't do anything more until something
happens here. */
switch (poll (fds, 1, -1))
{
case -1:
/* Error. Only one we ignore is an interrupt */
if (EINTR != errno)
{
fprintf (stderr, "Warning: poll for RSP failed: closing "
"server connection: %s\n", strerror (errno));
rsp_client_close();
rsp_server_close();
return;
}
break;
 
case 0:
/* Timeout. This can't occur! */
fprintf (stderr, "Warning: Unexpected RSP server poll timeout\n");
break;
 
default:
/* Is the poll due to input available? If we succeed ignore any
outstanding reports of exceptions. */
if (POLLIN == (fds[0].revents & POLLIN))
{
rsp_server_request ();
rsp.client_waiting = 0; /* No longer waiting */
}
else
{
/* Error leads to closing the client and server */
fprintf (stderr, "Warning: RSP server received flags "
"0x%08x: closing server connection\n", fds[0].revents);
rsp_client_close();
rsp_server_close();
}
}
rsp_get_client ();
rsp.client_waiting = 0; /* No longer waiting */
}
 
/* If we have an unacknowledged exception and a client is available, tell
GDB. If this exception was a trap due to a memory breakpoint, then
adjust the NPC. */
/* If we have an unacknowledged exception tell the GDB client. If this
exception was a trap due to a memory breakpoint, then adjust the NPC. */
if (rsp.client_waiting)
{
if ((TARGET_SIGNAL_TRAP == rsp.sigval) &&
438,46 → 252,10
rsp_report_exception();
rsp.client_waiting = 0; /* No longer waiting */
}
/* Poll the RSP client socket for a message from GDB */
fds[0].fd = rsp.client_fd; /* FD for the client socket */
fds[0].events = POLLIN; /* Poll for input activity */
 
/* Poll is always blocking. We can't do anything more until something
happens here. */
switch (poll (fds, 1, -1))
{
case -1:
/* Error. Only one we ignore is an interrupt */
if (EINTR != errno)
{
fprintf (stderr, "Warning: poll for RSP failed: closing "
"server connection: %s\n", strerror (errno));
rsp_client_close();
rsp_server_close();
}
/* Get a RSP client request */
rsp_client_request ();
 
return;
 
case 0:
/* Timeout. This can't occur! */
fprintf (stderr, "Warning: Unexpected RSP client poll timeout\n");
return;
 
default:
/* Is the client activity due to input available? */
if (POLLIN == (fds[0].revents & POLLIN))
{
rsp_client_request ();
}
else
{
/* Error leads to closing the client, but not the server. */
fprintf (stderr, "Warning: RSP client received flags "
"0x%08x: closing client connection\n", fds[0].revents);
rsp_client_close();
}
}
} /* handle_rsp () */
 
 
491,7 → 269,7
We flag up a warning if an exception is already pending, and ignore the
earlier exception.
 
@param[in] except The exception (Or1ksim form) */
@param[in] except The exception (Or1ksim form) */
/*---------------------------------------------------------------------------*/
void
rsp_exception (unsigned long int except)
532,89 → 310,118
 
 
/*---------------------------------------------------------------------------*/
/*!Handle a request to the server for a new client
/*!Get a new client connection.
 
We may already have a client. If we do, we will accept an immediately close
the new client. */
Blocks until the client connection is available.
 
A lot of this code is copied from remote_open in gdbserver remote-utils.c.
 
This involves setting up a socket to listen on a socket for attempted
connections from a single GDB instance (we couldn't be talking to multiple
GDBs at once!).
 
The service is specified either as a port number in the Or1ksim configuration
(parameter rsp_port in section debug, default 51000) or as a service name
in the constant OR1KSIM_RSP_SERVICE.
 
The protocol used for communication is specified in OR1KSIM_RSP_PROTOCOL. */
/*---------------------------------------------------------------------------*/
static void
rsp_server_request ()
rsp_get_client ()
{
struct sockaddr_in sock_addr; /* The socket address */
int tmp_fd; /* Temporary descriptor for socket */
int optval; /* Socket options */
struct sockaddr_in sock_addr; /* Socket address */
socklen_t len; /* Size of the socket address */
int fd; /* The client FD */
int flags; /* fcntl () flags */
int optval; /* Option value for setsockopt () */
 
/* Get the client FD */
len = sizeof (sock_addr);
fd = accept (rsp.server_fd, (struct sockaddr *)&sock_addr, &len);
if (fd < 0)
/* 0 is used as the RSP port number to indicate that we should use the
service name instead. */
if (0 == config.debug.rsp_port)
{
/* This is can happen, because a connection could have started, and then
terminated due to a protocol error or user initiation before the
accept could take place.
struct servent *service =
getservbyname (OR1KSIM_RSP_SERVICE, "tcp");
 
Two of the errors we can ignore (a retry is permissible). All other
errors, we assume the server port has gone tits up and close. */
 
if ((errno != EWOULDBLOCK) && (errno != EAGAIN))
if (NULL == service)
{
fprintf (stderr, "Warning: RSP server error creating client: "
"closing connection %s\n", strerror (errno));
rsp_client_close ();
rsp_server_close ();
fprintf (stderr, "Warning: RSP unable to find service \"%s\": %s\n",
OR1KSIM_RSP_SERVICE, strerror (errno));
return;
}
 
return;
config.debug.rsp_port = ntohs (service->s_port);
}
 
/* If we already have a client, then immediately close the new one */
if (-1 != rsp.client_fd)
/* Open a socket on which we'll listen for clients */
tmp_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (tmp_fd < 0)
{
fprintf (stderr, "Warning: Additional RSP client request refused\n");
close (fd);
return;
fprintf (stderr, "ERROR: Cannot open RSP socket\n");
sim_done ();
}
 
/* We have a new client, which should be non-blocking. Get the current flags
and then set the non-blocking flags */
flags = fcntl (fd, F_GETFL);
if (flags < 0)
/* Allow rapid reuse of the port on this socket */
optval = 1;
setsockopt (tmp_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval,
sizeof (optval));
 
/* Bind the port to the socket */
sock_addr.sin_family = PF_INET;
sock_addr.sin_port = htons (config.debug.rsp_port);
sock_addr.sin_addr.s_addr = INADDR_ANY;
if (bind (tmp_fd, (struct sockaddr *) &sock_addr, sizeof (sock_addr)))
{
fprintf (stderr, "Warning: Unable to get flags for RSP client socket "
"%d: %s\n", fd, strerror (errno));
close (fd);
return;
fprintf (stderr, "ERROR: Cannot bind to RSP socket\n");
sim_done ();
}
 
flags |= O_NONBLOCK;
if (fcntl (fd, F_SETFL, flags) < 0)
/* Listen for (at most one) client */
if (listen (tmp_fd, 1))
{
fprintf (stderr, "Warning: Unable to set flags for RSP client socket "
"%d to 0x%08x: %s\n", fd, flags, strerror (errno));
close (fd);
return;
fprintf (stderr, "ERROR: Cannot listen on RSP socket\n");
sim_done ();
}
 
/* Turn of Nagel's algorithm for the client socket. This means the client
sends stuff immediately, it doesn't wait to fill up a packet. */
optval = 0;
len = sizeof (optval);
if (setsockopt (fd, rsp.proto_num, TCP_NODELAY, &optval, len) < 0)
printf ("Listening for RSP on port %d\n", config.debug.rsp_port);
fflush (stdout);
 
/* Accept a client which connects */
rsp.client_fd = accept (tmp_fd, (struct sockaddr *)&sock_addr, &len);
 
if (-1 == rsp.client_fd)
{
fprintf (stderr, "Warning: Unable to disable Nagel's algorithm for "
"RSP client socket %d: %s\n", fd, strerror (errno));
close (fd);
fprintf (stderr, "Warning: Failed to accept RSP client\n");
return;
}
 
/* We have a new client socket */
rsp.client_fd = fd;
/* Enable TCP keep alive process */
optval = 1;
setsockopt (rsp.client_fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval,
sizeof (optval));
 
} /* rsp_server_request () */
/* Don't delay small packets, for better interactive response (disable
Nagel's algorithm) */
optval = 1;
setsockopt (rsp.client_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&optval,
sizeof (optval));
 
/* Socket is no longer needed */
close (tmp_fd); /* No longer need this */
signal (SIGPIPE, SIG_IGN); /* So we don't exit if client dies */
 
printf ("Remote debugging from host %s\n", inet_ntoa (sock_addr.sin_addr));
 
/* If fcntl () is available, use it to enable async I/O
#if defined(F_SETFL) && defined (FASYNC)
save_fcntl_flags = fcntl (remote_desc, F_GETFL, 0);
fcntl (remote_desc, F_SETFL, save_fcntl_flags | FASYNC);
#if defined (F_SETOWN)
fcntl (remote_desc, F_SETOWN, getpid ());
#endif
#endif */
 
} /* rsp_get_client () */
 
 
/*---------------------------------------------------------------------------*/
/*!Deal with a request from the GDB client session
 
693,6 → 500,7
put_str_packet ("OK");
rsp_client_close ();
set_stall_state (0);
rsp.sigval = TARGET_SIGNAL_NONE; /* No signal now */
return;
 
case 'F':
827,23 → 635,9
 
 
/*---------------------------------------------------------------------------*/
/*!Close the server if it is open */
/*!Close the connection to the client if it is open */
/*---------------------------------------------------------------------------*/
static void
rsp_server_close ()
{
if (-1 != rsp.server_fd)
{
close (rsp.server_fd);
rsp.server_fd = -1;
}
} /* rsp_server_close () */
 
 
/*---------------------------------------------------------------------------*/
/*!Close the client if it is open */
/*---------------------------------------------------------------------------*/
static void
rsp_client_close ()
{
if (-1 != rsp.client_fd)
1129,8 → 923,6
static int
get_rsp_char ()
{
unsigned char c; /* The character read */
 
if (-1 == rsp.client_fd)
{
fprintf (stderr, "Warning: Attempt to read from unopened RSP "
1138,14 → 930,16
return -1;
}
 
/* Read until successful (we retry after interrupts) or catastrophic
failure. */
/* Non-blocking read until successful (we retry after interrupts) or
catastrophic failure. */
while (1)
{
unsigned char c;
 
switch (read (rsp.client_fd, &c, sizeof (c)))
{
case -1:
/* Error: only allow interrupts or would block */
/* Error: only allow interrupts */
if ((EAGAIN != errno) && (EINTR != errno))
{
fprintf (stderr, "Warning: Failed to read from RSP client: "
1154,7 → 948,7
rsp_client_close ();
return -1;
}
 
break;
 
case 0:
1163,7 → 957,7
return -1;
 
default:
return c & 0xff; /* Success, we can return (no sign extend!) */
return c & 0xff; /* Success, we can return (no sign extend!) */
}
}
} /* get_rsp_char () */
1611,6 → 1405,9
/* Unstall the processor */
set_stall_state (0);
 
/* Any signal is cleared. */
rsp.sigval = TARGET_SIGNAL_NONE;
 
/* Note the GDB client is now waiting for a reply. */
rsp.client_waiting = 1;
 
1846,7 → 1643,7
unsigned int regnum;
 
/* Break out the fields from the data */
if (2 != sscanf (buf->data, "p%x", &regnum))
if (1 != sscanf (buf->data, "p%x", &regnum))
{
fprintf (stderr, "Warning: Failed to recognize RSP read register "
"command: %s\n", buf->data);
1946,7 → 1743,8
/*---------------------------------------------------------------------------*/
/*!Handle a RSP query request
 
@param[in] buf The request */
@param[in] buf The request. Reused for any packets that need to be sent
back. */
/*---------------------------------------------------------------------------*/
static void
rsp_query (struct rsp_buf *buf)
1954,9 → 1752,11
if (0 == strcmp ("qC", buf->data))
{
/* Return the current thread ID (unsigned hex). A null response
indicates to use the previously selected thread. Since we do not
support a thread concept, this is the appropriate response. */
put_str_packet ("");
indicates to use the previously selected thread. We use the constant
OR1KSIM_TID to represent our single thread of control. */
sprintf (buf->data, "QC%x", OR1KSIM_TID);
buf->len = strlen (buf->data);
put_packet (buf);
}
else if (0 == strncmp ("qCRC", buf->data, strlen ("qCRC")))
{
1966,8 → 1766,11
}
else if (0 == strcmp ("qfThreadInfo", buf->data))
{
/* Return info about active threads. We return just '-1' */
put_str_packet ("m-1");
/* Return info about active threads. We return just the constant
OR1KSIM_TID to represent our single thread of control. */
sprintf (buf->data, "m%x", OR1KSIM_TID);
buf->len = strlen (buf->data);
put_packet (buf);
}
else if (0 == strcmp ("qsThreadInfo", buf->data))
{
2084,7 → 1887,7
}
 
/* Construct the reply */
sprintf (cmd, "%8x", mfspr (regno));
sprintf (cmd, "%8lx", (unsigned long int)mfspr (regno));
ascii2hex (buf->data, cmd);
buf->len = strlen (buf->data);
put_packet (buf);
2244,6 → 2047,9
/* Unstall the processor */
set_stall_state (0);
 
/* Any signal is cleared. */
rsp.sigval = TARGET_SIGNAL_NONE;
 
/* Note the GDB client is now waiting for a reply. */
rsp.client_waiting = 1;
 
2393,8 → 2199,7
}
else
{
// circumvent the read-only check usually done for mem accesses
// data is in host order, because that's what set_direct32 needs
// Circumvent the read-only check usually done for mem accesses
set_program8 (addr + off, bindat[off]);
}
}
/trunk/or1ksim/cpu/or32/execute.c
863,8 → 863,11
 
/* MM1409: All progs should start at reset vector entry! This sorted out by
setting the cpu_state.pc field below. Not clear this is very good code! */
pcnext = 0x0;
 
/* Patches suggested by Shinji Wakatsuki, so that the vector address takes
notice of the Exception Prefix High bit of the Supervision register */
pcnext = (cpu_state.sprs[SPR_SR] & SPR_SR_EPH ? 0xf0000000 : 0x00000000);
 
if (config.sim.verbose)
{
PRINTF ("Starting at 0x%" PRIxADDR "\n", pcnext);
880,7 → 883,8
#endif
 
except_pending = 0;
cpu_state.pc = EXCEPT_RESET;
cpu_state.pc = cpu_state.sprs[SPR_SR] & SPR_SR_EPH ?
0xf0000000 + EXCEPT_RESET : EXCEPT_RESET;
 
} /* cpu_reset() */
 
/trunk/or1ksim/cpu/or32/insnset.c
484,7 → 484,7
hi = cpu_state.sprs[SPR_MACHI];
x = PARAM0;
y = PARAM1;
PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y);
/* PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y); */
l = (ULONGEST)lo | ((LONGEST)hi << 32);
l += (LONGEST) x * (LONGEST) y;
 
493,7 → 493,7
hi = ((LONGEST)l) >> 32;
cpu_state.sprs[SPR_MACLO] = lo;
cpu_state.sprs[SPR_MACHI] = hi;
PRINTF ("(%"PRIxREG",%"PRIxREG"\n", hi, lo);
/* PRINTF ("(%"PRIxREG",%"PRIxREG"\n", hi, lo); */
}
INSTRUCTION (l_msb) {
uorreg_t lo, hi;
505,7 → 505,7
x = PARAM0;
y = PARAM1;
 
PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y);
/* PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, y); */
 
l = (ULONGEST)lo | ((LONGEST)hi << 32);
l -= x * y;
515,7 → 515,7
hi = ((LONGEST)l) >> 32;
cpu_state.sprs[SPR_MACLO] = lo;
cpu_state.sprs[SPR_MACHI] = hi;
PRINTF ("(%"PRIxREG",%"PRIxREG")\n", hi, lo);
/* PRINTF ("(%"PRIxREG",%"PRIxREG")\n", hi, lo); */
}
INSTRUCTION (l_macrc) {
uorreg_t lo, hi;
/trunk/or1ksim/cpu/common/execute.h
66,6 → 66,7
uorreg_t sprs[MAX_SPRS]; /*!< Special purpose registers */
oraddr_t insn_ea; /*!< EA of instrs that have an EA */
int delay_insn; /*!< Is current instr in delay slot */
int npc_not_valid; /*!< NPC updated while stalled */
oraddr_t pc; /*!< PC (and translated PC) */
oraddr_t pc_delay; /*!< Delay instr EA register */
uint32_t pic_lines; /*!< State of PIC lines */
/trunk/or1ksim/cpu/or1k/spr-dump.c
361,7 → 361,7
{ "DSR_IME", SPR_DSR_IME },
{ "DSR_RE", SPR_DSR_RE },
{ "DSR_SCE", SPR_DSR_SCE },
{ "DSR_SSE", SPR_DSR_SSE },
{ "DSR_FPE", SPR_DSR_FPE },
{ "DSR_TE", SPR_DSR_TE },
{ NULL, 0 } };
 
/trunk/or1ksim/cpu/or1k/sprs.c
128,14 → 128,32
/* The debugger has redirected us to a new address */
/* This is usually done to reissue an instruction
which just caused a breakpoint exception. */
cpu_state.pc = value;
 
/* JPB patch. When GDB stepi, this may be used to set the PC to the
value it is already at. If this is the case, then we do nothing (in
particular we do not trash a delayed branch) */
 
if (value != cpu_state.pc)
{
cpu_state.pc = value;
if(!value && config.sim.verbose)
PRINTF("WARNING: PC just set to 0!\n");
/* Clear any pending delay slot jumps also */
cpu_state.delay_insn = 0;
pcnext = value + 4;
if(!value && config.sim.verbose)
PRINTF("WARNING: PC just set to 0!\n");
 
/* Clear any pending delay slot jumps also */
cpu_state.delay_insn = 0;
pcnext = value + 4;
 
/* Further JPB patch. If the processor is stalled, then subsequent
reads of the NPC should return 0 until the processor is
unstalled. If the processor is stalled, note that the NPC has
been updated while the processor was stalled. */
 
if (runtime.cpu.stalled)
{
cpu_state.npc_not_valid = 1;
}
}
}
break;
case SPR_PICSR:
221,8 → 239,22
 
switch (regno) {
case SPR_NPC:
ret = cpu_state.pc;
 
/* The NPC is the program counter UNLESS the NPC has been changed and we
are stalled, which will have flushed the pipeline, so the value is
zero. Currently this is optional behavior, since it breaks GDB.
*/
 
if (config.sim.strict_npc && cpu_state.npc_not_valid)
{
ret = 0;
}
else
{
ret = cpu_state.pc;
}
break;
 
case SPR_TTCR:
ret = spr_read_ttcr();
break;
/trunk/or1ksim/cpu/or1k/spr-defs.h
478,7 → 478,7
#define SPR_DSR_IME 0x00000200 /* ITLB miss exception */
#define SPR_DSR_RE 0x00000400 /* Range exception */
#define SPR_DSR_SCE 0x00000800 /* System call exception */
#define SPR_DSR_SSE 0x00001000 /* Single Step Exception */
#define SPR_DSR_FPE 0x00001000 /* Floating Point Exception */
#define SPR_DSR_TE 0x00002000 /* Trap exception */
 
/*
497,7 → 497,8
#define SPR_DRR_IME 0x00000200 /* ITLB miss exception */
#define SPR_DRR_RE 0x00000400 /* Range exception */
#define SPR_DRR_SCE 0x00000800 /* System call exception */
#define SPR_DRR_TE 0x00001000 /* Trap exception */
#define SPR_DRR_FPE 0x00001000 /* Floating Point Exception */
#define SPR_DRR_TE 0x00002000 /* Trap exception */
 
/*
* Bit definitions for Performance counters mode registers
/trunk/or1ksim/libtoplevel.c
104,7 → 104,8
 
sim_init ();
 
runtime.sim.ext_int = 0; /* No interrupts pending */
runtime.sim.ext_int_set = 0; /* No interrupts pending to be set */
runtime.sim.ext_int_clr = 0; /* No interrupts pending to be cleared */
 
return OR1KSIM_RC_OK;
 
137,6 → 138,8
int
or1ksim_run (double duration)
{
const int num_ints = sizeof (runtime.sim.ext_int_set) * 8;
 
or1ksim_reset_duration (duration);
 
/* Loop until we have done enough cycles (or forever if we had a negative
161,21 → 164,36
 
runtime.sim.cycles += runtime.sim.mem_cycles;
 
/* Taken any external interrupts. Outer test is for the common case for
/* Take any external interrupts. Outer test is for the common case for
efficiency. */
 
if (0 != runtime.sim.ext_int)
if (0 != runtime.sim.ext_int_set)
{
for (i = 0; i < sizeof (runtime.sim.ext_int); i++)
for (i = 0; i < num_ints; i++)
{
if (0x1 == ((runtime.sim.ext_int >> i) & 0x1))
if (0x1 == ((runtime.sim.ext_int_set >> i) & 0x1))
{
report_interrupt (i);
runtime.sim.ext_int &= ~(1 << i); /* Clear int */
runtime.sim.ext_int_set &= ~(1 << i); /* Clear req flag */
}
}
}
 
/* Clear any interrupts as requested. For edge triggered interrupts this
will happen in the same cycle. For level triggered, it must be an
explicit call. */
if (0 != runtime.sim.ext_int_clr)
{
for (i = 0; i < num_ints; i++)
{
/* Only clear interrupts that have been explicitly cleared */
if(0x1 == ((runtime.sim.ext_int_clr >> i) & 0x1))
{
clear_interrupt(i);
runtime.sim.ext_int_clr &= ~(1 << i); /* Clear clr flag */
}
}
}
 
/* Update the scheduler queue */
 
scheduler.job_queue->time -= (runtime.sim.cycles - time_start);
288,16 → 306,79
 
 
/*---------------------------------------------------------------------------*/
/*!Take an interrupt
/*!Trigger an edge triggered interrupt
 
@note There is no check that the specified interrupt number is reasonable
(i.e. <= 31).
This function is appropriate for edge triggered interrupts, which are taken
and then immediately cleared.
 
@note There is no check that the specified interrupt number is reasonable
(i.e. <= 31).
 
@param[in] i The interrupt number */
/*---------------------------------------------------------------------------*/
void
or1ksim_interrupt (int i)
{
runtime.sim.ext_int |= 1 << i; // Better not be > 31!
if (!config.pic.edge_trigger)
{
fprintf (stderr, "Warning: or1ksim_interrupt should not be used for "
"edge triggered interrupts. Ignored\n");
}
else
{
runtime.sim.ext_int_set |= 1 << i; // Better not be > 31!
runtime.sim.ext_int_clr |= 1 << i; // Better not be > 31!
}
} /* or1ksim_interrupt() */
 
 
/*---------------------------------------------------------------------------*/
/*!Set a level triggered interrupt
 
This function is appropriate for level triggered interrupts, which must be
explicitly cleared in a separate call.
 
@note There is no check that the specified interrupt number is reasonable
(i.e. <= 31).
 
@param[in] i The interrupt number to set */
/*---------------------------------------------------------------------------*/
void
or1ksim_interrupt_set (int i)
{
if (config.pic.edge_trigger)
{
fprintf (stderr, "Warning: or1ksim_interrupt_set should not be used for "
"level triggered interrupts. Ignored\n");
}
else
{
runtime.sim.ext_int_set |= 1 << i; // Better not be > 31!
}
} /* or1ksim_interrupt() */
 
 
/*---------------------------------------------------------------------------*/
/*!Clear a level triggered interrupt
 
This function is appropriate for level triggered interrupts, which must be
explicitly set first in a separate call.
 
@note There is no check that the specified interrupt number is reasonable
(i.e. <= 31).
 
@param[in] i The interrupt number to clear */
/*---------------------------------------------------------------------------*/
void
or1ksim_interrupt_clear (int i)
{
if (config.pic.edge_trigger)
{
fprintf (stderr, "Warning: or1ksim_interrupt_clear should not be used "
"for level triggered interrupts. Ignored\n");
}
else
{
runtime.sim.ext_int_clr |= 1 << i; // Better not be > 31!
}
} /* or1ksim_interrupt() */
/trunk/or1ksim/configure.ac
26,7 → 26,7
# Process this file with autoconf to produce a configure script.
 
 
AC_INIT([or1ksim], [0.3.0rc2], [openrisc@opencores.org])
AC_INIT([or1ksim], [0.3.0rc3], [openrisc@opencores.org])
AC_CONFIG_SRCDIR([cpu/or32/execute.c])
AC_CANONICAL_TARGET([])
AC_PROG_LIBTOOL
33,7 → 33,7
AM_INIT_AUTOMAKE
AC_CONFIG_HEADERS([config.h])
 
AC_REVISION([$Id: configure.ac,v 1.2 2008-11-11 13:24:02 jeremybennett Exp $ using automake version] AC_ACVERSION)
AC_REVISION([$Id: configure.ac,v 1.3 2009-02-24 16:55:37 jeremybennett Exp $ using automake version] AC_ACVERSION)
 
# make sure we are using a recent autoconf version
AC_PREREQ(2.59)
/trunk/or1ksim/doc/or1ksim.info
53,6 → 53,7
* Preparation::
* Configuring the Build::
* Build and Install::
* Known Issues::
 

File: or1ksim.info, Node: Preparation, Next: Configuring the Build, Up: Installation
63,7 → 64,7
Unpack the software and create a _separate_ directory in which to build
it:
 
tar jxf or1ksim-0.3.0rc2.tar.bz2
tar jxf or1ksim-0.3.0rc3.tar.bz2
mkdir builddir_or1ksim
cd builddir_or1ksim
 
80,7 → 81,7
OpenRISC 1000 32-bit architecture. If this argument is omitted, it will
default to OpenRISC 1000 32-bit with a warning
 
../or1ksim-0.3.0rc2/configure --target=or32-uclinux ...
../or1ksim-0.3.0rc3/configure --target=or32-uclinux ...
 
There are several other options available, many of which are standard
to GNU `configure' scripts. Use `configure --help' to see all the
195,7 → 196,7
 
 

File: or1ksim.info, Node: Build and Install, Prev: Configuring the Build, Up: Installation
File: or1ksim.info, Node: Build and Install, Next: Known Issues, Prev: Configuring the Build, Up: Installation
 
1.3 Building and Installing
===========================
219,6 → 220,53
make install-pdf
 

File: or1ksim.info, Node: Known Issues, Prev: Build and Install, Up: Installation
 
1.4 Known Problems and Issues
=============================
 
The following problems and issues are known about with Or1ksim
0.3.0rc3. The OpenRISC tracker may be used to see the current state of
these issues and to raise new problems and feature requests. It may be
found at `http://www.opencores.org/ptracker.cgi/view/or1k/398'.
 
* The Supervision Register Little Endian Enable (LEE) bit is
ignored. Or1ksim can be built for either little endian or big
endian use, but that behavior cannot be changed dynamically.
 
* The NPC is a read/write register, but after being written it
clears the pipeline. This means that if the processor is stalled,
the value should subsequently read back as 0, until the processor
is unstalled and able to refill its pipeline. By default Or1ksim
always reports back the value of NPC, even when it has been
written while stalled.
 
There is now an option, `--strict-npc', which will enforce this
behavior. At some stage in the future it will become the default
behavior, but for now it is an option, since its use will break
GDB.
 
* The memory components are given names in the configuration file.
However there is currently no way for Or1ksim to report that name
back to the user (for example to identify which memory block
corresponds to a particular access).
 
* Or1ksim allows the processor to be stalled (from the command
line), even if there is no debugger present. This seems to be a
meaningless operation.
 
* Or1ksim is not reentrant, so a program cannot instantiate multiple
instances using the library. This is clearly a problem when
considering multi-core applications. However it stems from the
original design, and can only be fixed by a complete rewrite. The
entire source code uses static global constants liberally!
 
* There is no support for floating point instructions currently in
Or1ksim. However this is a work in progress and should be
available in the near future.
 
 

File: or1ksim.info, Node: Usage, Next: Configuration, Prev: Installation, Up: Top
 
2 Usage
287,6 → 335,23
`--interactive'
After starting, drop into the Or1ksim interactive command shell.
 
`--strict-npc'
In real hardware, setting the next program counter (NPC, SPR 16),
flushes the processor pipeline. The consequence of this is that
until the pipeline refills, reading the NPC will return zero. This
is typically the case when debugging, since the processor is
stalled.
 
Historically, Or1ksim has always returned the value of the NPC,
irrespective of when it is changed. If the `--strict-npc' option is
used, then Or1ksim will mirror real hardware more accurately. If
the NPC is changed while the processor is stalled, subsequent
reads of its value will return 0 until the processor is unstalled.
 
This is not currently the default behavior, since tools such as
GDB have been implemented assuming the historic Or1ksim behavior.
However at some time in the future it will become the default.
 
`--enable-profile'
Enable instruction profiling.
 
425,7 → 490,15
passed back with these upcalls, allowing the function to associate
the call with the class which originally initialized the library.
 
MASK indicates which bytes in the word are to be written or read.
Bytes to be read/written should have 0xff set in MASK. Otherwise
the byte should be zero.
 
ADDR, MASK, WDATA and the result from UPR all use host-endianess,
_not_ model-endianess. The internal Or1ksim routines manage all
the conversion.
 
 
-- `or1ksim.h': int or1ksim_run (double DURATION)
Run the simulator for the simulated duration specified (in
seconds).
462,9 → 535,32
 
 
-- `or1ksim.h': void or1ksim_interrupt (int I)
Generate an interrupt on interrupt line I.
Generate an edge-triggered interrupt on interrupt line I. The
interrupt is then immediately cleared automatically. A warning
will be generated and the interrupt request ignored if level
sensitive interrupts have been configured with the programmable
interrupt controller (*note Interrupt Configuration: Interrupt
Configuration.).
 
 
-- `or1ksim.h': void or1ksim_interrupt_set (int I)
Assert a level-triggered interrupt on interrupt line I. The
interrupt must be cleared separately by an explicit call to
`or1ksim_interrupt_clear'. A warning will be generated, and the
interrupt request ignored if edge sensitive interrupts have been
configured with the programmable interrupt controller (*note
Interrupt Configuration: Interrupt Configuration.).
 
 
-- `or1ksim.h': void or1ksim_interrupt_clear (int I)
Clear a level-triggered interrupt on interrupt line I, which was
previously asserted by a call to `or1ksim_interrupt_set'. A
warning will be generated, and the interrupt request ignored if
edge sensitive interrupts have been configured with the
programmable interrupt controller (*note Interrupt Configuration:
Interrupt Configuration.).
 
 
The libraries will be installed in the `lib' sub-directory of the main
installation directory (as specified with the `--prefix' option to the
`configure' script).
3114,11 → 3210,11
* --enable-execution: Configuring the Build.
(line 32)
* --enable-mprofile: Standalone Simulator.
(line 60)
(line 77)
* --enable-ov-flag: Configuring the Build.
(line 69)
* --enable-profile: Standalone Simulator.
(line 57)
(line 74)
* --enable-profiling: Configuring the Build.
(line 24)
* --enable-range-stats: Configuring the Build.
3144,6 → 3240,8
* --quiet: Profiling Utility. (line 30)
* --srv: Standalone Simulator.
(line 40)
* --strict-npc: Standalone Simulator.
(line 57)
* --version: Standalone Simulator.
(line 16)
* --version (memory profiling utility): Memory Profiling Utility.
3541,7 → 3639,7
(line 121)
* log_enabled (verification API configuration): Verification API Configuration.
(line 28)
* long: Simulator Library. (line 65)
* long: Simulator Library. (line 73)
* mc (memory configuration): Memory Configuration.
(line 99)
* memory configuration: Memory Configuration.
3598,13 → 3696,15
* nways (cache configuration): Cache Configuration. (line 22)
* nways (MMU configuration): Memory Management Configuration.
(line 22)
* or1ksim_get_time_period: Simulator Library. (line 55)
* or1ksim_get_time_period: Simulator Library. (line 63)
* or1ksim_init: Simulator Library. (line 18)
* or1ksim_interrupt: Simulator Library. (line 70)
* or1ksim_is_le: Simulator Library. (line 60)
* or1ksim_reset_duration: Simulator Library. (line 40)
* or1ksim_run: Simulator Library. (line 35)
* or1ksim_set_time_point: Simulator Library. (line 51)
* or1ksim_interrupt: Simulator Library. (line 78)
* or1ksim_interrupt_clear: Simulator Library. (line 96)
* or1ksim_interrupt_set: Simulator Library. (line 87)
* or1ksim_is_le: Simulator Library. (line 68)
* or1ksim_reset_duration: Simulator Library. (line 48)
* or1ksim_run: Simulator Library. (line 43)
* or1ksim_set_time_point: Simulator Library. (line 59)
* output rediretion: Concepts. (line 7)
* overflow flag setting by instructions: Configuring the Build.
(line 70)
3932,51 → 4032,52
Tag Table:
Node: Top808
Node: Installation1218
Node: Preparation1448
Node: Configuring the Build1741
Node: Build and Install6855
Node: Usage7523
Node: Standalone Simulator7737
Node: Profiling Utility9757
Node: Memory Profiling Utility10665
Node: Simulator Library12024
Node: Configuration15970
Node: Configuration File Format16576
Node: Configuration File Preprocessing16868
Node: Configuration File Syntax17238
Node: Simulator Configuration20016
Node: Simulator Behavior20307
Node: Verification API Configuration24323
Node: CUC Configuration26252
Node: Core OpenRISC Configuration28157
Node: CPU Configuration28659
Node: Memory Configuration32449
Node: Memory Management Configuration37725
Node: Cache Configuration40086
Node: Interrupt Configuration42452
Node: Power Management Configuration43184
Node: Branch Prediction Configuration44456
Node: Debug Interface Configuration45809
Node: Peripheral Configuration50009
Node: Memory Controller Configuration50634
Node: UART Configuration53231
Node: DMA Configuration56737
Node: Ethernet Configuration58592
Node: GPIO Configuration62548
Node: Display Interface Configuration64171
Node: Frame Buffer Configuration66471
Node: Keyboard Configuration68321
Node: Disc Interface Configuration70547
Node: Generic Peripheral Configuration75462
Node: Interactive Command Line77746
Node: Verification API84694
Node: Code Internals89112
Node: Coding Conventions89669
Node: Global Data Structures94084
Node: Concepts96736
Ref: Output Redirection96881
Node: Internal Debugging97418
Node: GNU Free Documentation License97914
Node: Index120321
Node: Preparation1465
Node: Configuring the Build1758
Node: Build and Install6872
Node: Known Issues7561
Node: Usage9694
Node: Standalone Simulator9908
Node: Profiling Utility12797
Node: Memory Profiling Utility13705
Node: Simulator Library15064
Node: Configuration20526
Node: Configuration File Format21132
Node: Configuration File Preprocessing21424
Node: Configuration File Syntax21794
Node: Simulator Configuration24572
Node: Simulator Behavior24863
Node: Verification API Configuration28879
Node: CUC Configuration30808
Node: Core OpenRISC Configuration32713
Node: CPU Configuration33215
Node: Memory Configuration37005
Node: Memory Management Configuration42281
Node: Cache Configuration44642
Node: Interrupt Configuration47008
Node: Power Management Configuration47740
Node: Branch Prediction Configuration49012
Node: Debug Interface Configuration50365
Node: Peripheral Configuration54565
Node: Memory Controller Configuration55190
Node: UART Configuration57787
Node: DMA Configuration61293
Node: Ethernet Configuration63148
Node: GPIO Configuration67104
Node: Display Interface Configuration68727
Node: Frame Buffer Configuration71027
Node: Keyboard Configuration72877
Node: Disc Interface Configuration75103
Node: Generic Peripheral Configuration80018
Node: Interactive Command Line82302
Node: Verification API89250
Node: Code Internals93668
Node: Coding Conventions94225
Node: Global Data Structures98640
Node: Concepts101292
Ref: Output Redirection101437
Node: Internal Debugging101974
Node: GNU Free Documentation License102470
Node: Index124877

End Tag Table
/trunk/or1ksim/doc/stamp-vti
1,4 → 1,4
@set UPDATED 11 November 2008
@set UPDATED-MONTH November 2008
@set EDITION 0.3.0rc2
@set VERSION 0.3.0rc2
@set UPDATED 24 February 2009
@set UPDATED-MONTH February 2009
@set EDITION 0.3.0rc3
@set VERSION 0.3.0rc3
/trunk/or1ksim/doc/or1ksim.texi
76,6 → 76,7
* Preparation::
* Configuring the Build::
* Build and Install::
* Known Issues::
@end menu
 
@node Preparation
117,7 → 118,7
@cindex @code{--enable-profiling}
@itemx --disable-profiling
@cindex @code{--disable-profiling}
If enabled, Or1ksim is compiled for profiling with
If enabled, @value{OR1KSIM} is compiled for profiling with
@command{gprof}. This is disabled by default. Only really of value for
developers of @value{OR1KSIM}.
 
129,7 → 130,7
@cindex complex model
@cindex dynamic model
@value{OR1KSIM} has developed to improve functionality and
performance. This feature allows three versions of Or1ksim to be built
performance. This feature allows three versions of @value{OR1KSIM} to be built
 
@table @code
 
262,7 → 263,7
header file, @file{or1ksim.h} and this documentation in @command{info} format.
 
@quotation Note
Testing Or1ksim with @kbd{make check} is not yet supported.
Testing @value{OR1KSIM} with @kbd{make check} is not yet supported.
@end quotation
 
The documentation may be created and installed in alternative formats (PDF,
273,6 → 274,56
@kbd{make install-pdf}
@end example
 
@node Known Issues
@section Known Problems and Issues
 
The following problems and issues are known about with @value{OR1KSIM}
@value{VERSION}. The OpenRISC tracker may be used to see the current
state of these issues and to raise new problems and feature requests. It
may be found at @url{http://www.opencores.org/ptracker.cgi/view/or1k/398}.
 
@itemize @bullet
@item
The Supervision Register Little Endian Enable (LEE) bit is
ignored. @value{OR1KSIM} can be built for either little endian or big endian
use, but that behavior cannot be changed dynamically.
 
@item
The NPC is a read/write register, but after being written it clears the
pipeline. This means that if the processor is stalled, the value should
subsequently read back as 0, until the processor is unstalled and able
to refill its pipeline. By default @value{OR1KSIM} always reports back the value
of NPC, even when it has been written while stalled.
 
There is now an option, @code{--strict-npc}, which will enforce this
behavior. At some stage in the future it will become the default
behavior, but for now it is an option, since its use will break GDB.
 
@item
The memory components are given names in the configuration file. However
there is currently no way for @value{OR1KSIM} to report that name back to the
user (for example to identify which memory block corresponds to a
particular access).
 
@item
@value{OR1KSIM} allows the processor to be stalled (from the command
line), even if there is no debugger present. This seems to be a
meaningless operation.
 
@item
@value{OR1KSIM} is not reentrant, so a program cannot instantiate
multiple instances using the library. This is clearly a problem when
considering multi-core applications. However it stems from the original
design, and can only be fixed by a complete rewrite. The entire source
code uses static global constants liberally!
 
@item
There is no support for floating point instructions currently in
@value{OR1KSIM}. However this is a work in progress and should be available in
the near future.
 
@end itemize
 
@node Usage
@chapter Usage
@cindex running @value{OR1KSIM}
355,6 → 406,23
After starting, drop into the @value{OR1KSIM} interactive command
shell.
 
@item --strict-npc
@cindex @code{--strict-npc}
In real hardware, setting the next program counter (NPC, SPR 16),
flushes the processor pipeline. The consequence of this is that until
the pipeline refills, reading the NPC will return zero. This is typically
the case when debugging, since the processor is stalled.
 
Historically, @value{OR1KSIM} has always returned the value of the NPC,
irrespective of when it is changed. If the @code{--strict-npc} option is
used, then @value{OR1KSIM} will mirror real hardware more accurately. If the NPC
is changed while the processor is stalled, subsequent reads of its value
will return 0 until the processor is unstalled.
 
This is not currently the default behavior, since tools such as GDB have
been implemented assuming the historic @value{OR1KSIM} behavior. However at some
time in the future it will become the default.
 
@item --enable-profile
@cindex @code{--enable-profile}
Enable instruction profiling.
524,6 → 592,14
function to associate the call with the class which originally
initialized the library.
 
@var{mask} indicates which bytes in the word are to be written or
read. Bytes to be read/written should have 0xff set in
@var{mask}. Otherwise the byte should be zero.
 
@var{addr}, @var{mask}, @var{wdata} and the result from @var{upr} all
use host-endianess, @emph{not} model-endianess. The internal
@value{OR1KSIM} routines manage all the conversion.
 
@end deftypefn
 
@deftypefn {@file{or1ksim.h}} int or1ksim_run (double @var{duration})
574,10 → 650,35
 
@deftypefn {@file{or1ksim.h}} void or1ksim_interrupt (int @var{i})
 
Generate an interrupt on interrupt line @var{i}.
Generate an edge-triggered interrupt on interrupt line @var{i}. The interrupt
is then immediately cleared automatically. A warning will be generated and the
interrupt request ignored if level sensitive interrupts have been configured
with the programmable interrupt controller (@pxref{Interrupt Configuration, ,
Interrupt Configuration}).
 
@end deftypefn
 
@deftypefn {@file{or1ksim.h}} void or1ksim_interrupt_set (int @var{i})
 
Assert a level-triggered interrupt on interrupt line @var{i}. The interrupt
must be cleared separately by an explicit call to
@code{or1ksim_interrupt_clear}. A warning will be generated, and the interrupt
request ignored if edge sensitive interrupts have been configured with the
programmable interrupt controller (@pxref{Interrupt Configuration, , Interrupt
Configuration}).
 
@end deftypefn
 
@deftypefn {@file{or1ksim.h}} void or1ksim_interrupt_clear (int @var{i})
 
Clear a level-triggered interrupt on interrupt line @var{i}, which was
previously asserted by a call to @code{or1ksim_interrupt_set}. A warning will
be generated, and the interrupt request ignored if edge sensitive interrupts
have been configured with the programmable interrupt controller
(@pxref{Interrupt Configuration, , Interrupt Configuration}).
 
@end deftypefn
 
The libraries will be installed in the @file{lib} sub-directory of the
main installation directory (as specified with the @option{--prefix}
option to the @command{configure} script).
1048,7 → 1149,7
@cindex processor configuration
@cindex @code{section cpu}
CPU configuration is described in @code{section cpu}. This section
should appear only once. At present Or1ksim does not model multi-CPU
should appear only once. At present @value{OR1KSIM} does not model multi-CPU
systems. The following parameters may be specified.
 
@table @code
/trunk/or1ksim/doc/version.texi
1,4 → 1,4
@set UPDATED 11 November 2008
@set UPDATED-MONTH November 2008
@set EDITION 0.3.0rc2
@set VERSION 0.3.0rc2
@set UPDATED 24 February 2009
@set UPDATED-MONTH February 2009
@set EDITION 0.3.0rc3
@set VERSION 0.3.0rc3
/trunk/or1ksim/or1ksim.h
71,6 → 71,10
 
void or1ksim_interrupt( int i );
 
void or1ksim_interrupt_set( int i );
 
void or1ksim_interrupt_clear( int i );
 
#ifdef __cplusplus
}
#endif
/trunk/or1ksim/testbench/support/spr-defs.h
478,7 → 478,7
#define SPR_DSR_IME 0x00000200 /* ITLB miss exception */
#define SPR_DSR_RE 0x00000400 /* Range exception */
#define SPR_DSR_SCE 0x00000800 /* System call exception */
#define SPR_DSR_SSE 0x00001000 /* Single Step Exception */
#define SPR_DSR_FPE 0x00001000 /* Floating Point Exception */
#define SPR_DSR_TE 0x00002000 /* Trap exception */
 
/*
497,7 → 497,8
#define SPR_DRR_IME 0x00000200 /* ITLB miss exception */
#define SPR_DRR_RE 0x00000400 /* Range exception */
#define SPR_DRR_SCE 0x00000800 /* System call exception */
#define SPR_DRR_TE 0x00001000 /* Trap exception */
#define SPR_DRR_FPE 0x00001000 /* Floating Point Exception */
#define SPR_DRR_TE 0x00002000 /* Trap exception */
 
/*
* Bit definitions for Performance counters mode registers
/trunk/or1ksim/peripheral/channels/fd.c
106,15 → 106,27
return -1;
}
 
FD_ZERO (&rfds);
FD_SET (fds->fdin, &rfds);
/* Loop, to allow for select being interrupted */
do
{
FD_ZERO (&rfds);
FD_SET (fds->fdin, &rfds);
 
retval = select (fds->fdin + 1, &rfds, NULL, NULL, &timeout);
retval = select (fds->fdin + 1, &rfds, NULL, NULL, &timeout);
}
while ((retval < 0) && (EINTR == errno));
 
if (retval <= 0)
return retval;
 
return read (fds->fdin, buffer, size);
/* Loop, to allow for select being interrupted */
do
{
retval = read (fds->fdin, buffer, size);
}
while ((retval < 0) && (EINTR == errno));
 
return retval;
}
 
int
/trunk/or1ksim/peripheral/generic.c
22,9 → 22,14
/* This program is commented throughout in a fashion suitable for processing
with Doxygen. */
 
 
/* This is functional simulation of any external peripheral. It's job is to
* trap accesses in a specific range, so that the simulator can drive an
* external device.
*
* A note on endianess. All external communication is done using HOST
* endianess. A set of functions are provided to convert between host and
* model endianess (htoml, htoms, mtohl, mtohs).
*/
 
/* Autoconf and/or portability configuration */
76,11 → 81,99
};
 
 
/* Convert a 32-bit value from host to model endianess */
static unsigned long int
htoml (unsigned long int host_val)
{
unsigned char model_array[4];
 
#ifdef OR32_BIG_ENDIAN
model_array[0] = (host_val >> 24) & 0xff;
model_array[1] = (host_val >> 16) & 0xff;
model_array[2] = (host_val >> 8) & 0xff;
model_array[3] = (host_val ) & 0xff;
#else
model_array[0] = (host_val ) & 0xff;
model_array[1] = (host_val >> 8) & 0xff;
model_array[2] = (host_val >> 16) & 0xff;
model_array[3] = (host_val >> 24) & 0xff;
#endif
 
return *((unsigned long int *)model_array);
 
} /* htoml () */
 
 
/* Convert a 16-bit value from host to model endianess */
static unsigned short int
htoms (unsigned short int host_val)
{
unsigned char model_array[2];
 
#ifdef OR32_BIG_ENDIAN
model_array[0] = (host_val >> 8) & 0xff;
model_array[1] = (host_val ) & 0xff;
#else
model_array[0] = (host_val ) & 0xff;
model_array[1] = (host_val >> 8) & 0xff;
#endif
 
return *((unsigned short int *)model_array);
 
} /* htoms () */
 
 
/* Convert a 32-bit value from model to host endianess */
static unsigned long int
mtohl (unsigned long int model_val)
{
unsigned char *model_array = (unsigned char *)(&model_val);
unsigned long int host_val;
 
#ifdef OR32_BIG_ENDIAN
host_val = model_array[0];
host_val = (host_val << 8) | model_array[1];
host_val = (host_val << 8) | model_array[2];
host_val = (host_val << 8) | model_array[3];
#else
host_val = model_array[3];
host_val = (host_val << 8) | model_array[2];
host_val = (host_val << 8) | model_array[1];
host_val = (host_val << 8) | model_array[0];
#endif
 
return host_val;
 
} /* mtohl () */
 
 
/* Convert a 32-bit value from model to host endianess */
static unsigned short int
mtohs (unsigned short int model_val)
{
unsigned char *model_array = (unsigned char *)(&model_val);
unsigned short int host_val;
 
#ifdef OR32_BIG_ENDIAN
host_val = model_array[0];
host_val = (host_val << 8) | model_array[1];
#else
host_val = model_array[1];
host_val = (host_val << 8) | model_array[0];
#endif
 
return host_val;
 
} /* mtohs () */
 
 
/* Generic read and write upcall routines. Note the address here is absolute,
not relative to the device. */
not relative to the device. The mask uses host endianess, not Or1ksim
endianess. */
 
static unsigned long int
ext_read (unsigned long int addr, unsigned long int mask)
ext_read (unsigned long int addr,
unsigned long int mask)
{
return config.ext.read_up (config.ext.class_ptr, addr, mask);
 
88,11 → 181,13
 
 
/* Generic read and write upcall routines. Note the address here is absolute,
not relative to the device. */
not relative to the device. The mask and value use host endianess, not
Or1ksim endianess. */
 
static void
ext_write (unsigned long int addr,
unsigned long int mask, unsigned long int value)
ext_write (unsigned long int addr,
unsigned long int mask,
unsigned long int value)
{
config.ext.write_up (config.ext.class_ptr, addr, mask, value);
 
119,21 → 214,22
}
else
{
unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
unsigned long wordaddr = fulladdr & 0xfffffffc;
unsigned long bitoff = (fulladdr & 0x00000003) << 3;
unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
unsigned long wordaddr = fulladdr & 0xfffffffc;
unsigned long bytenum = fulladdr & 0x00000003;
 
#ifdef OR32_BIG_ENDIAN
unsigned long mask = 0x000000ff << (24 - bitoff);
unsigned long res = ext_read (wordaddr, mask);
uint8_t mask_array[4];
unsigned long res;
uint8_t *res_array;
 
return (uint8_t) ((res >> (24 - bitoff)) & 0x000000ff);
#else
unsigned long mask = 0x000000ff << bitoff;
unsigned long res = ext_read (wordaddr, mask);
/* This works whatever the host endianess */
memset (mask_array, 0, 4);
mask_array[bytenum] = 0xff;
 
return (uint8_t) ((res >> bitoff) & 0x00000ff);
#endif
res = ext_read (wordaddr, *((unsigned int *)mask_array));
res_array = (uint8_t *)(&res);
 
return res_array[bytenum];
}
} /* generic_read_byte() */
 
154,23 → 250,26
}
else
{
unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
unsigned long wordaddr = fulladdr & 0xfffffffc;
unsigned long bitoff = (fulladdr & 0x00000003) << 3;
unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
unsigned long wordaddr = fulladdr & 0xfffffffc;
 
#ifdef OR32_BIG_ENDIAN
unsigned long mask = 0x000000ff << (24 - bitoff);
unsigned long wordval = ((unsigned long int) value) << (24 - bitoff);
#else
unsigned long mask = 0x000000ff << bitoff;
unsigned long wordval = ((unsigned long int) value) << bitoff;
#endif
unsigned long bytenum = fulladdr & 0x00000003;
uint8_t mask_array[4];
uint8_t value_array[4];
 
ext_write (wordaddr, mask, wordval);
/* This works whatever the host endianess */
memset (mask_array, 0, 4);
mask_array[bytenum] = 0xff;
memset (value_array, 0, 4);
value_array[bytenum] = value;
 
ext_write (wordaddr, *((unsigned long int *)mask_array),
*((unsigned long int *)value_array));
}
} /* generic_write_byte() */
 
 
/* Result is in model endianess */
static uint16_t
generic_read_hw (oraddr_t addr, void *dat)
{
196,25 → 295,32
}
else
{
unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
unsigned long wordaddr = fulladdr & 0xfffffffc;
unsigned long bitoff = (fulladdr & 0x00000003) << 3;
unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
unsigned long wordaddr = fulladdr & 0xfffffffc;
unsigned long bytenum = fulladdr & 0x00000002;
 
#ifdef OR32_BIG_ENDIAN
unsigned long mask = 0x0000ffff << (16 - bitoff);
unsigned long res = ext_read (wordaddr, mask);
uint8_t mask_array[4];
unsigned long res;
uint8_t *res_array;
uint8_t hwres_array[2];
 
return (uint16_t) ((res >> (16 - bitoff)) & 0x0000ffff);
#else
unsigned long mask = 0x0000ffff << bitoff;
unsigned long res = ext_read (wordaddr, mask);
/* This works whatever the host endianess */
memset (mask_array, 0, 4);
mask_array[bytenum] = 0xff;
mask_array[bytenum + 1] = 0xff;
 
return (uint16_t) ((res >> bitoff) & 0x0000ffff);
#endif
res = ext_read (wordaddr, *((unsigned int *)mask_array));
res_array = (uint8_t *)(&res);
 
hwres_array[0] = res_array[bytenum];
hwres_array[1] = res_array[bytenum + 1];
 
return htoms (*((uint16_t *)hwres_array));
}
} /* generic_read_hw() */
 
 
/* Value is in model endianness */
static void
generic_write_hw (oraddr_t addr, uint16_t value, void *dat)
{
236,19 → 342,28
}
else
{
unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
unsigned long wordaddr = fulladdr & 0xfffffffc;
unsigned long bitoff = (fulladdr & 0x00000003) << 3;
uint16_t host_value = mtohs (value);
 
#ifdef OR32_BIG_ENDIAN
unsigned long mask = 0x0000ffff << (16 - bitoff);
unsigned long wordval = ((unsigned long int) value) << (16 - bitoff);
#else
unsigned long mask = 0x0000ffff << bitoff;
unsigned long wordval = ((unsigned long int) value) << bitoff;
#endif
unsigned long fulladdr = (unsigned long int) (addr + dev->baseaddr);
unsigned long wordaddr = fulladdr & 0xfffffffc;
unsigned long bytenum = fulladdr & 0x00000002;
 
ext_write (wordaddr, mask, wordval);
uint8_t mask_array[4];
uint8_t value_array[4];
uint8_t *hw_value_array;
 
/* This works whatever the host endianess */
memset (mask_array, 0, 4);
mask_array[bytenum] = 0xff;
mask_array[bytenum + 1] = 0xff;
 
memset (value_array, 0, 4);
hw_value_array = (uint8_t *)(&host_value);
value_array[bytenum] = hw_value_array[0];
value_array[bytenum + 1] = hw_value_array[1];
 
ext_write (wordaddr, *((unsigned long int *)mask_array),
*((unsigned long int *)value_array));
}
} /* generic_write_hw() */
 
280,7 → 395,7
{
unsigned long wordaddr = (unsigned long int) (addr + dev->baseaddr);
 
return (uint32_t) ext_read (wordaddr, 0xffffffff);
return (uint32_t) htoml (ext_read (wordaddr, 0xffffffff));
}
} /* generic_read_word() */
 
306,9 → 421,10
}
else
{
unsigned long wordaddr = (unsigned long int) (addr + dev->baseaddr);
unsigned long host_value = mtohl (value);
unsigned long wordaddr = (unsigned long int) (addr + dev->baseaddr);
 
ext_write (wordaddr, 0xffffffff, value);
ext_write (wordaddr, 0xffffffff, host_value);
}
} /* generic_write_word() */
 
/trunk/or1ksim/sim-config.c
239,6 → 239,9
runtime.sim.fmprof = NULL;
runtime.sim.fout = stdout;
 
/* NPC state. Set to 1 when NPC is changed while the processor is stalled. */
cpu_state.npc_not_valid = 0;
 
/* VAPI */
runtime.vapi.vapi_file = NULL;
runtime.vapi.enabled = 0;
266,12 → 269,13
struct arg_int *srv;
struct arg_str *dbg;
struct arg_lit *command;
struct arg_lit *strict_npc;
struct arg_lit *profile;
struct arg_lit *mprofile;
struct arg_file *load_file;
struct arg_end *end;
 
void *argtab[11];
void *argtab[12];
int nerrors;
 
/* Specify each argument, with fall back values */
286,6 → 290,7
srv->hdr.flag |= ARG_HASOPTVALUE;
dbg = arg_str0 ("d", "debug-config", "<str>", "Debug config string");
command = arg_lit0 ("i", "interactive", "launch interactive prompt");
strict_npc = arg_lit0 (NULL, "strict-npc", "setting NPC flushes pipeline");
profile = arg_lit0 (NULL, "enable-profile", "enable profiling");
mprofile = arg_lit0 (NULL, "enable-mprofile", "enable memory profiling");
load_file = arg_file0 (NULL, NULL, "<file>", "OR32 executable");
292,16 → 297,18
end = arg_end (20);
 
/* Set up the argument table */
argtab[0] = vercop;
argtab[1] = help;
argtab[2] = cfg_file;
argtab[3] = nosrv;
argtab[4] = srv;
argtab[5] = dbg, argtab[6] = command;
argtab[7] = profile;
argtab[8] = mprofile;
argtab[9] = load_file;
argtab[10] = end;
argtab[ 0] = vercop;
argtab[ 1] = help;
argtab[ 2] = cfg_file;
argtab[ 3] = nosrv;
argtab[ 4] = srv;
argtab[ 5] = dbg;
argtab[ 6] = command;
argtab[ 7] = strict_npc;
argtab[ 8] = profile;
argtab[ 9] = mprofile;
argtab[10] = load_file;
argtab[11] = end;
 
/* Parse */
nerrors = arg_parse (argc, argv, argtab);
380,6 → 387,9
/* Interactive operation */
runtime.sim.iprompt = command->count;
 
/* Request for strict NPC behavior (flush the pipeline on change) */
config.sim.strict_npc = strict_npc->count;
 
/* Profiling requests */
config.sim.profile = profile->count;
config.sim.mprofile = mprofile->count;

powered by: WebSVN 2.1.0

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