RELEASE: v2020214

815 views
Skip to first unread message

Warren Young

unread,
Feb 15, 2021, 3:37:19 AM2/15/21
to PiDP-8
It's been nearly two years since the last formal release, but we've finally got this one in a shape where it was worth making OS images.

We — by which I mean mostly Dr. William Cattey — have been busy through this quarantine time:
  • Raspberry Pi 4 support.

  • Increased SD card requirement from 2 GB to 8 GB. See the OS images doc for details. (Called README.md inside the OS images zip files.)

  • Integrated Bill Silver’s E8 Emacs-like text editor for the PDP–8.

  • Updated Ian Schofield’s CC8 C compiler to V2.0:

    • The OS/8 (“native”) compiler now has support for every K&R C 1978 construct except for struct, float, and function pointers. There are numerous compliance problems, but we’ve tried to document all of them in doc/cc8-manual.md.
Most notably, this release adds support for switch and all of the remaining 2-character operators: !=, >=, <= and ?:

    • Added several more examples, including a Forth interpreter.

  • The software build now creates a bootable RK05 disk image of the OS/8 Combined Kit (OCK) which is effectively the last official release of OS/8, with all patches. You can elect to use this for the IF=0 boot option instead of OS/8 V3D by configuring the software with the --use-ock flag.
Bill Cattey did almost all of the work for this.
Contrast the OS/8 V3F release, which wasn’t a formal release from DEC, but was rather V3D plus the Device Extensions Kit to support newer hardware that came out after V3D.

  • Added the os8pkg package manager, allowing installation and uninstallation of packages on the installed RK05 OS/8 boot media, whether OCK or V3D. This is the new mechanism behind the existing --with-os8-* options, allowing you to get different feature sets on existing media without rebuilding it from scratch. Bill Cattey did almost all of the work on this.

  • Many packages previously copied in as binary blobs have been shifted to the source tree to be built from source, or at the very least as individual binary files copied in from the source tree under code management. This not only permits “clean” builds, it allows adding and removing packages from OS/8 media after installation, where previously you had to rebuild the entire medium after reconfiguring the source tree using --enable-os8-* type flags. Bill Cattey did this integration.
The packages newly managed in this way are:

    • advent: The game of Adventure, built from source.

    • basic-games: The collection of BASIC games and demos. Although this is a collection of ASCII text files, and OS/8 BASIC is an interpreter of those text program files, not a compiler, we still build this package of PDP–8 ASCII text files from POSIX ASCII text files.
This not only permits later package add and remove options, it also allows fun things like editing the sources on the Pi side, rebuilding the package, and reinstalling, rather than editing the sources directly under OS/8. Or, skip the middleman and use os8-cp to copy the edited version to the boot media.

    • cc8: Ian Schofield’s C compiler was always built from source, but now it’s built to an intermediate package rather than copied straight to the OS/8 boot media.

    • chekmo: The Chekmo II chess playing program, built from source.

    • dcp: The OS/8 PDP–8 dissassembler, built from binary executables, since source has apparently been lost.

    • e8: Bill Silver’s E8 editor, built from source.

    • focal69: The first DEC FOCAL interpreter, built from source.

    • kermit: The communication and text encode/decode suite, built from source.

    • lcmod: The batch scripts UCSYS.BI, LCSYS.BI, UCBAS.BI and LCBAS.BI are now under source control. Being patches to OS/8, the sources are scattered within our OS/8 source subtree.

    • music: The PDP–8 Music compiler is now built from source with the scores under source control. Note that we still can’t actually hear the output owing to lack of connection between the sound generation and SIMH.

    • uwfocal: The U/W FOCAL interpreter. The main module is built from source, but other components are considered legacy and treated as binary blobs for now. This is documented in the uwfocal.pspec file.

    • vtedit: The VT screen editor extensions to TECO are now packaged separately, built from source.

  • Added os8-progtest tool for testing software under OS/8. Tests in pyyaml format create state machines for starting programs engaging in run dialogs, and confirming success. Test harnesses exist for advent, cc8, chekmo, uwfocal, and basic-games. Bill Cattey did almost all the work on this.

  • The distribution now follows a documented testing protocol.

  • Configurable screen manager, allowing either tmux or “none” as an alternative to GNU screen. Initial work on this feature done by Ryan Finnie.

  • Updated the PiDP–8/I KiCad hardware files to Oscar Vermeulen’s 2019 kit version.

  • Integrated the octal comparison tool ocomp into the lower level dist-v3d.rk05 and dist-ocomp.rk05 images. Used for validation of packages installed by os8pkg. Integration by Bill Cattey.

  • Added udev rules to allow mounting media from disks on USB floppy drives. (Thanks to Ryan Finnie for this feature.)

  • Updated SIMH to 2021–02–03 version, GitHub commit 2f66e74c50. The primary user-visible changes from the perspective of a PiDP–8/I user are:

    • The paper tape punch and LPT output devices now default to append mode for existing files, rather than overwriting them on ATTACH. This not only follows the principle of least surprise for modern users, it also replicates the way actual hardware operated: reopening such devices and sending more data to them just advanced the tape thru the punch or the paper thru the teletypewriter.

    • RF08: Fixed a bug that could cause loss of photo cell unit events.

    • The simulator now does a precalibration pass to achieve a good initial guess at the host’s IPS rate rather than drop sharply into a calibrated level some seconds past the simulator startup time, as in the prior release.

    • Improvements to SCP, the command shell / script interpreter:

    • Add the RENAME/MOVE/MV, MKDIR, and RMDIR commands.

    • The SAVE command can now overwrite existing files.

    • The unimplemented DUMP command now gives a helpful diagnostic message recommending use of EXAMINE.

    • Several improvements to power-of–2 unit handling in command output and parameter input.

    • Regular expressions in SIMH EXPECT commands now use PCRE syntax if available instead of the POSIX regex library.

    • Many improvements to magnetic tape device handling. (Nothing PDP–8 specific, just generic SIMH improvements.)

  • Fixed a bug in the SING_STEP + IF feature for switching between boot scripts (e.g. IF=2 for running TSS/8) that could cause the simulator to crash rather than execute the new script.
In typical use, this may not even be noticed by the user because systemd will restart a crashed simulator, which will then choose its boot script based on the same IF switch setting.
Likely the only people to notice this fix are those running the simulator attached to a terminal, such as in development.

  • The build system now detects the availability of Python 3 and prefers it if available. All documentation now assumes that you’re using Python 3. These changes mean we’re no longer testing regularly with Python 2, so there may be breakages going forward. These should be inadvertent, but we don’t rule out the possibility of a hard cut-over in the future that permanently breaks compatibility with Python 2. We believe we retain that compatibility in this release, but this may be the last such release of the PiDP–8/I software.

  • Considerable updates to the Python library classes we’ve built our tooling atop to support all of the above. Some library behaviors and interfaces may have changed in ways that affect outside users.

  • Updated Autosetup to v0.7.0+, allowing builds under Tcl 8.7.

  • The previous release shipped with a broken version of the UCSYS.BI script on the v3d.rk05 boot image. The script is supposed to turn off forcing lower case characters to upper case in the OS/8 keyboard monitor, and re-enable the linefeed key’s command to re-echo the command line. (Cleaning up messy character echoing.) Instead linefeed would hang the keyboard monitor. This is because the script for the v3f keyboard monitor was installed on the v3d packs.

  • Fixed a bug with the MB display in Sing Inst mode when poking around with Load Add and Exam. This only affects some configurations, not all, but the fix appears benign on the non-affected ones.

  • The os8script.py class has been documented to explain the design and assist others in writing programs that can drive operation under OS/8 in SIMH using Python expect and all the layers developed above it.

  • Portability and documentation improvements.

Warren Young

unread,
Feb 15, 2021, 3:39:02 AM2/15/21
to PiDP-8
Oooops... the release tag is v20210214. (Dropped the first "1".)

John Kennedy

unread,
Feb 22, 2021, 12:53:29 PM2/22/21
to PiDP-8
Awesome!

I don’t see a link to a guide - is it possible to upgrade in place, or is it better to nuke and start again?

Warren Young

unread,
Feb 22, 2021, 4:44:11 PM2/22/21
to PiDP-8
On Monday, February 22, 2021 at 10:53:29 AM UTC-7 johntk...@gmail.com wrote:

I don’t see a link to a guide


 is it better to nuke and start again?

John Kennedy

unread,
Feb 22, 2021, 4:55:55 PM2/22/21
to Warren Young, PiDP-8
Thank you. The “front page” was what I was missing. Hope my upfront laziness and ignorance helps the next person landing on this thread! :)

Thanks SO much for all the work that has gone into this. The PiDP-8 is perhaps my favorite retro (mini) computer project. Looking forward to exploring the changes. 

On Feb 22, 2021, at 1:44 PM, Warren Young <tange...@gmail.com> wrote:


--
You received this message because you are subscribed to a topic in the Google Groups "PiDP-8" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/pidp-8/_y8UHCQnsY4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to pidp-8+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pidp-8/9dbcf166-f0c3-4906-b933-36a359de0f4bn%40googlegroups.com.

