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;
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
View file

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

View file

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

View file

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