Monday, July 14, 2025

The REAL G-15 Four-word Memory Clear Program

In the prior blog post, I described a four-word program for the Bendix G-15 that would clear all of memory, the software-accessible registers, and the overflow and double-precision sign flip-flops. At the time, no source or object code for the program existed, but I was able to reconstruct a working version from a post by the late Jim Horning in his blog, "The Way it Was: Tales from a life in computing," and get it to run in my retro-g15 emulator.

That was three years ago, and a lot has happened in the G-15 community since then. Most importantly, there is actually a robust G-15 community now. When I started working on my emulator in 2021, there were few people who remembered the system, and fewer still who were interested in it. An earlier post in this blog describes how I knew about the G-15 and why I was interested in it.

Around the time I started working on the emulator, the System Source Computer Museum near Baltimore, Maryland (US) acquired two complete G-15 systems and a ton (literally) of documents, paper tapes, and other miscellanea for the system. Rob Kolstad has been curating the collection of documents and paper tapes in preparation for making the collection available publicly. One of the G-15s is currently on static display at the museum. Then in mid-2023, the museum shipped the older of its G-15s to David Lovett in Texas for restoration.

David is the creator of the Usagi Electric channel on YouTube, where he rotates his attention among various electronic and electro-mechanical restoration projects, releasing new videos approximately weekly. You can subscribe to early access for his videos on Patreon. There is also an active G-15 channel on the Usagi Electric Discord server.

David has done an amazing job with the restoration of this G-15 and has had the system working quite well since the end of 2024. His work has stimulated much of the recent growth of interest in the G-15. His current plan is to clean up some loose ends of the restoration, ship that system back to the museum later this year, and then receive their other G-15 for its restoration.

A Significant Find

All of the foregoing is background for the subject of this post. In February 2024, while plowing through the large collection of G-15 documents at System Source, Rob Kolstad encountered a one-page document titled "Example IV. Routine for Clearing Memory." Knowing of my prior blog post on the subject, he sent me a scanned PDF of the page.

That page does indeed describe the original four-word memory clear program, or at least one version of it. The document is not dated, but from its appearance was clearly prepared on a typewriter and is probably from the late 1950s or early '60s.

For the impatient, this original version of the program can be run by typing the following string of hexadecimal digits into the G-15 typewriter by using ENABLE fc7fq to preset the processor state and enable TYPE IN (see the "In Summary" section of the prior post for what those codes mean), or by preparing a paper-tape image from the digit string and loading it using ENABLE p.

060u35z08051vy8303yvxx040u778s 

I found it interesting to compare the four words of G-15 machine language in this document with my reconstruction of it from 2022. It was gratifying to see that I had reconstructed the mechanism of the program entirely correctly. I had the same instructions and in the same order, but it was a shock to see how much more sophisticated the timing of this version was. In the prior post, I had written:

Once those locations were determined, the values for the N fields were obvious (well, except for that weird N=105 in the command that cleared AR—that came later), and the values for the T fields were straightforward to calculate from the command locations. 

Well, yeah, determining the values for the N and T fields of the instructions was straightforward, if you didn't care how fast the program ran. The original version runs almost exactly twice as fast as my reconstructed one.

Analyzing the Timing Differences 

To understand why the original version is significantly faster, let's analyze the two versions and their respective timing. To understand the following discussion, I strongly recommend that you first read the prior blog post, if you haven't done so already, as it discusses many details about the G-15 and my reconstructed version that will be touched on only lightly here. Most importantly, it discusses the G-15 instruction word formats and the technique of precession, a word you will see multiple times in the following.

Comparing the Code 

My reconstructed version, after the initial precession that converts the program from its loaded form to its executing form, is this:

L WT Hex T N CH S D Description
0 0 060235z 6 2 0 26 31 INCREMENT AR by 3
1 0 02693vw 2 105 0 29 28 Set AR to 0 (not used here)
2 2 0403uz7 4 3 2 23 23 SWAP location 3 with AR
3 3 040237x* 4 2 0 27* 29* CLEAR a line to zero
0000000 0 0 0 0 0 NOOP (copy line 0 to itself)

See the prior post for definitions of the instruction fields. This table has an extra column, though, labeled WT, the word-time at which the instruction executes. For the reconstructed version of the program, it is the same as L, the physical location of the word on line 23 of the drum, but that is not the case in the original version below, and as we will see, that makes all the difference.

The original version, after the initial precession into its executing form, is this:

L WT Hex T N CH S D Description
0 0 060u35z 6 10 0 26 31 INCREMENT AR by 3
1 0 82053vw 2 5 0 29 28 Set AR to 0 (not used here)
2 10 0w0zuz7 12 15 2 23 23 SWAP location 3 with AR
3 15 100u37x* 16 10 0 27* 29* CLEAR a line to zero
0000000 0 0 0 0 0 NOOP (copy line 0 to itself)

The characters in red-boldface show the differences between the two versions. Note that the only differences are in the T and N fields of the instructions and in the word-times at which two of the instructions are executed. Those word-times are determined by the N fields of their preceding instructions in execution sequence, but note that they are congruent modulo-4 with the physical drum locations.

Also note, although it is not shown here, that all commands in my reconstructed version run in Immediate-mode. In the original version, the command that clears AR to zero (which is executed only once during initialization) is Deferred-mode and the other three are Immediate-mode. That one command being in Deferred-mode has no effect on the overall timing or behavior of the program. It could as well have been coded as an Immediate-mode command. For both versions that command is located at L=1 after the precession, but it was executed at word-time 0 before the precession.

The critical thing to appreciate about G-15 instruction timing is the difference between the physical drum location at which an instruction is stored (L) and the word-time at which that instruction is executed (WT). These programs run from line 23 on the drum, which is a 4-word line. You would think that an instruction addressed by the preceding instruction's N field of, say, 10, would be executed the next time that a physical location of 10 mod 4 (i.e., 2) passed under line 23's read head, but that's not how the G-15 works.

All timing for the drum is based on full 108-word drum cycles. If you want to execute an instruction on a four-word line at word-time 10, you have to wait for word #10 of 108 on the drum's circumference to rotate around to the read head, even though physical word #2 on that four-word line may pass the read head multiple times before that. The actual delay is determined by the difference between the N field of the prior instruction and word-time at which the prior instruction terminated its transfer state.

For example, if the prior instruction ended at word-time 4, you will need to wait for five word-times (5, 6, 7, 8, and 9, bypassing the desired physical word at word-time 6) until word-time 10 on the drum arrives at the read head. If, however, the prior instruction ended at word-time 36, you will need to wait for 81 word-times until word-time 10 arrives at the read head, bypassing the physical word you are trying to read at word-times 38, 42, 46, ... 102, 106, 2, and 6, for a total of 20 missed opportunities. Hence, how you code word-times in the T and N fields of instructions can have a big impact on timing.

I knew this when I was working on the reconstruction of the program three years ago, but I think it's fair to say that I didn't appreciate it very well. I appreciate it much better now, but I still don't think I could have come up with a solution as optimal as that of the original version of the program.

Comparing the Instruction Timing 

To see how optimal the original version is, let's examine the detailed timing of both versions. The following table shows the timing for my reconstructed version:

L WT T N CH S D Desc   RC WTR TR WRC TT
0 0 6 2 0 26 31 INCR   1 0 5 104 110
1 1 2 105 0 29 28 AR=0   1 0 1 102 104
2 2 4 3 2 23 23 SWAP   1 0 1 107 109
3 3 4 2 0 27* 29* CLEAR   1 0 108 106 215
0 0 0 0 0 NOOP   1 0 104 0 105

