1
0
mirror of https://github.com/simh/simh.git synced 2026-05-03 22:48:35 +00:00

TIMER: Add support for catchup clock ticks and cleaned up asynchronous clocks

Asynchronous clocks are now built for all simulators which are built with
SIM_ASYNCH_IO defined.  The default behavior has asynchronous clocks
disabled since this is still experimental, but it can be enabled with
SET TIMER ASYNC.

Catchup clock ticks are now available, but since they're experimental,
they aren't enabled by default.  Catchup ticks are only available if the
simulators clock device calls sim_rtcn_tick_ack to acknowledge processing
of clock ticks.  The VAX simulators have been modified to leverage this.
Catchup clock ticks can be enabled with SET TIMER CATCHUP

Additionally, an idle threshold is provided which can be used to
influence when clock calibration may be suppressed.  The default is not
to suppress calibration activities.

The various timer behaviors are visible with the SHOW TIMER command.

The state of the operating timer facilities is visible with: SHOW CLOCK

Timer events which are queued are visible with the SHOW QUEUE command.
This commit is contained in:
Mark Pizzolato
2016-11-16 23:50:53 -08:00
parent 32bf2629b1
commit 39d2944ede
19 changed files with 1049 additions and 679 deletions

View File

@@ -248,6 +248,8 @@ void iccs_wr (int32 data)
{
if ((data & CSR_IE) == 0)
CLR_INT (CLK);
if (data & CSR_DONE) /* Interrupt Acked? */
sim_rtcn_tick_ack (20, TMR_CLK); /* Let timers know */
clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW);
return;
}

View File

@@ -226,6 +226,8 @@ void iccs_wr (int32 data)
{
if ((data & CSR_IE) == 0)
CLR_INT (CLK);
if (data & CSR_DONE) /* Interrupt Acked? */
sim_rtcn_tick_ack (20, TMR_CLK); /* Let timers know */
clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW);
return;
}

View File

@@ -644,6 +644,8 @@ if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */
if (tmr_iccs & TMR_CSR_RUN) /* run 1 -> 0? */
tmr_icr = icr_rd (TRUE); /* update itr */
}
if (val & CSR_DONE) /* Interrupt Acked? */
sim_rtcn_tick_ack (20, TMR_CLK); /* Let timers know */
tmr_iccs = tmr_iccs & ~(val & TMR_CSR_W1C); /* W1C csr */
tmr_iccs = (tmr_iccs & ~TMR_CSR_WR) | /* new r/w */
(val & TMR_CSR_WR);
@@ -859,7 +861,7 @@ int32 todr_rd (void)
TOY *toy = (TOY *)clk_unit.filebuf;
struct timespec base, now, val;
clock_gettime(CLOCK_REALTIME, &now); /* get curr time */
sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */
base.tv_sec = toy->toy_gmtbase;
base.tv_nsec = toy->toy_gmtbasemsec * 1000000;
sim_timespec_diff (&val, &now, &base);
@@ -874,8 +876,7 @@ struct timespec now, val, base;
/* Save the GMT time when set value was 0 to record the base for future
read operations in "battery backed-up" state */
if (-1 == clock_gettime(CLOCK_REALTIME, &now)) /* get curr time */
return; /* error? */
sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */
val.tv_sec = ((uint32)data) / 100;
val.tv_nsec = (((uint32)data) % 100) * 10000000;
sim_timespec_diff (&base, &now, &val); /* base = now - data */

View File

@@ -666,6 +666,8 @@ if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */
if (tmr_iccs & TMR_CSR_RUN) /* run 1 -> 0? */
tmr_icr = icr_rd (TRUE); /* update itr */
}
if (val & CSR_DONE) /* Interrupt Acked? */
sim_rtcn_tick_ack (20, TMR_CLK); /* Let timers know */
tmr_iccs = tmr_iccs & ~(val & TMR_CSR_W1C); /* W1C csr */
tmr_iccs = (tmr_iccs & ~TMR_CSR_WR) | /* new r/w */
(val & TMR_CSR_WR);
@@ -895,7 +897,7 @@ int32 todr_rd (void)
TOY *toy = (TOY *)clk_unit.filebuf;
struct timespec base, now, val;
clock_gettime(CLOCK_REALTIME, &now); /* get curr time */
sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */
base.tv_sec = toy->toy_gmtbase;
base.tv_nsec = toy->toy_gmtbasemsec * 1000000;
sim_timespec_diff (&val, &now, &base);
@@ -911,8 +913,7 @@ struct timespec now, val, base;
/* Save the GMT time when set value was 0 to record the base for future
read operations in "battery backed-up" state */
if (-1 == clock_gettime(CLOCK_REALTIME, &now)) /* get curr time */
return; /* error? */
sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */
val.tv_sec = ((uint32)data) / 100;
val.tv_nsec = (((uint32)data) % 100) * 10000000;
sim_timespec_diff (&base, &now, &val); /* base = now - data */

View File

