1
0
mirror of https://github.com/simh/simh.git synced 2026-01-14 07:39:29 +00:00

All VAX: Simplify interval timers to leverage new usec timing APIs

This commit is contained in:
Mark Pizzolato 2016-12-30 10:34:29 -08:00
parent c9276407e6
commit d456bac8fc
5 changed files with 37 additions and 86 deletions

View File

@ -183,7 +183,6 @@ int32 tmr_iccs = 0; /* interval timer csr */
uint32 tmr_icr = 0; /* curr interval */
uint32 tmr_nicr = 0; /* next interval */
uint32 tmr_inc = 0; /* timer increment */
int32 tmr_sav = 0; /* timer save */
int32 tmr_int = 0; /* interrupt */
int32 clk_tps = 100; /* ticks/second */
int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */
@ -324,7 +323,6 @@ REG tmr_reg[] = {
{ FLDATAD (INT, tmr_int, 0, "interrupt request") },
{ DRDATAD (TPS, clk_tps, 8, "ticks per second (100)"), REG_NZ + PV_LEFT },
{ HRDATA (INCR, tmr_inc, 32), REG_HIDDEN },
{ HRDATA (SAVE, tmr_sav, 32), REG_HIDDEN },
{ NULL }
};
@ -709,8 +707,9 @@ int32 icr_rd (void)
int32 result;
if (tmr_iccs & TMR_CSR_RUN) { /* running? */
uint32 delta = sim_grtime() - tmr_sav;
result = (int32)(tmr_nicr + (uint32)((1000000.0 * delta) / sim_timer_inst_per_sec ()));
uint32 usecs_remaining = (uint32)sim_activate_time_usecs (&tmr_unit);
result = (int32)(~usecs_remaining + 1);
}
else
result = (int32)tmr_icr;
@ -735,7 +734,7 @@ tmr_nicr = val;
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 */
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
@ -762,8 +761,7 @@ 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 */
sim_activate_after (&tmr_unit, usecs);
}
/* 100Hz TODR reset */

View File

@ -173,7 +173,6 @@ int32 tmr_iccs = 0; /* interval timer csr */
uint32 tmr_icr = 0; /* curr interval */
uint32 tmr_nicr = 0; /* next interval */
uint32 tmr_inc = 0; /* timer increment */
int32 tmr_sav = 0; /* timer save */
int32 tmr_int = 0; /* interrupt */
int32 clk_tps = 100; /* ticks/second */
int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */
@ -317,7 +316,6 @@ REG tmr_reg[] = {
{ FLDATAD (INT, tmr_int, 0, "interrupt request") },
{ DRDATAD (TPS, clk_tps, 8, "ticks per second"), REG_NZ + PV_LEFT },
{ HRDATA (INCR, tmr_inc, 32), REG_HIDDEN },
{ HRDATA (SAVE, tmr_sav, 32), REG_HIDDEN },
{ NULL }
};
@ -705,8 +703,9 @@ int32 icr_rd (void)
int32 result;
if (tmr_iccs & TMR_CSR_RUN) { /* running? */
uint32 delta = sim_grtime() - tmr_sav;
result = (int32)(tmr_nicr + (uint32)((1000000.0 * delta) / sim_timer_inst_per_sec ()));
uint32 usecs_remaining = (uint32)sim_activate_time_usecs (&tmr_unit);
result = (int32)(~usecs_remaining + 1);
}
else
result = (int32)tmr_icr;
@ -731,7 +730,7 @@ tmr_nicr = val;
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 */
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
@ -758,8 +757,7 @@ 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 */
sim_activate_after (&tmr_unit, usecs);
}
/* 100Hz TODR reset */

View File