The next table shows the timing for the original version of the program:

L WT T N CH S D Desc   RC WTR TR WRC TT
0 0 6 10 0 26 31 INCR   1 0 5 4 10
1 1 2 5 0 29 28 AR=0   1 1 1 2 5
2 10 12 15 2 23 23 SWAP   1 0 1 3 5
3 15 16 10 0 27* 29* CLEAR   1 0 108 102 211
0 0 0 0 0 NOOP   1 0 92 0 93

The left-most eight columns in both tables are the same as the ones with corresponding headings in the two tables of instructions presented earlier. The right-most five columns show the timing of the states that each instruction goes through:

  • RC (Read Command):
    The number of word-times necessary to read a command and load it into the processor's internal registers. This is always one.
  • WTR (Wait to Transfer):
    The number of word-times necessary to wait after a command is read until Transfer state (execution of the command) can begin. This is always zero for Immediate-mode commands and at least one for Deferred-mode commands.
  • TR (Transfer):
    The number of word-times necessary to execute the instruction. This is always one for single-precision Deferred-mode commands and TWT–1 for Immediate-mode commands. If the result of that calculation is less than one, add 108 to compensate for address wraparound on the drum.
  • WRC (Wait to Read Command):
    The number of word-times necessary to wait after termination of Transfer state until the next instruction to be executed (at word-time N) arrives at the read head.
  • TT (Total Time):
    The total number of word-times for the instruction (RC+WTR+TR+WRC).

Note that all of the Total Times for the original version are lower than the corresponding ones for my reconstructed version, often by quite a lot.

Calculating Total Run Times 

Understanding the timing of the individual instructions is necessary, but to determine the total run time for each version, we next need to determine how long it takes to clear each line or destination. The two instructions that cleared AR to zero and precessed the words in line 23 into the form they clear the drum are executed only once at the beginning of the program, so they can be ignored for the moment. The remaining instructions are executed in a five-instruction loop—NOOP, INCR, SWAP, CLEAR, and SWAP again—with one iteration per drum line or destination. Referring to the Desc and TT columns of the two tables immediately above, the timing of the two versions for each line or destination is this:

Desc Reconstructed
Word-Times
Original
Word-Times
NOOP 105 93
INCR 110 10
SWAP 109 5
CLEAR 215 211
SWAP 109 5
Destination Total 648 324

There are a total of 32 destinations (0-31), but the program clears only 30 of them. As discussed in the prior blog post, the destinations were cleared in the sequence 0, 3, 6, ... 20, 23, but after line 23 is cleared to zero, the program now consists of nothing but NOOP instructions, so the system continues to run, copying line 0 to line 0 until it is halted manually. Thus, the program never gets to the remaining destinations in the sequence, 26 and 29. As the prior blog explains, that doesn't matter, because destination 26 was cleared as a side-effect of clearing line 25 earlier. Line 29 is not a separate drum line, but a special destination that added the source value to AR, so skipping it simply avoids adding zero to zero, and thus has no effect.

To determine the total run time for the program, we therefore need to multiply the per-destination times by 30, which yields the values in the Drum Total row in the table below. In addition, we need to account for the two initial instructions:

  • Clear AR to zero requires 105 word-times for the reconstructed version and five word-times for the original version.
  • Precessing the program into the form that actually clears memory requires 114 word-times for the reconstructed version and 10 word-times for the original version.

Therefore, the total time that each version should run is this:

Desc Reconstructed
Word-Times
Original
Word-Times
Destination Total 648 324
×30 = Drum Total 19,440 9,720
+ Initialization 219 15
Grand Total 19,659 9,735

Thus, the original version of the program clears the drum slightly more than twice as fast as my reconstructed version. As pleased with myself as I was after figuring out how to reconstruct the program and get it to work, this result is humbling.

Measuring Actual Run Times 

How does this analysis compare to actual run-times for both versions? To determine that, I had to have a way to stop the program once it finished clearing everything rather than have it continuously execute NOOPs. Therefore, I modified a local copy of the retro-g15 emulator (v1.08) to detect when a command word of all zeroes (the NOOP instruction) was executed at word-time 0.

I also modified the Diagnostic Panel so that I could reset its word-time counter and run-time clock, and modified the Diagnostic Trace feature to write only one line per instruction, prefixed by the current word-time counter so that the actual instruction sequences could be examined and their timing accurately determined. Lightly annotated copies of the trace output are available from the project's GitHub software repository for the reconstructed and original versions.

I then ran both versions of the program several times in Firefox version 140.0.4 (64-bit) under Microsoft Windows 10. After loading the program from a paper-tape image file, I reset the word-time counter and run-time clock on the Diagnostic Panel, set the COMPUTE switch to GO, and waited until the system halted. Then I recorded the timings as shown on the Diagnostic Panel, yielding these overall results:

  • For the reconstructed version:
    • Word-times ranged between 19,775 and 19,871 with a mean of 19,832.
    • Run times ranged between 5.32 and 5.36 seconds.
  • For the original version:
    • Word-times ranged between 9,937 and 10,041 with a mean of 9,990.
    • Run times ranged between 2.67 and 2.70 seconds.

The average word-time counts are higher than the calculated counts above by roughly 150, but it turns out there's two reasons for that, as discussed below for the original version.

First, the program finishes by clearing line 23 (where the program is running) to zero, but the N field of the instruction that does that clear is 10, so the processor dutifully proceeds to execute the command at word-time 10.
  • Normally that would be the second SWAP command, which runs for five word-times and then branches to the NOOP at word-time 0 to start the next cycle. But now the word at word-time 10 has been cleared to zero, i.e., it's a NOOP with a T field of zero and an N field of zero. Thus that NOOP requires 98 word-times instead of the five required by the SWAP, for a net increase of 93 word-times.
  • That NOOP completes the 30th iteration of the clear loop. The temporary modification to halt the program that I put into the emulator detects a NOOP being executed from word-time 0, but this NOOP was executed from word-time 10. Thus, the program continues running, branching to the location in the N field of the NOOP, which is 0 and addresses another NOOP. The emulator detects that NOOP as the halt condition, but the halt does not take place until the end of the instruction, which requires an additional 108 word-times.
  • Thus, the final iteration of the original version requires 93+108=201 additional word-times.
  • A similar analysis for the reconstructed program shows that the final iteration requires an additional 105 word-times.

Second, when the program is started, the drum is at a random location, but loading the program from paper tape implicitly sets the starting word-time to 0. Therefore, there will be an initial WRC delay ranging from 0 to 107 word-times before the first instruction of the program can be read and executed. Thus, we should expect that the run times as measured in the emulator should fall into the following ranges:

  • For the reconstructed program: 19,659+105+0=19,764 to 19,659+105+107=19,871 word-times.
  • For the original program: 9,735+201+0=9,936 to 9735+201+107=10,043 word-times.

As shown above, the measured word-times do indeed fall within those calculated ranges.

In Conclusion 

I am very pleased that Rob Kolstad found that one-page description of the original version of the program, and that it has given me the opportunity to analyze its performance and how it differs from my reconstructed version. I was particularly impressed by the way the initial precession that rotates the entire program by one word in line 23 was coded, and although it uses the same technique that my reconstructed version did, its T and N values yield a much more elegant solution to the problem.

The original version of the program is a tour de force in clever use of G-15 instructions and optimization of drum rotational latency. Frankly, I think it outshines anything that Mel was reported to have done. 