Steve Tockey

unread,
Mar 7, 2021, 3:35:29 PM3/7/21
to PiDP-8
Is this release intended to only run on Raspbian Buster? I’m trying it out on Raspbian Stretch (for other reasons) and I’m running into some anomalous behavior. One of the most obvious is that the Memory Buffer display on the front panel is not always acting like it should. If this release is not intended to work on Stretch, that could be an issue. But if it should work on Stretch as well as Buster then I think there’s a problem.

I’ll elaborate on the problem if this release is supposed to work on Stretch, otherwise I will temporarily assume it’s caused by the PiDP-8/I simulator not being intended to run on Stretch.


— steve 

Warren Young

unread,
Mar 8, 2021, 10:29:49 AM3/8/21
to PiDP-8
On Sunday, March 7, 2021 at 1:35:29 PM UTC-7 Steve Tockey wrote:
Is this release intended to only run on Raspbian Buster?

That's what it was tested atop, but I'm neither aware of any OS compatibility issues between Stretch and Buster, nor can I see that the host OS has anything to do with your actual question.
 
One of the most obvious is that the Memory Buffer display on the front panel is not always acting like it should.

That's a pretty vague problem report. What "should" it behave like, and what do you observe instead?

Ideally, you'll support your definition of "should" with chapter and verse from a relevant DEC manual.

Beware that MB doesn't behave the same across all PDP-8 models! Please don't bother quoting me a PDP-8/e manual page or tell me of your experience with PDP-8/a machines. This project is meant to replicate a PDP-8/I as well as we can given the underlying SIMH behavior, so only PDP-8/I references matter.

Another fun problem here is that some DEC manuals cover multiple PDP-8 models, and a given section of text actually refers to only one of them, and is wrong for the other model(s) nominally covered. Lacking period hardware to test against, we sometimes have to triangulate between multiple manuals to tease such discrepancies apart.

The current behavior was verified against an actual PDP-8/I machine (this one, I believe) and is checked against PDP-8/I docs. In this time of COVID, and given that it's a ~1.5 hour drive from his house, I wouldn't ask Dr. Cattey to repeat that test.

Lacking any specific info I'll take a wild stab at a guess. Try rebuilding and reinstalling after:

     $ fossil merge --backout 709bc3a7f6d7ce95

If that fixes it, then we're going to need some info from Oscar as to why that change would vary across PiDP-8/I builds.

Steve Tockey

unread,
Mar 8, 2021, 8:22:39 PM3/8/21
to PiDP-8

First of all, please don't interpret me as ever denigrating the work that you, Dr. Cattey, Oscar, and all the others are doing. I deeply appreciate the many hours all of you have invested in this.

"Ideally, you'll support your definition of "should" with chapter and verse from a relevant DEC manual."

Yes, chapter and verse follow. The relevant reference is the 1970 edition of the Small Computer Handbook which specifically describes the PDP-8/I and PDP-8/L. You can find it here:


The relevant quotes are, by page:

Page 4
------
Memory Buffer (MB) Register
The MB register is a 12-bit register that is used for all information transfers between the central processor registers and the core memory. This information can be transferred and temporarily held in the MB from the AC or PC. ... Information can be loaded into the MB from an external device during a data break or from core memory via the sense amplifiers ...


Page 5
------
Fetch (F) State
Assuming the computer is in a fully automatic, running condition; that is, the computer is continuously functioning to fetch and/or execute instructions, the PC register's contents are transferred to the MA register. ... At a time TS2, the contents of the memory appear at the the output of the memory (MEM) register (synonymous with the output from the sense amplifiers) and are transferred to the MB register. ...


Page 6
------
Execute (E) State
The Execute state its entered for all memory reference instructions except jump. During an AND, two's complement add, or increment and skip if zero instruction, the contents of the core memory location specified by the address portion of the instruction are read into the MB and the operation specified by the instruction register is performed. During a deposit and clear accumulator instruction, the contents of the AC are transferred into the MB and stored in core memory at the address specified in the instruction. ...


Page 17
-------
Table 2.1 Operator's Console Control and Indicator Functions (Cont), Second row

Control or indicator: Memory buffer indicator lights (12)

Nomenclature PDP-8/I: Memory Buffer
Nomenclature PDP-8/L: MEMORY BUFFER

Function: Indicates the contents of the MB, which usually designates the word just read or written at the core memory address held in the MA.


Page 21
-------
Manual Data Storage and Modification

c. Set the switch register switches to correspond to the data or instruction word to be stored at the address just set into the PC [MA]. Operate the deposit key and check that the MB, and therefore the core memory, contain the data in the switch register

(Later, same page)
To check the contents of any address in core memory, set that address into the PC [PC and MA] as in step b, then operate the examine key. The contents of the address are then shown by the MB register indicators. The contents of the PC are incremented by one ...


Note that I am only including page 21 in reference to the since-corrected behavior of Deposit and Exam from a few years back. I am also intentionally leaving off MB behavior in Data Break (Chapter 5) as I don't believe that ever got implemented--at least in a high-fidelity simulation manner.


"That's a pretty vague problem report. What "should" it behave like, and what do you observe instead?"

Yes, it was  vague. On purpose. I didn't want to spend a lot of time describing the problem only to have someone respond, "Yeah, that's a known limitation, it doesn't work on Stretch". Since this does not seem to be already known, here goes with detailed descriptions of expected and actual behaviors. All of these expected behaviors are consistent with the descriptions in the 1970 Small Computer Handbook and the observed behavior of the previous release.


Expectation #1
Boot OS/8. When OS/8 is in its keyboard wait loop, it is executing a pair of instructions at addresses 01207 and 01210

01207   6031        KSF
01210   5207        JMP .-1

Insofar as MB, quote, "designates the word just read or written at the core memory address held in the MA" the expectation is that MB should be an inclusive OR of 6031 with 5207, or a somewhat fuzzy 7237.

Observation #1
MB is a rock solid 0001.


Expectation #2
If one runs OS/8 BASIC, its keyboard wait loop is at 02604 and 02605

02604   6031        KSF
02605   5204        JMP .-1

Again, MB should be an inclusive OR of 6031 with 5204, or a somewhat fuzzy 7235.

Observation #2
When BASIC prints out NEW OR OLD-- after just starting up, MB is a solid 0000. With each character typed by the user, MB increments by 1. So, at the end of typing OLD DICE, we should expect to still see MB = fuzzy 7235 but instead we see MB = 0010 because "OLD DICE" is 8 (decimal) characters long.


Expectation #3
After BASIC prints its READY prompt, it is back in the same 02604-02605 keyboard wait loop so MB should again be the somewhat fuzzy 7235.

Observation #3
After the READY prompt, MB is a rock solid 7752.


Expectation #4
When one types LIST after the READY prompt following loading DICE.BA, BASIC is still in that same keyboard wait loop at 02604-02605 so MB should be the fuzzy 7235.

Observation #4
MB starts off as a solid 0000. With each character typed, MB increments by  1. So, at the end of typing LIST, we should expect to see MB = 7235 but we do see MB = 0004 because "LIST" is 4 (decimal) characters long.


Expectation #5
After exiting BASIC and returning to OS/8, we should see MB = fuzzy 7237 because of OS/8's keyboard wait loop. If one types any string of characters after the "." prompt, MB should remain the fuzzy 7237 because it's still in that wait loop. This should be true even after RUBOUT/BACKSPACE is typed.

Observation #5
After the "." prompt MB starts off as a solid 0001. After typing some random characters MB stays the solid 0001 until RUBOUT/BACKSPACE is hit, when MB goes to a solid 1223.


I hope it is obvious that these observed behaviors are completely inconsistent with expectations as set out in the 1970 Small Computer Handbook.


In case it is at all relevant, I am running Raspbian Stretch on a completely re-flashed 16GB microSD card in a Pi 2B. Stretch got fully updated after the re-flash (sudo apt-get update followed by sudo apt-get full-upgrade). I got the PiDP-8/i SIMH code using

wget -O pidp8i.tar.gz 
tar xvf pidp8i.tar.gz
cd pidp8i
./configure --lowercase=upper && make && sudo make install


I have not done the Fossil backout, sorry. But if someone could simply confirm or refute these same observations on a Buster install, it would be an easy data point.


Thanks in advance,

-- steve


Steve Tockey

unread,
Mar 8, 2021, 10:37:52 PM3/8/21
to PiDP-8

Sorry. Minor correction / clarification. I got the source code using

$ wget -O pidp8i.tar.gz https://goo.gl/JowPoC

Steve Tockey

unread,
Mar 18, 2021, 7:57:59 PM3/18/21
to PiDP-8
FYI, I re-flashed the uSD card with Buster and reload the latest PiDP-8/i release with

$ wget -O pidp8i.tar.gz https://goo.gl/JowPoC

The behavior of MB is the same as what I was getting on Stretch. So it's not an issue with what Pi OS is being run.

Steve Tockey

unread,
Nov 6, 2021, 4:58:44 PM11/6/21
to PiDP-8

Revisiting the Memory Buffer issue  from above . . .

