From 059a54152a6da067cc927c8d3c8da60e98dd2f53 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Tue, 24 Feb 2015 19:49:09 -0800 Subject: [PATCH] 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). --- frontpanel/FrontPanelTest.c | 53 ++++--- scp.c | 6 +- sim_frontpanel.c | 267 +++++++++++++++++++++++++++++------- sim_frontpanel.h | 27 ++-- 4 files changed, 272 insertions(+), 81 deletions(-) diff --git a/frontpanel/FrontPanelTest.c b/frontpanel/FrontPanelTest.c index 5f9acb9e..084b56fe 100644 --- a/frontpanel/FrontPanelTest.c +++ b/frontpanel/FrontPanelTest.c @@ -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; } diff --git a/scp.c b/scp.c index 84b34980..1b12be4c 100644 --- a/scp.c +++ b/scp.c @@ -225,6 +225,7 @@ #include "sim_video.h" #endif #include "sim_sock.h" +#include "sim_frontpanel.h" #include #include #include @@ -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; } diff --git a/sim_frontpanel.c b/sim_frontpanel.c index f17bf53f..486aef22 100644 --- a/sim_frontpanel.c +++ b/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; ireg_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; ireg_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; ireg_count; i++) { - sprintf (*buf + buf_data, "%s%s", (i>0) ? "," : "", panel->regs[i].name); +dev = ""; +for (i=j=0; ireg_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; iname); 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; idevice_name); i++) { + if (islower (reg->device_name[i])) + reg->device_name[i] = toupper (reg->device_name[i]); + } + } +for (i=0; ireg_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; ireg_count; i++) { if (!strcmp(p->regs[i].name, s)) { unsigned long long data; @@ -987,38 +1115,61 @@ 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) */ + } + 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->simulation_time, p->callback_context); + } + else { + p->io_waiting = 0; + pthread_cond_signal (&p->io_done); + pthread_mutex_unlock (&p->io_lock); } } 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); - } - else { - p->io_waiting = 0; - pthread_cond_signal (&p->io_done); - pthread_mutex_unlock (&p->io_lock); - } + 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); } else { - if (!strcmp (s + strlen (sim_prompt), command_done_echo)) { - pthread_mutex_lock (&p->io_lock); - 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); } diff --git a/sim_frontpanel.h b/sim_frontpanel.h index 578d09cc..5b80ead1 100644 --- a/sim_frontpanel.h +++ b/sim_frontpanel.h @@ -49,9 +49,13 @@ extern "C" { #include +#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,18 +118,22 @@ 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 - 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 - be loaded with the data in the simulator's 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 + be loaded with the data in the simulator's register */ 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