The project's G15-software repository contains the materials for both versions, including loadable paper-tape images of the code, static disassemblies of the code, the aforementioned trace files, a text-only transcription of the page describing the original version, a script showing the PPR commands used to assemble the original version, and a spreadsheet detailing the instruction timing calculations.

I hope that the discussion here will prove to be useful to those interested in learning about the G-15 and the techniques that were used to squeeze a much performance as possible from a relatively slow, drum-based computer system. It's a shame that so much thought and effort had to be put into managing drum latency rather than being invested in addressing larger and more complex application problems. As Harry Huskey mentioned in his 1982 lecture on the G-15 (starting at 52:40 in the video), once magnetic core memory became viable, that spelled the end for drum-based memory and the programming techniques that it required.

From that point onward, programmers have been able to concentrate on thinking in straight lines rather than circles.

Saturday, June 18, 2022

A G-15 Four-Word Memory Clear Program

A little over a year ago, while researching the Bendix G-15 computer system, I came across a blog, "The Way It Was: Tales from a life in computing," by Jim Horning. The earlier posts in that blog discuss his early programming experiences, starting in 1959, with a G-15 in the Data Processing Lab at Pacific Union College in Angwin, California. Jim went on to spend significant portions of his career at Xerox PARC and the DEC Systems Research Center.

I enjoyed Jim's stories of his adventures with the G-15, but one post in particular caught my attention, "My shortest Program," from 31 August 2006. In it he describes a program for the G-15, only four words long, that would completely clear the machine's drum-based main memory, its software-accessible registers, the arithmetic overflow flag, and a sign flip-flop used in double-precision arithmetic. That's a lot to accomplish in just four 29-bit words, especially since one of those words was executed only once, at the beginning of the program.

Jim did not provide the code for the program, and in the original post described it only in very general terms. His memory was stimulated by a reader's comment to that post, resulting in Jim appending a rather long comment of his own. In that comment he described in some detail the types of commands the program used, the general scheme by which they worked, and gave many clues for how the program used quirks in the G-15 architecture to achieve its ends. I suspect that in 2006 he was working entirely from an almost 50-year old memory and perhaps was unable to recreate the actual code of the program.

Having recently written a software emulator for the G-15 and taken it to the point where it is working fairly well, I thought it would be interesting to try to reconstruct that four-word program and get it to work. It would be a nice test of the emulator, and something of a programming challenge for me. So I started out by reading his post and long comment multiple times, making notes, and trying to write down what the commands must have looked like.

Overview

You can read Jim's post and long comment at the link above for details, but the general scheme of the program, once initialized, was a loop consisting of five commands:

  1. CLEAR—clear one "line" (track) on the drum using the value (initially) in AR, the accumulator register, which was cleared to zero during initialization by the command that got executed only once.
  2. SWAP—exchange that CLEAR command in memory with the zero in AR.
  3. NOOP—execute the zero word just swapped, which was effectively a no-op (short for "no operation"), i.e., it made no change to the internal state of the computer except to specify the location of the next command to be executed.
  4. INCREMENT—increase the value of a field in the original CLEAR command (now swapped into AR) such that it addressed a different line on the drum, and when executed would clear that line.
  5. SWAP—again exchange AR with the NOOP command in memory, leaving the zero value in AR and the incremented CLEAR command in memory ready to be executed again. Then specify the CLEAR command as the next one to be executed and repeat the process from step 1.

That's a five-word command sequence that fits in three words of memory! How is that possible? As Jim pointed out, one of the commands gets held in the AR register, alternating between CLEAR and NOOP on each cycle through the loop, so that's actually four words of storage. The fifth command is SWAP. It gets executed twice, but in both cases it's the same word in the same location of memory.

How that loop works requires some explanation. Understanding that explanation in turn requires some background on the G-15 and how its commands worked, so I'll start there. One of Jim's clues was that the program modified itself during initialization, so the form in which the program was loaded into the system was different than the form in which it did most of its work.

I'll describe that second form first, since it is easier to understand. After that, I'll describe the initial form the program had when it was loaded, then how it started executing and transformed itself into the second form that actually cleared the system.

The Bendix G-15

The G-15 was a mid-1950s, binary, vacuum tube, drum memory computer. As Jim hinted in his blog, there were two models, the original G-15A and the 1957 G-15D. There were some minor differences between the two that need not concern us here. My emulator is for the D model.

Drum Memory

The drum memory was organized as 29-bit words arranged in "lines", or tracks. There were 20 108-word ("long") lines numbered 0-19, four 4-word ("short" or "fast") lines numbered 20-23, three 2-word lines that functioned as double-precision registers numbered 24, 25, 26, and known as MQ (Multiplier-Quotient), ID (Multiplicand-Denominator), and PN (Product-Numerator), respectively. There was a single 1-word line numbered 28, AR, the single-precision accumulator. Line numbers 27 and 29-31 did not directly reference storage lines on the drum, but instead specified special functions the processor could perform. Note that the arithmetic registers were storage lines on the drum, not sets of flip-flops inside the processor.

All of the storage lines were implemented as recirculating delay lines, meaning that all of them were read and completely rewritten during each cycle through the line. The long lines cycled every 108 words (about once every 29 milliseconds). The fast lines cycled every four words (about once every millisecond), and AR cycled every word (once every 0.269 milliseconds). The amount of time it took for one word to pass its read or write head on the drum was termed a "word-time," also 0.269 milliseconds.

The basic operation the G-15 performed when executing commands was termed "transfer." Usually this involved copying one or more words from a location on one of the drum lines (termed the "source") to the corresponding location on another line (termed the "destination"). In some cases it was meaningful to specify the same line as both source and destination. When transferring between lines of different sizes, the locations were interpreted modulo the line size, e.g., location 2 on a 4-word line was also location 6, 10, 14, 18,... 102, and 106. 

By default, the transfer simply copied the bits from source to destination without change. A command could specify that certain transformations on a word were to take place during transfer, however. We will see one example of that in the memory-clear program. When a line was not being written by a software command, its bits were simply copied from its read head to its write head, hence recirculating them. The "delay" in the line was the time it took a bit on the surface of the drum to rotate from its write head back around to its read head.

Command Words

A command word in the G-15 executed a specific operation and consisted of eight fields having the following arrangement:

G-15 Command Word Layout

Briefly, the fields in this word, from right to left, had these purposes:

S/D (Single/Double) Bit

This is the sign bit in the word. In a command word it usually specified whether the processor operated in single (0) or double (1) precision mode. It was always zero in the memory-clear program, so need not concern us further here.

D (Destination) Field

The destination line for the transfer operation. This five-bit field could have values from 0 to 31, corresponding to the line numbers described above for the drum. Destination 31 specified that a special function was to be performed. The S field in this case, sometimes in conjunction with the CH field, specified the function. You will see below that the INCREMENT command of the memory-clear program was a Destination 31 command.

S (Source) Field

The source line for the transfer operation. Like D, this five-bit field could have values from 0 to 31. Sources 27 and 29-31 were not storage lines. Instead they supplied a value generated from Boolean operations on other storage lines.

CH (Characteristic) Field

This 2-bit field usually specified a transformation that was applied to a word as it transferred from source to destination. In commands that did not involve line-to-line data transfer, this field sometimes specified optional or variant behavior of the command. In the memory-clear program, this field was always zero—meaning no transformation, the bits were just copied—except for the SWAP command, where it was 2. The meaning of that code will be explained in the next section.

N (Next Command Word-Time) Field