I compared the source code from the previous release (2019?) which does have correct front panel MB behavior to this 2021 release and found the following difference in pdp8_cpu.c:

In the previous (2019?) release, starting at line 1574,

        // We need to update the LED data again.  Using IR for the MB
        // line here for same reason as above.
        set_pidp8i_leds (PC, SteadyMA, IR, IR, LAC, MQ, IF, DF, SC,
                int_req, Pause);

In the 2021 release, starting at line 1576,

        // We need to update the LED data again.  Unlike above, circa
        // line 444, we pass the final MB value, not a copy of IR, as
        // MB is settled by this point.
        set_pidp8i_leds (PC, SteadyMA, MB, IR, LAC, MQ, IF, DF, SC,
                 int_req, Pause);

When these 5 lines in the 2021 release are replaced by the 4 lines from the previous release, front panel Memory Buffer does, in fact, return to correct behavior. It would appear that the assumption that "MB is settled by this point" may not be correct.


Regards,

-- steve


Heinz-Bernd Eggenstein

unread,
Nov 9, 2021, 4:05:02 AM11/9/21
to PiDP-8
While this would fix the specific cases you observed (keyboard waiting loops), it would break others .
If we use IR instead of MB in all of them, that means that MB alsways reflects the instruction word and never something else, which works for KSF and JMP .-1 , but not for, say ISZ .

I think the biggest part of this problem problem is "upstream" in the SIMH/PDP8 code, which just ignores the MB register in most, but not all of the instruction decoding, because unless you have a front-panel attached, the MB is not important for SIMH's state machine.

Here is the part that decodes ISZ, and you can see it handles MB

/* Opcode 2, ISZ */

    case 010:                                           /* ISZ, dir, zero */
        MA = IF | (IR & 0177);                          /* dir addr, page zero */
        M[MA] = MB = (M[MA] + 1) & 07777;               /* field must exist */
        if (MB == 0)
            PC = (PC + 1) & 07777;
        break;

ok, but here is how SIMH decodes a direct JMP

    case 025:                                           /* JMP, dir, curr */
        PCQ_ENTRY (MA);
        MA = (MA & 007600) | (IR & 0177);               /* dir addr, curr page */
        if (UF) {                                       /* user mode? */
            tsc_ir = IR;                                /* save instruction */
            tsc_cdf = 0;                                /* clear flag */
            if (tsc_enb) {                              /* TSC8 enabled? */
                tsc_pc = (PC - 1) & 07777;              /* save PC */
                int_req = int_req | INT_TSC;            /* request intr */
                }
            }
        if (sim_idle_enab &&                            /* idling enabled? */
            (IF == IB)) {                               /* to same bank? */
            if (MA == ((PC - 2) & 07777)) {             /* 1) JMP *-1? */
                if (!(int_req & (INT_ION|INT_TTI)) &&   /*    iof, TTI flag off? */
                    (M[IB|((PC - 2) & 07777)] == OP_KSF)) /*  next is KSF? */
                    sim_idle (TMR_CLK, FALSE);          /* we're idle */
                }                                       /* end JMP *-1 */
            else if (MA == ((PC - 1) & 07777)) {        /* 2) JMP *? */
                if (!(int_req & INT_ION))               /*    iof? */
                    reason = STOP_LOOP;                 /* then infinite loop */
                else if (!(int_req & INT_ALL))          /*    ion, not intr? */
                    sim_idle (TMR_CLK, FALSE);          /* we're idle */
                }                                       /* end JMP */
            }                                           /* end idle enabled */
        IF = IB;                                        /* change IF */
        UF = UB;                                        /* change UF */
        int_req = int_req | INT_NO_CIF_PENDING;         /* clr intr inhibit */
        PC = MA;
        break;

uhhh... no MB . We might think that setting MB=IR at the start of the decode cycle would fix most caes, but there are still some other cases where I think MB is ignored .
E.g. is it supposed to change during indirect jumps?? But it is not:
--------------
    case 027:                                           /* JMP, indir, curr */
        PCQ_ENTRY (MA);
        MA = (MA & 077600) | (IR & 0177);               /* dir addr, curr page */
        if ((MA & 07770) != 00010)                      /* indirect; autoinc? */
            MA = M[MA];
        else MA = (M[MA] = (M[MA] + 1) & 07777);        /* incr before use */
        if (UF) {                                       /* user mode? */
            tsc_ir = IR;                                /* save instruction */
            tsc_cdf = 0;                                /* clear flag */
            if (tsc_enb) {                              /* TSC8 enabled? */
                tsc_pc = (PC - 1) & 07777;              /* save PC */
                int_req = int_req | INT_TSC;            /* request intr */
                }
            }
        IF = IB;                                        /* change IF */
        UF = UB;                                        /* change UF */
        int_req = int_req | INT_NO_CIF_PENDING;         /* clr intr inhibit */
        PC = MA;
        break;
----------------------

So in essence, I see two problems here:

1) setting the MB variable in the instruction decode code of the upstream SIMH codebase is not what one would expect it to be if MB is supposed to track the actual behaviour.