@ -205,7 +205,6 @@ int32 tmr_iccs = 0; /* interval timer csr */
uint32 tmr_icr = 0; /* curr interval */
uint32 tmr_nicr = 0; /* next interval */
uint32 tmr_inc = 0; /* timer increment */
uint32 tmr_sav = 0; /* timer save */
int32 tmr_int = 0; /* interrupt */
int32 clk_tps = 100; /* ticks/second */
int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */
@ -364,7 +363,6 @@ REG tmr_reg[] = {
{ FLDATAD (INT, tmr_int, 0, "interrupt request") },
{ DRDATAD (TPS, clk_tps, 8, "ticks per second"), REG_NZ + PV_LEFT },
{ HRDATA (INCR, tmr_inc, 32), REG_HIDDEN },
{ HRDATA (SAVE, tmr_sav, 32), REG_HIDDEN },
{ NULL }
};
@ -675,8 +673,9 @@ int32 icr_rd (void)
int32 result;
if (tmr_iccs & TMR_CSR_RUN) { /* running? */
uint32 delta = sim_grtime() - tmr_sav;
result = (int32)(tmr_nicr + (uint32)((1000000.0 * delta) / sim_timer_inst_per_sec ()));
uint32 usecs_remaining = (uint32)sim_timer_activate_time_usecs (&tmr_unit);
result = (int32)(~usecs_remaining + 1);
}
else
result = (int32)tmr_icr;
@ -701,7 +700,7 @@ tmr_nicr = val;
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 */
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
@ -728,8 +727,7 @@ 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 */
sim_activate_after (&tmr_unit, usecs);
}
/* 100Hz TODR reset */

View File

@ -215,7 +215,6 @@ int32 tmr_iccs = 0; /* interval timer csr */
uint32 tmr_icr = 0; /* curr interval */
uint32 tmr_nicr = 0; /* next interval */
uint32 tmr_inc = 0; /* timer increment */
int32 tmr_sav = 0; /* timer save */
int32 tmr_int = 0; /* interrupt */
int32 clk_tps = 100; /* ticks/second */
int32 tmxr_poll = CLK_DELAY * TMXR_MULT; /* term mux poll */
@ -389,7 +388,6 @@ REG tmr_reg[] = {
{ FLDATAD (INT, tmr_int, 0, "interrupt request") },
{ DRDATAD (TPS, clk_tps, 8, "ticks per second"), REG_NZ + PV_LEFT },
{ HRDATA (INCR, tmr_inc, 32), REG_HIDDEN },
{ HRDATA (SAVE, tmr_sav, 32), REG_HIDDEN },
{ NULL }
};
@ -810,8 +808,9 @@ int32 icr_rd (void)
int32 result;
if (tmr_iccs & TMR_CSR_RUN) { /* running? */
uint32 delta = sim_grtime() - tmr_sav;
result = (int32)(tmr_nicr + (uint32)((1000000.0 * delta) / sim_timer_inst_per_sec ()));
uint32 usecs_remaining = (uint32)sim_activate_time_usecs (&tmr_unit);
result = (int32)(~usecs_remaining + 1);
}
else
result = (int32)tmr_icr;
@ -836,7 +835,7 @@ tmr_nicr = val;
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 */
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
@ -863,8 +862,7 @@ 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 */
sim_activate_after (&tmr_unit, usecs);
}
/* 100Hz TODR reset */

View File

