From d456bac8fc90da0da4496ad750537971eac17030 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Fri, 30 Dec 2016 10:34:29 -0800 Subject: [PATCH] All VAX: Simplify interval timers to leverage new usec timing APIs --- VAX/vax730_stddev.c | 12 +++----- VAX/vax750_stddev.c | 12 +++----- VAX/vax780_stddev.c | 12 +++----- VAX/vax860_stddev.c | 12 +++----- VAX/vax_sysdev.c | 75 ++++++++++----------------------------------- 5 files changed, 37 insertions(+), 86 deletions(-) diff --git a/VAX/vax730_stddev.c b/VAX/vax730_stddev.c index 42370719..658578f9 100644 --- a/VAX/vax730_stddev.c +++ b/VAX/vax730_stddev.c @@ -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 */ diff --git a/VAX/vax750_stddev.c b/VAX/vax750_stddev.c index 03e3f75a..1f831a12 100644 --- a/VAX/vax750_stddev.c +++ b/VAX/vax750_stddev.c @@ -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 */ diff --git a/VAX/vax780_stddev.c b/VAX/vax780_stddev.c index 53bb9c9f..aff8781a 100644 --- a/VAX/vax780_stddev.c +++ b/VAX/vax780_stddev.c @@ -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 */ diff --git a/VAX/vax860_stddev.c b/VAX/vax860_stddev.c index 0b35f14e..be4b2492 100644 --- a/VAX/vax860_stddev.c +++ b/VAX/vax860_stddev.c @@ -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 */ diff --git a/VAX/vax_sysdev.c b/VAX/vax_sysdev.c index f3319488..6a4e231e 100644 --- a/VAX/vax_sysdev.c +++ b/VAX/vax_sysdev.c @@ -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;