2) currently the LEDs are updated once after each instruction is executed. this creates a problem if any  lights change their status during the execution of the instruction, like MB would during an ISZ command (initailly show the instruction word, then the data written to memory. When we stop the simulation, or single-step thru the instructions, we probably want to display the lights in a constitent state at the end of the execution. for displaying  fuzzy lights during execution, one would probably want to have all states reflected, but that would mean increasing the number of rather expensive updates to the lights-on-off-stistics.

So I hope I could convince you that going back to the previous release isn't the silver buller here, and things are .... complicated!

For the moment,  as an interim "fix" rather than going back to the previous edition, I would suggest to replace this line:

IR = M[MA];                                         /* fetch instruction */

with

IR = MB = M[MA];                             /* fetch instruction */

in pdp8_cpu.c
which should bring most if not all of your expectations in your bug report inline with actual behavior, even tho this needs more work (see above).

Cheers
HB

Steve Tockey

unread,
Nov 9, 2021, 12:49:04 PM11/9/21
to PiDP-8

HB,

"I think the biggest part of this problem problem is "upstream" in the SIMH/PDP8 code, which just ignores the MB register in most, but not all of the instruction decoding, because unless you have a front-panel attached, the MB is not important for SIMH's state machine."

You are exactly correct. The SIMH implementation of the PDP-8 glosses over the Fetch-Defer-Execute cycles in real -8 hardware. Take an ISZ I PTR instruction (24xx). At the end of the Fetch cycle, MB should reflect the 24xx instruction that was read. At the end of the Defer cycle, MB should reflect the value that is in address 00xx. At the end of the Execute cycle, MB should reflect the incremented value that was pointed at by address 00xx. SIMH PDP-8 code completely glosses over this in terms of how it emulates the -8. Yes, exactly, "unless you have a front-panel attached, the MB is not important for SIMH's state machine.".

To make PiDP-8/I front panel behavior truly correct would require a fairly complete re-write of the core of the SIMH PDP-8 code. I've actually kicked around the idea but haven't taken it on yet because C is not one of my, ahem, most favorite programming languages . . .

The modification I am recommending at least makes the front panel "more correct" than the obviously totally broken behavior it has without the fix. No real -8 would ever show a solid MB value that gets incremented when a key is typed, or change from one value to another because someone typed a RUBOUT. The modification makes the front panel behavior as accurate as it can be within the limits of the underlying SIMH PDP-8 implementation.


Regards,

-- steve

Mike Katz

unread,
Nov 9, 2021, 1:43:42 PM11/9/21
to Steve Tockey, PiDP-8
Steve,

'C' is my favorite programming language.  I have often thought about writing a cycle accurate PDP-8 simulator.  Writing a stand alone instruction simulator I can do.  Added all of the IOT emulation and Integrating it into SIMH is another issue entirely.

The cycle accurate simulator would have to take into account:

1.    The Fetch, Defer & Execute phases for each instruction.
2.    Indirect Addressing
3.    Auto Increment Addressing
4.    Extended Addressing
5.    EAE instructions
6.    Basic IOT (including the IOT skip)
7.    1 cycle and 3 cycle data break.
8.    Bus signals that affect cpu cycles
9.    Differences between the different family of 8 CPUs (hopefully excluding the PDP-5)
10.  Interrupt handling

The key for the front panel is to be sure to stop after each bus cycle (not instruction phase) and update the all of the displayed registers correctly (according to the family of 8 CPU being emulated).  This does mean that some displayed registers may update multiple times during a single instruction as you have already pointed out.

Your example did not include the possibility of a different data or instruction field than the cpu is executing from.

I have the capability of analyzing the bus for the PDP-8/E though it would take a little bit of effort to correlate all of the bus signals for each instruction.  My logic analyzer is only 16 bits wide.  If we take on this project maybe we can have multiple people mapping out the actual bus behavior for each instruction and it's options.

      Mike
--
You received this message because you are subscribed to the Google Groups "PiDP-8" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pidp-8+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pidp-8/79a0d38a-c5fe-4bd3-9b04-8f82a74267d4n%40googlegroups.com.

Warren Young

unread,
Nov 9, 2021, 2:24:51 PM11/9/21
to PiDP-8
On Tuesday, November 9, 2021 at 11:43:42 AM UTC-7 justme...@gmail.com wrote:

a cycle accurate PDP-8 simulator

Since the purpose behind this would be accuracy and fidelity to actual hardware, I'd be willing to give up on efficiency up to the point of being slower than actual hardware.

As it stands, we achieve something like 7-8 MIPS on a Pi 3, roughly 24 times faster than a PiDP-8/I. We achieve that in part with the incandescent lamp simulator by passing an approximation of the full data between the CPU and display threads. If you send info about each and every instruction to the display thread, the simulation rate drops to about 1 MIPS, or only about 3x faster than actual hardware.

I think it's part of this wish for extreme accuracy to take that hit, which then means you've only got about a 3x margin for doing the cycle-accurate parts atop this, and then only if you consider the Pi 3 to be a hard base.

If fully expect this plan will be unworkable on a Pi Zero, Pi B+, or Pi 2 class system.

If this plan will require a Pi 4, I suspect it's doomed before it begins.

An interesting middle ground might be the new Pi Zero 2 W, which is *roughly* Pi 3 equivalent from a CPU standpoint. Even so, I'd rather this plan didn't require everyone to buy new Pi boards.
 
 Writing a stand alone instruction simulator I can do.  Added all of the IOT emulation and Integrating it into SIMH is another issue entirely.

A completely rewritten simulator isn't likely to displace the current one. There's just too much useful stuff in the SIMH core and in the current PDP8 simulator to just toss it all in the name of accuracy, unless you're proposing to replace all of it.

Instead, what if we just fork the pdp8_cpu.c module entirely but continue to rely on the rest of SIMH?

There will probably be too many diffs to make integrating the changes upstream practical, and there's little point in doing so if the only way to see the difference is to have a front panel. Changing the code to call into one "sim_instr()` loop versus another won't be too horrid, though, I think.

Another factor to beware of is that we currently use the SING_STEP key for all of the extended front-panel functionality. Presumably part of the desire here is to allow single-stepping mode to work as on the actual hardware, so all of that functionality will have to be done differently. Someone proposing such a mode should think thought how they want those functions to be handled. If it amounts to "SSH in and attach to the simulator..." you've got to realize you'll be carving away big chunks of the user community.
 
The cycle accurate simulator would have to take into account:

11. Peripheral delays?

I was just looking at an ADC peripheral that takes 20 µs to take a sample and then another 3 to do the conversion. Shouldn't such things be reflected into the simulator, if period-accurate timing is to be maintained?

How about things like seek times on storage peripherals?

HB Eggenstein

unread,
Nov 9, 2021, 3:03:30 PM11/9/21
to PiDP-8
So what about taking this one step at a time:

First step: make sure MB is correct at least at the end of each instruction execution, and ignore MB state changes during execution phases for now.

This would ..

-  require ca 60 (+/- a few)  lines of code to be  changed in pdp8_cpu.c (and carefully reviewed), already tedious but doable in time for, say, an early 2022 release latest
-  come at no significant performance penalty
-  make sure the LED display doesn't insult PDP-8 gurus during single-instruction-step mode
-  would be an incremental investment that doesn't have to be undone when later on we decide to go further and simulate the phases for instruction execution, including LED panel updates.

Thoughts?
HBE

Warren Young

unread,
Nov 9, 2021, 3:24:24 PM11/9/21
to PiDP-8
On Tuesday, November 9, 2021 at 1:03:30 PM UTC-7 hbe....@gmail.com wrote:
-  make sure the LED display doesn't insult PDP-8 gurus during single-instruction-step mode

I think that's the core problem right there. The current MB display handling has been fought over for years, and I think we're only now seeing why: none of the prior modes is correct, because none of them capture the full sense of what this register actually does.

If you think you can remedy that in 60 SLOC, go right on ahead.

If you implement "EXAM MB" at the SIMH console, you could then upstream the improvement, since you can see it without the front panel.

(That's right: neither MA, MB, nor IR are exposed as CPU registers in the current simulator. See §2.1 in the SIMH PDP-8 manual.)

Steve Tockey

unread,
Nov 9, 2021, 4:04:41 PM11/9/21
to PiDP-8

All,
Admittedly the "fix" I offered really only treats a symptom. What confuses me is how MB gets set to such strange values in the first place, e.g., a count of the number of characters typed. I couldn't find anything obvious. A possibility might be that a pointer that should be pointing somewhere else somehow gets set to pointing to the MB instead.

Anyway, I could get behind an effort for a more accurate PDP-8 simulator. I'm not sure it would need to go all the way down to actual bus signals, I think it would be sufficient to just have accurate end-of-state (Fetch, Defer, Execute) displays on the front panel. And given how much SIMH has to be throttled down to make it comparable to a real -8 in speed, I would not be worried about a cycle-accurate simulation being slower than real hardware.

I also hope it would be do-able in a way that doesn't require re-implementing all of the IO device simulators. For example, I don't think the RK05 simulator is accurate in terms of real Data Break but I could live with that still being inaccurate.


-- steve


HB Eggenstein

unread,
Nov 9, 2021, 4:59:32 PM11/9/21
to PiDP-8
> What confuses me is how MB gets set to such strange values in the first place, e.g., a count of the number of characters typed

The explanation is this: in the SIMH code that implements the actual execution of instructions, some of the instructions (like ISZ) set the MB variable to a meaningful value at the end of the instruction. But most simulated instructions actually completely ignore the MB variable, they don't touch it at all. So what ends up on the LED panel is the state of MB set by some previous instruction that falls into the first category. This could be many instructions in the past, and when the current loop executing has only instructions that don't set MB, it stays that way "forever".

> If you think you can remedy that in 60 SLOC, go right on ahead.

OK, I'll try, but in the end we will need people to check this very, very carefully. That's not the part of the code where you want to have a silly typo or cut-and-paste stupidity :--)

Cheers
HB

Gordon Henderson

unread,
Nov 9, 2021, 5:11:26 PM11/9/21
to PiDP-8
On Tue, 9 Nov 2021, Warren Young wrote:

>> a cycle accurate PDP-8 simulator

> If fully expect this plan will be unworkable on a Pi Zero

Pi Zero solution in C:

https://www.youtube.com/watch?v=qFt_9LsAgso

The Zero is running at 1Ghz. Plenty of cycles left over to have a
reasonable attempt at ILS...

Gordon

Mike Katz

unread,
Nov 9, 2021, 5:58:42 PM11/9/21
to Steve Tockey, PiDP-8
Is the behavior of the MA, MB and other processor registers and signals the same for all of the "family of 8" models?

I know that some instructions (especially the micro instructions) behave differently from system to system.  Does the same hold true for the bus signals?

I know that not all of the front panels have the same indicators.

Here is a table of what indicators are on which front panel.  Are we going for accuracy to emulate each front panel or just the panel for the PiDP-8/I?

Please feel free to send me corrections as most of this was inferred from pictures or my PiDP-8/I and PDP-8/E actual panels.

Indicator

PDP-8

PDP-8/S

PDP-8/I

PDP-8/L

PDP-8/E

PDP-12

Memory Address

12

12

12

12

12

12

Program Counter

12

12

12

 

 

12

Memory Buffer

12

12

12

12

12 (BUS)

12

Memory Data

 

 

 

 

12 (MD)

 

Accumulator

12

12

12

12

12 (AC)

12

Multiplier Quotient

12

 

12

 

12 (MQ)

12

Step Counter

 

 

5

 

 

 

Instruction Field

3

3

3

 

3 (STATUS)

5

Data Field

3

3

3

 

3 (STATUS)

5

AND

1

1

1

 

 

 

TAD

1

1

1

 

 

 

ISZ

1

1

1

 

 

 

DCA

1

1

1

 

 

 

JMS

1

1

1

 

 

 

JMP

1

1

1

 

 

 

IOT

1

1

1

 

 

 

OPR

1

1

1

 

 

 

Fetch

1

1

1

1

1 (STATE)

1

Execute

1

1

1

1

1 (STATE)

1

Defer

1

1

1

1

1 (STATE)

1

Word Count

 

 

1

1

 

1

Current Address

 

 

1

1

 

1

Break

1

1

1

1

1 (STATE)

1

Pause

1

1

1

 

1 (STATE)

 

Run

1

1

1

1

1

1

Ion

1

 

1

1

1 (STATUS)

1

Link

1

 

1

 

1 (STATUS)

 

IR0

 

 

 

 

1 (STATE)

 

IR1

 

 

 

 

1 (STATE)

 

IR2

 

 

 

 

1 (STATE)

 

MD DIR

 

 

 

 

1 (STATE)

 

DATA CONT

 

 

 

 

1 (STATE)

 

SW

 

 

 

 

1 (STATE)

 

BRK PROG

 

 

 

 

1 (STATE)

 

GT

 

 

 

 

1 (STATUS)

 

INT BUS

 

 

 

 

1 (STATUS)

 

NO INT

 

 

 

 

1 (STATUS)

 

UM

 

 

 

 

1 (STATUS)

 

INDEX

 

1

 

 

 

 

END

 

1

 

 

 

 

PARITY

 

1

 

1 (PAR)

 

 

PARITY ERROR

 

1

 

 

 

 

INSTRUCTION

 

 

 

3

 

12

PROT

 

 

 

1

 

 

E2

 

 

 

 

 

1

INT

 

 

 

 

 

1

TB

 

 

 

 

 

1

8 Mode

 

 

 

 

 

1

LINC MODE

 

 

 

 

 

1

I/O PAUSE

 

 

 

 

 

1

INT PAUSE

 

 

 

 

 

1

AUTO

 

 

 

 

 

1

TRAP

 

 

 

 

 

1

SKIP

 

 

 

 

 

1

FLO

 

 

 

 

 

1

 

Number in columns is number of indicators.

PDP-12 Specific indicator.  Not used in PDP-8 mode.

PDP-8 uses 3 of the 5 indicators.

PDP-8/E dial position indicated in parenthesis.

 







Do we only care about the ones that are displayed on the PiDP-8/I
--
You received this message because you are subscribed to the Google Groups "PiDP-8" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pidp-8+un...@googlegroups.com.

Mike Katz

unread,
Nov 9, 2021, 7:14:27 PM11/9/21
to Gordon Henderson, PiDP-8
I was planning on doing exactly that on the pico but it seems that
someone beat me to it.  Damn😁

I will check it out.

Mike Katz

unread,
Nov 9, 2021, 7:29:37 PM11/9/21
to Gordon Henderson, PiDP-8
I jumped the gun.  That is not a Raspberry Pi PIco version of the PDP-8.

The Pico is a dual core 133MHz microprocessor.

1 core for code emulation and 1 core for the incandescent light emulation.

Another thought I had for this would be a new front panel design with
the same switches but using addressable LEDs.  With the PIO processor on
the Pico you could drive all of the LEDs with just 2 Pins and update
them at very high speeds.  Another option for addressable LEDs would be
to use 1 GPIO for each row and drive the GPIOs with DMA.

It would not be that difficult to write a PDP-8 simulator that is bus
cycle (not timing cycle) accurate for the PiPD-8/I.  We include hooks
for displaying internal states in the emulator.

Once we have a cycle accurate emulator running then we can implement the
front panel indicators in the hooks.

The difficulty comes in in simulating peripherals on a system without an
OS.  For mass storage I was thinking of adding a micro SD card and only
emulating the RX8E & RK8E.  DECtape gets too complicated.

Adding the ability for custom IOT drivers  becomes just jump table with
8 entries for each device.



The Raspberry Pi Zero

Simulating the Data Brake of the RK8E and

On 11/9/2021 4:11 PM, Gordon Henderson wrote:

Mike Katz

unread,
Nov 10, 2021, 1:35:29 PM11/10/21
to Steve Tockey, PiDP-8
If we are going to architect the cycle accurate simulator we need to figure out what each of the registers and indicators should be after each state/phase/step of each instruction from a hardware standpoint.

For example:  ISZ I 0010

    1.    Enter Fetch State   
    2.    Fetch instruction
    2.    Instruction decode
    3.    Enter Defer State
    4.    Get data at address at 0010
    5.    Increment 0010 (Does this happen here)
    6.    Enter Execute State
    7.    Get Data at address loaded in step 4
    8.    Increment data
    9.    Store data back at address loaded in step 4
    10.  Set skip flip flop if data == 0

There may be more steps in hardware than I listed above.

For each of these steps we need to know what registers (internal and external) and front panel indicators are affected at each step.

IOTs, Interrupts and Combined Microinstructions get even more complicated in terms of steps, their order and how they affect the registers and indicators.

Different PDP-8s will function differently for certain instructions as well.

If we can determine all of the steps and their effects for each and every instruction for each CPU then we can start writing the emulator.

We only need to reflect the result at points where the PDP-8 CPU would stop during normal operations with the appropriate Single Step, Single Instruction and Halt switches in the active (down) state.  This will differ between different PDP-8 CPUs.

This might simplify the architecture.

However, if we want to truly emulate the bus, we need to accurately represent each bus cycle even if a single step incorporates multiple bus cycles.

If we write the emulator first we run the risk of missing something that we don't realize the hardware is doing.
--
You received this message because you are subscribed to the Google Groups "PiDP-8" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pidp-8+un...@googlegroups.com.

Steve Tockey

unread,
Nov 10, 2021, 3:39:09 PM11/10/21
to PiDP-8

"5.    Increment 0010 (Does this happen here)"

Yes, the increment of an Autoindex register (read-modify-write) happens in the Defer state.


"For each of these steps we need to know what registers (internal and external) and front panel indicators are affected at each step"

There are various more or less formal specifications of this in the DEC documentation.


"IOTs, Interrupts and Combined Microinstructions get even more complicated in terms of steps, their order and how they affect the registers and indicators."

I'm not sure I get your point here. My goal would be to have the front panel reflect realistic status as of the end of each Fetch, Defer, or Execute cycle. Ideally, we would be able to re-activate the Sing Step switch on the PiDP-8/I front panel and have it look as it would on a real machine.


"Different PDP-8s will function differently for certain instructions as well."

True, but the number of differences is fairly small. If this effort does take off, one should pick a reference model of -8 and build to that. In truth, the current SIMH PDP-8 simulation is an 8/e. It's just hiding behind an -8/I front panel. If it were up to me, I would stick with the 'execute as an 8/e but hide behind an -8/I front panel' idea.


"We only need to reflect the result at points where the PDP-8 CPU would stop during normal operations with the appropriate Single Step, Single Instruction and Halt switches in the active (down) state.  This will differ between different PDP-8 CPUs."

Differ in the sense of, for example, what 600x, 7002, 7014, 7016, and EAE Mode B instructions do? This would be solved by picking the reference model. Or, do you mean something else?


"However, if we want to truly emulate the bus, we need to accurately represent each bus cycle even if a single step incorporates multiple bus cycles."

FWIW, I don't see any value in a bus cycle-level emulation.






Mike Katz

unread,
Nov 10, 2021, 4:49:31 PM11/10/21
to Steve Tockey, PiDP-8
Steve,

I agree with you.

Please see my comments in orange below.


On 11/10/2021 2:39 PM, Steve Tockey wrote:

"5.    Increment 0010 (Does this happen here)"

Yes, the increment of an Autoindex register (read-modify-write) happens in the Defer state.
Thank you for confirming this.



"For each of these steps we need to know what registers (internal and external) and front panel indicators are affected at each step"

There are various more or less formal specifications of this in the DEC documentation.
I figure that most of this is documented somewhere.  From a development stand point having all of the instruction details combined into one document before hand, that we all can follow and agree on will make the software development, integration and testing much easier



"IOTs, Interrupts and Combined Microinstructions get even more complicated in terms of steps, their order and how they affect the registers and indicators."

I'm not sure I get your point here. My goal would be to have the front panel reflect realistic status as of the end of each Fetch, Defer, or Execute cycle. Ideally, we would be able to re-activate the Sing Step switch on the PiDP-8/I front panel and have it look as it would on a real machine.

Are all of the relevant stages of IOTs, Interrupts and the Microinstructions also documented.  For example a lot happens when an interrupt occurs (and more if there is an M837 Extended Memory/Time Share board in the system).  What is the CPU state between when the interrupt request is asserted and the interrupt handler starts executing?
 

"Different PDP-8s will function differently for certain instructions as well."

True, but the number of differences is fairly small. If this effort does take off, one should pick a reference model of -8 and build to that. In truth, the current SIMH PDP-8 simulation is an 8/e. It's just hiding behind an -8/I front panel. If it were up to me, I would stick with the 'execute as an 8/e but hide behind an -8/I front panel' idea.
I think we should aim for the PDP-8/I first since the front panel looks like a PDP-8/I.  We can add the others as some kind of configurable option after the code is finished.  We should provide for this during the writing of the code to keep implementing the other CPUs easier.



"We only need to reflect the result at points where the PDP-8 CPU would stop during normal operations with the appropriate Single Step, Single Instruction and Halt switches in the active (down) state.  This will differ between different PDP-8 CPUs."

Differ in the sense of, for example, what 600x, 7002, 7014, 7016, and EAE Mode B instructions do? This would be solved by picking the reference model. Or, do you mean something else?
Exactly!



"However, if we want to truly emulate the bus, we need to accurately represent each bus cycle even if a single step incorporates multiple bus cycles."

FWIW, I don't see any value in a bus cycle-level emulation.
As someone who appreciates the elegance of the PDP-8 and who is designing a hardware remote front panel/bus analyzer/hardware breakpoint debugger board how each cycle works on the PDP-8/E is of specific interest to me.  I keep threatening to do a gate accurate FPGA implementation of the PDP-8/E so I can understand each and every flip flop at each and every bus cycle.






--
You received this message because you are subscribed to the Google Groups "PiDP-8" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pidp-8+un...@googlegroups.com.

Heinz-Bernd Eggenstein

unread,
Nov 12, 2021, 5:08:34 PM11/12/21
to PiDP-8
So how best to get this idea turned into working software?

The current implementation from SIMH in file pdp8_cpu.c , function sim_instr(),  is mainly a big long
switch() .. case .. block. The granularity of the case blocks is , for example for the memnory reference instructions,  opcode and adressing mode, so for example
AND, zero page direct
AND, zero page indirect
AND, current page direct
AND, current page indirect

all have their own "case" block, and each "case" block handles FETCH, DEFER and EXECUTE phases all in one go with a special treatment for auto-indexing where applicable in each of the affected case blocks, so there is a lot of code duplication and even more duplication if we insert code to give the panel a chance to sample the register state after each of FETCH, DEFER, EXECUTE.
This code structure is not well suited for what we have in mind.

So ....my proposal would be to
*  completely forget about the SIMH functionsim_instr()  and leave that one unchanged in the code
* add a new function sim_instr_pdp8i (and try to push this upstream to SIMH but if they don't want it, fine, then it's one block of code we'll have as a pidp8i specific patch)
  *  this sim_instr_pdp8i would be activated by a SIMH bootscript option  (like with the PDP11 where you can switch between variants of the  11/xx )
  * sim_inst_pdp8i would have a different structure:
    it would have one code block each for the FETCH, DEFER and EXECUTE phases, hopefully reducing code duplication and making things easier to review.
    Within those blocks, different processing paths for the different opcodes would then be handled by switch-..case..like constructs
 * Up to here the changes would be ok for inclusion into SIMH upstream
* For pidp8i front panel support, the LEDs state sampling gets a chance to be called after each of the substates FETCH, DEFER, EXECUTE, using the
  current mechanism of sampling only every (N-th +/- some dithering value) time. This way we would not only have a more realistic display of MB  but we would also finally give the DEFER light a chance to light up.

Thoughts?
hb

Steve Tockey

unread,
Nov 15, 2021, 1:01:53 PM11/15/21
to PiDP-8

hb,

"So how best to get this idea turned into working software?

The current implementation from SIMH in file pdp8_cpu.c , function sim_instr(),  is mainly a big long switch() .. case .. block."

Note that I am far, far away from home on a business trip and don't have convenient access to the PDP-8 SIMH source code. On the assumption that function sim_instr() simulates execution of a single instruction then returns, I would approach it roughly as follows (in a very pseudo-code-y way):

    // simulate the Fetch state
    sim_fetch()
    update_front_panel_lights()
    if( single_step_switch_is_set )
        wait_for_cont_switch()

    // is it a Memory Reference Instruction (MRI)?
    if( 0 <=  op_code <= 5 )

        // yes, it's a MRI. Is it indirect addressing?
        if( memory_buffer[ 4 ] == 1 )
            // yes, it's indirect. Simulate the Defer state
            sim_defer()
            update_front_panel_lights()
            if( single_step_switch_is_set )
                wait_for_cont_switch()

        // simulate the Execute state
        sim_execute()
        update_front_panel_lights()
        if( single_step_switch_is_set or single_instruction_switch_is_set )
            wait_for_cont_switch()


Function sim_fetch() would handle all OPR combinations and all IOT instructions as well as the Fetch state actions for MRIs. This could be a awitch-case as follows:

    memory_address = program_counter
    program_counter++
    inst_register = memory_buffer = Memory[ inst_field + memory_address ]
    switch op_code
        case OPR: // do all of the decoding and executing of the various OPR combinations here
                  break
        case IOT: // do all of the decoding and executing of the various IOTs here
                  break
        else:     // do the fetch-state part of a MRI. Is it current page or zero page?
                  if( inst_register[ 4 ] == 0 )
                      // it's zero page
                      memory_address[ 0 .. 4 ] = 0
                  memory_address[ 5 .. 11 ] = inst_register[ 5 .. 11 ]
                  break


Function sim_defer() would handle the indirect addressing part of a MRI

    if( 0010 <= memory_address <= 0017 )
        Memory[ inst_field + memory_address ]++
    memory_address = memory_buffer = Memory[ inst_field + memory_address ]


Function sim_execute() would handle the execution part of a MRI. This would be a switch-case with one case block for each op code, e.g.,

    // IIRC, direct addressing goes to the current inst_field, indirect goes to the current data_field
    if( inst_register[ 4 ] == 0 )
        current_field = inst_field
    else
        current_field = data_field
    switch op_code
        case AND: AC_register = AC_register && Memory[ current_field + memory_address ]
                  break
        case TAD: AC_register = AC_register + Memory[ current_field + memory_address ]
                  break
        case ISZ: Memory[ current_field + memory_address ]++
                  if( Memory[ current_field + memory_address ] == 0 )
                      program_counter++
                  break
        case DCA: Memory[ current_field + memory_address ] = AC_register
                  AC_register = 0 
                  break
        case JMS: inst_field = pending_inst_field  // in case this JMS follows a CIF
                  Memory[ inst_field + memory_address ] = program_counter
                  program_counter++
                  break
        case JMP: inst_field = pending_inst_field  // in case this JMP follows a CIF
                  program_counter = memory_address
                  break

There could easily be problems above. I seem to recall that a JMP direct is actually completed in the Fetch state alone but I could be mistaken. Anyway, I hope this gets a possible general structure across. The gory details to make it correct could be worked out later.


Cheers,

-- steve


Heinz-Bernd Eggenstein

unread,
Nov 15, 2021, 7:54:38 PM11/15/21
to PiDP-8
Thanks for making this detailed pseudo code.

Yes that is the structure I had in mind, tho it's of course much more detailed in reality, like the MB and MA registers needs to be simulated which is the thing that started the whole discussion about a re-implementation in the first place. Altogether, with handling of interrupts, microprogramming of instructions, EAE instructions and the time sharing option logic, a complete rewrite is about 900 lines of code, mostly copy-and-paste from existing code but restructuring it the way you outlined.

But there are a few design decisions that need to be made that can be disciussed based on the pseudo code.

1) Do we really want to be able to use the single step switch? We would lose all the extra functions that are now associated with it (mounting mass storage media & restarting). Is being aple to single-step thru fetch, defer, execute  more useful to users than those functions? The main motivation for the re-write seemed to be to get a more realistic display of the MA and especially MB LEDs both in "free-running" and single-instruction mode, not necessarily to be able to single step, I thought. And the single-step mode would not just entail to wait for CONT, you would also have to deal with Exam and DEPOSIT and what that does to the state machine. I think it's a can of worms.

2) There are a few instructions currently implemented in SIMH that are kind of odd and deviate from the scheme you expressed in the pseudo code, e.g. the EAE instruction in "Mode B" that allow indirect addressing, so I guess they go thru a DEFER state even tho they are OPR instructions,
BUT
I understand "Mode B" EAE instructions were not impmented for the 8i's EAE, but are in SIMH because because it simulates an 8e....so should we be "strictly-8i" and have the new implementation support just the 8e instructions, or let it cover the 8i EAE as well (e.g. because  some of the codes curated in the pidp8i software may actually need it)??

