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.
This commit is contained in:
Mark Pizzolato 2017-01-19 15:25:08 -08:00
parent 57d14e5b4a
commit 1bb42b83ef
5 changed files with 158 additions and 51 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

2
scp.c
View file

@ -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));
}