1
0
mirror of https://github.com/prirun/p50em.git synced 2026-04-26 04:16:56 +00:00

added get/put16t to handle address trap cases, real-time clock changes

devcp supports varying clock tick rates
reinit clock if it gets off more than 5 seconds
This commit is contained in:
Jim
2007-03-25 00:00:00 -04:00
parent bc8742fb5c
commit 1419a909d5
2 changed files with 147 additions and 131 deletions

68
emdev.h
View File

@@ -1188,14 +1188,15 @@ int devmt (int class, int func, int device) {
IMPORTANT NOTE 1: this device ('20) never skips!
IMPORTANT NOTE 2: if the host system suspends, then when it awakes,
devcp will make the clock tick faster until it catches up to where
it should be. Fake clock interrupts are injected every 100 Prime
instructions to catch up. These fast interrupts can't occur too
quickly (like every 10 Prime instructions), because CLKDIM can't
execute completely in 10 instructions and the repeated interrupts
will eventually cause the clock semaphore to overflow.
IMPORTANT NOTE 2: when the emulator wakes up after the host system
suspends, devcp will either reset the clock (if it knows where
Primos' DATNOW variable is), or will make the clock tick faster
until it catches up to where it should be. Fake clock interrupts
are injected every 100 Prime instructions to catch up. These fast
interrupts can't occur too quickly (like every 10 Prime
instructions), because CLKDIM can't execute completely in 10
instructions and the repeated interrupts will eventually cause the
clock semaphore to overflow.
*/
/* initclock sets Primos' real-time clock variable */
@@ -1215,7 +1216,7 @@ initclock(ea_t datnowea) {
int devcp (int class, int func, int device) {
static short enabled = 0;
static unsigned short clkvec = 0;
static short clkpic = 947;
static short clkpic = -947;
static float clkrate = 3.2;
static unsigned long ticks = -1;
static unsigned long absticks = -1;
@@ -1301,21 +1302,47 @@ int devcp (int class, int func, int device) {
case 3:
TRACE(T_INST, " OTA '%02o%02o\n", func, device);
/* standard Primos always sets a PIC interval of 947 and uses the
hardware clock rate of 3.2 usec. This causes a software interrupt
every 947*3.2 usec, or 3030.4 milliseconds, and this works out
to 330 software interrupts per second. BUT newer machines tick
at whatever rate they want and ignore the PIC interval set here.
To keep emulator overhead low, some versions of Primos have been
modified to set the PIC interval to 15625 and send 20 ticks per
second to Primos.
To handle both cases, this code looks at the cpuid to determine
the actual # of ticks per second expected by Primos whenever
the PIC interval is set to 947. If PIC is set to something
other than 947, that value is used.
*/
if (func == 02) { /* set PIC interval */
clkpic = *(short *)(crs+A);
if (clkpic == -947)
if (cpuid == 11 || cpuid == 20)
clkpic = -625; /* P2250: 500 ticks/second */
else if (cpuid >= 15) /* newer machines: 250 ticks/second */
clkpic = -1250;
TRACE(T_INST, "Clock PIC %d requested, set to %d\n", *(short *)(crs+A), clkpic);
SETCLKPOLL;
TRACE(T_INST, "Clock PIC interval set to %d\n", clkpic);
} else if (func == 07) {
TRACE(T_INST, "Clock control register set to '%o\n", crs[A]);
if (crs[A] & 020)
clkrate = 100.0; /* 102.4 on real SOC, but not good for RT clock */
clkrate = 102.4;
else
clkrate = 3.2;
SETCLKPOLL;
} else if (func == 013) {
} else if (func == 013) { /* set interrupt vector */
clkvec = crs[A];
TRACE(T_INST, "Clock interrupt vector address = '%o\n", clkvec);
} else if (func == 017) { /* write lights */
} else if (func == 017) { /* write lights */
} else {
printf("Unimplemented OTA device '%02o function '%02o, A='%o\n", device, func, crs[A]);
fatal(NULL);
@@ -1353,15 +1380,16 @@ int devcp (int class, int func, int device) {
targetticks = elapsedms/(-clkpic*clkrate/1000);
#if 0
absticks++;
if (absticks%1000 == 0)
printf("Clock check: target=%d, ticks=%d\n", targetticks, ticks);
if (absticks%1000 == 0 || abs(ticks-targetticks) > 5)
printf("\nClock check: target=%d, ticks=%d\n", targetticks, ticks);
#endif
/* 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 */
suspend), reset it IFF datnowea is set. 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. In addition to lowering overhead, slower
clock tick rates make catching up much faster. */
if (abs(ticks-targetticks) > 5000 && datnowea != 0)
ticks = -1;
@@ -1384,7 +1412,7 @@ int devcp (int class, int func, int device) {
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);
//printf("\ninstpermsec=%d\n", instpermsec);
previnstcount = instcount;
prev_tv = tv;
}