FRONTPANEL: General Enhancements

- added verification of the existence of simulator registers which they are referenced.
- sim_frontpanel API version checking to make sure that the invoking API and the simulator support the same capabilities.
- added the ability for a simulator to reference data in simh register data which is not in the set of registers defined in the default simh device (usually the CPU).
- added a simulator time reference relating to a set of register data which is provided.
- added example automatically creating a console terminal port from a simulator startup (front panel or not).
This commit is contained in:
Mark Pizzolato 2015-02-24 19:49:09 -08:00
parent 26ef9b566a
commit 059a54152a
4 changed files with 272 additions and 81 deletions

View file

@ -59,7 +59,7 @@ const char *sim_config =
unsigned int PC, SP, FP, AP, R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11; unsigned int PC, SP, FP, AP, R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11;
static void static void
DisplayCallback (PANEL *panel, void *context) DisplayCallback (PANEL *panel, unsigned long long simulation_time, void *context)
{ {
char buf1[100], buf2[100], buf3[100]; char buf1[100], buf2[100], buf3[100];
static const char *states[] = {"Halt", "Run "}; static const char *states[] = {"Halt", "Run "};
@ -139,6 +139,15 @@ if ((f = fopen (sim_config, "w"))) {
fprintf (f, "set cpu 64\n"); fprintf (f, "set cpu 64\n");
fprintf (f, "set console telnet=buffered\n"); fprintf (f, "set console telnet=buffered\n");
fprintf (f, "set console telnet=1927\n"); fprintf (f, "set console telnet=1927\n");
/* Start a terminal emulator for the console port */
#if defined(_WIN32)
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");
#elif defined(__APPLE__)
fprintf (f, "! osascript -e 'tell application \"Terminal\" to do script \"telnet localhost 1927; exit\"'\n");
#endif
fclose (f); fclose (f);
} }
@ -165,80 +174,84 @@ if (!tape) {
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "PC", sizeof(PC), &PC)) { if (!sim_panel_add_register (panel, "ZPC", NULL, sizeof(PC), &PC)) {
printf ("Unexpecdted success adding non-existent register 'ZPC'\n");
goto Done;
}
if (sim_panel_add_register (panel, "PC", NULL, sizeof(PC), &PC)) {
printf ("Error adding register 'PC': %s\n", sim_panel_get_error()); printf ("Error adding register 'PC': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "SP", sizeof(SP), &SP)) { if (sim_panel_add_register (panel, "SP", NULL, sizeof(SP), &SP)) {
printf ("Error adding register 'SP': %s\n", sim_panel_get_error()); printf ("Error adding register 'SP': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "FP", sizeof(FP), &FP)) { if (sim_panel_add_register (panel, "FP", "CPU", sizeof(FP), &FP)) {
printf ("Error adding register 'FP': %s\n", sim_panel_get_error()); printf ("Error adding register 'FP': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "AP", sizeof(SP), &AP)) { if (sim_panel_add_register (panel, "AP", NULL, sizeof(SP), &AP)) {
printf ("Error adding register 'AP': %s\n", sim_panel_get_error()); printf ("Error adding register 'AP': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "R0", sizeof(R0), &R0)) { if (sim_panel_add_register (panel, "R0", NULL, sizeof(R0), &R0)) {
printf ("Error adding register 'R0': %s\n", sim_panel_get_error()); printf ("Error adding register 'R0': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "R1", sizeof(R1), &R1)) { if (sim_panel_add_register (panel, "R1", NULL, sizeof(R1), &R1)) {
printf ("Error adding register 'R1': %s\n", sim_panel_get_error()); printf ("Error adding register 'R1': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "R2", sizeof(R2), &R2)) { if (sim_panel_add_register (panel, "R2", NULL, sizeof(R2), &R2)) {
printf ("Error adding register 'R2': %s\n", sim_panel_get_error()); printf ("Error adding register 'R2': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "R3", sizeof(R3), &R3)) { if (sim_panel_add_register (panel, "R3", NULL, sizeof(R3), &R3)) {
printf ("Error adding register 'R3': %s\n", sim_panel_get_error()); printf ("Error adding register 'R3': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "R4", sizeof(R4), &R4)) { if (sim_panel_add_register (panel, "R4", NULL, sizeof(R4), &R4)) {
printf ("Error adding register 'R4': %s\n", sim_panel_get_error()); printf ("Error adding register 'R4': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "R5", sizeof(R5), &R5)) { if (sim_panel_add_register (panel, "R5", NULL, sizeof(R5), &R5)) {
printf ("Error adding register 'R5': %s\n", sim_panel_get_error()); printf ("Error adding register 'R5': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "R6", sizeof(R6), &R6)) { if (sim_panel_add_register (panel, "R6", NULL, sizeof(R6), &R6)) {
printf ("Error adding register 'R6': %s\n", sim_panel_get_error()); printf ("Error adding register 'R6': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "R7", sizeof(R7), &R7)) { if (sim_panel_add_register (panel, "R7", NULL, sizeof(R7), &R7)) {
printf ("Error adding register 'R7': %s\n", sim_panel_get_error()); printf ("Error adding register 'R7': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "R8", sizeof(R8), &R8)) { if (sim_panel_add_register (panel, "R8", NULL, sizeof(R8), &R8)) {
printf ("Error adding register 'R8': %s\n", sim_panel_get_error()); printf ("Error adding register 'R8': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "R9", sizeof(R9), &R9)) { if (sim_panel_add_register (panel, "R9", NULL, sizeof(R9), &R9)) {
printf ("Error adding register 'R9': %s\n", sim_panel_get_error()); printf ("Error adding register 'R9': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "R10", sizeof(R10), &R10)) { if (sim_panel_add_register (panel, "R10", NULL, sizeof(R10), &R10)) {
printf ("Error adding register 'R10': %s\n", sim_panel_get_error()); printf ("Error adding register 'R10': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_add_register (panel, "R11", sizeof(R11), &R11)) { if (sim_panel_add_register (panel, "R11", NULL, sizeof(R11), &R11)) {
printf ("Error adding register 'R11': %s\n", sim_panel_get_error()); printf ("Error adding register 'R11': %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (sim_panel_get_registers (panel)) { if (sim_panel_get_registers (panel, NULL)) {
printf ("Error getting register data: %s\n", sim_panel_get_error()); printf ("Error getting register data: %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
DisplayCallback (panel, NULL); DisplayCallback (panel, 0ll, NULL);
if (sim_panel_set_display_callback (panel, &DisplayCallback, NULL, 5)) { if (sim_panel_set_display_callback (panel, &DisplayCallback, NULL, 5)) {
printf ("Error setting automatic display callback: %s\n", sim_panel_get_error()); printf ("Error setting automatic display callback: %s\n", sim_panel_get_error());
goto Done; goto Done;
} }
if (!sim_panel_get_registers (panel)) { if (!sim_panel_get_registers (panel, NULL)) {
printf ("Unexpected success getting register data: %s\n", sim_panel_get_error()); printf ("Unexpected success getting register data: %s\n", sim_panel_get_error());
goto Done; goto Done;
} }

6
scp.c
View file

@ -225,6 +225,7 @@
#include "sim_video.h" #include "sim_video.h"
#endif #endif
#include "sim_sock.h" #include "sim_sock.h"
#include "sim_frontpanel.h"
#include <signal.h> #include <signal.h>
#include <ctype.h> #include <ctype.h>
#include <time.h> #include <time.h>
@ -4246,6 +4247,9 @@ if (flag) {
#endif #endif
#if defined (SIM_ASYNCH_CLOCKS) #if defined (SIM_ASYNCH_CLOCKS)
fprintf (st, "\n\t\tAsynchronous Clock support"); fprintf (st, "\n\t\tAsynchronous Clock support");
#endif
#if defined (SIM_FRONTPANEL_VERSION)
fprintf (st, "\n\t\tFrontPanel API Version %d", SIM_FRONTPANEL_VERSION);
#endif #endif
fprintf (st, "\n\tHost Platform:"); fprintf (st, "\n\tHost Platform:");
#if defined (__GNUC__) && defined (__VERSION__) #if defined (__GNUC__) && defined (__VERSION__)
@ -4418,7 +4422,7 @@ t_stat show_time (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
{ {
if (cptr && (*cptr != 0)) if (cptr && (*cptr != 0))
return SCPE_2MARG; return SCPE_2MARG;
fprintf (st, "Time:\t%.0f\n", sim_time); fprintf (st, "Time:\t%.0f\n", sim_gtime());
return SCPE_OK; return SCPE_OK;
} }

View file

@ -108,24 +108,27 @@ return 0;
typedef struct { typedef struct {
char *name; char *name;
char *device_name;
void *addr; void *addr;
size_t size; size_t size;
} REG; } REG;
struct PANEL { struct PANEL {
PANEL *parent; /* Device Panels can have parent panels */ PANEL *parent; /* Device Panels can have parent panels */
char *name; /* simulator path or device name */ char *path; /* simulator path */
char *config; char *config;
char *device_name; /* device name */
char *temp_config; char *temp_config;
char hostport[64]; char hostport[64];
size_t device_count; size_t device_count;
PANEL **devices; PANEL **devices;
SOCKET sock; SOCKET sock;
int reg_count; size_t reg_count;
REG *regs; REG *regs;
char *reg_query; char *reg_query;
size_t reg_query_size; size_t reg_query_size;
OperationalState State; OperationalState State;
unsigned long long simulation_time;
pthread_mutex_t lock; pthread_mutex_t lock;
pthread_t io_thread; pthread_t io_thread;
int io_thread_running; int io_thread_running;
@ -133,6 +136,9 @@ struct PANEL {
pthread_mutex_t io_send_lock; pthread_mutex_t io_send_lock;
int io_reg_query_pending; int io_reg_query_pending;
int io_waiting; int io_waiting;
char *io_response;
size_t io_response_data;
size_t io_response_size;
pthread_cond_t io_done; pthread_cond_t io_done;
pthread_cond_t startup_cond; pthread_cond_t startup_cond;
PANEL_DISPLAY_PCALLBACK callback; PANEL_DISPLAY_PCALLBACK callback;
@ -141,6 +147,7 @@ struct PANEL {
void *callback_context; void *callback_context;
int callbacks_per_second; int callbacks_per_second;
int debug; int debug;
char *simulator_version;
FILE *Debug; FILE *Debug;
#if defined(_WIN32) #if defined(_WIN32)
HANDLE hProcess; HANDLE hProcess;
@ -150,7 +157,9 @@ struct PANEL {
}; };
static const char *sim_prompt = "sim> "; static const char *sim_prompt = "sim> ";
static const char *register_get_prefix = "show time";
static const char *register_get_echo = "# REGISTERS-DONE"; static const char *register_get_echo = "# REGISTERS-DONE";
static const char *register_dev_echo = "# REGISTERS-FOR-DEVICE:";
static const char *command_done_echo = "# COMMAND-DONE"; static const char *command_done_echo = "# COMMAND-DONE";
static int little_endian; static int little_endian;
static void *_panel_reader(void *arg); static void *_panel_reader(void *arg);
@ -324,17 +333,18 @@ return sent;
} }
static int static int
_panel_sendf (PANEL *p, int wait_for_completion, const char *fmt, ...); _panel_sendf (PANEL *p, int wait_for_completion, char **response, const char *fmt, ...);
static int static int
_panel_register_query_string (PANEL *panel, char **buf, size_t *buf_size) _panel_register_query_string (PANEL *panel, char **buf, size_t *buf_size)
{ {
int i; size_t i, j, buf_data, buf_needed = 0;
size_t buf_data, buf_needed = 0; char *dev;
pthread_mutex_lock (&panel->io_lock); pthread_mutex_lock (&panel->io_lock);
buf_needed = 2 + strlen (register_get_prefix); /* SHOW TIME */
for (i=0; i<panel->reg_count; i++) for (i=0; i<panel->reg_count; i++)
buf_needed += 7 + strlen (panel->regs[i].name); buf_needed += 9 + strlen (panel->regs[i].name) + (panel->regs[i].device_name ? strlen (panel->regs[i].device_name) : 0);
buf_needed += 10 + strlen (register_get_echo); /* # REGISTERS-DONE */ buf_needed += 10 + strlen (register_get_echo); /* # REGISTERS-DONE */
if (buf_needed > *buf_size) { if (buf_needed > *buf_size) {
free (*buf); free (*buf);
@ -347,21 +357,40 @@ if (buf_needed > *buf_size) {
*buf_size = buf_needed; *buf_size = buf_needed;
} }
buf_data = 0; buf_data = 0;
#if SEPARATE_REGISTERS sprintf (*buf + buf_data, "%s\r", register_get_prefix);
for (i=0; i<panel->reg_count; i++) {
sprintf (*buf + buf_data, "E -H %s\r", panel->regs[i].name);
buf_data += strlen (*buf + buf_data); buf_data += strlen (*buf + buf_data);
dev = "";
for (i=j=0; i<panel->reg_count; i++) {
char *reg_dev = panel->regs[i].device_name ? panel->regs[i].device_name : "";
if (strcmp (dev, reg_dev)) {/* devices are different */
char *tbuf;
buf_needed += 4 + strlen (register_dev_echo) + strlen (reg_dev); /* # REGISTERS-for-DEVICE:XXX */
tbuf = (char *)_panel_malloc (buf_needed);
if (tbuf == NULL) {
panel->State = Error;
pthread_mutex_unlock (&panel->io_lock);
return -1;
} }
#else strcpy (tbuf, *buf);
sprintf (*buf + buf_data, "E -H "); free (*buf);
*buf = tbuf;
sprintf (*buf + buf_data, "%s%s%s\r", (i == 0)? "" : "\r", register_dev_echo, reg_dev);
buf_data += strlen (*buf + buf_data); buf_data += strlen (*buf + buf_data);
for (i=0; i<panel->reg_count; i++) { dev = reg_dev;
sprintf (*buf + buf_data, "%s%s", (i>0) ? "," : "", panel->regs[i].name); j = 0;
*buf_size = buf_needed;
}
if (j == 0)
sprintf (*buf + buf_data, "E -H %s %s", dev, panel->regs[i].name);
else
sprintf (*buf + buf_data, ",%s", panel->regs[i].name);
++j;
buf_data += strlen (*buf + buf_data); buf_data += strlen (*buf + buf_data);
} }
strcpy (*buf + buf_data, "\r"); strcpy (*buf + buf_data, "\r");
buf_data += strlen (*buf + buf_data); buf_data += strlen (*buf + buf_data);
#endif
strcpy (*buf + buf_data, register_get_echo); strcpy (*buf + buf_data, register_get_echo);
buf_data += strlen (*buf + buf_data); buf_data += strlen (*buf + buf_data);
strcpy (*buf + buf_data, "\r"); strcpy (*buf + buf_data, "\r");
@ -461,10 +490,10 @@ if (p == NULL)
goto Error_Return; goto Error_Return;
memset (p, 0, sizeof(*p)); memset (p, 0, sizeof(*p));
p->sock = INVALID_SOCKET; p->sock = INVALID_SOCKET;
p->name = (char *)_panel_malloc (strlen (sim_path) + 1); p->path = (char *)_panel_malloc (strlen (sim_path) + 1);
if (p->name == NULL) if (p->path == NULL)
goto Error_Return; goto Error_Return;
strcpy (p->name, sim_path); strcpy (p->path, sim_path);
p->config = (char *)_panel_malloc (strlen (sim_config) + 1); p->config = (char *)_panel_malloc (strlen (sim_config) + 1);
if (p->config == NULL) if (p->config == NULL)
goto Error_Return; goto Error_Return;
@ -577,6 +606,22 @@ if (device_panel_count) {
memset (p->devices, 0, device_panel_count*sizeof(*p->devices)); memset (p->devices, 0, device_panel_count*sizeof(*p->devices));
p->device_count = device_panel_count; p->device_count = device_panel_count;
} }
msleep (1000);
/* Validate existence of requested register */
if (_panel_sendf (p, 1, &p->simulator_version, "SHOW VERSION\r")) {
goto Error_Return;
}
if (1) {
int api_version = 0;
char *c = strstr (p->simulator_version, "FrontPanel API Version");
if ((!c) ||
(1 != sscanf (c, "FrontPanel API Version %d", &api_version)) ||
(api_version != SIM_FRONTPANEL_VERSION)) {
sim_panel_set_error ("Inconsistent sim_frontpanel API version %d in simulator. Version %d needed.-", api_version, SIM_FRONTPANEL_VERSION);
goto Error_Return;
}
}
_panel_register_panel (p); _panel_register_panel (p);
return p; return p;
@ -608,13 +653,17 @@ for (device_num=0; device_num < simulator_panel->device_count; ++device_num)
if (simulator_panel->devices[device_num] == NULL) if (simulator_panel->devices[device_num] == NULL)
break; break;
if (device_num == simulator_panel->device_count) { if (device_num == simulator_panel->device_count) {
sim_panel_set_error ("No free panel devices slots available %s simulator. All %d slots are used.", simulator_panel->name, (int)simulator_panel->device_count); sim_panel_set_error ("No free panel devices slots available %s simulator. All %d slots are used.", simulator_panel->path, (int)simulator_panel->device_count);
return NULL; return NULL;
} }
p = (PANEL *)_panel_malloc (sizeof(*p)); p = (PANEL *)_panel_malloc (sizeof(*p));
if (p == NULL) if (p == NULL)
goto Error_Return; goto Error_Return;
memset (p, 0, sizeof(*p)); memset (p, 0, sizeof(*p));
p->device_name = (char *)_panel_malloc (1 + strlen (device_name));
if (p->device_name == NULL)
goto Error_Return;
strcpy (p->device_name, device_name);
p->parent = simulator_panel; p->parent = simulator_panel;
p->sock = INVALID_SOCKET; p->sock = INVALID_SOCKET;
for (i=0; i<5; i++) { for (i=0; i<5; i++) {
@ -665,7 +714,7 @@ sim_panel_destroy (PANEL *panel)
REG *reg; REG *reg;
if (panel) { if (panel) {
_panel_debug (panel, DBG_XMT|DBG_RCV, "Closing Panel %s\n", NULL, 0, panel->name); _panel_debug (panel, DBG_XMT|DBG_RCV, "Closing Panel %s\n", NULL, 0, panel->device_name? panel->device_name : panel->path);
if (panel->devices) { if (panel->devices) {
size_t i; size_t i;
@ -678,7 +727,8 @@ if (panel) {
} }
_panel_deregister_panel (panel); _panel_deregister_panel (panel);
free (panel->name); free (panel->path);
free (panel->device_name);
free (panel->config); free (panel->config);
if (panel->sock != INVALID_SOCKET) { if (panel->sock != INVALID_SOCKET) {
SOCKET sock = panel->sock; SOCKET sock = panel->sock;
@ -724,10 +774,13 @@ if (panel) {
reg = panel->regs; reg = panel->regs;
while (panel->reg_count--) { while (panel->reg_count--) {
free (reg->name); free (reg->name);
free (reg->device_name);
reg++; reg++;
} }
free (panel->regs); free (panel->regs);
free (panel->reg_query); free (panel->reg_query);
free (panel->io_response);
free (panel->simulator_version);
sim_cleanup_sock (); sim_cleanup_sock ();
free (panel); free (panel);
} }
@ -745,10 +798,13 @@ return panel->State;
int int
sim_panel_add_register (PANEL *panel, sim_panel_add_register (PANEL *panel,
const char *name, const char *name,
const char *device_name,
size_t size, size_t size,
void *addr) void *addr)
{ {
REG *regs, *reg; REG *regs, *reg;
char *response = NULL;
size_t i;
if (!panel || (panel->State == Error)) { if (!panel || (panel->State == Error)) {
sim_panel_set_error ("Invalid Panel"); sim_panel_set_error ("Invalid Panel");
@ -770,8 +826,71 @@ if (reg->name == NULL) {
return -1; return -1;
} }
strcpy (reg->name, name); strcpy (reg->name, name);
for (i=0; i<strlen (reg->name); i++) {
if (islower (reg->name[i]))
reg->name[i] = toupper (reg->name[i]);
}
if (device_name) {
reg->device_name = (char *)_panel_malloc (1 + strlen (device_name));
if (reg->device_name == NULL) {
free (reg->name);
panel->State = Error;
free (regs);
return -1;
}
strcpy (reg->device_name, device_name);
for (i=0; i<strlen (reg->device_name); i++) {
if (islower (reg->device_name[i]))
reg->device_name[i] = toupper (reg->device_name[i]);
}
}
for (i=0; i<panel->reg_count; i++) {
char *t1 = (char *)_panel_malloc (2 + strlen (regs[i].name) + (regs[i].device_name? strlen (regs[i].device_name) : 0));
char *t2 = (char *)_panel_malloc (2 + strlen (reg->name) + (reg->device_name? strlen (reg->device_name) : 0));
if ((t1 == NULL) || (t2 == NULL)) {
free (t1);
free (t2);
free (reg->name);
free (reg->device_name);
panel->State = Error;
free (regs);
return -1;
}
sprintf (t1, "%s %s", regs[i].device_name ? regs[i].device_name : "", regs[i].name);
sprintf (t2, "%s %s", reg->device_name ? reg->device_name : "", reg->name);
if (!strcmp (t1, t2)) {
sim_panel_set_error ("Duplicate Register Declaration");
free (t1);
free (t2);
free (reg->name);
free (reg->device_name);
free (regs);
return -1;
}
free (t1);
free (t2);
}
reg->addr = addr; reg->addr = addr;
reg->size = size; reg->size = size;
pthread_mutex_unlock (&panel->io_lock);
/* Validate existence of requested register */
if (_panel_sendf (panel, 1, &response, "EXAMINE %s %s\r", device_name? device_name : "", name)) {
free (reg->name);
free (reg->device_name);
free (regs);
return -1;
}
if (!strcmp ("Invalid argument\r\n", response)) {
sim_panel_set_error ("Invalid Register: %s %s", device_name? device_name : "", name);
free (response);
free (reg->name);
free (reg->device_name);
free (regs);
return -1;
}
free (response);
pthread_mutex_lock (&panel->io_lock);
++panel->reg_count; ++panel->reg_count;
free (panel->regs); free (panel->regs);
panel->regs = regs; panel->regs = regs;
@ -783,7 +902,7 @@ return 0;
} }
int int
sim_panel_get_registers (PANEL *panel) sim_panel_get_registers (PANEL *panel, unsigned long long *simulation_time)
{ {
if ((!panel) || (panel->State == Error)) { if ((!panel) || (panel->State == Error)) {
sim_panel_set_error ("Invalid Panel"); sim_panel_set_error ("Invalid Panel");
@ -806,6 +925,8 @@ if (panel->reg_query_size != _panel_send (panel, panel->reg_query, panel->reg_qu
panel->io_waiting = 1; panel->io_waiting = 1;
while (panel->io_waiting) while (panel->io_waiting)
pthread_cond_wait (&panel->io_done, &panel->io_lock); pthread_cond_wait (&panel->io_done, &panel->io_lock);
if (simulation_time)
*simulation_time = panel->simulation_time;
pthread_mutex_unlock (&panel->io_lock); pthread_mutex_unlock (&panel->io_lock);
return 0; return 0;
} }
@ -871,7 +992,7 @@ if (panel->State == Run) {
sim_panel_set_error ("Not Halted"); sim_panel_set_error ("Not Halted");
return -1; return -1;
} }
if (_panel_sendf (panel, 0, "BOOT %s\r", device)) if (_panel_sendf (panel, 0, NULL, "BOOT %s\r", device))
return -1; return -1;
panel->State = Run; panel->State = Run;
return 0; return 0;
@ -888,7 +1009,7 @@ if (panel->State == Run) {
sim_panel_set_error ("Not Halted"); sim_panel_set_error ("Not Halted");
return -1; return -1;
} }
if (_panel_sendf (panel, 0, "CONT\r", 5)) if (_panel_sendf (panel, 0, NULL, "CONT\r", 5))
return -1; return -1;
panel->State = Run; panel->State = Run;
return 0; return 0;
@ -925,7 +1046,7 @@ if (panel->callback) {
sim_panel_set_error ("Callback provides register data"); sim_panel_set_error ("Callback provides register data");
return -1; return -1;
} }
if (_panel_sendf (panel, 1, "D %s %s", name, value)) if (_panel_sendf (panel, 1, NULL, "DEPOSIT %s %s", name, value))
return -1; return -1;
return 0; return 0;
} }
@ -972,9 +1093,16 @@ while ((p->sock != INVALID_SOCKET) &&
*eol++ = '\0'; *eol++ = '\0';
e = strchr (s, ':'); e = strchr (s, ':');
if (e) { if (e) {
int i; size_t i;
*e++ = '\0'; *e++ = '\0';
if (!strcmp("Time", s)) {
p->simulation_time = strtoull (e, NULL, 10);
s = eol;
while (isspace(0xFF & (*s)))
++s;
continue;
}
for (i=0; i<p->reg_count; i++) { for (i=0; i<p->reg_count; i++) {
if (!strcmp(p->regs[i].name, s)) { if (!strcmp(p->regs[i].name, s)) {
unsigned long long data; unsigned long long data;
@ -987,17 +1115,22 @@ while ((p->sock != INVALID_SOCKET) &&
break; break;
} }
} }
if (i == p->reg_count) { if (i != p->reg_count) {
/* Unexpected Register Data Found */ s = eol;
while (isspace(0xFF & (*s)))
++s;
continue;
} }
--e;
*e = ':';
/* Unexpected Register Data Found (or other output containing a : character) */
} }
else {
if (!strcmp (s + strlen (sim_prompt), register_get_echo)) { if (!strcmp (s + strlen (sim_prompt), register_get_echo)) {
pthread_mutex_lock (&p->io_lock); pthread_mutex_lock (&p->io_lock);
--p->io_reg_query_pending; --p->io_reg_query_pending;
if (p->callback) { if (p->callback) {
pthread_mutex_unlock (&p->io_lock); pthread_mutex_unlock (&p->io_lock);
p->callback (p, p->callback_context); p->callback (p, p->simulation_time, p->callback_context);
} }
else { else {
p->io_waiting = 0; p->io_waiting = 0;
@ -1006,19 +1139,37 @@ while ((p->sock != INVALID_SOCKET) &&
} }
} }
else { else {
if (!strcmp (s + strlen (sim_prompt), command_done_echo)) {
pthread_mutex_lock (&p->io_lock); pthread_mutex_lock (&p->io_lock);
if (!strcmp (s + strlen (sim_prompt), command_done_echo)) {
p->io_waiting = 0; p->io_waiting = 0;
pthread_cond_signal (&p->io_done); pthread_cond_signal (&p->io_done);
pthread_mutex_unlock (&p->io_lock);
} }
else { else {
/* Non Register Data Found (echo of EXAMINE or other commands) */ /* Non Register Data Found (echo of EXAMINE or other commands and/or command output) */
if (p->io_waiting) {
char *t;
if (p->io_response_data + strlen (s) + 2 > p->io_response_size) {
t = (char *)_panel_malloc (p->io_response_data + strlen (s) + 3);
if (t == NULL) {
_panel_debug (p, DBG_RCV, "%s", NULL, 0, sim_panel_get_error());
p->State = Error;
pthread_mutex_unlock (&p->io_lock);
break;
}
memcpy (t, p->io_response, p->io_response_data);
free (p->io_response);
p->io_response = t;
p->io_response_size = p->io_response_data + strlen (s) + 3;
}
strcpy (p->io_response + p->io_response_data, s);
strcat (p->io_response, "\r\n");
p->io_response_data += strlen(s) + 2;
} }
} }
pthread_mutex_unlock (&p->io_lock);
} }
s = eol; s = eol;
while (isspace(*s)) while (isspace(0xFF & (*s)))
++s; ++s;
} }
pthread_mutex_lock (&p->io_lock); pthread_mutex_lock (&p->io_lock);
@ -1157,7 +1308,7 @@ return;
} }
static int static int
_panel_sendf (PANEL *p, int wait_for_completion, const char *fmt, ...) _panel_sendf (PANEL *p, int wait_for_completion, char **response, const char *fmt, ...)
{ {
char stackbuf[1024]; char stackbuf[1024];
int bufsize = sizeof(stackbuf); int bufsize = sizeof(stackbuf);
@ -1187,7 +1338,10 @@ while (1) { /* format passed string, arg
break; break;
} }
if (len && (buf[len-1] != '\r')) {
strcat (buf, "\r"); /* Make sure command line is terminated */ strcat (buf, "\r"); /* Make sure command line is terminated */
++len;
}
if (wait_for_completion) { if (wait_for_completion) {
strcat (buf, command_done_echo); strcat (buf, command_done_echo);
@ -1202,6 +1356,15 @@ if (wait_for_completion) {
p->io_waiting = 1; p->io_waiting = 1;
while (p->io_waiting) while (p->io_waiting)
pthread_cond_wait (&p->io_done, &p->io_lock); /* Wait for completion */ pthread_cond_wait (&p->io_done, &p->io_lock); /* Wait for completion */
if (response) {
*response = (char *)_panel_malloc (p->io_response_data + 1);
if (0 == memcmp (buf, p->io_response + strlen (sim_prompt), len)) {
memcpy (*response, p->io_response + strlen (sim_prompt) + len + 1, p->io_response_data + 1 - (strlen (sim_prompt) + len + 1));
}
else
memcpy (*response, p->io_response, p->io_response_data + 1);
}
p->io_response_data = 0;
} }
pthread_mutex_unlock (&p->io_lock); pthread_mutex_unlock (&p->io_lock);
} }

View file

@ -49,9 +49,13 @@ extern "C" {
#include <stdlib.h> #include <stdlib.h>
#if !defined(__VAX) /* Supported platform */
#define SIM_FRONTPANEL_VERSION 1
/** /**
sim_panel_start_simulator A starts a simulatir with a particular sim_panel_start_simulator A starts a simulator with a particular
configuration configuration
sim_path the path to the simulator binary sim_path the path to the simulator binary
@ -114,9 +118,12 @@ sim_panel_destroy (PANEL *panel);
The registers that a particular frontpanel application mught need The registers that a particular frontpanel application mught need
access to are described by the application by calling: access to are described by the application by calling:
sim_pabel_add_register sim_panel_add_register
name the name the simulator knows this register by name the name the simulator knows this register by
device_name the device this register is part of. Defaults to
the device of the panel (in a device panel) or the
default device in the simulator (usually the CPU).
size the size (in local storage) of the buffer which will size the size (in local storage) of the buffer which will
receive the data in the simulator's register receive the data in the simulator's register
addr a pointer to the location of the buffer which will addr a pointer to the location of the buffer which will
@ -126,6 +133,7 @@ sim_panel_destroy (PANEL *panel);
int int
sim_panel_add_register (PANEL *panel, sim_panel_add_register (PANEL *panel,
const char *name, const char *name,
const char *device_name,
size_t size, size_t size,
void *addr); void *addr);
@ -150,13 +158,14 @@ sim_panel_add_register (PANEL *panel,
*/ */
int int
sim_panel_get_registers (PANEL *panel); sim_panel_get_registers (PANEL *panel, unsigned long long *simulation_time);
/** /**
*/ */
typedef void (*PANEL_DISPLAY_PCALLBACK)(PANEL *panel, typedef void (*PANEL_DISPLAY_PCALLBACK)(PANEL *panel,
unsigned long long simulation_time,
void *context); void *context);
int int
@ -250,6 +259,8 @@ sim_panel_set_debug_mode (PANEL *panel, int debug_bits);
void void
sim_panel_flush_debug (PANEL *panel); sim_panel_flush_debug (PANEL *panel);
#endif /* !defined(__VAX) */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif