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:
parent
26ef9b566a
commit
059a54152a
4 changed files with 272 additions and 81 deletions
|
@ -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;
|
||||
|
||||
static void
|
||||
DisplayCallback (PANEL *panel, void *context)
|
||||
DisplayCallback (PANEL *panel, unsigned long long simulation_time, void *context)
|
||||
{
|
||||
char buf1[100], buf2[100], buf3[100];
|
||||
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 console telnet=buffered\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);
|
||||
}
|
||||
|
||||
|
@ -165,80 +174,84 @@ if (!tape) {
|
|||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
goto Done;
|
||||
}
|
||||
DisplayCallback (panel, NULL);
|
||||
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;
|
||||
}
|
||||
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());
|
||||
goto Done;
|
||||
}
|
||||
|
|
6
scp.c
6
scp.c
|
@ -225,6 +225,7 @@
|
|||
#include "sim_video.h"
|
||||
#endif
|
||||
#include "sim_sock.h"
|
||||
#include "sim_frontpanel.h"
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
@ -4246,6 +4247,9 @@ if (flag) {
|
|||
#endif
|
||||
#if defined (SIM_ASYNCH_CLOCKS)
|
||||
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
|
||||
fprintf (st, "\n\tHost Platform:");
|
||||
#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))
|
||||
return SCPE_2MARG;
|
||||
fprintf (st, "Time:\t%.0f\n", sim_time);
|
||||
fprintf (st, "Time:\t%.0f\n", sim_gtime());
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
237
sim_frontpanel.c
237
sim_frontpanel.c
|
@ -108,24 +108,27 @@ return 0;
|
|||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *device_name;
|
||||
void *addr;
|
||||
size_t size;
|
||||
} REG;
|
||||
|
||||
struct PANEL {
|
||||
PANEL *parent; /* Device Panels can have parent panels */
|
||||
char *name; /* simulator path or device name */
|
||||
char *path; /* simulator path */
|
||||
char *config;
|
||||
char *device_name; /* device name */
|
||||
char *temp_config;
|
||||
char hostport[64];
|
||||
size_t device_count;
|
||||
PANEL **devices;
|
||||
SOCKET sock;
|
||||
int reg_count;
|
||||
size_t reg_count;
|
||||
REG *regs;
|
||||
char *reg_query;
|
||||
size_t reg_query_size;
|
||||
OperationalState State;
|
||||
unsigned long long simulation_time;
|
||||
pthread_mutex_t lock;
|
||||
pthread_t io_thread;
|
||||
int io_thread_running;
|
||||
|
@ -133,6 +136,9 @@ struct PANEL {
|
|||
pthread_mutex_t io_send_lock;
|
||||
int io_reg_query_pending;
|
||||
int io_waiting;
|
||||
char *io_response;
|
||||
size_t io_response_data;
|
||||
size_t io_response_size;
|
||||
pthread_cond_t io_done;
|
||||
pthread_cond_t startup_cond;
|
||||
PANEL_DISPLAY_PCALLBACK callback;
|
||||
|
@ -141,6 +147,7 @@ struct PANEL {
|
|||
void *callback_context;
|
||||
int callbacks_per_second;
|
||||
int debug;
|
||||
char *simulator_version;
|
||||
FILE *Debug;
|
||||
#if defined(_WIN32)
|
||||
HANDLE hProcess;
|
||||
|
@ -150,7 +157,9 @@ struct PANEL {
|
|||
};
|
||||
|
||||
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_dev_echo = "# REGISTERS-FOR-DEVICE:";
|
||||
static const char *command_done_echo = "# COMMAND-DONE";
|
||||
static int little_endian;
|
||||
static void *_panel_reader(void *arg);
|
||||
|
@ -324,17 +333,18 @@ return sent;
|
|||
}
|
||||
|
||||
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
|
||||
_panel_register_query_string (PANEL *panel, char **buf, size_t *buf_size)
|
||||
{
|
||||
int i;
|
||||
size_t buf_data, buf_needed = 0;
|
||||
size_t i, j, buf_data, buf_needed = 0;
|
||||
char *dev;
|
||||
|
||||
pthread_mutex_lock (&panel->io_lock);
|
||||
buf_needed = 2 + strlen (register_get_prefix); /* SHOW TIME */
|
||||
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 */
|
||||
if (buf_needed > *buf_size) {
|
||||
free (*buf);
|
||||
|
@ -347,21 +357,40 @@ if (buf_needed > *buf_size) {
|
|||
*buf_size = buf_needed;
|
||||
}
|
||||
buf_data = 0;
|
||||
#if SEPARATE_REGISTERS
|
||||
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);
|
||||
}
|
||||
#else
|
||||
sprintf (*buf + buf_data, "E -H ");
|
||||
sprintf (*buf + buf_data, "%s\r", register_get_prefix);
|
||||
buf_data += strlen (*buf + buf_data);
|
||||
for (i=0; i<panel->reg_count; i++) {
|
||||
sprintf (*buf + buf_data, "%s%s", (i>0) ? "," : "", panel->regs[i].name);
|
||||
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;
|
||||
}
|
||||
strcpy (tbuf, *buf);
|
||||
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);
|
||||
dev = reg_dev;
|
||||
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);
|
||||
}
|
||||
strcpy (*buf + buf_data, "\r");
|
||||
buf_data += strlen (*buf + buf_data);
|
||||
#endif
|
||||
strcpy (*buf + buf_data, register_get_echo);
|
||||
buf_data += strlen (*buf + buf_data);
|
||||
strcpy (*buf + buf_data, "\r");
|
||||
|
@ -461,10 +490,10 @@ if (p == NULL)
|
|||
goto Error_Return;
|
||||
memset (p, 0, sizeof(*p));
|
||||
p->sock = INVALID_SOCKET;
|
||||
p->name = (char *)_panel_malloc (strlen (sim_path) + 1);
|
||||
if (p->name == NULL)
|
||||
p->path = (char *)_panel_malloc (strlen (sim_path) + 1);
|
||||
if (p->path == NULL)
|
||||
goto Error_Return;
|
||||
strcpy (p->name, sim_path);
|
||||
strcpy (p->path, sim_path);
|
||||
p->config = (char *)_panel_malloc (strlen (sim_config) + 1);
|
||||
if (p->config == NULL)
|
||||
goto Error_Return;
|
||||
|
@ -577,6 +606,22 @@ 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 */
|
||||
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);
|
||||
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)
|
||||
break;
|
||||
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;
|
||||
}
|
||||
p = (PANEL *)_panel_malloc (sizeof(*p));
|
||||
if (p == NULL)
|
||||
goto Error_Return;
|
||||
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->sock = INVALID_SOCKET;
|
||||
for (i=0; i<5; i++) {
|
||||
|
@ -665,7 +714,7 @@ sim_panel_destroy (PANEL *panel)
|
|||
REG *reg;
|
||||
|
||||
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) {
|
||||
size_t i;
|
||||
|
||||
|
@ -678,7 +727,8 @@ if (panel) {
|
|||
}
|
||||
|
||||
_panel_deregister_panel (panel);
|
||||
free (panel->name);
|
||||
free (panel->path);
|
||||
free (panel->device_name);
|
||||
free (panel->config);
|
||||
if (panel->sock != INVALID_SOCKET) {
|
||||
SOCKET sock = panel->sock;
|
||||
|
@ -724,10 +774,13 @@ if (panel) {
|
|||
reg = panel->regs;
|
||||
while (panel->reg_count--) {
|
||||
free (reg->name);
|
||||
free (reg->device_name);
|
||||
reg++;
|
||||
}
|
||||
free (panel->regs);
|
||||
free (panel->reg_query);
|
||||
free (panel->io_response);
|
||||
free (panel->simulator_version);
|
||||
sim_cleanup_sock ();
|
||||
free (panel);
|
||||
}
|
||||
|
@ -745,10 +798,13 @@ return panel->State;
|
|||
int
|
||||
sim_panel_add_register (PANEL *panel,
|
||||
const char *name,
|
||||
const char *device_name,
|
||||
size_t size,
|
||||
void *addr)
|
||||
{
|
||||
REG *regs, *reg;
|
||||
char *response = NULL;
|
||||
size_t i;
|
||||
|
||||
if (!panel || (panel->State == Error)) {
|
||||
sim_panel_set_error ("Invalid Panel");
|
||||
|
@ -770,8 +826,71 @@ if (reg->name == NULL) {
|
|||
return -1;
|
||||
}
|
||||
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->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;
|
||||
free (panel->regs);
|
||||
panel->regs = regs;
|
||||
|
@ -783,7 +902,7 @@ return 0;
|
|||
}
|
||||
|
||||
int
|
||||
sim_panel_get_registers (PANEL *panel)
|
||||
sim_panel_get_registers (PANEL *panel, unsigned long long *simulation_time)
|
||||
{
|
||||
if ((!panel) || (panel->State == Error)) {
|
||||
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;
|
||||
while (panel->io_waiting)
|
||||
pthread_cond_wait (&panel->io_done, &panel->io_lock);
|
||||
if (simulation_time)
|
||||
*simulation_time = panel->simulation_time;
|
||||
pthread_mutex_unlock (&panel->io_lock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -871,7 +992,7 @@ if (panel->State == Run) {
|
|||
sim_panel_set_error ("Not Halted");
|
||||
return -1;
|
||||
}
|
||||
if (_panel_sendf (panel, 0, "BOOT %s\r", device))
|
||||
if (_panel_sendf (panel, 0, NULL, "BOOT %s\r", device))
|
||||
return -1;
|
||||
panel->State = Run;
|
||||
return 0;
|
||||
|
@ -888,7 +1009,7 @@ if (panel->State == Run) {
|
|||
sim_panel_set_error ("Not Halted");
|
||||
return -1;
|
||||
}
|
||||
if (_panel_sendf (panel, 0, "CONT\r", 5))
|
||||
if (_panel_sendf (panel, 0, NULL, "CONT\r", 5))
|
||||
return -1;
|
||||
panel->State = Run;
|
||||
return 0;
|
||||
|
@ -925,7 +1046,7 @@ if (panel->callback) {
|
|||
sim_panel_set_error ("Callback provides register data");
|
||||
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 0;
|
||||
}
|
||||
|
@ -972,9 +1093,16 @@ while ((p->sock != INVALID_SOCKET) &&
|
|||
*eol++ = '\0';
|
||||
e = strchr (s, ':');
|
||||
if (e) {
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
*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++) {
|
||||
if (!strcmp(p->regs[i].name, s)) {
|
||||
unsigned long long data;
|
||||
|
@ -987,17 +1115,22 @@ while ((p->sock != INVALID_SOCKET) &&
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (i == p->reg_count) {
|
||||
/* Unexpected Register Data Found */
|
||||
if (i != p->reg_count) {
|
||||
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)) {
|
||||
pthread_mutex_lock (&p->io_lock);
|
||||
--p->io_reg_query_pending;
|
||||
if (p->callback) {
|
||||
pthread_mutex_unlock (&p->io_lock);
|
||||
p->callback (p, p->callback_context);
|
||||
p->callback (p, p->simulation_time, p->callback_context);
|
||||
}
|
||||
else {
|
||||
p->io_waiting = 0;
|
||||
|
@ -1006,19 +1139,37 @@ while ((p->sock != INVALID_SOCKET) &&
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (!strcmp (s + strlen (sim_prompt), command_done_echo)) {
|
||||
pthread_mutex_lock (&p->io_lock);
|
||||
if (!strcmp (s + strlen (sim_prompt), command_done_echo)) {
|
||||
p->io_waiting = 0;
|
||||
pthread_cond_signal (&p->io_done);
|
||||
pthread_mutex_unlock (&p->io_lock);
|
||||
}
|
||||
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;
|
||||
while (isspace(*s))
|
||||
while (isspace(0xFF & (*s)))
|
||||
++s;
|
||||
}
|
||||
pthread_mutex_lock (&p->io_lock);
|
||||
|
@ -1157,7 +1308,7 @@ return;
|
|||
}
|
||||
|
||||
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];
|
||||
int bufsize = sizeof(stackbuf);
|
||||
|
@ -1187,7 +1338,10 @@ while (1) { /* format passed string, arg
|
|||
break;
|
||||
}
|
||||
|
||||
strcat (buf, "\r"); /* Make sure command line is terminated */
|
||||
if (len && (buf[len-1] != '\r')) {
|
||||
strcat (buf, "\r"); /* Make sure command line is terminated */
|
||||
++len;
|
||||
}
|
||||
|
||||
if (wait_for_completion) {
|
||||
strcat (buf, command_done_echo);
|
||||
|
@ -1202,6 +1356,15 @@ if (wait_for_completion) {
|
|||
p->io_waiting = 1;
|
||||
while (p->io_waiting)
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -49,9 +49,13 @@ extern "C" {
|
|||
|
||||
#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
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
receive the data in the simulator's register
|
||||
addr a pointer to the location of the buffer which will
|
||||
|
@ -126,6 +133,7 @@ sim_panel_destroy (PANEL *panel);
|
|||
int
|
||||
sim_panel_add_register (PANEL *panel,
|
||||
const char *name,
|
||||
const char *device_name,
|
||||
size_t size,
|
||||
void *addr);
|
||||
|
||||
|
@ -150,13 +158,14 @@ sim_panel_add_register (PANEL *panel,
|
|||
|
||||
*/
|
||||
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,
|
||||
unsigned long long simulation_time,
|
||||
void *context);
|
||||
|
||||
int
|
||||
|
@ -250,6 +259,8 @@ sim_panel_set_debug_mode (PANEL *panel, int debug_bits);
|
|||
void
|
||||
sim_panel_flush_debug (PANEL *panel);
|
||||
|
||||
#endif /* !defined(__VAX) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue