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:
parent
9c32c97d38
commit
5cf9e9ab86
1 changed files with 22 additions and 23 deletions
|
@ -234,7 +234,6 @@ uint8 comm_region[COMM_LNT] = { 0 }; /* comm region */
|
||||||
|
|
||||||
t_stat tti_svc (UNIT *uptr);
|
t_stat tti_svc (UNIT *uptr);
|
||||||
t_stat tto_svc (UNIT *uptr);
|
t_stat tto_svc (UNIT *uptr);
|
||||||
t_stat clk_svc (UNIT *uptr);
|
|
||||||
t_stat tmr_svc (UNIT *uptr);
|
t_stat tmr_svc (UNIT *uptr);
|
||||||
t_stat tti_reset (DEVICE *dptr);
|
t_stat tti_reset (DEVICE *dptr);
|
||||||
t_stat tto_reset (DEVICE *dptr);
|
t_stat tto_reset (DEVICE *dptr);
|
||||||
|
@ -334,12 +333,12 @@ DEVICE tto_dev = {
|
||||||
|
|
||||||
/* TODR and TMR data structures */
|
/* 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[] = {
|
REG clk_reg[] = {
|
||||||
{ DRDATAD (TIME, clk_unit.wait, 24, "initial poll interval"), REG_NZ + PV_LEFT },
|
{ 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 (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)
|
#if defined (SIM_ASYNCH_IO)
|
||||||
{ DRDATAD (ASYNCH, sim_asynch_enabled, 1, "asynch I/O enabled flag"), PV_LEFT },
|
{ 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 },
|
{ 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_TICK 0x02 /* Ticks */
|
||||||
#define TMR_DB_SCHED 0x04 /* Scheduling */
|
#define TMR_DB_SCHED 0x04 /* Scheduling */
|
||||||
#define TMR_DB_INT 0x08 /* Interrupts */
|
#define TMR_DB_INT 0x08 /* Interrupts */
|
||||||
|
#define TMR_DB_TODR 0x10 /* TODR */
|
||||||
|
|
||||||
DEBTAB tmr_deb[] = {
|
DEBTAB tmr_deb[] = {
|
||||||
{ "REG", TMR_DB_REG, "Register Access"},
|
{ "REG", TMR_DB_REG, "Register Access"},
|
||||||
{ "TICK", TMR_DB_TICK, "Ticks"},
|
{ "TICK", TMR_DB_TICK, "Ticks"},
|
||||||
{ "SCHED", TMR_DB_SCHED, "Ticks"},
|
{ "SCHED", TMR_DB_SCHED, "Ticks"},
|
||||||
{ "INT", TMR_DB_INT, "Interrupts"},
|
{ "INT", TMR_DB_INT, "Interrupts"},
|
||||||
|
{ "TODR", TMR_DB_TODR, "TODR activities"},
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -503,7 +504,7 @@ t_stat tti_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 c;
|
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? */
|
if ((tti_csr & CSR_DONE) && /* input still pending and < 500ms? */
|
||||||
((sim_os_msec () - tti_buftime) < 500))
|
((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);
|
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? */
|
if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */
|
||||||
sim_cancel (&tmr_unit); /* cancel timer */
|
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 */
|
tmr_icr = icr_rd (); /* update itr */
|
||||||
|
sim_rtcn_calb (0, TMR_CLK); /* stop timer */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (val & CSR_DONE) /* Interrupt Acked? */
|
if (val & CSR_DONE) /* Interrupt Acked? */
|
||||||
sim_rtcn_tick_ack (20, TMR_CLK); /* Let timers know */
|
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_RUN) { /* run? */
|
||||||
if (val & TMR_CSR_XFR) /* new tir? */
|
if (val & TMR_CSR_XFR) /* new tir? */
|
||||||
sim_cancel (&tmr_unit); /* stop prev */
|
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 */
|
tmr_sched (tmr_icr); /* activate */
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
if (val & TMR_CSR_XFR) /* xfr set? */
|
if (val & TMR_CSR_XFR) /* xfr set? */
|
||||||
tmr_icr = tmr_nicr;
|
tmr_icr = tmr_nicr;
|
||||||
|
@ -691,22 +696,12 @@ sim_debug (TMR_DB_REG, &tmr_dev, "nicr_wr(0x%08X)\n", val);
|
||||||
tmr_nicr = 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 */
|
/* Interval timer unit service */
|
||||||
|
|
||||||
t_stat tmr_svc (UNIT *uptr)
|
t_stat tmr_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
sim_debug (TMR_DB_TICK, &tmr_dev, "tmr_svc()\n");
|
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 */
|
if (tmr_iccs & TMR_CSR_DON) /* done? set err */
|
||||||
tmr_iccs = tmr_iccs | TMR_CSR_ERR;
|
tmr_iccs = tmr_iccs | TMR_CSR_ERR;
|
||||||
else
|
else
|
||||||
|
@ -719,6 +714,7 @@ if (tmr_iccs & TMR_CSR_IE) { /* ie? set int req */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tmr_int = 0;
|
tmr_int = 0;
|
||||||
|
AIO_SET_INTERRUPT_LATENCY(tmr_poll*clk_tps); /* set interrrupt latency */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,7 +724,10 @@ void tmr_sched (uint32 nicr)
|
||||||
{
|
{
|
||||||
uint32 usecs = (nicr) ? (~nicr + 1) : 0xFFFFFFFF;
|
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))
|
if (SCPE_OK == sim_activate_after (&tmr_unit, usecs))
|
||||||
tmr_sav = sim_grtime(); /* Save interval base time */
|
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)
|
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 */
|
if (clk_unit.filebuf == NULL) { /* make sure the TODR is initialized */
|
||||||
clk_unit.filebuf = calloc(sizeof(TOY), 1);
|
clk_unit.filebuf = calloc(sizeof(TOY), 1);
|
||||||
if (clk_unit.filebuf == NULL)
|
if (clk_unit.filebuf == NULL)
|
||||||
return SCPE_MEM;
|
return SCPE_MEM;
|
||||||
todr_resync ();
|
|
||||||
}
|
}
|
||||||
|
todr_resync ();
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -845,11 +841,12 @@ return r;
|
||||||
|
|
||||||
t_stat tmr_reset (DEVICE *dptr)
|
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_iccs = 0;
|
||||||
tmr_nicr = 0;
|
tmr_nicr = 0;
|
||||||
tmr_int = 0;
|
tmr_int = 0;
|
||||||
sim_cancel (&tmr_unit); /* cancel timer */
|
sim_cancel (&tmr_unit); /* cancel timer */
|
||||||
todr_resync (); /* resync TODR */
|
|
||||||
return SCPE_OK;
|
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_sec = toy->toy_gmtbase;
|
||||||
base.tv_nsec = toy->toy_gmtbasemsec * 1000000;
|
base.tv_nsec = toy->toy_gmtbasemsec * 1000000;
|
||||||
sim_timespec_diff (&val, &now, &base);
|
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 */
|
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 */
|
sim_timespec_diff (&base, &now, &val); /* base = now - data */
|
||||||
toy->toy_gmtbase = (uint32)base.tv_sec;
|
toy->toy_gmtbase = (uint32)base.tv_sec;
|
||||||
toy->toy_gmtbasemsec = base.tv_nsec/1000000;
|
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)
|
t_stat todr_resync (void)
|
||||||
|
|
Loading…
Add table
Reference in a new issue