As with many drum or delay-line memory systems of its era, each G-15 command specified the location of the next command to be executed. In most systems with other types of memories, commands were taken from sequential locations unless some command specifically altered the sequence. In the G-15, commands were executed from a single drum line at a time, each command's N field specifying the location of the next command on that line to be executed. Execution continued from that line until a command switched it to a different line. The memory-clear program was loaded into and ran entirely from the 4-word line 23.

BP (Breakpoint) Bit

This bit, if 1, caused the processor to halt if the COMPUTE switch was in the BP position. It was also always zero in the memory-clear program, and thus can be ignored in this discussion.

T (Timing) Field

This field controlled the timing of the transfer phase of the command. The way that field was interpreted depended on the state of the I/D bit described next.

I/D (Immediate/Deferred) Bit

This bit specified whether the command was to be run in Immediate (0) or Deferred (1) mode. All commands in the memory-clear program were Immediate, so we need not be concerned with Deferred mode. In Immediate mode, transfer began with the word-time (location) immediately following that of the command itself, although often on different source and destination lines. Transfer continued up to, but not including, the word-time specified in the T field. You will see below that the use of the T field in the INCREMENT command of the memory-clear program was an exception to this.

For more detailed information on G-15 commands, you may wish to look at a prior post in this blog, which gives fuller descriptions. For the whole story, the best reference is the G-15 Programmers Reference Manual. If you are feeling particularly brave, circuit-level details of command execution can be found in the G-15 Theory of Operation Manual.

Precession

A very important concept in the G-15 is precession, which is a form of data shifting. The processor did precession in units of bits and whole words; the input/output subsystem did precession in units of one bit, three bits, and four bits. All of these were accomplished by interrupting the normal transfer path from the read head for the source drum line and routing that stream of bits through a shift register of length n bits before routing the bits to the write head for the destination line. The effect of this was to delay writing to the destination line by n bits. The end result was:

  • The original n bits of the register became the low-order n bits of the first word written to the destination line.
  • The original contents of the destination line were shifted to the left (towards higher addresses) by n bits.
  • The original high-order n bits in the last word from the source line were left in the register.

This was a powerful, if somewhat unusual, feature of the system and was used extensively in many programs. The SWAP command in the memory-clear program made use of whole-word precession, primarily to exchange the CLEAR and NOOP commands through the AR register, but also as part of the transformation the program underwent from its loaded to its executing form.

The Second Program Form

As previously mentioned, the memory-clear program changed during its initialization from the form in which it was initially loaded to the form in which it cleared the system. This section describes that second form the program took and how it worked. The following table shows the program's command words immediately following their initialization:

L Hex T N CH S D Description
0 060235z 6 2 0 26 31 INCREMENT AR by 3
1 02693vw 2 105 0 29 28 Set AR to 0 (not used here)
2 0403uz7 4 3 2 23 23 SWAP location 3 with AR
3 040237x* 4 2 0 27* 29* CLEAR a line to zero
0000000 0 0 0 0 0 NOOP (copy line 0 to itself)

L is the location of the command in line 23 on the drum. The Hex column shows the hexadecimal value of the command word with the low-order sign bit stripped off, since it is always zero, leaving the 7 hex digits of the remaining 28 bits. Note the use of the G-15 convention for hexadecimal digits: u=10(a), v=11(b), w=12(c), x=13(d), y=14(e), and z=15(f).

The initialization phase of the program loads zero into the AR register, transforms the code into this second form, and then sets location 3 to be the next command executed. The table entry for location 3 shows two commands, CLEAR and NOOP, because these commands are swapped with the AR register on each cycle through the program's loop. When the CLEAR command is in location 3, the NOOP command (a word of zeroes) is in AR, and vice versa.

Execution of this phase begins at location 3 with the CLEAR command, shown here in its initial state. That command copies zeroes from AR (line 28) to long line 0. This command is modified by the INCREMENT command, however, changing the value of the CLEAR command's D field to address a sequence of lines on the drum. Hence the asterisks and underscores in those table cells, indicating that these values change as the program runs.

The command in location 1 is not executed during this phase of the program and was used only once to initialize AR to zero. Note that this command has a strange N value of 105. How can you have a next-command location of 105 for a 4-word line? It turns out you can, and that value is critically important to the initialization process, as will be explained in the next section.

We are now ready to trace through the execution of this phase of the program, starting with the CLEAR command in word 3. The AR register is zero.

CLEAR—This command transfers the value of AR to a line on the drum, initially line 0. Because it executes in Immediate mode, transfer begins with the word-time (location) after that of the command itself. Since the command is at word-time 3, transfer begins at 4. The transfer phase for an Immediate command continues up to but not including the value in the T field, 4, so transfer ends at word-time 3. Thus this one command will copy the zero in AR to locations 4, 5, 6,... 106, 107, 0, 1, 2, and 3, clearing the entire 108-word line.

The N field of the command specifies that the next command will be taken from word-time 2, the SWAP command.

SWAP—This command has source 23 and destination 23, which is the line from which the program's commands are being executed. This seems like it will not accomplish anything useful other than to specify the next command location, but this command has a CH (characteristic) field of 2.

CH=2 specifies a type of transformation termed Transfer Via AR (TVA). This is a form of whole-word precession. During each word-time of the transfer phase, the value of the word from the source line is copied to AR, while simultaneously copying the value originally in AR to the corresponding location on the destination line.

Since this is an Immediate command at word-time 2 with a T field of 4, the transfer phase will start with word-time 3 and end with word-time 3. That means that a single word will be precessed from the source through AR to the destination. Also, in this case the source and destination lines are the same, so the effect is simply to swap the contents of AR with the word at location 3, leaving the CLEAR command in AR and the word of zeroes (the NOOP command) in location 3.

The N field of the command specifies that the next command will be taken from word-time 3, now the NOOP command.

NOOP—This command, being a word of zero, simply copies data from line 0 to line 0. Since the location of the command is 3 and the T field is 0, transfer state will extend from word-times 4 through 107, but that is not important, because nothing gets changed. The only effect of this command comes from its N field, which specifies the next command will be taken from word-time 0, the INCREMENT command. Another (passive) purpose of this command is to preserve the value of zero while the CLEAR command is in the AR register being incremented.

INCREMENT—As Jim pointed out in his long comment, this is actually a G-15 shift command. It shifts the MQ register (line 24) left while simultaneously shifting the ID register (line 25) right. Since these are 2-word registers, each shift requires two word-times. This command executes in Immediate mode, but the T field in this case is interpreted as an absolute count, not the ending word-time. Since each shift requires two word-times, the T value must be twice the number of shifts desired.

The shifting behavior of the command is not relevant to its purpose in this program, however, and those registers are eventually going to be cleared anyway. Instead, the command is used for a side effect—if the CH field of the command is 0, the AR register is incremented by one for each shift performed.

At this point, the AR register holds the CLEAR command. The T field has the value 6, which means that three shifts will be performed. Thus, the real purpose of this command is to increment the D field of the CLEAR command by 3. Jim explains the rationale for incrementing by 3 in his long comment, but suffice it to say that this results in a sequence of values for the D field of 0, 3, 9,... 24, 27, 30, 1, 4, 7,... 25, 28, 31, 2, 5, 8,... 23, 26, 29, 0. Overflows from field D into field S of the CLEAR command occur when incrementing from 30 to 1 (yielding S=29) and from 31 to 2 (yielding S=30). The reason why the CLEAR command continued to work properly after its S field no longer referenced AR is explained below.

The N field of the INCREMENT command specifies that the next command will be taken from word-time 2, which is again the SWAP command.

