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", ®num)) |
if (1 != sscanf (buf->data, "p%x", ®num)) |
{ |
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; |