SCP: Add more clock adjustments while idling
This commit is contained in:
parent
6a3424df86
commit
5fdc1e6d0f
2 changed files with 32 additions and 6 deletions
5
scp.c
5
scp.c
|
@ -1266,7 +1266,7 @@ static const char simh_help[] =
|
|||
" running in the simulator is doing nothing, and runs the simulator at full\n"
|
||||
" speed when there is work to do. Throttling and idling are mutually\n"
|
||||
" exclusive.\n"
|
||||
#define HLP_SET_CLOCKS "*Commands SET Clocks"
|
||||
#define HLP_SET_CLOCK "*Commands SET Clock"
|
||||
"3Clock\n"
|
||||
#if defined (SIM_ASYNCH_CLOCKS)
|
||||
"+SET CLOCK asynch enable asynchronous clocks\n"
|
||||
|
@ -1275,6 +1275,7 @@ static const char simh_help[] =
|
|||
"+SET CLOCK nocatchup disable catchup clock ticks\n"
|
||||
"+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"
|
||||
" The SET CLOCK STOP command allows execution to have a bound when\n"
|
||||
" execution starts with a BOOT, NEXT or CONTINUE command.\n"
|
||||
|
@ -2313,7 +2314,7 @@ static CTAB set_glob_tab[] = {
|
|||
{ "NODEBUG", &sim_set_deboff, 0, HLP_SET_DEBUG },
|
||||
{ "THROTTLE", &sim_set_throt, 1, HLP_SET_THROTTLE },
|
||||
{ "NOTHROTTLE", &sim_set_throt, 0, HLP_SET_THROTTLE },
|
||||
{ "CLOCKS", &sim_set_timers, 1, HLP_SET_CLOCKS },
|
||||
{ "CLOCKS", &sim_set_timers, 1, HLP_SET_CLOCK },
|
||||
{ "ASYNCH", &sim_set_asynch, 1, HLP_SET_ASYNCH },
|
||||
{ "NOASYNCH", &sim_set_asynch, 0, HLP_SET_ASYNCH },
|
||||
{ "ENVIRONMENT", &sim_set_environment, 1, HLP_SET_ENVIRON },
|
||||
|
|
31
sim_timer.c
31
sim_timer.c
|
@ -773,6 +773,8 @@ static uint32 rtc_clock_calib_skip_idle[SIM_NTIMERS+1] = { 0 };/* Calibrations s
|
|||
static uint32 rtc_clock_calib_gap2big[SIM_NTIMERS+1] = { 0 };/* Calibrations skipped Gap Too Big */
|
||||
static uint32 rtc_clock_calib_backwards[SIM_NTIMERS+1] = { 0 };/* Calibrations skipped Clock Running Backwards */
|
||||
static uint32 sim_idle_cyc_ms = 0; /* Cycles per millisecond while not idling */
|
||||
static uint32 sim_idle_cyc_sleep = 0; /* Cycles per minimum sleep interval */
|
||||
static double sim_idle_end_time = 0.0; /* Time when last idle completed */
|
||||
|
||||
UNIT sim_timer_units[SIM_NTIMERS+1]; /* Clock assist units */
|
||||
/* one for each timer and one for an internal */
|
||||
|
@ -979,8 +981,11 @@ if (last_idle_pct > (100 - sim_idle_calib_pct)) {
|
|||
return rtc_currd[tmr]; /* avoid calibrating idle checks */
|
||||
}
|
||||
new_gtime = sim_gtime();
|
||||
if ((last_idle_pct == 0) && (delta_rtime != 0))
|
||||
if ((last_idle_pct == 0) && (delta_rtime != 0)) {
|
||||
sim_idle_cyc_ms = (uint32)((new_gtime - rtc_gtime[tmr]) / delta_rtime);
|
||||
if ((sim_idle_rate_ms != 0) && (delta_rtime > 1))
|
||||
sim_idle_cyc_sleep = (uint32)((new_gtime - rtc_gtime[tmr]) / (delta_rtime / sim_idle_rate_ms));
|
||||
}
|
||||
if (sim_asynch_timer) {
|
||||
/* An asynchronous clock, merely needs to divide the number of */
|
||||
/* instructions actually executed by the clock rate. */
|
||||
|
@ -1279,6 +1284,7 @@ return SCPE_OK;
|
|||
|
||||
REG sim_timer_reg[] = {
|
||||
{ DRDATAD (IDLE_CYC_MS, sim_idle_cyc_ms, 32, "Cycles Per Millisecond"), PV_RSPC|REG_RO},
|
||||
{ DRDATAD (IDLE_CYC_SLEEP, sim_idle_cyc_sleep, 32, "Cycles Per Minimum Sleep"), PV_RSPC|REG_RO},
|
||||
{ DRDATAD (IDLE_STABLE, sim_idle_stable, 32, "IDLE stability delay"), PV_RSPC},
|
||||
{ DRDATAD (ROM_DELAY, sim_rom_delay, 32, "ROM memory reference delay"), PV_RSPC|REG_RO},
|
||||
{ DRDATAD (TICK_RATE_0, rtc_hz[0], 32, "Timer 0 Ticks Per Second") },
|
||||
|
@ -1342,12 +1348,21 @@ return SCPE_OK;
|
|||
|
||||
t_stat sim_timer_set_idle_pct (int32 flag, CONST char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
t_stat r = SCPE_OK;
|
||||
int32 newpct;
|
||||
char gbuf[CBUFSIZE];
|
||||
|
||||
if (cptr == NULL)
|
||||
return SCPE_ARG;
|
||||
cptr = get_glyph_nc (cptr, gbuf, 0); /* get argument */
|
||||
if (isdigit (gbuf[0]))
|
||||
newpct = (int32) get_uint (cptr, 10, 100, &r);
|
||||
else {
|
||||
if (MATCH_CMD (gbuf, "ALWAYS") == 0)
|
||||
newpct = 0;
|
||||
else
|
||||
r = SCPE_ARG;
|
||||
}
|
||||
if ((r != SCPE_OK) || (newpct == (int32)(sim_idle_calib_pct)))
|
||||
return r;
|
||||
if (newpct == 0)
|
||||
|
@ -1504,6 +1519,7 @@ t_bool sim_idle (uint32 tmr, int sin_cyc)
|
|||
uint32 w_ms, w_idle, act_ms;
|
||||
int32 act_cyc;
|
||||
static t_bool in_nowait = FALSE;
|
||||
double cyc_since_idle;
|
||||
|
||||
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]));
|
||||
|
@ -1553,8 +1569,11 @@ if (_rtcn_tick_catchup_check(tmr, 0)) {
|
|||
means something, while not idling when it isn't enabled.
|
||||
*/
|
||||
sim_debug (DBG_TRC, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d)\n", tmr, sin_cyc);
|
||||
if (sim_idle_cyc_ms == 0)
|
||||
if (sim_idle_cyc_ms == 0) {
|
||||
sim_idle_cyc_ms = (rtc_currd[tmr] * rtc_hz[tmr]) / 1000;/* cycles per msec */
|
||||
if (sim_idle_rate_ms != 0)
|
||||
sim_idle_cyc_sleep = (rtc_currd[tmr] * rtc_hz[tmr]) / (1000 / sim_idle_rate_ms);/* cycles per sleep */
|
||||
}
|
||||
if ((sim_idle_rate_ms == 0) || (sim_idle_cyc_ms == 0)) {/* not possible? */
|
||||
sim_interval -= sin_cyc;
|
||||
sim_debug (DBG_IDL, &sim_timer_dev, "not possible idle_rate_ms=%d - cyc/ms=%d\n", sim_idle_rate_ms, sim_idle_cyc_ms);
|
||||
|
@ -1582,10 +1601,16 @@ 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);
|
||||
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);
|
||||
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[tmr] += act_ms;
|
||||
act_cyc = act_ms * sim_idle_cyc_ms;
|
||||
if (cyc_since_idle > sim_idle_cyc_sleep)
|
||||
act_cyc -= sim_idle_cyc_sleep / 2; /* account for half an interval's worth of cycles */
|
||||
else
|
||||
act_cyc -= (int32)cyc_since_idle; /* acount for cycles executed */
|
||||
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);
|
||||
else
|
||||
|
|
Loading…
Add table
Reference in a new issue