SWAP—This is exactly the same SWAP command as the one above and works in exactly the same way, swapping AR with the word in location 3. The difference this time, however, is that the incremented CLEAR command is in AR and the zero for the NOOP command is in location 3. These are exchanged so that once again the zero is in AR and the CLEAR command is in location 3.

The N field of this command is still 3, so the next command to be executed will be the now-incremented CLEAR command. This completes the program's cycle for one destination line. That cycle now starts over again at the CLEAR command.

There are several additional details necessary to complete the picture of how this phase of the program worked, most of which Jim mentioned in his long comment.

  • How does the program terminate? It doesn't. Once line 23 gets cleared, the program no longer exists, or rather, its words have all been overwritten with zeroes, which are NOOP commands. No matter in which word-time the CLEAR for line 23 ends, the NOOP will copy line 0 to line 0 and take the next command from location 0, which is also a NOOP. Thus, the program finishes by endlessly executing NOOP commands, copying line 0 to line 0 until the operator halts the system.
  • The CLEAR command always executes with AR being zero, so once the CLEAR for line 23 finishes, AR remains zero, as do all of the other registers.
  • Note from the discussion of the INCREMENT command above that the sequence of incremented D field values for the CLEAR command does not end with 23—destinations 26 and 29 come after that. Thus, once line 23 is cleared and the system starts continuously executing NOOPs, those last two destinations do not get cleared. That does not matter, though, because:
    • As Jim pointed out, line 26 is the PN register, which the system automatically clears when a value is copied to line 25, the ID register. This happens before line 23 is cleared.
    • Destination 29 is not actually a storage line on the drum. Instead it is a destination used to add a value to AR. Thus, not copying (nor adding) anything to it is not a problem.
  • When a value from an even word-time is copied into line 25 (ID), the sign of that value is copied automatically into the IP flip-flop, which holds the sign for multiplication and division commands. Thus, when line 25 is cleared to zero, IP also gets reset.
  • Destination 27 is also not a storage line on the drum. It is the TEST destination. If during the transfer phase it receives any 1-bits, then the next command is taken from the location one after that specified in the N field of the test command. The CLEAR command only transfers zero bits, however, so this "skip on non-zero" action never takes place.
  • Similarly, destination 31 is not a storage line on the drum. It indicates that the operation specified by the S field in the command will be performed. Destination 31 will be addressed during the time that the S field in the CLEAR command has the value 29. The combination D=31, S=29 tests and resets the arithmetic overflow flip-flop. As with the TEST destination above, if the overflow flip-flop was set, the next command is taken from the location one after that specified in the N field of the command. The CLEAR command that triggers this test has an N field of 2, so if the overflow flip-flop was not set, execution continues to that location in the normal manner. If overflow was set, however, the next command will be taken from location 3, which is once again the CLEAR command for destination 27. This time, though, the overflow flip-flop is guaranteed to be reset, since the test done by the prior CLEAR would have reset it, and execution will still continue to location 2 in the normal manner.

How was I able to reconstruct this form of the program? Jim's description in his long comment of the individual commands and the sequence in which they operated gave me a general idea of what the commands needed to be. What wasn't so clear were the locations in which they needed to be stored and values of the T and N fields in each command. I was able to piece the rest of it together by reading between the lines a bit and taking into consideration some constraints imposed by the G-15 architecture.

  1. As Jim pointed out, the INCREMENT command had to be in location 0, because the NOOP command specified it as the next command, and the N field of the NOOP command was 0.
  2. The command that cleared AR to zero was executed only once during initialization, so its location was unimportant during this phase of the program, and it could be placed anywhere.
  3. The most tantalizing clue was this statement of Jim's:
    "The final bit of cleverness was the third use of SWAP. When used in the loop, it executed for a single word time, thereby exchanging AR and a single word of line 23. But it was a block command, and its first execution was at a different word time than all the others. It precessed line 23 to place INCREMENT in word 0."
    That suggested to me that the initial precession rotated all four words of line 23 by one word. The command that cleared AR probably had to be in location 0 initially, so that it would be first to be executed after the program loaded. Precession moves words to higher locations; thus after precession that command would be in location 1.
  4. That left only two undetermined locations, 2 and 3, which had to be used for the SWAP and CLEAR/NOOP commands. Since SWAP was an Immediate command, the CLEAR/NOOP command it operated on during its transfer phase had to start at the word-time immediately after its own. Therefore SWAP had to be at location 2 and CLEAR/NOOP at location 3.

Once those locations were determined, the values for the N fields were obvious (well, except for that weird N=105 in the command that cleared AR—that came later), and the values for the T fields were straightforward to calculate from the command locations.

Sad to say, this phase of the program was the easy part to figure out. Understanding how the program had to be structured for loading and how it got transformed into this second form was much more difficult and took a lot longer. That is the goal of the next section.

The Initial Program Form

Programs were typically loaded into the G-15 from paper tape, something that could be initiated from the typewriter by engaging the ENABLE switch on the base of the typewriter and pressing the "p" key. Jim pointed out that you could also enter programs directly from the typewriter keyboard using a different sequence of control commands that are discussed in the final section of this post. Typewriter entry was practical only for very small programs like this one, though. There was no way to backspace or make corrections—one mistake and you had to start all over.

An input operation read data from paper tape or the typewriter and precessed it into line 19 in blocks of up to 108 words. Line 19, however, with a cycle time of 29 milliseconds, was too slow to precess digits directly from the paper tape reader, which at 250 characters/second read tape frames every 4 milliseconds. To get around this, 4-word line 23, which cycled about once per millisecond, was used as an intermediate high-speed buffer. Once line 23 accumulated four words, an operation termed "reload" would cause the hardware to copy the contents of line 23 to another 4-word line, MZ, which was not visible to software. From there MZ had plenty of time to precess its data into the beginning of line 19 while line 23 continued to fill up with digits from the reader. Reload was triggered by a control frame on the tape or the "/" key on the typewriter, although a later enhancement to the G-15 to handle alphanumeric data allowed reload to happen automatically.

Input from the typewriter was slow enough that direct entry into line 19 would have been feasible, but typewriter input still went through the same Tinker-to-Evers-to-Chance process that input from paper tape did. Since the memory-clear program was only four words long, there was no need for a reload to move it into line 19, as those four words could be executed directly from line 23.

With that preface on how a program gets loaded into the G-15, my problem at this point was to figure out how to arrange the words of code for the memory-clear program so that it would start executing properly.

Since programs started executing at word 0 after loading and the command that cleared AR to zero was executed only once, it made sense to assume that one-time command should be loaded into word 0. That command transferred source 29 (the Input Register, IR) to destination 28 (the AR register). The IR was a means to read a word of bits from external equipment, but unless it was enabled and the external equipment was actually present, it supplied zeroes, thus clearing AR.

The next issue was to understand how the initial execution of the SWAP command could precess the words in line 23 so that the INCREMENT command would end up in word 0 on the line, where from the discussion in the prior section we know it had to be. The only thing that made sense was to have the SWAP command rotate the entire line by one word. This is tricky, because in doing that rotate, all of the words would change location, including that for the SWAP command itself. It also meant that the next command originally addressed by the N field of the SWAP wouldn't be there any more after the swap—a different command would be in that location.

How a SWAP command executed from one location could rotate all four words of the line and the exact same command executed from a different location after the rotation would exchange only one word on the line with AR was the most difficult part of the initialization phase to figure out. The fact that the SWAP command moved, though, was also a clue. Executing the command from a different location would change the effect of the T field in that command, namely, the number of word-times the command's transfer phase would last.

