mirror of
https://github.com/prirun/p50em.git
synced 2026-01-13 15:17:32 +00:00
move instpermsec updating to devcp (clock device)
This commit is contained in:
parent
4b76c2ea1d
commit
8f1833c843
37
em.c
37
em.c
@ -257,7 +257,6 @@ unsigned short sswitch = 0; /* sense switches, set with -ss & -boot*/
|
||||
unsigned short cpuid = 27; /* STPM CPU model, set with -cpuid */
|
||||
|
||||
unsigned long instcount=0; /* global instruction count */
|
||||
unsigned long previnstcount=0; /* value of above at last gettimeofday */
|
||||
|
||||
unsigned short inhcount = 0; /* number of instructions to stay inhibited */
|
||||
|
||||
@ -1040,7 +1039,7 @@ int (*devmap[64])(short, short, short) = {
|
||||
|
||||
|
||||
|
||||
/* NOTE: This code is untested! */
|
||||
/* 16S Addressing Mode */
|
||||
|
||||
ea_t ea16s (unsigned short inst, short i, short x) {
|
||||
|
||||
@ -1077,7 +1076,7 @@ ea_t ea16s (unsigned short inst, short i, short x) {
|
||||
}
|
||||
|
||||
|
||||
/* NOTE: This code is untested! */
|
||||
/* 32S Addressing Mode */
|
||||
|
||||
ea_t ea32s (unsigned short inst, short i, short x) {
|
||||
|
||||
@ -1276,9 +1275,9 @@ ea_t apea(unsigned short *bitarg) {
|
||||
unsigned short ibr, ea_s, ea_w, bit, br, a;
|
||||
ea_t ea, ip;
|
||||
|
||||
ibr = get16(RP);
|
||||
ibr = iget16(RP);
|
||||
RPL++;
|
||||
a = get16(RP);
|
||||
a = iget16(RP);
|
||||
RPL++;
|
||||
bit = (ibr >> 12) & 0xF;
|
||||
br = (ibr >> 8) & 3;
|
||||
@ -2756,7 +2755,6 @@ main (int argc, char **argv) {
|
||||
unsigned char zch1, zch2, *zcp1, *zcp2, zspace;
|
||||
|
||||
struct timeval boot_tv;
|
||||
struct timeval tv, prev_tv;
|
||||
struct timezone tz;
|
||||
float mips;
|
||||
|
||||
@ -3026,7 +3024,6 @@ For disk boots, the last 3 digits can be:\n\
|
||||
perror("gettimeofday failed");
|
||||
fatal(NULL);
|
||||
}
|
||||
prev_tv = boot_tv;
|
||||
|
||||
/* main instruction decode loop */
|
||||
|
||||
@ -3041,7 +3038,8 @@ For disk boots, the last 3 digits can be:\n\
|
||||
|
||||
while (1) {
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
/* this is for FTN Generic 3 trace */
|
||||
if (crs[OWNERL] == 0100100 && RPL >= 034750 && RPL <= 034760)
|
||||
traceflags = -1;
|
||||
else
|
||||
@ -3089,10 +3087,6 @@ For disk boots, the last 3 digits can be:\n\
|
||||
if (devpoll[i] && (--devpoll[i] <= 0)) {
|
||||
if (!devmap[i])
|
||||
fatal("devpoll set but devmap is null");
|
||||
#if 0
|
||||
if (i == 054)
|
||||
traceflags = savetraceflags;
|
||||
#endif
|
||||
devmap[i](4, 0, i);
|
||||
}
|
||||
|
||||
@ -3161,19 +3155,6 @@ For disk boots, the last 3 digits can be:\n\
|
||||
RPL++;
|
||||
instcount++;
|
||||
|
||||
/* update instpermsec every 5 seconds */
|
||||
|
||||
if (instcount-previnstcount > instpermsec*1000*5) {
|
||||
if (gettimeofday(&tv, NULL) != 0)
|
||||
fatal("em: gettimeofday failed");
|
||||
instpermsec = (instcount-previnstcount) /
|
||||
((tv.tv_sec*1000+(tv.tv_usec/1000)) - (prev_tv.tv_sec*1000+(prev_tv.tv_usec/1000)));
|
||||
//printf("instcount = %d, previnstcount = %d, diff=%d, instpermsec=%d\n", instcount, previnstcount, instcount-previnstcount, instpermsec);
|
||||
//printf("instpermsec=%d\n", instpermsec);
|
||||
previnstcount = instcount;
|
||||
prev_tv = tv;
|
||||
}
|
||||
|
||||
/* while a process is running, RP is the real program counter, PBH
|
||||
is the active procedure segment, and PBL is zero. When a
|
||||
process stops running, RP is copied to PB. When a process
|
||||
@ -3613,7 +3594,6 @@ stfa:
|
||||
if (crsl[FLR1] & 0x8000)
|
||||
zea2 |= EXTMASK32;
|
||||
TRACE(T_INST, " ea1=%o/%o, ea2=%o/%o, len=%d\n", zea1>>16, zea1&0xffff, zea2>>16, zea2&0xffff, zlen1);
|
||||
//printf("ZMVD: ea1=%o/%o, ea2=%o/%o, len=%d\n", zea1>>16, zea1&0xffff, zea2>>16, zea2&0xffff, zlen1);
|
||||
zclen1 = 0;
|
||||
zclen2 = 0;
|
||||
while (zlen2) {
|
||||
@ -4311,10 +4291,7 @@ bidy:
|
||||
usleep(delayusec);
|
||||
if (gettimeofday(&tv1, NULL) != 0)
|
||||
fatal("em: gettimeofday 1 failed");
|
||||
if (tv1.tv_usec > tv0.tv_usec)
|
||||
actualmsec = (tv1.tv_sec-tv0.tv_sec)*1000 + (tv1.tv_usec-tv0.tv_usec)/1000;
|
||||
else
|
||||
actualmsec = (tv1.tv_sec-tv0.tv_sec-1)*1000 + (tv1.tv_usec+1000000-tv0.tv_usec)/1000;
|
||||
actualmsec = (tv1.tv_sec-tv0.tv_sec-1)*1000 + (tv1.tv_usec+1000000-tv0.tv_usec)/1000;
|
||||
// TRACEA(" BDX loop at %o/%o, remainder=%d, owner=%o, utempl=%d, wanted %d us, got %d ms\n", prevpc>>16, prevpc&0xffff, crs[X], crs[OWNERL], utempl, delayusec, actualusec);
|
||||
|
||||
/* do timer bookkeeping that would have occurred if we had
|
||||
|
||||
182
emdev.h
182
emdev.h
@ -12,7 +12,7 @@
|
||||
'01 = paper tape reader
|
||||
'02 = paper tape punch
|
||||
'03 = #1 MPC/URC (line printer/card reader/card punch)
|
||||
'04 = SOC board (system console/user terminal)
|
||||
'04 = SOC/Option A/VCP board (system console/user terminal)
|
||||
'05 = #2 MPC/URC (line printer/card reader/card punch)
|
||||
'06 = card punch? (RTOS User Guide, A-1) / IPC (Engr Handbook p.101)
|
||||
'06 = Interproc. Channel (IPC) (R20 Hacker's Guide)
|
||||
@ -292,13 +292,13 @@ int devasr (short class, short func, short device) {
|
||||
fatal(NULL);
|
||||
}
|
||||
|
||||
/* open console log file */
|
||||
/* open console log file and set to line buffering */
|
||||
|
||||
if ((conslog = fopen("console.log", "w")) == NULL) {
|
||||
perror(" unable to open console log file");
|
||||
fatal(NULL);
|
||||
}
|
||||
setvbuf(conslog, NULL, _IOLBF, 0); /* set to line buffering */
|
||||
setvbuf(conslog, NULL, _IOLBF, 0);
|
||||
return 0;
|
||||
|
||||
case 0:
|
||||
@ -309,32 +309,28 @@ int devasr (short class, short func, short device) {
|
||||
TRACE(T_INST, " SKS '%02o%02o\n", func, device);
|
||||
|
||||
if (func == 6) { /* skip if room for a character */
|
||||
#if 0
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
FD_SET(ttydev, &fds);
|
||||
n = select(ttydev+1, NULL, &fds, NULL, &timeout);
|
||||
if (n == -1) {
|
||||
perror(" unable to do write select on ttydev");
|
||||
perror(" unable to do write select on tty");
|
||||
fatal(NULL);
|
||||
}
|
||||
if (n) {
|
||||
IOSKIP;
|
||||
}
|
||||
#else
|
||||
IOSKIP; /* assume there is room under Unix */
|
||||
#endif
|
||||
|
||||
} else if (func == 7) { /* skip if received a char */
|
||||
if (crs[MODALS] & 010) /* PX enabled? */
|
||||
timeout.tv_sec = 0; /* yes, can't delay */
|
||||
else
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_sec = 1; /* single user: okay to delay */
|
||||
timeout.tv_usec = 0;
|
||||
FD_SET(ttydev, &fds);
|
||||
n = select(ttydev+1, &fds, NULL, NULL, &timeout);
|
||||
if (n == -1) {
|
||||
perror(" unable to do select on tty");
|
||||
perror(" unable to do read select on tty");
|
||||
fatal(NULL);
|
||||
}
|
||||
if (n) {
|
||||
@ -357,11 +353,12 @@ int devasr (short class, short func, short device) {
|
||||
fatal(NULL);
|
||||
}
|
||||
ttyflags = newflags;
|
||||
if (needflush && BLOCKIO) {
|
||||
fflush(stdout);
|
||||
if (needflush) {
|
||||
if (fflush(stdout) == 0) {
|
||||
needflush = 0;
|
||||
devpoll[device] = 0;
|
||||
}
|
||||
fflush(conslog);
|
||||
needflush = 0;
|
||||
devpoll[device] = 0;
|
||||
}
|
||||
readasr:
|
||||
n = read(ttydev, &ch, 1);
|
||||
@ -385,9 +382,9 @@ readasr:
|
||||
crs[A] = 0;
|
||||
crs[A] = crs[A] | ch;
|
||||
TRACE(T_INST, " character read=%o: %c\n", crs[A], crs[A] & 0x7f);
|
||||
if (ch != 015) { /* don't log carriage returns */
|
||||
if (ch != 015) { /* log all except carriage returns */
|
||||
fputc(ch, conslog);
|
||||
fflush(conslog);
|
||||
fflush(conslog); /* immediately flush typing echos */
|
||||
}
|
||||
IOSKIP;
|
||||
} else if (n != 0) {
|
||||
@ -438,15 +435,16 @@ readasr:
|
||||
printf("%10d| ", instcount);
|
||||
#endif
|
||||
putchar(ch);
|
||||
if (ch != 015)
|
||||
putc(ch, conslog);
|
||||
if (ch == 015)
|
||||
atbol = 1;
|
||||
else if (ch == 012)
|
||||
atnewl = 1;
|
||||
else {
|
||||
atbol = 0;
|
||||
atnewl = 0;
|
||||
putc(ch, conslog);
|
||||
if (ch == 012)
|
||||
atnewl = 1;
|
||||
else {
|
||||
atbol = 0;
|
||||
atnewl = 0;
|
||||
}
|
||||
}
|
||||
needflush = 1;
|
||||
if (devpoll[device] == 0)
|
||||
@ -469,17 +467,17 @@ readasr:
|
||||
break;
|
||||
|
||||
case 4:
|
||||
/* since the tty device is in non-blocking mode under Primos, keep
|
||||
flushing output every .1 seconds for smoothest and fastest
|
||||
output. Problem is, we can't tell if fflush was able to send
|
||||
everything out (check fflush return?), so we just keep flushing */
|
||||
|
||||
/* tty output is blocking, even under Primos, which means that
|
||||
writes and fflush can hang the entire system, eg, if XOFF
|
||||
happens while writing to the console) */
|
||||
|
||||
if (needflush) {
|
||||
fflush(stdout);
|
||||
if (BLOCKIO)
|
||||
if (fflush(stdout) == 0)
|
||||
needflush = 0;
|
||||
else
|
||||
devpoll[device] = instpermsec*100;
|
||||
fflush(conslog);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1147,25 +1145,49 @@ int devmt (short class, short func, short device) {
|
||||
|
||||
*/
|
||||
|
||||
/* initclock sets Primos' real-time clock variable */
|
||||
|
||||
initclock(datnowea) {
|
||||
int datnow, i;
|
||||
time_t unixtime;
|
||||
struct tm *tms;
|
||||
|
||||
unixtime = time(NULL);
|
||||
tms = localtime(&unixtime);
|
||||
datnow = tms->tm_year<<25 | (tms->tm_mon+1)<<21 | tms->tm_mday<<16 | ((tms->tm_hour*3600 + tms->tm_min*60 + tms->tm_sec)/4);
|
||||
put32r(datnow, datnowea, 0);
|
||||
}
|
||||
|
||||
|
||||
int devcp (short class, short func, short device) {
|
||||
static short enabled = 0;
|
||||
static unsigned short clkvec;
|
||||
static short clkpic;
|
||||
static unsigned long ticks=0;
|
||||
static short clkpic = 0;
|
||||
static unsigned long ticks = -1;
|
||||
static unsigned long absticks = -1;
|
||||
static struct timeval start_tv;
|
||||
static ea_t datnowea = 0;
|
||||
static struct timeval prev_tv;
|
||||
static unsigned long previnstcount=0; /* value of instcount corresponding to above */
|
||||
|
||||
struct timeval tv;
|
||||
unsigned long elapsedms,targetticks;
|
||||
int datnow, i;
|
||||
time_t unixtime;
|
||||
ea_t datnowea;
|
||||
struct tm *tms;
|
||||
int i;
|
||||
|
||||
#define SETCLKPOLL devpoll[device] = instpermsec*(-clkpic*3.2)/1000;
|
||||
|
||||
switch (class) {
|
||||
|
||||
case -1:
|
||||
|
||||
/* if -map is used, lookup DATNOW symbol and set the 32-bit
|
||||
Primos time value (DATNOW+TIMNOW) */
|
||||
|
||||
datnowea = 0;
|
||||
for (i=0; i<numsyms; i++) {
|
||||
if (strcmp(mapsym[i].symname, "DATNOW") == 0)
|
||||
datnowea = mapsym[i].address;
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 0:
|
||||
@ -1188,25 +1210,8 @@ int devcp (short class, short func, short device) {
|
||||
//traceflags = ~TB_MAP;
|
||||
//TRACEA("Clock interrupt enabled!\n");
|
||||
enabled = 1;
|
||||
if (gettimeofday(&start_tv, NULL) != 0)
|
||||
fatal("em: gettimeofday 2 failed");
|
||||
ticks = 0;
|
||||
SETCLKPOLL;
|
||||
|
||||
/* if -map is used, lookup DATNOW symbol and set the 32-bit
|
||||
Primos time value (DATNOW+TIMNOW) */
|
||||
|
||||
datnowea = 0;
|
||||
for (i=0; i<numsyms; i++) {
|
||||
if (strcmp(mapsym[i].symname, "DATNOW") == 0)
|
||||
datnowea = mapsym[i].address;
|
||||
}
|
||||
if (datnowea != 0) {
|
||||
unixtime = time(NULL);
|
||||
tms = localtime(&unixtime);
|
||||
datnow = tms->tm_year<<25 | (tms->tm_mon+1)<<21 | tms->tm_mday<<16 | ((tms->tm_hour*3600 + tms->tm_min*60 + tms->tm_sec)/4);
|
||||
put32(datnow, datnowea);
|
||||
}
|
||||
ticks = -1;
|
||||
|
||||
} else if (func == 016 || func == 017) {
|
||||
enabled = 0;
|
||||
@ -1259,29 +1264,72 @@ int devcp (short class, short func, short device) {
|
||||
}
|
||||
break;
|
||||
|
||||
/* Clock poll important considerations are:
|
||||
1. ticks = -1 initially; this triggers initialization here
|
||||
2. start_tv corresponds to the time where ticks = 0
|
||||
3. if the clock gets out of sync, it ticks faster or slower until
|
||||
it is right
|
||||
4. if the clock is WAY out of sync, try to jump to the correct time
|
||||
5. once the clock is in sync, reset start_tv if ticks gets too big
|
||||
(uh, after 5 months!) to prevent overflows in time calculations
|
||||
*/
|
||||
|
||||
case 4:
|
||||
/* interrupt if enabled and no interrupt active */
|
||||
|
||||
if (enabled) {
|
||||
if (intvec == -1) {
|
||||
intvec = clkvec;
|
||||
SETCLKPOLL;
|
||||
ticks++;
|
||||
if (gettimeofday(&tv, NULL) != 0)
|
||||
fatal("em: gettimeofday 3 failed");
|
||||
if (tv.tv_usec > start_tv.tv_usec)
|
||||
elapsedms = (tv.tv_sec-start_tv.tv_sec)*1000 + (tv.tv_usec-start_tv.tv_usec)/1000;
|
||||
else
|
||||
elapsedms = (tv.tv_sec-start_tv.tv_sec-1)*1000 + (tv.tv_usec+1000000-start_tv.tv_usec)/1000;
|
||||
if (ticks == 0) {
|
||||
start_tv = tv;
|
||||
prev_tv = tv;
|
||||
previnstcount = instcount;
|
||||
if (datnowea != 0)
|
||||
initclock(datnowea);
|
||||
printf("em: resetting real time clock\n");
|
||||
}
|
||||
elapsedms = (tv.tv_sec-start_tv.tv_sec-1)*1000 + (tv.tv_usec+1000000-start_tv.tv_usec)/1000;
|
||||
targetticks = elapsedms/(-clkpic*3.2/1000);
|
||||
if (ticks < targetticks) {
|
||||
//printf("Clock catchup, elapsed=%d, target=%d, ticks=%d\n", elapsedms, targetticks, ticks);
|
||||
devpoll[device] = 100; /* behind, so catch-up */
|
||||
} else {
|
||||
#if 0
|
||||
if (ticks%1000 == 0)
|
||||
printf("Clock check: target=%d, ticks=%d\n", targetticks, ticks);
|
||||
#if 1
|
||||
absticks++;
|
||||
if (absticks%1000 == 0)
|
||||
printf("Clock check: target=%d, ticks=%d\n", targetticks, ticks);
|
||||
#endif
|
||||
SETCLKPOLL;
|
||||
if (ticks > targetticks)
|
||||
devpoll[device] = devpoll[device]*2;
|
||||
|
||||
/* if the clock gets way out of whack (eg, because of a host
|
||||
suspend or time change (eg, DST), reset it IFF datnowea is
|
||||
known. This causes an immediate jump to the correct time.
|
||||
If datnowea is not available (no Primos maps), then we have
|
||||
to tick our way to the correct time */
|
||||
|
||||
if (abs(ticks-targetticks) > 1000 && datnowea != 0)
|
||||
ticks = -1;
|
||||
else if (ticks < targetticks)
|
||||
devpoll[device] = 100; /* behind, so catch-up */
|
||||
else if (ticks > targetticks)
|
||||
devpoll[device] = devpoll[device]*2; /* ahead, so slow down */
|
||||
else { /* just right! */
|
||||
if (ticks > 1000000000) { /* after a long time, */
|
||||
start_tv = tv; /* reset tick vars */
|
||||
ticks = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* update instpermsec every 5 seconds
|
||||
NB: this should probably be done whether the clock is running
|
||||
or not */
|
||||
|
||||
if (instcount-previnstcount > instpermsec*1000*5) {
|
||||
instpermsec = (instcount-previnstcount) /
|
||||
((tv.tv_sec-prev_tv.tv_sec-1)*1000 + (tv.tv_usec+1000000-prev_tv.tv_usec)/1000);
|
||||
//printf("instcount = %d, previnstcount = %d, diff=%d, instpermsec=%d\n", instcount, previnstcount, instcount-previnstcount, instpermsec);
|
||||
printf("instpermsec=%d\n", instpermsec);
|
||||
previnstcount = instcount;
|
||||
prev_tv = tv;
|
||||
}
|
||||
} else {
|
||||
devpoll[device] = 100; /* couldn't interrupt, try again soon */
|
||||
@ -2520,5 +2568,3 @@ int devpnc (short class, short func, short device) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user