diff -ru /usr/local/src/pidp8i/trunk/simh-update-temp/simh/ours/PDP8/pdp8_cpu.c ./src/PDP8/pdp8_cpu.c
--- /usr/local/src/pidp8i/trunk/simh-update-temp/simh/ours/PDP8/pdp8_cpu.c 2017-03-18 20:42:31.000000000 -0600
+++ ./src/PDP8/pdp8_cpu.c 2017-03-18 19:46:38.000000000 -0600
@@ -23,6 +23,35 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
+ ----------------------------------------------------------------------------
+
+ Portions copyright (c) 2015-2017, Oscar Vermeulen and Warren Young
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the authors above shall
+ not be used in advertising or otherwise to promote the sale, use or other
+ dealings in this Software without prior written authorization from those
+ authors.
+
+ ----------------------------------------------------------------------------
+
cpu central processor
09-Mar-17 RMS Fixed PCQ_ENTRY for interrupts (COVERITY)
@@ -192,7 +221,10 @@
pdp8_sys.c add sim_devices table entry
*/
-#include "pdp8_defs.h"
+/* ---PiDP change------------------------------------------------------------------------------------------- */
+#include "gpio-common.h"
+#include "pidp8i.h"
+/* ---PiDP end---------------------------------------------------------------------------------------------- */
#define PCQ_SIZE 64 /* must be 2**n */
#define PCQ_MASK (PCQ_SIZE - 1)
@@ -339,10 +371,33 @@
int_req = INT_UPDATE;
reason = 0;
+
+/* ---PiDP add--------------------------------------------------------------------------------------------- */
+// PiDP-8/I specific flag, set when the last instruction was an IOT
+// instruction to a real device. SIMH doesn't track this, but the front
+// panel needs it.
+int Pause = 0;
+
+// Set our initial IPS value from the throttle, if given.
+static time_t last_update = 0;
+static size_t max_skips = 0;
+static const size_t pidp8i_updates_per_sec = 3200;
+max_skips = get_pidp8i_initial_max_skips (pidp8i_updates_per_sec);
+srand48 (time (&last_update));
+
+// Reset display info in case we're re-entering the simulator from Ctrl-E
+extern display display_bufs[2];
+memset (display_bufs, 0, sizeof(display_bufs));
+static size_t skip_count, dither, inst_count;
+skip_count = dither = inst_count = 0;
+/* ---PiDP end---------------------------------------------------------------------------------------------- */
+
+
/* Main instruction fetch/decode loop */
while (reason == 0) { /* loop until halted */
+ // Allow clean exit to SCP: https://github.com/simh/simh/issues/387
if (cpu_astop != 0) {
cpu_astop = 0;
reason = SCPE_STOP;
@@ -350,10 +405,64 @@
}
if (sim_interval <= 0) { /* check clock queue */
- if ((reason = sim_process_event ()))
+ if ((reason = sim_process_event ())) {
+/* ---PiDP add--------------------------------------------------------------------------------------------- */
+ // We're about to leave the loop, so repaint one last time
+ // in case this is a Ctrl-E and we later get a "cont"
+ // command. Set a flag that will let us auto-resume.
+ extern int resumeFromInstructionLoopExit, swStop, swSingInst;
+ resumeFromInstructionLoopExit = swStop = swSingInst = 1;
+ set_pidp8i_leds (PC, MA, MB, IR, LAC, MQ, IF, DF, SC,
+ int_req, Pause);
+
+ // Also copy SR hardware value to software register in case
+ // the user tries poking at it from the sim> prompt.
+ SR = get_switch_register();
+/* ---PiDP end---------------------------------------------------------------------------------------------- */
break;
+ }
}
+/* ---PiDP add--------------------------------------------------------------------------------------------- */
+
+ switch (handle_flow_control_switches(M, &PC, &MA, &MB, &LAC, &IF,
+ &DF, &int_req)) {
+ case pft_stop:
+ // Tell the SIMH event queue to keep running even though
+ // we're stopped. Without this, it will ignore Ctrl-E
+ // until the simulator is back in free-running mode.
+ sim_interval = sim_interval - 1;
+
+ // Have to keep display updated while stopped. This does
+ // mean if the software starts with the STOP switch held
+ // down, we'll put garbage onto the display for MA, MB, and
+ // IR, but that's what the real hardware does, too. See
+ // https://github.com/simh/simh/issues/386
+ set_pidp8i_leds (PC, MA, MB, IR, LAC, MQ, IF, DF, SC,
+ int_req, Pause);
+
+ // Go no further in STOP mode. In particular, fetch no more
+ // instructions, and do not touch PC!
+ continue;
+
+ case pft_halt:
+ // Clear all registers and halt simulator
+ PC = saved_PC = 0;
+ IF = saved_PC = 0;
+ DF = saved_DF = 0;
+ LAC = saved_LAC = 0;
+ MQ = saved_MQ = 0;
+ int_req = 0;
+ reason = STOP_HALT;
+ continue;
+
+ case pft_normal:
+ // execute normally
+ break;
+ }
+
+/* ---PiDP end---------------------------------------------------------------------------------------------- */
+
if (int_req > INT_PENDING) { /* interrupt? */
int_req = int_req & ~INT_ION; /* interrupts off */
SF = (UF << 6) | (IF >> 9) | (DF >> 12); /* form save field */
@@ -923,10 +1032,19 @@
tsc_cdf = 0; /* clear flag */
}
else {
- if (IR & 04) /* OSR */
+ if (IR & 04) { /* OSR */
+/* ---PiDP add--------------------------------------------------------------------------------------------- */
+ SR = get_switch_register(); /* get current SR */
+/* ---PiDP end---------------------------------------------------------------------------------------------- */
LAC = LAC | SR;
- if (IR & 02) /* HLT */
- reason = STOP_HALT;
+ }
+ if (IR & 02) { /* HLT */
+//--- PiDP change-----------------------------------------------------------------------
+ // reason = STOP_HALT;
+ extern int swStop;
+ swStop = 1;
+ }
+//--- end of PiDP change----------------------------------------------------------------
}
break;
} /* end if group 2 */
@@ -1346,6 +1464,10 @@
default: /* I/O device */
if (dev_tab[device]) { /* dev present? */
+/* ---PiDP add--------------------------------------------------------------------------------------------- */
+ // Any other device will trigger IOP, so light pause
+ Pause = 1;
+/* ---PiDP end---------------------------------------------------------------------------------------------- */
iot_data = dev_tab[device] (IR, iot_data);
LAC = (LAC & 010000) | (iot_data & 07777);
if (iot_data & IOT_SKP)
@@ -1358,6 +1480,72 @@
} /* end switch device */
break; /* end case IOT */
} /* end switch opcode */
+
+/* ---PiDP add--------------------------------------------------------------------------------------------- */
+ // Update the front panel with this instruction's final state.
+ //
+ // There's no point saving *every* LED "on" count. We just need a
+ // suitable amount of oversampling. We can skip this if we called
+ // set_pidp8i_leds recently enough, avoiding all the expensive bit
+ // shift and memory update work it does.
+ //
+ // The trick here is figuring out what "recently enough" means
+ // without making expensive OS timer calls. These timers aren't
+ // hopelessly slow (http://stackoverflow.com/a/13096917/142454) but
+ // we still don't want to be taking dozens of cycles per instruction
+ // just to keep our update estimate current in the face of system
+ // load changes and SET THROTTLE updates.
+ //
+ // Instead, we maintain a model of the current IPS value — seeded
+ // with the initial "SET THROTTLE" value, if any — to figure out
+ // how many calls we can skip while still meeting our other goals.
+ // This involves a bit of math, but when paid only once a second,
+ // it amortizes much nicer than estimating the skip count directly
+ // based on a more accurate time source which is more expensive
+ // to call. It's also cheaper than continually asking SIMH to
+ // estimate the SIMH IPS value, since it uses FP math.
+ //
+ // Each LED panel repaint takes about 10 ms, so we do about 100
+ // full-panel updates per second. We need a bare minimum of 32
+ // discernible brightness values per update for ILS, so if we don't
+ // update the LED status data at least 3,200 times per second, we
+ // don't have enough data for smooth panel updates. Fortunately,
+ // computers are pretty quick, and our slowest script runs at 30
+ // kIPS. (5.script.)
+ //
+ // We deliberately add some timing jitter here to get stochastic
+ // sampling of the incoming instructions to avoid beat frequencies
+ // between our update rate and the instruction pattern being
+ // executed by the front panel. It's a form of dithering.
+ //
+ // You might think to move this code to the top of set_pidp8i_leds,
+ // but the function call itself is a nontrivial hit. In fact, you
+ // don't even want to move all of this to a function here in this
+ // module and try to get GCC to inline it: that's good for a 1 MIPS
+ // speed hit in my testing! (GCC 4.9.2, Raspbian Jessie on Pi 3B.)
+
+ if (++skip_count >= (max_skips - dither)) {
+ // Save skips to inst counter and reset
+ inst_count += skip_count;
+ skip_count = 0;
+
+ // We need to update the LED data again
+ set_pidp8i_leds (PC, MA, MB, IR, LAC, MQ, IF, DF, SC, int_req, Pause);
+ Pause = 0;
+
+ // Has it been ~1s since we updated our max_skips value?
+ time_t now;
+ if (time(&now) > last_update) {
+ // Yep; simulator IPS may have changed, so freshen it.
+ last_update = now;
+ max_skips = inst_count / pidp8i_updates_per_sec;
+ //printf("Inst./repaint: %zu - %zu; %.2f MIPS\r\n",
+ // max_skips, dither, inst_count / 1e6);
+ inst_count = 0;
+ }
+ dither = max_skips > 32 ? lrand48() % (max_skips >> 3) : 0; // 12.5%
+ }
+/* ---PiDP end---------------------------------------------------------------------------------------------- */
} /* end while */
/* Simulation halted */
diff -ru /usr/local/src/pidp8i/trunk/simh-update-temp/simh/ours/scp.c ./src/scp.c
--- /usr/local/src/pidp8i/trunk/simh-update-temp/simh/ours/scp.c 2017-03-18 20:42:31.000000000 -0600
+++ ./src/scp.c 2017-03-18 20:21:21.000000000 -0600
@@ -23,6 +23,35 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
+ ----------------------------------------------------------------------------
+
+ Portions copyright (c) 2015-2017, Oscar Vermeulen and Warren Young
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS LISTED ABOVE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+ Except as contained in this notice, the names of the authors above shall
+ not be used in advertising or otherwise to promote the sale, use or other
+ dealings in this Software without prior written authorization from those
+ authors.
+
+ ----------------------------------------------------------------------------
+
08-Mar-16 RMS Added shutdown flag for detach_all
20-Mar-12 MP Fixes to "SHOW <x> SHOW" commands
06-Jan-12 JDB Fixed "SHOW DEVICE" with only one enabled unit (Dave Bryan)
@@ -214,6 +243,11 @@
/* Macros and data structures */
+#ifdef PIDP8I
+#include "gpio-common.h" // for start/stop_pidp8i_gpio_thread()
+#include "PDP8/pidp8i.h" // for build_pidp8i_scp_cmd()
+#endif
+
#define NOT_MUX_USING_CODE /* sim_tmxr library provider or agnostic */
#include "sim_defs.h"
@@ -1997,6 +2031,10 @@
t_bool lookswitch;
t_stat stat;
+#ifdef PIDP8I
+if (start_pidp8i_gpio_thread ("PiDP-8/I simulator", 1) != 0) exit (EXIT_FAILURE);
+#endif
+
#if defined (__MWERKS__) && defined (macintosh)
argc = ccommand (&argv);
#endif
@@ -2140,6 +2178,11 @@
sim_cleanup_sock (); /* cleanup sockets */
fclose (stdnul); /* close bit bucket file handle */
free (targv); /* release any argv copy that was made */
+
+#ifdef PIDP8I
+stop_pidp8i_gpio_thread ();
+#endif
+
return 0;
}
@@ -2152,6 +2195,11 @@
stat = SCPE_BARE_STATUS(stat); /* remove possible flag */
while (stat != SCPE_EXIT) { /* in case exit */
+#ifdef PIDP8I
+ if (cptr = build_pidp8i_scp_cmd (cbuf, sizeof (cbuf)))
+ printf ("Running '%s'...\n", cptr);
+ else
+#endif
if ((cptr = sim_brk_getact (cbuf, sizeof(cbuf)))) /* pending action? */
printf ("%s%s\n", sim_prompt, cptr); /* echo */
else if (sim_vm_read != NULL) { /* sim routine? */
Comments