Recall that a command executing in Immediate mode starts its transfer phase in the word-time immediately after that command's word-time on the drum. Transfer continues up to, but not including the location specified by the T field. Thus far, I have been using the terms "word-time" and "location" as if they are interchangeable, but they are not. It is tempting to think of the values in the T and N fields of a command as locations (addresses) of words on a drum line, but they are not that either. Those values actually represent counts.

The G-15 did not keep track of addresses on the drum. Instead it loaded the T and N values into a register, which then counted its way to the correct position on the drum. In reality, it loaded the complement of the difference between the T or N value and the drum's current position into the register and counted up until the 7-bit register overflowed. The counts were held and incremented as fields in a 1-word line on the drum, CM, the Command register, that was not visible to software. Exactly how this worked is complicated and is described in the G-15 Theory of Operation manual, section C-17 (starting on page 40, or PDF page 46).

After struggling over a number of days with how the initial SWAP command could be made to do different things from different locations, I finally realized that the answer had to be in the potential difference between a command's drum location and its word-time. For the long 108-word lines there normally is no difference, but for a 4-word line, word-times are still accounted for on a 108-word basis, even though a word's physical location is its word-time modulo 4. What I needed to do was arrange for the SWAP command to start at a word-time that was congruent modulo 4 with its drum location but that allowed the command's transfer phase to run longer.

For that, I first had to determine how many word-times of the SWAP command's TVA transformation were necessary to rotate all four words of line 23 by one word. TVA uses AR for its precession, and AR at that point has the zero value that will be needed by the CLEAR commands later, so this execution of SWAP had to work in a way that also preserved the zero for later use.

The answer turned out to be six word-times. To see this, first look at the sequence of commands as I now knew they had to be loaded into line 23. Un-rotating the commands as presented in the prior section, that sequence is:

0: SET-ZERO (set AR to zero)
1: SWAP
2: CLEAR
3: INCREMENT

Precessing these words through six TVA transformations yields the following sequence of exchanges:

Step Drum
Word
Before After
AR Line 23 AR Line 23
1 2 0 CLEAR CLEAR 0
2 3 CLEAR INCREMENT INCREMENT CLEAR
3 0 INCREMENT SET-ZERO SET-ZERO INCREMENT
4 1 SET-ZERO SWAP SWAP SET-ZERO
5 2 SWAP 0 0 SWAP
6 3 0 CLEAR CLEAR 0

The SWAP is executed from location 1 (but not word-time 1—that important detail will be discussed next), so it starts operating on the word immediately after that at location 2. After the command finishes, line 23 has been rotated by one word and now has the following arrangement:

0: INCREMENT
1: SET-ZERO
2: SWAP
3: NOOP (the 0 originally in AR)

The only remaining piece of the puzzle was to arrange for the initial execution of the SWAP command to run for six word-times instead of one. The solution to that involves the difference between drum locations and word-times, and is the reason for that weird N value of 105 in the one-time command that sets the AR register to zero.

N=105 modulo 4 is 1, so that will specify the SWAP command, initially at location 1, as the next command. The SWAP command will then start its transfer phase in the word-time after that, 106, and will continue up to but not including the word-time specified by its T field, 4. Thus, the transfer phase for the initial SWAP command executes during word-times 106, 107, 0, 1, 2, and 3—for a total of 6 word times.

After this point, the SWAP is in location 2 and is specified as the next command by the INCREMENT and CLEAR commands, which both have N=2, so in those instances there is no difference between location and word-time, and thus the SWAP executes only during word-time 3.

The way in which this precession worked is pretty slick, but it left me with two curiosities. First the CLEAR command was not at word 3 in line 23 anymore where I thought it needed to be—it was now in AR and word 3 now had a 0, the NOOP command. Second, and even more curious, the N field of the SWAP command has a value of 3, and therefore:

  • The next command to be executed after the initial SWAP will be the NOOP.
  • The only effect of the NOOP will be to move on to the command specified by its N field, which is 0, specifying the INCREMENT command.
  • The INCREMENT command will add 3 to the contents of AR (the CLEAR command), then move to its next command, the SWAP, now at location 2.
  • The SWAP, now in its new location, will execute for a single word time and exchange the NOOP and CLEAR commands, leaving the value 0 in AR and the CLEAR command in location 3.
  • SWAP still designates its next command to be location 3, now the CLEAR, which starts the second phase of the program as described in the prior section.

Thus, this sequence of commands has rearranged the words of line 23 into precisely the form needed to clear the system, just as described in the prior section.

The only problem now is that the CLEAR command has already been incremented, so if it had originally been loaded ready to clear line 0, it now has a D field of 3, meaning line 3 would be the first to be cleared and the program would never get to line 0. This was disappointing—the program had transformed itself exactly as needed except for that initial INCREMENT messing up the CLEAR command's starting line number.

I couldn't see any way to bypass the INCREMENT step, and worried over the problem for more than an hour before finally realizing (and smacking myself upside the head for being so dense) that the obvious solution was to load the CLEAR command so that incrementing it would properly address line 0 at the start of the clearing phase. Instead of loading the command with S=28 and D=0, it needed to be loaded with S=27 and D=29. Adding 3 to the word would increase D to 32, which in its five-bit field would be zero, and the resulting overflow into S would increase that field to 28. VoilĂ !

Therefore, the initial form of the program as loaded is this:

L Hex T N CH S D Description
0 02693vw 2 105 0 29 28 Set AR to 0
1 0403uz7 4 3 2 23 23 SWAP (rotate line 23 by 1 word)
2 040237x* 4 2 0 27* 29* CLEAR (before initial INCREMENT)
3 060235z 6 2 0 26 31 INCREMENT AR by 3

The asterisks indicate fields that are modified by the initial INCREMENT command during the initialization process.

In Summary

The form of the program that Jim would have typed on the G-15 typewriter at Pacific Union likely would have been this:

060235z02011vy8100yvxw04x2778s

The "s" at the end is a Stop control code that terminated typewriter input. The hexadecimal string above is in a compact form where the 116 bits of the four 29-bit words are packed into 4-bit hex digits without regard to word boundaries. The underscores indicate digits that contain bits from adjacent words.

There is a less-compact and more-easily understood form that could also be used:

060235zT 040237xT 0403uz7T 02693vwT s

where the "T"s represent pressing the Tab key on the typewriter and "s" again represents the Stop code. The spaces are optional and will be ignored by the G-15 hardware. Note that the words must be entered in the reverse of the order that they will be stored in memory—an artifact of the precession mechanism used by the G-15 input/output subsystem.

Jim would have preceded either of these forms by engaging the ENABLE switch on the base of the typewriter and typing "sc7fq". The ENABLE switch caused the G-15 hardware to recognize certain typewriter keys as control commands. These keys caused the following to occur:

  • "s" canceled any input/output operation that was currently in progress. This was not needed if no I/O was active.
  • "c7" set the system's Command Line register to 7, which would cause the processor to execute commands from line 23.
  • "f" set the location (word-time) of the next command to be executed as 0. When the system was started, it would thus take its first command from word 0 of line 23.
  • "q" enabled the typewriter for data input.

See the G-15 Operating Manual for more information on the ENABLE switch, its keyboard commands, and data entry from the typewriter.

I can't be certain that the code I have presented here is exactly what Jim would have remembered using. It's possible there may be variations on what I have managed to reconstruct that would also work, although my code does match his description, and more importantly, it works just as Jim described. In my retro-g15 emulator, which attempts to run at the same speed as a real G-15, the program takes about 5.3 seconds to complete.

