/* toplevel.c -- Top level simulator source file
|
/* toplevel.c -- Top level simulator source file
|
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
|
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
|
|
|
This file is part of OpenRISC 1000 Architectural Simulator.
|
This file is part of OpenRISC 1000 Architectural Simulator.
|
|
|
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation; either version 2 of the License, or
|
(at your option) any later version.
|
(at your option) any later version.
|
|
|
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
GNU General Public License for more details.
|
GNU General Public License for more details.
|
|
|
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|
|
/* Simulator commands. Help and version output. SIGINT processing.
|
/* Simulator commands. Help and version output. SIGINT processing.
|
Stdout redirection is specific to linux (I need to fix this). */
|
Stdout redirection is specific to linux (I need to fix this). */
|
|
|
#include "config.h"
|
#include "config.h"
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <ctype.h>
|
#include <ctype.h>
|
#include <string.h>
|
#include <string.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <unistd.h>
|
#include <unistd.h>
|
#include <signal.h>
|
#include <signal.h>
|
#include <stdarg.h>
|
#include <stdarg.h>
|
/* Added by CZ 24/05/01 */
|
/* Added by CZ 24/05/01 */
|
#include <sys/stat.h>
|
#include <sys/stat.h>
|
#include <sys/types.h>
|
#include <sys/types.h>
|
#include <sys/socket.h>
|
#include <sys/socket.h>
|
#include <netinet/in.h>
|
#include <netinet/in.h>
|
#include <sys/select.h>
|
#include <sys/select.h>
|
#include <sys/poll.h>
|
#include <sys/poll.h>
|
#include <fcntl.h>
|
#include <fcntl.h>
|
#include <netdb.h>
|
#include <netdb.h>
|
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
#include <inttypes.h>
|
#include <inttypes.h>
|
|
|
#ifdef HAVE_LIBREADLINE
|
#ifdef HAVE_LIBREADLINE
|
#include <readline/readline.h>
|
#include <readline/readline.h>
|
#include <readline/history.h>
|
#include <readline/history.h>
|
#endif /* HAVE_LIBREADLINE */
|
#endif /* HAVE_LIBREADLINE */
|
|
|
#include "arch.h"
|
#include "arch.h"
|
#include "parse.h"
|
#include "parse.h"
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "labels.h"
|
#include "labels.h"
|
#include "trace.h"
|
#include "trace.h"
|
#include "execute.h"
|
#include "execute.h"
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "spr_defs.h"
|
#include "spr_defs.h"
|
#include "dma.h"
|
#include "dma.h"
|
|
|
#include "coff.h"
|
#include "coff.h"
|
|
|
/* Added by CZ 24/05/01 */
|
/* Added by CZ 24/05/01 */
|
#include "gdb.h"
|
#include "gdb.h"
|
#include <signal.h>
|
#include <signal.h>
|
#include <errno.h>
|
#include <errno.h>
|
typedef enum {
|
typedef enum {
|
false = 0,
|
false = 0,
|
true = 1,
|
true = 1,
|
} Boolean;
|
} Boolean;
|
unsigned int serverIP = 0;
|
unsigned int serverIP = 0;
|
unsigned int serverPort = 0;
|
unsigned int serverPort = 0;
|
unsigned int server_fd = 0;
|
unsigned int server_fd = 0;
|
unsigned int gdb_fd = 0;
|
unsigned int gdb_fd = 0;
|
void HandleServerSocket(Boolean);
|
void HandleServerSocket(Boolean);
|
void JTAGRequest(void);
|
void JTAGRequest(void);
|
void GDBRequest(void);
|
void GDBRequest(void);
|
void ProtocolClean(int,int32_t);
|
void ProtocolClean(int,int32_t);
|
static int gdb_read(void*,int);
|
static int gdb_read(void*,int);
|
static int gdb_write(void*,int);
|
static int gdb_write(void*,int);
|
void BlockJTAG(void);
|
void BlockJTAG(void);
|
|
|
/* CVS revision number. */
|
/* CVS revision number. */
|
const char rcsrev[] = "$Revision: 1.31 $";
|
const char rcsrev[] = "$Revision: 1.32 $";
|
|
|
/* Continuos run versus single step tracing switch. */
|
/* Continuos run versus single step tracing switch. */
|
int cont_run;
|
int cont_run;
|
|
|
/* History of execution */
|
/* History of execution */
|
int histexec[HISTEXEC_LEN];
|
int histexec[HISTEXEC_LEN];
|
|
|
char *sim_commands [] = {
|
char *sim_commands [] = {
|
"q",
|
"q",
|
"t",
|
"t",
|
"help",
|
"help",
|
"de",
|
"de",
|
"dm",
|
"dm",
|
"run",
|
"run",
|
"pr",
|
"pr",
|
"pm",
|
"pm",
|
"pc",
|
"pc",
|
"reset",
|
"reset",
|
"break",
|
"break",
|
"hist",
|
"hist",
|
"stats",
|
"stats",
|
"stall"
|
"stall"
|
"info",
|
"info",
|
"r",
|
"r",
|
"dv",
|
"dv",
|
0
|
0
|
};
|
};
|
|
|
inline void debug(const char *format, ...)
|
inline void debug(const char *format, ...)
|
{
|
{
|
#ifndef DEBUGMOD_OFF
|
#ifndef DEBUGMOD_OFF
|
char *p;
|
char *p;
|
va_list ap;
|
va_list ap;
|
|
|
if (config.simdebug) {
|
if (config.simdebug) {
|
if ((p = malloc(1000)) == NULL)
|
if ((p = malloc(1000)) == NULL)
|
return;
|
return;
|
va_start(ap, format);
|
va_start(ap, format);
|
(void) vsnprintf(p, 1000, format, ap);
|
(void) vsnprintf(p, 1000, format, ap);
|
va_end(ap);
|
va_end(ap);
|
printf("%s\n", p);
|
printf("%s\n", p);
|
fflush(stdout);
|
fflush(stdout);
|
free(p);
|
free(p);
|
} else {
|
} else {
|
#if DEBUG
|
#if DEBUG
|
if ((p = malloc(1000)) == NULL)
|
if ((p = malloc(1000)) == NULL)
|
return;
|
return;
|
va_start(ap, format);
|
va_start(ap, format);
|
(void) vsnprintf(p, 1000, format, ap);
|
(void) vsnprintf(p, 1000, format, ap);
|
va_end(ap);
|
va_end(ap);
|
printf("%s\n", p);
|
printf("%s\n", p);
|
fflush(stdout);
|
fflush(stdout);
|
free(p);
|
free(p);
|
#endif
|
#endif
|
}
|
}
|
#endif /* no DEBUGMOD_OFF */
|
#endif /* no DEBUGMOD_OFF */
|
}
|
}
|
|
|
/* Strip whitespace from the start and end of STRING. Return a pointer
|
/* Strip whitespace from the start and end of STRING. Return a pointer
|
into STRING. */
|
into STRING. */
|
#ifndef whitespace
|
#ifndef whitespace
|
#define whitespace(a) ((a) == '\t' ? 1 : ((a) == ' '? 1 : 0))
|
#define whitespace(a) ((a) == '\t' ? 1 : ((a) == ' '? 1 : 0))
|
#endif
|
#endif
|
|
|
char *
|
char *
|
stripwhite (string)
|
stripwhite (string)
|
char *string;
|
char *string;
|
{
|
{
|
register char *s, *t;
|
register char *s, *t;
|
|
|
for (s = string; whitespace (*s); s++)
|
for (s = string; whitespace (*s); s++)
|
;
|
;
|
|
|
if (*s == 0)
|
if (*s == 0)
|
return (s);
|
return (s);
|
|
|
t = s + strlen (s) - 1;
|
t = s + strlen (s) - 1;
|
while (t > s && whitespace (*t))
|
while (t > s && whitespace (*t))
|
t--;
|
t--;
|
*++t = '\0';
|
*++t = '\0';
|
|
|
return s;
|
return s;
|
}
|
}
|
|
|
void
|
void
|
ctrl_c(signum)
|
ctrl_c(signum)
|
int signum;
|
int signum;
|
{
|
{
|
extern int cpu_stalled; /* CZ from debug_interface */
|
extern int cpu_stalled; /* CZ from debug_interface */
|
cont_run = cpu_stalled ? 0 : 1;
|
cont_run = cpu_stalled ? 0 : 1;
|
config.iprompt = 1;
|
config.iprompt = 1;
|
cpu_stalled = 0;
|
cpu_stalled = 0;
|
signal(SIGINT, ctrl_c);
|
signal(SIGINT, ctrl_c);
|
}
|
}
|
|
|
void
|
void
|
version()
|
version()
|
{
|
{
|
printf ("\n");
|
printf ("\n");
|
printf ("OpenRISC 1000 (OR16+OR32) Architectural Simulator, %s\n", rcsrev);
|
printf ("OpenRISC 1000 (OR16+OR32) Architectural Simulator, %s\n", rcsrev);
|
printf ("Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n");
|
printf ("Copyright (C) 1999 Damjan Lampret, lampret@opencores.org\n");
|
printf ("Copyright (C) 2000 Damjan Lampret, lampret@opencores.org\n");
|
printf ("Copyright (C) 2000 Damjan Lampret, lampret@opencores.org\n");
|
printf (" Jimmy Chen-Min Chen, jimmy@ee.nctu.edu.tw\n");
|
printf (" Jimmy Chen-Min Chen, jimmy@ee.nctu.edu.tw\n");
|
printf (" Johan Rydberg, johan.rydberg@insight.se\n");
|
printf (" Johan Rydberg, johan.rydberg@insight.se\n");
|
printf ("Visit http://www.opencores.org for more information about ");
|
printf ("Visit http://www.opencores.org for more information about ");
|
printf ("OpenRISC 1000 and\nother open source cores.\n\n");
|
printf ("OpenRISC 1000 and\nother open source cores.\n\n");
|
printf ("This software comes with ABSOLUTELY NO WARRANTY; for ");
|
printf ("This software comes with ABSOLUTELY NO WARRANTY; for ");
|
printf ("details see COPYING.\nThis is free software, and you ");
|
printf ("details see COPYING.\nThis is free software, and you ");
|
printf ("are welcome to redistribute it under certain\nconditions; ");
|
printf ("are welcome to redistribute it under certain\nconditions; ");
|
printf ("for details see COPYING.\n");
|
printf ("for details see COPYING.\n");
|
}
|
}
|
|
|
void
|
void
|
help()
|
help()
|
{
|
{
|
printf("q - quit simulator\n");
|
printf("q - quit simulator\n");
|
printf("r - display all registers\n");
|
printf("r - display all registers\n");
|
printf("t - execute next instruction\n");
|
printf("t - execute next instruction\n");
|
printf("run <cycles> [<hush>] - execute <cycles> instructions, no reg dump if hush\n");
|
printf("run <cycles> [<hush>] - execute <cycles> instructions, no reg dump if hush\n");
|
printf("pr <r> <value> - patch register <r> with <value>\n");
|
printf("pr <r> <value> - patch register <r> with <value>\n");
|
printf("dm <fromaddr> [<toaddr>] - display memory from <fromaddr> to <toaddr>\n");
|
printf("dm <fromaddr> [<toaddr>] - display memory from <fromaddr> to <toaddr>\n");
|
printf("de <fromaddr> [<toaddr>] - debug insn memory\n");
|
printf("de <fromaddr> [<toaddr>] - debug insn memory\n");
|
printf("pm <addr> <value> - patch memory location <addr> with <value>\n");
|
printf("pm <addr> <value> - patch memory location <addr> with <value>\n");
|
printf("pc <value> - patch PC register with <value>\n");
|
printf("pc <value> - patch PC register with <value>\n");
|
printf("break <addr> - toggle breakpoint at address <addr>\n");
|
printf("break <addr> - toggle breakpoint at address <addr>\n");
|
printf("reset - simulator reset\n");
|
printf("reset - simulator reset\n");
|
printf("hist - execution history\n");
|
printf("hist - execution history\n");
|
printf("stall - stalls the processor and gives control to the debugger\n");
|
printf("stall - stalls the processor and gives control to the debugger\n");
|
printf("stats <num|clear> - execution statistics num or clear it.\n");
|
printf("stats <num|clear> - execution statistics num or clear it.\n");
|
printf("info - configuration info (caches etc.)\n");
|
printf("info - configuration info (caches etc.)\n");
|
printf("dv <fromaddr> [<toaddr>] [<modname>] - dumps memory as verilog (use redirect)\n");
|
printf("dv <fromaddr> [<toaddr>] [<modname>] - dumps memory as verilog (use redirect)\n");
|
printf("dh <fromaddr> [<toaddr>] - dumps memory as hex code (use redirect)\n");
|
printf("dh <fromaddr> [<toaddr>] - dumps memory as hex code (use redirect)\n");
|
printf("<cmd> > <filename> - redirect simulator stdout to <filename> (and not emulated printf)\n");
|
printf("<cmd> > <filename> - redirect simulator stdout to <filename> (and not emulated printf)\n");
|
printf("debug - toggles simulator debug mode\n");
|
printf("debug - toggles simulator debug mode\n");
|
printf("help - available commands (this list)\n");
|
printf("help - available commands (this list)\n");
|
}
|
}
|
|
|
void debugmem( unsigned long from, unsigned long to );
|
void debugmem( unsigned long from, unsigned long to );
|
|
|
main(argc, argv)
|
main(argc, argv)
|
int argc;
|
int argc;
|
char *argv[];
|
char *argv[];
|
{
|
{
|
char *linestr;
|
char *linestr;
|
char item1[500], b2[500], prev_str[500] = "";
|
char item1[500], b2[500], prev_str[500] = "";
|
char *redirstr;
|
char *redirstr;
|
int hush = 0;
|
int hush = 0;
|
unsigned long endaddr = 0xFFFFFFFF;
|
unsigned long endaddr = 0xFFFFFFFF;
|
int first_prompt = 1;
|
int first_prompt = 1;
|
int trace_fd = 0;
|
int trace_fd = 0;
|
|
|
srand(getpid());
|
srand(getpid());
|
init_defconfig();
|
init_defconfig();
|
if (parse_args(argc, argv)) {
|
if (parse_args(argc, argv)) {
|
printf("Usage: %s [options] <filename>\n", argv[0]);
|
printf("Usage: %s [options] <filename>\n", argv[0]);
|
printf("Options:\n");
|
printf("Options:\n");
|
printf(" -v: version and copyright note\n");
|
printf(" -v: version and copyright note\n");
|
printf(" -i: enable interactive command prompt\n");
|
printf(" -i: enable interactive command prompt\n");
|
printf(" -bpb: disable branch prediction buffer analysis\n");
|
printf(" -bpb: disable branch prediction buffer analysis\n");
|
printf(" -btic: disable branch prediction target insn cache analysis\n");
|
printf(" -btic: disable branch prediction target insn cache analysis\n");
|
printf(" -hazards: disable dependency hazards analysis\n");
|
printf(" -hazards: disable dependency hazards analysis\n");
|
printf(" -history: disable instruction stream history analysis\n");
|
printf(" -history: disable instruction stream history analysis\n");
|
printf(" -superscalar: disable superscalar analysis\n");
|
printf(" -superscalar: disable superscalar analysis\n");
|
printf(" -fast: disable BPB, BTIC, SLP, dependency hazards, history"
|
printf(" -fast: disable BPB, BTIC, SLP, dependency hazards, history"
|
" analysis etc.\n");
|
" analysis etc.\n");
|
printf(" -profile: generates profiling data.\n"); /* MM */
|
printf(" -profile: generates profiling data.\n"); /* MM */
|
printf(" -upr <n>: set UPR to n\n");
|
printf(" -upr <n>: set UPR to n\n");
|
printf(" -ver <n>: set VR[VER] to n\n");
|
printf(" -ver <n>: set VR[VER] to n\n");
|
printf(" -rev <n>: set VR[REV] to n\n");
|
printf(" -rev <n>: set VR[REV] to n\n");
|
printf(" -loadmem[@<n>] <filename>: load memory with file, "
|
|
"optionally at address <n>\n"); /* (CZ) */
|
|
printf(" -nosrv: do not launch JTAG proxy server\n"); /* (CZ) */
|
printf(" -nosrv: do not launch JTAG proxy server\n"); /* (CZ) */
|
printf(" -srv <n>: launch JTAG proxy server on port <n>\n"); /* (CZ) */
|
printf(" -srv <n>: launch JTAG proxy server on port <n>\n"); /* (CZ) */
|
printf(" -initmem <n | random>: initialize memory to value "
|
|
"<n> or random\n"); /* (CZ) */
|
|
exit(-1);
|
exit(-1);
|
}
|
}
|
|
|
#ifdef HAVE_LIBREADLINE
|
#ifdef HAVE_LIBREADLINE
|
initialize_readline (); /* Bind our completer. */
|
initialize_readline (); /* Bind our completer. */
|
#endif
|
#endif
|
|
|
if(!config.inhibit_server)
|
if(!config.inhibit_server)
|
{
|
{
|
serverPort = config.server_port;
|
serverPort = config.server_port;
|
if(server_fd = GetServerSocket("or1ksim","tcp",serverPort))
|
if(server_fd = GetServerSocket("or1ksim","tcp",serverPort))
|
printf("JTAG Proxy server started on port %d\n",serverPort);
|
printf("JTAG Proxy server started on port %d\n",serverPort);
|
}
|
}
|
|
|
if(config.profile) {
|
if(config.profile) {
|
config.fprof = fopen("sim-profile","wt+");
|
config.fprof = fopen("sim-profile","wt+");
|
if(!config.fprof) {
|
if(!config.fprof) {
|
config.profile = 0;
|
config.profile = 0;
|
printf("Problems opening profile file. Profiling disabled. \n");
|
printf("Problems opening profile file. Profiling disabled. \n");
|
} else
|
} else
|
fprintf(config.fprof, "+00000000 FFFFFFFF FFFFFFFF main\n");
|
fprintf(config.fprof, "+00000000 FFFFFFFF FFFFFFFF main\n");
|
}
|
}
|
|
|
/* Read configuration file. */
|
/* Read configuration file. */
|
read_script_file("sim.cfg");
|
read_script_file("sim.cfg");
|
init_labels();
|
init_labels();
|
init_breakpoints();
|
init_breakpoints();
|
print_config();
|
print_config();
|
signal(SIGINT, ctrl_c);
|
signal(SIGINT, ctrl_c);
|
initstats();
|
initstats();
|
build_automata();
|
build_automata();
|
|
|
/* Modified by CZ on 24/05/01 ... if a filename is
|
/* Initialize memory */
|
specified, behave as the simulator always has. This way,
|
{
|
no existing test suites should be broken. If a filename
|
|
is not specified, default to the new style behavior. Let
|
|
the simulator start up and execute garbage, the same way
|
|
a real CPU would. This should maximize the reality of
|
|
the capabilities. In this mode, we will expect that
|
|
someone will attach to us over the JTAG Proxy interface
|
|
and begin debugging that way. */
|
|
|
|
if(config.filename) {
|
|
endaddr = loadcode(config.filename, 0, 0); /* MM170901 always load at address zero. */
|
|
if (endaddr == -1) {
|
|
printf("Problems loading boot code.\n");
|
|
exit(1);
|
|
}
|
|
} else {
|
|
extern struct dev_memarea *dev_list;
|
extern struct dev_memarea *dev_list;
|
int i;
|
int i;
|
if(config.random_mem) {
|
if(config.memory.type == MT_RANDOM) {
|
unsigned int val = 0;
|
unsigned int val = 0;
|
int seed = time(NULL);
|
|
int breakpoint = 0;
|
|
|
|
srandom(seed);
|
if (config.memory.random_seed == -1) {
|
|
config.memory.random_seed = time(NULL);
|
/* Print out the seed just in case we ever need to debug */
|
/* Print out the seed just in case we ever need to debug */
|
printf("Seeding random generator with value %d\n",seed);
|
printf("Seeding random generator with value %d\n", config.memory.random_seed);
|
|
}
|
|
srandom(config.memory.random_seed);
|
|
|
for (cur_area = dev_list; cur_area; cur_area = cur_area->next)
|
for (cur_area = dev_list; cur_area; cur_area = cur_area->next)
|
for(i = 0; i < cur_area->size; i++) {
|
for(i = 0; i < cur_area->size; i++) {
|
val = random();
|
val = random();
|
if(random() > RAND_MAX/2)
|
setsim_mem8(i + cur_area->addr_compare, val & 0xFF);
|
val |= 0x80000000;
|
|
set_mem8(i + cur_area->addr_compare, val, &breakpoint);
|
|
}
|
}
|
} else if(config.pattern_mem) {
|
} else if(config.memory.type == MT_PATTERN) {
|
int breakpoint = 0;
|
|
for (cur_area = dev_list; cur_area; cur_area = cur_area->next)
|
for (cur_area = dev_list; cur_area; cur_area = cur_area->next)
|
for(i = 0; i < cur_area->size; i++)
|
for(i = 0; i < cur_area->size; i++)
|
set_mem8(i + cur_area->addr_compare, config.pattern_mem, &breakpoint);
|
setsim_mem8(i + cur_area->addr_compare, config.memory.pattern);
|
} else {
|
} else {
|
int breakpoint = 0;
|
fprintf(stderr, "Invalid memory configuration type.\n");
|
for (cur_area = dev_list; cur_area; cur_area = cur_area->next)
|
exit(1);
|
for(i = 0; i < cur_area->size; i++)
|
}
|
set_mem8(i + cur_area->addr_compare, 0, &breakpoint);
|
}
|
|
|
|
if(config.filename) {
|
|
endaddr = loadcode(config.filename, 0, 0); /* MM170901 always load at address zero. */
|
|
if (endaddr == -1) {
|
|
fprintf(stderr, "Problems loading boot code.\n");
|
|
exit(1);
|
}
|
}
|
}
|
}
|
|
|
uart_reset();
|
uart_reset();
|
dma_reset();
|
dma_reset();
|
eth_reset();
|
eth_reset();
|
tick_reset();
|
tick_reset();
|
pm_reset();
|
pm_reset();
|
pic_reset();
|
pic_reset();
|
mc_reset();
|
mc_reset();
|
reset();
|
reset();
|
|
|
while(1) {
|
while(1) {
|
if (config.iprompt) {
|
if (config.iprompt) {
|
if(server_fd)
|
if(server_fd)
|
{
|
{
|
printf ("(sim) ");
|
printf ("(sim) ");
|
fflush(stdout);
|
fflush(stdout);
|
HandleServerSocket(true); /* block & check_stdin = true */
|
HandleServerSocket(true); /* block & check_stdin = true */
|
}
|
}
|
#ifdef HAVE_LIBREADLINE
|
#ifdef HAVE_LIBREADLINE
|
/* Must disable readline in new mode. It isn't compatible
|
/* Must disable readline in new mode. It isn't compatible
|
with non blocking environments */
|
with non blocking environments */
|
if(!server_fd)
|
if(!server_fd)
|
linestr = readline("(sim) ");
|
linestr = readline("(sim) ");
|
else
|
else
|
linestr = fgets(b2, sizeof b2, stdin);
|
linestr = fgets(b2, sizeof b2, stdin);
|
#else
|
#else
|
if(!server_fd)
|
if(!server_fd)
|
printf ("(sim) ");
|
printf ("(sim) ");
|
linestr = fgets(b2, sizeof b2, stdin);
|
linestr = fgets(b2, sizeof b2, stdin);
|
#endif
|
#endif
|
} else
|
} else
|
strcpy(linestr = b2, "run -1 hush");
|
strcpy(linestr = b2, "run -1 hush");
|
|
|
if (!linestr)
|
if (!linestr)
|
break;
|
break;
|
linestr = stripwhite (linestr);
|
linestr = stripwhite (linestr);
|
|
|
#ifdef HAVE_LIBREADLINE
|
#ifdef HAVE_LIBREADLINE
|
/* Readline only works in the old mode */
|
/* Readline only works in the old mode */
|
if(!server_fd)
|
if(!server_fd)
|
{
|
{
|
if (strlen(linestr) == 0) {
|
if (strlen(linestr) == 0) {
|
char *l = repeat_last_command ();
|
char *l = repeat_last_command ();
|
|
|
if (l) {
|
if (l) {
|
free (linestr);
|
free (linestr);
|
linestr = l;
|
linestr = l;
|
}
|
}
|
}
|
}
|
|
|
if (*linestr) {
|
if (*linestr) {
|
add_history (linestr);
|
add_history (linestr);
|
}
|
}
|
}
|
}
|
#endif /* HAVE_LIBREADLINE */
|
#endif /* HAVE_LIBREADLINE */
|
|
|
if (redirstr = strstr(linestr, ">")) {
|
if (redirstr = strstr(linestr, ">")) {
|
*redirstr = '\0';
|
*redirstr = '\0';
|
strtoken(&redirstr[1], item1, 1);
|
strtoken(&redirstr[1], item1, 1);
|
freopen(item1, "w+", stdout);
|
freopen(item1, "w+", stdout);
|
}
|
}
|
|
|
if (linestr[0] == '\n')
|
if (linestr[0] == '\n')
|
strcpy (linestr, &prev_str[0]);
|
strcpy (linestr, &prev_str[0]);
|
else
|
else
|
strcpy (&prev_str[0], linestr);
|
strcpy (&prev_str[0], linestr);
|
|
|
strtoken(linestr, item1, 1);
|
strtoken(linestr, item1, 1);
|
if (strcmp(item1, "q") == 0) { /* quit */
|
if (strcmp(item1, "q") == 0) { /* quit */
|
printf ("\n");
|
printf ("\n");
|
if (config.profile) {
|
if (config.profile) {
|
extern int cycles;
|
extern int cycles;
|
fprintf(config.fprof,"-%08X FFFFFFFF\n", cycles);
|
fprintf(config.fprof,"-%08X FFFFFFFF\n", cycles);
|
fclose(config.fprof);
|
fclose(config.fprof);
|
}
|
}
|
exit(0);
|
exit(0);
|
} else
|
} else
|
if (strcmp(item1, "help") == 0) /* help */
|
if (strcmp(item1, "help") == 0) /* help */
|
help();
|
help();
|
else
|
else
|
if (strcmp(item1, "t") == 0) { /* trace */
|
if (strcmp(item1, "t") == 0) { /* trace */
|
cont_run = 1;
|
cont_run = 1;
|
} else
|
} else
|
if (strcmp(item1, "dm") == 0) { /* dump memory */
|
if (strcmp(item1, "dm") == 0) { /* dump memory */
|
char item2[20];
|
char item2[20];
|
char item3[20];
|
char item3[20];
|
static int from = 0, to = 0;
|
static int from = 0, to = 0;
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item3, 3);
|
strtoken(linestr, item3, 3);
|
|
|
if (strlen(item2)) {
|
if (strlen(item2)) {
|
if (item2[0] == '_')
|
if (item2[0] == '_')
|
from = eval_label(item2);
|
from = eval_label(item2);
|
else
|
else
|
from = strtoul(item2, NULL, 0);
|
from = strtoul(item2, NULL, 0);
|
to = from + 0x40;
|
to = from + 0x40;
|
}
|
}
|
if (strlen(item3))
|
if (strlen(item3))
|
to = strtoul(item3, NULL, 0);
|
to = strtoul(item3, NULL, 0);
|
dumpmemory(from, to, 0);
|
dumpmemory(from, to, 0);
|
printf("\n");
|
printf("\n");
|
} else
|
} else
|
if (strcmp(item1, "dv") == 0) {/* dump memory as verilog*/
|
if (strcmp(item1, "dv") == 0) {/* dump memory as verilog*/
|
char item2[20];
|
char item2[20];
|
char item3[20];
|
char item3[20];
|
char item4[20];
|
char item4[20];
|
static int from = 0, to = 0;
|
static int from = 0, to = 0;
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item3, 3);
|
strtoken(linestr, item3, 3);
|
strtoken(linestr, item4, 4);
|
strtoken(linestr, item4, 4);
|
|
|
if (strlen(item2)) {
|
if (strlen(item2)) {
|
if (item2[0] == '_')
|
if (item2[0] == '_')
|
from = eval_label(item2);
|
from = eval_label(item2);
|
else
|
else
|
from = strtoul(item2, NULL, 0);
|
from = strtoul(item2, NULL, 0);
|
to = from + 0x40;
|
to = from + 0x40;
|
}
|
}
|
if (strlen(item3))
|
if (strlen(item3))
|
to = strtoul(item3, NULL, 0);
|
to = strtoul(item3, NULL, 0);
|
if (!strlen(item4))
|
if (!strlen(item4))
|
strcpy(item4, "or1k_mem");
|
strcpy(item4, "or1k_mem");
|
dumpverilog(item4, from, to);
|
dumpverilog(item4, from, to);
|
printf("\n");
|
printf("\n");
|
} else
|
} else
|
if (strcmp(item1, "dh") == 0) {/* dump memory as hex*/
|
if (strcmp(item1, "dh") == 0) {/* dump memory as hex*/
|
char item2[20];
|
char item2[20];
|
char item3[20];
|
char item3[20];
|
static int from = 0, to = 0;
|
static int from = 0, to = 0;
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item3, 3);
|
strtoken(linestr, item3, 3);
|
|
|
if (strlen(item2)) {
|
if (strlen(item2)) {
|
if (item2[0] == '_')
|
if (item2[0] == '_')
|
from = eval_label(item2);
|
from = eval_label(item2);
|
else
|
else
|
from = strtoul(item2, NULL, 0);
|
from = strtoul(item2, NULL, 0);
|
to = from + 0x40;
|
to = from + 0x40;
|
}
|
}
|
if (strlen(item3))
|
if (strlen(item3))
|
to = strtoul(item3, NULL, 0);
|
to = strtoul(item3, NULL, 0);
|
dumphex(from, to);
|
dumphex(from, to);
|
printf("\n");
|
printf("\n");
|
} else
|
} else
|
if (strcmp(item1, "pm") == 0) { /* patch memory */
|
if (strcmp(item1, "pm") == 0) { /* patch memory */
|
char item2[20];
|
char item2[20];
|
char item3[20];
|
char item3[20];
|
static int addr = 0;
|
static int addr = 0;
|
int breakpoint = 0;
|
int breakpoint = 0;
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item3, 3);
|
strtoken(linestr, item3, 3);
|
if (strlen(item2))
|
if (strlen(item2))
|
if (item2[0] == '_')
|
if (item2[0] == '_')
|
addr = eval_label(item2);
|
addr = eval_label(item2);
|
else
|
else
|
addr = strtoul(item2, NULL, 0);
|
addr = strtoul(item2, NULL, 0);
|
set_mem32(addr, strtoul(item3, NULL, 0), &breakpoint);
|
set_mem32(addr, strtoul(item3, NULL, 0), &breakpoint);
|
} else
|
} else
|
if (strcmp(item1, "pr") == 0) { /* patch regs */
|
if (strcmp(item1, "pr") == 0) { /* patch regs */
|
char item2[20];
|
char item2[20];
|
char item3[20];
|
char item3[20];
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item3, 3);
|
strtoken(linestr, item3, 3);
|
set_reg32(strtoul(item2, NULL,0), strtoul(item3, NULL, 0));
|
set_reg32(strtoul(item2, NULL,0), strtoul(item3, NULL, 0));
|
} else
|
} else
|
if (strcmp(item1, "pc") == 0) { /* patch PC */
|
if (strcmp(item1, "pc") == 0) { /* patch PC */
|
char item2[20];
|
char item2[20];
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
pcnext = strtoul(item2, NULL, 0);
|
pcnext = strtoul(item2, NULL, 0);
|
} else
|
} else
|
if (strcmp(item1, "break") == 0) { /* set/clear breakpoint */
|
if (strcmp(item1, "break") == 0) { /* set/clear breakpoint */
|
char item2[20];
|
char item2[20];
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
set_insnbrkpoint(strtoul(item2, NULL, 0));
|
set_insnbrkpoint(strtoul(item2, NULL, 0));
|
} else
|
} else
|
if (strcmp(item1, "r") == 0) { /* dump regs */
|
if (strcmp(item1, "r") == 0) { /* dump regs */
|
dumpreg();
|
dumpreg();
|
} else
|
} else
|
if (strcmp(item1, "de") == 0) { /* reset simulator */
|
if (strcmp(item1, "de") == 0) { /* reset simulator */
|
char item2[20];
|
char item2[20];
|
char item3[20];
|
char item3[20];
|
static int from = 0, to = 0;
|
static int from = 0, to = 0;
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item3, 3);
|
strtoken(linestr, item3, 3);
|
|
|
if (strlen(item2)) {
|
if (strlen(item2)) {
|
if (item2[0] == '_')
|
if (item2[0] == '_')
|
from = eval_label(item2);
|
from = eval_label(item2);
|
else
|
else
|
from = strtoul(item2, NULL, 0);
|
from = strtoul(item2, NULL, 0);
|
to = from + 0x40;
|
to = from + 0x40;
|
}
|
}
|
if (strlen(item3))
|
if (strlen(item3))
|
to = strtoul(item3, NULL, 0);
|
to = strtoul(item3, NULL, 0);
|
debugmem(from, to);
|
debugmem(from, to);
|
printf("\n");
|
printf("\n");
|
} else
|
} else
|
if (strcmp(item1, "reset") == 0) { /* reset simulator */
|
if (strcmp(item1, "reset") == 0) { /* reset simulator */
|
uart_reset();
|
uart_reset();
|
dma_reset();
|
dma_reset();
|
eth_reset();
|
eth_reset();
|
tick_reset();
|
tick_reset();
|
pm_reset();
|
pm_reset();
|
pic_reset();
|
pic_reset();
|
reset(); /* Old or new mode */
|
reset(); /* Old or new mode */
|
} else
|
} else
|
if (strcmp(item1, "debug") == 0) { /* debug mode */
|
if (strcmp(item1, "debug") == 0) { /* debug mode */
|
config.simdebug ^= 1;
|
config.simdebug ^= 1;
|
} else
|
} else
|
if (strcmp(item1, "hist") == 0) { /* dump history */
|
if (strcmp(item1, "hist") == 0) { /* dump history */
|
int i;
|
int i;
|
for(i = HISTEXEC_LEN; i; i--)
|
for(i = HISTEXEC_LEN; i; i--)
|
dumpmemory(histexec[i - 1], histexec[i - 1] + 4, 1);
|
dumpmemory(histexec[i - 1], histexec[i - 1] + 4, 1);
|
printf("\n");
|
printf("\n");
|
} else
|
} else
|
if (strcmp(item1, "run") == 0) { /* run */
|
if (strcmp(item1, "run") == 0) { /* run */
|
char item2[20];
|
char item2[20];
|
char item3[20];
|
char item3[20];
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item3, 3);
|
strtoken(linestr, item3, 3);
|
if (strcmp(item3, "hush") == 0)
|
if (strcmp(item3, "hush") == 0)
|
hush = 1;
|
hush = 1;
|
else
|
else
|
hush = 0;
|
hush = 0;
|
cont_run = strtol(item2, NULL, 0);
|
cont_run = strtol(item2, NULL, 0);
|
} else
|
} else
|
if(!strcmp(item1, "stall")) { /* Added by CZ 210801 */
|
if(!strcmp(item1, "stall")) { /* Added by CZ 210801 */
|
extern int cpu_stalled; /* CZ from debug_interface */
|
extern int cpu_stalled; /* CZ from debug_interface */
|
cpu_stalled = 1;
|
cpu_stalled = 1;
|
config.iprompt = 0;
|
config.iprompt = 0;
|
cont_run = -1;
|
cont_run = -1;
|
hush = 1;
|
hush = 1;
|
} else
|
} else
|
if (!strcmp(item1, "trace")) { /* Added by CZ 210801 */
|
if (!strcmp(item1, "trace")) { /* Added by CZ 210801 */
|
char item2[256];
|
char item2[256];
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
if(trace_fd)
|
if(trace_fd)
|
{
|
{
|
close(trace_fd);
|
close(trace_fd);
|
trace_fd = 0;
|
trace_fd = 0;
|
}
|
}
|
if(strcmp(item2,"off")) /* if we're not being turned off */
|
if(strcmp(item2,"off")) /* if we're not being turned off */
|
{
|
{
|
if(item2[0])
|
if(item2[0])
|
trace_fd = open(item2,O_CREAT | O_NOCTTY |
|
trace_fd = open(item2,O_CREAT | O_NOCTTY |
|
O_TRUNC | O_WRONLY, 0644);
|
O_TRUNC | O_WRONLY, 0644);
|
else
|
else
|
trace_fd = dup(1);
|
trace_fd = dup(1);
|
if(trace_fd < 0)
|
if(trace_fd < 0)
|
{
|
{
|
perror(item2[0]?item2:"stdout");
|
perror(item2[0]?item2:"stdout");
|
trace_fd = 0;
|
trace_fd = 0;
|
}
|
}
|
}
|
}
|
} else
|
} else
|
if (strcmp(item1, "stats") == 0) { /* stats */
|
if (strcmp(item1, "stats") == 0) { /* stats */
|
char item2[20];
|
char item2[20];
|
int i = 0;
|
int i = 0;
|
|
|
strtoken(linestr, item2, 2);
|
strtoken(linestr, item2, 2);
|
if (strcmp(item2, "clear") == 0) {
|
if (strcmp(item2, "clear") == 0) {
|
initstats();
|
initstats();
|
printf("Cleared.\n");
|
printf("Cleared.\n");
|
} else {
|
} else {
|
i = strtoul(item2, NULL, 0);
|
i = strtoul(item2, NULL, 0);
|
printstats(i);
|
printstats(i);
|
}
|
}
|
} else
|
} else
|
if (strcmp(item1, "info") == 0) { /* configuration info */
|
if (strcmp(item1, "info") == 0) { /* configuration info */
|
itlb_status(-1);
|
itlb_status(-1);
|
dtlb_status(-1);
|
dtlb_status(-1);
|
bpb_info();
|
bpb_info();
|
btic_info();
|
btic_info();
|
ic_info();
|
ic_info();
|
dc_info();
|
dc_info();
|
uart_status();
|
uart_status();
|
sprs_status();
|
sprs_status();
|
dma_status();
|
dma_status();
|
eth_status();
|
eth_status();
|
} else {
|
} else {
|
printf("%s: Unknown command.\n", linestr);
|
printf("%s: Unknown command.\n", linestr);
|
}
|
}
|
|
|
/* MM: 'run -1' means endless execution. */
|
/* MM: 'run -1' means endless execution. */
|
while(cont_run != 0) {
|
while(cont_run != 0) {
|
int debug_slowdown = DEBUG_SLOWDOWN;
|
int debug_slowdown = DEBUG_SLOWDOWN;
|
extern int cycle_delay; /* Added by CZ 27/05/01. Set during exception. */
|
extern int cycle_delay; /* Added by CZ 27/05/01. Set during exception. */
|
extern int cpu_stalled; /* CZ from debug_interface */
|
extern int cpu_stalled; /* CZ from debug_interface */
|
|
|
if(cpu_stalled)
|
if(cpu_stalled)
|
{
|
{
|
BlockJTAG();
|
BlockJTAG();
|
HandleServerSocket(false);
|
HandleServerSocket(false);
|
continue;
|
continue;
|
}
|
}
|
|
|
if (!testsprbits(SPR_PMR, SPR_PMR_DME | SPR_PMR_SME)) {
|
if (!testsprbits(SPR_PMR, SPR_PMR_DME | SPR_PMR_SME)) {
|
if(cycle_delay <= 0)
|
if(cycle_delay <= 0)
|
{
|
{
|
unsigned int addr;
|
unsigned int addr;
|
if (cont_run > 0) cont_run--;
|
if (cont_run > 0) cont_run--;
|
if(fetch()) {
|
if(fetch()) {
|
cont_run = 0; /* memory breakpoint encountered */
|
cont_run = 0; /* memory breakpoint encountered */
|
break;
|
break;
|
}
|
}
|
addr = iqueue[0].insn_addr;
|
addr = iqueue[0].insn_addr;
|
|
|
/* If trace_fd is non zero, we want
|
/* If trace_fd is non zero, we want
|
to make sure that disassemble is called */
|
to make sure that disassemble is called */
|
|
|
decode_execute(&iqueue[0],trace_fd);
|
decode_execute(&iqueue[0],trace_fd);
|
if(trace_fd)
|
if(trace_fd)
|
{
|
{
|
char sTemp[256];
|
char sTemp[256];
|
char sTemp2[256];
|
char sTemp2[256];
|
unsigned long value;
|
unsigned long value;
|
extern char *disassembled;
|
extern char *disassembled;
|
extern unsigned long reg[];
|
extern unsigned long reg[];
|
|
|
/* The objects passed to the
|
/* The objects passed to the
|
trace command should not be
|
trace command should not be
|
hardcoded like this...instead
|
hardcoded like this...instead
|
what to dump should be passed
|
what to dump should be passed
|
on the command line.
|
on the command line.
|
|
|
FIX THIS LATER...
|
FIX THIS LATER...
|
*/
|
*/
|
value = (evalsim_mem8(0x306bc) << 24) +
|
value = (evalsim_mem8(0x306bc) << 24) +
|
(evalsim_mem8(0x306bd) << 16) +
|
(evalsim_mem8(0x306bd) << 16) +
|
(evalsim_mem8(0x306be) << 8)
|
(evalsim_mem8(0x306be) << 8)
|
+ evalsim_mem8(0x306bf);
|
+ evalsim_mem8(0x306bf);
|
|
|
sprintf(sTemp,"0x%06x: %s",addr,disassembled);
|
sprintf(sTemp,"0x%06x: %s",addr,disassembled);
|
memset(sTemp2,' ',sizeof(sTemp2));
|
memset(sTemp2,' ',sizeof(sTemp2));
|
strncpy(sTemp2,sTemp,strlen(sTemp));
|
strncpy(sTemp2,sTemp,strlen(sTemp));
|
sprintf(&sTemp2[40],"<0x%08x,0x%08x> [0x%08x]\n",
|
sprintf(&sTemp2[40],"<0x%08x,0x%08x> [0x%08x]\n",
|
reg[3],reg[4],value);
|
reg[3],reg[4],value);
|
write(trace_fd,sTemp2,strlen(sTemp2));
|
write(trace_fd,sTemp2,strlen(sTemp2));
|
}
|
}
|
update_pc();
|
update_pc();
|
analysis();
|
analysis();
|
if (!hush)
|
if (!hush)
|
dumpreg();
|
dumpreg();
|
}
|
}
|
else
|
else
|
cycle_delay--;
|
cycle_delay--;
|
|
|
pic_clock();
|
pic_clock();
|
dc_clock();
|
dc_clock();
|
ic_clock();
|
ic_clock();
|
}
|
}
|
if (!testsprbits(SPR_PMR, SPR_PMR_SME))
|
if (!testsprbits(SPR_PMR, SPR_PMR_SME))
|
tick_clock();
|
tick_clock();
|
pm_clock();
|
pm_clock();
|
uart_clock();
|
uart_clock();
|
dma_clock();
|
dma_clock();
|
eth_clock();
|
eth_clock();
|
|
|
#ifndef DEBUGMOD_OFF
|
#ifndef DEBUGMOD_OFF
|
if (debug_slowdown-- == 0) {
|
if (debug_slowdown-- == 0) {
|
debug_slowdown = DEBUG_SLOWDOWN;
|
debug_slowdown = DEBUG_SLOWDOWN;
|
HandleServerSocket(false); /* block & check_stdin = false */
|
HandleServerSocket(false); /* block & check_stdin = false */
|
}
|
}
|
#endif
|
#endif
|
}
|
}
|
hush = 0;
|
hush = 0;
|
fflush(stdout);
|
fflush(stdout);
|
freopen("/dev/fd/0", "w+", stdout);
|
freopen("/dev/fd/0", "w+", stdout);
|
|
|
if (!config.iprompt) { /* non-interactive quit */
|
if (!config.iprompt) { /* non-interactive quit */
|
if (config.profile) {
|
if (config.profile) {
|
extern int cycles;
|
extern int cycles;
|
fprintf(config.fprof,"-%08X FFFFFFFF\n", cycles);
|
fprintf(config.fprof,"-%08X FFFFFFFF\n", cycles);
|
fclose(config.fprof);
|
fclose(config.fprof);
|
}
|
}
|
exit(0);
|
exit(0);
|
}
|
}
|
#ifdef HAVE_LIBREADLINE
|
#ifdef HAVE_LIBREADLINE
|
if (linestr)
|
if (linestr)
|
free (linestr);
|
free (linestr);
|
#endif
|
#endif
|
|
|
}
|
}
|
exit(0);
|
exit(0);
|
}
|
}
|
|
|
#ifdef HAVE_LIBREADLINE
|
#ifdef HAVE_LIBREADLINE
|
char *command_generator ();
|
char *command_generator ();
|
char **sim_completion ();
|
char **sim_completion ();
|
|
|
/* Tell the GNU readline library how to complete. We want to try to complete
|
/* Tell the GNU readline library how to complete. We want to try to complete
|
on command names if this is the first word in the line, or on filenames
|
on command names if this is the first word in the line, or on filenames
|
if not. */
|
if not. */
|
void initialize_readline ()
|
void initialize_readline ()
|
{
|
{
|
/* Allow conditional parsing of the ~/.inputrc file. */
|
/* Allow conditional parsing of the ~/.inputrc file. */
|
rl_readline_name = "or1ksim";
|
rl_readline_name = "or1ksim";
|
|
|
/* Tell the completer that we want a crack first. */
|
/* Tell the completer that we want a crack first. */
|
rl_attempted_completion_function = (CPPFunction *)sim_completion;
|
rl_attempted_completion_function = (CPPFunction *)sim_completion;
|
}
|
}
|
|
|
/* Attempt to complete on the contents of TEXT. START and END bound the
|
/* Attempt to complete on the contents of TEXT. START and END bound the
|
region of rl_line_buffer that contains the word to complete. TEXT is
|
region of rl_line_buffer that contains the word to complete. TEXT is
|
the word to complete. We can use the entire contents of rl_line_buffer
|
the word to complete. We can use the entire contents of rl_line_buffer
|
in case we want to do some simple parsing. Return the array of matches,
|
in case we want to do some simple parsing. Return the array of matches,
|
or NULL if there aren't any. */
|
or NULL if there aren't any. */
|
char **
|
char **
|
sim_completion (text, start, end)
|
sim_completion (text, start, end)
|
char *text;
|
char *text;
|
int start, end;
|
int start, end;
|
{
|
{
|
char **matches;
|
char **matches;
|
|
|
matches = (char **)NULL;
|
matches = (char **)NULL;
|
|
|
/* If this word is at the start of the line, then it is a command
|
/* If this word is at the start of the line, then it is a command
|
to complete. Otherwise it is the name of a file in the current
|
to complete. Otherwise it is the name of a file in the current
|
directory. */
|
directory. */
|
if (start == 0)
|
if (start == 0)
|
matches = completion_matches (text, command_generator);
|
matches = completion_matches (text, command_generator);
|
|
|
return (matches);
|
return (matches);
|
}
|
}
|
|
|
/* Generator function for command completion. STATE lets us know whether
|
/* Generator function for command completion. STATE lets us know whether
|
to start from scratch; without any state (i.e. STATE == 0), then we
|
to start from scratch; without any state (i.e. STATE == 0), then we
|
start at the top of the list. */
|
start at the top of the list. */
|
char *
|
char *
|
command_generator (text, state)
|
command_generator (text, state)
|
char *text;
|
char *text;
|
int state;
|
int state;
|
{
|
{
|
static int list_index, len;
|
static int list_index, len;
|
char *name;
|
char *name;
|
|
|
/* If this is a new word to complete, initialize now. This includes
|
/* If this is a new word to complete, initialize now. This includes
|
saving the length of TEXT for efficiency, and initializing the index
|
saving the length of TEXT for efficiency, and initializing the index
|
variable to 0. */
|
variable to 0. */
|
if (!state)
|
if (!state)
|
{
|
{
|
list_index = 0;
|
list_index = 0;
|
len = strlen (text);
|
len = strlen (text);
|
}
|
}
|
|
|
/* Return the next name which partially matches from the command list. */
|
/* Return the next name which partially matches from the command list. */
|
while (name = sim_commands[list_index])
|
while (name = sim_commands[list_index])
|
{
|
{
|
list_index++;
|
list_index++;
|
|
|
if (strncmp (name, text, len) == 0)
|
if (strncmp (name, text, len) == 0)
|
return (dupstr(name));
|
return (dupstr(name));
|
}
|
}
|
|
|
/* If no names matched, then return NULL. */
|
/* If no names matched, then return NULL. */
|
return ((char *)NULL);
|
return ((char *)NULL);
|
}
|
}
|
|
|
char *
|
char *
|
dupstr (s)
|
dupstr (s)
|
char *s;
|
char *s;
|
{
|
{
|
char *r;
|
char *r;
|
|
|
r = xmalloc (strlen (s) + 1);
|
r = xmalloc (strlen (s) + 1);
|
strcpy (r, s);
|
strcpy (r, s);
|
return (r);
|
return (r);
|
}
|
}
|
|
|
/* Repeats the last command. */
|
/* Repeats the last command. */
|
char *
|
char *
|
repeat_last_command ()
|
repeat_last_command ()
|
{
|
{
|
int offset = where_history ();
|
int offset = where_history ();
|
HIST_ENTRY *hist;
|
HIST_ENTRY *hist;
|
|
|
if (hist = history_get (offset))
|
if (hist = history_get (offset))
|
{
|
{
|
return dupstr (hist->line);
|
return dupstr (hist->line);
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
#endif
|
#endif
|
|
|
extern char *disassembled;
|
extern char *disassembled;
|
void debugmem( unsigned long from, unsigned long to )
|
void debugmem( unsigned long from, unsigned long to )
|
{
|
{
|
int i;
|
int i;
|
printf("starting to dump mem...\n");
|
printf("starting to dump mem...\n");
|
for(i=from; i<to; ) {
|
for(i=from; i<to; ) {
|
struct label_entry *entry;
|
struct label_entry *entry;
|
unsigned int _insn;
|
unsigned int _insn;
|
printf("i=%x :: ", i);
|
printf("i=%x :: ", i);
|
|
|
if (verify_memoryarea(i) && (entry = get_label(i)))
|
if (verify_memoryarea(i) && (entry = get_label(i)))
|
printf("label: %s |", entry->name);
|
printf("label: %s |", entry->name);
|
|
|
iqueue[0].insn = _insn = evalsim_mem32(i);
|
iqueue[0].insn = _insn = evalsim_mem32(i);
|
iqueue[0].insn_index = insn_decode(_insn);
|
iqueue[0].insn_index = insn_decode(_insn);
|
disassemble_insn (_insn);
|
disassemble_insn (_insn);
|
printf("%08x %s\n", _insn, disassembled);
|
printf("%08x %s\n", _insn, disassembled);
|
i += insn_len( iqueue[0].insn_index );
|
i += insn_len( iqueue[0].insn_index );
|
}
|
}
|
}
|
}
|
|
|
static int tcp_level = 0;
|
static int tcp_level = 0;
|
|
|
/* Added by CZ 24/05/01 */
|
/* Added by CZ 24/05/01 */
|
int GetServerSocket(const char* name,const char* proto,int port)
|
int GetServerSocket(const char* name,const char* proto,int port)
|
{
|
{
|
struct servent *service;
|
struct servent *service;
|
struct protoent *protocol;
|
struct protoent *protocol;
|
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
struct hostent *hp;
|
struct hostent *hp;
|
int sockfd;
|
int sockfd;
|
char myname[256];
|
char myname[256];
|
int flags;
|
int flags;
|
char sTemp[256];
|
char sTemp[256];
|
|
|
/* First, get the protocol number of TCP */
|
/* First, get the protocol number of TCP */
|
if(!(protocol = getprotobyname(proto)))
|
if(!(protocol = getprotobyname(proto)))
|
{
|
{
|
sprintf(sTemp,"Unable to load protocol \"%s\"",proto);
|
sprintf(sTemp,"Unable to load protocol \"%s\"",proto);
|
perror(sTemp);
|
perror(sTemp);
|
return 0;
|
return 0;
|
}
|
}
|
tcp_level = protocol->p_proto; /* Save for later */
|
tcp_level = protocol->p_proto; /* Save for later */
|
|
|
/* If we weren't passed a non standard port, get the port
|
/* If we weren't passed a non standard port, get the port
|
from the services directory. */
|
from the services directory. */
|
if(!port)
|
if(!port)
|
{
|
{
|
if(service = getservbyname(name,protocol->p_name))
|
if(service = getservbyname(name,protocol->p_name))
|
port = ntohs(service->s_port);
|
port = ntohs(service->s_port);
|
}
|
}
|
|
|
/* Create the socket using the TCP protocol */
|
/* Create the socket using the TCP protocol */
|
if((sockfd = socket(PF_INET,SOCK_STREAM,protocol->p_proto)) < 0)
|
if((sockfd = socket(PF_INET,SOCK_STREAM,protocol->p_proto)) < 0)
|
{
|
{
|
perror("Unable to create socket");
|
perror("Unable to create socket");
|
return 0;
|
return 0;
|
}
|
}
|
|
|
flags = 1;
|
flags = 1;
|
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int))
|
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int))
|
< 0)
|
< 0)
|
{
|
{
|
sprintf(sTemp,"Can not set SO_REUSEADDR option on socket %d",sockfd);
|
sprintf(sTemp,"Can not set SO_REUSEADDR option on socket %d",sockfd);
|
perror(sTemp);
|
perror(sTemp);
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* The server should also be non blocking. Get the current flags. */
|
/* The server should also be non blocking. Get the current flags. */
|
if(fcntl(sockfd,F_GETFL,&flags) < 0)
|
if(fcntl(sockfd,F_GETFL,&flags) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to get flags for socket %d",sockfd);
|
sprintf(sTemp,"Unable to get flags for socket %d",sockfd);
|
perror(sTemp);
|
perror(sTemp);
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* Set the nonblocking flag */
|
/* Set the nonblocking flag */
|
if(fcntl(sockfd,F_SETFL, flags | O_NONBLOCK) < 0)
|
if(fcntl(sockfd,F_SETFL, flags | O_NONBLOCK) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to set flags for socket %d to value 0x%08x",
|
sprintf(sTemp,"Unable to set flags for socket %d to value 0x%08x",
|
sockfd,flags | O_NONBLOCK);
|
sockfd,flags | O_NONBLOCK);
|
perror(sTemp);
|
perror(sTemp);
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* Find out what our address is */
|
/* Find out what our address is */
|
memset(&sa,0,sizeof(struct sockaddr_in));
|
memset(&sa,0,sizeof(struct sockaddr_in));
|
gethostname(myname,sizeof(myname));
|
gethostname(myname,sizeof(myname));
|
if(!(hp = gethostbyname(myname)))
|
if(!(hp = gethostbyname(myname)))
|
{
|
{
|
perror("Unable to read hostname");
|
perror("Unable to read hostname");
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
/* Bind our socket to the appropriate address */
|
/* Bind our socket to the appropriate address */
|
sa.sin_family = hp->h_addrtype;
|
sa.sin_family = hp->h_addrtype;
|
sa.sin_port = htons(port);
|
sa.sin_port = htons(port);
|
if(bind(sockfd,(struct sockaddr*)&sa,sizeof(struct sockaddr_in)) < 0)
|
if(bind(sockfd,(struct sockaddr*)&sa,sizeof(struct sockaddr_in)) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to bind socket %d to port %d",sockfd,port);
|
sprintf(sTemp,"Unable to bind socket %d to port %d",sockfd,port);
|
perror(sTemp);
|
perror(sTemp);
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
serverIP = sa.sin_addr.s_addr;
|
serverIP = sa.sin_addr.s_addr;
|
flags = sizeof(struct sockaddr_in);
|
flags = sizeof(struct sockaddr_in);
|
if(getsockname(sockfd,(struct sockaddr*)&sa,&flags) < 0)
|
if(getsockname(sockfd,(struct sockaddr*)&sa,&flags) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to get socket information for socket %d",sockfd);
|
sprintf(sTemp,"Unable to get socket information for socket %d",sockfd);
|
perror(sTemp);
|
perror(sTemp);
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
serverPort = ntohs(sa.sin_port);
|
serverPort = ntohs(sa.sin_port);
|
|
|
/* Set the backlog to 1 connections */
|
/* Set the backlog to 1 connections */
|
if(listen(sockfd,1) < 0)
|
if(listen(sockfd,1) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to set backlog on socket %d to %d",sockfd,1);
|
sprintf(sTemp,"Unable to set backlog on socket %d to %d",sockfd,1);
|
perror(sTemp);
|
perror(sTemp);
|
close(sockfd);
|
close(sockfd);
|
return 0;
|
return 0;
|
}
|
}
|
|
|
return sockfd;
|
return sockfd;
|
}
|
}
|
|
|
void BlockJTAG()
|
void BlockJTAG()
|
{
|
{
|
struct pollfd fds[2];
|
struct pollfd fds[2];
|
int n = 0;
|
int n = 0;
|
|
|
fds[n].fd = server_fd;
|
fds[n].fd = server_fd;
|
fds[n].events = POLLIN;
|
fds[n].events = POLLIN;
|
fds[n++].revents = 0;
|
fds[n++].revents = 0;
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
fds[n].fd = gdb_fd;
|
fds[n].fd = gdb_fd;
|
fds[n].events = POLLIN;
|
fds[n].events = POLLIN;
|
fds[n++].revents = 0;
|
fds[n++].revents = 0;
|
}
|
}
|
poll(fds,n,-1);
|
poll(fds,n,-1);
|
}
|
}
|
|
|
void HandleServerSocket(Boolean block)
|
void HandleServerSocket(Boolean block)
|
{
|
{
|
struct pollfd fds[3];
|
struct pollfd fds[3];
|
int n = 0;
|
int n = 0;
|
int timeout = block ? -1 : 0;
|
int timeout = block ? -1 : 0;
|
int server_index = -1;
|
int server_index = -1;
|
int gdb_index = -1;
|
int gdb_index = -1;
|
Boolean data_on_stdin = false;
|
Boolean data_on_stdin = false;
|
int o_serv_fd = server_fd;
|
int o_serv_fd = server_fd;
|
|
|
if(!o_serv_fd && !gdb_fd)
|
if(!o_serv_fd && !gdb_fd)
|
return;
|
return;
|
|
|
if(o_serv_fd)
|
if(o_serv_fd)
|
{
|
{
|
fds[n].fd = o_serv_fd;
|
fds[n].fd = o_serv_fd;
|
fds[n].events = POLLIN;
|
fds[n].events = POLLIN;
|
fds[n++].revents = 0;
|
fds[n++].revents = 0;
|
}
|
}
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
fds[n].fd = gdb_fd;
|
fds[n].fd = gdb_fd;
|
fds[n].events = POLLIN;
|
fds[n].events = POLLIN;
|
fds[n++].revents = 0;
|
fds[n++].revents = 0;
|
}
|
}
|
if(block)
|
if(block)
|
{
|
{
|
fds[n].fd = 0;
|
fds[n].fd = 0;
|
fds[n].events = POLLIN;
|
fds[n].events = POLLIN;
|
fds[n++].revents = 0;
|
fds[n++].revents = 0;
|
}
|
}
|
|
|
while(!data_on_stdin)
|
while(!data_on_stdin)
|
{
|
{
|
switch(poll(fds,n,timeout))
|
switch(poll(fds,n,timeout))
|
{
|
{
|
case -1:
|
case -1:
|
if(errno == EINTR)
|
if(errno == EINTR)
|
continue;
|
continue;
|
perror("poll");
|
perror("poll");
|
server_fd = 0;
|
server_fd = 0;
|
break;
|
break;
|
case 0: /* Nothing interesting going on */
|
case 0: /* Nothing interesting going on */
|
data_on_stdin = true; /* Can only get here if nonblocking */
|
data_on_stdin = true; /* Can only get here if nonblocking */
|
break;
|
break;
|
default:
|
default:
|
/* Make sure to handle the gdb port first! */
|
/* Make sure to handle the gdb port first! */
|
if((fds[0].revents && (gdb_fd && !o_serv_fd) ||
|
if((fds[0].revents && (gdb_fd && !o_serv_fd) ||
|
fds[1].revents && (server_fd && gdb_fd)))
|
fds[1].revents && (server_fd && gdb_fd)))
|
{
|
{
|
int revents = o_serv_fd ? fds[1].revents : fds[0].revents;
|
int revents = o_serv_fd ? fds[1].revents : fds[0].revents;
|
|
|
if(revents & POLLIN)
|
if(revents & POLLIN)
|
GDBRequest();
|
GDBRequest();
|
else /* Error Occurred */
|
else /* Error Occurred */
|
{
|
{
|
fprintf(stderr,"Received flags 0x%08x on gdb socket. Shutting down.\n",revents);
|
fprintf(stderr,"Received flags 0x%08x on gdb socket. Shutting down.\n",revents);
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
}
|
}
|
if(fds[0].revents && o_serv_fd)
|
if(fds[0].revents && o_serv_fd)
|
{
|
{
|
if(fds[0].revents & POLLIN)
|
if(fds[0].revents & POLLIN)
|
JTAGRequest();
|
JTAGRequest();
|
else /* Error Occurred */
|
else /* Error Occurred */
|
{
|
{
|
fprintf(stderr,"Received flags 0x%08x on server. Shutting down.\n",fds[0].revents);
|
fprintf(stderr,"Received flags 0x%08x on server. Shutting down.\n",fds[0].revents);
|
close(o_serv_fd);
|
close(o_serv_fd);
|
server_fd = 0;
|
server_fd = 0;
|
serverPort = 0;
|
serverPort = 0;
|
serverIP = 0;
|
serverIP = 0;
|
}
|
}
|
}
|
}
|
if(fds[2].revents || (fds[1].revents && !gdb_fd))
|
if(fds[2].revents || (fds[1].revents && !gdb_fd))
|
data_on_stdin = true;
|
data_on_stdin = true;
|
break;
|
break;
|
} /* End of switch statement */
|
} /* End of switch statement */
|
} /* End of while statement */
|
} /* End of while statement */
|
}
|
}
|
|
|
void JTAGRequest()
|
void JTAGRequest()
|
{
|
{
|
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
struct sockaddr* addr = (struct sockaddr*)&sa;
|
struct sockaddr* addr = (struct sockaddr*)&sa;
|
int n = sizeof(struct sockaddr_in);
|
int n = sizeof(struct sockaddr_in);
|
int fd = accept(server_fd,addr,&n);
|
int fd = accept(server_fd,addr,&n);
|
int on_off = 0; /* Turn off Nagel's algorithm on the socket */
|
int on_off = 0; /* Turn off Nagel's algorithm on the socket */
|
int flags;
|
int flags;
|
char sTemp[256];
|
char sTemp[256];
|
|
|
if(fd < 0)
|
if(fd < 0)
|
{
|
{
|
/* This is valid, because a connection could have started,
|
/* This is valid, because a connection could have started,
|
and then terminated due to a protocol error or user
|
and then terminated due to a protocol error or user
|
initiation before the accept could take place. */
|
initiation before the accept could take place. */
|
if(errno != EWOULDBLOCK && errno != EAGAIN)
|
if(errno != EWOULDBLOCK && errno != EAGAIN)
|
{
|
{
|
perror("accept");
|
perror("accept");
|
close(server_fd);
|
close(server_fd);
|
server_fd = 0;
|
server_fd = 0;
|
serverPort = 0;
|
serverPort = 0;
|
serverIP = 0;
|
serverIP = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
|
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
close(fd);
|
close(fd);
|
return;
|
return;
|
}
|
}
|
|
|
if(fcntl(fd,F_GETFL,&flags) < 0)
|
if(fcntl(fd,F_GETFL,&flags) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to get flags for gdb socket %d",fd);
|
sprintf(sTemp,"Unable to get flags for gdb socket %d",fd);
|
perror(sTemp);
|
perror(sTemp);
|
close(fd);
|
close(fd);
|
return;
|
return;
|
}
|
}
|
|
|
if(fcntl(fd,F_SETFL, flags | O_NONBLOCK) < 0)
|
if(fcntl(fd,F_SETFL, flags | O_NONBLOCK) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to set flags for gdb socket %d to value 0x%08x",
|
sprintf(sTemp,"Unable to set flags for gdb socket %d to value 0x%08x",
|
fd,flags | O_NONBLOCK);
|
fd,flags | O_NONBLOCK);
|
perror(sTemp);
|
perror(sTemp);
|
close(fd);
|
close(fd);
|
return;
|
return;
|
}
|
}
|
|
|
if(setsockopt(fd,tcp_level,TCP_NODELAY,&on_off,sizeof(int)) < 0)
|
if(setsockopt(fd,tcp_level,TCP_NODELAY,&on_off,sizeof(int)) < 0)
|
{
|
{
|
sprintf(sTemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt",fd);
|
sprintf(sTemp,"Unable to disable Nagel's algorithm for socket %d.\nsetsockopt",fd);
|
perror(sTemp);
|
perror(sTemp);
|
close(fd);
|
close(fd);
|
return;
|
return;
|
}
|
}
|
|
|
gdb_fd = fd;
|
gdb_fd = fd;
|
}
|
}
|
|
|
void GDBRequest()
|
void GDBRequest()
|
{
|
{
|
JTAGProxyWriteMessage msg_write;
|
JTAGProxyWriteMessage msg_write;
|
JTAGProxyReadMessage msg_read;
|
JTAGProxyReadMessage msg_read;
|
JTAGProxyChainMessage msg_chain;
|
JTAGProxyChainMessage msg_chain;
|
JTAGProxyWriteResponse resp_write;
|
JTAGProxyWriteResponse resp_write;
|
JTAGProxyReadResponse resp_read;
|
JTAGProxyReadResponse resp_read;
|
JTAGProxyChainResponse resp_chain;
|
JTAGProxyChainResponse resp_chain;
|
JTAGProxyBlockWriteMessage *msg_bwrite;
|
JTAGProxyBlockWriteMessage *msg_bwrite;
|
JTAGProxyBlockReadMessage msg_bread;
|
JTAGProxyBlockReadMessage msg_bread;
|
JTAGProxyBlockWriteResponse resp_bwrite;
|
JTAGProxyBlockWriteResponse resp_bwrite;
|
JTAGProxyBlockReadResponse *resp_bread;
|
JTAGProxyBlockReadResponse *resp_bread;
|
char *buf;
|
char *buf;
|
unsigned long long data;
|
unsigned long long data;
|
int err = 0;
|
int err = 0;
|
uint32_t command,length;
|
uint32_t command,length;
|
int len,i;
|
int len,i;
|
|
|
/* First, we must read the incomming command */
|
/* First, we must read the incomming command */
|
if(gdb_read(&command,sizeof(uint32_t)) < 0)
|
if(gdb_read(&command,sizeof(uint32_t)) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 1");
|
perror("gdb socket - 1");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
if(gdb_read(&length,sizeof(uint32_t)) < 0)
|
if(gdb_read(&length,sizeof(uint32_t)) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 2");
|
perror("gdb socket - 2");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
length = ntohl(length);
|
length = ntohl(length);
|
|
|
/* Now, verify the protocol and implement the command */
|
/* Now, verify the protocol and implement the command */
|
switch(ntohl(command))
|
switch(ntohl(command))
|
{
|
{
|
case JTAG_COMMAND_WRITE:
|
case JTAG_COMMAND_WRITE:
|
if(length != sizeof(msg_write) - 8)
|
if(length != sizeof(msg_write) - 8)
|
{
|
{
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
return;
|
return;
|
}
|
}
|
buf = (char*)&msg_write;
|
buf = (char*)&msg_write;
|
if(gdb_read(&buf[8],length) < 0)
|
if(gdb_read(&buf[8],length) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 3");
|
perror("gdb socket - 3");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
msg_write.address = ntohl(msg_write.address);
|
msg_write.address = ntohl(msg_write.address);
|
msg_write.data_H = ntohl(msg_write.data_H);
|
msg_write.data_H = ntohl(msg_write.data_H);
|
msg_write.data_L = ntohl(msg_write.data_L);
|
msg_write.data_L = ntohl(msg_write.data_L);
|
err = DebugSetRegister(msg_write.address,msg_write.data_L);
|
err = DebugSetRegister(msg_write.address,msg_write.data_L);
|
resp_write.status = htonl(err);
|
resp_write.status = htonl(err);
|
if(gdb_write(&resp_write,sizeof(resp_write)) < 0)
|
if(gdb_write(&resp_write,sizeof(resp_write)) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 4");
|
perror("gdb socket - 4");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
break;
|
break;
|
case JTAG_COMMAND_READ:
|
case JTAG_COMMAND_READ:
|
if(length != sizeof(msg_read) - 8)
|
if(length != sizeof(msg_read) - 8)
|
{
|
{
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
return;
|
return;
|
}
|
}
|
buf = (char*)&msg_read;
|
buf = (char*)&msg_read;
|
if(gdb_read(&buf[8],length) < 0)
|
if(gdb_read(&buf[8],length) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 5");
|
perror("gdb socket - 5");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
msg_read.address = ntohl(msg_read.address);
|
msg_read.address = ntohl(msg_read.address);
|
err = DebugGetRegister(msg_read.address,&resp_read.data_L);
|
err = DebugGetRegister(msg_read.address,&resp_read.data_L);
|
resp_read.status = htonl(err);
|
resp_read.status = htonl(err);
|
resp_read.data_H = 0;
|
resp_read.data_H = 0;
|
resp_read.data_L = htonl(resp_read.data_L);
|
resp_read.data_L = htonl(resp_read.data_L);
|
if(gdb_write(&resp_read,sizeof(resp_read)) < 0)
|
if(gdb_write(&resp_read,sizeof(resp_read)) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 6");
|
perror("gdb socket - 6");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
break;
|
break;
|
case JTAG_COMMAND_BLOCK_WRITE:
|
case JTAG_COMMAND_BLOCK_WRITE:
|
if(length < sizeof(JTAGProxyBlockWriteMessage)-8)
|
if(length < sizeof(JTAGProxyBlockWriteMessage)-8)
|
{
|
{
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
return;
|
return;
|
}
|
}
|
if(!(buf = (char*)malloc(8+length)))
|
if(!(buf = (char*)malloc(8+length)))
|
{
|
{
|
ProtocolClean(length,JTAG_PROXY_OUT_OF_MEMORY);
|
ProtocolClean(length,JTAG_PROXY_OUT_OF_MEMORY);
|
return;
|
return;
|
}
|
}
|
msg_bwrite = (JTAGProxyBlockWriteMessage*)buf;
|
msg_bwrite = (JTAGProxyBlockWriteMessage*)buf;
|
if(gdb_read(&buf[8],length) < 0)
|
if(gdb_read(&buf[8],length) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 5");
|
perror("gdb socket - 5");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
free(buf);
|
free(buf);
|
return;
|
return;
|
}
|
}
|
msg_bwrite->address = ntohl(msg_bwrite->address);
|
msg_bwrite->address = ntohl(msg_bwrite->address);
|
msg_bwrite->nRegisters = ntohl(msg_bwrite->nRegisters);
|
msg_bwrite->nRegisters = ntohl(msg_bwrite->nRegisters);
|
for(i=0;i<msg_bwrite->nRegisters;i++)
|
for(i=0;i<msg_bwrite->nRegisters;i++)
|
{
|
{
|
int t_err = 0;
|
int t_err = 0;
|
|
|
msg_bwrite->data[i] = ntohl(msg_bwrite->data[i]);
|
msg_bwrite->data[i] = ntohl(msg_bwrite->data[i]);
|
t_err = DebugSetRegister(msg_bwrite->address+i,msg_bwrite->data[i]);
|
t_err = DebugSetRegister(msg_bwrite->address+i,msg_bwrite->data[i]);
|
err = err ? err : t_err;
|
err = err ? err : t_err;
|
}
|
}
|
resp_bwrite.status = htonl(err);
|
resp_bwrite.status = htonl(err);
|
free(buf);
|
free(buf);
|
buf = NULL;
|
buf = NULL;
|
msg_bwrite = NULL;
|
msg_bwrite = NULL;
|
if(gdb_write(&resp_bwrite,sizeof(resp_bwrite)) < 0)
|
if(gdb_write(&resp_bwrite,sizeof(resp_bwrite)) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 4");
|
perror("gdb socket - 4");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
break;
|
break;
|
case JTAG_COMMAND_BLOCK_READ:
|
case JTAG_COMMAND_BLOCK_READ:
|
if(length != sizeof(msg_bread) - 8)
|
if(length != sizeof(msg_bread) - 8)
|
{
|
{
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
return;
|
return;
|
}
|
}
|
buf = (char*)&msg_bread;
|
buf = (char*)&msg_bread;
|
if(gdb_read(&buf[8],length) < 0)
|
if(gdb_read(&buf[8],length) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 5");
|
perror("gdb socket - 5");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
msg_bread.address = ntohl(msg_bread.address);
|
msg_bread.address = ntohl(msg_bread.address);
|
msg_bread.nRegisters = ntohl(msg_bread.nRegisters);
|
msg_bread.nRegisters = ntohl(msg_bread.nRegisters);
|
len = sizeof(JTAGProxyBlockReadResponse) + 4*(msg_bread.nRegisters-1);
|
len = sizeof(JTAGProxyBlockReadResponse) + 4*(msg_bread.nRegisters-1);
|
if(!(buf = (char*)malloc(len)))
|
if(!(buf = (char*)malloc(len)))
|
{
|
{
|
ProtocolClean(0,JTAG_PROXY_OUT_OF_MEMORY);
|
ProtocolClean(0,JTAG_PROXY_OUT_OF_MEMORY);
|
return;
|
return;
|
}
|
}
|
resp_bread = (JTAGProxyBlockReadResponse*)buf;
|
resp_bread = (JTAGProxyBlockReadResponse*)buf;
|
for(i=0;i<msg_bread.nRegisters;i++)
|
for(i=0;i<msg_bread.nRegisters;i++)
|
{
|
{
|
int t_err;
|
int t_err;
|
|
|
t_err = DebugGetRegister(msg_bread.address+i,&resp_bread->data[i]);
|
t_err = DebugGetRegister(msg_bread.address+i,&resp_bread->data[i]);
|
resp_bread->data[i] = htonl(resp_bread->data[i]);
|
resp_bread->data[i] = htonl(resp_bread->data[i]);
|
err = err ? err : t_err;
|
err = err ? err : t_err;
|
}
|
}
|
resp_bread->status = htonl(err);
|
resp_bread->status = htonl(err);
|
resp_bread->nRegisters = htonl(msg_bread.nRegisters);
|
resp_bread->nRegisters = htonl(msg_bread.nRegisters);
|
if(gdb_write(resp_bread,len) < 0)
|
if(gdb_write(resp_bread,len) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 6");
|
perror("gdb socket - 6");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
free(buf);
|
free(buf);
|
return;
|
return;
|
}
|
}
|
free(buf);
|
free(buf);
|
buf = NULL;
|
buf = NULL;
|
resp_bread = NULL;
|
resp_bread = NULL;
|
break;
|
break;
|
case JTAG_COMMAND_CHAIN:
|
case JTAG_COMMAND_CHAIN:
|
if(length != sizeof(msg_chain) - 8)
|
if(length != sizeof(msg_chain) - 8)
|
{
|
{
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
ProtocolClean(length,JTAG_PROXY_PROTOCOL_ERROR);
|
return;
|
return;
|
}
|
}
|
buf = (char*)&msg_chain;
|
buf = (char*)&msg_chain;
|
if(gdb_read(&buf[8],sizeof(msg_chain)-8) < 0)
|
if(gdb_read(&buf[8],sizeof(msg_chain)-8) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 7");
|
perror("gdb socket - 7");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
msg_chain.chain = htonl(msg_chain.chain);
|
msg_chain.chain = htonl(msg_chain.chain);
|
err = DebugSetChain(msg_chain.chain);
|
err = DebugSetChain(msg_chain.chain);
|
resp_chain.status = htonl(err);
|
resp_chain.status = htonl(err);
|
if(gdb_write(&resp_chain,sizeof(resp_chain)) < 0)
|
if(gdb_write(&resp_chain,sizeof(resp_chain)) < 0)
|
{
|
{
|
if(gdb_fd)
|
if(gdb_fd)
|
{
|
{
|
perror("gdb socket - 8");
|
perror("gdb socket - 8");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
return;
|
return;
|
}
|
}
|
break;
|
break;
|
default:
|
default:
|
ProtocolClean(length,JTAG_PROXY_COMMAND_NOT_IMPLEMENTED);
|
ProtocolClean(length,JTAG_PROXY_COMMAND_NOT_IMPLEMENTED);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
void ProtocolClean(int length,int32_t err)
|
void ProtocolClean(int length,int32_t err)
|
{
|
{
|
char buf[4096];
|
char buf[4096];
|
|
|
err = htonl(err);
|
err = htonl(err);
|
if((gdb_read(buf,length) < 0) ||
|
if((gdb_read(buf,length) < 0) ||
|
(gdb_write(&err,sizeof(err)) < 0) && gdb_fd)
|
(gdb_write(&err,sizeof(err)) < 0) && gdb_fd)
|
{
|
{
|
perror("gdb socket - 9");
|
perror("gdb socket - 9");
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
}
|
}
|
}
|
}
|
|
|
static int gdb_write(void* buf,int len)
|
static int gdb_write(void* buf,int len)
|
{
|
{
|
int n;
|
int n;
|
char* w_buf = (char*)buf;
|
char* w_buf = (char*)buf;
|
struct pollfd block;
|
struct pollfd block;
|
|
|
while(len)
|
while(len)
|
{
|
{
|
if((n = write(gdb_fd,w_buf,len)) < 0)
|
if((n = write(gdb_fd,w_buf,len)) < 0)
|
{
|
{
|
switch(errno)
|
switch(errno)
|
{
|
{
|
case EWOULDBLOCK: /* or EAGAIN */
|
case EWOULDBLOCK: /* or EAGAIN */
|
/* We've been called on a descriptor marked
|
/* We've been called on a descriptor marked
|
for nonblocking I/O. We better simulate
|
for nonblocking I/O. We better simulate
|
blocking behavior. */
|
blocking behavior. */
|
block.fd = gdb_fd;
|
block.fd = gdb_fd;
|
block.events = POLLOUT;
|
block.events = POLLOUT;
|
block.revents = 0;
|
block.revents = 0;
|
poll(&block,1,-1);
|
poll(&block,1,-1);
|
continue;
|
continue;
|
case EINTR:
|
case EINTR:
|
continue;
|
continue;
|
case EPIPE:
|
case EPIPE:
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
return -1;
|
return -1;
|
default:
|
default:
|
return -1;
|
return -1;
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
len -= n;
|
len -= n;
|
w_buf += n;
|
w_buf += n;
|
}
|
}
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|
static int gdb_read(void* buf,int len)
|
static int gdb_read(void* buf,int len)
|
{
|
{
|
int n;
|
int n;
|
char* r_buf = (char*)buf;
|
char* r_buf = (char*)buf;
|
struct pollfd block;
|
struct pollfd block;
|
|
|
while(len)
|
while(len)
|
{
|
{
|
if((n = read(gdb_fd,r_buf,len)) < 0)
|
if((n = read(gdb_fd,r_buf,len)) < 0)
|
{
|
{
|
switch(errno)
|
switch(errno)
|
{
|
{
|
case EWOULDBLOCK: /* or EAGAIN */
|
case EWOULDBLOCK: /* or EAGAIN */
|
/* We've been called on a descriptor marked
|
/* We've been called on a descriptor marked
|
for nonblocking I/O. We better simulate
|
for nonblocking I/O. We better simulate
|
blocking behavior. */
|
blocking behavior. */
|
block.fd = gdb_fd;
|
block.fd = gdb_fd;
|
block.events = POLLIN;
|
block.events = POLLIN;
|
block.revents = 0;
|
block.revents = 0;
|
poll(&block,1,-1);
|
poll(&block,1,-1);
|
continue;
|
continue;
|
case EINTR:
|
case EINTR:
|
continue;
|
continue;
|
default:
|
default:
|
return -1;
|
return -1;
|
}
|
}
|
}
|
}
|
else if(n == 0)
|
else if(n == 0)
|
{
|
{
|
close(gdb_fd);
|
close(gdb_fd);
|
gdb_fd = 0;
|
gdb_fd = 0;
|
return -1;
|
return -1;
|
}
|
}
|
else
|
else
|
{
|
{
|
len -= n;
|
len -= n;
|
r_buf += n;
|
r_buf += n;
|
}
|
}
|
}
|
}
|
return 0;
|
return 0;
|
}
|
}
|
|
|