mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-13 07:19:26 +00:00
SCP: Updated to current.
This commit is contained in:
parent
65fa360984
commit
0b6718d429
9
scp.c
9
scp.c
@ -2619,6 +2619,10 @@ if (*argv[0]) { /* sim name arg? */
|
||||
setenv ("SIM_BIN_PATH", argv[0], 1);
|
||||
}
|
||||
sim_argv = argv;
|
||||
|
||||
if (sim_switches & SWMASK ('T')) /* Command Line -T switch */
|
||||
stat = sim_library_unit_tests (); /* run library unit tests */
|
||||
|
||||
cptr = getenv("HOME");
|
||||
if (cptr == NULL) {
|
||||
cptr = getenv("HOMEPATH");
|
||||
@ -2657,9 +2661,6 @@ else if (*argv[0]) { /* sim name arg? */
|
||||
if (SCPE_BARE_STATUS(stat) == SCPE_OPENERR) /* didn't exist/can't open? */
|
||||
stat = SCPE_OK;
|
||||
|
||||
if (sim_switches & SWMASK ('T')) /* Command Line -T switch */
|
||||
stat = sim_library_unit_tests (); /* run library unit tests */
|
||||
|
||||
if (SCPE_BARE_STATUS(stat) != SCPE_EXIT)
|
||||
process_stdin_commands (SCPE_BARE_STATUS(stat), argv);
|
||||
|
||||
@ -6942,7 +6943,7 @@ else {
|
||||
uptr->fileref = sim_fopen (cptr, "wb+"); /* open new file */
|
||||
if (uptr->fileref == NULL) /* open fail? */
|
||||
return attach_err (uptr, SCPE_OPENERR); /* yes, error */
|
||||
sim_messagef (SCPE_OK, "%s: creating new file\n", sim_dname (dptr));
|
||||
sim_messagef (SCPE_OK, "%s: creating new file: %s\n", sim_dname (dptr), cptr);
|
||||
}
|
||||
else { /* normal */
|
||||
uptr->fileref = sim_fopen (cptr, "rb+"); /* open r/w */
|
||||
|
||||
229
sim_timer.c
229
sim_timer.c
@ -155,8 +155,9 @@ static int32 sim_calb_tmr = -1; /* the system calibrated tim
|
||||
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 uint32 sim_stop_time = 0; /* time when sim_stop_timer_services was called */
|
||||
double sim_time_at_sim_prompt = 0; /* time spent processing commands from sim> prompt */
|
||||
|
||||
static uint32 sim_idle_rate_ms = 0;
|
||||
static uint32 sim_idle_rate_ms = 0; /* Minimum Sleep time */
|
||||
static uint32 sim_os_sleep_min_ms = 0;
|
||||
static uint32 sim_os_sleep_inc_ms = 0;
|
||||
static uint32 sim_os_clock_resoluton_ms = 0;
|
||||
@ -182,10 +183,11 @@ static uint32 sim_throt_delay = 3;
|
||||
static int32 sim_int_clk_tps;
|
||||
|
||||
typedef struct RTC {
|
||||
UNIT *clock_unit;
|
||||
UNIT *clock_unit; /* registered ticking clock unit */
|
||||
UNIT *timer_unit; /* points to related clock assist unit (sim_timer_units) */
|
||||
UNIT *clock_cosched_queue;
|
||||
int32 cosched_interval;
|
||||
int32 ticks; /* ticks */
|
||||
uint32 ticks; /* ticks */
|
||||
uint32 hz; /* tick rate */
|
||||
uint32 last_hz; /* prior tick rate */
|
||||
uint32 rtime; /* real time (usecs) */
|
||||
@ -198,7 +200,6 @@ typedef struct RTC {
|
||||
uint32 elapsed; /* seconds since init */
|
||||
uint32 calibrations; /* calibration count */
|
||||
double clock_skew_max; /* asynchronous max skew */
|
||||
double clock_start_gtime; /* reference instruction time for clock */
|
||||
double clock_tick_size; /* 1/hz */
|
||||
uint32 calib_initializations; /* Initialization Count */
|
||||
double calib_tick_time; /* ticks time */
|
||||
@ -750,7 +751,7 @@ while (diff->tv_nsec >= 1000000000) {
|
||||
|
||||
static double _timespec_to_double (struct timespec *time);
|
||||
static void _double_to_timespec (struct timespec *time, double dtime);
|
||||
static t_bool _rtcn_tick_catchup_check (int32 tmr, int32 time);
|
||||
static t_bool _rtcn_tick_catchup_check (RTC *rtc, int32 time);
|
||||
static void _rtcn_configure_calibrated_clock (int32 newtmr);
|
||||
static t_bool _sim_coschedule_cancel (UNIT *uptr);
|
||||
static t_bool _sim_wallclock_cancel (UNIT *uptr);
|
||||
@ -837,10 +838,11 @@ void sim_rtcn_init_all (void)
|
||||
int32 tmr;
|
||||
RTC *rtc;
|
||||
|
||||
for (tmr = 0; tmr <= SIM_NTIMERS; tmr++)
|
||||
for (tmr = 0; tmr <= SIM_NTIMERS; tmr++) {
|
||||
rtc = &rtcs[tmr];
|
||||
if (rtc->initd != 0)
|
||||
sim_rtcn_init (rtc->initd, tmr);
|
||||
}
|
||||
}
|
||||
|
||||
int32 sim_rtcn_init (int32 time, int32 tmr)
|
||||
@ -880,7 +882,7 @@ if (uptr) {
|
||||
if (!rtc->clock_unit)
|
||||
sim_register_clock_unit_tmr (uptr, tmr);
|
||||
}
|
||||
rtc->clock_start_gtime = sim_gtime();
|
||||
rtc->gtime = sim_gtime();
|
||||
rtc->rtime = sim_is_running ? sim_os_msec () : sim_stop_time;
|
||||
rtc->vtime = rtc->rtime;
|
||||
rtc->nxintv = 1000;
|
||||
@ -916,7 +918,7 @@ RTC *rtc = &rtcs[tmr];
|
||||
return sim_rtcn_calb (rtc->hz, tmr);
|
||||
}
|
||||
|
||||
int32 sim_rtcn_calb (int32 ticksper, int32 tmr)
|
||||
int32 sim_rtcn_calb (uint32 ticksper, int32 tmr)
|
||||
{
|
||||
uint32 new_rtime, delta_rtime, last_idle_pct, catchup_ticks_curr;
|
||||
int32 delta_vtime;
|
||||
@ -945,8 +947,16 @@ if (rtc->hz != ticksper) { /* changing tick rate? */
|
||||
rtc->hz = ticksper;
|
||||
_rtcn_configure_calibrated_clock (tmr);
|
||||
if (ticksper != 0) {
|
||||
RTC *crtc = &rtcs[sim_calb_tmr];
|
||||
|
||||
rtc->clock_tick_size = 1.0 / ticksper;
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(ticksper=%d,tmr=%d) currd=%d, prior_hz=%d\n", ticksper, tmr, rtc->currd, (int)prior_hz);
|
||||
|
||||
if ((tmr != sim_calb_tmr) && rtc->clock_unit && (ticksper > crtc->hz)) {
|
||||
sim_catchup_ticks = TRUE;
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(%d) - forcing catchup ticks for %s ticking at %d, host tick rate %ds\n", tmr, sim_uname (rtc->clock_unit), ticksper, sim_os_tick_hz);
|
||||
_rtcn_tick_catchup_check (rtc, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
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, (int)prior_hz);
|
||||
@ -987,6 +997,7 @@ if (new_rtime < rtc->rtime) { /* time running backwards? *
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "time running backwards - OldTime: %u, NewTime: %u, result: %d\n", rtc->rtime, new_rtime, rtc->currd);
|
||||
rtc->vtime = rtc->rtime = new_rtime; /* reset wall time */
|
||||
rtc->nxintv = 1000;
|
||||
rtc->based = rtc->currd;
|
||||
if (rtc->clock_catchup_eligible) {
|
||||
rtc->clock_catchup_base_time = sim_timenow_double();
|
||||
rtc->calib_tick_time = 0.0;
|
||||
@ -1007,6 +1018,7 @@ if (delta_rtime > 30000) { /* gap too big? */
|
||||
rtc->vtime = rtc->rtime; /* sync virtual and real time */
|
||||
rtc->nxintv = 1000; /* reset next interval */
|
||||
rtc->gtime = sim_gtime(); /* save instruction time */
|
||||
rtc->based = rtc->currd;
|
||||
if (rtc->clock_catchup_eligible)
|
||||
rtc->calib_tick_time += ((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);
|
||||
@ -1021,7 +1033,7 @@ if (tmr != SIM_NTIMERS) {
|
||||
rtc->rtime = new_rtime; /* save wall time */
|
||||
rtc->vtime += 1000; /* adv sim time */
|
||||
rtc->gtime = sim_gtime(); /* save instruction time */
|
||||
rtc->based = rtc->initd;
|
||||
rtc->based = rtc->currd;
|
||||
++rtc->clock_calib_skip_idle;
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "skipping calibration due to idling (%d%%) - result: %d\n", last_idle_pct, rtc->currd);
|
||||
return rtc->currd; /* avoid calibrating idle checks */
|
||||
@ -1033,8 +1045,9 @@ if ((last_idle_pct == 0) && (delta_rtime != 0)) {
|
||||
if ((sim_idle_rate_ms != 0) && (delta_rtime > 1))
|
||||
sim_idle_cyc_sleep = (uint32)((new_gtime - rtc->gtime) / (delta_rtime / sim_idle_rate_ms));
|
||||
}
|
||||
if (sim_asynch_timer) {
|
||||
/* An asynchronous clock, merely needs to divide the number of */
|
||||
if (sim_asynch_timer || (catchup_ticks_curr > 0)) {
|
||||
/* An asynchronous clock or when catchup ticks have */
|
||||
/* occurred, we merely needs to divide the number of */
|
||||
/* instructions actually executed by the clock rate. */
|
||||
new_currd = (int32)((new_gtime - rtc->gtime)/ticksper);
|
||||
/* avoid excessive swings in the calibrated result */
|
||||
@ -1044,9 +1057,10 @@ if (sim_asynch_timer) {
|
||||
if (new_currd < rtc->currd/10) /* don't swing small too fast */
|
||||
new_currd = rtc->currd/10;
|
||||
}
|
||||
rtc->currd = new_currd;
|
||||
rtc->based = rtc->currd = new_currd;
|
||||
rtc->gtime = new_gtime; /* save instruction time */
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "asynch calibration result: %d\n", rtc->currd);
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(%s tmr=%d, tickper=%d) catchups=%u, idle=%d%% result: %d\n",
|
||||
sim_asynch_timer ? "asynch" : "catchup", tmr, ticksper, catchup_ticks_curr, last_idle_pct, rtc->currd);
|
||||
return rtc->currd; /* calibrated result */
|
||||
}
|
||||
rtc->gtime = new_gtime; /* save instruction time */
|
||||
@ -1072,7 +1086,7 @@ if (rtc->based <= 0) /* never negative or zero! *
|
||||
rtc->based = 1;
|
||||
if (rtc->currd <= 0) /* never negative or zero! */
|
||||
rtc->currd = 1;
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(calibrated tmr=%d, tickper=%d) (delta_rtime=%d, delta_vtime=%d, base=%d, nxintv=%u, catchups=%u, idle=%d%%, result: %d)\n",
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(tmr=%d, tickper=%d) (delta_rtime=%d, delta_vtime=%d, base=%d, nxintv=%u, catchups=%u, idle=%d%%, result: %d)\n",
|
||||
tmr, ticksper, (int)delta_rtime, (int)delta_vtime, rtc->based, rtc->nxintv, catchup_ticks_curr, last_idle_pct, rtc->currd);
|
||||
/* Adjust calibration for other timers which depend on this timer's calibration */
|
||||
for (itmr=0; itmr<=SIM_NTIMERS; itmr++) {
|
||||
@ -1092,7 +1106,7 @@ int32 sim_rtc_init (int32 time)
|
||||
return sim_rtcn_init (time, 0);
|
||||
}
|
||||
|
||||
int32 sim_rtc_calb (int32 ticksper)
|
||||
int32 sim_rtc_calb (uint32 ticksper)
|
||||
{
|
||||
return sim_rtcn_calb (ticksper, 0);
|
||||
}
|
||||
@ -1108,8 +1122,9 @@ sim_debug (DBG_TRC, &sim_timer_dev, "sim_timer_init()\n");
|
||||
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||
RTC *rtc = &rtcs[tmr];
|
||||
|
||||
sim_timer_units[tmr].action = &sim_timer_tick_svc;
|
||||
sim_timer_units[tmr].flags = UNIT_DIS | UNIT_IDLE;
|
||||
rtc->timer_unit = &sim_timer_units[tmr];
|
||||
rtc->timer_unit->action = &sim_timer_tick_svc;
|
||||
rtc->timer_unit->flags = UNIT_DIS | UNIT_IDLE;
|
||||
rtc->clock_cosched_queue = QUEUE_LIST_END;
|
||||
}
|
||||
sim_stop_unit.action = &sim_timer_stop_svc;
|
||||
@ -1189,6 +1204,13 @@ else
|
||||
#if defined(SIM_ASYNCH_CLOCKS)
|
||||
fprintf (st, "Asynchronous Clocks: %s\n", sim_asynch_timer ? "Active" : "Available");
|
||||
#endif
|
||||
if (sim_time_at_sim_prompt != 0.0) {
|
||||
double prompt_time = 0.0;
|
||||
if (!sim_is_running)
|
||||
prompt_time = ((double)(sim_os_msec () - sim_stop_time)) / 1000.0;
|
||||
fprintf (st, "Time at sim> prompt: %s\n", sim_fmt_secs (sim_time_at_sim_prompt + prompt_time));
|
||||
}
|
||||
|
||||
fprintf (st, "\n");
|
||||
for (tmr=clocks=0; tmr<=SIM_NTIMERS; ++tmr) {
|
||||
RTC *rtc = &rtcs[tmr];
|
||||
@ -1265,7 +1287,7 @@ for (tmr=clocks=0; tmr<=SIM_NTIMERS; ++tmr) {
|
||||
clock_gettime (CLOCK_REALTIME, &now);
|
||||
time_t_now = (time_t)now.tv_sec;
|
||||
fprintf (st, " Wall Clock Time Now: %8.8s.%03d\n", 11+ctime(&time_t_now), (int)(now.tv_nsec/1000000));
|
||||
if (rtc->clock_catchup_eligible) {
|
||||
if (sim_catchup_ticks && rtc->clock_catchup_eligible) {
|
||||
_double_to_timespec (&now, rtc->clock_catchup_base_time+rtc->calib_tick_time);
|
||||
time_t_now = (time_t)now.tv_sec;
|
||||
fprintf (st, " Catchup Tick Time: %8.8s.%03d\n", 11+ctime(&time_t_now), (int)(now.tv_nsec/1000000));
|
||||
@ -1595,12 +1617,16 @@ RTC *rtc = &rtcs[tmr];
|
||||
if (rtc->hz == 0) /* specified timer is not running? */
|
||||
tmr = sim_calb_tmr; /* use calibrated timer instead */
|
||||
rtc = &rtcs[tmr];
|
||||
if (rtc->clock_catchup_pending) { /* Catchup clock tick pending? */
|
||||
if (rtc->clock_catchup_pending) { /* Catchup clock tick pending due to ack? */
|
||||
sim_debug (DBG_TIK, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d) - accelerating pending catch-up tick before idling %s\n", tmr, sin_cyc, sim_uname (rtc->clock_unit));
|
||||
sim_activate_abs (&sim_timer_units[tmr], 0);
|
||||
sim_interval -= sin_cyc;
|
||||
return FALSE;
|
||||
}
|
||||
if (_rtcn_tick_catchup_check (rtc, -1)) { /* Check for slow clock tick? */
|
||||
sim_interval -= sin_cyc;
|
||||
return FALSE;
|
||||
}
|
||||
if ((!sim_idle_enab) || /* idling disabled */
|
||||
((sim_clock_queue == QUEUE_LIST_END) && /* or clock queue empty? */
|
||||
(!sim_asynch_timer))|| /* and not asynch? */
|
||||
@ -1614,14 +1640,9 @@ if ((!sim_idle_enab) || /* idling disabled */
|
||||
sim_interval -= sin_cyc;
|
||||
return FALSE;
|
||||
}
|
||||
if (_rtcn_tick_catchup_check (tmr, -1)) {
|
||||
sim_debug (DBG_TIK, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d) - rescheduling catchup tick %d for %s\n", tmr, sin_cyc, 1 + rtc->ticks, sim_uname (rtc->clock_unit));
|
||||
sim_interval -= sin_cyc;
|
||||
return FALSE;
|
||||
}
|
||||
/*
|
||||
When a simulator is in an instruction path (or under other conditions
|
||||
which would indicate idling), the countdown of sim_interval will not
|
||||
which would indicate idling), the countdown of sim_interval may not
|
||||
be happening at a pace which is consistent with the rate it happens
|
||||
when not in the 'idle capable' state. The consequence of this is that
|
||||
the clock calibration may produce calibrated results which vary much
|
||||
@ -1646,7 +1667,7 @@ sim_debug (DBG_TRC, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d)\n", tmr, sin_c
|
||||
if (sim_idle_cyc_ms == 0) {
|
||||
sim_idle_cyc_ms = (rtc->currd * rtc->hz) / 1000;/* cycles per msec */
|
||||
if (sim_idle_rate_ms != 0)
|
||||
sim_idle_cyc_sleep = (rtc->currd * rtc->hz) / (1000 / sim_idle_rate_ms);/* cycles per sleep */
|
||||
sim_idle_cyc_sleep = (rtc->currd * rtc->hz) / (1000 / sim_idle_rate_ms);/* cycles per minimum sleep */
|
||||
}
|
||||
if ((sim_idle_rate_ms == 0) || (sim_idle_cyc_ms == 0)) {/* not possible? */
|
||||
sim_interval -= sin_cyc;
|
||||
@ -1660,19 +1681,18 @@ w_ms = (uint32) sim_interval / sim_idle_cyc_ms; /* ms to wait */
|
||||
/* the simulator acknowledges the processing of clock ticks, then catchup */
|
||||
/* ticks can be used to make up for missed ticks. */
|
||||
if (rtc->clock_catchup_eligible)
|
||||
w_idle = (sim_interval * 1000) / rtc->currd; /* 1000 * pending fraction of tick */
|
||||
w_idle = (sim_interval * 1000) / rtc->currd; /* 1000 * pending fraction of tick */
|
||||
else
|
||||
w_idle = (w_ms * 1000) / sim_idle_rate_ms; /* 1000 * intervals to wait */
|
||||
if (w_idle < 500) { /* shorter than 1/2 the interval? */
|
||||
sim_interval -= sin_cyc;
|
||||
if ((w_idle < 500) || (w_ms == 0)) { /* shorter than 1/2 the interval or */
|
||||
sim_interval -= sin_cyc; /* minimal sleep time? */
|
||||
if (!in_nowait)
|
||||
sim_debug (DBG_IDL, &sim_timer_dev, "no wait, too short: %d usecs\n", w_idle);
|
||||
in_nowait = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
if (w_ms > 1000) { /* too long a wait */
|
||||
if (w_ms > 1000) /* too long a wait (runaway calibration) */
|
||||
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);
|
||||
@ -1991,6 +2011,7 @@ switch (sim_throt_state) {
|
||||
/* Run through all timers and adjust the calibration for each */
|
||||
/* one that is running to reflect the throttle rate */
|
||||
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||
rtc = &rtcs[tmr];
|
||||
if (rtc->hz) { /* running? */
|
||||
rtc->currd = (int32)(sim_throt_cps / rtc->hz);/* use throttle calibration */
|
||||
rtc->ticks = rtc->hz - 1; /* force clock calibration on next tick */
|
||||
@ -2185,21 +2206,40 @@ clock_gettime (CLOCK_REALTIME, now);
|
||||
/* _rtcn_tick_catchup_check - idle simulator until next event or for specified interval
|
||||
|
||||
Inputs:
|
||||
tmr = calibrated timer to check/schedule
|
||||
RTC = calibrated timer to check/schedule
|
||||
time = instruction delay for next tick
|
||||
|
||||
Returns TRUE if a catchup tick has been scheduled
|
||||
*/
|
||||
|
||||
static t_bool _rtcn_tick_catchup_check (int32 tmr, int32 time)
|
||||
static t_bool _rtcn_tick_catchup_check (RTC *rtc, int32 time)
|
||||
{
|
||||
RTC *rtc;
|
||||
int32 tmr;
|
||||
t_bool bReturn = FALSE;
|
||||
|
||||
if ((!sim_catchup_ticks) ||
|
||||
((tmr < 0) || (tmr >= SIM_NTIMERS)))
|
||||
if (!sim_catchup_ticks)
|
||||
return FALSE;
|
||||
rtc = &rtcs[tmr];
|
||||
if ((!rtc->clock_catchup_eligible) && /* not eligible yet? */
|
||||
if (time == -1) {
|
||||
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||
rtc = &rtcs[tmr];
|
||||
if ((rtc->hz > 0) && rtc->clock_catchup_eligible)
|
||||
{
|
||||
double tnow = sim_timenow_double();
|
||||
|
||||
if (tnow > (rtc->clock_catchup_base_time + (rtc->calib_tick_time + rtc->clock_tick_size))) {
|
||||
if (!rtc->clock_catchup_pending) {
|
||||
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, sim_uname (rtc->clock_unit), sim_fmt_secs (tnow - (rtc->clock_catchup_base_time + (rtc->calib_tick_time + rtc->clock_tick_size))));
|
||||
rtc->clock_catchup_pending = TRUE;
|
||||
sim_activate_abs (rtc->timer_unit, 0);
|
||||
bReturn = TRUE;
|
||||
}
|
||||
else
|
||||
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, sim_uname (rtc->clock_unit), sim_fmt_secs (tnow - (rtc->clock_catchup_base_time + (rtc->calib_tick_time + rtc->clock_tick_size))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((!rtc->clock_catchup_eligible) && /* not eligible yet? */
|
||||
(time != -1)) { /* called from ack? */
|
||||
rtc->clock_catchup_base_time = sim_timenow_double();
|
||||
rtc->clock_ticks_tot += rtc->clock_ticks;
|
||||
@ -2212,7 +2252,7 @@ if ((!rtc->clock_catchup_eligible) && /* not eligible yet? */
|
||||
rtc->calib_ticks_acked = 0;
|
||||
rtc->clock_catchup_eligible = TRUE;
|
||||
sim_debug (DBG_QUE, &sim_timer_dev, "_rtcn_tick_catchup_check() - Enabling catchup ticks for %s\n", sim_uname (rtc->clock_unit));
|
||||
return TRUE;
|
||||
bReturn = TRUE;
|
||||
}
|
||||
if ((rtc->hz > 0) &&
|
||||
rtc->clock_catchup_eligible)
|
||||
@ -2223,25 +2263,25 @@ if ((rtc->hz > 0) &&
|
||||
if (!rtc->clock_catchup_pending) {
|
||||
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, sim_uname (rtc->clock_unit), sim_fmt_secs (tnow - (rtc->clock_catchup_base_time + (rtc->calib_tick_time + rtc->clock_tick_size))));
|
||||
rtc->clock_catchup_pending = TRUE;
|
||||
sim_activate_abs (&sim_timer_units[tmr], (time < 0) ? 0 : time);
|
||||
sim_activate_abs (rtc->timer_unit, (time < 0) ? 0 : time);
|
||||
}
|
||||
else
|
||||
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, sim_uname (rtc->clock_unit), sim_fmt_secs (tnow - (rtc->clock_catchup_base_time + (rtc->calib_tick_time + rtc->clock_tick_size))));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
t_stat sim_rtcn_tick_ack (uint32 time, int32 tmr)
|
||||
{
|
||||
RTC *rtc;
|
||||
|
||||
if ((tmr < 0) || (tmr >= SIM_NTIMERS))
|
||||
if ((tmr < 0) || (tmr > SIM_NTIMERS))
|
||||
return SCPE_TIMER;
|
||||
rtc = &rtcs[tmr];
|
||||
sim_debug (DBG_ACK, &sim_timer_dev, "sim_rtcn_tick_ack - for %s\n", sim_uname (rtc->clock_unit));
|
||||
_rtcn_tick_catchup_check (tmr, (int32)time);
|
||||
_rtcn_tick_catchup_check (rtc, (int32)time);
|
||||
++rtc->calib_ticks_acked;
|
||||
return SCPE_OK;
|
||||
}
|
||||
@ -2423,29 +2463,30 @@ for (tmr=0; tmr<SIM_NTIMERS; tmr++) {
|
||||
}
|
||||
if (tmr == SIM_NTIMERS) { /* None found? */
|
||||
if ((tmr != newtmr) && (!sim_is_active (&SIM_INTERNAL_UNIT))) {
|
||||
crtc = &rtcs[sim_calb_tmr];
|
||||
if ((sim_calb_tmr != SIM_NTIMERS) &&/* not internal timer? */
|
||||
(sim_calb_tmr != -1) && /* previously active? */
|
||||
(!crtc->hz)) { /* now stopped? */
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "_rtcn_configure_calibrated_clock(newtmr=%d) - Cleaning up stopped timer %s support\n", newtmr, sim_uname(crtc->clock_unit));
|
||||
/* Migrate any coscheduled devices to the standard queue */
|
||||
/* with appropriate usecs_remaining reflecting their currently */
|
||||
/* scheduled firing time. sim_process_event() will coschedule */
|
||||
/* appropriately. */
|
||||
/* temporarily restore prior hz to get correct remaining time */
|
||||
crtc->hz = crtc->last_hz;
|
||||
while (crtc->clock_cosched_queue != QUEUE_LIST_END) {
|
||||
UNIT *uptr = crtc->clock_cosched_queue;
|
||||
double usecs_remaining = sim_timer_activate_time_usecs (uptr) - 1;
|
||||
(sim_calb_tmr != -1)) { /* previously active? */
|
||||
crtc = &rtcs[sim_calb_tmr];
|
||||
if (!crtc->hz) { /* now stopped? */
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "_rtcn_configure_calibrated_clock(newtmr=%d) - Cleaning up stopped timer %s support\n", newtmr, sim_uname(crtc->clock_unit));
|
||||
/* Migrate any coscheduled devices to the standard queue */
|
||||
/* with appropriate usecs_remaining reflecting their currently */
|
||||
/* scheduled firing time. sim_process_event() will coschedule */
|
||||
/* appropriately. */
|
||||
/* temporarily restore prior hz to get correct remaining time */
|
||||
crtc->hz = crtc->last_hz;
|
||||
while (crtc->clock_cosched_queue != QUEUE_LIST_END) {
|
||||
UNIT *uptr = crtc->clock_cosched_queue;
|
||||
double usecs_remaining = sim_timer_activate_time_usecs (uptr) - 1;
|
||||
|
||||
_sim_coschedule_cancel (uptr);
|
||||
_sim_activate (uptr, 1);
|
||||
uptr->usecs_remaining = usecs_remaining;
|
||||
_sim_coschedule_cancel (uptr);
|
||||
_sim_activate (uptr, 1);
|
||||
uptr->usecs_remaining = usecs_remaining;
|
||||
}
|
||||
crtc->hz = 0; /* back to 0 */
|
||||
if (crtc->clock_unit)
|
||||
sim_cancel (crtc->clock_unit);
|
||||
sim_cancel (crtc->timer_unit);
|
||||
}
|
||||
crtc->hz = 0; /* back to 0 */
|
||||
if (crtc->clock_unit)
|
||||
sim_cancel (crtc->clock_unit);
|
||||
sim_cancel (&sim_timer_units[sim_calb_tmr]);
|
||||
}
|
||||
/* Start the internal timer */
|
||||
sim_calb_tmr = SIM_NTIMERS;
|
||||
@ -2470,26 +2511,27 @@ if (sim_calb_tmr == SIM_NTIMERS) { /* was old the internal timer? */
|
||||
sim_cancel (&sim_timer_units[SIM_NTIMERS]);
|
||||
}
|
||||
else {
|
||||
rtc = &rtcs[sim_calb_tmr];
|
||||
if ((sim_calb_tmr != -1) &&
|
||||
(rtc->hz == 0)) {
|
||||
/* Migrate any coscheduled devices to the standard queue */
|
||||
/* with appropriate usecs_remaining reflecting their currently */
|
||||
/* scheduled firing time. sim_process_event() will coschedule */
|
||||
/* appropriately. */
|
||||
/* temporarily restore prior hz to get correct remaining time */
|
||||
rtc->hz = rtc->last_hz;
|
||||
while (rtc->clock_cosched_queue != QUEUE_LIST_END) {
|
||||
UNIT *uptr = rtc->clock_cosched_queue;
|
||||
double usecs_remaining = sim_timer_activate_time_usecs (uptr) - 1;
|
||||
if (sim_calb_tmr != -1) {
|
||||
crtc = &rtcs[sim_calb_tmr];
|
||||
if (crtc->hz == 0) {
|
||||
/* Migrate any coscheduled devices to the standard queue */
|
||||
/* with appropriate usecs_remaining reflecting their currently */
|
||||
/* scheduled firing time. sim_process_event() will coschedule */
|
||||
/* appropriately. */
|
||||
/* temporarily restore prior hz to get correct remaining time */
|
||||
crtc->hz = crtc->last_hz;
|
||||
while (crtc->clock_cosched_queue != QUEUE_LIST_END) {
|
||||
UNIT *uptr = crtc->clock_cosched_queue;
|
||||
double usecs_remaining = sim_timer_activate_time_usecs (uptr) - 1;
|
||||
|
||||
_sim_coschedule_cancel (uptr);
|
||||
_sim_activate (uptr, 1);
|
||||
uptr->usecs_remaining = usecs_remaining;
|
||||
_sim_coschedule_cancel (uptr);
|
||||
_sim_activate (uptr, 1);
|
||||
uptr->usecs_remaining = usecs_remaining;
|
||||
}
|
||||
crtc->hz = 0; /* back to 0 */
|
||||
}
|
||||
rtc->hz = 0; /* back to 0 */
|
||||
}
|
||||
sim_debug (DBG_CAL|DBG_INT, &sim_timer_dev, "_rtcn_configure_calibrated_clock(newtmr=%d) - Changing Calibrated Timer from %d (%dHz) to %d (%dHz)\n", newtmr, sim_calb_tmr, rtc->hz, tmr, rtc->hz);
|
||||
sim_debug (DBG_CAL|DBG_INT, &sim_timer_dev, "_rtcn_configure_calibrated_clock(newtmr=%d) - Changing Calibrated Timer from %d (%dHz) to %d (%dHz)\n", newtmr, sim_calb_tmr, crtc->hz, tmr, crtc->hz);
|
||||
sim_calb_tmr = tmr;
|
||||
}
|
||||
sim_calb_tmr = tmr;
|
||||
@ -2514,18 +2556,24 @@ void sim_start_timer_services (void)
|
||||
{
|
||||
int32 tmr;
|
||||
uint32 sim_prompt_time = sim_os_msec () - sim_stop_time;
|
||||
int32 registered_units = 0;
|
||||
|
||||
sim_time_at_sim_prompt += (((double)sim_prompt_time) / 1000.0);
|
||||
for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||
RTC *rtc = &rtcs[tmr];
|
||||
|
||||
if (rtc->hz) { /* calibrated clock running? */
|
||||
if (rtc->initd) { /* calibrated clock initialized? */
|
||||
rtc->rtime += sim_prompt_time;
|
||||
rtc->vtime += 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)
|
||||
rtc->calib_tick_time += (((double)sim_prompt_time) / 1000.0);
|
||||
if (rtc->clock_unit)
|
||||
++registered_units;
|
||||
}
|
||||
}
|
||||
if (registered_units == 1)
|
||||
sim_catchup_ticks = FALSE;
|
||||
if (sim_calb_tmr == -1) {
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_start_timer_services() - starting from scratch\n");
|
||||
_rtcn_configure_calibrated_clock (sim_calb_tmr);
|
||||
@ -2570,11 +2618,11 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||
RTC *rtc = &rtcs[tmr];
|
||||
|
||||
if (rtc->clock_unit) {
|
||||
int32 clock_time = _sim_activate_time (&sim_timer_units[tmr]);
|
||||
int32 clock_time = _sim_activate_time (rtc->timer_unit);
|
||||
|
||||
/* Stop clock assist unit and make sure the clock unit has a tick queued */
|
||||
if (sim_is_active (&sim_timer_units[tmr])) {
|
||||
sim_cancel (&sim_timer_units[tmr]);
|
||||
if (sim_is_active (rtc->timer_unit)) {
|
||||
sim_cancel (rtc->timer_unit);
|
||||
sim_debug (DBG_QUE, &sim_timer_dev, "sim_stop_timer_services() - tmr=%d scheduling %s after %d\n", tmr, sim_uname (rtc->clock_unit), clock_time);
|
||||
_sim_activate (rtc->clock_unit, clock_time);
|
||||
}
|
||||
@ -2687,7 +2735,7 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||
RTC *rtc = &rtcs[tmr];
|
||||
|
||||
if (rtc->clock_unit == uptr) {
|
||||
uptr = &sim_timer_units[tmr];
|
||||
uptr = rtc->timer_unit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2721,13 +2769,13 @@ if (uptr->usecs_remaining != 0.0) /* No calibrated timer yet, wait one cycle *
|
||||
inst_delay_d = inst_delay = 1; /* Minimum non-zero delay is 1 instruction */
|
||||
crtc = &rtcs[sim_calb_tmr];
|
||||
if ((sim_calb_tmr != -1) && (crtc->hz)) { /* Calibrated Timer available? */
|
||||
int32 inst_til_tick = sim_activate_time (&sim_timer_units[sim_calb_tmr]) - 1;
|
||||
int32 inst_til_tick = sim_activate_time (crtc->timer_unit) - 1;
|
||||
int32 ticks_til_calib = crtc->hz - crtc->ticks;
|
||||
double usecs_per_tick = floor (1000000.0 / crtc->hz);
|
||||
int32 inst_til_calib = inst_til_tick + ((ticks_til_calib - 1) * crtc->currd);
|
||||
uint32 usecs_til_calib = (uint32)ceil(inst_til_calib / inst_per_usec);
|
||||
|
||||
if ((uptr != &sim_timer_units[sim_calb_tmr]) && /* Not scheduling calibrated timer */
|
||||
if ((uptr != crtc->timer_unit) && /* Not scheduling calibrated timer */
|
||||
(inst_til_tick > 0)) { /* and tick not pending? */
|
||||
if (inst_delay_d > (double)inst_til_calib) { /* long wait? */
|
||||
stat = sim_clock_coschedule_tmr (uptr, sim_calb_tmr, ticks_til_calib - 1);
|
||||
@ -2855,15 +2903,15 @@ if (NULL == uptr) { /* deregistering? */
|
||||
rtc->clock_unit->dynflags &= ~UNIT_TMR_UNIT;
|
||||
}
|
||||
rtc->clock_unit = NULL;
|
||||
sim_cancel (&sim_timer_units[tmr]);
|
||||
sim_cancel (rtc->timer_unit);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (NULL == rtc->clock_unit)
|
||||
rtc->clock_cosched_queue = QUEUE_LIST_END;
|
||||
rtc->clock_unit = uptr;
|
||||
uptr->dynflags |= UNIT_TMR_UNIT;
|
||||
sim_timer_units[tmr].flags = ((tmr == SIM_NTIMERS) ? 0 : UNIT_DIS) |
|
||||
(rtc->clock_unit ? UNIT_IDLE : 0);
|
||||
rtc->timer_unit->flags = ((tmr == SIM_NTIMERS) ? 0 : UNIT_DIS) |
|
||||
(rtc->clock_unit ? UNIT_IDLE : 0);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -3391,4 +3439,5 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
||||
rtc->calib_initializations = 1;
|
||||
}
|
||||
sim_inst_per_sec_last = sim_precalibrate_ips;
|
||||
sim_idle_stable = 0;
|
||||
}
|
||||
|
||||
@ -112,10 +112,10 @@ int32 sim_rtcn_init_unit_ticks (UNIT *uptr, int32 time, int32 tmr, int32 tickspe
|
||||
void sim_rtcn_get_time (struct timespec *now, int tmr);
|
||||
t_stat sim_rtcn_tick_ack (uint32 time, int32 tmr);
|
||||
void sim_rtcn_init_all (void);
|
||||
int32 sim_rtcn_calb (int32 ticksper, int32 tmr);
|
||||
int32 sim_rtcn_calb (uint32 ticksper, int32 tmr);
|
||||
int32 sim_rtcn_calb_tick (int32 tmr);
|
||||
int32 sim_rtc_init (int32 time);
|
||||
int32 sim_rtc_calb (int32 ticksper);
|
||||
int32 sim_rtc_calb (uint32 ticksper);
|
||||
t_stat sim_set_timers (int32 arg, CONST char *cptr);
|
||||
t_stat sim_show_timers (FILE* st, DEVICE *dptr, UNIT* uptr, int32 val, CONST char* desc);
|
||||
t_stat sim_show_clock_queues (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user