1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-03-29 02:55:02 +00:00

SCP: Updated to current.

This commit is contained in:
Richard Cornwell
2020-03-08 19:40:01 -04:00
parent 0cc717e1cb
commit 0e90417e2d
9 changed files with 154 additions and 103 deletions

View File

@@ -1,8 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BuildROMs", "BuildROMs.vcproj", "{D40F3AF1-EEE7-4432-9807-2AD287B490F8}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "B5500", "B5500.vcproj", "{BA514FA1-D029-4D25-91CC-255E5953FF6E}"
ProjectSection(ProjectDependencies) = postProject
{D40F3AF1-EEE7-4432-9807-2AD287B490F8} = {D40F3AF1-EEE7-4432-9807-2AD287B490F8}

View File

@@ -149,7 +149,7 @@ find_exe = $(abspath $(strip $(firstword $(foreach dir,$(strip $(subst :, ,${PAT
find_lib = $(abspath $(strip $(firstword $(foreach dir,$(strip ${LIBPATH}),$(wildcard $(dir)/lib$(1).${LIBEXT})))))
find_include = $(abspath $(strip $(firstword $(foreach dir,$(strip ${INCPATH}),$(wildcard $(dir)/$(1).h)))))
ifneq (0,$(TESTS))
find_test = RegisterSanityCheck $(abspath $(wildcard $(1)/tests/$(2)_test.ini))
find_test = RegisterSanityCheck $(abspath $(wildcard $(1)/tests/$(2)_test.ini)) </dev/null
TESTING_FEATURES = - Per simulator tests will be run
else
TESTING_FEATURES = - Per simulator tests will be skipped

136
scp.c
View File

@@ -386,7 +386,7 @@ if (AIO_QUEUE_VAL != QUEUE_LIST_END) { /* List !Empty */
q = AIO_QUEUE_VAL;
} while (q != AIO_QUEUE_SET(QUEUE_LIST_END, q));
while (q != QUEUE_LIST_END) { /* List !Empty */
sim_debug (SIM_DBG_AIO_QUEUE, &sim_scp_dev, "Migrating Asynch event for %s after %d instructions\n", sim_uname(q), q->a_event_time);
sim_debug (SIM_DBG_AIO_QUEUE, &sim_scp_dev, "Migrating Asynch event for %s after %d %s\n", sim_uname(q), q->a_event_time, sim_vm_interval_units);
++migrated;
uptr = q;
q = q->a_next;
@@ -414,7 +414,7 @@ return migrated;
void sim_aio_activate (ACTIVATE_API caller, UNIT *uptr, int32 event_time)
{
AIO_ILOCK;
sim_debug (SIM_DBG_AIO_QUEUE, &sim_scp_dev, "Queueing Asynch event for %s after %d instructions\n", sim_uname(uptr), event_time);
sim_debug (SIM_DBG_AIO_QUEUE, &sim_scp_dev, "Queueing Asynch event for %s after %d %s\n", sim_uname(uptr), event_time, sim_vm_interval_units);
if (uptr->a_next) {
uptr->a_activate_call = sim_activate_abs;
}
@@ -430,7 +430,7 @@ else {
AIO_IUNLOCK;
sim_asynch_check = 0; /* try to force check */
if (sim_idle_wait) {
sim_debug (TIMER_DBG_IDLE, &sim_timer_dev, "waking due to event on %s after %d instructions\n", sim_uname(uptr), event_time);
sim_debug (TIMER_DBG_IDLE, &sim_timer_dev, "waking due to event on %s after %d %s\n", sim_uname(uptr), event_time, sim_vm_interval_units);
pthread_cond_signal (&sim_asynch_wake);
}
}
@@ -573,6 +573,8 @@ const char *sim_prog_name = NULL; /* pointer to the execut
DEVICE *sim_dflt_dev = NULL;
UNIT *sim_clock_queue = QUEUE_LIST_END;
int32 sim_interval = 0;
const char *sim_vm_interval_units = "instructions"; /* Simulator can change to "cycles" as needed */
const char *sim_vm_step_unit = "instruction"; /* Simulator can change */
int32 sim_switches = 0;
int32 sim_switch_number = 0;
FILE *sim_ofile = NULL;
@@ -1031,11 +1033,11 @@ static const char simh_help[] =
#define HLP_STEP "*Commands Running_A_Simulated_Program STEP"
"3STEP\n"
" The STEP command (abbreviated S) resumes execution at the current PC for\n"
" the number of instructions given by its argument. If no argument is\n"
" supplied, one instruction is executed.\n"
" the number of %Is given by its argument. If no argument is\n"
" supplied, one %I is executed.\n"
"4Switches\n"
" If the STEP command is invoked with the -T switch, the step command will\n"
" cause execution to run for microseconds rather than instructions.\n"
" cause execution to run for microseconds rather than %I.\n"
#define HLP_NEXT "*Commands Running_A_Simulated_Program NEXT"
"3NEXT\n"
" The NEXT command (abbreviated N) resumes execution at the current PC for\n"
@@ -1116,7 +1118,7 @@ static const char simh_help[] =
" diagnostic which didn't achieve explicit success or failure within\n"
" some user specified time. The RUNLIMIT command provides ways to\n"
" limit execution.\n\n"
"++RUNLIMIT n {CYCLES|MICROSECONDS|SECONDS|MINUTES|HOURS}\n"
"++RUNLIMIT n {%C|MICROSECONDS|SECONDS|MINUTES|HOURS}\n"
"++NORUNLIMIT\n\n"
" Equivalently:\n\n"
"++SET RUNLIMIT n {CYCLES|MICROSECONDS|SECONDS|MINUTES|HOURS}\n"
@@ -1124,7 +1126,7 @@ static const char simh_help[] =
" The run limit state can be examined with:\n\n"
"++SHOW RUNLIMIT\n\n"
" If the units of the run limit are not specified, the default units are\n"
" cycles. Once an execution run limit has beenn reached, any subsequent\n"
" %C. Once an execution run limit has beenn reached, any subsequent\n"
" GO, RUN, CONTINUE, STEP or BOOT commands will cause the simulator to\n"
" exit. A previously defined RUNLIMIT can be cleared with the NORUNLIMIT\n"
" command or the establishment of a new run limit.\n"
@@ -1330,7 +1332,7 @@ static const char simh_help[] =
"+SET NODEBUG disables any currently active debug output\n"
"4Switches\n"
" Debug message output contains a timestamp which indicates the number of\n"
" simulated instructions which have been executed prior to the debug event.\n\n"
" simulated %C which have been executed prior to the debug event.\n\n"
" Debug message output can be enhanced to contain additional, potentially\n"
" useful information.\n"
"5-T\n"
@@ -1374,17 +1376,17 @@ static const char simh_help[] =
"3Throttle\n"
" Simulator instruction execution rate can be controlled by specifying\n"
" one of the following throttle commands:\n\n"
"+SET THROTTLE xM execute x million instructions per second\n"
"+SET THROTTLE xK execute x thousand instructions per second\n"
"+SET THROTTLE xM execute x million %C per second\n"
"+SET THROTTLE xK execute x thousand %C per second\n"
"+SET THROTTLE x%% occupy x percent of the host capacity\n"
"++++++++executing instructions\n"
"+SET THROTTLE x/t sleep for t milliseconds after executing x\n"
"++++++++instructions\n\n"
"++++++++%C\n\n"
"+SET NOTHROTTLE set simulation rate to maximum\n\n"
" Throttling is only available on host systems that implement a precision\n"
" real-time delay function.\n\n"
" xM, xK and x%% modes require the simulator to execute sufficient\n"
" instructions to actually calibrate the desired execution rate relative\n"
" %C to actually calibrate the desired execution rate relative\n"
" to wall clock time. Very short running programs may complete before\n"
" calibration completes and therefore before the simulated execution rate\n"
" can match the desired rate.\n\n"
@@ -1406,7 +1408,7 @@ static const char simh_help[] =
"+SET CLOCK catchup enable catchup clock ticks\n"
"+SET CLOCK calib=n%% specify idle calibration skip %%\n"
"+SET CLOCK calib=ALWAYS specify calibration independent of idle\n"
"+SET CLOCK stop=n stop execution after n instructions\n\n"
"+SET CLOCK stop=n stop execution after n %C\n\n"
" The SET CLOCK STOP command allows execution to have a bound when\n"
" execution starts with a BOOT, NEXT or CONTINUE command.\n"
#define HLP_SET_ASYNCH "*Commands SET Asynch"
@@ -2041,7 +2043,7 @@ static const char simh_help[] =
" a multiplier of 1000 or 1000000 respectively\n"
/***************** 80 character line width template *************************/
"4After\n"
" Specifies an integer (>=0) representing a minimal number of instructions\n"
" Specifies an integer (>=0) representing a minimal number of %C\n"
" which must execute before the first character in the string is sent.\n"
" The after parameter value can be set by itself with:\n\n"
"++SEND AFTER=n\n\n"
@@ -2072,7 +2074,7 @@ static const char simh_help[] =
" Switches can be used to influence the behavior of SEND commands\n\n"
"5-t\n"
" The -t switch indicates that the Delay and After values are in\n"
" units of microseconds rather than instructions.\n"
" units of microseconds rather than %C.\n"
/***************** 80 character line width template *************************/
#define HLP_EXPECT "*Commands Executing_Command_Files Reacting_To_Console_Output"
/***************** 80 character line width template *************************/
@@ -2138,7 +2140,7 @@ static const char simh_help[] =
" The -i switch is only valid for regular expression expect rules.\n"
"5-t\n"
" The -t switch indicates that the value specified by the HaltAfter\n"
" parameter are in units of microseconds rather than instructions.\n"
" parameter are in units of microseconds rather than %C.\n"
"4Determining Which Output Matched\n"
" When an expect rule matches data in the output stream, the rule which\n"
" matched is recorded in the environment variable _EXPECT_MATCH_PATTERN.\n"
@@ -2168,7 +2170,7 @@ static const char simh_help[] =
" and hext character values of the form:\n"
"++\\xh{h} where each h is a hex digit (0-9A-Fa-f)\n"
"4HaltAfter\n"
" Specifies the number of instructions which should be executed before\n"
" Specifies the number of %C which should be executed before\n"
" simulator instruction execution should stop. The default is to stop\n"
" executing instructions immediately (i.e. HALTAFTER=0).\n"
" The default HaltAfter delay, once set, persists for all expect behaviors\n"
@@ -2582,7 +2584,7 @@ return 0;
}
#endif
t_stat process_stdin_commands (t_stat stat, char *argv[]);
t_stat process_stdin_commands (t_stat stat, char *argv[], t_bool do_called);
/* Main command loop */
@@ -2679,7 +2681,8 @@ if (sim_emax <= 0)
sim_emax = 1;
if (sim_timer_init ()) {
fprintf (stderr, "Fatal timer initialization error\n");
read_line_p ("Hit Return to exit: ", cbuf, sizeof (cbuf) - 1, stdin);
if (sim_ttisatty())
read_line_p ("Hit Return to exit: ", cbuf, sizeof (cbuf) - 1, stdin);
return EXIT_FAILURE;
}
sim_register_internal_device (&sim_scp_dev);
@@ -2703,13 +2706,6 @@ if ((sim_eval = (t_value *) calloc (sim_emax, sizeof (t_value))) == NULL) {
};
if (sim_dflt_dev == NULL) /* if no default */
sim_dflt_dev = sim_devices[0];
if (sim_timer_init ()) {
fprintf (stderr, "Fatal timer initialization error\n");
read_line_p ("Hit Return to exit: ", cbuf, sizeof (cbuf) - 1, stdin);
return EXIT_FAILURE;
}
/* Invoke power reset again in case some devices depend on timer
initialization having occurred */
if ((stat = reset_all_p (0)) != SCPE_OK) {
fprintf (stderr, "Fatal simulator initialization error\n%s\n",
sim_error_text (stat));
@@ -2795,7 +2791,7 @@ if (SCPE_BARE_STATUS(stat) == SCPE_OPENERR) /* didn't exist/can't op
stat = SCPE_OK;
if (SCPE_BARE_STATUS(stat) != SCPE_EXIT)
process_stdin_commands (SCPE_BARE_STATUS(stat), argv);
process_stdin_commands (SCPE_BARE_STATUS(stat), argv, FALSE);
detach_all (0, TRUE); /* close files */
sim_set_deboff (0, NULL); /* close debug */
@@ -2810,7 +2806,7 @@ free (targv); /* release any argv copy
return sim_exit_status;
}
t_stat process_stdin_commands (t_stat stat, char *argv[])
t_stat process_stdin_commands (t_stat stat, char *argv[], t_bool do_called)
{
char cbuf[4*CBUFSIZE], gbuf[CBUFSIZE];
CONST char *cptr;
@@ -2866,8 +2862,11 @@ while (stat != SCPE_EXIT) { /* in case exit */
}
cptr = get_glyph_cmd (cptr, gbuf); /* get command glyph */
sim_switches = 0; /* init switches */
if ((cmdp = find_cmd (gbuf))) /* lookup command */
if ((cmdp = find_cmd (gbuf))) { /* lookup command */
if (do_called && (cmdp->action == &return_cmd)) /* RETURN command? */
break;
stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */
}
else
stat = SCPE_UNK;
stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */
@@ -2884,6 +2883,14 @@ while (stat != SCPE_EXIT) { /* in case exit */
if (sim_vm_post != NULL)
(*sim_vm_post) (TRUE);
} /* end while */
if (do_called && cmdp &&
(cmdp->action == &return_cmd) && (0 != *cptr)) { /* return command with argument? */
sim_string_to_stat (cptr, &stat);
sim_last_cmd_stat = stat; /* save explicit status as command error status */
if (sim_switches & SWMASK ('Q'))
stat |= SCPE_NOMESSAGE; /* suppress error message display (in caller) if requested */
return stat; /* return with explicit return status */
}
return stat;
}
@@ -3656,7 +3663,7 @@ t_stat do_cmd_label (int32 flag, CONST char *fcptr, CONST char *label)
{
char cbuf[4*CBUFSIZE], gbuf[CBUFSIZE], abuf[4*CBUFSIZE], quote, *c, *do_arg[11];
CONST char *cptr;
FILE *fpin;
FILE *fpin = NULL;
CTAB *cmdp = NULL;
int32 echo, nargs, errabort, i;
int32 saved_sim_do_echo = sim_do_echo,
@@ -3699,7 +3706,8 @@ for (nargs = 0; nargs < 10; ) { /* extract arguments */
if (do_arg [0] == NULL) /* need at least 1 */
return SCPE_2FARG;
if ((fpin = fopen (do_arg[0], "r")) == NULL) { /* file failed to open? */
if ((strcasecmp (do_arg[0], "<stdin>") != 0) &&
((fpin = fopen (do_arg[0], "r")) == NULL)) { /* file failed to open? */
strlcpy (cbuf, do_arg[0], sizeof (cbuf)); /* try again with .sim extension */
strlcat (cbuf, ".sim", sizeof (cbuf));
if ((fpin = fopen (cbuf, "r")) == NULL) { /* failed a second time? */
@@ -3758,6 +3766,11 @@ if (label) {
if (errabort) /* -e flag? */
set_on (1, NULL); /* equivalent to ON ERROR RETURN */
if (strcasecmp (do_arg[0], "<stdin>") == 0) {
stat = process_stdin_commands (SCPE_OK, do_arg, TRUE);
goto Cleanup_Return;
}
do {
if (stop_cpu) { /* SIGINT? */
if (sim_on_actions[sim_do_depth][ON_SIGINT_ACTION]) {
@@ -3872,7 +3885,8 @@ do {
(*sim_vm_post) (TRUE);
} while (staying);
Cleanup_Return:
fclose (fpin); /* close file */
if (fpin)
fclose (fpin); /* close file */
sim_gotofile = NULL;
if (flag >= 0) {
sim_do_echo = saved_sim_do_echo; /* restore echo state we entered with */
@@ -6169,14 +6183,14 @@ memset (&buf, 0, sizeof (buf));
if (cptr && (*cptr != 0))
return SCPE_2MARG;
if (sim_clock_queue == QUEUE_LIST_END)
fprintf (st, "%s event queue empty, time = %.0f, executing %s instructios/sec\n",
sim_name, sim_time, sim_fmt_numeric (sim_timer_inst_per_sec ()));
fprintf (st, "%s event queue empty, time = %.0f, executing %s %s/sec\n",
sim_name, sim_time, sim_fmt_numeric (sim_timer_inst_per_sec ()), sim_vm_interval_units);
else {
const char *tim = "";
double inst_per_sec = sim_timer_inst_per_sec ();
fprintf (st, "%s event queue status, time = %.0f, executing %s instructions/sec\n",
sim_name, sim_time, sim_fmt_numeric (inst_per_sec));
fprintf (st, "%s event queue status, time = %.0f, executing %s %s/sec\n",
sim_name, sim_time, sim_fmt_numeric (inst_per_sec), sim_vm_interval_units);
for (uptr = sim_clock_queue; uptr != QUEUE_LIST_END; uptr = uptr->next) {
if (uptr == &sim_step_unit)
fprintf (st, " Step timer");
@@ -6222,7 +6236,7 @@ else {
}
}
fprintf (st, "asynch latency: %d nanoseconds\n", sim_asynch_latency);
fprintf (st, "asynch instruction latency: %d instructions\n", sim_asynch_inst_latency);
fprintf (st, "asynch instruction latency: %d %s\n", sim_asynch_inst_latency, sim_vm_interval_units);
pthread_mutex_unlock (&sim_asynch_lock);
sim_mfile = NULL;
fprintf (st, "%*.*s", (int)buf.pos, (int)buf.pos, buf.buf);
@@ -6954,7 +6968,7 @@ if ((r != SCPE_OK) || (num == 0)) /* error? */
return sim_messagef (SCPE_ARG, "Invalid argument: %s\n", gbuf);
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
if ((gbuf[0] == '\0') ||
(MATCH_CMD (gbuf, "CYCLES") == 0))
(MATCH_CMD (gbuf, sim_vm_interval_units) == 0))
sim_switches &= ~SWMASK ('T');
else {
int i;
@@ -7017,14 +7031,14 @@ if (sim_runlimit_enabled) {
}
else {
if (sim_runlimit_initial != sim_runlimit) {
fprintf (st, "%d cycles initially, ", sim_runlimit_initial);
fprintf (st, "%d %s initially, ", sim_runlimit_initial, sim_vm_interval_units);
if (sim_is_active (&sim_runlimit_unit))
fprintf (st, "and %d cycles remaining\n", sim_activate_time (&sim_runlimit_unit));
fprintf (st, "and %d %s remaining\n", sim_activate_time (&sim_runlimit_unit), sim_vm_interval_units);
else
fprintf (st, "expired now\n");
}
else
fprintf (st, "%d cycles\n", sim_runlimit_initial);
fprintf (st, "%d %s\n", sim_runlimit_initial, sim_vm_interval_units);
}
}
else
@@ -12358,7 +12372,7 @@ if (exp->buf_size) {
fprintf (st, " Buffer Insert Offset: %d\n", exp->buf_ins);
fprintf (st, " Buffer Contents: %s\n", bstr);
if (default_haltafter)
fprintf (st, " Default HaltAfter: %u instructions\n", (unsigned)default_haltafter);
fprintf (st, " Default HaltAfter: %u %s\n", (unsigned)default_haltafter, sim_vm_interval_units);
free (bstr);
}
if (exp->dptr && (exp->dbit & exp->dptr->dctrl))
@@ -12622,19 +12636,19 @@ else
fprintf (st, " No Pending Input Data\n");
if ((snd->next_time - sim_gtime()) > 0) {
if (((snd->next_time - sim_gtime()) > (sim_timer_inst_per_sec()/1000000.0)) && ((sim_timer_inst_per_sec()/1000000.0) > 0.0))
fprintf (st, " Minimum of %d instructions (%d microseconds) before sending first character\n", (int)(snd->next_time - sim_gtime()),
fprintf (st, " Minimum of %d %s (%d microseconds) before sending first character\n", (int)(snd->next_time - sim_gtime()), sim_vm_interval_units,
(int)((snd->next_time - sim_gtime())/(sim_timer_inst_per_sec()/1000000.0)));
else
fprintf (st, " Minimum of %d instructions before sending first character\n", (int)(snd->next_time - sim_gtime()));
fprintf (st, " Minimum of %d %s before sending first character\n", (int)(snd->next_time - sim_gtime()), sim_vm_interval_units);
}
if ((snd->delay > (sim_timer_inst_per_sec()/1000000.0)) && ((sim_timer_inst_per_sec()/1000000.0) > 0.0))
fprintf (st, " Minimum of %d instructions (%d microseconds) between characters\n", (int)snd->delay, (int)(snd->delay/(sim_timer_inst_per_sec()/1000000.0)));
fprintf (st, " Minimum of %d %s (%d microseconds) between characters\n", (int)snd->delay, sim_vm_interval_units, (int)(snd->delay/(sim_timer_inst_per_sec()/1000000.0)));
else
fprintf (st, " Minimum of %d instructions between characters\n", (int)snd->delay);
fprintf (st, " Minimum of %d %s between characters\n", (int)snd->delay, sim_vm_interval_units);
if (after)
fprintf (st, " Default delay before first character input is %u instructions\n", after);
fprintf (st, " Default delay before first character input is %u %s\n", after, sim_vm_interval_units);
if (delay)
fprintf (st, " Default delay between character input is %u instructions\n", after);
fprintf (st, " Default delay between character input is %u %s\n", after, sim_vm_interval_units);
if (snd->dptr && (snd->dbit & snd->dptr->dctrl))
fprintf (st, " Send Debugging via: SET %s DEBUG%s%s\n", sim_dname(snd->dptr), snd->dptr->debflags ? "=" : "", snd->dptr->debflags ? _get_dbg_verb (snd->dbit, snd->dptr, NULL) : "");
return SCPE_OK;
@@ -13598,6 +13612,12 @@ for (hblock = astrings; (htext = *hblock) != NULL; hblock++) {
case 'S':
appendText (topic, sim_name, strlen (sim_name));
break;
case 'C':
appendText (topic, sim_vm_interval_units, strlen (sim_vm_interval_units));
break;
case 'I':
appendText (topic, sim_vm_step_unit, strlen (sim_vm_step_unit));
break;
case '%':
appendText (topic, "%", 1);
break;
@@ -15087,9 +15107,9 @@ free (f);
static t_stat sim_sanity_check_register_declarations (void)
{
t_stat stat = SCPE_OK;
int i;
DEVICE *dptr;
t_stat stat = SCPE_OK;
MFILE *f = MOpen ();
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
@@ -15149,13 +15169,19 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
}
if ((rptr->obj_size != 0) && (rptr->ele_size != 0) && (rptr->depth != 0) && (rptr->macro != NULL)) {
if (rptr->flags & REG_UNIT) {
if (rptr->depth > udptr->numunits) {
if (udptr == NULL) {
Bad = TRUE;
Mprintf (f, "\tthe depth of the UNIT array exceeds the number of units on the %s device which is %u\n", dptr->name, udptr->numunits);
Mprintf (f, "\tthe indicated UNIT can't be found for this $u depth array\n", rptr->depth);
}
if (rptr->obj_size > sizeof (t_value)) {
Bad = TRUE;
Mprintf (f, "\t%u is larger than the size of the t_value type (%u)\n", (uint32)rptr->obj_size, (uint32)sizeof (t_value));
else {
if (rptr->depth > udptr->numunits) {
Bad = TRUE;
Mprintf (f, "\tthe depth of the UNIT array exceeds the number of units on the %s device which is %u\n", dptr->name, udptr->numunits);
}
if (rptr->obj_size > sizeof (t_value)) {
Bad = TRUE;
Mprintf (f, "\t%u is larger than the size of the t_value type (%u)\n", (uint32)rptr->obj_size, (uint32)sizeof (t_value));
}
}
}
else {

2
scp.h
View File

@@ -429,6 +429,8 @@ extern t_bool (*sim_vm_fprint_stopped) (FILE *st, t_stat reason);
extern t_value (*sim_vm_pc_value) (void);
extern t_bool (*sim_vm_is_subroutine_call) (t_addr **ret_addrs);
extern const char **sim_clock_precalibrate_commands;
extern const char *sim_vm_interval_units; /* Simulator can change this - default "instructions" */
extern const char *sim_vm_step_unit; /* Simulator can change this - default "instruction" */
/* Core SCP libraries can potentially have unit test routines.

View File

@@ -47,6 +47,8 @@
* * %D - Inserts the name of the device (e.g. "DTA").
* * %U - Inserts the name of the unit (e.g. "DTA0").
* * %S - Inserts the current simulator name (e.g. "PDP-10")
* * %C - Inserts the current value of the sim_vm_interval_units string
* * %I - Inserts the current value of the sim_vm_step_unit string
* * %#s - Inserts the string suppled in the "#"th optional argument to the help
* routine. # starts with 1. Any embedded newlines will cause following
* text to be indented.

View File

@@ -639,9 +639,9 @@ for (i=connections=0; i<sim_rem_con_tmxr.lines; i++) {
DEVICE *dptr = NULL;
if (rem->smp_sample_dither_pct)
fprintf (st, "Register Bit Sampling is occurring every %d cycles (dithered %d percent)\n", rem->smp_sample_interval, rem->smp_sample_dither_pct);
fprintf (st, "Register Bit Sampling is occurring every %d %s (dithered %d percent)\n", rem->smp_sample_interval, sim_vm_interval_units, rem->smp_sample_dither_pct);
else
fprintf (st, "Register Bit Sampling is occurring every %d cycles\n", rem->smp_sample_interval);
fprintf (st, "Register Bit Sampling is occurring every %d %s\n", rem->smp_sample_interval, sim_vm_interval_units);
fprintf (st, " Registers being sampled are: ");
for (reg = 0; reg < rem->smp_reg_count; reg++) {
if (rem->smp_regs[reg].indirect)

View File

@@ -1653,7 +1653,9 @@ static int _eth_get_system_id (char *buf, size_t buf_size)
#endif
if ((status = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Cryptography", 0, KEY_QUERY_VALUE|KEY_WOW64_64KEY, &reghnd)) != ERROR_SUCCESS)
return -1;
reglen = buf_size;
if (buf_size < 37)
return -1;
reglen = buf_size - 1;
if ((status = RegQueryValueExA (reghnd, "MachineGuid", NULL, &regtype, (LPBYTE)buf, &reglen)) != ERROR_SUCCESS) {
RegCloseKey (reghnd);
return -1;
@@ -1672,19 +1674,16 @@ static int _eth_get_system_id (char *buf, size_t buf_size)
FILE *f;
memset (buf, 0, buf_size);
if ((f = fopen ("/etc/machine-id", "r"))) {
if (fread (buf, 1, buf_size - 1, f))
fclose (f);
else
fclose (f);
}
else {
if ((f = popen ("hostname", "r"))) {
if (fread (buf, 1, buf_size - 1, f))
pclose (f);
else
pclose (f);
}
if (buf_size < 37)
return -1;
if ((f = fopen ("/etc/machine-id", "r")) == NULL)
f = popen ("hostname", "r");
if (f) {
size_t read_size;
read_size = fread (buf, 1, buf_size - 1, f);
buf[read_size] = '\0';
fclose (f);
}
while ((strlen (buf) > 0) && sim_isspace(buf[strlen (buf) - 1]))
buf[strlen (buf) - 1] = '\0';
@@ -2073,7 +2072,7 @@ if (0 == strncmp("tap:", savname, 4)) {
strcpy(savname, devname);
}
#if defined (__APPLE__)
if (1) {
if (tun < 0) { /* Not good yet? */
struct ifreq ifr;
int s;
@@ -3840,7 +3839,7 @@ else
/* test reflections. This is done early in this routine since eth_reflect */
/* calls eth_filter recursively and thus changes the state of the device. */
if (dev->reflections == -1)
eth_reflect(dev);
status = eth_reflect(dev);
/* set new filter addresses */
for (i = 0; i < addr_count; i++)

View File

@@ -381,6 +381,11 @@ t_stat ethq_destroy(ETH_QUE* que); /* release FIFO queue */
const char *eth_capabilities(void);
t_stat sim_ether_test (DEVICE *dptr); /* unit test routine */
#if !defined(SIM_TEST_INIT) /* Need stubs for test APIs */
#define SIM_TEST_INIT
#define SIM_TEST(xxx)
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -943,9 +943,9 @@ if (rtc->hz != ticksper) { /* changing tick rate? */
(rtc->last_hz != ticksper) &&
(ticksper != 0))
rtc->currd = (int32)(sim_timer_inst_per_sec () / ticksper);
_rtcn_configure_calibrated_clock (tmr);
rtc->last_hz = rtc->hz;
rtc->hz = ticksper;
_rtcn_configure_calibrated_clock (tmr);
if (ticksper != 0) {
RTC *crtc = &rtcs[sim_calb_tmr];
@@ -1124,12 +1124,18 @@ int tmr;
uint32 clock_start, clock_last, clock_now;
sim_debug (DBG_TRC, &sim_timer_dev, "sim_timer_init()\n");
/* Clear the event queue before initializing the timer subsystem */
while (sim_clock_queue != QUEUE_LIST_END)
sim_cancel (sim_clock_queue);
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
RTC *rtc = &rtcs[tmr];
rtc->timer_unit = &sim_timer_units[tmr];
rtc->timer_unit->action = &sim_timer_tick_svc;
rtc->timer_unit->flags = UNIT_DIS | UNIT_IDLE;
if (rtc->clock_cosched_queue)
while (rtc->clock_cosched_queue != QUEUE_LIST_END)
sim_cancel (rtc->clock_cosched_queue);
rtc->clock_cosched_queue = QUEUE_LIST_END;
}
sim_stop_unit.action = &sim_timer_stop_svc;
@@ -1188,7 +1194,7 @@ fprintf (st, "Minimum Host Sleep Time: %d ms (%dHz)\n", sim_os_sleep_min_
if (sim_os_sleep_min_ms != sim_os_sleep_inc_ms)
fprintf (st, "Minimum Host Sleep Incr Time: %d ms\n", sim_os_sleep_inc_ms);
fprintf (st, "Host Clock Resolution: %d ms\n", sim_os_clock_resoluton_ms);
fprintf (st, "Execution Rate: %s cycles/sec\n", sim_fmt_numeric (inst_per_sec));
fprintf (st, "Execution Rate: %s %s/sec\n", sim_fmt_numeric (inst_per_sec), sim_vm_interval_units);
if (sim_idle_enab) {
fprintf (st, "Idling: Enabled\n");
fprintf (st, "Time before Idling starts: %d seconds\n", sim_idle_stable);
@@ -1638,10 +1644,10 @@ if ((!sim_idle_enab) || /* idling disabled */
((sim_clock_queue != QUEUE_LIST_END) && /* or clock queue not empty */
((sim_clock_queue->flags & UNIT_IDLE) == 0))|| /* and event not idle-able? */
(rtc->elapsed < sim_idle_stable)) { /* or calibrated timer not stable? */
sim_debug (DBG_IDL, &sim_timer_dev, "Can't idle: %s - elapsed: %d.%03d\n", !sim_idle_enab ? "idle disabled" :
sim_debug (DBG_IDL, &sim_timer_dev, "Can't idle: %s - elapsed: %d and %d/%d\n", !sim_idle_enab ? "idle disabled" :
((rtc->elapsed < sim_idle_stable) ? "not stable" :
((sim_clock_queue != QUEUE_LIST_END) ? sim_uname (sim_clock_queue) :
"")), rtc->elapsed, rtc->ticks);
"")), rtc->elapsed, rtc->ticks, rtc->hz);
sim_interval -= sin_cyc;
return FALSE;
}
@@ -1700,9 +1706,9 @@ if (w_ms > 1000) /* too long a wait (runa
sim_debug (DBG_TIK, &sim_timer_dev, "waiting too long: w_ms=%d usecs, w_idle=%d usecs, sim_interval=%d, rtc->currd=%d\n", w_ms, w_idle, sim_interval, rtc->currd);
in_nowait = FALSE;
if (sim_clock_queue == QUEUE_LIST_END)
sim_debug (DBG_IDL, &sim_timer_dev, "sleeping for %d ms - pending event in %d instructions\n", w_ms, sim_interval);
sim_debug (DBG_IDL, &sim_timer_dev, "sleeping for %d ms - pending event in %d %s\n", w_ms, sim_interval, sim_vm_interval_units);
else
sim_debug (DBG_IDL, &sim_timer_dev, "sleeping for %d ms - pending event on %s in %d instructions\n", w_ms, sim_uname(sim_clock_queue), sim_interval);
sim_debug (DBG_IDL, &sim_timer_dev, "sleeping for %d ms - pending event on %s in %d %s\n", w_ms, sim_uname(sim_clock_queue), sim_interval, sim_vm_interval_units);
cyc_since_idle = sim_gtime() - sim_idle_end_time; /* time since prior idle */
act_ms = sim_idle_ms_sleep (w_ms); /* wait */
rtc->clock_time_idled += act_ms;
@@ -1714,9 +1720,9 @@ else
sim_interval = sim_interval - act_cyc; /* count down sim_interval to reflect idle period */
sim_idle_end_time = sim_gtime(); /* save idle completed time */
if (sim_clock_queue == QUEUE_LIST_END)
sim_debug (DBG_IDL, &sim_timer_dev, "slept for %d ms - pending event in %d instructions\n", act_ms, sim_interval);
sim_debug (DBG_IDL, &sim_timer_dev, "slept for %d ms - pending event in %d %s\n", act_ms, sim_interval, sim_vm_interval_units);
else
sim_debug (DBG_IDL, &sim_timer_dev, "slept for %d ms - pending event on %s in %d instructions\n", act_ms, sim_uname(sim_clock_queue), sim_interval);
sim_debug (DBG_IDL, &sim_timer_dev, "slept for %d ms - pending event on %s in %d %s\n", act_ms, sim_uname(sim_clock_queue), sim_interval, sim_vm_interval_units);
return TRUE;
}
@@ -1838,21 +1844,21 @@ else {
switch (sim_throt_type) {
case SIM_THROT_MCYC:
fprintf (st, "Throttle: %d megacycles\n", sim_throt_val);
fprintf (st, "Throttle: %d mega%s\n", sim_throt_val, sim_vm_interval_units);
if (sim_throt_wait)
fprintf (st, "Throttling by sleeping for: %d ms every %d cycles\n", sim_throt_sleep_time, sim_throt_wait);
fprintf (st, "Throttling by sleeping for: %d ms every %d %s\n", sim_throt_sleep_time, sim_throt_wait, sim_vm_interval_units);
break;
case SIM_THROT_KCYC:
fprintf (st, "Throttle: %d kilocycles\n", sim_throt_val);
fprintf (st, "Throttle: %d kilo%s\n", sim_throt_val, sim_vm_interval_units);
if (sim_throt_wait)
fprintf (st, "Throttling by sleeping for: %d ms every %d cycles\n", sim_throt_sleep_time, sim_throt_wait);
fprintf (st, "Throttling by sleeping for: %d ms every %d %s\n", sim_throt_sleep_time, sim_throt_wait, sim_vm_interval_units);
break;
case SIM_THROT_PCT:
if (sim_throt_wait) {
fprintf (st, "Throttle: %d%% of %s cycles per second\n", sim_throt_val, sim_fmt_numeric (sim_throt_peak_cps));
fprintf (st, "Throttling by sleeping for: %d ms every %d cycles\n", sim_throt_sleep_time, sim_throt_wait);
fprintf (st, "Throttle: %d%% of %s %s per second\n", sim_throt_val, sim_fmt_numeric (sim_throt_peak_cps), sim_vm_interval_units);
fprintf (st, "Throttling by sleeping for: %d ms every %d %s\n", sim_throt_sleep_time, sim_throt_wait, sim_vm_interval_units);
}
else
fprintf (st, "Throttle: %d%%\n", sim_throt_val);
@@ -1860,7 +1866,7 @@ else {
case SIM_THROT_SPC:
fprintf (st, "Throttle: %d/%d\n", sim_throt_val, sim_throt_sleep_time);
fprintf (st, "Throttling by sleeping for: %d ms every %d cycles\n", sim_throt_sleep_time, sim_throt_val);
fprintf (st, "Throttling by sleeping for: %d ms every %d %s\n", sim_throt_sleep_time, sim_throt_val, sim_vm_interval_units);
break;
default:
@@ -1970,8 +1976,8 @@ switch (sim_throt_state) {
sim_set_throt (0, NULL); /* disable throttling */
return SCPE_OK;
}
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Not enough time. %d ms executing %.f instructions.\n",
(int)delta_ms, delta_inst);
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Not enough time. %d ms executing %.f %s.\n",
(int)delta_ms, delta_inst, sim_vm_interval_units);
sim_throt_wait = (int32)(delta_inst * SIM_THROT_WMUL);
sim_throt_inst_start = sim_gtime();
sim_idle_ms_sleep (sim_idle_rate_ms); /* start on a tick boundart to calibrate */
@@ -1991,8 +1997,8 @@ switch (sim_throt_state) {
a_cps, d_cps);
sim_throt_state = SIM_THROT_STATE_INIT;
sim_printf ("*********** WARNING ***********\n");
sim_printf ("Host CPU is too slow to simulate %s instructions per second\n", sim_fmt_numeric(d_cps));
sim_printf ("Host CPU can only simulate %s instructions per second\n", sim_fmt_numeric(sim_throt_peak_cps));
sim_printf ("Host CPU is too slow to simulate %s %s per second\n", sim_fmt_numeric(d_cps), sim_vm_interval_units);
sim_printf ("Host CPU can only simulate %s %s per second\n", sim_fmt_numeric(sim_throt_peak_cps), sim_vm_interval_units);
sim_printf ("Throttling disabled.\n");
sim_set_throt (0, NULL);
return SCPE_OK;
@@ -2451,6 +2457,16 @@ return SCPE_OK;
clock with an appropriate tick rate, an internal clock is run that meets
this requirement, OR when asynch clocks are enabled, the internal clock
is always run.
Some simulators have clocks that have dynamically programmable tick
rates. Such a clock is only a reliable candidate to be the calibrated
clock if it uses a single tick rate rather than changing the tick rate
on the fly. Generally most systems like this, under normal conditions
don't change their tick rates unless they're running something that is
examining the behavior of the clock system (like a diagnostic). Under
these conditions this clock is removed from the potential selection as
"the" calibrated clock all others are relative to and if necessary, an
internal calibrated clock is selected.
*/
static void _rtcn_configure_calibrated_clock (int32 newtmr)
{
@@ -2461,9 +2477,11 @@ RTC *rtc, *crtc;
sim_int_clk_tps = MIN(CLK_TPS, sim_os_tick_hz);
for (tmr=0; tmr<SIM_NTIMERS; tmr++) {
rtc = &rtcs[tmr];
if ((rtc->hz) &&
(rtc->hz <= (uint32)sim_os_tick_hz) &&
(rtc->clock_unit))
if ((rtc->hz) && /* is calibrated AND */
(rtc->hz <= (uint32)sim_os_tick_hz) && /* slower than OS tick rate AND */
(rtc->clock_unit) && /* clock has been registered AND */
((rtc->last_hz == 0) || /* first calibration call OR */
(rtc->last_hz == rtc->hz))) /* subsequent calibration call with an unchanged tick rate */
break;
}
if (tmr == SIM_NTIMERS) { /* None found? */
@@ -2499,7 +2517,7 @@ if (tmr == SIM_NTIMERS) { /* None found? */
SIM_INTERNAL_UNIT.action = &sim_timer_clock_tick_svc;
SIM_INTERNAL_UNIT.flags = UNIT_IDLE;
sim_register_internal_device (&sim_int_timer_dev); /* Register Internal timer device */
sim_rtcn_init_unit (&SIM_INTERNAL_UNIT, (int32)((CLK_INIT*CLK_TPS)/sim_int_clk_tps), SIM_INTERNAL_CLK);
sim_rtcn_init_unit_ticks (&SIM_INTERNAL_UNIT, (int32)((CLK_INIT*CLK_TPS)/sim_int_clk_tps), SIM_INTERNAL_CLK, sim_int_clk_tps);
SIM_INTERNAL_UNIT.action (&SIM_INTERNAL_UNIT); /* Force tick to activate timer */
}
return;
@@ -2560,7 +2578,7 @@ return SCPE_OK;
void sim_start_timer_services (void)
{
int32 tmr;
uint32 sim_prompt_time = sim_os_msec () - sim_stop_time;
uint32 sim_prompt_time = (sim_gtime () > 0) ? (sim_os_msec () - sim_stop_time) : 0;
int32 registered_units = 0;
sim_time_at_sim_prompt += (((double)sim_prompt_time) / 1000.0);
@@ -2585,7 +2603,8 @@ if (sim_calb_tmr == -1) {
}
else {
if (sim_calb_tmr == SIM_NTIMERS) {
sim_debug (DBG_CAL, &sim_timer_dev, "sim_start_timer_services() - restarting internal timer after %d cycles\n", sim_internal_timer_time);
sim_debug (DBG_CAL, &sim_timer_dev, "sim_start_timer_services() - restarting internal timer after %d %s\n",
sim_internal_timer_time, sim_vm_interval_units);
sim_activate (&SIM_INTERNAL_UNIT, sim_internal_timer_time);
}
}
@@ -2913,7 +2932,7 @@ if (NULL == uptr) { /* deregistering? */
sim_cancel (rtc->timer_unit);
return SCPE_OK;
}
if (NULL == rtc->clock_unit)
if (rtc->clock_unit == NULL)
rtc->clock_cosched_queue = QUEUE_LIST_END;
rtc->clock_unit = uptr;
uptr->dynflags |= UNIT_TMR_UNIT;
@@ -2976,7 +2995,7 @@ else {
}
rtc = &rtcs[tmr];
if ((NULL == rtc->clock_unit) || (rtc->hz == 0)) {
sim_debug (DBG_TIM, &sim_timer_dev, "sim_clock_coschedule_tmr(%s, tmr=%d, ticks=%d) - no clock activating after %d instructions\n", sim_uname (uptr), tmr, ticks, ticks * (rtc->currd ? rtc->currd : rtcs[sim_rtcn_calibrated_tmr ()].currd));
sim_debug (DBG_TIM, &sim_timer_dev, "sim_clock_coschedule_tmr(%s, tmr=%d, ticks=%d) - no clock activating after %d %s\n", sim_uname (uptr), tmr, ticks, ticks * (rtc->currd ? rtc->currd : rtcs[sim_rtcn_calibrated_tmr ()].currd), sim_vm_interval_units);
return sim_activate (uptr, ticks * (rtc->currd ? rtc->currd : rtcs[sim_rtcn_calibrated_tmr ()].currd));
}
else {