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:
Mark Pizzolato 2017-12-09 01:25:34 -08:00
parent 0e4ee6ecce
commit b4c3fa1656
3 changed files with 208 additions and 164 deletions

View file

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

View file

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

View file

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