From 48db10994d208e75cc01abde38dbf952a6699307 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Tue, 28 May 2019 22:47:06 -0700 Subject: [PATCH] TIMER: Calibrated clock fixes - Properly handle clock transitions when control flows back and forth between instruction execution and simh commands. - Changed Internal Timer from 10 Hz to the MAX(100Hz, HostOSClockHz) - Changed default idle calibration percent to 50% - Make sure that error cases (backwards and gap too big) properly advance the real time while avoiding calibration. - Fix selection of the calibrated clock. - Fix logic that sets the idle percentage that controls calibration. --- doc/simh.doc | Bin 285184 -> 298496 bytes sim_timer.c | 88 ++++++++++++++++++++++++++++----------------------- 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/doc/simh.doc b/doc/simh.doc index 9cd375c495c98a2691d969e410f76be696d7c639..96c4c1b9e2abf6df7d4f294ab66adc372f8422b1 100644 GIT binary patch delta 43426 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 cTz-Gy%R3q=-};w&)50|bgoDJ;<9 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 diff --git a/sim_timer.c b/sim_timer.c index 7793639d..ce6e8ed3 100644 --- a/sim_timer.c +++ b/sim_timer.c @@ -153,7 +153,7 @@ volatile t_bool sim_idle_wait = FALSE; /* global flag */ static int32 sim_calb_tmr = -1; /* the system calibrated timer */ static int32 sim_calb_tmr_last = -1; /* shadow value when at sim> prompt */ static double sim_inst_per_sec_last = 0; /* shadow value when at sim> prompt */ -static double sim_stop_time = 0; /* time when sim_stop_timer_services was called */ +static uint32 sim_stop_time = 0; /* time when sim_stop_timer_services was called */ static uint32 sim_idle_rate_ms = 0; static uint32 sim_os_sleep_min_ms = 0; @@ -161,7 +161,7 @@ static uint32 sim_os_sleep_inc_ms = 0; static uint32 sim_os_clock_resoluton_ms = 0; static uint32 sim_os_tick_hz = 0; static uint32 sim_idle_stable = SIM_IDLE_STDFLT; -static uint32 sim_idle_calib_pct = 0; +static uint32 sim_idle_calib_pct = 50; static double sim_timer_stop_time = 0; static uint32 sim_rom_delay = 0; static uint32 sim_throt_ms_start = 0; @@ -176,7 +176,7 @@ static double sim_throt_inst_start; static uint32 sim_throt_sleep_time = 0; static int32 sim_throt_wait = 0; static uint32 sim_throt_delay = 3; -#define CLK_TPS 10 +#define CLK_TPS 100 #define CLK_INIT (SIM_INITIAL_IPS/CLK_TPS) static int32 sim_int_clk_tps; static UNIT *sim_clock_unit[SIM_NTIMERS+1] = {NULL}; @@ -781,6 +781,7 @@ UNIT sim_timer_units[SIM_NTIMERS+1]; /* Clock assist units /* clock if no clocks are registered. */ UNIT sim_stop_unit; /* Stop unit */ UNIT sim_internal_timer_unit; /* Internal calibration timer */ +int32 sim_internal_timer_time; /* Pending internal timer delay */ UNIT sim_throttle_unit; /* one for throttle */ t_stat sim_throt_svc (UNIT *uptr); @@ -858,7 +859,7 @@ if (uptr) { sim_register_clock_unit_tmr (uptr, tmr); } rtc_clock_start_gtime[tmr] = sim_gtime(); -rtc_rtime[tmr] = sim_os_msec (); +rtc_rtime[tmr] = sim_is_running ? sim_os_msec () : sim_stop_time; rtc_vtime[tmr] = rtc_rtime[tmr]; rtc_nxintv[tmr] = 1000; rtc_ticks[tmr] = 0; @@ -900,6 +901,8 @@ else { return 10000; } if (rtc_hz[tmr] != ticksper) { /* changing tick rate? */ + uint32 prior_hz = rtc_hz[tmr]; + if (rtc_hz[tmr] == 0) rtc_clock_tick_start_time[tmr] = sim_timenow_double (); if ((rtc_last_hz[tmr] != 0) && @@ -911,10 +914,10 @@ if (rtc_hz[tmr] != ticksper) { /* changing tick rate? * _rtcn_configure_calibrated_clock (tmr); if (ticksper != 0) { rtc_clock_tick_size[tmr] = 1.0 / ticksper; - sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(ticksper=%d,tmr=%d) currd=%d\n", ticksper, tmr, rtc_currd[tmr]); + sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(ticksper=%d,tmr=%d) currd=%d, prior_hz=%d\n", ticksper, tmr, rtc_currd[tmr], (int)prior_hz); } else - sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(ticksper=%d,tmr=%d) timer stopped currd was %d\n", ticksper, tmr, rtc_currd[tmr]); + sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(ticksper=%d,tmr=%d) timer stopped currd was %d, prior_hz=%d\n", ticksper, tmr, rtc_currd[tmr], (int)prior_hz); } if (ticksper == 0) /* running? */ return 10000; @@ -947,7 +950,8 @@ if (new_rtime < rtc_rtime[tmr]) { /* time running backward /* for 49 days approximately every 49 days thereafter. */ ++rtc_clock_calib_backwards[tmr]; /* Count statistic */ sim_debug (DBG_CAL, &sim_timer_dev, "time running backwards - OldTime: %u, NewTime: %u, result: %d\n", rtc_rtime[tmr], new_rtime, rtc_currd[tmr]); - rtc_rtime[tmr] = new_rtime; /* reset wall time */ + rtc_vtime[tmr] = rtc_rtime[tmr] = new_rtime; /* reset wall time */ + rtc_nxintv[tmr] = 1000; return rtc_currd[tmr]; /* can't calibrate */ } delta_rtime = new_rtime - rtc_rtime[tmr]; /* elapsed wtime */ @@ -1022,7 +1026,8 @@ if (rtc_based[tmr] <= 0) /* never negative or zer rtc_based[tmr] = 1; if (rtc_currd[tmr] <= 0) /* never negative or zero! */ rtc_currd[tmr] = 1; -sim_debug (DBG_CAL, &sim_timer_dev, "calibrated tmr=%d, tickper=%d (base=%d, nxintv=%u, result: %d)\n", tmr, ticksper, rtc_based[tmr], rtc_nxintv[tmr], rtc_currd[tmr]); +sim_debug (DBG_CAL, &sim_timer_dev, "calibrated tmr=%d, tickper=%d (delta_rtime=%d, delta_vtime=%d, base=%d, nxintv=%u, result: %d)\n", + tmr, ticksper, (int)delta_rtime, (int)delta_vtime, rtc_based[tmr], rtc_nxintv[tmr], rtc_currd[tmr]); /* Adjust calibration for other timers which depend on this timer's calibration */ for (itmr=0; itmr<=SIM_NTIMERS; itmr++) if ((itmr != tmr) && (rtc_hz[itmr] != 0)) @@ -1066,7 +1071,7 @@ sim_idle_enab = FALSE; /* init idle off */ sim_idle_rate_ms = sim_os_ms_sleep_init (); /* get OS timer rate */ sim_set_rom_delay_factor (sim_get_rom_delay_factor ()); /* initialize ROM delay factor */ -clock_last = clock_start = sim_os_msec (); +sim_stop_time = clock_last = clock_start = sim_os_msec (); sim_os_clock_resoluton_ms = 1000; do { uint32 clock_diff; @@ -1354,9 +1359,9 @@ char gbuf[CBUFSIZE]; if (cptr == NULL) return SCPE_ARG; -cptr = get_glyph_nc (cptr, gbuf, 0); /* get argument */ +cptr = get_glyph (cptr, gbuf, 0); /* get argument */ if (isdigit (gbuf[0])) - newpct = (int32) get_uint (cptr, 10, 100, &r); + newpct = (int32) get_uint (gbuf, 10, 100, &r); else { if (MATCH_CMD (gbuf, "ALWAYS") == 0) newpct = 0; @@ -1521,6 +1526,8 @@ int32 act_cyc; static t_bool in_nowait = FALSE; double cyc_since_idle; +if (rtc_hz[tmr] == 0) /* specified timer is not running? */ + tmr = sim_calb_tmr; /* use calibrated timer instead */ if (rtc_clock_catchup_pending[tmr]) { /* Catchup clock tick pending? */ sim_debug (DBG_CAL, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d) - accelerating pending catch-up tick before idling %s\n", tmr, sin_cyc, sim_uname (sim_clock_unit[tmr])); sim_activate_abs (&sim_timer_units[tmr], 0); @@ -1532,7 +1539,7 @@ if ((!sim_idle_enab) || /* idling disabled */ (!sim_asynch_timer))|| /* and not asynch? */ ((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[tmr] < sim_idle_stable)) { /* or timer not stable? */ + (rtc_elapsed[tmr] < 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" : ((rtc_elapsed[tmr] < sim_idle_stable) ? "not stable" : ((sim_clock_queue != QUEUE_LIST_END) ? sim_uname (sim_clock_queue) : @@ -2282,17 +2289,18 @@ return NULL; #endif /* defined(SIM_ASYNCH_CLOCKS) */ /* - In the event that there are no active clock devices, no instruction - rate calibration will be performed. This is more likely on simpler - simulators which don't have a full spectrum of standard devices or - possibly when a clock device exists but its use is optional. + In the event that there are no active calibrated clock devices, + no instruction rate calibration will be performed. This is more + likely on simpler simulators which don't have a full spectrum of + standard devices or possibly when a clock device exists but its + use is optional. - Additonally, when a host system has a natural clock tick (or minimal - sleep time) which is greater than the tick size that a simulator - wants to run a clock at, we run this clock at the rate implied by - the host system's minimal sleep time or 50Hz. + Additonally, when a host system has a natural clock tick ( + or minimal sleep time) which is greater than the tick size that + a simulator wants to run a clock at, we run this clock at the + rate implied by the host system's minimal sleep time or 50Hz. - To solve this we merely run an internal clock at 10Hz. + To solve this we merely run an internal clock at 100Hz. */ static t_stat sim_timer_clock_tick_svc (UNIT *uptr) @@ -2414,24 +2422,25 @@ return SCPE_OK; void sim_start_timer_services (void) { -/* - * If we're quickly running again after being stopped for less than - * the time of one calibrated clock tick, then don't force a complete - * recalibration of any timers that may have been previously running. - */ -if ((sim_calb_tmr_last != -1) && - ((sim_timenow_double () - sim_stop_time) < rtc_clock_tick_size[sim_calb_tmr_last])) { - int32 clock_time = sim_activate_time (sim_clock_unit[sim_calb_tmr_last]); +int32 tmr; +uint32 sim_prompt_time = sim_os_msec () - sim_stop_time; - sim_calb_tmr = sim_calb_tmr_last; - sim_cancel (sim_clock_unit[sim_calb_tmr]); - sim_activate (&sim_timer_units[sim_calb_tmr], clock_time); - sim_debug (DBG_TRC, &sim_timer_dev, "sim_start_timer_services() - restarting with previously calibrated timer %d (%s) at %d\n", sim_calb_tmr, sim_uname (sim_clock_unit[sim_calb_tmr]), clock_time); +for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { + if (rtc_hz[tmr]) { /* calibrated clock running? */ + rtc_rtime[tmr] += sim_prompt_time; + rtc_vtime[tmr] += sim_prompt_time; + sim_debug (DBG_TRC, &sim_timer_dev, "sim_start_timer_services(tmr=%d) - adjusting calibration real time by %d ms\n", tmr, (int)sim_prompt_time); + } + } +if (sim_calb_tmr == -1) { + sim_debug (DBG_TRC, &sim_timer_dev, "sim_start_timer_services() - starting from scratch\n"); + _rtcn_configure_calibrated_clock (sim_calb_tmr); } else { - sim_debug (DBG_TRC, &sim_timer_dev, "sim_start_timer_services() - starting from scratch\n"); - sim_rtcn_init_all (); /* re-init clocks */ - _rtcn_configure_calibrated_clock (sim_calb_tmr); + if (sim_calb_tmr == SIM_NTIMERS) { + sim_debug (DBG_TRC, &sim_timer_dev, "sim_start_timer_services() - restarting internal timer after %d cycles\n", sim_internal_timer_time); + sim_activate (&SIM_INTERNAL_UNIT, sim_internal_timer_time); + } } if (sim_timer_stop_time > sim_gtime()) sim_activate_abs (&sim_stop_unit, (int32)(sim_timer_stop_time - sim_gtime())); @@ -2457,7 +2466,7 @@ void sim_stop_timer_services (void) { int tmr; -sim_debug (DBG_TRC, &sim_timer_dev, "sim_stop_timer_services(sim_interval=%d)\n", sim_interval); +sim_debug (DBG_TRC, &sim_timer_dev, "sim_stop_timer_services(sim_interval=%d, sim_calb_tmr=%d)\n", sim_interval, sim_calb_tmr); if (sim_interval < 0) sim_interval = 0; /* No catching up after stopping */ @@ -2496,12 +2505,13 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { } } +if (sim_calb_tmr == SIM_NTIMERS) + sim_internal_timer_time = sim_activate_time (&SIM_INTERNAL_UNIT) - 1; sim_cancel (&SIM_INTERNAL_UNIT); /* Make sure Internal Timer is stopped */ sim_cancel (&sim_timer_units[SIM_NTIMERS]); sim_calb_tmr_last = sim_calb_tmr; /* Save calibrated timer value for display */ sim_inst_per_sec_last = sim_timer_inst_per_sec (); /* Save execution rate for display */ -sim_calb_tmr = -1; -sim_stop_time = sim_timenow_double (); /* record when execution stopped */ +sim_stop_time = sim_os_msec (); /* record when execution stopped */ #if defined(SIM_ASYNCH_CLOCKS) pthread_mutex_lock (&sim_timer_lock); if (sim_timer_thread_running) {