@ -248,7 +248,6 @@ int32 tmr_csr[2] = { 0 }; /* SSC timers */
uint32 tmr_tir[2] = { 0 }; /* curr interval */
uint32 tmr_tnir[2] = { 0 }; /* next interval */
int32 tmr_tivr[2] = { 0 }; /* vector */
uint32 tmr_sav[2] = { 0 }; /* saved inst cnt */
int32 ssc_adsm[2] = { 0 }; /* addr strobes */
int32 ssc_adsk[2] = { 0 };
int32 cdg_dat[CDASIZE >> 2]; /* cache data */
@ -293,7 +292,7 @@ int32 cdg_rd (int32 pa);
void cdg_wr (int32 pa, int32 val, int32 lnt);
int32 ssc_rd (int32 pa);
void ssc_wr (int32 pa, int32 val, int32 lnt);
int32 tmr_tir_rd (int32 tmr, t_bool interp);
int32 tmr_tir_rd (int32 tmr);
void tmr_csr_wr (int32 tmr, int32 val);
void tmr_sched (int32 tmr);
void tmr_incr (int32 tmr, uint32 inc);
@ -481,12 +480,10 @@ REG sysd_reg[] = {
{ HRDATAD (TIR0, tmr_tir[0], 32, "SSC timer 0 interval register") },
{ HRDATAD (TNIR0, tmr_tnir[0], 32, "SSC timer 0 next interval register") },
{ HRDATAD (TIVEC0, tmr_tivr[0], 9, "SSC timer 0 interrupt vector register") },
{ HRDATAD (TSAV0, tmr_sav[0], 32, "SSC timer 0 saved inst cnt") },
{ HRDATAD (TCSR1, tmr_csr[1], 32, "SSC timer 1 control/status register") },
{ HRDATAD (TIR1, tmr_tir[1], 32, "SSC timer 1 interval register") },
{ HRDATAD (TNIR1, tmr_tnir[1], 32, "SSC timer 1 next interval register") },
{ HRDATAD (TIVEC1, tmr_tivr[1], 9, "SSC timer 1 interrupt vector register") },
{ HRDATAD (TSAV1, tmr_sav[1], 32, "SSC timer 1 saved inst cnt") },
{ HRDATAD (ADSM0, ssc_adsm[0], 32, "SSC address match 0 address") },
{ HRDATAD (ADSK0, ssc_adsk[0], 32, "SSC address match 0 mask") },
{ HRDATAD (ADSM1, ssc_adsm[1], 32, "SSC address match 1 address") },
@ -1356,7 +1353,7 @@ switch (rg) {
return tmr_csr[0];
case 0x41: /* T0INT */
return tmr_tir_rd (0, FALSE);
return tmr_tir_rd (0);
case 0x42: /* T0NI */
sim_debug (DBG_REGR, &sysd_dev, "tmr_tnir_rd(tmr=%d) - 0x%X\n", 0, tmr_tnir[0]);
@ -1372,7 +1369,7 @@ switch (rg) {
return tmr_csr[1];
case 0x45: /* T1INT */
return tmr_tir_rd (1, FALSE);
return tmr_tir_rd (1);
case 0x46: /* T1NI */
sim_debug (DBG_REGR, &sysd_dev, "tmr_tnir_rd(tmr=%d) - 0x%X\n", 1, tmr_tnir[1]);
@ -1479,8 +1476,8 @@ switch (rg) {
break;
case 0x46: /* T1NI */
sim_debug (DBG_REGW, &sysd_dev, "tmr_tnir_wr(tmr=%d) - 0x%X\n", 1, tmr_tnir[1]);
tmr_tnir[1] = val;
sim_debug (DBG_REGW, &sysd_dev, "tmr_tnir_wr(tmr=%d) - 0x%X\n", 1, tmr_tnir[1]);
break;
case 0x47: /* T1VEC */
@ -1510,22 +1507,7 @@ switch (rg) {
The SSC timers, which increment at 1Mhz, cannot be simulated
with ticks due to the overhead that would be required for 1M
clock events per second. Instead, a gross hack is used. When
a timer is started, the clock interval is inspected.
if (smaller than when the next clock tick will occur) then
explicitly delay the interval number of usecs which is
determined from the instruction execution rate of the
calibrated clock.
if (interval will occur after the next clock tick) then, schedule
events to coinside with the clock tick consume the interval
at the clock tick rate, and when the remaining time value
gets small enough, behave like the small case above.
If the interval register is read, then its value between events
is interpolated using the current instruction count versus the
count when the most recent event started, the result is scaled
to the calibrated system clock.
clock events per second.
The powerup TOY Test sometimes fails its tolerance test. This was
due to varying system load causing varying calibration values to be
@ -1538,17 +1520,17 @@ switch (rg) {
calibration factor.
*/
int32 tmr_tir_rd (int32 tmr, t_bool interp)
int32 tmr_tir_rd (int32 tmr)
{
uint32 delta_usecs;
if (tmr_csr[tmr] & TMR_CSR_RUN) { /* running? then interpolate */
uint32 usecs_remaining = (uint32)sim_activate_time_usecs (&sysd_dev.units[tmr]);
uint32 cur_tir = ~usecs_remaining + 1;
if (interp || (tmr_csr[tmr] & TMR_CSR_RUN)) { /* interp, running? */
delta_usecs = (uint32)(((sim_grtime () - tmr_sav[tmr]) * 1000000.0) / sim_timer_inst_per_sec ());
sim_debug (DBG_REGR, &sysd_dev, "tmr_tir_rd(tmr=%d) - 0x%X, %s\n", tmr, tmr_tir[tmr] + delta_usecs, interp ? "Interpolated" : ((tmr_csr[tmr] & TMR_CSR_RUN) ? " while running" : ""));
return tmr_tir[tmr] + delta_usecs;
sim_debug (DBG_REGR, &sysd_dev, "tmr_tir_rd(tmr=%d) - 0x%X, Interpolated while running\n", tmr, cur_tir);
return cur_tir;
}
sim_debug (DBG_REGR, &sysd_dev, "tmr_tir_rd(tmr=%d) - 0x%X, %s\n", tmr, tmr_tir[tmr], interp ? "Interpolated" : "");
sim_debug (DBG_REGR, &sysd_dev, "tmr_tir_rd(tmr=%d) - 0x%X\n", tmr, tmr_tir[tmr]);
return tmr_tir[tmr];
}
@ -1567,7 +1549,7 @@ sim_debug_bits_hdr (DBG_REGW, &sysd_dev, " ", tmr_csr_bits, val, val, 1);
if ((val & TMR_CSR_RUN) == 0) { /* clearing run? */
sim_cancel (&sysd_unit[tmr]); /* cancel timer */
if (tmr_csr[tmr] & TMR_CSR_RUN) /* run 1 -> 0? */
tmr_tir[tmr] = tmr_tir_rd (tmr, TRUE); /* update itr */
tmr_tir[tmr] = tmr_tir_rd (tmr); /* update itr */
}
tmr_csr[tmr] = tmr_csr[tmr] & ~(val & TMR_CSR_W1C); /* W1C csr */
tmr_csr[tmr] = (tmr_csr[tmr] & ~TMR_CSR_RW) | /* new r/w */
@ -1602,9 +1584,8 @@ if ((tmr_csr[tmr] & (TMR_CSR_DON | TMR_CSR_IE)) != /* update int */
t_stat tmr_svc (UNIT *uptr)
{
int32 tmr = uptr - sysd_dev.units; /* get timer # */
uint32 delta_usecs;
uint32 delta_usecs = ~tmr_tir[tmr] + 1;
delta_usecs = (uint32)(((sim_grtime () - tmr_sav[tmr]) * 1000000.0) / sim_timer_inst_per_sec ());
tmr_incr (tmr, delta_usecs); /* incr timer */
return SCPE_OK;
}
@ -1646,30 +1627,9 @@ else {
void tmr_sched (int32 tmr)
{
int32 clk_time = sim_activate_time (&clk_unit) - 1;
int32 tmr_time;
double tmr_time_d;
tmr_sav[tmr] = sim_grtime (); /* save intvl base */
tmr_time_d = ((~tmr_tir[tmr] + 1) * sim_timer_inst_per_sec ()) / 1000000.0;
if ((tmr_time_d == 0.0) || (tmr_time_d > (double)0x7FFFFFFF))
tmr_time = 0x7FFFFFFF;
else
tmr_time = (int32)ceil(tmr_time_d);
sim_debug (DBG_SCHD, &sysd_dev, "tmr_sched(tmr=%d) - tmr_sav=%u, clk_time=%d, tmr_time=%d, tmr_poll=%d\n", tmr, tmr_sav[tmr], clk_time, tmr_time, tmr_poll);
if (tmr_time > clk_time) {
/* Align scheduled event to be identical to the event for the next clock
tick. This lets us always see a consistent calibrated value, both for
this scheduling, AND for any query of the current timer register that
may happen in tmr_tir_rd (). This presumes that sim_activate will
queue the interval timer behind the event for the clock tick. */
tmr_time = clk_time;
sim_clock_coschedule_tmr (&sysd_unit[tmr], TMR_CLK, 1);
}
else
sim_activate (&sysd_unit[tmr], tmr_time);
uint32 usecs_sched = tmr_tir[tmr] ? (~tmr_tir[tmr] + 1) : 0xFFFFFFFF;
sim_debug (DBG_SCHD, &sysd_dev, "tmr_sched(tmr=%d) - after %u usecs\n", tmr, usecs_sched);
sim_activate_after (&sysd_unit[tmr], usecs_sched);
}
int32 tmr0_inta (void)
@ -1800,7 +1760,6 @@ int32 i;
if (sim_switches & SWMASK ('P')) sysd_powerup (); /* powerup? */
for (i = 0; i < 2; i++) {
tmr_csr[i] = tmr_tnir[i] = tmr_tir[i] = 0;
tmr_sav[i] = 0;
sim_cancel (&sysd_unit[i]);
}
csi_csr = 0;