VAX780: Removed pseudo ticks from TODR device

Removing pseudo ticking of the TODR improves simulator behavior
when idling.  As previously implement, the timing of the TODR and TMR
ticks weren't aligned and and idle simulator would have to wake up to
service both tick activities.

The real hardware has a TODR which changes every 10ms to reflect changes
to wall clock time.  This is already completely achieved by referencing the
host system time whenever the TODR register is referenced.  No need for
to simulate pseudo ticking.

The real interval timer hardware generates ticks a the rate specifically
programmed in the interval timer device registers.  The common cases
programmed the ticks at 10 ms intervals (100Hz), but real operating systems
exist which programmed ticks at 16667 usecs (60Hz).
This commit is contained in:
Mark Pizzolato 2016-12-16 10:39:49 -08:00
parent 9c32c97d38
commit 5cf9e9ab86

View file

@ -234,7 +234,6 @@ uint8 comm_region[COMM_LNT] = { 0 }; /* comm region */
t_stat tti_svc (UNIT *uptr);
t_stat tto_svc (UNIT *uptr);
t_stat clk_svc (UNIT *uptr);
t_stat tmr_svc (UNIT *uptr);
t_stat tti_reset (DEVICE *dptr);
t_stat tto_reset (DEVICE *dptr);
@ -334,12 +333,12 @@ DEVICE tto_dev = {
/* TODR and TMR data structures */
UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE+UNIT_FIX, sizeof(TOY)), CLK_DELAY };/* 100Hz */
UNIT clk_unit = { UDATA (NULL, UNIT_FIX, sizeof(TOY))};
REG clk_reg[] = {
{ DRDATAD (TIME, clk_unit.wait, 24, "initial poll interval"), REG_NZ + PV_LEFT },
{ DRDATAD (POLL, tmr_poll, 24, "calibrated poll interval"), REG_NZ + PV_LEFT + REG_HRO },
{ DRDATAD (TPS, clk_tps, 8, "ticks per second (100)"), REG_NZ + PV_LEFT },
{ DRDATAD (TPS, clk_tps, 8, "ticks per second"), REG_NZ + PV_LEFT },
#if defined (SIM_ASYNCH_IO)
{ DRDATAD (ASYNCH, sim_asynch_enabled, 1, "asynch I/O enabled flag"), PV_LEFT },
{ DRDATAD (LATENCY, sim_asynch_latency, 32, "desired asynch interrupt latency"), PV_LEFT },
@ -373,12 +372,14 @@ REG tmr_reg[] = {
#define TMR_DB_TICK 0x02 /* Ticks */
#define TMR_DB_SCHED 0x04 /* Scheduling */
#define TMR_DB_INT 0x08 /* Interrupts */
#define TMR_DB_TODR 0x10 /* TODR */
DEBTAB tmr_deb[] = {
{ "REG", TMR_DB_REG, "Register Access"},
{ "TICK", TMR_DB_TICK, "Ticks"},
{ "SCHED", TMR_DB_SCHED, "Ticks"},
{ "INT", TMR_DB_INT, "Interrupts"},
{ "TODR", TMR_DB_TODR, "TODR activities"},
{ NULL, 0 }
};
@ -503,7 +504,7 @@ t_stat tti_svc (UNIT *uptr)
{
int32 c;
sim_clock_coschedule_tmr (uptr, TMR_CLK, TMXR_MULT); /* continue poll */
sim_clock_coschedule (uptr, tmxr_poll); /* continue poll */
if ((tti_csr & CSR_DONE) && /* input still pending and < 500ms? */
((sim_os_msec () - tti_buftime) < 500))
@ -621,8 +622,10 @@ void iccs_wr (int32 val)
sim_debug_bits_hdr (TMR_DB_REG, &tmr_dev, "iccs_wr()", tmr_iccs_bits, tmr_iccs, val, TRUE);
if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */
sim_cancel (&tmr_unit); /* cancel timer */
if (tmr_iccs & TMR_CSR_RUN) /* run 1 -> 0? */
if (tmr_iccs & TMR_CSR_RUN) { /* run 1 -> 0? */
tmr_icr = icr_rd (); /* update itr */
sim_rtcn_calb (0, TMR_CLK); /* stop timer */
}
}
if (val & CSR_DONE) /* Interrupt Acked? */
sim_rtcn_tick_ack (20, TMR_CLK); /* Let timers know */
@ -634,9 +637,11 @@ if (val & TMR_CSR_XFR) /* xfr set? */
if (val & TMR_CSR_RUN) { /* run? */
if (val & TMR_CSR_XFR) /* new tir? */
sim_cancel (&tmr_unit); /* stop prev */
if (!sim_is_active (&tmr_unit)) /* not running? */
if (!sim_is_active (&tmr_unit)) { /* not running? */
sim_rtcn_init_unit (&tmr_unit, CLK_DELAY, TMR_CLK); /* init timer */
tmr_sched (tmr_icr); /* activate */
}
}
else {
if (val & TMR_CSR_XFR) /* xfr set? */
tmr_icr = tmr_nicr;
@ -691,22 +696,12 @@ sim_debug (TMR_DB_REG, &tmr_dev, "nicr_wr(0x%08X)\n", val);
tmr_nicr = val;
}
/* 100Hz base clock unit service */
t_stat clk_svc (UNIT *uptr)
{
tmr_poll = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
sim_activate_after (uptr, 1000000/clk_tps); /* reactivate unit */
tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */
AIO_SET_INTERRUPT_LATENCY(tmr_poll*clk_tps); /* set interrrupt latency */
return SCPE_OK;
}
/* Interval timer unit service */
t_stat tmr_svc (UNIT *uptr)
{
sim_debug (TMR_DB_TICK, &tmr_dev, "tmr_svc()\n");
tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */
if (tmr_iccs & TMR_CSR_DON) /* done? set err */
tmr_iccs = tmr_iccs | TMR_CSR_ERR;
else
@ -719,6 +714,7 @@ if (tmr_iccs & TMR_CSR_IE) { /* ie? set int req */
}
else
tmr_int = 0;
AIO_SET_INTERRUPT_LATENCY(tmr_poll*clk_tps); /* set interrrupt latency */
return SCPE_OK;
}
@ -728,7 +724,10 @@ void tmr_sched (uint32 nicr)
{
uint32 usecs = (nicr) ? (~nicr + 1) : 0xFFFFFFFF;
sim_debug (TMR_DB_SCHED, &tmr_dev, "tmr_sched(0x%08X-0x%08X)\n", nicr, usecs);
clk_tps = 1000000 / usecs;
sim_debug (TMR_DB_SCHED, &tmr_dev, "tmr_sched(nicr=0x%08X-usecs=0x%08X) - tps=%d\n", nicr, usecs, clk_tps);
tmr_poll = sim_rtcn_calb (clk_tps, TMR_CLK);
if (SCPE_OK == sim_activate_after (&tmr_unit, usecs))
tmr_sav = sim_grtime(); /* Save interval base time */
}
@ -737,15 +736,12 @@ if (SCPE_OK == sim_activate_after (&tmr_unit, usecs))
t_stat clk_reset (DEVICE *dptr)
{
tmr_poll = sim_rtcn_init_unit (&clk_unit, clk_unit.wait, TMR_CLK);/* init 100Hz timer */
sim_activate_after (&clk_unit, 1000000/clk_tps); /* activate 100Hz unit */
tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */
if (clk_unit.filebuf == NULL) { /* make sure the TODR is initialized */
clk_unit.filebuf = calloc(sizeof(TOY), 1);
if (clk_unit.filebuf == NULL)
return SCPE_MEM;
todr_resync ();
}
todr_resync ();
return SCPE_OK;
}
@ -845,11 +841,12 @@ return r;
t_stat tmr_reset (DEVICE *dptr)
{
tmr_poll = sim_rtcn_init_unit (&tmr_unit, CLK_DELAY, TMR_CLK); /* init timer */
tmxr_poll = tmr_poll * TMXR_MULT; /* set mux poll */
tmr_iccs = 0;
tmr_nicr = 0;
tmr_int = 0;
sim_cancel (&tmr_unit); /* cancel timer */
todr_resync (); /* resync TODR */
return SCPE_OK;
}
@ -869,6 +866,7 @@ 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);
sim_debug (TMR_DB_TODR, &tmr_dev, "todr_rd() - TODR=0x%X\n", (int32)(val.tv_sec*100 + val.tv_nsec/10000000));
return (int32)(val.tv_sec*100 + val.tv_nsec/10000000); /* 100hz Clock Ticks */
}
@ -887,6 +885,7 @@ val.tv_nsec = (((uint32)data) % 100) * 10000000;
sim_timespec_diff (&base, &now, &val); /* base = now - data */
toy->toy_gmtbase = (uint32)base.tv_sec;
toy->toy_gmtbasemsec = base.tv_nsec/1000000;
sim_debug (TMR_DB_TODR, &tmr_dev, "todr_wr(0x%X)\n", data);
}
t_stat todr_resync (void)