TIMER: Add external initialization option for clock calibration

Clock calibration normally takes several seconds to zero in on somewhat
accurate values for reasonable synchronization of simulated time to wall
clock time.  Often this doesn't matter one way or another.  However,
one thing which requires somewhat accurate clock calibration is the
pacing of output to serial ports on the host system.  Pacing happens
at the configured bits per second rates as long as the simulators
instruction execution rate has been reasonably calibrated with respect
to wall clock time.  A given host system will most likely simulate
instructions at the same rate from one run to the next, so running a
simulator for a little while and then examining the execution rate with
the SHOW CLOCK command can provide knowledge about the calibrated
execution rate which can be used to start a future simulator's execution
with a very good estimate of what the ultimate calibrated rate will be.
If the SHOW CLOCK shows simulator execution at 120,000,000 instructions
per second, and the simulated system has a simulated clock that runs at
60 hz, then the pre-calibrated values can be set with these commands:

    sim> DEPOSIT INT-CLOCK TICK_SIZE_0 2000000
    sim> DEPOSIT INT-CLOCK TICK_RATE_0 60
    sim> DEPOSIT INT-CLOCK INTERNAL_TICK_SIZE 12000000

The INTERNAL_TIMER runs in the background whenever the simulator
doesn't have a calibrated timer running.  It runs at 10 Hz.
This commit is contained in:
Mark Pizzolato 2018-04-06 01:46:44 -07:00
parent 95f5a1c371
commit 2bcb60e76f

View file

@ -175,6 +175,9 @@ static double sim_throt_inst_start;
static uint32 sim_throt_sleep_time = 0; 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 10
#define CLK_INIT (SIM_INITIAL_IPS/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};
static int32 sim_cosched_interval[SIM_NTIMERS+1]; static int32 sim_cosched_interval[SIM_NTIMERS+1];
@ -1252,6 +1255,24 @@ return SCPE_OK;
REG sim_timer_reg[] = { REG sim_timer_reg[] = {
{ DRDATAD (IDLE_CYC_MS, sim_idle_cyc_ms, 32, "Cycles Per Millisecond"), PV_RSPC|REG_RO}, { DRDATAD (IDLE_CYC_MS, sim_idle_cyc_ms, 32, "Cycles Per Millisecond"), PV_RSPC|REG_RO},
{ DRDATAD (ROM_DELAY, sim_rom_delay, 32, "ROM memory reference delay"), PV_RSPC|REG_RO}, { 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") },
{ DRDATAD (TICK_SIZE_0, rtc_currd[0], 32, "Timer 0 Tick Size") },
{ DRDATAD (TICK_RATE_1, rtc_hz[1], 32, "Timer 1 Ticks Per Second") },
{ DRDATAD (TICK_SIZE_1, rtc_currd[1], 32, "Timer 1 Tick Size") },
{ DRDATAD (TICK_RATE_2, rtc_hz[2], 32, "Timer 2 Ticks Per Second") },
{ DRDATAD (TICK_SIZE_2, rtc_currd[2], 32, "Timer 2 Tick Size") },
{ DRDATAD (TICK_RATE_3, rtc_hz[3], 32, "Timer 3 Ticks Per Second") },
{ DRDATAD (TICK_SIZE_3, rtc_currd[3], 32, "Timer 3 Tick Size") },
{ DRDATAD (TICK_RATE_4, rtc_hz[4], 32, "Timer 4 Ticks Per Second") },
{ DRDATAD (TICK_SIZE_4, rtc_currd[4], 32, "Timer 4 Tick Size") },
{ DRDATAD (TICK_RATE_5, rtc_hz[5], 32, "Timer 5 Ticks Per Second") },
{ DRDATAD (TICK_SIZE_5, rtc_currd[5], 32, "Timer 5 Tick Size") },
{ DRDATAD (TICK_RATE_6, rtc_hz[6], 32, "Timer 6 Ticks Per Second") },
{ DRDATAD (TICK_SIZE_6, rtc_currd[6], 32, "Timer 6 Tick Size") },
{ DRDATAD (TICK_RATE_7, rtc_hz[7], 32, "Timer 7 Ticks Per Second") },
{ DRDATAD (TICK_SIZE_7, rtc_currd[7], 32, "Timer 7 Tick Size") },
{ DRDATAD (INTERNAL_TICK_RATE,sim_int_clk_tps, 32, "Internal Timer Ticks Per Second") },
{ DRDATAD (INTERNAL_TICK_SIZE,rtc_currd[SIM_NTIMERS],32, "Internal Timer Tick Size") },
{ NULL } { NULL }
}; };
@ -1386,6 +1407,7 @@ static const char *sim_throttle_description (DEVICE *dptr)
return "Throttle facility"; return "Throttle facility";
} }
DEVICE sim_timer_dev = { DEVICE sim_timer_dev = {
"INT-CLOCK", sim_timer_units, sim_timer_reg, sim_timer_mod, "INT-CLOCK", sim_timer_units, sim_timer_reg, sim_timer_mod,
SIM_NTIMERS+1, 0, 0, 0, 0, 0, SIM_NTIMERS+1, 0, 0, 0, 0, 0,
@ -2216,10 +2238,6 @@ return NULL;
To solve this we merely run an internal clock at 10Hz. To solve this we merely run an internal clock at 10Hz.
*/ */
#define CLK_TPS 10
#define CLK_INIT (SIM_INITIAL_IPS/CLK_TPS)
static int32 sim_int_clk_tps;
static t_stat sim_timer_clock_tick_svc (UNIT *uptr) static t_stat sim_timer_clock_tick_svc (UNIT *uptr)
{ {
sim_debug(DBG_INT, &sim_timer_dev, "sim_timer_clock_tick_svc()\n"); sim_debug(DBG_INT, &sim_timer_dev, "sim_timer_clock_tick_svc()\n");