Cheers
HB

Warren Young

unread,
Nov 15, 2021, 8:12:55 PM11/15/21
to PiDP-8
On Monday, November 15, 2021 at 11:01:53 AM UTC-7 Steve Tockey wrote:

I am far, far away from home on a business trip and don't have convenient access to the PDP-8 SIMH source code.

You can post here but you cannot browse the PDP8 subdirectory in the SIMH source repo?
 
On the assumption that function sim_instr() simulates execution of a single instruction then returns...

If it did that, it would drop in performance by roughly an order of magnitude. That's a measurement, not a guess.

In most cases, the cost of a function call is negligible, and inlining may eliminate the rest of the cost if the compiler's optimization stage can find a way to justify doing so, but neither is applicable here.

A tiny cost taken millions of times per second becomes a substantial cost. This is why sim_instr() is structured as one huge switch statement even though this is unjustifiably bad style in most cases: it makes the simulator performant by avoiding all the stack pushing and popping associated with function call frames, non-locality of code execution associated with jumping around in memory between compilation units, etc.

Inlining can fix such problems, but it usually doesn't happen across compilation modules, and here it's a case of the SIMH main interaction loop in scp.c calling into the PDP-8 CPU core, so traditional C optimizers can't even see that inlining might be possible, much less advisable. There are optimization strategies like PGO and LTO that can fix this, but we don't attempt to build the simulator with these techniques as they're costly at build time, and building on the Pi is slow enough already.