You can download a paper-tape image of the program code, in a form that will work in my emulator, from the project's GitHub software repository. There is also a text file containing a trace of the program's execution as it initializes itself and proceeds to clear the system.

This program is a good example—perhaps even an extreme one—of the cleverness and trickery in which programmers were willing to engage during the 1950s and early 1960s in order to obtain maximum performance in minimum storage space from early computer systems. It illustrates a couple of important G-15 programming techniques, including precession and the gaming of word-times to control what a command did.

I was quite pleased with myself for being able to reconstruct this program from Jim's description and my still-growing knowledge of G-15 architecture and programming techniques. Multiple head-pounding episodes of frustration aside, it was a lot of fun, and very gratifying to accomplish.

I had hoped to contact Jim after getting the program to work and telling him about my efforts and my interest in the G-15. Alas, I learned from a mutual friend that Jim had passed away in 2011, and I regret that I was never able to know him. His blog is still available, though, and I recommend it to anyone who is interested in knowing what it was like ca. 1960 to use a slow and difficult system from computing's early days.


Sunday, June 5, 2022

Introducing the retro-g15 Emulator

In the prior post, I described the origins and architecture of the Bendix G-15, a mid-1950s, binary, vacuum tube, drum memory computer system. In this post I will describe the retro-g15 software emulator I have written for that system. As with my earlier retro-b5500, retro-205, and retro-220 emulators, retro-g15 is written in JavaScript and runs in a standard web browser.

At time I am writing this, the emulator is at version 1.00. We don't yet have much software for the system, but it successfully runs a diagnostic program we do have, and appears to run the ubiquitous PPR (Program Preparation Routine) utility program correctly. The emulator presently implements only a basic G-15 system, supporting just paper tape and typewriter input/output. Support for magnetic tape, punched cards, and alphanumeric devices is feasible, but we don't yet have any software that requires those devices. Until we do, it is not worth trying to implement them.

For those who would like to jump ahead and start using the emulator, the source code and resource files for it are maintained as an open-source project at https://github.com/pkimpel/retro-g15/. You can run the emulator from a hosting site I have set up, or you can clone or download the files from the project's Git repository and set them up on your own web server. See the section Using the Emulator, below, for details on how to do this. Additional set-up and operating instructions can be found in the project wiki.

Choosing to Emulate the G-15

I studied Chemical Engineering at the University of Delaware from 1966 to 1970. During that time the campus Computer Center was located on the third floor of DuPont Hall. Outside the doors to that room and a short distance down the hall from it was a stairwell that went down to the ground floor. DuPont Hall is a three-story building, but for some reason the stairwell went up another half floor, where there was a large landing at the top.

On that landing, for the entire time I was on campus, there sat a Bendix G-15 in its turquoise livery, disconnected, forlorn, and all alone. I suspect that this may have been the University's first digital computer. By 1966, the G-15 was out of production, no longer supported, and seriously obsolete. My guess is that it had been decommissioned and moved up to the landing a couple of years before I arrived, to make room for the University's Scientific Data Systems 9300 computer, and then forgotten about. When I visited campus some years after graduation, I climbed back up to that landing, but the G-15 by that time was gone. I have no idea what happened to it.

