From 5cf9e9ab86a23ebe5e952b266264c5ebfd06c5a1 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Fri, 16 Dec 2016 10:39:49 -0800 Subject: [PATCH] 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). --- VAX/vax780_stddev.c | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/VAX/vax780_stddev.c b/VAX/vax780_stddev.c index c46076b4..290f87fe 100644 --- a/VAX/vax780_stddev.c +++ b/VAX/vax780_stddev.c @@ -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,8 +637,10 @@ 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? */ @@ -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)