FRONTPANEL: Added better protocol debug support to debug simulator startup issues
This commit is contained in:
parent
df6953bf82
commit
71fe58b33a
4 changed files with 135 additions and 64 deletions
|
@ -58,12 +58,23 @@ const char *sim_config =
|
|||
/* Registers visible on the Front Panel */
|
||||
unsigned int PC, SP, FP, AP, R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11;
|
||||
|
||||
int update_display = 1;
|
||||
|
||||
static void
|
||||
DisplayCallback (PANEL *panel, unsigned long long simulation_time, void *context)
|
||||
{
|
||||
update_display = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
DisplayRegisters (PANEL *panel)
|
||||
{
|
||||
char buf1[100], buf2[100], buf3[100];
|
||||
static const char *states[] = {"Halt", "Run "};
|
||||
|
||||
if (!update_display)
|
||||
return;
|
||||
update_display = 0;
|
||||
buf1[sizeof(buf1)-1] = buf2[sizeof(buf2)-1] = buf3[sizeof(buf3)-1] = 0;
|
||||
sprintf (buf1, "%s PC: %08X SP: %08X AP: %08X FP: %08X\r\n", states[sim_panel_get_state (panel)], PC, SP, AP, FP);
|
||||
sprintf (buf2, "R0:%08X R1:%08X R2:%08X R3:%08X R4:%08X R5:%08X\r\n", R0, R1, R2, R3, R4, R5);
|
||||
|
@ -133,8 +144,8 @@ if ((argc > 1) && ((!strcmp("-d", argv[1])) || (!strcmp("-D", argv[1])) || (!str
|
|||
if ((f = fopen (sim_config, "w"))) {
|
||||
if (debug) {
|
||||
fprintf (f, "set verbose\n");
|
||||
fprintf (f, "set debug -n -a simulator.dbg\n");
|
||||
fprintf (f, "set log debug\n");
|
||||
fprintf (f, "set log simulator.dbg\n");
|
||||
fprintf (f, "set debug -n -a log\n");
|
||||
fprintf (f, "set cpu conhalt\n");
|
||||
fprintf (f, "set remote telnet=2226\n");
|
||||
fprintf (f, "set rem-con debug=XMT;RCV\n");
|
||||
|
@ -149,7 +160,7 @@ if ((f = fopen (sim_config, "w"))) {
|
|||
fprintf (f, "set env PATH=%%PATH%%;%%ProgramFiles%%\\PuTTY;%%ProgramFiles(x86)%%\\PuTTY\n");
|
||||
fprintf (f, "! start PuTTY telnet://localhost:1927\n");
|
||||
#elif defined(__linux) || defined(__linux__)
|
||||
fprintf (f, "! xterm -e 'telnet localhost 1927' &\n");
|
||||
fprintf (f, "! nohup xterm -e 'telnet localhost 1927' &\n");
|
||||
#elif defined(__APPLE__)
|
||||
fprintf (f, "! osascript -e 'tell application \"Terminal\" to do script \"telnet localhost 1927; exit\"'\n");
|
||||
#endif
|
||||
|
@ -158,9 +169,10 @@ if ((f = fopen (sim_config, "w"))) {
|
|||
|
||||
InitDisplay();
|
||||
signal (SIGINT, halt_handler);
|
||||
panel = sim_panel_start_simulator (sim_path,
|
||||
panel = sim_panel_start_simulator_debug (sim_path,
|
||||
sim_config,
|
||||
2);
|
||||
2,
|
||||
debug? "frontpanel.dbg" : NULL);
|
||||
|
||||
if (!panel) {
|
||||
printf ("Error starting simulator: %s\n", sim_panel_get_error());
|
||||
|
@ -168,7 +180,6 @@ if (!panel) {
|
|||
}
|
||||
|
||||
if (debug) {
|
||||
sim_panel_set_debug_file (panel, "frontpanel.dbg");
|
||||
sim_panel_set_debug_mode (panel, DBG_XMT|DBG_RCV);
|
||||
}
|
||||
|
||||
|
@ -251,7 +262,6 @@ if (sim_panel_get_registers (panel, NULL)) {
|
|||
printf ("Error getting register data: %s\n", sim_panel_get_error());
|
||||
goto Done;
|
||||
}
|
||||
DisplayCallback (panel, 0ll, NULL);
|
||||
if (sim_panel_set_display_callback (panel, &DisplayCallback, NULL, 5)) {
|
||||
printf ("Error setting automatic display callback: %s\n", sim_panel_get_error());
|
||||
goto Done;
|
||||
|
@ -265,6 +275,7 @@ while (1) {
|
|||
char cmd[512];
|
||||
|
||||
while (sim_panel_get_state (panel) == Halt) {
|
||||
DisplayRegisters (panel);
|
||||
printf ("SIM> ");
|
||||
if (!fgets (cmd, sizeof(cmd)-1, stdin))
|
||||
break;
|
||||
|
@ -295,6 +306,8 @@ while (1) {
|
|||
}
|
||||
while (sim_panel_get_state (panel) == Run) {
|
||||
usleep (100);
|
||||
if (update_display)
|
||||
DisplayRegisters(panel);
|
||||
if (halt_cpu) {
|
||||
halt_cpu = 0;
|
||||
sim_panel_exec_halt (panel);
|
||||
|
|
150
sim_frontpanel.c
150
sim_frontpanel.c
|
@ -188,84 +188,98 @@ static unsigned char mantra[] = {
|
|||
TN_IAC, TN_DO, TN_BIN
|
||||
};
|
||||
|
||||
static void *
|
||||
_panel_malloc (size_t size)
|
||||
{
|
||||
void *p = malloc (size);
|
||||
|
||||
if (p == NULL)
|
||||
sim_panel_set_error ("Out of Memory");
|
||||
return p;
|
||||
}
|
||||
|
||||
static void _panel_debug (PANEL *p, int dbits, const char *fmt, const char *buf, int bufsize, ...)
|
||||
{
|
||||
if (p && p->Debug && (dbits & p->debug)) {
|
||||
int i;
|
||||
struct timespec time_now;
|
||||
va_list arglist;
|
||||
char timestamp[32];
|
||||
size_t obufsize = 10240 + 8*bufsize;
|
||||
char *obuf = (char *)_panel_malloc (obufsize);
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &time_now);
|
||||
fprintf(p->Debug, "%lld.%03d ", (long long)(time_now.tv_sec), (int)(time_now.tv_nsec/1000000));
|
||||
sprintf (timestamp, "%lld.%03d ", (long long)(time_now.tv_sec), (int)(time_now.tv_nsec/1000000));
|
||||
|
||||
va_start (arglist, bufsize);
|
||||
vfprintf (p->Debug, fmt, arglist);
|
||||
vsnprintf (obuf, obufsize - 1, fmt, arglist);
|
||||
va_end (arglist);
|
||||
|
||||
|
||||
for (i=0; i<bufsize; ++i) {
|
||||
switch ((unsigned char)buf[i]) {
|
||||
case TN_CR:
|
||||
fprintf(p->Debug, "_TN_CR_");
|
||||
sprintf (&obuf[strlen (obuf)], "_TN_CR_");
|
||||
break;
|
||||
case TN_LF:
|
||||
fprintf(p->Debug, "_TN_LF_");
|
||||
sprintf (&obuf[strlen (obuf)], "_TN_LF_");
|
||||
break;
|
||||
case TN_IAC:
|
||||
fprintf(p->Debug, "_TN_IAC_");
|
||||
sprintf (&obuf[strlen (obuf)], "_TN_IAC_");
|
||||
switch ((unsigned char)buf[i+1]) {
|
||||
case TN_IAC:
|
||||
fprintf(p->Debug, "_TN_IAC_"); ++i;
|
||||
sprintf (&obuf[strlen (obuf)], "_TN_IAC_"); ++i;
|
||||
break;
|
||||
case TN_DONT:
|
||||
fprintf(p->Debug, "_TN_DONT_"); ++i;
|
||||
sprintf (&obuf[strlen (obuf)], "_TN_DONT_"); ++i;
|
||||
break;
|
||||
case TN_DO:
|
||||
fprintf(p->Debug, "_TN_DO_"); ++i;
|
||||
sprintf (&obuf[strlen (obuf)], "_TN_DO_"); ++i;
|
||||
break;
|
||||
case TN_WONT:
|
||||
fprintf(p->Debug, "_TN_WONT_"); ++i;
|
||||
sprintf (&obuf[strlen (obuf)], "_TN_WONT_"); ++i;
|
||||
break;
|
||||
case TN_WILL:
|
||||
fprintf(p->Debug, "_TN_WILL_"); ++i;
|
||||
sprintf (&obuf[strlen (obuf)], "_TN_WILL_"); ++i;
|
||||
break;
|
||||
default:
|
||||
fprintf(p->Debug, "_0x%02X_", (unsigned char)buf[i+1]); ++i;
|
||||
sprintf (&obuf[strlen (obuf)], "_0x%02X_", (unsigned char)buf[i+1]); ++i;
|
||||
break;
|
||||
}
|
||||
switch ((unsigned char)buf[i+1]) {
|
||||
case TN_BIN:
|
||||
fprintf(p->Debug, "_TN_BIN_"); ++i;
|
||||
sprintf (&obuf[strlen (obuf)], "_TN_BIN_"); ++i;
|
||||
break;
|
||||
case TN_ECHO:
|
||||
fprintf(p->Debug, "_TN_ECHO_"); ++i;
|
||||
sprintf (&obuf[strlen (obuf)], "_TN_ECHO_"); ++i;
|
||||
break;
|
||||
case TN_SGA:
|
||||
fprintf(p->Debug, "_TN_SGA_"); ++i;
|
||||
sprintf (&obuf[strlen (obuf)], "_TN_SGA_"); ++i;
|
||||
break;
|
||||
case TN_LINE:
|
||||
fprintf(p->Debug, "_TN_LINE_"); ++i;
|
||||
sprintf (&obuf[strlen (obuf)], "_TN_LINE_"); ++i;
|
||||
break;
|
||||
default:
|
||||
fprintf(p->Debug, "_0x%02X_", (unsigned char)buf[i+1]); ++i;
|
||||
sprintf (&obuf[strlen (obuf)], "_0x%02X_", (unsigned char)buf[i+1]); ++i;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (isprint((u_char)buf[i]))
|
||||
fprintf(p->Debug, "%c", buf[i]);
|
||||
sprintf (&obuf[strlen (obuf)], "%c", buf[i]);
|
||||
else {
|
||||
fprintf(p->Debug, "_");
|
||||
sprintf (&obuf[strlen (obuf)], "_");
|
||||
if ((buf[i] >= 1) && (buf[i] <= 26))
|
||||
fprintf(p->Debug, "^%c", 'A' + buf[i] - 1);
|
||||
sprintf (&obuf[strlen (obuf)], "^%c", 'A' + buf[i] - 1);
|
||||
else
|
||||
fprintf(p->Debug, "\\%03o", (u_char)buf[i]);
|
||||
fprintf(p->Debug, "_");
|
||||
sprintf (&obuf[strlen (obuf)], "\\%03o", (u_char)buf[i]);
|
||||
sprintf (&obuf[strlen (obuf)], "_");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(p->Debug, "\n");
|
||||
fprintf(p->Debug, "%s%s\n", timestamp, obuf);
|
||||
free (obuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,16 +308,6 @@ if (panel->Debug)
|
|||
}
|
||||
|
||||
|
||||
static void *
|
||||
_panel_malloc (size_t size)
|
||||
{
|
||||
void *p = malloc (size);
|
||||
|
||||
if (p == NULL)
|
||||
sim_panel_set_error ("Out of Memory");
|
||||
return p;
|
||||
}
|
||||
|
||||
static int
|
||||
_panel_send (PANEL *p, const char *msg, int len)
|
||||
{
|
||||
|
@ -446,6 +450,15 @@ sim_panel_start_simulator (const char *sim_path,
|
|||
const char *sim_config,
|
||||
size_t device_panel_count)
|
||||
{
|
||||
return sim_panel_start_simulator_debug (sim_path, sim_config, device_panel_count, NULL);
|
||||
}
|
||||
|
||||
PANEL *
|
||||
sim_panel_start_simulator_debug (const char *sim_path,
|
||||
const char *sim_config,
|
||||
size_t device_panel_count,
|
||||
const char *debug_file)
|
||||
{
|
||||
PANEL *p = NULL;
|
||||
FILE *fIn = NULL;
|
||||
FILE *fOut = NULL;
|
||||
|
@ -528,6 +541,11 @@ fprintf (fOut, "set remote -u telnet=%s\n", hostport);
|
|||
fprintf (fOut, "set remote master\n");
|
||||
fclose (fOut);
|
||||
fOut = NULL;
|
||||
if (debug_file) {
|
||||
sim_panel_set_debug_file (p, debug_file);
|
||||
sim_panel_set_debug_mode (p, DBG_XMT|DBG_RCV);
|
||||
_panel_debug (p, DBG_XMT|DBG_RCV, "Creating Simulator Process %s\n", NULL, 0, sim_path);
|
||||
}
|
||||
if (1) {
|
||||
#if defined(_WIN32)
|
||||
char cmd[2048];
|
||||
|
@ -554,6 +572,7 @@ if (1) {
|
|||
p->pidProcess = fork();
|
||||
if (p->pidProcess == 0) {
|
||||
close (0); close (1); close (2); /* make sure not to pass the open standard handles */
|
||||
dup (dup (open ("/dev/null", O_RDWR))); /* open standard handles to /dev/null */
|
||||
if (execlp (sim_path, sim_path, p->temp_config, NULL, NULL)) {
|
||||
perror ("execl");
|
||||
exit(errno);
|
||||
|
@ -574,17 +593,25 @@ for (i=0; i<100; i++) { /* Allow up to 10 seconds waiting for simulator
|
|||
break;
|
||||
}
|
||||
if (p->sock == INVALID_SOCKET) {
|
||||
if (stat (sim_path, &statb) < 0)
|
||||
sim_panel_set_error ("Can't stat simulator '%s': %s", sim_path, strerror(errno));
|
||||
else
|
||||
sim_panel_set_error ("Can't connect to simulator Remote Console on port %s", hostport);
|
||||
goto Error_Return;
|
||||
}
|
||||
strcpy (p->hostport, hostport);
|
||||
if (1) {
|
||||
pthread_attr_t attr;
|
||||
|
||||
_panel_debug (p, DBG_XMT|DBG_RCV, "Connected to simulator at %s after %dms\n", NULL, 0, hostport, i*100);
|
||||
pthread_mutex_init (&p->io_lock, NULL);
|
||||
pthread_mutex_init (&p->io_send_lock, NULL);
|
||||
pthread_cond_init (&p->io_done, NULL);
|
||||
pthread_cond_init (&p->startup_cond, NULL);
|
||||
if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
|
||||
sim_panel_set_error ("Error sending Telnet mantra (options): %s", sim_get_err_sock ("send"));
|
||||
goto Error_Return;
|
||||
}
|
||||
if (1) {
|
||||
pthread_attr_t attr;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
||||
pthread_mutex_lock (&p->io_lock);
|
||||
|
@ -595,10 +622,6 @@ if (1) {
|
|||
pthread_mutex_unlock (&p->io_lock);
|
||||
pthread_cond_destroy (&p->startup_cond);
|
||||
}
|
||||
if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
|
||||
sim_panel_set_error ("Error sending Telnet mantra (options): %s", sim_get_err_sock ("send"));
|
||||
goto Error_Return;
|
||||
}
|
||||
if (device_panel_count) {
|
||||
p->devices = (PANEL **)_panel_malloc (device_panel_count*sizeof(*p->devices));
|
||||
if (p->devices == NULL)
|
||||
|
@ -606,8 +629,7 @@ if (device_panel_count) {
|
|||
memset (p->devices, 0, device_panel_count*sizeof(*p->devices));
|
||||
p->device_count = device_panel_count;
|
||||
}
|
||||
msleep (1000);
|
||||
/* Validate existence of requested register */
|
||||
/* Validate sim_frontpanel API version */
|
||||
if (_panel_sendf (p, 1, &p->simulator_version, "SHOW VERSION\r")) {
|
||||
goto Error_Return;
|
||||
}
|
||||
|
@ -634,7 +656,15 @@ if (fOut) {
|
|||
}
|
||||
if (buf)
|
||||
free (buf);
|
||||
if (1) {
|
||||
const char *err = sim_panel_get_error();
|
||||
char *errbuf = (char *)_panel_malloc (1 + strlen (err));
|
||||
|
||||
strcpy (errbuf, err); /* preserve error info while closing */
|
||||
sim_panel_destroy (p);
|
||||
sim_panel_set_error ("%s", errbuf);
|
||||
free (errbuf);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -666,7 +696,7 @@ if (p->device_name == NULL)
|
|||
strcpy (p->device_name, device_name);
|
||||
p->parent = simulator_panel;
|
||||
p->sock = INVALID_SOCKET;
|
||||
for (i=0; i<5; i++) {
|
||||
for (i=0; i<100; i++) {
|
||||
p->sock = sim_connect_sock_ex (NULL, simulator_panel->hostport, NULL, NULL, SIM_SOCK_OPT_NODELAY | SIM_SOCK_OPT_BLOCKING);
|
||||
if (p->sock == INVALID_SOCKET)
|
||||
msleep (100);
|
||||
|
@ -678,13 +708,17 @@ if (p->sock == INVALID_SOCKET) {
|
|||
goto Error_Return;
|
||||
}
|
||||
strcpy (p->hostport, simulator_panel->hostport);
|
||||
if (1) {
|
||||
pthread_attr_t attr;
|
||||
|
||||
pthread_mutex_init (&p->io_lock, NULL);
|
||||
pthread_mutex_init (&p->io_send_lock, NULL);
|
||||
pthread_cond_init (&p->io_done, NULL);
|
||||
pthread_cond_init (&p->startup_cond, NULL);
|
||||
if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
|
||||
sim_panel_set_error ("Error sending Telnet mantra (options): %s", sim_get_err_sock ("send"));
|
||||
goto Error_Return;
|
||||
}
|
||||
if (1) {
|
||||
pthread_attr_t attr;
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
||||
pthread_mutex_lock (&p->io_lock);
|
||||
|
@ -695,10 +729,6 @@ if (1) {
|
|||
pthread_mutex_unlock (&p->io_lock);
|
||||
pthread_cond_destroy (&p->startup_cond);
|
||||
}
|
||||
if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
|
||||
sim_panel_set_error ("Error sending Telnet mantra (options): %s", sim_get_err_sock ("send"));
|
||||
goto Error_Return;
|
||||
}
|
||||
simulator_panel->devices[device_num] = p;
|
||||
_panel_register_panel (p);
|
||||
return p;
|
||||
|
@ -1069,6 +1099,28 @@ pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority);
|
|||
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
|
||||
|
||||
pthread_mutex_lock (&p->io_lock);
|
||||
if (!p->parent) {
|
||||
while (1) {
|
||||
int new_data = sim_read_sock (p->sock, &buf[buf_data], sizeof(buf)-(buf_data+1));
|
||||
|
||||
if (new_data <= 0) {
|
||||
sim_panel_set_error ("%s", sim_get_err_sock("Unexpected socket read"));
|
||||
_panel_debug (p, DBG_RCV, "%s", NULL, 0, sim_panel_get_error());
|
||||
p->State = Error;
|
||||
break;
|
||||
}
|
||||
_panel_debug (p, DBG_RCV, "Startup receive of %d bytes: ", &buf[buf_data], new_data, new_data);
|
||||
buf_data += new_data;
|
||||
buf[buf_data] = '\0';
|
||||
if ((size_t)buf_data < strlen (sim_prompt))
|
||||
continue;
|
||||
if (!strcmp (sim_prompt, &buf[buf_data - strlen (sim_prompt)])) {
|
||||
memmove (buf, &buf[buf_data - strlen (sim_prompt)], strlen (sim_prompt) + 1);
|
||||
buf_data = strlen (sim_prompt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
p->io_thread_running = 1;
|
||||
pthread_cond_signal (&p->startup_cond); /* Signal we're ready to go */
|
||||
while ((p->sock != INVALID_SOCKET) &&
|
||||
|
|
|
@ -82,6 +82,12 @@ sim_panel_start_simulator (const char *sim_path,
|
|||
const char *sim_config,
|
||||
size_t device_panel_count);
|
||||
|
||||
PANEL *
|
||||
sim_panel_start_simulator_debug (const char *sim_path,
|
||||
const char *sim_config,
|
||||
size_t device_panel_count,
|
||||
const char *debug_file);
|
||||
|
||||
/**
|
||||
|
||||
sim_panel_add_device_panel - creates a sub panel associated
|
||||
|
|
|
@ -3906,7 +3906,7 @@ while (1) { /* format passed string, arg
|
|||
/* Output the formatted data expanding newlines where they exist */
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
if ('\n' == buf[i]) {
|
||||
if (('\n' == buf[i]) && ((i == 0) || ('\r' != buf[i-1]))) {
|
||||
while (SCPE_STALL == tmxr_putc_ln (lp, '\r'))
|
||||
if (lp->txbsz == tmxr_send_buffered_data (lp))
|
||||
sim_os_ms_sleep (10);
|
||||
|
|
Loading…
Add table
Reference in a new issue