1
0
mirror of https://github.com/simh/simh.git synced 2026-01-11 23:52:58 +00:00

TIMER: More reliable NOCALIBRATE initialization

- Behave well when NOCALIBRATE mode is enabled after some instruction
  execution already happened.
- Properly detect the reliable calibrated clock or use the internal one.
This commit is contained in:
Mark Pizzolato 2023-06-27 13:46:31 -10:00
parent be831daa1d
commit 91e2e4beb9
3 changed files with 25 additions and 16 deletions

21
scp.c
View File

@ -1515,7 +1515,7 @@ static const char simh_help1[] =
" When running in NOCALIBRATE mode, port speed pacing on telnet or serial\n"
" connections will be affected and on serial connections data out any\n"
" serial ports will likely get mangled.\n"
"4BASE\n"
"4BASE\n"
" When running with calibration disabled, wall clock time within the\n"
" simulator is not meaningfully related to the real wall clock time.\n"
" Simulator devices may query what they believe to be the wall clock\n"
@ -3071,9 +3071,7 @@ if (sim_tmpfile == NULL) {
return EXIT_FAILURE;
}
stop_cpu = FALSE;
sim_interval = 0;
sim_time = sim_rtime = 0;
noqueue_time = 0;
sim_reset_time ();
sim_clock_queue = QUEUE_LIST_END;
sim_is_running = FALSE;
sim_log = NULL;
@ -3181,7 +3179,7 @@ if (!sim_quiet) {
show_version (stdout, NULL, NULL, 0, NULL);
}
sim_timer_precalibrate_execution_rate ();
sim_time = sim_rtime = 0;
sim_reset_time ();
show_version (stdnul, NULL, NULL, 1, NULL); /* Quietly set SIM_OSTYPE */
#if defined (HAVE_PCRE_H)
setenv ("SIM_REGEX_TYPE", "PCRE", 1); /* Publish regex type */
@ -9895,8 +9893,7 @@ t_stat r;
/* reset queue */
while (sim_clock_queue != QUEUE_LIST_END)
sim_cancel (sim_clock_queue);
sim_time = sim_rtime = 0;
noqueue_time = sim_interval = 0;
sim_reset_time ();
r = reset_all (0);
if ((r == SCPE_OK) && (flag == RU_RUN)) {
if ((run_cmd_did_reset) && (0 == (sim_switches & SWMASK ('Q')))) {
@ -12854,6 +12851,13 @@ UPDATE_SIM_TIME;
return sim_rtime;
}
void sim_reset_time (void)
{
sim_interval = 0;
sim_time = sim_rtime = 0;
noqueue_time = 0;
}
/* sim_qcount - return queue entry count
Inputs: none
@ -17112,8 +17116,7 @@ sim_scp_dev.dctrl = 0xFFFFFFFF;
/* reset queue */
while (sim_clock_queue != QUEUE_LIST_END)
sim_cancel (sim_clock_queue);
sim_time = sim_rtime = 0;
noqueue_time = sim_interval = 0;
sim_reset_time ();
/* queue test unit events */
for (i = 0; i < dptr->numunits; i++) {

1
scp.h
View File

@ -150,6 +150,7 @@ double sim_activate_time_usecs (UNIT *uptr);
t_stat sim_run_boot_prep (int32 flag);
double sim_gtime (void);
uint32 sim_grtime (void);
void sim_reset_time (void);
int32 sim_qcount (void);
t_stat attach_unit (UNIT *uptr, CONST char *cptr);
t_stat detach_unit (UNIT *uptr);

View File

@ -879,7 +879,7 @@ if (rtc->hz != ticksper) { /* changing tick rate? */
ticksper = rtc->last_hz; /* Use the prior tick rate */
if (rtc->hz == 0)
rtc->clock_tick_start_time = sim_timenow_double ();
if ((rtc->last_hz != ticksper) && (ticksper != 0))
if ((rtc->last_hz != 0) && (rtc->last_hz != ticksper) && (ticksper != 0))
rtc->currd = (int32)(sim_timer_inst_per_sec () / ticksper);
rtc->last_hz = rtc->hz;
rtc->hz = ticksper;
@ -1133,7 +1133,8 @@ 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 %s/sec\n", sim_fmt_numeric (inst_per_sec), sim_vm_interval_units);
if (sim_timer_calib_enabled)
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);
@ -1473,7 +1474,7 @@ if (!sim_timer_calib_enabled)
if (sim_throt_type != SIM_THROT_NONE)
return sim_messagef (SCPE_NOFNC, "calibration can't be disabled when throttling\n");
if (sim_idle_enab)
return sim_messagef (SCPE_NOFNC, "calibration can't be disabled when idling\n");
return sim_messagef (SCPE_NOFNC, "calibration can't be disabled with idle detection enabled\n");
if ((cptr == NULL) || (*cptr == '\0')) {
if (sim_timer_uncalib_base_time.tv_sec == 0)
sim_rtcn_get_time (&sim_timer_uncalib_base_time, 0);
@ -1498,12 +1499,15 @@ sim_timer_set_async (0, NULL);
if (sim_timer_uncalib_base_time.tv_sec == 0)
sim_rtcn_get_time (&sim_timer_uncalib_base_time, 0);
sim_timer_calib_enabled = FALSE;
sim_reset_time ();
sim_precalibrate_ips = (uint32)(val * units);
for (tmr=clocks=0; tmr<=SIM_NTIMERS; ++tmr) {
RTC *rtc = &rtcs[tmr];
if (rtc->hz != 0)
rtc->initd = rtc->based = rtc->currd = sim_precalibrate_ips / rtc->hz;
if (rtc->last_hz != 0)
rtc->initd = rtc->based = rtc->currd = sim_precalibrate_ips / rtc->last_hz;
}
reset_all_p (0);
return sim_messagef (SCPE_OK, "calibration disabled running at %s %s per pseudo second\n",
@ -2588,7 +2592,10 @@ return SCPE_OK;
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.
internal calibrated clock is selected. Additionally, any timer device
which is used in a way where the tick rate changes should never be a
calibrated clock. The logic here will detect that and merely force
that clock to use calibration from the underlying calibrated clock.
*/
static void _rtcn_configure_calibrated_clock (int32 newtmr)
{
@ -2601,9 +2608,7 @@ for (tmr=0; tmr<SIM_NTIMERS; tmr++) {
rtc = &rtcs[tmr];
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 */
(rtc->clock_unit)) /* clock has been registered AND */
break;
}
if (tmr == SIM_NTIMERS) { /* None found? */