TIMER: Stabilize run away clock calibration conditions

- Adjust calibration parameters to properly record catchup variables for
  odd condition cases.
- Disable idle percentage calibration skipping until the correct set of
  calibration variables are available.
- When a pre-calibrate operation has been performed, make the results
  visible in the output of SHOW CLOCK

As discussed in #705 and #699
This commit is contained in:
Mark Pizzolato 2019-06-03 20:45:40 -07:00
parent f917accbec
commit 9514ea5a58

View file

@ -150,6 +150,7 @@ return real_sim_os_ms_sleep (msec);
t_bool sim_idle_enab = FALSE; /* global flag */ t_bool sim_idle_enab = FALSE; /* global flag */
volatile t_bool sim_idle_wait = FALSE; /* global flag */ volatile t_bool sim_idle_wait = FALSE; /* global flag */
static int32 sim_precalibrate_ips = SIM_INITIAL_IPS;
static int32 sim_calb_tmr = -1; /* the system calibrated timer */ static int32 sim_calb_tmr = -1; /* the system calibrated timer */
static int32 sim_calb_tmr_last = -1; /* shadow value when at sim> prompt */ 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_inst_per_sec_last = 0; /* shadow value when at sim> prompt */
@ -161,7 +162,7 @@ static uint32 sim_os_sleep_inc_ms = 0;
static uint32 sim_os_clock_resoluton_ms = 0; static uint32 sim_os_clock_resoluton_ms = 0;
static uint32 sim_os_tick_hz = 0; static uint32 sim_os_tick_hz = 0;
static uint32 sim_idle_stable = SIM_IDLE_STDFLT; static uint32 sim_idle_stable = SIM_IDLE_STDFLT;
static uint32 sim_idle_calib_pct = 50; static uint32 sim_idle_calib_pct = 100;
static double sim_timer_stop_time = 0; static double sim_timer_stop_time = 0;
static uint32 sim_rom_delay = 0; static uint32 sim_rom_delay = 0;
static uint32 sim_throt_ms_start = 0; static uint32 sim_throt_ms_start = 0;
@ -177,7 +178,7 @@ static uint32 sim_throt_sleep_time = 0;
static int32 sim_throt_wait = 0; static int32 sim_throt_wait = 0;
static uint32 sim_throt_delay = 3; static uint32 sim_throt_delay = 3;
#define CLK_TPS 100 #define CLK_TPS 100
#define CLK_INIT (SIM_INITIAL_IPS/CLK_TPS) #define CLK_INIT (sim_precalibrate_ips/CLK_TPS)
static int32 sim_int_clk_tps; static int32 sim_int_clk_tps;
static UNIT *sim_clock_unit[SIM_NTIMERS+1] = {NULL}; static UNIT *sim_clock_unit[SIM_NTIMERS+1] = {NULL};
UNIT * volatile sim_clock_cosched_queue[SIM_NTIMERS+1] = {NULL}; UNIT * volatile sim_clock_cosched_queue[SIM_NTIMERS+1] = {NULL};
@ -800,12 +801,14 @@ t_stat sim_timer_stop_svc (UNIT *uptr);
#define DBG_CHK 0x100 /* check scheduled activation time*/ #define DBG_CHK 0x100 /* check scheduled activation time*/
#define DBG_INT 0x200 /* internal timer activities */ #define DBG_INT 0x200 /* internal timer activities */
#define DBG_GET 0x400 /* get_time activities */ #define DBG_GET 0x400 /* get_time activities */
#define DBG_TIK 0x800 /* tick activities */
DEBTAB sim_timer_debug[] = { DEBTAB sim_timer_debug[] = {
{"TRACE", DBG_TRC, "Trace routine calls"}, {"TRACE", DBG_TRC, "Trace routine calls"},
{"IDLE", DBG_IDL, "Idling activities"}, {"IDLE", DBG_IDL, "Idling activities"},
{"QUEUE", DBG_QUE, "Event queuing activities"}, {"QUEUE", DBG_QUE, "Event queuing activities"},
{"IACK", DBG_ACK, "interrupt acknowledgement activities"}, {"IACK", DBG_ACK, "interrupt acknowledgement activities"},
{"CALIB", DBG_CAL, "Calibration activities"}, {"CALIB", DBG_CAL, "Calibration activities"},
{"TICK", DBG_TIK, "Calibration tick activities"},
{"TIME", DBG_TIM, "Activation and scheduling activities"}, {"TIME", DBG_TIM, "Activation and scheduling activities"},
{"GETTIME", DBG_GET, "get_time activities"}, {"GETTIME", DBG_GET, "get_time activities"},
{"INTER", DBG_INT, "Internal timer activities"}, {"INTER", DBG_INT, "Internal timer activities"},
@ -930,11 +933,11 @@ if (rtc_clock_catchup_pending[tmr]) { /* catchup tick? */
++rtc_clock_catchup_ticks[tmr]; /* accumulating which were catchups */ ++rtc_clock_catchup_ticks[tmr]; /* accumulating which were catchups */
rtc_clock_catchup_pending[tmr] = FALSE; rtc_clock_catchup_pending[tmr] = FALSE;
} }
rtc_ticks[tmr] = rtc_ticks[tmr] + 1; /* count ticks */ rtc_ticks[tmr] += 1; /* count ticks */
if (rtc_ticks[tmr] < ticksper) /* 1 sec yet? */ if (rtc_ticks[tmr] < ticksper) /* 1 sec yet? */
return rtc_currd[tmr]; return rtc_currd[tmr];
rtc_ticks[tmr] = 0; /* reset ticks */ rtc_ticks[tmr] = 0; /* reset ticks */
rtc_elapsed[tmr] = rtc_elapsed[tmr] + 1; /* count sec */ rtc_elapsed[tmr] += 1; /* count sec */
if (!rtc_avail) /* no timer? */ if (!rtc_avail) /* no timer? */
return rtc_currd[tmr]; return rtc_currd[tmr];
if (sim_calb_tmr != tmr) { if (sim_calb_tmr != tmr) {
@ -953,11 +956,15 @@ if (new_rtime < rtc_rtime[tmr]) { /* time running backward
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]); 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_vtime[tmr] = rtc_rtime[tmr] = new_rtime; /* reset wall time */ rtc_vtime[tmr] = rtc_rtime[tmr] = new_rtime; /* reset wall time */
rtc_nxintv[tmr] = 1000; rtc_nxintv[tmr] = 1000;
if (rtc_clock_catchup_eligible[tmr]) {
rtc_clock_catchup_base_time[tmr] = sim_timenow_double();
rtc_calib_tick_time[tmr] = 0.0;
}
return rtc_currd[tmr]; /* can't calibrate */ return rtc_currd[tmr]; /* can't calibrate */
} }
delta_rtime = new_rtime - rtc_rtime[tmr]; /* elapsed wtime */ delta_rtime = new_rtime - rtc_rtime[tmr]; /* elapsed wtime */
rtc_rtime[tmr] = new_rtime; /* adv wall time */ rtc_rtime[tmr] = new_rtime; /* adv wall time */
rtc_vtime[tmr] = rtc_vtime[tmr] + 1000; /* adv sim time */ rtc_vtime[tmr] += 1000; /* adv sim time */
if (delta_rtime > 30000) { /* gap too big? */ if (delta_rtime > 30000) { /* gap too big? */
/* This simulator process has somehow been suspended for a significant */ /* This simulator process has somehow been suspended for a significant */
/* amount of time. This will certainly happen if the host system has */ /* amount of time. This will certainly happen if the host system has */
@ -969,6 +976,8 @@ if (delta_rtime > 30000) { /* gap too big? */
rtc_vtime[tmr] = rtc_rtime[tmr]; /* sync virtual and real time */ rtc_vtime[tmr] = rtc_rtime[tmr]; /* sync virtual and real time */
rtc_nxintv[tmr] = 1000; /* reset next interval */ rtc_nxintv[tmr] = 1000; /* reset next interval */
rtc_gtime[tmr] = sim_gtime(); /* save instruction time */ rtc_gtime[tmr] = sim_gtime(); /* save instruction time */
if (rtc_clock_catchup_eligible[tmr])
rtc_calib_tick_time[tmr] += ((double)delta_rtime / 1000.0);/* advance tick time */
sim_debug (DBG_CAL, &sim_timer_dev, "gap too big: delta = %d - result: %d\n", delta_rtime, rtc_currd[tmr]); sim_debug (DBG_CAL, &sim_timer_dev, "gap too big: delta = %d - result: %d\n", delta_rtime, rtc_currd[tmr]);
return rtc_currd[tmr]; /* can't calibr */ return rtc_currd[tmr]; /* can't calibr */
} }
@ -978,14 +987,17 @@ if (tmr != SIM_NTIMERS) {
else else
last_idle_pct = MIN(100, (uint32)(100.0 * (((double)(rtc_clock_time_idled[tmr] - rtc_clock_time_idled_last[tmr])) / ((double)delta_rtime)))); last_idle_pct = MIN(100, (uint32)(100.0 * (((double)(rtc_clock_time_idled[tmr] - rtc_clock_time_idled_last[tmr])) / ((double)delta_rtime))));
rtc_clock_time_idled_last[tmr] = rtc_clock_time_idled[tmr]; rtc_clock_time_idled_last[tmr] = rtc_clock_time_idled[tmr];
if (last_idle_pct > (100 - sim_idle_calib_pct)) { #if defined (SIM_TIME_IDLE_PCT)
if (last_idle_pct > sim_idle_calib_pct) {
rtc_rtime[tmr] = new_rtime; /* save wall time */ rtc_rtime[tmr] = new_rtime; /* save wall time */
rtc_vtime[tmr] = rtc_vtime[tmr] + 1000; /* adv sim time */ rtc_vtime[tmr] += 1000; /* adv sim time */
rtc_gtime[tmr] = sim_gtime(); /* save instruction time */ rtc_gtime[tmr] = sim_gtime(); /* save instruction time */
rtc_based[tmr] = rtc_initd[tmr];
++rtc_clock_calib_skip_idle[tmr]; ++rtc_clock_calib_skip_idle[tmr];
sim_debug (DBG_CAL, &sim_timer_dev, "skipping calibration due to idling (%d%%) - result: %d\n", last_idle_pct, rtc_currd[tmr]); sim_debug (DBG_CAL, &sim_timer_dev, "skipping calibration due to idling (%d%%) - result: %d\n", last_idle_pct, rtc_currd[tmr]);
return rtc_currd[tmr]; /* avoid calibrating idle checks */ return rtc_currd[tmr]; /* avoid calibrating idle checks */
} }
#endif
} }
new_gtime = sim_gtime(); new_gtime = sim_gtime();
if ((last_idle_pct == 0) && (delta_rtime != 0)) { if ((last_idle_pct == 0) && (delta_rtime != 0)) {
@ -1000,9 +1012,10 @@ if (sim_asynch_timer) {
/* avoid excessive swings in the calibrated result */ /* avoid excessive swings in the calibrated result */
if (new_currd > 10*rtc_currd[tmr]) /* don't swing big too fast */ if (new_currd > 10*rtc_currd[tmr]) /* don't swing big too fast */
new_currd = 10*rtc_currd[tmr]; new_currd = 10*rtc_currd[tmr];
else else {
if (new_currd < rtc_currd[tmr]/10) /* don't swing small too fast */ if (new_currd < rtc_currd[tmr]/10) /* don't swing small too fast */
new_currd = rtc_currd[tmr]/10; new_currd = rtc_currd[tmr]/10;
}
rtc_currd[tmr] = new_currd; rtc_currd[tmr] = new_currd;
rtc_gtime[tmr] = new_gtime; /* save instruction time */ rtc_gtime[tmr] = new_gtime; /* save instruction time */
sim_debug (DBG_CAL, &sim_timer_dev, "asynch calibration result: %d\n", rtc_currd[tmr]); sim_debug (DBG_CAL, &sim_timer_dev, "asynch calibration result: %d\n", rtc_currd[tmr]);
@ -1020,8 +1033,10 @@ else
delta_vtime = rtc_vtime[tmr] - rtc_rtime[tmr]; /* gap */ delta_vtime = rtc_vtime[tmr] - rtc_rtime[tmr]; /* gap */
if (delta_vtime > SIM_TMAX) /* limit gap */ if (delta_vtime > SIM_TMAX) /* limit gap */
delta_vtime = SIM_TMAX; delta_vtime = SIM_TMAX;
else if (delta_vtime < -SIM_TMAX) else {
delta_vtime = -SIM_TMAX; if (delta_vtime < -SIM_TMAX)
delta_vtime = -SIM_TMAX;
}
rtc_nxintv[tmr] = 1000 + delta_vtime; /* next wtime */ rtc_nxintv[tmr] = 1000 + delta_vtime; /* next wtime */
rtc_currd[tmr] = (int32) (((double) rtc_based[tmr] * (double) rtc_nxintv[tmr]) / rtc_currd[tmr] = (int32) (((double) rtc_based[tmr] * (double) rtc_nxintv[tmr]) /
1000.0); /* next delay */ 1000.0); /* next delay */
@ -1116,27 +1131,31 @@ time_t time_t_now;
int32 calb_tmr = (sim_calb_tmr == -1) ? sim_calb_tmr_last : sim_calb_tmr; int32 calb_tmr = (sim_calb_tmr == -1) ? sim_calb_tmr_last : sim_calb_tmr;
double inst_per_sec = sim_timer_inst_per_sec (); double inst_per_sec = sim_timer_inst_per_sec ();
fprintf (st, "Minimum Host Sleep Time: %d ms (%dHz)\n", sim_os_sleep_min_ms, sim_os_tick_hz); fprintf (st, "Minimum Host Sleep Time: %d ms (%dHz)\n", sim_os_sleep_min_ms, sim_os_tick_hz);
if (sim_os_sleep_min_ms != sim_os_sleep_inc_ms) 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, "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, "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 cycles/sec\n", sim_fmt_numeric (inst_per_sec));
if (sim_idle_enab) { if (sim_idle_enab) {
fprintf (st, "Idling: Enabled\n"); fprintf (st, "Idling: Enabled\n");
fprintf (st, "Time before Idling starts: %d seconds\n", sim_idle_stable); fprintf (st, "Time before Idling starts: %d seconds\n", sim_idle_stable);
} }
if (sim_throt_type != SIM_THROT_NONE) { if (sim_throt_type != SIM_THROT_NONE) {
sim_show_throt (st, NULL, uptr, val, desc); sim_show_throt (st, NULL, uptr, val, desc);
} }
fprintf (st, "Calibrated Timer: %s\n", (calb_tmr == -1) ? "Undetermined" : fprintf (st, "Calibrated Timer: %s\n", (calb_tmr == -1) ? "Undetermined" :
((calb_tmr == SIM_NTIMERS) ? "Internal Timer" : ((calb_tmr == SIM_NTIMERS) ? "Internal Timer" :
(sim_clock_unit[calb_tmr] ? sim_uname(sim_clock_unit[calb_tmr]) : ""))); (sim_clock_unit[calb_tmr] ? sim_uname(sim_clock_unit[calb_tmr]) : "")));
if (calb_tmr == SIM_NTIMERS) if (calb_tmr == SIM_NTIMERS)
fprintf (st, "Catchup Ticks: %s for clocks ticking faster than %d Hz\n", sim_catchup_ticks ? "Enabled" : "Disabled", sim_os_tick_hz); fprintf (st, "Catchup Ticks: %s for clocks ticking faster than %d Hz\n", sim_catchup_ticks ? "Enabled" : "Disabled", sim_os_tick_hz);
if (sim_idle_calib_pct == 0) fprintf (st, "Pre-Calibration Estimated Rate: %s\n", sim_fmt_numeric ((double)sim_precalibrate_ips));
fprintf (st, "Calibration: Always\n"); if (sim_idle_calib_pct == 100)
fprintf (st, "Calibration: Always\n");
else else
fprintf (st, "Calibration: Skipped when Idle exceeds %d%%\n", sim_idle_calib_pct); fprintf (st, "Calibration: Skipped when Idle exceeds %d%%\n", sim_idle_calib_pct);
#if defined(SIM_ASYNCH_CLOCKS)
fprintf (st, "Asynchronous Clocks: %s\n", sim_asynch_timer ? "Active" : "Available");
#endif
fprintf (st, "\n"); fprintf (st, "\n");
for (tmr=clocks=0; tmr<=SIM_NTIMERS; ++tmr) { for (tmr=clocks=0; tmr<=SIM_NTIMERS; ++tmr) {
if (0 == rtc_initd[tmr]) if (0 == rtc_initd[tmr])
@ -1159,8 +1178,8 @@ for (tmr=clocks=0; tmr<=SIM_NTIMERS; ++tmr) {
fprintf (st, " Seconds Running: %s (%s)\n", sim_fmt_numeric ((double)rtc_elapsed[tmr]), sim_fmt_secs ((double)rtc_elapsed[tmr])); fprintf (st, " Seconds Running: %s (%s)\n", sim_fmt_numeric ((double)rtc_elapsed[tmr]), sim_fmt_secs ((double)rtc_elapsed[tmr]));
if (tmr == calb_tmr) { if (tmr == calb_tmr) {
fprintf (st, " Calibration Opportunities: %s\n", sim_fmt_numeric ((double)rtc_calibrations[tmr])); fprintf (st, " Calibration Opportunities: %s\n", sim_fmt_numeric ((double)rtc_calibrations[tmr]));
if (sim_idle_calib_pct) if (sim_idle_calib_pct && (sim_idle_calib_pct != 100))
fprintf (st, " Calib Skip Idle Thresh %%: %u\n", sim_idle_calib_pct); fprintf (st, " Calib Skip when Idle >: %u%%\n", sim_idle_calib_pct);
if (rtc_clock_calib_skip_idle[tmr]) if (rtc_clock_calib_skip_idle[tmr])
fprintf (st, " Calibs Skip While Idle: %u\n", rtc_clock_calib_skip_idle[tmr]); fprintf (st, " Calibs Skip While Idle: %u\n", rtc_clock_calib_skip_idle[tmr]);
if (rtc_clock_calib_backwards[tmr]) if (rtc_clock_calib_backwards[tmr])
@ -1340,8 +1359,9 @@ if (flag) {
sim_catchup_ticks = TRUE; sim_catchup_ticks = TRUE;
} }
else { else {
if (sim_catchup_ticks) if (sim_catchup_ticks) {
sim_catchup_ticks = FALSE; sim_catchup_ticks = FALSE;
}
} }
return SCPE_OK; return SCPE_OK;
} }
@ -1357,26 +1377,33 @@ return SCPE_OK;
t_stat sim_timer_set_idle_pct (int32 flag, CONST char *cptr) t_stat sim_timer_set_idle_pct (int32 flag, CONST char *cptr)
{ {
t_stat r = SCPE_OK; t_stat r = SCPE_OK;
int32 newpct;
char gbuf[CBUFSIZE];
if (cptr == NULL) if (cptr == NULL)
return SCPE_ARG; return SCPE_ARG;
cptr = get_glyph (cptr, gbuf, 0); /* get argument */ #if defined (SIM_TIME_IDLE_PCT)
if (isdigit (gbuf[0])) if (1) {
newpct = (int32) get_uint (gbuf, 10, 100, &r); int32 newpct;
else { char gbuf[CBUFSIZE];
if (MATCH_CMD (gbuf, "ALWAYS") == 0)
newpct = 0; cptr = get_glyph (cptr, gbuf, 0); /* get argument */
else if (isdigit (gbuf[0]))
r = SCPE_ARG; newpct = (int32) get_uint (gbuf, 10, 100, &r);
else {
if (MATCH_CMD (gbuf, "ALWAYS") == 0)
newpct = 100;
else
r = SCPE_ARG;
}
if ((r != SCPE_OK) || (newpct == (int32)(sim_idle_calib_pct)))
return r;
if (newpct == 0)
return SCPE_ARG;
sim_idle_calib_pct = (uint32)newpct;
} }
if ((r != SCPE_OK) || (newpct == (int32)(sim_idle_calib_pct)))
return r;
if (newpct == 0)
return SCPE_ARG;
sim_idle_calib_pct = (uint32)newpct;
return SCPE_OK; return SCPE_OK;
#else
return sim_messagef (SCPE_NOFNC, "Calibration Idle Threshold %% is not implemented\n");
#endif
} }
/* Set stop time */ /* Set stop time */
@ -1551,7 +1578,7 @@ if ((!sim_idle_enab) || /* idling disabled */
return FALSE; return FALSE;
} }
if (_rtcn_tick_catchup_check (tmr, -1)) { if (_rtcn_tick_catchup_check (tmr, -1)) {
sim_debug (DBG_CAL, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d) - rescheduling catchup tick for %s\n", tmr, sin_cyc, sim_uname (sim_clock_unit[tmr])); sim_debug (DBG_CAL, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d) - rescheduling catchup tick %d for %s\n", tmr, sin_cyc, 1 + rtc_ticks[tmr], sim_uname (sim_clock_unit[tmr]));
sim_interval -= sin_cyc; sim_interval -= sin_cyc;
return FALSE; return FALSE;
} }
@ -1569,7 +1596,7 @@ if (_rtcn_tick_catchup_check (tmr, -1)) {
To negate this effect, we accumulate the time actually idled here. To negate this effect, we accumulate the time actually idled here.
sim_rtcn_calb compares the accumulated idle time during the most recent sim_rtcn_calb compares the accumulated idle time during the most recent
second and if it exceeds the percentage defined by and sim_idle_calib_pct second and if it exceeds the percentage defined by sim_idle_calib_pct
calibration is suppressed. Thus recalibration only happens if things calibration is suppressed. Thus recalibration only happens if things
didn't idle too much. didn't idle too much.
@ -1606,6 +1633,9 @@ if (w_idle < 500) { /* shorter than 1/2 the
in_nowait = TRUE; in_nowait = TRUE;
return FALSE; return FALSE;
} }
if (w_ms > 1000) { /* too long a wait */
sim_debug (DBG_TIK, &sim_timer_dev, "waiting too long: w_ms=%d usecs, w_idle=%d usecs, sim_interval=%d, rtc_currd[tmr]=%d\n", w_ms, w_idle, sim_interval, rtc_currd[tmr]);
}
in_nowait = FALSE; in_nowait = FALSE;
if (sim_clock_queue == QUEUE_LIST_END) 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 instructions\n", w_ms, sim_interval);
@ -1734,7 +1764,7 @@ else {
if (sim_throt_type == SIM_THROT_SPC) /* Set initial value while correct one is determined */ if (sim_throt_type == SIM_THROT_SPC) /* Set initial value while correct one is determined */
sim_throt_cps = (int32)((1000.0 * sim_throt_val) / (double)sim_throt_sleep_time); sim_throt_cps = (int32)((1000.0 * sim_throt_val) / (double)sim_throt_sleep_time);
else else
sim_throt_cps = SIM_INITIAL_IPS; sim_throt_cps = sim_precalibrate_ips;
return SCPE_OK; return SCPE_OK;
} }
@ -2147,12 +2177,12 @@ if ((rtc_hz[tmr] > 0) &&
if (tnow > (rtc_clock_catchup_base_time[tmr] + (rtc_calib_tick_time[tmr] + rtc_clock_tick_size[tmr]))) { if (tnow > (rtc_clock_catchup_base_time[tmr] + (rtc_calib_tick_time[tmr] + rtc_clock_tick_size[tmr]))) {
if (!rtc_clock_catchup_pending[tmr]) { if (!rtc_clock_catchup_pending[tmr]) {
sim_debug (DBG_CAL, &sim_timer_dev, "_rtcn_tick_catchup_check(%d) - scheduling catchup tick for %s which is behind %s\n", time, sim_uname (sim_clock_unit[tmr]), sim_fmt_secs ((rtc_clock_catchup_base_time[tmr] + (rtc_calib_tick_time[tmr] + rtc_clock_tick_size[tmr]))- tnow)); sim_debug (DBG_TIK, &sim_timer_dev, "_rtcn_tick_catchup_check(%d) - scheduling catchup tick %d for %s which is behind %s\n", time, 1 + rtc_ticks[tmr], sim_uname (sim_clock_unit[tmr]), sim_fmt_secs (tnow - (rtc_clock_catchup_base_time[tmr] + (rtc_calib_tick_time[tmr] + rtc_clock_tick_size[tmr]))));
rtc_clock_catchup_pending[tmr] = TRUE; rtc_clock_catchup_pending[tmr] = TRUE;
sim_activate_abs (&sim_timer_units[tmr], (time < 0) ? 0 : time); sim_activate_abs (&sim_timer_units[tmr], (time < 0) ? 0 : time);
} }
else else
sim_debug (DBG_CAL, &sim_timer_dev, "_rtcn_tick_catchup_check(%d) - already pending catchup tick for %s which is behind %s\n", time, sim_uname (sim_clock_unit[tmr]), sim_fmt_secs ((rtc_clock_catchup_base_time[tmr] + (rtc_calib_tick_time[tmr] + rtc_clock_tick_size[tmr]))- tnow)); sim_debug (DBG_TIK, &sim_timer_dev, "_rtcn_tick_catchup_check(%d) - already pending catchup tick %d for %s which is behind %s\n", time, 1 + rtc_ticks[tmr], sim_uname (sim_clock_unit[tmr]), sim_fmt_secs (tnow - (rtc_clock_catchup_base_time[tmr] + (rtc_calib_tick_time[tmr] + rtc_clock_tick_size[tmr]))));
return TRUE; return TRUE;
} }
} }
@ -2373,7 +2403,7 @@ if (tmr == SIM_NTIMERS) { /* None found? */
SIM_INTERNAL_UNIT.action = &sim_timer_clock_tick_svc; SIM_INTERNAL_UNIT.action = &sim_timer_clock_tick_svc;
SIM_INTERNAL_UNIT.flags = UNIT_IDLE; SIM_INTERNAL_UNIT.flags = UNIT_IDLE;
sim_register_internal_device (&sim_int_timer_dev); /* Register Internal timer device */ sim_register_internal_device (&sim_int_timer_dev); /* Register Internal timer device */
sim_rtcn_init_unit (&SIM_INTERNAL_UNIT, (CLK_INIT*CLK_TPS)/sim_int_clk_tps, SIM_INTERNAL_CLK); sim_rtcn_init_unit (&SIM_INTERNAL_UNIT, (int32)((CLK_INIT*CLK_TPS)/sim_int_clk_tps), SIM_INTERNAL_CLK);
SIM_INTERNAL_UNIT.action (&SIM_INTERNAL_UNIT); /* Force tick to activate timer */ SIM_INTERNAL_UNIT.action (&SIM_INTERNAL_UNIT); /* Force tick to activate timer */
} }
return; return;
@ -2440,7 +2470,7 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
rtc_vtime[tmr] += sim_prompt_time; rtc_vtime[tmr] += sim_prompt_time;
sim_debug (DBG_CAL, &sim_timer_dev, "sim_start_timer_services(tmr=%d) - adjusting calibration real time by %d ms\n", tmr, (int)sim_prompt_time); sim_debug (DBG_CAL, &sim_timer_dev, "sim_start_timer_services(tmr=%d) - adjusting calibration real time by %d ms\n", tmr, (int)sim_prompt_time);
if (rtc_clock_catchup_eligible[tmr]) if (rtc_clock_catchup_eligible[tmr])
rtc_clock_catchup_base_time[tmr] += (((double)sim_prompt_time) / 1000.0); rtc_calib_tick_time[tmr] += (((double)sim_prompt_time) / 1000.0);
} }
} }
if (sim_calb_tmr == -1) { if (sim_calb_tmr == -1) {
@ -3235,7 +3265,6 @@ void sim_timer_precalibrate_execution_rate (void)
{ {
const char **cmd = sim_clock_precalibrate_commands; const char **cmd = sim_clock_precalibrate_commands;
uint32 start, end; uint32 start, end;
double ips_rate;
int32 saved_switches = sim_switches; int32 saved_switches = sim_switches;
int32 tmr; int32 tmr;
UNIT precalib_unit = { UDATA (&sim_timer_stop_svc, 0, 0) }; UNIT precalib_unit = { UDATA (&sim_timer_stop_svc, 0, 0) };
@ -3249,18 +3278,16 @@ while (*cmd)
exdep_cmd (EX_D, *(cmd++)); exdep_cmd (EX_D, *(cmd++));
sim_switches = saved_switches; sim_switches = saved_switches;
sim_cancel (&SIM_INTERNAL_UNIT); sim_cancel (&SIM_INTERNAL_UNIT);
sim_activate (&precalib_unit, SIM_INITIAL_IPS); sim_activate (&precalib_unit, sim_precalibrate_ips);
start = sim_os_msec(); start = sim_os_msec();
sim_instr(); sim_instr();
end = sim_os_msec(); end = sim_os_msec();
ips_rate = 1000.0 * (SIM_INITIAL_IPS / (double)(end - start)); sim_precalibrate_ips = (int32)(1000.0 * (sim_precalibrate_ips / (double)(end - start)));
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) { for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
if (rtc_hz[tmr]) if (rtc_hz[tmr])
rtc_initd[tmr] = rtc_currd[tmr] = (int32)(ips_rate / rtc_hz[tmr]); rtc_initd[tmr] = rtc_currd[tmr] = (int32)(((double)sim_precalibrate_ips) / rtc_hz[tmr]);
} }
reset_all_p (0); reset_all_p (0);
sim_run_boot_prep (RU_GO); sim_run_boot_prep (RU_GO);
if (sim_switches & SWMASK ('V'))
sim_printf ("Pre-Calibrate execution rate: %s cycles/sec\n", sim_fmt_numeric (ips_rate));
} }