Bottom line, sim_instr() is ugly on purpose, with solid justification.

I've refrained from pointing these things out until now because some of the proposals up-thread admit of better optimization possibility. Putting all of the code into a single module would help tremendously, for instance.

    update_front_panel_lights()

The same logic above applies: that's in yet another module, so inlining doesn't occur, and a tiny cost taken millions of times per second becomes a big cost. Here the cost is totally unjustifiable since the PiDP-8/I front panel display is a human visual output device, so millions of updates per second are visually indistinguishable from any practical ideal you can come up with.

We can reasonably argue about whether 24 or 100 or 240 or whatever updates per second is "enough," but millions is certainly too many.
 
    if( single_step_switch_is_set )
        wait_for_cont_switch()

It takes a rather expensive GPIO scanning loop to determine that. Since switch changes are another case of human perception times interacting with software iteration loops, it's unjustifiable to pay that cost on each CPU instruction. Scanning the switches at the same time we update the display is fast enough for the human to perceive each switch change as "instant."

As for the rest of your pseudocode, I think you should study what the simulator already does than rewrite it blind. Most of what you write about already occurs, so responding in that context is more likely to provide substantial insight.

I seem to recall that a JMP direct is actually completed in the Fetch state alone but I could be mistaken.

I expect it differs between Family of 8 types as well.

