1
0
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:
Jim 2007-02-22 00:00:00 -05:00
parent 4b76c2ea1d
commit 8f1833c843
2 changed files with 121 additions and 98 deletions

37
em.c
View File

@ -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
View File

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