SCP: Extend RUN and GO commands with optional UNTIL criteria.

The new RUN/GO command syntax supports a stop criteria.
There are two forms of stop criteria:

1) A normal breakpoint (which exists only until it is encountered)
2) A user specified output string is emitted by the simulated system.

Command syntax is:

    RUN|GO {START-PC-VALUE} {UNTIL breakpoint|"output-string"}
This commit is contained in:
Mark Pizzolato 2016-06-05 02:39:41 -07:00
parent c5ee1ad971
commit f3467d678c
2 changed files with 48 additions and 14 deletions

View file

@ -279,6 +279,10 @@ The EXPECT command now exists to provide a means of reacting to simulator output
EXPECT React to output produced by a simulated system EXPECT React to output produced by a simulated system
SEND Inject input to a simulated system's console SEND Inject input to a simulated system's console
SCREENSHOT Snapshot the current video display window SCREENSHOT Snapshot the current video display window
RUN UNTIL breakpoint Establish the breakpoiunt specified and run until it is encountered
RUN UNTIL "output-string" ... Establish the specified "output-string" as an EXPECT and run until it is encountered.
GO UNTIL breakpoint Establish the breakpoiunt specified and go until it is encountered
GO UNTILE "output-string" ... Establish the specified "output-string" as an EXPECT and go until it is encountered.
#### Command Processing Enhancements #### Command Processing Enhancements

46
scp.c
View file

@ -6072,12 +6072,14 @@ if (warned)
return r; return r;
} }
/* Run, go, cont, step commands /* Run, go, boot, cont, step, next commands
ru[n] [new PC] reset and start simulation ru[n] [new PC] reset and start simulation
go [new PC] start simulation go [new PC] start simulation
co[nt] start simulation co[nt] start simulation
s[tep] [step limit] start simulation for 'limit' instructions s[tep] [step limit] start simulation for 'limit' instructions
next start simulation for 1 instruction
stepping over subroutine calls
b[oot] device bootstrap from device and start simulation b[oot] device bootstrap from device and start simulation
switches: switches:
@ -6088,12 +6090,12 @@ return r;
t_stat run_cmd (int32 flag, CONST char *cptr) t_stat run_cmd (int32 flag, CONST char *cptr)
{ {
char gbuf[CBUFSIZE]; char gbuf[CBUFSIZE] = "";
CONST char *tptr; CONST char *tptr;
uint32 i, j; uint32 i, j;
int32 sim_next; int32 sim_next;
int32 unitno; int32 unitno;
t_value pcv; t_value pcv, orig_pcv;
t_stat r; t_stat r;
DEVICE *dptr; DEVICE *dptr;
UNIT *uptr; UNIT *uptr;
@ -6101,22 +6103,50 @@ UNIT *uptr;
GET_SWITCHES (cptr); /* get switches */ GET_SWITCHES (cptr); /* get switches */
sim_step = 0; sim_step = 0;
if ((flag == RU_RUN) || (flag == RU_GO)) { /* run or go */ if ((flag == RU_RUN) || (flag == RU_GO)) { /* run or go */
orig_pcv = get_rval (sim_PC, 0); /* get current PC value */
if (*cptr != 0) { /* argument? */ if (*cptr != 0) { /* argument? */
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
if (*cptr != 0) /* should be end */ if (MATCH_CMD (gbuf, "UNTIL") != 0) {
return SCPE_2MARG;
if (sim_vm_parse_addr) /* address parser? */ if (sim_vm_parse_addr) /* address parser? */
pcv = sim_vm_parse_addr (sim_dflt_dev, gbuf, &tptr); pcv = sim_vm_parse_addr (sim_dflt_dev, gbuf, &tptr);
else pcv = strtotv (gbuf, &tptr, sim_PC->radix);/* parse PC */ else pcv = strtotv (gbuf, &tptr, sim_PC->radix);/* parse PC */
if ((tptr == gbuf) || (*tptr != 0) || /* error? */ if ((tptr == gbuf) || (*tptr != 0) || /* error? */
(pcv > width_mask[sim_PC->width])) (pcv > width_mask[sim_PC->width]))
return SCPE_ARG; return SCPE_ARG;
put_rval (sim_PC, 0, pcv); put_rval (sim_PC, 0, pcv); /* Save in PC */
}
} }
if ((flag == RU_RUN) && /* run? */ if ((flag == RU_RUN) && /* run? */
((r = sim_run_boot_prep ()) != SCPE_OK)) /* reset sim */ ((r = sim_run_boot_prep ()) != SCPE_OK)) { /* reset sim */
put_rval (sim_PC, 0, orig_pcv); /* restore original PC */
return r; return r;
} }
if ((*cptr) || (MATCH_CMD (gbuf, "UNTIL") == 0)) { /* should be end */
int32 saved_switches = sim_switches;
if (MATCH_CMD (gbuf, "UNTIL") != 0)
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
if (MATCH_CMD (gbuf, "UNTIL") != 0)
return sim_messagef (SCPE_2MARG, "Unexpected %s command argument: %s %s\n",
(flag == RU_RUN) ? "RUN" : "GO", gbuf, cptr);
sim_switches = 0;
GET_SWITCHES (cptr);
if ((*cptr == '\'') || (*cptr == '"')) { /* Expect UNTIL condition */
r = expect_cmd (1, cptr);
if (r != SCPE_OK)
return r;
}
else { /* BREAK UNTIL condition */
if (sim_switches == 0)
sim_switches = sim_brk_dflt;
sim_switches |= BRK_TYP_TEMP; /* make this a one-shot breakpoint */
r = ssh_break (NULL, cptr, SSH_ST);
if (r != SCPE_OK)
return sim_messagef (r, "Unable to establish breakpoint at: %s\n", cptr);
}
sim_switches = saved_switches;
}
}
else if ((flag == RU_STEP) || else if ((flag == RU_STEP) ||
((flag == RU_NEXT) && !sim_vm_is_subroutine_call)) { /* step */ ((flag == RU_NEXT) && !sim_vm_is_subroutine_call)) { /* step */
@ -9075,7 +9105,7 @@ if ((bp = sim_brk_fnd (loc)) && (btyp & bp->typ)) { /* in table, and type ma
sim_brk_setact (bp->act); /* set up actions */ sim_brk_setact (bp->act); /* set up actions */
res = btyp & bp->typ; /* set return value */ res = btyp & bp->typ; /* set return value */
if (bp->typ & BRK_TYP_TEMP) if (bp->typ & BRK_TYP_TEMP)
sim_brk_clr (loc, btyp); /* delete one-shot breakpoint */ sim_brk_clr (loc, btyp | BRK_TYP_TEMP); /* delete one-shot breakpoint */
else { else {
sim_brk_ploc[spc] = loc; /* save location */ sim_brk_ploc[spc] = loc; /* save location */
sim_brk_pend[spc] = TRUE; /* don't do twice */ sim_brk_pend[spc] = TRUE; /* don't do twice */