FRONTPANEL: sim_frontpanel API version 4 release
Add simulator side register bit sampling with averaged sample values delivered across the API at specified rates.
This commit is contained in:
parent
f171055809
commit
665ebf0fd1
5 changed files with 627 additions and 82 deletions
|
@ -59,6 +59,10 @@ const char *sim_config =
|
|||
unsigned int PC, SP, FP, AP, PSL, R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, atPC;
|
||||
unsigned int PCQ[32];
|
||||
|
||||
int PSL_bits[32];
|
||||
int PC_bits[32];
|
||||
int PC_indirect_bits[32];
|
||||
|
||||
int update_display = 1;
|
||||
|
||||
static void
|
||||
|
@ -357,6 +361,35 @@ if (sim_panel_break_output_set (panel, "-P \"Device? [XQA0]: \"")) {
|
|||
printf ("Unexpected error establishing an output breakpoint: %s\n", sim_panel_get_error());
|
||||
goto Done;
|
||||
}
|
||||
if (!sim_panel_set_sampling_parameters (panel, 0, 199)) {
|
||||
printf ("Unexpected success setting sampling parameters to 0, 199\n");
|
||||
goto Done;
|
||||
}
|
||||
if (!sim_panel_set_sampling_parameters (panel, 199, 0)) {
|
||||
printf ("Unexpected success setting sampling parameters to 199, 0\n");
|
||||
goto Done;
|
||||
}
|
||||
if (!sim_panel_add_register_bits (panel, "PSL", NULL, 32, PSL_bits)) {
|
||||
printf ("Unexpected success setting PSL bits before setting sampling parameters\n");
|
||||
goto Done;
|
||||
}
|
||||
if (sim_panel_set_sampling_parameters (panel, 500, 100)) {
|
||||
printf ("Unexpected error setting sampling parameters to 200, 100: %s\n", sim_panel_get_error());
|
||||
goto Done;
|
||||
}
|
||||
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());
|
||||
goto Done;
|
||||
}
|
||||
if (sim_panel_add_register_bits (panel, "PSL", NULL, 32, PSL_bits)) {
|
||||
printf ("Error adding register 'PSL' bits: %s\n", sim_panel_get_error());
|
||||
goto Done;
|
||||
}
|
||||
if (sim_panel_add_register_bits (panel, "PC", NULL, 32, PC_bits)) {
|
||||
printf ("Error adding register 'PSL' bits: %s\n", sim_panel_get_error());
|
||||
goto Done;
|
||||
}
|
||||
|
||||
sim_panel_clear_error ();
|
||||
while (1) {
|
||||
size_t i;
|
||||
|
|
3
scp.h
3
scp.h
|
@ -195,6 +195,7 @@ CTAB *find_ctab (CTAB *tab, const char *gbuf);
|
|||
C1TAB *find_c1tab (C1TAB *tab, const char *gbuf);
|
||||
SHTAB *find_shtab (SHTAB *tab, const char *gbuf);
|
||||
t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr);
|
||||
t_value get_rval (REG *rptr, uint32 idx);
|
||||
BRKTAB *sim_brk_fnd (t_addr loc);
|
||||
uint32 sim_brk_test (t_addr bloc, uint32 btyp);
|
||||
void sim_brk_clrspc (uint32 spc, uint32 btyp);
|
||||
|
@ -264,6 +265,8 @@ t_stat scp_vhelpFromFile (FILE *st, DEVICE *dptr,
|
|||
/* Global data */
|
||||
|
||||
extern DEVICE *sim_dflt_dev;
|
||||
extern DEVICE *sim_dfdev;
|
||||
extern UNIT *sim_dfunit;
|
||||
extern int32 sim_interval;
|
||||
extern int32 sim_switches;
|
||||
extern int32 sim_quiet;
|
||||
|
|
406
sim_console.c
406
sim_console.c
|
@ -428,14 +428,18 @@ return SCPE_OK;
|
|||
t_stat sim_rem_con_poll_svc (UNIT *uptr); /* remote console connection poll routine */
|
||||
t_stat sim_rem_con_data_svc (UNIT *uptr); /* remote console connection data routine */
|
||||
t_stat sim_rem_con_repeat_svc (UNIT *uptr); /* remote auto repeat command console timing routine */
|
||||
t_stat sim_rem_con_smp_collect_svc (UNIT *uptr); /* remote remote register data sampling routine */
|
||||
t_stat sim_rem_con_reset (DEVICE *dptr); /* remote console reset routine */
|
||||
#define rem_con_poll_unit (&sim_remote_console.units[0])
|
||||
#define rem_con_data_unit (&sim_remote_console.units[1])
|
||||
#define REM_CON_BASE_UNITS 2
|
||||
#define rem_con_repeat_units (&sim_remote_console.units[REM_CON_BASE_UNITS])
|
||||
#define rem_con_smp_smpl_units (&sim_remote_console.units[REM_CON_BASE_UNITS+sim_rem_con_tmxr.lines])
|
||||
|
||||
#define DBG_MOD 0x00000004 /* Remote Console Mode activities */
|
||||
#define DBG_REP 0x00000008 /* Remote Console Repeat activities */
|
||||
#define DBG_CMD 0x00000010 /* Remote Console Command activities */
|
||||
#define DBG_SAM 0x00000010 /* Remote Console Sample activities */
|
||||
#define DBG_CMD 0x00000020 /* Remote Console Command activities */
|
||||
|
||||
DEBTAB sim_rem_con_debug[] = {
|
||||
{"TRC", DBG_TRC, "routine calls"},
|
||||
|
@ -445,6 +449,7 @@ DEBTAB sim_rem_con_debug[] = {
|
|||
{"CMD", DBG_CMD, "Remote Console Command activity"},
|
||||
{"MODE", DBG_MOD, "Remote Console Mode activity"},
|
||||
{"REPEAT", DBG_REP, "Remote Console Repeat activity"},
|
||||
{"SAMPLE", DBG_SAM, "Remote Console Sample activity"},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
@ -464,6 +469,22 @@ DEVICE sim_remote_console = {
|
|||
NULL, DEV_DEBUG | DEV_NOSAVE, 0, sim_rem_con_debug,
|
||||
NULL, NULL, NULL, NULL, NULL, sim_rem_con_description};
|
||||
|
||||
typedef struct BITSAMPLE BITSAMPLE;
|
||||
struct BITSAMPLE {
|
||||
int tot; /* total of all values */
|
||||
int ptr; /* pointer to next value cell */
|
||||
int depth; /* number of values */
|
||||
int *vals; /* values */
|
||||
};
|
||||
typedef struct BITSAMPLE_REG BITSAMPLE_REG;
|
||||
struct BITSAMPLE_REG {
|
||||
REG *reg; /* Register to be sampled */
|
||||
t_bool indirect; /* Register value points at memory */
|
||||
DEVICE *dptr; /* Device register is part of */
|
||||
UNIT *uptr; /* Unit Register is related to */
|
||||
uint32 width; /* number of bits to sample */
|
||||
BITSAMPLE *bits;
|
||||
};
|
||||
typedef struct REMOTE REMOTE;
|
||||
struct REMOTE {
|
||||
int32 buf_size;
|
||||
|
@ -474,16 +495,18 @@ struct REMOTE {
|
|||
char *act;
|
||||
t_bool single_mode;
|
||||
uint32 read_timeout;
|
||||
int line;
|
||||
TMLN *lp;
|
||||
UNIT *uptr;
|
||||
uint32 repeat_interval;
|
||||
t_bool repeat_pending;
|
||||
char *repeat_action;
|
||||
int line; /* remote console line number */
|
||||
TMLN *lp; /* mux line/socket for remote session */
|
||||
UNIT *uptr; /* remote console unit */
|
||||
uint32 repeat_interval; /* usecs between repeat execution */
|
||||
t_bool repeat_pending; /* repeat delivery pending */
|
||||
char *repeat_action; /* command(s) to repeatedly execute */
|
||||
int smp_sample_interval; /* cycles between samples */
|
||||
uint32 smp_reg_count; /* sample register count */
|
||||
BITSAMPLE_REG *smp_regs; /* registers being sampled */
|
||||
};
|
||||
REMOTE *sim_rem_consoles = NULL;
|
||||
|
||||
|
||||
static TMXR sim_rem_con_tmxr = { 0, 0, 0, NULL, NULL, &sim_remote_console };/* remote console line mux */
|
||||
static uint32 sim_rem_read_timeout = 30; /* seconds before automatic continue */
|
||||
static uint32 *sim_rem_read_timeouts = NULL;/* per line read timeout (default from sim_rem_read_timeout) */
|
||||
|
@ -498,6 +521,26 @@ static t_bool sim_rem_master_was_enabled = FALSE; /* Master was Enabled */
|
|||
static t_bool sim_rem_master_was_connected = FALSE; /* Master Mode has been connected */
|
||||
static t_offset sim_rem_cmd_log_start = 0; /* Log File saved position */
|
||||
|
||||
static t_stat sim_rem_sample_output (FILE *st, int32 line)
|
||||
{
|
||||
REMOTE *rem = &sim_rem_consoles[line];
|
||||
uint32 reg;
|
||||
|
||||
if (rem->smp_reg_count == 0) {
|
||||
fprintf (st, "Samples are not being collected\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
for (reg = 0; reg < rem->smp_reg_count; reg++) {
|
||||
uint32 bit;
|
||||
|
||||
fprintf (st, "}%s %s%s %d:", rem->smp_regs[reg].dptr->name, rem->smp_regs[reg].reg->name, rem->smp_regs[reg].indirect ? " -I" : "", rem->smp_regs[reg].bits[0].depth);
|
||||
for (bit = 0; bit < rem->smp_regs[reg].width; bit++)
|
||||
fprintf (st, "%s%d", (bit != 0) ? "," : "", rem->smp_regs[reg].bits[bit].tot);
|
||||
fprintf (st, "\n");
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* SET REMOTE CONSOLE command */
|
||||
|
||||
|
@ -567,6 +610,24 @@ for (i=connections=0; i<sim_rem_con_tmxr.lines; i++) {
|
|||
fprintf (st, "The Command: %s\n", rem->repeat_action);
|
||||
fprintf (st, " is repeated every %s\n", sim_fmt_secs (rem->repeat_interval / 1000000.0));
|
||||
}
|
||||
if (rem->smp_reg_count) {
|
||||
uint32 reg;
|
||||
DEVICE *dptr = NULL;
|
||||
|
||||
fprintf (st, "Register Bit Sampling is occurring every %d cycles\n", rem->smp_sample_interval);
|
||||
fprintf (st, " Registers being sampled are: ");
|
||||
for (reg = 0; reg < rem->smp_reg_count; reg++) {
|
||||
if (rem->smp_regs[reg].indirect)
|
||||
fprintf (st, " indirect ");
|
||||
if (dptr != rem->smp_regs[reg].dptr)
|
||||
fprintf (st, "%s ", rem->smp_regs[reg].dptr->name);
|
||||
fprintf (st, "%s%s", rem->smp_regs[reg].reg->name, ((reg + 1) < rem->smp_reg_count) ? ", " : "");
|
||||
dptr = rem->smp_regs[reg].dptr;
|
||||
}
|
||||
fprintf (st, "\n");
|
||||
if (sim_switches & SWMASK ('D'))
|
||||
sim_rem_sample_output (st, rem->line);
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -620,16 +681,26 @@ static t_stat x_repeat_cmd (int32 flag, CONST char *cptr)
|
|||
return 2+SCPE_IERR; /* This routine should never be called */
|
||||
}
|
||||
|
||||
static t_stat x_step_cmd (int32 flag, CONST char *cptr)
|
||||
static t_stat x_collect_cmd (int32 flag, CONST char *cptr)
|
||||
{
|
||||
return 3+SCPE_IERR; /* This routine should never be called */
|
||||
}
|
||||
|
||||
static t_stat x_run_cmd (int32 flag, CONST char *cptr)
|
||||
static t_stat x_sampleout_cmd (int32 flag, CONST char *cptr)
|
||||
{
|
||||
return 4+SCPE_IERR; /* This routine should never be called */
|
||||
}
|
||||
|
||||
static t_stat x_step_cmd (int32 flag, CONST char *cptr)
|
||||
{
|
||||
return 5+SCPE_IERR; /* This routine should never be called */
|
||||
}
|
||||
|
||||
static t_stat x_run_cmd (int32 flag, CONST char *cptr)
|
||||
{
|
||||
return 6+SCPE_IERR; /* This routine should never be called */
|
||||
}
|
||||
|
||||
static t_stat x_help_cmd (int32 flag, CONST char *cptr);
|
||||
|
||||
static CTAB allowed_remote_cmds[] = {
|
||||
|
@ -642,6 +713,8 @@ static CTAB allowed_remote_cmds[] = {
|
|||
{ "DEASSIGN", &deassign_cmd, 0 },
|
||||
{ "CONTINUE", &x_continue_cmd, 0 },
|
||||
{ "REPEAT", &x_repeat_cmd, 0 },
|
||||
{ "COLLECT", &x_collect_cmd, 0 },
|
||||
{ "SAMPLEOUT",&x_sampleout_cmd, 0 },
|
||||
{ "STEP", &x_step_cmd, 0 },
|
||||
{ "PWD", &pwd_cmd, 0 },
|
||||
{ "SAVE", &save_cmd, 0 },
|
||||
|
@ -664,6 +737,8 @@ static CTAB allowed_master_remote_cmds[] = {
|
|||
{ "DEASSIGN", &deassign_cmd, 0 },
|
||||
{ "CONTINUE", &x_continue_cmd, 0 },
|
||||
{ "REPEAT", &x_repeat_cmd, 0 },
|
||||
{ "COLLECT", &x_collect_cmd, 0 },
|
||||
{ "SAMPLEOUT",&x_sampleout_cmd, 0 },
|
||||
{ "STEP", &x_step_cmd, 0 },
|
||||
{ "PWD", &pwd_cmd, 0 },
|
||||
{ "SAVE", &save_cmd, 0 },
|
||||
|
@ -693,6 +768,8 @@ static CTAB allowed_single_remote_cmds[] = {
|
|||
{ "EXAMINE", &exdep_cmd, EX_E },
|
||||
{ "EVALUATE", &eval_cmd, 0 },
|
||||
{ "REPEAT", &x_repeat_cmd, 0 },
|
||||
{ "COLLECT", &x_collect_cmd, 0 },
|
||||
{ "SAMPLEOUT",&x_sampleout_cmd, 0 },
|
||||
{ "PWD", &pwd_cmd, 0 },
|
||||
{ "DIR", &dir_cmd, 0 },
|
||||
{ "LS", &dir_cmd, 0 },
|
||||
|
@ -704,6 +781,8 @@ static CTAB allowed_single_remote_cmds[] = {
|
|||
|
||||
static CTAB remote_only_cmds[] = {
|
||||
{ "REPEAT", &x_repeat_cmd, 0 },
|
||||
{ "COLLECT", &x_collect_cmd, 0 },
|
||||
{ "SAMPLEOUT",&x_sampleout_cmd, 0 },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -864,7 +943,7 @@ return buf;
|
|||
Parse and setup Remote Console REPEAT command:
|
||||
REPEAT EVERY nnn USECS Command {; command...}
|
||||
*/
|
||||
static t_stat _rem_repeat_cmd_setup (int32 line, CONST char **iptr)
|
||||
static t_stat sim_rem_repeat_cmd_setup (int32 line, CONST char **iptr)
|
||||
{
|
||||
char gbuf[CBUFSIZE];
|
||||
int32 val;
|
||||
|
@ -940,6 +1019,239 @@ if (stat == SCPE_OK) {
|
|||
return stat;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Parse and setup Remote Console REPEAT command:
|
||||
COLLECT nnn SAMPLES EVERY nnn CYCLES reg{,reg...}
|
||||
*/
|
||||
static t_stat sim_rem_collect_cmd_setup (int32 line, CONST char **iptr)
|
||||
{
|
||||
char gbuf[CBUFSIZE];
|
||||
int32 samples, cycles;
|
||||
t_bool all_stop = FALSE;
|
||||
t_stat stat = SCPE_OK;
|
||||
CONST char *cptr = *iptr;
|
||||
REMOTE *rem = &sim_rem_consoles[line];
|
||||
|
||||
sim_debug (DBG_SAM, &sim_remote_console, "Collect Setup: %s\n", cptr);
|
||||
if (*cptr == 0) /* required argument? */
|
||||
return SCPE_2FARG;
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||
samples = (int32) get_uint (gbuf, 10, INT_MAX, &stat);
|
||||
if ((stat != SCPE_OK) || (samples <= 0)) { /* error? */
|
||||
if (MATCH_CMD (gbuf, "STOP") == 0) {
|
||||
stat = SCPE_OK;
|
||||
if (*cptr) { /* more command arguments? */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||
if ((MATCH_CMD (gbuf, "ALL") != 0) || /* */
|
||||
(*cptr != 0) || /* */
|
||||
(line != 0)) /* master line? */
|
||||
stat = SCPE_ARG;
|
||||
else
|
||||
all_stop = TRUE;
|
||||
}
|
||||
if (stat == SCPE_OK) {
|
||||
for (line = all_stop ? 0 : rem->line; line < (all_stop ? sim_rem_con_tmxr.lines : (rem->line + 1)); line++) {
|
||||
uint32 i, j;
|
||||
|
||||
rem = &sim_rem_consoles[line];
|
||||
for (i = 0; i< rem->smp_reg_count; i++) {
|
||||
for (j = 0; j < rem->smp_regs[i].width; j++)
|
||||
free (rem->smp_regs[i].bits[j].vals);
|
||||
free (rem->smp_regs[i].bits);
|
||||
}
|
||||
free (rem->smp_regs);
|
||||
rem->smp_regs = NULL;
|
||||
rem->smp_reg_count = 0;
|
||||
sim_cancel (&rem_con_smp_smpl_units[rem->line]);
|
||||
rem->smp_sample_interval = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
stat = sim_messagef (SCPE_ARG, "Expected value or STOP found: %s\n", gbuf);
|
||||
}
|
||||
else {
|
||||
const char *tptr;
|
||||
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||
if (MATCH_CMD (gbuf, "SAMPLES") != 0) {
|
||||
*iptr = cptr;
|
||||
return sim_messagef (SCPE_ARG, "Expected SAMPLES found: %s\n", gbuf);
|
||||
}
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||
if (MATCH_CMD (gbuf, "EVERY") != 0) {
|
||||
*iptr = cptr;
|
||||
return sim_messagef (SCPE_ARG, "Expected EVERY found: %s\n", gbuf);
|
||||
}
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||
cycles = (int32) get_uint (gbuf, 10, INT_MAX, &stat);
|
||||
if ((stat != SCPE_OK) || (cycles <= 0)) { /* error? */
|
||||
*iptr = cptr;
|
||||
return sim_messagef (SCPE_ARG, "Expected value found: %s\n", gbuf);
|
||||
}
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||
if ((MATCH_CMD (gbuf, "CYCLES") != 0) || (*cptr == 0)) {
|
||||
*iptr = cptr;
|
||||
return sim_messagef (SCPE_ARG, "Expected CYCLES found: %s\n", gbuf);
|
||||
}
|
||||
tptr = strcpy (gbuf, "STOP"); /* Start from a clean slate */
|
||||
sim_rem_collect_cmd_setup (rem->line, &tptr);
|
||||
rem->smp_sample_interval = cycles;
|
||||
rem->smp_reg_count = 0;
|
||||
while (cptr && *cptr) {
|
||||
const char *comma = strchr (cptr, ',');
|
||||
char tbuf[2*CBUFSIZE];
|
||||
uint32 bit, width;
|
||||
REG *reg;
|
||||
int32 saved_switches = sim_switches;
|
||||
t_bool indirect = FALSE;
|
||||
BITSAMPLE_REG *smp_regs;
|
||||
|
||||
if (comma) {
|
||||
strncpy (tbuf, cptr, comma - cptr);
|
||||
tbuf[comma - cptr] = '\0';
|
||||
cptr = comma + 1;
|
||||
}
|
||||
else {
|
||||
strcpy (tbuf, cptr);
|
||||
cptr += strlen (cptr);
|
||||
}
|
||||
tptr = tbuf;
|
||||
if (strchr (tbuf, ' ')) {
|
||||
sim_switches = 0;
|
||||
tptr = get_sim_opt (CMD_OPT_SW|CMD_OPT_DFT, tbuf, &stat); /* get switches and device */
|
||||
indirect = ((sim_switches & SWMASK('I')) != 0);
|
||||
sim_switches = saved_switches;
|
||||
}
|
||||
if (stat != SCPE_OK)
|
||||
break;
|
||||
tptr = get_glyph (tptr, gbuf, 0); /* get next glyph */
|
||||
reg = find_reg (gbuf, &tptr, sim_dfdev);
|
||||
if (reg == NULL) {
|
||||
stat = sim_messagef (SCPE_NXREG, "Nonexistent Register: %s\n", gbuf);
|
||||
break;
|
||||
}
|
||||
smp_regs = (BITSAMPLE_REG *)realloc (rem->smp_regs, (rem->smp_reg_count + 1) * sizeof(*smp_regs));
|
||||
if (smp_regs == NULL) {
|
||||
stat = SCPE_MEM;
|
||||
break;
|
||||
}
|
||||
rem->smp_regs = smp_regs;
|
||||
smp_regs[rem->smp_reg_count].reg = reg;
|
||||
smp_regs[rem->smp_reg_count].dptr = sim_dfdev;
|
||||
smp_regs[rem->smp_reg_count].uptr = sim_dfunit;
|
||||
smp_regs[rem->smp_reg_count].indirect = indirect;
|
||||
width = indirect ? sim_dfdev->dwidth : reg->width;
|
||||
smp_regs[rem->smp_reg_count].width = width;
|
||||
smp_regs[rem->smp_reg_count].bits = (BITSAMPLE *)calloc (width, sizeof (*smp_regs[rem->smp_reg_count - 1].bits));
|
||||
if (smp_regs[rem->smp_reg_count].bits == NULL) {
|
||||
stat = SCPE_MEM;
|
||||
break;
|
||||
}
|
||||
rem->smp_reg_count += 1;
|
||||
for (bit = 0; bit < width; bit++) {
|
||||
smp_regs[rem->smp_reg_count - 1].bits[bit].depth = samples;
|
||||
smp_regs[rem->smp_reg_count - 1].bits[bit].vals = (int *)calloc (samples, sizeof (int));
|
||||
if (smp_regs[rem->smp_reg_count - 1].bits[bit].vals == NULL) {
|
||||
stat = SCPE_MEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stat != SCPE_OK)
|
||||
break;
|
||||
}
|
||||
if (stat != SCPE_OK) { /* Error? */
|
||||
*iptr = cptr;
|
||||
cptr = strcpy (gbuf, "STOP");
|
||||
sim_rem_collect_cmd_setup (line, &cptr);/* Cleanup mess */
|
||||
return stat;
|
||||
}
|
||||
sim_activate (&rem_con_smp_smpl_units[rem->line], rem->smp_sample_interval);
|
||||
}
|
||||
*iptr = cptr;
|
||||
return stat;
|
||||
}
|
||||
|
||||
t_stat sim_rem_con_repeat_svc (UNIT *uptr)
|
||||
{
|
||||
int line = uptr - rem_con_repeat_units;
|
||||
REMOTE *rem = &sim_rem_consoles[line];
|
||||
|
||||
sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_repeat_svc(line=%d) - interval=%d\n", line, rem->repeat_interval);
|
||||
if (rem->repeat_interval) {
|
||||
rem->repeat_pending = TRUE;
|
||||
sim_activate_after (uptr, rem->repeat_interval); /* reschedule */
|
||||
sim_activate_abs (rem_con_data_unit, -1); /* wake up to process */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static void sim_rem_record_reg_bit (BITSAMPLE *bit, int val)
|
||||
{
|
||||
bit->tot -= bit->vals[bit->ptr]; /* remove retired value */
|
||||
bit->tot += val; /* accumulate new value */
|
||||
bit->vals[bit->ptr] = val; /* save new value */
|
||||
++bit->ptr; /* increment next pointer */
|
||||
if (bit->ptr >= bit->depth) /* if too big */
|
||||
bit->ptr = 0; /* wrap around */
|
||||
}
|
||||
|
||||
static void sim_rem_set_reg_bit (BITSAMPLE *bit, int val)
|
||||
{
|
||||
int i;
|
||||
|
||||
bit->tot = bit->depth * val; /* compute total */
|
||||
for (i = 0; i < bit->depth; i++) /* set all value bits */
|
||||
bit->vals[i] = val;
|
||||
}
|
||||
|
||||
static void sim_rem_collect_reg_bits (BITSAMPLE_REG *reg)
|
||||
{
|
||||
uint32 i;
|
||||
t_value val = get_rval (reg->reg, 0);
|
||||
|
||||
if (reg->indirect)
|
||||
val = get_aval ((t_addr)val, reg->dptr, reg->uptr);
|
||||
val = val >> reg->reg->offset;
|
||||
for (i = 0; i < reg->width; i++) {
|
||||
if (sim_is_running)
|
||||
sim_rem_record_reg_bit (®->bits[i], val&1);
|
||||
else
|
||||
sim_rem_set_reg_bit (®->bits[i], val&1);
|
||||
val = val >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void sim_rem_collect_registers (REMOTE *rem)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
for (i = 0; i < rem->smp_reg_count; i++)
|
||||
sim_rem_collect_reg_bits (&rem->smp_regs[i]);
|
||||
}
|
||||
|
||||
static void sim_rem_collect_all_registers (void)
|
||||
{
|
||||
int32 line;
|
||||
|
||||
for (line = 0; line < sim_rem_con_tmxr.lines; line++)
|
||||
sim_rem_collect_registers (&sim_rem_consoles[line]);
|
||||
}
|
||||
|
||||
t_stat sim_rem_con_smp_collect_svc (UNIT *uptr)
|
||||
{
|
||||
int line = uptr - rem_con_smp_smpl_units;
|
||||
REMOTE *rem = &sim_rem_consoles[line];
|
||||
|
||||
sim_debug (DBG_SAM, &sim_remote_console, "sim_rem_con_smp_collect_svc(line=%d) - interval=%d\n", line, rem->smp_sample_interval);
|
||||
if (rem->smp_sample_interval && (rem->smp_reg_count != 0)) {
|
||||
sim_rem_collect_registers (rem);
|
||||
sim_activate (uptr, rem->smp_sample_interval); /* reschedule */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Unit service for remote console data polling */
|
||||
|
||||
t_stat sim_rem_con_data_svc (UNIT *uptr)
|
||||
|
@ -969,7 +1281,11 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
|||
if (!lp->conn) {
|
||||
if (rem->repeat_interval) { /* was repeated enabled? */
|
||||
cptr = strcpy (gbuf, "STOP");
|
||||
_rem_repeat_cmd_setup (i, &cptr); /* make sure it is now disabled */
|
||||
sim_rem_repeat_cmd_setup (i, &cptr); /* make sure it is now disabled */
|
||||
}
|
||||
if (rem->smp_reg_count) { /* were bit samples being collected? */
|
||||
cptr = strcpy (gbuf, "STOP");
|
||||
sim_rem_collect_cmd_setup (i, &cptr); /* make sure it is now disabled */
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -996,6 +1312,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
|||
}
|
||||
else {
|
||||
sim_is_running = 0;
|
||||
sim_rem_collect_all_registers ();
|
||||
sim_stop_timer_services ();
|
||||
for (j=0; j < sim_rem_con_tmxr.lines; j++) {
|
||||
TMLN *lpj = &sim_rem_con_tmxr.ldsc[j];
|
||||
|
@ -1016,6 +1333,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
|||
if (c == sim_int_char) { /* ^E (the interrupt character) must start continue mode console interaction */
|
||||
rem->single_mode = FALSE; /* enter multi command mode */
|
||||
sim_is_running = 0;
|
||||
sim_rem_collect_all_registers ();
|
||||
sim_stop_timer_services ();
|
||||
stat = SCPE_STOP;
|
||||
_sim_rem_message ("RUN", stat);
|
||||
|
@ -1254,7 +1572,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
|||
}
|
||||
else {
|
||||
if ((cmdp = find_ctab (rem->single_mode ? allowed_single_remote_cmds : (master_session ? allowed_master_remote_cmds : allowed_remote_cmds), gbuf))) {/* lookup command */
|
||||
sim_debug (DBG_CMD, &sim_remote_console, "gbuf='%s', basecmd='%s', cmd='%s', action=%p, continue_cmd=%p, repeat_cmd=%p\n", gbuf, basecmdp->name, cmdp->name, cmdp->action, &x_continue_cmd, &x_repeat_cmd);
|
||||
sim_debug (DBG_CMD, &sim_remote_console, "gbuf='%s', basecmd='%s', cmd='%s'\n", gbuf, basecmdp->name, cmdp->name);
|
||||
if (cmdp->action == &x_continue_cmd) {
|
||||
sim_debug (DBG_CMD, &sim_remote_console, "continue_cmd executing\n");
|
||||
stat = SCPE_OK;
|
||||
|
@ -1294,21 +1612,34 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (cmdp->action == &x_repeat_cmd) {
|
||||
sim_debug (DBG_CMD, &sim_remote_console, "repeat_cmd executing\n");
|
||||
stat = _rem_repeat_cmd_setup (i, &cptr);
|
||||
if (cmdp->action == &x_sampleout_cmd) {
|
||||
sim_debug (DBG_CMD, &sim_remote_console, "sampleout_cmd executing\n");
|
||||
sim_oline = lp; /* specify output socket */
|
||||
stat = sim_rem_sample_output (NULL, i);
|
||||
}
|
||||
else {
|
||||
if (sim_con_stable_registers &&
|
||||
sim_rem_master_mode) { /* can we process command now? */
|
||||
sim_debug (DBG_CMD, &sim_remote_console, "Processing Command directly\n");
|
||||
sim_oline = lp; /* specify output socket */
|
||||
sim_remote_process_command ();
|
||||
stat = SCPE_OK; /* any message has already been emitted */
|
||||
if (cmdp->action == &x_repeat_cmd) {
|
||||
sim_debug (DBG_CMD, &sim_remote_console, "repeat_cmd executing\n");
|
||||
stat = sim_rem_repeat_cmd_setup (i, &cptr);
|
||||
}
|
||||
else {
|
||||
sim_debug (DBG_CMD, &sim_remote_console, "Processing Command via SCPE_REMOTE\n");
|
||||
stat = SCPE_REMOTE; /* force processing outside of sim_instr() */
|
||||
if (cmdp->action == &x_collect_cmd) {
|
||||
sim_debug (DBG_CMD, &sim_remote_console, "sample_cmd executing\n");
|
||||
stat = sim_rem_collect_cmd_setup (i, &cptr);
|
||||
}
|
||||
else {
|
||||
if (sim_con_stable_registers &&
|
||||
sim_rem_master_mode) { /* can we process command now? */
|
||||
sim_debug (DBG_CMD, &sim_remote_console, "Processing Command directly\n");
|
||||
sim_oline = lp; /* specify output socket */
|
||||
sim_remote_process_command ();
|
||||
stat = SCPE_OK; /* any message has already been emitted */
|
||||
}
|
||||
else {
|
||||
sim_debug (DBG_CMD, &sim_remote_console, "Processing Command via SCPE_REMOTE\n");
|
||||
stat = SCPE_REMOTE; /* force processing outside of sim_instr() */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1402,20 +1733,6 @@ else
|
|||
return SCPE_OK; /* keep going */
|
||||
}
|
||||
|
||||
t_stat sim_rem_con_repeat_svc (UNIT *uptr)
|
||||
{
|
||||
int line = uptr - rem_con_repeat_units;
|
||||
REMOTE *rem = &sim_rem_consoles[line];
|
||||
|
||||
sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_repeat_svc(line=%d) - interval=%d\n", line, rem->repeat_interval);
|
||||
if (rem->repeat_interval) {
|
||||
rem->repeat_pending = TRUE;
|
||||
sim_activate_after (uptr, rem->repeat_interval); /* reschedule */
|
||||
sim_activate_abs (rem_con_data_unit, -1); /* wake up to process */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat sim_rem_con_reset (DEVICE *dptr)
|
||||
{
|
||||
if (sim_rem_con_tmxr.lines) {
|
||||
|
@ -1429,7 +1746,9 @@ if (sim_rem_con_tmxr.lines) {
|
|||
continue;
|
||||
sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_reset(line=%d, usecs=%d)\n", i, rem->repeat_interval);
|
||||
if (rem->repeat_interval)
|
||||
sim_activate_after (rem_con_repeat_units + i, rem->repeat_interval);/* schedule */
|
||||
sim_activate_after (&rem_con_repeat_units[rem->line], rem->repeat_interval); /* schedule */
|
||||
if (rem->smp_reg_count)
|
||||
sim_activate (&rem_con_smp_smpl_units[rem->line], rem->smp_sample_interval); /* schedule */
|
||||
}
|
||||
if (i != sim_rem_con_tmxr.lines)
|
||||
sim_activate_after (rem_con_data_unit, 100000); /* continue polling for open sessions */
|
||||
|
@ -1501,13 +1820,14 @@ for (i=0; i<sim_rem_con_tmxr.lines; i++) {
|
|||
free (rem->act);
|
||||
free (rem->repeat_action);
|
||||
sim_cancel (&rem_con_repeat_units[i]);
|
||||
sim_cancel (&rem_con_smp_smpl_units[i]);
|
||||
}
|
||||
sim_rem_con_tmxr.lines = lines;
|
||||
sim_rem_con_tmxr.ldsc = (TMLN *)realloc (sim_rem_con_tmxr.ldsc, sizeof(*sim_rem_con_tmxr.ldsc)*lines);
|
||||
memset (sim_rem_con_tmxr.ldsc, 0, sizeof(*sim_rem_con_tmxr.ldsc)*lines);
|
||||
sim_remote_console.units = (UNIT *)realloc (sim_remote_console.units, sizeof(*sim_remote_console.units)*(lines + REM_CON_BASE_UNITS));
|
||||
memset (sim_remote_console.units, 0, sizeof(*sim_remote_console.units)*(lines + REM_CON_BASE_UNITS));
|
||||
sim_remote_console.numunits = lines + REM_CON_BASE_UNITS;
|
||||
sim_remote_console.units = (UNIT *)realloc (sim_remote_console.units, sizeof(*sim_remote_console.units)*((2 * lines) + REM_CON_BASE_UNITS));
|
||||
memset (sim_remote_console.units, 0, sizeof(*sim_remote_console.units)*((2 * lines) + REM_CON_BASE_UNITS));
|
||||
sim_remote_console.numunits = (2 * lines) + REM_CON_BASE_UNITS;
|
||||
rem_con_poll_unit->action = &sim_rem_con_poll_svc;/* remote console connection polling unit */
|
||||
rem_con_poll_unit->flags |= UNIT_IDLE;
|
||||
rem_con_data_unit->action = &sim_rem_con_data_svc;/* console data handling unit */
|
||||
|
@ -1519,6 +1839,8 @@ memset (sim_rem_command_buf, 0, 4*CBUFSIZE+1);
|
|||
for (i=0; i<lines; i++) {
|
||||
rem_con_repeat_units[i].flags = UNIT_DIS;
|
||||
rem_con_repeat_units[i].action = &sim_rem_con_repeat_svc;
|
||||
rem_con_smp_smpl_units[i].flags = UNIT_DIS;
|
||||
rem_con_smp_smpl_units[i].action = &sim_rem_con_smp_collect_svc;
|
||||
rem = &sim_rem_consoles[i];
|
||||
rem->line = i;
|
||||
rem->lp = &sim_rem_con_tmxr.ldsc[i];
|
||||
|
|
188
sim_frontpanel.c
188
sim_frontpanel.c
|
@ -119,6 +119,8 @@ typedef struct {
|
|||
size_t size;
|
||||
int indirect;
|
||||
size_t element_count;
|
||||
int *bits;
|
||||
size_t bit_count;
|
||||
} REG;
|
||||
|
||||
struct PANEL {
|
||||
|
@ -158,6 +160,8 @@ struct PANEL {
|
|||
int callback_thread_running;
|
||||
void *callback_context;
|
||||
int usecs_between_callbacks;
|
||||
unsigned int sample_frequency;
|
||||
unsigned int sample_depth;
|
||||
int debug;
|
||||
char *simulator_version;
|
||||
int radix;
|
||||
|
@ -175,6 +179,10 @@ static const char *register_repeat_stop = "repeat stop";
|
|||
static const char *register_repeat_stop_all = "repeat stop all";
|
||||
static const char *register_repeat_units = " usecs ";
|
||||
static const char *register_get_prefix = "show time";
|
||||
static const char *register_collect_prefix = "collect ";
|
||||
static const char *register_collect_mid1 = " samples every ";
|
||||
static const char *register_collect_mid2 = " cycles ";
|
||||
static const char *register_get_postfix = "sampleout";
|
||||
static const char *register_get_echo = "# REGISTERS-DONE";
|
||||
static const char *register_repeat_echo = "# REGISTERS-REPEAT-DONE";
|
||||
static const char *register_dev_echo = "# REGISTERS-FOR-DEVICE:";
|
||||
|
@ -374,18 +382,25 @@ _panel_sendf (PANEL *p, int *completion_status, char **response, const char *fmt
|
|||
static int
|
||||
_panel_register_query_string (PANEL *panel, char **buf, size_t *buf_size)
|
||||
{
|
||||
size_t i, j, buf_data, buf_needed = 0;
|
||||
size_t i, j, buf_data, buf_needed = 0, reg_count = 0, bit_reg_count = 0;
|
||||
const 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 += 9 + strlen (panel->regs[i].name) + (panel->regs[i].device_name ? strlen (panel->regs[i].device_name) : 0);
|
||||
if (panel->regs[i].element_count > 0)
|
||||
buf_needed += 4 + 6 /* 6 digit register array index */;
|
||||
if (panel->regs[i].indirect)
|
||||
buf_needed += 12 + strlen (register_ind_echo) + strlen (panel->regs[i].name);
|
||||
if (panel->regs[i].bits)
|
||||
++bit_reg_count;
|
||||
else {
|
||||
++reg_count;
|
||||
buf_needed += 9 + strlen (panel->regs[i].name) + (panel->regs[i].device_name ? strlen (panel->regs[i].device_name) : 0);
|
||||
if (panel->regs[i].element_count > 0)
|
||||
buf_needed += 4 + 6 /* 6 digit register array index */;
|
||||
if (panel->regs[i].indirect)
|
||||
buf_needed += 12 + strlen (register_ind_echo) + strlen (panel->regs[i].name);
|
||||
}
|
||||
}
|
||||
if (bit_reg_count)
|
||||
buf_needed += 2 + strlen (register_get_postfix);
|
||||
buf_needed += 10 + strlen (register_get_echo); /* # REGISTERS-DONE */
|
||||
if (buf_needed > *buf_size) {
|
||||
free (*buf);
|
||||
|
@ -398,13 +413,15 @@ if (buf_needed > *buf_size) {
|
|||
*buf_size = buf_needed;
|
||||
}
|
||||
buf_data = 0;
|
||||
sprintf (*buf + buf_data, "%s\r", register_get_prefix);
|
||||
buf_data += strlen (*buf + buf_data);
|
||||
if (reg_count) {
|
||||
sprintf (*buf + buf_data, "%s\r", register_get_prefix);
|
||||
buf_data += strlen (*buf + buf_data);
|
||||
}
|
||||
dev = "";
|
||||
for (i=j=0; i<panel->reg_count; i++) {
|
||||
const char *reg_dev = panel->regs[i].device_name ? panel->regs[i].device_name : "";
|
||||
|
||||
if (panel->regs[i].indirect)
|
||||
if ((panel->regs[i].indirect) || (panel->regs[i].bits))
|
||||
continue;
|
||||
if (strcmp (dev, reg_dev)) {/* devices are different */
|
||||
char *tbuf;
|
||||
|
@ -447,11 +464,17 @@ if (buf_data && ((*buf)[buf_data-1] != '\r')) {
|
|||
for (i=j=0; i<panel->reg_count; i++) {
|
||||
const char *reg_dev = panel->regs[i].device_name ? panel->regs[i].device_name : "";
|
||||
|
||||
if (!panel->regs[i].indirect)
|
||||
if ((!panel->regs[i].indirect) || (panel->regs[i].bits))
|
||||
continue;
|
||||
sprintf (*buf + buf_data, "%s%s\rE -H %s %s,$\r", register_ind_echo, panel->regs[i].name, reg_dev, panel->regs[i].name);
|
||||
buf_data += strlen (*buf + buf_data);
|
||||
}
|
||||
if (bit_reg_count) {
|
||||
strcpy (*buf + buf_data, register_get_postfix);
|
||||
buf_data += strlen (*buf + buf_data);
|
||||
strcpy (*buf + buf_data, "\r");
|
||||
buf_data += strlen (*buf + buf_data);
|
||||
}
|
||||
strcpy (*buf + buf_data, register_get_echo);
|
||||
buf_data += strlen (*buf + buf_data);
|
||||
strcpy (*buf + buf_data, "\r");
|
||||
|
@ -461,6 +484,53 @@ pthread_mutex_unlock (&panel->io_lock);
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_panel_establish_register_bits_collection (PANEL *panel)
|
||||
{
|
||||
size_t i, buf_data, buf_needed = 0, reg_count = 0, bit_reg_count = 0;
|
||||
int cmd_stat, bits_count = 0;
|
||||
char *buf, *response = NULL;
|
||||
|
||||
pthread_mutex_lock (&panel->io_lock);
|
||||
for (i=0; i<panel->reg_count; i++) {
|
||||
if (panel->regs[i].bits)
|
||||
buf_needed += 9 + strlen (panel->regs[i].name) + (panel->regs[i].device_name ? strlen (panel->regs[i].device_name) : 0);
|
||||
}
|
||||
buf = (char *)_panel_malloc (buf_needed);
|
||||
if (!buf) {
|
||||
panel->State = Error;
|
||||
pthread_mutex_unlock (&panel->io_lock);
|
||||
return -1;
|
||||
}
|
||||
*buf = '\0';
|
||||
buf_data = 0;
|
||||
for (i=0; i<panel->reg_count; i++) {
|
||||
if (panel->regs[i].bits) {
|
||||
++bits_count;
|
||||
sprintf (buf + buf_data, "%s%s", (bits_count != 1) ? "," : "", panel->regs[i].indirect ? "-I " : "");
|
||||
buf_data += strlen (buf + buf_data);
|
||||
if (panel->regs[i].device_name) {
|
||||
sprintf (buf + buf_data, "%s ", panel->regs[i].device_name);
|
||||
buf_data += strlen (buf + buf_data);
|
||||
}
|
||||
sprintf (buf + buf_data, "%s", panel->regs[i].name);
|
||||
buf_data += strlen (buf + buf_data);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock (&panel->io_lock);
|
||||
if (_panel_sendf (panel, &cmd_stat, &response, "%s%u%s%u%s%s\r", register_collect_prefix, panel->sample_depth,
|
||||
register_collect_mid1, panel->sample_frequency,
|
||||
register_collect_mid2, buf)) {
|
||||
sim_panel_set_error ("Error establishing bit data collection:%s", response);
|
||||
free (response);
|
||||
free (buf);
|
||||
return -1;
|
||||
}
|
||||
free (response);
|
||||
free (buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PANEL **panels = NULL;
|
||||
static int panel_count = 0;
|
||||
|
||||
|
@ -927,7 +997,9 @@ _panel_add_register (PANEL *panel,
|
|||
size_t size,
|
||||
void *addr,
|
||||
int indirect,
|
||||
size_t element_count)
|
||||
size_t element_count,
|
||||
int *bits,
|
||||
size_t bit_count)
|
||||
{
|
||||
REG *regs, *reg;
|
||||
char *response = NULL;
|
||||
|
@ -942,6 +1014,10 @@ if (panel->State == Run) {
|
|||
sim_panel_set_error ("Not Halted");
|
||||
return -1;
|
||||
}
|
||||
if ((bit_count != 0) && (panel->sample_depth == 0)) {
|
||||
sim_panel_set_error ("sim_panel_set_sampling_parameters() must be called first");
|
||||
return -1;
|
||||
}
|
||||
regs = (REG *)_panel_malloc ((1 + panel->reg_count)*sizeof(*regs));
|
||||
if (regs == NULL) {
|
||||
panel->State = Error;
|
||||
|
@ -959,6 +1035,11 @@ if (reg->name == NULL) {
|
|||
}
|
||||
strcpy (reg->name, name);
|
||||
reg->indirect = indirect;
|
||||
reg->addr = addr;
|
||||
reg->size = size;
|
||||
reg->element_count = element_count;
|
||||
reg->bits = bits;
|
||||
reg->bit_count = bit_count;
|
||||
for (i=0; i<strlen (reg->name); i++) {
|
||||
if (islower (reg->name[i]))
|
||||
reg->name[i] = toupper (reg->name[i]);
|
||||
|
@ -992,7 +1073,9 @@ for (i=0; i<panel->reg_count; i++) {
|
|||
}
|
||||
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)) && (reg->indirect == regs[i].indirect)) {
|
||||
if ((!strcmp (t1, t2)) &&
|
||||
(reg->indirect == regs[i].indirect) &&
|
||||
((reg->bits == NULL) == (regs[i].bits == NULL))) {
|
||||
sim_panel_set_error ("Duplicate Register Declaration");
|
||||
free (t1);
|
||||
free (t2);
|
||||
|
@ -1004,9 +1087,6 @@ for (i=0; i<panel->reg_count; i++) {
|
|||
free (t1);
|
||||
free (t2);
|
||||
}
|
||||
reg->addr = addr;
|
||||
reg->size = size;
|
||||
reg->element_count = element_count;
|
||||
pthread_mutex_unlock (&panel->io_lock);
|
||||
/* Validate existence of requested register/array */
|
||||
if (_panel_sendf (panel, &cmd_stat, &response, "EXAMINE %s %s%s\r", device_name? device_name : "", name, (element_count > 0) ? "[0]" : "")) {
|
||||
|
@ -1050,6 +1130,11 @@ pthread_mutex_unlock (&panel->io_lock);
|
|||
/* Now build the register query string for the whole register list */
|
||||
if (_panel_register_query_string (panel, &panel->reg_query, &panel->reg_query_size))
|
||||
return -1;
|
||||
if (bits) {
|
||||
memset (bits, 0, sizeof (*bits) * bit_count);
|
||||
if (_panel_establish_register_bits_collection (panel))
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1060,7 +1145,17 @@ sim_panel_add_register (PANEL *panel,
|
|||
size_t size,
|
||||
void *addr)
|
||||
{
|
||||
return _panel_add_register (panel, name, device_name, size, addr, 0, 0);
|
||||
return _panel_add_register (panel, name, device_name, size, addr, 0, 0, NULL, 0);
|
||||
}
|
||||
|
||||
int
|
||||
sim_panel_add_register_bits (PANEL *panel,
|
||||
const char *name,
|
||||
const char *device_name,
|
||||
size_t bit_width,
|
||||
int *bits)
|
||||
{
|
||||
return _panel_add_register (panel, name, device_name, 0, NULL, 0, 0, bits, bit_width);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1071,7 +1166,7 @@ sim_panel_add_register_array (PANEL *panel,
|
|||
size_t size,
|
||||
void *addr)
|
||||
{
|
||||
return _panel_add_register (panel, name, device_name, size, addr, 0, element_count);
|
||||
return _panel_add_register (panel, name, device_name, size, addr, 0, element_count, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1082,7 +1177,17 @@ sim_panel_add_register_indirect (PANEL *panel,
|
|||
size_t size,
|
||||
void *addr)
|
||||
{
|
||||
return _panel_add_register (panel, name, device_name, size, addr, 1, 0);
|
||||
return _panel_add_register (panel, name, device_name, size, addr, 1, 0, NULL, 0);
|
||||
}
|
||||
|
||||
int
|
||||
sim_panel_add_register_indirect_bits (PANEL *panel,
|
||||
const char *name,
|
||||
const char *device_name,
|
||||
size_t bit_width,
|
||||
int *bits)
|
||||
{
|
||||
return _panel_add_register (panel, name, device_name, 0, NULL, 1, 0, bits, bit_width);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1165,6 +1270,24 @@ pthread_mutex_unlock (&panel->io_lock);
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sim_panel_set_sampling_parameters (PANEL *panel,
|
||||
unsigned int sample_frequency,
|
||||
unsigned int sample_depth)
|
||||
{
|
||||
if (sample_frequency == 0) {
|
||||
sim_panel_set_error ("Invalid sample frequency value: %u", sample_frequency);
|
||||
return -1;
|
||||
}
|
||||
if (sample_depth == 0) {
|
||||
sim_panel_set_error ("Invalid sample depth value: %u", sample_depth);
|
||||
return -1;
|
||||
}
|
||||
panel->sample_frequency = sample_frequency;
|
||||
panel->sample_depth = sample_depth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sim_panel_exec_halt (PANEL *panel)
|
||||
{
|
||||
|
@ -1760,6 +1883,8 @@ while ((p->sock != INVALID_SOCKET) &&
|
|||
e = strchr (s, ':');
|
||||
if (e) {
|
||||
size_t i;
|
||||
char smp_dev[32], smp_reg[32], smp_ind[32];
|
||||
unsigned int bit;
|
||||
|
||||
*e++ = '\0';
|
||||
if (!strcmp("Time", s)) {
|
||||
|
@ -1769,6 +1894,33 @@ while ((p->sock != INVALID_SOCKET) &&
|
|||
++s;
|
||||
continue;
|
||||
}
|
||||
if ((*s == '}') &&
|
||||
(3 == sscanf (s, "}%s %s %s", smp_dev, smp_reg, smp_ind))) { /* Register bit Sample Data? */
|
||||
r = NULL;
|
||||
for (i=0; i<p->reg_count; i++) {
|
||||
if (p->regs[i].bits == NULL)
|
||||
continue;
|
||||
if ((!strcmp (smp_reg, p->regs[i].name)) &&
|
||||
((!p->device_name) || (!strcmp (smp_dev, p->device_name)))) {
|
||||
r = &p->regs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (r) {
|
||||
for (bit = 0; bit < r->bit_count; bit++) {
|
||||
int val = (int)strtol (e, &e, 10);
|
||||
r->bits[bit] = val;
|
||||
if (*e == ',')
|
||||
++e;
|
||||
else
|
||||
break;
|
||||
}
|
||||
s = eol;
|
||||
}
|
||||
while (isspace(0xFF & (*s)))
|
||||
++s;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp (s + strlen (sim_prompt), register_ind_echo, strlen (register_ind_echo) - 1)) {
|
||||
e = s + strlen (sim_prompt) + strlen (register_ind_echo);
|
||||
r = NULL;
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
into the application.
|
||||
4) Use a simh simulator built from the same version of simh that the
|
||||
sim_frontpanel and sim_sock modules came from.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SIM_FRONTPANEL_H_
|
||||
|
@ -57,7 +56,7 @@ extern "C" {
|
|||
|
||||
#if !defined(__VAX) /* Unsupported platform */
|
||||
|
||||
#define SIM_FRONTPANEL_VERSION 3
|
||||
#define SIM_FRONTPANEL_VERSION 4
|
||||
|
||||
/**
|
||||
|
||||
|
@ -78,7 +77,6 @@ extern "C" {
|
|||
Note 2: - Configuration file specified should contain device setup
|
||||
statements (enable, disable, CPU types and attach commands).
|
||||
It should not start a simulator running.
|
||||
|
||||
*/
|
||||
|
||||
typedef struct PANEL PANEL;
|
||||
|
@ -101,8 +99,8 @@ sim_panel_start_simulator_debug (const char *sim_path,
|
|||
|
||||
simulator_panel the simulator panel to connect to
|
||||
device_name the simulator's name for the device
|
||||
|
||||
*/
|
||||
|
||||
PANEL *
|
||||
sim_panel_add_device_panel (PANEL *simulator_panel,
|
||||
const char *device_name);
|
||||
|
@ -113,8 +111,8 @@ sim_panel_add_device_panel (PANEL *simulator_panel,
|
|||
|
||||
Note: destroying a simulator panel will also destroy any
|
||||
related sub panels
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
sim_panel_destroy (PANEL *panel);
|
||||
|
||||
|
@ -128,12 +126,14 @@ sim_panel_destroy (PANEL *panel);
|
|||
simulator.
|
||||
|
||||
The registers that a particular frontpanel application mught need
|
||||
access to are described by the application when it calls:
|
||||
access to are specified by the application when it calls:
|
||||
|
||||
sim_panel_add_register
|
||||
sim_panel_add_register_bits
|
||||
sim_panel_add_register_array
|
||||
and
|
||||
sim_panel_add_register_indirect
|
||||
sim_panel_add_register_indirect_bits
|
||||
|
||||
name the name the simulator knows this register by
|
||||
device_name the device this register is part of. Defaults to
|
||||
|
@ -144,8 +144,14 @@ and
|
|||
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
|
||||
|
||||
bit_width the number of values to populate in the bits array
|
||||
bits an array of integers which is bit_width long that
|
||||
will receive each bit's current accumulated value.
|
||||
The accumulated value will range from 0 thru the
|
||||
the sample_depth specified when calling
|
||||
sim_panel_set_sampling_parameters().
|
||||
*/
|
||||
|
||||
int
|
||||
sim_panel_add_register (PANEL *panel,
|
||||
const char *name,
|
||||
|
@ -153,6 +159,13 @@ sim_panel_add_register (PANEL *panel,
|
|||
size_t size,
|
||||
void *addr);
|
||||
|
||||
int
|
||||
sim_panel_add_register_bits (PANEL *panel,
|
||||
const char *name,
|
||||
const char *device_name,
|
||||
size_t bit_width,
|
||||
int *bits);
|
||||
|
||||
int
|
||||
sim_panel_add_register_array (PANEL *panel,
|
||||
const char *name,
|
||||
|
@ -167,11 +180,19 @@ sim_panel_add_register_indirect (PANEL *panel,
|
|||
const char *device_name,
|
||||
size_t size,
|
||||
void *addr);
|
||||
|
||||
int
|
||||
sim_panel_add_register_indirect_bits (PANEL *panel,
|
||||
const char *name,
|
||||
const char *device_name,
|
||||
size_t bit_width,
|
||||
int *bits);
|
||||
|
||||
/**
|
||||
|
||||
A panel application has a choice of two different methods of getting
|
||||
the values contained in the set of registers it has declared interest in via
|
||||
the sim_panel_add_register API.
|
||||
the sim_panel_add_register APIs.
|
||||
|
||||
1) The values can be polled (when ever it is desired) by calling
|
||||
sim_panel_get_registers().
|
||||
|
@ -189,15 +210,11 @@ sim_panel_add_register_indirect (PANEL *panel,
|
|||
or frontpanel interactions with the simulator may be disrupted.
|
||||
Setting a flag, signaling an event or posting a message are
|
||||
reasonable activities to perform in a callback routine.
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
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);
|
||||
|
@ -208,6 +225,26 @@ sim_panel_set_display_callback_interval (PANEL *panel,
|
|||
void *context,
|
||||
int usecs_between_callbacks);
|
||||
|
||||
/**
|
||||
|
||||
When a front panel application wants to get averaged bit sample
|
||||
values, it must first declare the sampling parameters that will
|
||||
be used while collecting the bit values.
|
||||
|
||||
sim_panel_set_sampling_parameters
|
||||
|
||||
sample_frequency cycles/instructions between sample captures
|
||||
sample_depth how many samples to accumulate in the rolling
|
||||
average for each bit sample. Returned bit
|
||||
sample values will range from 0 thru this
|
||||
value.
|
||||
*/
|
||||
|
||||
int
|
||||
sim_panel_set_sampling_parameters (PANEL *panel,
|
||||
unsigned int sample_frequency,
|
||||
unsigned int sample_depth);
|
||||
|
||||
/**
|
||||
|
||||
When a front panel application needs to change the running
|
||||
|
@ -218,8 +255,8 @@ sim_panel_set_display_callback_interval (PANEL *panel,
|
|||
sim_panel_exec_boot - Boot a simulator from a specific device
|
||||
sim_panel_exec_run - Start/Resume a simulator running instructions
|
||||
sim_panel_exec_step - Have a simulator execute a single step
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
sim_panel_exec_halt (PANEL *panel);
|
||||
|
||||
|
@ -249,7 +286,6 @@ sim_panel_exec_step (PANEL *panel);
|
|||
|
||||
Note: Any breakpoint switches/flags must be located at the
|
||||
beginning of the condition string
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
|
@ -277,7 +313,6 @@ sim_panel_break_output_clear (PANEL *panel, const char *condition);
|
|||
sim_panel_mem_deposit - Deposit to memory location
|
||||
sim_panel_set_register_value - Deposit to a register or memory
|
||||
location
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
@ -359,6 +394,7 @@ sim_panel_mem_deposit (PANEL *panel,
|
|||
const void *value);
|
||||
|
||||
/**
|
||||
|
||||
sim_panel_set_register_value
|
||||
|
||||
name the name of a simulator register or a memory address
|
||||
|
@ -366,7 +402,6 @@ sim_panel_mem_deposit (PANEL *panel,
|
|||
value the new value in character string form. The string
|
||||
must be in the native/natural radix that the simulator
|
||||
uses when referencing that register
|
||||
|
||||
*/
|
||||
int
|
||||
sim_panel_set_register_value (PANEL *panel,
|
||||
|
@ -375,24 +410,24 @@ sim_panel_set_register_value (PANEL *panel,
|
|||
|
||||
/**
|
||||
|
||||
When a front panel application may needs to change the media
|
||||
When a front panel application needs to change the media
|
||||
in a simulated removable media device one of the following
|
||||
routines should be called:
|
||||
|
||||
sim_panel_mount - mounts the indicated media file on a device
|
||||
sim_panel_dismount - dismounts the currently mounted media file
|
||||
from a device
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
sim_panel_mount
|
||||
|
||||
device the name of a simulator device/unit
|
||||
switches any switches appropriate for the desire attach
|
||||
path the path on the local system to be attached
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
sim_panel_mount (PANEL *panel,
|
||||
const char *device,
|
||||
|
@ -400,11 +435,12 @@ sim_panel_mount (PANEL *panel,
|
|||
const char *path);
|
||||
|
||||
/**
|
||||
|
||||
sim_panel_dismount
|
||||
|
||||
device the name of a simulator device/unit
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
sim_panel_dismount (PANEL *panel,
|
||||
const char *device);
|
||||
|
@ -430,7 +466,6 @@ sim_panel_get_state (PANEL *panel);
|
|||
|
||||
sim_panel_get_error - the details of the most recent error
|
||||
sim_panel_clear_error - clears the error buffer
|
||||
|
||||
*/
|
||||
|
||||
const char *sim_panel_get_error (void);
|
||||
|
|
Loading…
Add table
Reference in a new issue