FRONTPANEL: sim_frontpanel API release 7
- Add explicit support for referencing register array elements. - Reworked the parsing of the grouped output sets for explicitly queried registers and the auto repeat output sets. - Fix race conditions in the various RUN, START, BOOT, and CONT commands. - Fix incorrect RUN/HALT state after STEP commands - Tolerate input TCP traffic that has been legitimately coalesced into different
This commit is contained in:
parent
0e4ee6ecce
commit
b4c3fa1656
3 changed files with 208 additions and 164 deletions
|
@ -62,6 +62,7 @@ unsigned int PCQ[32];
|
||||||
int PSL_bits[32];
|
int PSL_bits[32];
|
||||||
int PC_bits[32];
|
int PC_bits[32];
|
||||||
int PC_indirect_bits[32];
|
int PC_indirect_bits[32];
|
||||||
|
int PCQ_3_bits[32];
|
||||||
|
|
||||||
int update_display = 1;
|
int update_display = 1;
|
||||||
|
|
||||||
|
@ -422,7 +423,7 @@ if (sim_panel_set_sampling_parameters_ex (panel, 500, 10, 100)) {
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
if (sim_panel_add_register_indirect_bits (panel, "PC", NULL, 32, PC_indirect_bits)) {
|
if (sim_panel_add_register_indirect_bits (panel, "PC", NULL, 32, PC_indirect_bits)) {
|
||||||
printf ("Error adding register 'PSL' bits: %s\n", sim_panel_get_error());
|
printf ("Error adding register 'PC' indirect bits: %s\n", sim_panel_get_error());
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
if (sim_panel_add_register_bits (panel, "PSL", NULL, 32, PSL_bits)) {
|
if (sim_panel_add_register_bits (panel, "PSL", NULL, 32, PSL_bits)) {
|
||||||
|
@ -433,6 +434,10 @@ if (sim_panel_add_register_bits (panel, "PC", NULL, 32, PC_bits)) {
|
||||||
printf ("Error adding register 'PSL' bits: %s\n", sim_panel_get_error());
|
printf ("Error adding register 'PSL' bits: %s\n", sim_panel_get_error());
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
if (sim_panel_add_register_bits (panel, "PCQ[3]", NULL, 32, PCQ_3_bits)) {
|
||||||
|
printf ("Error adding register 'PCQ[3]' bits: %s\n", sim_panel_get_error());
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
if (1) {
|
if (1) {
|
||||||
unsigned int noop_noop_noop_halt = 0x00010101, addr400 = 0x00000400, pc_value;
|
unsigned int noop_noop_noop_halt = 0x00010101, addr400 = 0x00000400, pc_value;
|
||||||
int mstime = 0;
|
int mstime = 0;
|
||||||
|
@ -464,7 +469,24 @@ if (1) {
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
if (pc_value != addr400 + 4) {
|
if (pc_value != addr400 + 4) {
|
||||||
printf ("Unexpected error getting PC value: %08X, expected: %08X\n", pc_value, addr400 + 4);
|
printf ("Unexpected PC value after HALT: %08X, expected: %08X\n", pc_value, addr400 + 4);
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
if (sim_panel_gen_deposit (panel, "PC", sizeof(addr400), &addr400)) {
|
||||||
|
printf ("Error setting PC to %08X: %s\n", addr400, sim_panel_get_error());
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
if (sim_panel_exec_step (panel)) {
|
||||||
|
printf ("Error executing a single step: %s\n", sim_panel_get_error());
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
pc_value = 0;
|
||||||
|
if (sim_panel_gen_examine (panel, "PC", sizeof(pc_value), &pc_value)) {
|
||||||
|
printf ("Unexpected error getting PC value: %s\n", sim_panel_get_error());
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
if (pc_value != addr400 + 1) {
|
||||||
|
printf ("Unexpected PC value after STEP: %08X, expected: %08X\n", pc_value, addr400 + 1);
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,8 +217,10 @@ static const char *register_collect_mid1 = " samples every ";
|
||||||
static const char *register_collect_mid2 = " cycles dither ";
|
static const char *register_collect_mid2 = " cycles dither ";
|
||||||
static const char *register_collect_mid3 = " percent ";
|
static const char *register_collect_mid3 = " percent ";
|
||||||
static const char *register_get_postfix = "sampleout";
|
static const char *register_get_postfix = "sampleout";
|
||||||
static const char *register_get_echo = "# REGISTERS-DONE";
|
static const char *register_get_start = "# REGISTERS-START";
|
||||||
static const char *register_repeat_echo = "# REGISTERS-REPEAT-DONE";
|
static const char *register_get_end = "# REGISTERS-DONE";
|
||||||
|
static const char *register_repeat_start = "# REGISTERS-REPEAT-START\r";
|
||||||
|
static const char *register_repeat_end = "# REGISTERS-REPEAT-DONE";
|
||||||
static const char *register_dev_echo = "# REGISTERS-FOR-DEVICE:";
|
static const char *register_dev_echo = "# REGISTERS-FOR-DEVICE:";
|
||||||
static const char *register_ind_echo = "# REGISTER-INDIRECT:";
|
static const char *register_ind_echo = "# REGISTER-INDIRECT:";
|
||||||
static const char *command_status = "ECHO Status:%STATUS%-%TSTATUS%";
|
static const char *command_status = "ECHO Status:%STATUS%-%TSTATUS%";
|
||||||
|
@ -451,7 +453,9 @@ size_t i, j, buf_data, buf_needed = 0, reg_count = 0, bit_reg_count = 0;
|
||||||
const char *dev;
|
const char *dev;
|
||||||
|
|
||||||
pthread_mutex_lock (&panel->io_lock);
|
pthread_mutex_lock (&panel->io_lock);
|
||||||
buf_needed = 2 + strlen (register_get_prefix); /* SHOW TIME */
|
buf_needed = 3 +
|
||||||
|
strlen (register_get_start) + /* # REGISTERS-START */
|
||||||
|
strlen (register_get_prefix); /* SHOW TIME */
|
||||||
for (i=0; i<panel->reg_count; i++) {
|
for (i=0; i<panel->reg_count; i++) {
|
||||||
if (panel->regs[i].bits)
|
if (panel->regs[i].bits)
|
||||||
++bit_reg_count;
|
++bit_reg_count;
|
||||||
|
@ -466,7 +470,7 @@ for (i=0; i<panel->reg_count; i++) {
|
||||||
}
|
}
|
||||||
if (bit_reg_count)
|
if (bit_reg_count)
|
||||||
buf_needed += 2 + strlen (register_get_postfix);
|
buf_needed += 2 + strlen (register_get_postfix);
|
||||||
buf_needed += 10 + strlen (register_get_echo); /* # REGISTERS-DONE */
|
buf_needed += 10 + strlen (register_get_end); /* # REGISTERS-DONE */
|
||||||
if (buf_needed > *buf_size) {
|
if (buf_needed > *buf_size) {
|
||||||
free (*buf);
|
free (*buf);
|
||||||
*buf = (char *)_panel_malloc (buf_needed);
|
*buf = (char *)_panel_malloc (buf_needed);
|
||||||
|
@ -479,7 +483,7 @@ if (buf_needed > *buf_size) {
|
||||||
}
|
}
|
||||||
buf_data = 0;
|
buf_data = 0;
|
||||||
if (reg_count) {
|
if (reg_count) {
|
||||||
sprintf (*buf + buf_data, "%s\r", register_get_prefix);
|
sprintf (*buf + buf_data, "%s\r%s\r", register_get_start, register_get_prefix);
|
||||||
buf_data += strlen (*buf + buf_data);
|
buf_data += strlen (*buf + buf_data);
|
||||||
}
|
}
|
||||||
dev = "";
|
dev = "";
|
||||||
|
@ -540,7 +544,7 @@ if (bit_reg_count) {
|
||||||
strcpy (*buf + buf_data, "\r");
|
strcpy (*buf + buf_data, "\r");
|
||||||
buf_data += strlen (*buf + buf_data);
|
buf_data += strlen (*buf + buf_data);
|
||||||
}
|
}
|
||||||
strcpy (*buf + buf_data, register_get_echo);
|
strcpy (*buf + buf_data, register_get_end);
|
||||||
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);
|
||||||
|
@ -1435,7 +1439,7 @@ if (_panel_sendf (panel, &cmd_stat, NULL, "SHOW TIME\r"))
|
||||||
panel->simulation_time_base += panel->simulation_time;
|
panel->simulation_time_base += panel->simulation_time;
|
||||||
if (_panel_sendf (panel, NULL, NULL, "BOOT %s\r", device))
|
if (_panel_sendf (panel, NULL, NULL, "BOOT %s\r", device))
|
||||||
return -1;
|
return -1;
|
||||||
panel->State = Run;
|
msleep (100); /* Allow Run/Hslt state to settle */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1464,7 +1468,7 @@ if (_panel_sendf (panel, &cmd_stat, NULL, "SHOW TIME\r"))
|
||||||
panel->simulation_time_base += panel->simulation_time;
|
panel->simulation_time_base += panel->simulation_time;
|
||||||
if (_panel_sendf (panel, NULL, NULL, "RUN -Q\r", 5))
|
if (_panel_sendf (panel, NULL, NULL, "RUN -Q\r", 5))
|
||||||
return -1;
|
return -1;
|
||||||
panel->State = Run;
|
msleep (100); /* Allow Run/Hslt state to settle */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1485,7 +1489,7 @@ if (panel->State == Run) {
|
||||||
}
|
}
|
||||||
if (_panel_sendf (panel, NULL, NULL, "CONT\r", 5))
|
if (_panel_sendf (panel, NULL, NULL, "CONT\r", 5))
|
||||||
return -1;
|
return -1;
|
||||||
panel->State = Run;
|
msleep (100); /* Allow Run/Hslt state to settle */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1507,7 +1511,6 @@ if (panel->State == Run) {
|
||||||
|
|
||||||
if (5 != _panel_send (panel, "STEP\r", 5))
|
if (5 != _panel_send (panel, "STEP\r", 5))
|
||||||
return -1;
|
return -1;
|
||||||
panel->State = Run;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1951,11 +1954,12 @@ static void *
|
||||||
_panel_reader(void *arg)
|
_panel_reader(void *arg)
|
||||||
{
|
{
|
||||||
PANEL *p = (PANEL*)arg;
|
PANEL *p = (PANEL*)arg;
|
||||||
REG *r;
|
REG *r = NULL;
|
||||||
int sched_policy;
|
int sched_policy;
|
||||||
struct sched_param sched_priority;
|
struct sched_param sched_priority;
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
int buf_data = 0;
|
int buf_data = 0;
|
||||||
|
int processing_register_output = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Boost Priority for this response processing thread to quickly digest
|
Boost Priority for this response processing thread to quickly digest
|
||||||
|
@ -2020,10 +2024,10 @@ while ((p->sock != INVALID_SOCKET) &&
|
||||||
s = buf;
|
s = buf;
|
||||||
while ((eol = strchr (s, '\n'))) {
|
while ((eol = strchr (s, '\n'))) {
|
||||||
/* Line to process */
|
/* Line to process */
|
||||||
r = NULL;
|
|
||||||
*eol++ = '\0';
|
*eol++ = '\0';
|
||||||
while ((*s) && (s[strlen(s)-1] == '\r'))
|
while ((*s) && (s[strlen(s)-1] == '\r'))
|
||||||
s[strlen(s)-1] = '\0';
|
s[strlen(s)-1] = '\0';
|
||||||
|
if (processing_register_output) {
|
||||||
e = strchr (s, ':');
|
e = strchr (s, ':');
|
||||||
if (e) {
|
if (e) {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -2145,25 +2149,36 @@ while ((p->sock != INVALID_SOCKET) &&
|
||||||
*e = ':';
|
*e = ':';
|
||||||
/* Unexpected Register Data Found (or other output containing a : character) */
|
/* Unexpected Register Data Found (or other output containing a : character) */
|
||||||
}
|
}
|
||||||
if (!strcmp (s + strlen (sim_prompt), register_repeat_echo)) {
|
}
|
||||||
|
if (!strcmp (s + strlen (sim_prompt), register_repeat_end)) {
|
||||||
|
_panel_debug (p, DBG_RCV, "*Repeat Block Complete", NULL, 0);
|
||||||
if (p->callback) {
|
if (p->callback) {
|
||||||
pthread_mutex_unlock (&p->io_lock);
|
pthread_mutex_unlock (&p->io_lock);
|
||||||
p->callback (p, p->simulation_time_base + p->simulation_time, p->callback_context);
|
p->callback (p, p->simulation_time_base + p->simulation_time, p->callback_context);
|
||||||
pthread_mutex_lock (&p->io_lock);
|
pthread_mutex_lock (&p->io_lock);
|
||||||
}
|
}
|
||||||
|
processing_register_output = 0;
|
||||||
|
goto Start_Next_Line;
|
||||||
}
|
}
|
||||||
if (!strcmp (s + strlen (sim_prompt), register_get_echo)) {
|
if ((!strcmp (s + strlen (sim_prompt), register_repeat_start)) ||
|
||||||
|
(!strcmp (s + strlen (sim_prompt), register_get_start))) {
|
||||||
|
_panel_debug (p, DBG_RCV, "*Repeat/Register Block Starting", NULL, 0);
|
||||||
|
processing_register_output = 1;
|
||||||
|
goto Start_Next_Line;
|
||||||
|
}
|
||||||
|
if (!strcmp (s + strlen (sim_prompt), register_get_end)) {
|
||||||
|
_panel_debug (p, DBG_RCV, "*Register Block Complete", NULL, 0);
|
||||||
--p->io_reg_query_pending;
|
--p->io_reg_query_pending;
|
||||||
p->io_waiting = 0;
|
p->io_waiting = 0;
|
||||||
pthread_cond_signal (&p->io_done);
|
pthread_cond_signal (&p->io_done);
|
||||||
|
goto Start_Next_Line;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (!strcmp (s + strlen (sim_prompt), command_done_echo)) {
|
if (!strcmp (s + strlen (sim_prompt), command_done_echo)) {
|
||||||
_panel_debug (p, DBG_RCV, "Received Command Complete", NULL, 0);
|
_panel_debug (p, DBG_RCV, "*Received Command Complete", NULL, 0);
|
||||||
p->io_waiting = 0;
|
p->io_waiting = 0;
|
||||||
pthread_cond_signal (&p->io_done);
|
pthread_cond_signal (&p->io_done);
|
||||||
|
goto Start_Next_Line;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
/* Non Register Data Found (echo of EXAMINE or other commands and/or command output) */
|
/* Non Register Data Found (echo of EXAMINE or other commands and/or command output) */
|
||||||
if (p->io_waiting) {
|
if (p->io_waiting) {
|
||||||
char *t;
|
char *t;
|
||||||
|
@ -2188,14 +2203,14 @@ while ((p->sock != INVALID_SOCKET) &&
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
_panel_debug (p, DBG_RCV, "Receive Data Discarded: '%s'", NULL, 0, s);
|
_panel_debug (p, DBG_RCV, "Receive Data Discarded: '%s'", NULL, 0, s);
|
||||||
}
|
Start_Next_Line:
|
||||||
}
|
|
||||||
s = eol;
|
s = eol;
|
||||||
while (isspace(0xFF & (*s)))
|
while (isspace(0xFF & (*s)))
|
||||||
++s;
|
++s;
|
||||||
}
|
}
|
||||||
memmove (buf, s, strlen (s)+1);
|
memmove (buf, s, strlen (s)+1);
|
||||||
buf_data = strlen (buf);
|
buf_data = strlen (buf);
|
||||||
|
if (buf_data)
|
||||||
_panel_debug (p, DBG_RSP, "Remnant Buffer Contents: '%s'", NULL, 0, buf);
|
_panel_debug (p, DBG_RSP, "Remnant Buffer Contents: '%s'", NULL, 0, buf);
|
||||||
if (!memcmp ("Simulator Running...", buf, 20)) {
|
if (!memcmp ("Simulator Running...", buf, 20)) {
|
||||||
_panel_debug (p, DBG_RSP, "State transitioning to Run", NULL, 0);
|
_panel_debug (p, DBG_RSP, "State transitioning to Run", NULL, 0);
|
||||||
|
@ -2280,22 +2295,25 @@ while ((p->sock != INVALID_SOCKET) &&
|
||||||
strlen (register_repeat_units) + /* units and spacing */
|
strlen (register_repeat_units) + /* units and spacing */
|
||||||
buf_data + /* command contents */
|
buf_data + /* command contents */
|
||||||
1 + /* carriage return */
|
1 + /* carriage return */
|
||||||
strlen (register_repeat_echo) + /* auto repeat completion */
|
strlen (register_repeat_start) + /* auto repeat begin */
|
||||||
|
1 + /* carriage return */
|
||||||
|
strlen (register_repeat_end) + /* auto repeat completion */
|
||||||
1 + /* carriage return */
|
1 + /* carriage return */
|
||||||
1; /* NUL */
|
1; /* NUL */
|
||||||
char *repeat = (char *)malloc (repeat_data);
|
char *repeat = (char *)malloc (repeat_data);
|
||||||
char *c;
|
char *c;
|
||||||
|
|
||||||
sprintf (repeat, "%s%d%s%*.*s", register_repeat_prefix,
|
sprintf (repeat, "%s%d%s%s%*.*s", register_repeat_prefix,
|
||||||
p->usecs_between_callbacks,
|
p->usecs_between_callbacks,
|
||||||
register_repeat_units,
|
register_repeat_units,
|
||||||
|
register_repeat_start,
|
||||||
(int)buf_data, (int)buf_data, buf);
|
(int)buf_data, (int)buf_data, buf);
|
||||||
pthread_mutex_unlock (&p->io_lock);
|
pthread_mutex_unlock (&p->io_lock);
|
||||||
for (c = strchr (repeat, '\r'); c != NULL; c = strchr (c, '\r'))
|
for (c = strchr (repeat, '\r'); c != NULL; c = strchr (c, '\r'))
|
||||||
*c = ';'; /* replace carriage returns with semicolons */
|
*c = ';'; /* replace carriage returns with semicolons */
|
||||||
c = strstr (repeat, register_get_echo); /* remove register_done_echo string and */
|
c = strstr (repeat, register_get_end); /* remove register_done_echo string and */
|
||||||
if (c) /* always true */
|
if (c) /* always true */
|
||||||
strcpy (c, register_repeat_echo); /* replace it with the register_repeat_echo string */
|
strcpy (c, register_repeat_end); /* replace it with the register_repeat_end string */
|
||||||
if (_panel_sendf (p, &cmd_stat, NULL, "%s", repeat)) {
|
if (_panel_sendf (p, &cmd_stat, NULL, "%s", repeat)) {
|
||||||
pthread_mutex_lock (&p->io_lock);
|
pthread_mutex_lock (&p->io_lock);
|
||||||
free (repeat);
|
free (repeat);
|
||||||
|
@ -2450,16 +2468,17 @@ ret = ((len + status_echo_len) == (sent_len = _panel_send (p, buf, len + status_
|
||||||
|
|
||||||
if (completion_status) {
|
if (completion_status) {
|
||||||
if (!ret) { /* Sent OK? */
|
if (!ret) { /* Sent OK? */
|
||||||
|
char *tresponse = NULL;
|
||||||
|
|
||||||
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) {
|
tresponse = (char *)_panel_malloc (p->io_response_data + 1);
|
||||||
*response = (char *)_panel_malloc (p->io_response_data + 1);
|
|
||||||
if (0 == memcmp (buf, p->io_response + strlen (sim_prompt), len)) {
|
if (0 == memcmp (buf, p->io_response + strlen (sim_prompt), len)) {
|
||||||
char *eol, *status;
|
char *eol, *status;
|
||||||
memcpy (*response, p->io_response + strlen (sim_prompt) + len + 1, p->io_response_data + 1 - (strlen (sim_prompt) + len + 1));
|
memcpy (tresponse, p->io_response + strlen (sim_prompt) + len + 1, p->io_response_data + 1 - (strlen (sim_prompt) + len + 1));
|
||||||
*completion_status = -1;
|
*completion_status = -1;
|
||||||
status = strstr (*response, command_status);
|
status = strstr (tresponse, command_status);
|
||||||
if (status) {
|
if (status) {
|
||||||
*(status - strlen (sim_prompt)) = '\0';
|
*(status - strlen (sim_prompt)) = '\0';
|
||||||
status += strlen (command_status) + 2;
|
status += strlen (command_status) + 2;
|
||||||
|
@ -2470,12 +2489,15 @@ if (completion_status) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
memcpy (*response, p->io_response, p->io_response_data + 1);
|
memcpy (tresponse, p->io_response, p->io_response_data + 1);
|
||||||
|
if (response) {
|
||||||
|
*response = tresponse;
|
||||||
_panel_debug (p, DBG_RSP, "Command %d Response(Status=%d): '%s'", NULL, 0, p->command_count, *completion_status, *response);
|
_panel_debug (p, DBG_RSP, "Command %d Response(Status=%d): '%s'", NULL, 0, p->command_count, *completion_status, *response);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
free (tresponse);
|
||||||
if (p->io_response_data)
|
if (p->io_response_data)
|
||||||
_panel_debug (p, DBG_RSP, "Discarded Unwanted Command %d Response Data:", p->io_response, p->io_response_data, p->command_count);
|
_panel_debug (p, DBG_RSP, "Discarded Unwanted Command %d Response Data(Status=%d):", p->io_response, p->io_response_data, p->command_count, *completion_status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p->io_response_data = 0;
|
p->io_response_data = 0;
|
||||||
|
|
|
@ -56,7 +56,7 @@ extern "C" {
|
||||||
|
|
||||||
#if !defined(__VAX) /* Unsupported platform */
|
#if !defined(__VAX) /* Unsupported platform */
|
||||||
|
|
||||||
#define SIM_FRONTPANEL_VERSION 6
|
#define SIM_FRONTPANEL_VERSION 7
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue