;;;
;;; README for Project Nevermore
;;;
;;; Assorted notes on the purpose, usage, maintenance, history, and future of the Nevermore system.
;;;


The Nevermore system is, at present, an experimental simulator for the Explorer I (Raven) microcoded CPU and some of the related peripheral hardware (NuPI board for hard disk support, System Interface Board for partial screen and keyboard emulation, Memory boards etc.) It is hoped that it will one day be capable of booting a Lisp world (and may that day be soon).


The original core of this project was the result of my desire to have a working disassembler for the Raven microcode. After my second attempt in C, I realized that the best output format would be as close to the original input format as I could manage. The third attempt was again in C, and ran afoul of the list and symbol manipulation required when putting together a prototype for such a disassembler. The fourth attempt was written over the course of Nov. 7 through 9, 2003 in CMUCL. This was successful enough that over the Sunday and following Monday I was looking through the disassembly of the boot PROM and figuring out how certain parts of the code functioned.

On the Tuesday of that next week, I decided that the only way to answer some questions as to what parts of the code was doing was to write a simulator, so I laid out the first versions of microengine-step and friends. I am writing this on Saturday the 15th of November, 2003, and progress has been rapid over the past week.


The boot PROM starts off with some self-test code for the CPU, which excersizes most or all of the on-board hardware and memories, which has been very useful since the code is quite unambiguous as to what behavior it expects from the system.

As things stand now, the basic microengine appears to be mostly complete, and development is concentrating on getting all of the EXPT diagnostics to run (as of october 15, the score is 12-4, our favor; see the bottom of this file for details).


There has been a recent reorganization involving moving most of the Raven-specific code to a new package. There are still a few places where further cleanup is needed (mostly around the nubus implementation). Note that the microengine control is now in the :raven package, while the ROM loader and screenshot functions are still in :nevermore.

A new feature is the addition of the ability to dump a screenshot as text. After loading the ROMs, do (nevermore::sib-init-character-recognizer). Then, when you run into a keyboard busy-loop, do (nevermore::sib-text-screenshot). This will print a 126 by 61 character representation of the contents of the framebuffer.

Another new feature is the addition of a streamlined method for stuffing keystrokes into the receive buffer. To set it up, do (nevermore::sib-init-keypress-stuffer). Then, when you run into a keyboard busy-loop, do (nevermore::sib-keyboard-stuff-keypress <character>), substituting an appropriate character (digit, upper-case character, #\Tab, or #\Return. This will put a down-and-up key transition pair into the receive buffer on the System Interface Board.

Before you start, edit nupi-handle-command-drive-read in nupi-nubus.lisp to reflect the location of your disk image. If you can't start any of the diagnostics, you will probably have to edit the image file with a hex editor to set the diagnostic flag on a few partitions.



The system now has an ASDF definition for :nevermore in nevermore.asd. The usual deal applies:

    (load "nevermore.asd")
    (asdf:operate 'asdf:load-op :nevermore)

At this point, switch to the nevermore package:

    (in-package :nevermore)

Now set the value of *rom-file-path* to the location of your ROM files and then load them:

    (setf *rom-file-path* #p"/path/to/E1_eproms/")
    (load-romfiles)

And set up your hard drive image file:

    (setf *nupi-scsi0-0-disk-file* #p"/path/to/explorerI_diskDumps/explScsi0Dr0.dsk")

Next, initialize the character recognizer (so you can see what's going on later) and the keypress stuffer (so you can control what's going on later):

    (sib-init-character-recognizer)
    (sib-init-keypress-stuffer)

From here on out, we want to be in the raven package:

    (in-package :raven)

Next, reset the microengine to the start state.

    (microengine-initialize)

To have the simulator execute a single microinstruction, call microengine-step with no arguments:

    (microengine-step)

The system should respond by printing:

    L-0 Inhibited.
    L-0 ((M-0 TEST-SYNCH) SETZ)

If it doesn't, something went wrong.

To have the simulator execute a number of instructions in turn, call microengine-run-to with an argument of the micro-pc to stop at (it will also stop at locations 18 and 40):

    (microengine-run-to 85)

The function microengine-step will output the disassembly of the instruction interpreted, and the disassembly of the next instruction to interpret (after applying any OA-register effects). The return value is the address of the next instruction to be read from I-Memory (either the PROM or the real memory space).

The invocation (microengine-run-to 171) will run the microengine until shortly before the start of M-Memory tests.

The invocation (microengine-run-to 395) will run the microengine until the start of the multiply/divide tests.

The invocation (microengine-run-to -1) will run the microengine until either Something Goes Wrong or it hits location 40 (which will happen during the normal boot sequence). If it does stop at location 40, just (microengine-step) past it and then use microengine-run-to again.

You can get a graphical representation of the contents of the SIB framebuffer by issuing the call:

    (nevermore::sib-write-screenshot #p"screenshot.bmp")

You can get a textual representation of the contents of the SIB framebuffer (at east until the Lisp world boots) by issuing the call:

    (nevermore::sib-text-screenshot)

If you are in the host debugger, and wish to return to your REPL, execute (microengine-force-halt) and continue. At present, microengine-force-halt operates by modifying the next fetched microinstruction to enable the HALT bit, which will cause microengine-run-to to stop. In the future, this will likely be changed to involve a separate flag, so as not to interfere with parity checking and the like.

The emulator can detect when the system is waiting for a keypress within the STBM, startup menu, and EXPT load. When this occurs, it will break to the debugger from within an I/O handler. At this point it can be useful to look at a text screenshot (see above) and possibly stuff a keypress into the receive buffer. The keyboard stuffer is quite limited, and will only accept digits, upper-case characters, #\Tab, and #\Return key.

    (nevermore::sib-keyboard-stuff-keypress #\A)

This should be sufficient to get you started. Now you too can see Nevermore fail the EXPT tests. Enjoy!


Thanks to the following people of freenode #lisp for helping me make nevermore faster when I was seriously thinking about switching to C for speed:

    Krystof, rtoy_, mucit, chandler, antifuchs, frodef, bdowning, rahul, Xach.

Thanks to Steve Krueger and Paul Fuqua for answering some questions about various features of the Raven CPU, and to the old unlambda lispm-hackers list members for getting me into explorer emulation in the first place.

Thanks to... umm... someone for supplying a dump of the last rom in the Raven set (where'd that email go?).


EXPT test status, 2005/Oct/15:

+---+------------------------------------+------+
| 0 | ALU/OBUS                           | pass |
| 1 | BYTE/BARREL SHIFTER                | pass |
| 2 | I-MEMORY                           | FAIL |
| 3 | PUSHDOWN LIST (PDL)                | pass |
| 4 | M-MEMORY                           | pass |
| 5 | A-MEMORY                           | pass |
| 6 | MICRO-PROGRAM COUNTER STACK (UPCS) | pass |
| 7 | TAG CLASSIFIER                     | pass | (somewhat spammy)
| 8 | UNMAPPED ACCESSING                 | FAIL | (this is new)
| 9 | VMA                                | pass |
| A | GCVF LOGIC                         | pass |
| B | DISPATCH                           | pass |
| C | MACROCODE DECODE                   | pass |
| D | EVENT POSTING                      | FAIL |
| E | INSTRUCTION STREAM HARDWARE        | pass |
| F | MEMORY CYCLE ABORT                 | FAIL |
+---+------------------------------------+------+

;;; EOF