Warren Young

unread,
Nov 15, 2021, 8:36:11 PM11/15/21
to PiDP-8
On Monday, November 15, 2021 at 5:54:38 PM UTC-7 hbep...@googlemail.com wrote:

1) Do we really want to be able to use the single step switch?

It could be a build-time choice. All of those functions are possible via SSH. To some, that's a reasonable alternative. To others, you lose them approximately at "Just SSH in and say..."
 
the single-step mode would not just entail to wait for CONT

I took that idea in the pseudocode less literally: we'd want to save the fact that we're in single-step mode on each GPIO scan — presumably still done on each front panel LED update, as now — and modify the CPU instruction decoding according to the last known value of that flag.

Perhaps there are two decoding loops: one in single-step mode, and one in single-instruction and free-running mode? Intermixing them sounds like a great way to blow the CPU cache: code rarely run intermixed with code potentially run millions of times per second.

Of course, now this means you have two simulators to keep in lock-step to avoid inconsistency...
 
I think it's a can of worms.

It will be up to whoever implements this (not me) to choose how far down that slippery slope they'll permit themselves to slide before they swing the ice-axe. Someone sufficiently insane could take this down to the level of a software FPGA only to be outdone by someone who writes a software FPGA simulator to capture all of the RFI and signal coupling and such as well in order to drive a physically-accurate sound signal for the MUSIC.PA case.

2) There are a few instructions currently implemented in SIMH that are kind of odd and deviate from the scheme you expressed in the pseudo code, e.g. the EAE instruction

Let us not forget that things like this are IOT instructions handled inline as if they were CPU instructions, even though in the actual device they went out on the bus to be handled by a peripheral. This is another case of purposeful inlining in the name of performance.
 
I understand "Mode B" EAE instructions were not impmented for the 8i's EAE

True.
 
SIMH...simulates an 8e

Closer to a PDP-8/a without the 128 kWord memory extension feature.

And you can find people who will argue with that characterization, too, and they'll be somewhat justified because the current simulator is a mongrel.

....so should we be "strictly-8i" and have the new implementation support just the 8e instructions

If you take my idea of two simulator decoding loops, then the single-step mode at least should behave that way, else it will differ from real hardware when you go to verify your implementation down at the museum.

The reason the current simulator is a mongrel is because they're not interested in such details: they want a best-of-all-worlds simulator that handles all cases simultaneously to the extent possible. It can't let you simulate anything that causes an IOT conflict for instance, but it will allow things that never occurred in real hardware: for instance. running PDP-8/a era EAE instructions from a Straight-8 era fixed-head disk.

Warren Young

unread,
Nov 15, 2021, 9:08:12 PM11/15/21
to PiDP-8
On Monday, November 15, 2021 at 6:12:55 PM UTC-7 Warren Young wrote:
Scanning the switches at the same time we update the display is fast enough for the human to perceive each switch change as "instant."

A detail just occurred to me. Line 141 of gpio-common.c.in:

     static const ms_time_t debounce_ms = 50;    // time switch state must remain stable

If you want debouncing — and you really really do want debouncing — you can't get much more than these ~200 switch changes per second anyway, so checking millions of times per second is pointless.

Steve Tockey

unread,
Nov 15, 2021, 11:11:09 PM11/15/21
to PiDP-8

"You can post here but you cannot browse the PDP8 subdirectory in the SIMH source repo?"

It's clearly not a matter of technology. I freely admit to just being lazy. I'm working long days trying to recover a critical software project for certain country's Ministry of Finance and I was tired. I don't carry the link to the SIMH source repo on my work laptop and I didn't want to spend the time trying to craft the right search criteria to avoid all of the chaff. I thought HB deserved a more timely reply than he was getting, even if it was less than 100% complete. That's all.


Re: Inlining--yes, that was definitely in the back of my mind but I wanted to first make the structure of the code crystal clear. IMHO posting an inlined version would tend to obscure the general intent, which is far more important at this point. Inlining later is a trivial exercise.


"We can reasonably argue about whether 24 or 100 or 240 or whatever updates per second is "enough," but millions is certainly too many."

I totally agree. In fact, the more I think about it, the more I would recommend separating the CPU emulation code as much as possible from the front panel IO code, possibly having them in separate threads that communicate only through a shared memory representation of the relevant registers and switch statuses.


"As for the rest of your pseudocode, I think you should study what the simulator already does than rewrite it blind."

I kind of agree, but in the end seeing what's already there will be mandatory at some point. I do think there's some value to thinking about what a totally greenfield re-implementation might look like so that possible opportunities for improvement might be found.




Steve Tockey

unread,
Nov 15, 2021, 11:19:40 PM11/15/21
to PiDP-8

"Do we really want to be able to use the single step switch? We would lose all the extra functions that are now associated with it (mounting mass storage media & restarting)."

I do. I don't think those extra functions are lost, it's just a matter of finding different ways of signaling them. For instance, we might consider mapping the "switch operating systems" to a combination of Start and Load Addr at the same time. "Mount USB Media" could be mapped to Start and Exam at the same time, etc. It should be entirely possible to have both cycle-level emulation and retain the extra functions.

"I understand "Mode B" EAE instructions were not impmented for the 8i's EAE, but are in SIMH because because it simulates an 8e....so should we be "strictly-8i" and have the new implementation support just the 8e instructions, or let it cover the 8i EAE as well (e.g. because  some of the codes curated in the pidp8i software may actually need it)??"

Correct. Mode A is exactly what the -8/I does natively (but only when EAE is installed). Mode B was introduced in the -8/e, Mode A was kept for backwards compatibility so -8/I code would run on an -8/e. I would vote for emulating an -8/e or -8/a under the covers and just hide it behind an -8/I panel otherwise someone who wanted to run code with Mode B instructions would be out of luck. This is the way it's done now, anyway. I suppose one could look at the compilation options mechanism that's already there and add "emulate a pure -8/I vs. emulate an -8/e or later" option.



Ian Schofield

unread,
Nov 16, 2021, 12:02:53 PM11/16/21
to PiDP-8
Dear Steve,

 I agree with you thought exactly in that the simh build does make things a bit difficult to get precise timing and by extension, the light show.
 I thought I would have a pop with the Pi Pico and just finished a minimal implementation running OS/8 from the flash memory.
 It is a VisualGDB project using PicoProbe which will clearly need a rebuild for Linux.
 The purpose was indeed to put the light code into the other core and see how it goes.
 Similarly, for speed requirements, the simulation code need to be cut down as much as possible.
 I have attached the origin of the pico code which is a stand alone PDP8 sim. Not surprisingly, it is very similar to your pseudo code as above.
 Having looked at this from the timing point of view, this still need some optimization as even this code is marginal with a 200MHz clock in the Pico.

Regards, Ian.
Nano8.cpp

Mike Katz

unread,
Nov 16, 2021, 1:21:49 PM11/16/21
to Ian Schofield, PiDP-8
Are you over clocking your pico to 200MNHz.  What kind of cooling do you need to do that.

I believe the standard clock on the Pico is 133MHz.
--
You received this message because you are subscribed to the Google Groups "PiDP-8" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pidp-8+un...@googlegroups.com.

Ian Schofield

unread,
Nov 17, 2021, 1:32:09 PM11/17/21
to PiDP-8
Hi,

 No cooling needed, just feels very slightly warm. Apparently you can go up to 420MHz but then the flash can't keep up. The dissipation at 420 is around 300mW so it doesn't get too hot!!

Mike Katz

unread,
Nov 17, 2021, 1:43:42 PM11/17/21
to Ian Schofield, PiDP-8
That's good to know because I'm designing the RP2040 into a test design at work.

Thank you.

I was thinking of doing exactly what you are doing with the Pico.  I would love to see your code at some point.

I was thinking of implementing the IOTs as registerable drivers so that different devices can be emulated.  I have no idea of the SIMH internals so I'm just thinking about what would be most efficient and usable.

   Mike

Ian Schofield

unread,
Nov 17, 2021, 4:26:55 PM11/17/21
to PiDP-8
Dear Mike,

You are welcome. I am sort of impressed with this board ... good for real-time stuff.
Still think that the PiZero W is the tiny (size) option of choice. Might try RTOS on this.
Code is very close to nano8.cpp which I posted on this thread yesterday.
I am still working on this ... mainly documentation. I have attached the undocumented source for this. You should be able to work out what is happening.
Wow, what an enormous include file. This is a 128Kb DF32 OS8 disk image (2 platters). This starts off in ROM and then runs from a memory image (due to LFS being v slow with large random access files).
It is declared 'const'. Make sure your linker puts it onto the FLASH.rodata segment or you will run out of RAM!!!
BW, Ian.
df32_os8_2p.dsk.h
Pico_OS8.c

