From 5a4bbbad8d75dec697e00b564286a14e668703b3 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Mon, 20 Oct 2014 16:47:33 -0700 Subject: [PATCH] SCP: Extended EXPECT and SEND to have more flexible activation delays - EXPECT will now tolerate a HALTAFTER=n parameter which delay the simulator stopping execution for n instructions. Unpredictable behavior will happen if multiple EXPECT conditions see matching data before the first actualy halt occurs. - SEND has an AFTER=n argument which delays the initial stuffed data from being input for at least n instructions. It also has a DELAY=m argument which specifies the minimum number of instructions which must execute between stuffed input data. - Changed run_cmd() to no longer clear pending breakpoint actions before starting instruction execution. - Added a -Q switch to the commands which dispatch through run_cmd() (RUN, STEP, NEXT, GO, BOOT, etc.). This switch will suppress status output when execution stops. This will allow sequences of breakpoint action commands to silently execute when needed. --- scp.c | 77 ++++++++++++++++++++++++++++++++++++++++-------------- scp.h | 4 +-- sim_defs.h | 32 ++++++++++++----------- 3 files changed, 77 insertions(+), 36 deletions(-) diff --git a/scp.c b/scp.c index 596624db..ede4435b 100644 --- a/scp.c +++ b/scp.c @@ -3025,6 +3025,7 @@ char gbuf[CBUFSIZE], *gptr = gbuf, *tptr; uint8 dbuf[CBUFSIZE], *dptr = dbuf; uint32 dsize = 0; uint32 delay = 0; +uint32 after = 0; t_stat r; SEND *snd; @@ -3039,13 +3040,30 @@ if (isalpha(gbuf[0]) && (strchr (gbuf, ':'))) { else snd = sim_cons_get_send (); -if ((!strncmp(gbuf, "DELAY=", 6)) && (gbuf[6])) { - delay = (uint32)get_uint (&gbuf[6], 10, 10000000, &r); - if (r != SCPE_OK) { - sim_printf ("Invalid Delay Value\n"); - return SCPE_ARG|SCPE_NOMESSAGE; +while (*cptr) { + if ((!strncmp(gbuf, "DELAY=", 6)) && (gbuf[6])) { + delay = (uint32)get_uint (&gbuf[6], 10, 10000000, &r); + if (r != SCPE_OK) { + sim_printf ("Invalid Delay Value\n"); + return SCPE_ARG|SCPE_NOMESSAGE; + } + cptr = tptr; + tptr = get_glyph (cptr, gbuf, ','); + continue; } - cptr = tptr; + if ((!strncmp(gbuf, "AFTER=", 6)) && (gbuf[6])) { + after = (uint32)get_uint (&gbuf[6], 10, 10000000, &r); + if (r != SCPE_OK) { + sim_printf ("Invalid Delay Value\n"); + return SCPE_ARG|SCPE_NOMESSAGE; + } + cptr = tptr; + tptr = get_glyph (cptr, gbuf, ','); + continue; + } + if ((*cptr == '"') || (*cptr == '\'')) + break; + return SCPE_ARG; } if (*cptr) { if ((*cptr != '"') && (*cptr != '\'')) { @@ -3063,7 +3081,7 @@ if (*cptr) { } if ((dsize == 0) && (delay == 0)) return SCPE_2FARG; -return sim_send_input (snd, dbuf, dsize, delay); +return sim_send_input (snd, dbuf, dsize, after, delay); } t_stat sim_show_send (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) @@ -5605,7 +5623,6 @@ fflush(stdout); /* flush stdout */ if (sim_log) /* flush log if enabled */ fflush (sim_log); sim_throt_sched (); /* set throttle */ -sim_brk_clract (); /* defang actions */ sim_rtcn_init_all (); /* re-init clocks */ sim_start_timer_services (); /* enable wall clock timing */ @@ -5620,7 +5637,7 @@ do { t_addr val; BRKTAB *bp; - if (r >= SCPE_BASE) /* done if an error occurred */ + if (SCPE_BARE_STATUS(r) >= SCPE_BASE) /* done if an error occurred */ break; if (sim_vm_pc_value) /* done if didn't stop at a dynamic breakpoint */ val = (t_addr)(*sim_vm_pc_value)(); @@ -5680,7 +5697,7 @@ sim_cancel (&sim_step_unit); /* cancel step timer */ sim_throt_cancel (); /* cancel throttle */ AIO_UPDATE_QUEUE; UPDATE_SIM_TIME; /* update sim time */ -return r; +return r | ((sim_switches & SWMASK ('Q')) ? SCPE_NOMESSAGE : 0); } /* run command message handler */ @@ -8290,19 +8307,32 @@ return SCPE_OK; t_stat sim_set_expect (EXPECT *exp, char *cptr) { -char gbuf[CBUFSIZE], *c1ptr; +char gbuf[CBUFSIZE], *gptr = gbuf, *tptr, *c1ptr; +uint32 after = exp->after; int32 cnt = 0; +t_stat r; if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG; if (*cptr == '[') { cnt = (int32) strtotv (cptr + 1, &c1ptr, 10); - if ((cptr == c1ptr) || (*c1ptr != ']')) - return SCPE_ARG; + if ((cptr == c1ptr) || (*c1ptr != ']')) { + sim_printf ("Invalid Repeat count specification\n"); + return SCPE_ARG|SCPE_NOMESSAGE; + } cptr = c1ptr + 1; while (isspace(*cptr)) ++cptr; } +tptr = get_glyph (cptr, gbuf, ','); +if ((!strncmp(gbuf, "HALTAFTER=", 10)) && (gbuf[10])) { + after = (uint32)get_uint (&gbuf[10], 10, 100000000, &r); + if (r != SCPE_OK) { + sim_printf ("Invalid Halt After Value\n"); + return SCPE_ARG|SCPE_NOMESSAGE; + } + cptr = tptr; + } if ((*cptr != '"') && (*cptr != '\'')) { sim_printf ("String must be quote delimited\n"); return SCPE_ARG|SCPE_NOMESSAGE; @@ -8310,7 +8340,7 @@ if ((*cptr != '"') && (*cptr != '\'')) { cptr = get_glyph_quoted (cptr, gbuf, 0); if (*cptr != '\0') return SCPE_2MARG; /* No more arguments */ -return sim_exp_set (exp, gbuf, cnt, sim_switches, cptr); +return sim_exp_set (exp, gbuf, cnt, after, sim_switches, cptr); } /* Clear expect */ @@ -8398,7 +8428,7 @@ return SCPE_OK; /* Set/Add an expect rule */ -t_stat sim_exp_set (EXPECT *exp, const char *match, int32 cnt, int32 switches, char *act) +t_stat sim_exp_set (EXPECT *exp, const char *match, int32 cnt, uint32 after, int32 switches, char *act) { EXPTAB *ep; uint8 *match_buf; @@ -8450,6 +8480,7 @@ if (ep) /* no, allocate */ exp->rules = (EXPTAB *) realloc (exp->rules, sizeof (*exp->rules)*(exp->size + 1)); ep = &exp->rules[exp->size]; exp->size += 1; +exp->after = after; /* set halt after value */ memset (ep, 0, sizeof(*ep)); ep->match_pattern = (char *)malloc (strlen (match) + 1); strcpy (ep->match_pattern, match); @@ -8529,6 +8560,8 @@ if (exp->buf_size) { fprintf (st, "Match Buffer Size: %d\n", exp->buf_size); fprintf (st, "Buffer Insert Offset: %d\n", exp->buf_ins); } +if (exp->after) + fprintf (st, "Halt After: %d instructions\n", exp->after); if (!*match) return sim_exp_showall (st, exp); if (!ep) @@ -8645,7 +8678,7 @@ if (i != exp->size) { /* Found? */ sim_exp_clr_tab (exp, ep); /* delete it */ if (ep->switches & EXP_TYP_CLEARALL) /* One shot expect rule? */ sim_exp_clrall (exp); /* delete all rules */ - sim_activate (&sim_expect_unit, 0); /* schedule simulation stop asap */ + sim_activate (&sim_expect_unit, exp->after); /* schedule simulation stop when indicated */ } } return SCPE_OK; @@ -8653,7 +8686,7 @@ return SCPE_OK; /* Queue input data for sending */ -t_stat sim_send_input (SEND *snd, uint8 *data, size_t size, uint32 delay) +t_stat sim_send_input (SEND *snd, uint8 *data, size_t size, uint32 after, uint32 delay) { if (snd->extoff != 0) { if (snd->insoff-snd->extoff > 0) @@ -8669,7 +8702,11 @@ memcpy(snd->buffer+snd->insoff, data, size); snd->insoff += size; if (delay) snd->delay = delay; -snd->next_time = sim_gtime() + snd->delay; +if (after) + snd->after = after; +if (snd->after == 0) + snd->after = snd->delay; +snd->next_time = sim_gtime() + snd->after; return SCPE_OK; } @@ -8684,7 +8721,9 @@ if (snd->extoff < snd->insoff) { } else fprintf (st, "No Pending Input Data\n"); -fprintf (st, "Pending Input Delay=%d instructions per character\n", snd->delay); +if ((snd->next_time - sim_gtime()) > 0) + fprintf (st, "Minimum of %d instructions befor sending first character\n", (int)(snd->next_time - sim_gtime())); +fprintf (st, "Minimum of %d instructions between characters\n", (int)snd->delay); return SCPE_OK; } diff --git a/scp.h b/scp.h index dd93744f..063032b3 100644 --- a/scp.h +++ b/scp.h @@ -145,12 +145,12 @@ uint32 sim_brk_test (t_addr bloc, uint32 btyp); void sim_brk_clrspc (uint32 spc); char *sim_brk_clract (void); void sim_brk_setact (const char *action); -t_stat sim_send_input (SEND *snd, uint8 *data, size_t size, uint32 delay); +t_stat sim_send_input (SEND *snd, uint8 *data, size_t size, uint32 after, uint32 delay); t_stat sim_show_send_input (FILE *st, SEND *snd); t_bool sim_send_poll_data (SEND *snd, t_stat *stat); t_stat sim_set_expect (EXPECT *exp, char *cptr); t_stat sim_set_noexpect (EXPECT *exp, char *cptr); -t_stat sim_exp_set (EXPECT *exp, const char *match, int32 cnt, int32 switches, char *act); +t_stat sim_exp_set (EXPECT *exp, const char *match, int32 cnt, uint32 after, int32 switches, char *act); t_stat sim_exp_clr (EXPECT *exp, const char *match); t_stat sim_exp_clrall (EXPECT *exp); t_stat sim_exp_show (FILE *st, EXPECT *exp, const char *match); diff --git a/sim_defs.h b/sim_defs.h index 6fb37876..3d2f3963 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -664,27 +664,29 @@ struct sim_exptab { /* Expect Context */ struct sim_expect { - struct sim_device *dptr; /* Device (for Debug) */ - uint32 dbit; /* Debugging Bit */ - struct sim_exptab *rules; /* match rules */ - int32 size; /* count of match rules */ - uint8 *buf; /* buffer of output data which has produced */ - uint32 buf_ins; /* buffer insertion point for the next output data */ - uint32 buf_size; /* buffer size */ + struct sim_device *dptr; /* Device (for Debug) */ + uint32 dbit; /* Debugging Bit */ + struct sim_exptab *rules; /* match rules */ + int32 size; /* count of match rules */ + uint32 after; /* delay before halting */ + uint8 *buf; /* buffer of output data which has produced */ + uint32 buf_ins; /* buffer insertion point for the next output data */ + uint32 buf_size; /* buffer size */ }; /* Send Context */ struct sim_send { - uint32 delay; /* instruction delay before/between sent data */ - struct sim_device *dptr; /* Device (for Debug) */ - uint32 dbit; /* Debugging Bit */ + uint32 delay; /* instruction delay between sent data */ #define SEND_DEFAULT_DELAY 1000 /* default delay instruction count */ - double next_time; /* execution time when next data can be sent */ - uint8 *buffer; /* buffer */ - size_t bufsize; /* buffer size */ - int32 insoff; /* insert offset */ - int32 extoff; /* extra offset */ + struct sim_device *dptr; /* Device (for Debug) */ + uint32 dbit; /* Debugging Bit */ + uint32 after; /* instruction delay before sending any data */ + double next_time; /* execution time when next data can be sent */ + uint8 *buffer; /* buffer */ + size_t bufsize; /* buffer size */ + int32 insoff; /* insert offset */ + int32 extoff; /* extra offset */ }; /* Debug table */