FRONTPANEL: Added better protocol debug support to debug simulator startup issues

This commit is contained in:
Mark Pizzolato 2015-02-26 11:28:08 -08:00
parent df6953bf82
commit 71fe58b33a
4 changed files with 135 additions and 64 deletions

View file

@ -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,
sim_config,
2);
panel = sim_panel_start_simulator_debug (sim_path,
sim_config,
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);

View file

@ -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];
@ -553,7 +571,8 @@ if (1) {
#else
p->pidProcess = fork();
if (p->pidProcess == 0) {
close (0); close (1); close (2); /* make sure not to pass the open standard handles */
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) {
sim_panel_set_error ("Can't connect to simulator Remote Console on port %s", hostport);
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);
_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_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);
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);
sim_panel_destroy (p);
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);
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_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);
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) &&

View file

@ -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

View file

@ -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);