I was intrigued by that abandoned system and wondered how it worked and how it had been used. That has remained sort of an idle curiosity since. I have a faint memory that someone (I don't remember who, probably one of my instructors) told me a G-15 had been used by Professors Jack Gerster and Robert Pigford to do pioneering work in modeling multi-tray distillation towers, a subject that would have been important to the large chemical industry in the Delaware River valley. If so, it would be interesting to know more about that, even though my days of understanding the chemistry, physics, and math of such a thing are long past.

As I approached retirement and had some success in building software emulators for old computer systems, I realized that this was now an itch that I could scratch. The bitsavers.org web site has a good collection of scanned G-15 manuals, and for the past couple of years I have been looking at those periodically. In late 2021 I started working on the design and development of the emulator in earnest.

Using the Emulator

As mentioned above, the emulator runs in a standard web browser, with Firefox and Chrome being the two I have used the most. You will also need a reasonably powerful workstation. Emulation of the G-15 instructions requires almost nothing, but update of the panels and I/O device windows can be graphics-intensive, and requires a fair amount of horsepower. My eight-year old Dell PC with a 3GHz quad-core Pentium i3 processor handles the emulator without difficulty.

The emulator must be served to your browser from a web server over HTTP. You will not be able to download the emulator files to your workstation and run them directly from your local file system. That is a limitation with the way that browsers work, not with the emulator. Of course, there's no reason you can't run a web server on your workstation and serve the emulator files from there. Regardless, once the emulator is loaded into your workstation, it runs entirely locally, and needs no further access to the web server.

Setting Up the Emulator

The easiest way to get started with the emulator is to run it from the hosting site where I have set up the emulator files. Feel free to use it:

If you would prefer to run the emulator from another web server, download the files from the Git repository on the project site. You can download a zip file of the latest version of the emulator source code and related resources by clicking the Download ZIP button on the repository's home page:

Alternatively, you can clone the project from the repository using the following Git command:

git clone https://github.com/pkimpel/retro-g15 retro-g15

Although the GitHub project site uses a Git source code repository, GitHub also allows you to access the repository using Subversion clients. A read-only checkout of the emulator files can be performed using a Subversion command similar to this:

 svn checkout https://github.com/pkimpel/retro-g15/trunk retro-g15

You will need at least the emulator/, webUI/, and webUI/resources/ directories from the repository. The emulator/ and webUI/ directories must be rooted in the same virtual directory on your web server. You may also wish to download/check out the software/ directory, as it contains some utility scripts, but that directory is not required to run the emulator.

The emulator may open a number of sub-windows when it initializes. Most browsers will consider these windows to be "pop-ups," so if you are using a pop-up blocker, you may need to disable it before starting the emulator. Most pop-up blockers will allow you to disable blocking for specific web sites, however, which will allow you to run the emulator without having to forgo protection from pop-ups for all sites. Modern browsers enable a pop-up blocker by default, and many browser toolbar plug-ins implement additional ones. All of them may need to be disabled for the emulator site.

More information on system requirements, setting up the emulator, and using a local web server is available on the Getting Started wiki page.

The Emulator Home Page

When you first load the emulator, it initializes with a default configuration, which is adequate to get started using it. Once it loads into your browser, it's ready to run. The hosting-site URL above references the emulator's home page, which looks like this:

retro-g15 emulator Home Page
retro-g15 Emulator Home Page

The picture on the page is the late Harry Huskey, the G-15 designer, apparently at the typewriter of his personal G-15 system. To start the emulator, just click the Start the Emulator button on the page. That will open the Control Panel for the emulator, which will overlay the Home Page in the same browser tab.

The Emulator Control Panel

The Control Panel for the emulator is a somewhat simplified version of the G-15 front panel and looks like this:

retro-g15 Control Panel and Typewriter

The top portion of the panel has the controls for the in-built paper tape punch and reader. The middle portion reproduces the lamps from the front the physical G-15 cabinet.The portion below that shows a few buttons and lamps that on a real G-15 were used to power the machine up and down; in the emulator those serve to initialize and terminate the emulator and are discussed in more detail below.

The meters and knobs on a real G-15 front panel are not shown -- they were used for monitoring power levels and maintenance functions, and are not relevant to the implementation or operation of the emulator.

Below the Control Panel is a gray box with a number of radio-button controls. These represent three toggle switches that were located on the base of the system's typewriter.

  • The ENABLE switch controlled the ability to enter certain hardware control commands from the typewriter keyboard.
  • The PAPER TAPE switch in its PUNCH position caused all characters sent to the typewriter to be output as well to the paper tape punch; in its REWIND position, it caused the paper tape reader to rewind its tape.
  • The COMPUTE switch controlled the G-15 processor. In its center (off) position, the processor was halted. Moving the switch to its GO position started the processor executing commands. Moving the switch to its BP (breakpoint) position worked like GO, but in addition, if the processor executed a command word with a particular bit set, the processor would halt. This feature was typically used for debugging.

The white area below the switches represents the "paper" of the typewriter. Its size is responsive to the size of the browser window, and will scroll once the typed output fills up the visible area. Your workstation keyboard functions as the typewriter keyboard and is active whenever the browser window has the input focus. Whether pressing a key on the keyboard has any effect on the system other than echoing that character to the paper depends on the setting of the ENABLE switch and whether a "Type In" command is currently being executed.

To power up a real G-15, you turned on the master A/C switch (labeled START) on the front panel. After the tubes in the power supplies warmed up, you would then press and hold the RESET button until the red DC lamp lit, then release the RESET button. At that point, the G-15 hardware performed an automatic sequence of functions that included:

  1. Read the first block of data from the paper tape reader to line (track) 19 on the drum.
  2. Copy that data from line 19 to a separate line on the drum known as the Number Track. This track provided a set of timing and logic signals to the hardware logic. The hardware logic also wrote to portions of this track during its operation, so that line on the drum had to function as a recirculating delay line like all of the others on the drum. All data was lost from these recirculating delay lines when the system was powered off, which is why the Number Track had to be reloaded each time the system was powered up.
  3. Set the Command Line register to 7, which would cause the processor to execute instructions from the four-word ("fast") line 23.
  4. Set the location of the next word to be executed from that line to zero.
  5. Read the next block of data from the paper tape reader to line 19. This block was typically a loader routine for some program that followed it on the tape. The way that paper tape was read on the G-15 required that line 23 be used as a high-speed buffer, allowing four words at a time to be read from the tape, then precessed (shifted) from line 23 to the beginning of line 19. The words had to be on the tape in reverse order, and the reading worked in such a manner that a copy of the four words stored at the beginning of line 19 were also left in line 23. Thus you actually bootstrapped a program from line 23, which usually transferred control to the actual loader routine located somewhere in line 19.
  6. Terminate the initialization process by turning on the green READY lamp and leaving the system in a halted state.

Initializing the emulator works in a very similar way. Clicking the Start the Emulator button on the Home Page is equivalent to turning on the master A/C switch. Once the Control Panel appears, you click the RESET button (although holding it down is not necessary). After a short delay the DC lamp lights and the system attempts to read two blocks from paper tape and perform the other actions described above.

The emulator does not actually use the data on the Number Track for its operations, but a program can execute a command that will copy the Number Track to line 18 on the drum, from which the program could read and make use of that data. Except for that detail, the emulator will still function properly if there is no tape in the reader when the RESET button is clicked, or if the first block does not actually contain Number Track data.

As a convenience, the emulator preloads the paper tape reader's buffer with a tape image for PPR (the Program Preparation Routine), a very common utility program for the G-15. This image has the Number Track data and the PPR loader as its first two blocks. Thus, by default you can simply start the emulator, click the RESET button, wait for the green READY light to come on, then move the COMPUTE switch to GO to run PPR. If you want to initialize the system with a different tape image, just unload the PPR image from the reader and load the other image before clicking RESET.

As another convenience, the ESC key on the keyboard can substitute for the ENABLE switch. It is a little awkward in the emulator to have to turn on the ENABLE switch, press a typewriter key for one of the hardware control commands, and then turn the switch off. Instead, you can use the ESC key like a shift key. If you press and hold the ESC key, the ENABLE switch will move to its ON position. Once you release the ESC key, the switch will revert to its off position.

For more information on the layout and functioning of the Control Panel, including the paper tape and typewriter devices, see the "Using the Control Panel" wiki page. For information on the hardware control commands, use of the ENABLE switch, and the PPR program, see the G-15 Operating Manual.

The G-15 was not a particularly easy system to use, and a great deal of responsibility fell on the person running the system to know how to perform the necessary functions and to do them properly. Aside from a few conveniences in its interface, the retro-g15 emulator works the same way -- by design. This is a time trip to 1950s computing and you are going to suffer, so plan to do some reading before trying to use the emulator.

The Diagnostic Panel

To aid in debugging the emulator, I implemented a more detailed panel that shows all of the registers, the current command word separated into its several fields, the current drum and command locations, and several significant flip-flops in the system. The panel displays all four of the 4-word (fast) lines and the MZ line that was used as an I/O buffer but was not visible to software. You can select a single 108-word (long) line for display as well.

At the bottom of the panel are three buttons that can be used to start, stop, and single-step the processor.

retro-g15 Diagnostic Panel

To open this panel, double-click the G-15 logo on the Control Panel. You can open and close the Diagnostic Panel at will while the emulator is running. "Powering off" the emulator automatically closes the Diagnostic Panel window if it is open. The panel updates itself at a rate of about 20Hz. The display of the drum lines updates a couple of times a second.

Even if you don't use it for diagnostic purposes, this panel can be interesting to watch while the system is running.

Software

We do not yet have much software for the G-15 in terms of standalone programs. There is more available and I am working to acquire it, but that is probably going to take some time. In the interim, thanks to David Green in Western Australia and Paul Pierce in Portland, Oregon, we have these three interesting items.

PPR (Program Preparation Routine)

PPR, as mentioned earlier, was a utility program that was used by most G-15 sites and developers. It was operated from the system's typewriter and provided features for:

  • Entering object code words as a series of decimal fields and assembling those fields into binary command words.
  • Reading existing object code from paper tapes and editing the code in memory.
  • Merging library routines from other paper tapes into memory.
  • Punching new tape from the edited code.
  • Typing the contents of tape blocks in hexadecimal.
  • Computing and typing out checksums of tape block contents.
  • Disassembling code from tape blocks in a format similar to that used for entering command words.
  • Debugging programs with breakpoints and tracing.
  • Creating the loader routines for a program.
  • Relocating code for library routines so they could be moved to different lines on the memory drum.

A bootable paper tape image of the program can be downloaded from the G15-software code repository. As described above, the retro-g15 emulator preloads this tape image into its paper tape reader during initialization. This tape image was obtained from David Green.

Instructions for running PPR can be found in the G-15 Operating Manual. A listing of the object code for the program, in the form of G-15 coding sheets, is available on bitsavers.org.

BXTST

The standard G-15 diagnostic program that was provided by Bendix.

A bootable paper tape image of the program can be downloaded from the G15-software code repository. Instructions for running the program and discussions of the various error codes can be found in "PART III - APPENDIX" of the G-15 Theory of Operations manual, starting on PDF page 193.

This is a bootable paper tape image and includes the Number Track and test loader as the first two blocks on the tape. This tape image is from Paul Pierce's web site. A slightly different version of the program from David Green, G15TAPE, is also available in that repository.

TQ

This is a short, one-block program that plays a numeric version of the game "Twenty Questions." The idea is that the player chooses a number between zero and 1048575 (220 - 1) and the program will discover that number.

A bootable tape image of the program and instructions for it can be downloaded from the G15-software code repository. This tape image was obtained from Paul Pierce.

In the next post to this blog, I will describe another interesting, but very short, program that I have recently recovered.


The REAL G-15 Four-word Memory Clear Program

In the prior blog post , I described a four-word program for the Bendix G-15 that would clear all of memory, the software-accessible registe...