From 1bb42b83ef4672c8a3e0542259443425d3e2bef4 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Thu, 19 Jan 2017 15:25:08 -0800 Subject: [PATCH] VAX730, VAX750, VAX780, VAX8600: Make TODR a little more precise Add consistent debug options to track TODR activities and the values which are set. Debug data will display the VMS time related to the values set and read. --- VAX/vax730_stddev.c | 50 +++++++++++++++++++++++++------- VAX/vax750_stddev.c | 70 ++++++++++++++++++++++++++++----------------- VAX/vax780_stddev.c | 49 ++++++++++++++++++++++++------- VAX/vax860_stddev.c | 38 ++++++++++++++++++++++-- scp.c | 2 +- 5 files changed, 158 insertions(+), 51 deletions(-) diff --git a/VAX/vax730_stddev.c b/VAX/vax730_stddev.c index 3c8017dc..0cdbd218 100644 --- a/VAX/vax730_stddev.c +++ b/VAX/vax730_stddev.c @@ -888,6 +888,31 @@ return "interval timer"; /* TODR routines */ +static const char *todr_fmt_vms_todr (int32 val) +{ +static char buf[32]; +uint32 uval = (uint32)val; + +if (val < 0x10000000) + sprintf (buf, "Not VMS Time: 0x%08X", uval); +else { + int yday, hr, min, sec, msecs; + + uval -= 0x10000000; + msecs = (uval % 100) * 10; + uval /= 100; + sec = uval % 60; + uval /= 60; + min = uval % 60; + uval /= 60; + hr = uval % 24; + uval /= 24; + yday = uval; + sprintf (buf, "yday:%d %02d:%02d:%02d.%03d", yday, hr, min, sec, msecs); + } +return buf; +} + int32 todr_rd (void) { TOY *toy = (TOY *)clk_unit.filebuf; @@ -897,7 +922,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)); +sim_debug (TMR_DB_TODR, &tmr_dev, "todr_rd() - TODR=0x%X - %s\n", (int32)(val.tv_sec*100 + val.tv_nsec/10000000), todr_fmt_vms_todr ((int32)(val.tv_sec*100 + val.tv_nsec/10000000))); return (int32)(val.tv_sec*100 + val.tv_nsec/10000000); /* 100hz Clock Ticks */ } @@ -905,24 +930,26 @@ void todr_wr (int32 data) { TOY *toy = (TOY *)clk_unit.filebuf; struct timespec now, val, base; +time_t tbase; -/* Save the GMT time when set value was 0 to record the base for future - read operations in "battery backed-up" state */ +/* Save the GMT time when set value was 0 to record the base for + future read operations in "battery backed-up" state */ sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ val.tv_sec = ((uint32)data) / 100; val.tv_nsec = (((uint32)data) % 100) * 10000000; sim_timespec_diff (&base, &now, &val); /* base = now - data */ toy->toy_gmtbase = (uint32)base.tv_sec; +tbase = (time_t)base.tv_sec; toy->toy_gmtbasemsec = base.tv_nsec/1000000; -sim_debug (TMR_DB_TODR, &tmr_dev, "todr_wr(0x%X)\n", data); +sim_debug (TMR_DB_TODR, &tmr_dev, "todr_wr(0x%X) - %s - GMTBASE=%8.8s.%03d\n", data, todr_fmt_vms_todr (data), 11+ctime(&tbase), (int)(base.tv_nsec/1000000)); } t_stat todr_resync (void) { TOY *toy = (TOY *)clk_unit.filebuf; -if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX780 */ +if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX TODR */ if (!toy->toy_gmtbase) /* Never set? */ todr_wr (0); /* Start ticking from 0 */ } @@ -930,18 +957,21 @@ else { /* Not-Attached means */ uint32 base; /* behave like simh VMS default */ time_t curr; struct tm *ctm; + struct timespec now; - curr = time (NULL); /* get curr time */ + sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ + curr = (time_t)now.tv_sec; if (curr == (time_t) -1) /* error? */ return SCPE_NOFNC; ctm = localtime (&curr); /* decompose */ if (ctm == NULL) /* error? */ return SCPE_NOFNC; base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */ - ctm->tm_hour) * 60) + - ctm->tm_min) * 60) + - ctm->tm_sec; - todr_wr ((base * 100) + 0x10000000); /* use VMS form */ + ctm->tm_hour) * 60) + + ctm->tm_min) * 60) + + ctm->tm_sec; + todr_wr ((base * 100) + 0x10000000 + /* use VMS form */ + (int32)(now.tv_nsec / 10000000)); } return SCPE_OK; } diff --git a/VAX/vax750_stddev.c b/VAX/vax750_stddev.c index 6a4dcc65..45802e91 100644 --- a/VAX/vax750_stddev.c +++ b/VAX/vax750_stddev.c @@ -885,55 +885,68 @@ return "interval timer"; /* TODR routines */ +static const char *todr_fmt_vms_todr (int32 val) +{ +static char buf[32]; +uint32 uval = (uint32)val; + +if (val < 0x10000000) + sprintf (buf, "Not VMS Time: 0x%08X", uval); +else { + int yday, hr, min, sec, msecs; + + uval -= 0x10000000; + msecs = (uval % 100) * 10; + uval /= 100; + sec = uval % 60; + uval /= 60; + min = uval % 60; + uval /= 60; + hr = uval % 24; + uval /= 24; + yday = uval; + sprintf (buf, "yday:%d %02d:%02d:%02d.%03d", yday, hr, min, sec, msecs); + } +return buf; +} + int32 todr_rd (void) { TOY *toy = (TOY *)clk_unit.filebuf; struct timespec base, now, val; -/* Maximum number of seconds which can be represented as 10ms ticks - in the 32bit TODR. This is the 33bit value 0x100000000/100 to get seconds */ -#define TOY_MAX_SECS (0x40000000/25) - 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); - -if ((val.tv_sec >= TOY_MAX_SECS) || (!toy->toy_gmtbase))/* todr overflowed? */ - return 0; /* stop counting */ -sim_debug (TMR_DB_TODR, &tmr_dev, "todr_rd() - TODR=0x%X\n", (int32)(val.tv_sec*100 + val.tv_nsec/10000000)); +sim_debug (TMR_DB_TODR, &tmr_dev, "todr_rd() - TODR=0x%X - %s\n", (int32)(val.tv_sec*100 + val.tv_nsec/10000000), todr_fmt_vms_todr ((int32)(val.tv_sec*100 + val.tv_nsec/10000000))); return (int32)(val.tv_sec*100 + val.tv_nsec/10000000); /* 100hz Clock Ticks */ } - void todr_wr (int32 data) { TOY *toy = (TOY *)clk_unit.filebuf; struct timespec now, val, base; +time_t tbase; -sim_debug (TMR_DB_TODR, &tmr_dev, "todr_wr(0x%X)\n", data); -if (data) { - /* Save the GMT time when set value was not 0 to record the base for - future read operations in "battery backed-up" state */ +/* Save the GMT time when set value was 0 to record the base for + future read operations in "battery backed-up" state */ - sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ - val.tv_sec = ((uint32)data) / 100; - 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; - } -else { /* stop the clock */ - toy->toy_gmtbase = 0; - toy->toy_gmtbasemsec = 0; - } +sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ +val.tv_sec = ((uint32)data) / 100; +val.tv_nsec = (((uint32)data) % 100) * 10000000; +sim_timespec_diff (&base, &now, &val); /* base = now - data */ +toy->toy_gmtbase = (uint32)base.tv_sec; +tbase = (time_t)base.tv_sec; +toy->toy_gmtbasemsec = base.tv_nsec/1000000; +sim_debug (TMR_DB_TODR, &tmr_dev, "todr_wr(0x%X) - %s - GMTBASE=%8.8s.%03d\n", data, todr_fmt_vms_todr (data), 11+ctime(&tbase), (int)(base.tv_nsec/1000000)); } t_stat todr_resync (void) { TOY *toy = (TOY *)clk_unit.filebuf; -if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX780 */ +if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX TODR */ if (!toy->toy_gmtbase) /* Never set? */ todr_wr (0); /* Start ticking from 0 */ } @@ -941,8 +954,10 @@ else { /* Not-Attached means */ uint32 base; /* behave like simh VMS default */ time_t curr; struct tm *ctm; + struct timespec now; - curr = time (NULL); /* get curr time */ + sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ + curr = (time_t)now.tv_sec; if (curr == (time_t) -1) /* error? */ return SCPE_NOFNC; ctm = localtime (&curr); /* decompose */ @@ -952,7 +967,8 @@ else { /* Not-Attached means */ ctm->tm_hour) * 60) + ctm->tm_min) * 60) + ctm->tm_sec; - todr_wr ((base * 100) + 0x10000000); /* use VMS form */ + todr_wr ((base * 100) + 0x10000000 + /* use VMS form */ + (int32)(now.tv_nsec / 10000000)); } return SCPE_OK; } diff --git a/VAX/vax780_stddev.c b/VAX/vax780_stddev.c index 4655f433..5ef6ff2d 100644 --- a/VAX/vax780_stddev.c +++ b/VAX/vax780_stddev.c @@ -855,6 +855,31 @@ return "interval timer"; /* TODR routines */ +static const char *todr_fmt_vms_todr (int32 val) +{ +static char buf[32]; +uint32 uval = (uint32)val; + +if (val < 0x10000000) + sprintf (buf, "Not VMS Time: 0x%08X", uval); +else { + int yday, hr, min, sec, msecs; + + uval -= 0x10000000; + msecs = (uval % 100) * 10; + uval /= 100; + sec = uval % 60; + uval /= 60; + min = uval % 60; + uval /= 60; + hr = uval % 24; + uval /= 24; + yday = uval; + sprintf (buf, "yday:%d %02d:%02d:%02d.%03d", yday, hr, min, sec, msecs); + } +return buf; +} + int32 todr_rd (void) { TOY *toy = (TOY *)clk_unit.filebuf; @@ -864,17 +889,17 @@ 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)); +sim_debug (TMR_DB_TODR, &tmr_dev, "todr_rd() - TODR=0x%X - %s\n", (int32)(val.tv_sec*100 + val.tv_nsec/10000000), todr_fmt_vms_todr ((int32)(val.tv_sec*100 + val.tv_nsec/10000000))); return (int32)(val.tv_sec*100 + val.tv_nsec/10000000); /* 100hz Clock Ticks */ } - void todr_wr (int32 data) { TOY *toy = (TOY *)clk_unit.filebuf; struct timespec now, val, base; +time_t tbase; -/* Save the GMT time when set value was written to record the base for +/* Save the GMT time when set value was 0 to record the base for future read operations in "battery backed-up" state */ sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ @@ -882,15 +907,16 @@ val.tv_sec = ((uint32)data) / 100; val.tv_nsec = (((uint32)data) % 100) * 10000000; sim_timespec_diff (&base, &now, &val); /* base = now - data */ toy->toy_gmtbase = (uint32)base.tv_sec; +tbase = (time_t)base.tv_sec; toy->toy_gmtbasemsec = base.tv_nsec/1000000; -sim_debug (TMR_DB_TODR, &tmr_dev, "todr_wr(0x%X)\n", data); +sim_debug (TMR_DB_TODR, &tmr_dev, "todr_wr(0x%X) - %s - GMTBASE=%8.8s.%03d\n", data, todr_fmt_vms_todr (data), 11+ctime(&tbase), (int)(base.tv_nsec/1000000)); } t_stat todr_resync (void) { TOY *toy = (TOY *)clk_unit.filebuf; -if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX780 */ +if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX TODR */ if (!toy->toy_gmtbase) /* Never set? */ todr_wr (0); /* Start ticking from 0 */ } @@ -898,18 +924,21 @@ else { /* Not-Attached means */ uint32 base; /* behave like simh VMS default */ time_t curr; struct tm *ctm; + struct timespec now; - curr = time (NULL); /* get curr time */ + sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ + curr = (time_t)now.tv_sec; if (curr == (time_t) -1) /* error? */ return SCPE_NOFNC; ctm = localtime (&curr); /* decompose */ if (ctm == NULL) /* error? */ return SCPE_NOFNC; base = (((((ctm->tm_yday * 24) + /* sec since 1-Jan */ - ctm->tm_hour) * 60) + - ctm->tm_min) * 60) + - ctm->tm_sec; - todr_wr ((base * 100) + 0x10000000); /* use VMS form */ + ctm->tm_hour) * 60) + + ctm->tm_min) * 60) + + ctm->tm_sec; + todr_wr ((base * 100) + 0x10000000 + /* use VMS form */ + (int32)(now.tv_nsec / 10000000)); } return SCPE_OK; } diff --git a/VAX/vax860_stddev.c b/VAX/vax860_stddev.c index 682466fc..a45e233e 100644 --- a/VAX/vax860_stddev.c +++ b/VAX/vax860_stddev.c @@ -989,6 +989,31 @@ return "interval timer"; /* TODR routines */ +static const char *todr_fmt_vms_todr (int32 val) +{ +static char buf[32]; +uint32 uval = (uint32)val; + +if (val < 0x10000000) + sprintf (buf, "Not VMS Time: 0x%08X", uval); +else { + int yday, hr, min, sec, msecs; + + uval -= 0x10000000; + msecs = (uval % 100) * 10; + uval /= 100; + sec = uval % 60; + uval /= 60; + min = uval % 60; + uval /= 60; + hr = uval % 24; + uval /= 24; + yday = uval; + sprintf (buf, "yday:%d %02d:%02d:%02d.%03d", yday, hr, min, sec, msecs); + } +return buf; +} + int32 todr_rd (void) { TOY *toy = (TOY *)clk_unit.filebuf; @@ -998,6 +1023,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 - %s\n", (int32)(val.tv_sec*100 + val.tv_nsec/10000000), todr_fmt_vms_todr ((int32)(val.tv_sec*100 + val.tv_nsec/10000000))); return (int32)(val.tv_sec*100 + val.tv_nsec/10000000); /* 100hz Clock Ticks */ } @@ -1005,6 +1031,7 @@ void todr_wr (int32 data) { TOY *toy = (TOY *)clk_unit.filebuf; struct timespec now, val, base; +time_t tbase; /* Save the GMT time when set value was 0 to record the base for future read operations in "battery backed-up" state */ @@ -1014,14 +1041,16 @@ val.tv_sec = ((uint32)data) / 100; val.tv_nsec = (((uint32)data) % 100) * 10000000; sim_timespec_diff (&base, &now, &val); /* base = now - data */ toy->toy_gmtbase = (uint32)base.tv_sec; +tbase = (time_t)base.tv_sec; toy->toy_gmtbasemsec = base.tv_nsec/1000000; +sim_debug (TMR_DB_TODR, &tmr_dev, "todr_wr(0x%X) - %s - GMTBASE=%8.8s.%03d\n", data, todr_fmt_vms_todr (data), 11+ctime(&tbase), (int)(base.tv_nsec/1000000)); } t_stat todr_resync (void) { TOY *toy = (TOY *)clk_unit.filebuf; -if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX860 */ +if (clk_unit.flags & UNIT_ATT) { /* Attached means behave like real VAX TODR */ if (!toy->toy_gmtbase) /* Never set? */ todr_wr (0); /* Start ticking from 0 */ } @@ -1029,8 +1058,10 @@ else { /* Not-Attached means */ uint32 base; /* behave like simh VMS default */ time_t curr; struct tm *ctm; + struct timespec now; - curr = time (NULL); /* get curr time */ + sim_rtcn_get_time(&now, TMR_CLK); /* get curr time */ + curr = (time_t)now.tv_sec; if (curr == (time_t) -1) /* error? */ return SCPE_NOFNC; ctm = localtime (&curr); /* decompose */ @@ -1040,7 +1071,8 @@ else { /* Not-Attached means */ ctm->tm_hour) * 60) + ctm->tm_min) * 60) + ctm->tm_sec; - todr_wr ((base * 100) + 0x10000000); /* use VMS form */ + todr_wr ((base * 100) + 0x10000000 + /* use VMS form */ + (int32)(now.tv_nsec / 10000000)); } return SCPE_OK; } diff --git a/scp.c b/scp.c index 855090d3..6ee92171 100644 --- a/scp.c +++ b/scp.c @@ -10483,7 +10483,7 @@ if (sim_deb_switches & (SWMASK ('T') | SWMASK ('R') | SWMASK ('A'))) { sim_timespec_diff (&time_now, &time_now, &sim_deb_basetime); if (sim_deb_switches & SWMASK ('T')) { time_t tnow = (time_t)time_now.tv_sec; - struct tm *now = gmtime(&tnow); + struct tm *now = localtime(&tnow); sprintf(tim_t, "%02d:%02d:%02d.%03d ", now->tm_hour, now->tm_min, now->tm_sec, (int)(time_now.tv_nsec/1000000)); }