From 0e90417e2dfed44585749dbdc86c661b636b1d31 Mon Sep 17 00:00:00 2001 From: Richard Cornwell Date: Sun, 8 Mar 2020 19:40:01 -0400 Subject: [PATCH] SCP: Updated to current. --- Visual Studio Projects/Simh.sln | 2 - makefile | 2 +- scp.c | 136 +++++++++++++++++++------------- scp.h | 2 + scp_help.h | 2 + sim_console.c | 4 +- sim_ether.c | 31 ++++---- sim_ether.h | 5 ++ sim_timer.c | 73 ++++++++++------- 9 files changed, 154 insertions(+), 103 deletions(-) diff --git a/Visual Studio Projects/Simh.sln b/Visual Studio Projects/Simh.sln index b0e9e5f..3596783 100644 --- a/Visual Studio Projects/Simh.sln +++ b/Visual Studio Projects/Simh.sln @@ -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} diff --git a/makefile b/makefile index cbbf73d..a704c09 100644 --- a/makefile +++ b/makefile @@ -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)) 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], "") != 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], "") == 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 { diff --git a/scp.h b/scp.h index 120145d..ba2db86 100644 --- a/scp.h +++ b/scp.h @@ -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. diff --git a/scp_help.h b/scp_help.h index 19b4613..980f9e5 100644 --- a/scp_help.h +++ b/scp_help.h @@ -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. diff --git a/sim_console.c b/sim_console.c index b084e6c..888b9f4 100644 --- a/sim_console.c +++ b/sim_console.c @@ -639,9 +639,9 @@ for (i=connections=0; ismp_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) diff --git a/sim_ether.c b/sim_ether.c index 5231793..531ac66 100644 --- a/sim_ether.c +++ b/sim_ether.c @@ -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, ®hnd)) != ERROR_SUCCESS) return -1; - reglen = buf_size; + if (buf_size < 37) + return -1; + reglen = buf_size - 1; if ((status = RegQueryValueExA (reghnd, "MachineGuid", NULL, ®type, (LPBYTE)buf, ®len)) != 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++) diff --git a/sim_ether.h b/sim_ether.h index ecada30..598f8b8 100644 --- a/sim_ether.h +++ b/sim_ether.h @@ -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 diff --git a/sim_timer.c b/sim_timer.c index b120716..7fa6bd3 100644 --- a/sim_timer.c +++ b/sim_timer.c @@ -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; tmrhz) && - (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 {