Mike Katz

unread,
Nov 17, 2021, 5:41:33 PM11/17/21
to Ian Schofield, PiDP-8
Have you seen this from pimoroni?

https://shop.pimoroni.com/products/tiny-2040

It doesn't get much smaller than this.

Ian Schofield

unread,
Nov 18, 2021, 1:06:34 PM11/18/21
to PiDP-8
That is amazing.
In the meanwhile, the PIO module might be worth a look to drive the LEDs without using the CPU????

Mike Katz

unread,
Nov 18, 2021, 3:25:59 PM11/18/21
to Ian Schofield, PiDP-8
I have thought about using the PIO to drive a strand of addressable color LCDs to simulate the incandescent lamps.  It should be easier to do than pwm the leds.  All you need to do is slowly change the colors.

William Cattey

unread,
Nov 18, 2021, 9:10:38 PM11/18/21
to PiDP-8
I'm behind in reading this very interesting thread. I wanted to respond to this particular point, however.

In the most recent release, I had to craft a nasty patch to U/W FOCAL because the code line we currently have is EAE only, but which assumed it was running on a PDP-8/i.  When FOCAL was started after running FORTRAN IV, the EAE was left in mode B which caused FOCAL to go nuts.  My nasty patch, in some space reserved for I/O resets for additional real-time hardware that FOCAL wanted to accommodate, I carefully ran code that would do nothing visible if the EAE was in mode A, but would take it out of mode B if it was in that state.  This enabled FOCAL to run reliably after a FORTRAN IV program had been run.

I'd very much like to get SIMH to a point where I could say:

set enable 8i

or some such so that we'd be able to have a rigorous PDP-8 Family membership

Detail:


# The following patch fixes a problem if U/W FOCAL is started # after another program has left the EAE in Mode B.
# For example, the FORTRAN IV runtime system ALWAYS does this!
# At location 5400 is a block of 20 Zeroes that apparently
# get populated with code to "CLEAR ANNOYING FLAGS".
# This seems a fit for that need. # I expect device overlays would fill that in.
# The U/W FOCAL build we have at the moment has no such overlays.
# So we grab the first location and put in the following contents:
# 7447 SWBA /SET MODE B
# 7000 NOP /PREVIOUS INSTRUCTION IS DVI ON 8/I
# 7621 CAM /CLEAR AC MQ AFTER DVI.

Heinz-Bernd Eggenstein

unread,
Nov 19, 2021, 2:35:14 PM11/19/21
to PiDP-8
>I'd very much like to get SIMH to a point where I could say:
>
>set enable 8i
>
>or some such so that we'd be able to have a rigorous PDP-8 Family membership

So what would a real PDP-8i or what should SIMH do with "enable 8i" when you run code on it that tries to switch to "mode B" like the FORTRAN iV you mentuioned? ? Halt the processor? 

Cheers
HB

Bill Cattey

unread,
Nov 19, 2021, 5:20:31 PM11/19/21
to Heinz-Bernd Eggenstein, PiDP-8
No. The opcode to swap from mode A to mode B is 7431.

I'm looking at page 54-59 of the 1970 edition of the Small Computer Handbook (which features the 8i).
The instruction would be MQL NMI, but the narrative says that those two cannot be combined.

However I found a richer analysis at: http://www.quadibloc.com/comp/cp0306.htm
It says:

7431 SWAB Switch from A to B

this replaced the combined operation MQL NMI, which would not have produced a sensible result; due to the opcode used, in addition to performing a mode switch, it also performed the MQL operation.

If I'm understanding it, the EAE would dutifully copy normalize a 24 bit word consisting of the AC replicated into the MQ. Not useful.

So it woudn't halt the processor, it would just generate silly results.  Code specifically written for the 8i should not, as a matter of correctness, have that opcode.

Proper code that executes on the Family of 8 has an array of processor tests.  The code in KERMIT that Charles Lasner wrote is the definitive set of such tests.  Alternatively one compiles for the specific family member. Code specifically written for the 8e and later versions of EAE would either contain the tests, or say on the box 8e EAE required.

If people are interested in working on the family paramaterization, we can start up another thread where we inventory the differences, how they are detected, and cook up some upstream SIMH patches to allow meticulous support of the PDP-8 family just like it has support for specific members of the PDP-11 family.

-Bill

'Heinz-Bernd Eggenstein' via PiDP-8 wrote on 11/19/21 2:35 PM:
--
You received this message because you are subscribed to a topic in the Google Groups "PiDP-8" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/pidp-8/_y8UHCQnsY4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to pidp-8+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pidp-8/5ac8cdb7-9ac6-4eab-9004-08e02cb6d917n%40googlegroups.com.

Heinz-Bernd Eggenstein

unread,
Nov 19, 2021, 6:00:11 PM11/19/21
to PiDP-8
>If people are interested in working on the family paramaterization, we can start up another thread where we inventory the differences,
>how they are detected, and cook up some upstream SIMH patches to allow meticulous support of the PDP-8 family just like it has support
>for specific members of the PDP-11 family.

I think if we want to push this upstream, we need to do this together with new code that simulates the FETCH, DEFER and EXECUTE states separately and gives an acurate state for the MB register, as discussed earlier in this thread, because that code will be so different from the current code. Maybe the PDP-8 family member support (here 8i support) is the best argument to get this new code upstream  anyway, like "let's feature a dedicated 8i simulation, and while we are at it, let's simulate MB as a proper register. 
 
I'm currently working on this more detailed simulation in my own SIMH fork, but yet without limiting it to the 8i instruction set. It already passes the tests from some historical DEC maintenance self-test which are part of the SIMH build script (for the 8e of course) , I wonder whether the 8i self test codes are available somewhere as well?

Bill Cattey

unread,
Nov 19, 2021, 6:58:45 PM11/19/21
to Heinz-Bernd Eggenstein, PiDP-8
A little swimming around in alt.sys.pdp8 turns up cjl's explanation of system tests:
https://groups.google.com/g/alt.sys.pdp8/c/1mPDH7nsVEk/m/TYIACIfqCgAJ
There's also a pretty-print of his "What am I" program at:
http://www.ibiblio.org/pub/academic/computer-science/history/pdp-8/Generic%20Programs/WHATAMI.pdf
The source, WHATAMI.PAL can be found at:
https://www.ibiblio.org/pub/academic/computer-science/history/pdp-8/Generic%20Programs/

'Heinz-Bernd Eggenstein' via PiDP-8 wrote on 11/19/21 6:00 PM:

Ian Schofield

unread,
Nov 20, 2021, 4:28:49 PM11/20/21
to PiDP-8
 Further to a Windows/Linux app to explicitly define the CPU time states, these OSs don't do real-time at the granularity required for an accurate simulation.
 The next option of a bare metal build still has the problem of CPU speed. This is why I am interested in the RP2040 as this gets close.
 Specifically, an emulated 8/I manages 900 cpu cycles per ms. with a 220 MHz clock. Obviously, a Pi processor would be much faster but
 doing bare metal is a bit of a pain. At this point, the CPLD option remains in play. I have a Altera Cyclone III EP3C25F324 PDP8/L build
 which is (obviously) rock solid with fetch/defer/execute states at 20 ns a pop. The down side of these methods is that it is difficult to provide
 the flexibility of simh as in attaching various devices etc.
 Overall, I think that the current simh build is pretty good and it would be tricky to update to 'exactly' match the original hardware in regard of timing.
 I reckon Heinz-Bernd and Bill have a point from above in that the PDP11 version of simh allows for a number of different types of CPU.
 So, I agree that the next thing to do would be to add the option to set the CPU to emulate a particular model.

BW, Ian.

Heinz-Bernd Eggenstein

unread,
Nov 21, 2021, 10:01:13 AM11/21/21
to PiDP-8
People who are interested ina microcontroller emulation might find this interesting:


But maybe that's for a separate thread? Perhaps we should keep this thread for discussions of what would basically be the next major release of the pidp8i software, based on SIMH.

HB

William Cattey

unread,
Nov 22, 2021, 3:37:25 PM11/22/21
to PiDP-8
I forget if it was mentioned in this thread or elsewhere. But there is someone working on a cycle-accurate emulation of the 8i in an FPGA for the PiDP-8/i:

Heinz-Bernd Eggenstein

unread,
Nov 22, 2021, 4:00:39 PM11/22/21
to PiDP-8

folke...@gmail.com

unread,
Nov 22, 2021, 4:24:52 PM11/22/21
to PiDP-8
And it's still running TSS/8 here: http://fb.solhost.org:8000

You can test the front panel behavior there, including all lamps, states, single step / inst, data breaks, etc. You can also disable the EAE or change the amount of core memory and see what that does to the memory access and IF / DF lamps, even works correctly if you remove the whole MC8/I.

All CPU parts are implemented based on the original 8/I schematics and that part is 100% done. However, the external peripherals follow a minimalistic approach for now and only support the minimum required to use them.

(Sorry if this message arrives twice, I sent a similar message 30 minutes ago and somehow it didn't get through)
 
Reply all
Reply to author
Forward
0 new messages