@@ -623,6 +623,8 @@ if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */
if (tmr_iccs & TMR_CSR_RUN) /* run 1 -> 0? */
tmr_icr = icr_rd (); /* update itr */
}
if (val & CSR_DONE) /* Interrupt Acked? */
sim_rtcn_tick_ack (20, TMR_CLK); /* Let timers know */
tmr_iccs = tmr_iccs & ~(val & TMR_CSR_W1C); /* W1C csr */
tmr_iccs = (tmr_iccs & ~TMR_CSR_WR) | /* new r/w */
(val & TMR_CSR_WR);
@@ -835,7 +837,7 @@ int32 todr_rd (void)
TOY *toy = (TOY *)clk_unit.filebuf;
struct timespec base, now, val;
clock_gettime(CLOCK_REALTIME, &now); /* get curr time */
sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */
base.tv_sec = toy->toy_gmtbase;
base.tv_nsec = toy->toy_gmtbasemsec * 1000000;
sim_timespec_diff (&val, &now, &base);
@@ -851,8 +853,7 @@ struct timespec now, val, base;
/* Save the GMT time when set value was 0 to record the base for future
read operations in "battery backed-up" state */
if (-1 == clock_gettime(CLOCK_REALTIME, &now)) /* get curr time */
return; /* error? */
sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */
val.tv_sec = ((uint32)data) / 100;
val.tv_nsec = (((uint32)data) % 100) * 10000000;
sim_timespec_diff (&base, &now, &val); /* base = now - data */

View File

@@ -747,6 +747,8 @@ if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */
if (tmr_iccs & TMR_CSR_RUN) /* run 1 -> 0? */
tmr_icr = icr_rd (TRUE); /* update itr */
}
if (val & CSR_DONE) /* Interrupt Acked? */
sim_rtcn_tick_ack (20, TMR_CLK); /* Let timers know */
tmr_iccs = tmr_iccs & ~(val & TMR_CSR_W1C); /* W1C csr */
tmr_iccs = (tmr_iccs & ~TMR_CSR_WR) | /* new r/w */
(val & TMR_CSR_WR);
@@ -962,7 +964,7 @@ int32 todr_rd (void)
TOY *toy = (TOY *)clk_unit.filebuf;
struct timespec base, now, val;
clock_gettime(CLOCK_REALTIME, &now); /* get curr time */
sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */
base.tv_sec = toy->toy_gmtbase;
base.tv_nsec = toy->toy_gmtbasemsec * 1000000;
sim_timespec_diff (&val, &now, &base);
@@ -977,8 +979,7 @@ struct timespec now, val, base;
/* Save the GMT time when set value was 0 to record the base for future
read operations in "battery backed-up" state */
if (-1 == clock_gettime(CLOCK_REALTIME, &now)) /* get curr time */
return; /* error? */
sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */
val.tv_sec = ((uint32)data) / 100;
val.tv_nsec = (((uint32)data) % 100) * 10000000;
sim_timespec_diff (&base, &now, &val); /* base = now - data */

View File

@@ -428,12 +428,12 @@ MTAB cpu_mod[] = {
};
DEBTAB cpu_deb[] = {
{ "INTEXC", LOG_CPU_I },
{ "REI", LOG_CPU_R },
{ "CONTEXT", LOG_CPU_P },
{ "EVENT", SIM_DBG_EVENT },
{ "ACTIVATE", SIM_DBG_ACTIVATE },
{ "ASYNCH", SIM_DBG_AIO_QUEUE },
{ "INTEXC", LOG_CPU_I, "interrupt and exception activities" },
{ "REI", LOG_CPU_R, "REI activities" },
{ "CONTEXT", LOG_CPU_P, "context switching activities" },
{ "EVENT", SIM_DBG_EVENT, "event dispatch activities" },
{ "ACTIVATE", SIM_DBG_ACTIVATE, "queue insertion activities" },
{ "ASYNCH", SIM_DBG_AIO_QUEUE, "asynch queue activities" },
{ NULL, 0 }
};

View File

@@ -299,6 +299,8 @@ void iccs_wr (int32 data)
{
if ((data & CSR_IE) == 0)
CLR_INT (CLK);
if (data & CSR_DONE) /* Interrupt Acked? */
sim_rtcn_tick_ack (20, TMR_CLK); /* Let timers know */
clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW);
return;
}
@@ -484,7 +486,7 @@ if (0 == todr_reg) { /* clock running? */
in the 32bit TODR. This is the 33bit value 0x100000000/100 to get seconds */
#define TOY_MAX_SECS (0x40000000/25)
clock_gettime(CLOCK_REALTIME, &now); /* get curr time */
sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */
base.tv_sec = toy->toy_gmtbase;
base.tv_nsec = toy->toy_gmtbasemsec * 1000000;
sim_timespec_diff (&val, &now, &base);
@@ -507,8 +509,7 @@ struct timespec now, val, base;
/* Save the GMT time when set value was 0 to record the base for future
read operations in "battery backed-up" state */
if (-1 == clock_gettime(CLOCK_REALTIME, &now)) /* get curr time */
return; /* error? */
sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */
val.tv_sec = ((uint32)data) / 100;
val.tv_nsec = (((uint32)data) % 100) * 10000000;
sim_timespec_diff (&base, &now, &val); /* base = now - data */

View File

@@ -162,11 +162,13 @@ int32 wtc_rd (int32 pa)
int32 rg = (pa >> 1) & 0xF;
int32 val = 0;
time_t curr;
struct timespec now;
static int mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
struct tm *ctm = NULL;
if (rg < 10) { /* time reg? */
curr = time (NULL); /* get curr time */
sim_rtcn_get_time (&now, TMR_CLK);
curr = now.tv_sec; /* get curr time */
if (curr == (time_t) -1) /* error? */
return 0;
ctm = localtime (&curr); /* decompose */
@@ -296,7 +298,8 @@ return SCPE_OK;
t_stat wtc_set (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
{
if (cptr != NULL) wtc_mode = strcmp(cptr, "STD");
if (cptr != NULL)
wtc_mode = ((strcmp(cptr, "STD") != 0) ? WTC_MODE_VMS : WTC_MODE_STD);
return SCPE_OK;
}