Document library
Change log
Bug and issues
Developer info
Virtual AGC — AGS — LVDC — Gemini

The AGC Simulation Software

Language Manual
Physical Implementations

Please enable javascript in your browser to see a site-search form here.

What is yaAGC?

yaAGC is a computer program which emulates the behavior of the Apollo Guidance Computer (AGC).  It is a virtual computer (existing within, for example, a desktop PC) which is capable of running software written for the original AGCs used in the Apollo project.  yaAGC emulates only the computer itself, and not the peripheral devices used by the AGC.  For example, the display/keyboard (DSKY) used by the AGC is a peripheral device and is emulated by a completely different computer program called yaDSKY.  Just as the true AGC and DSKY communicated between themselves by mean of wiring, the virtual yaAGC and yaDSKY communicate between themselves using communication channels (sockets) that act like virtual wires. 

Similarly, as a "computer", yaAGC by itself provided little or no functionality.  To be useful, it needs to be "loaded" with appropriate flight software—in other words, with the Command Module (CM) or Lunar Module (LM) flight-software written for the original Apollo missions.   The CM and LM software are called Colossus and Luminary, respectively.

What, Exactly, is Being Simulated?

Guidance&Navigation block architecture

Photograph of core-rope
A small section of the ferrite cores in the "core rope" non-volatile memory of the AGC.  (The photo was taken from the web; it was credited to Raytheon Corp.)
Click to enlarge.
Logic modules, plugged into a backplane.  Though you cannot tell it from this photo, if the modules were disassembled, you would see that they are of "welded cordwood" construction.  What that means is that the modules are full of cylindrical holes, like swiss cheese; the electrical components, such a resistors, slide into these holes, and their leads protrude from either side of the module.  Wires are weldednot solderedonto the leads to interconnect the components.  (Photo by Stephan Hotto, taken at the Computer Historic Museum in Palo Alto, California.)
Click to enlarge
The backplane the logic and memory modules  which the logic and memory modules plug into.  Notice that it is wire-wrapped.  Even the production models were wire-wrapped, and not just the engineering models.  (Photo by Stephan Hotto, taken at the Computer Historic Museum in Palo Alto, California.)

Invoking yaAGC

Important Note!
The description that follows describes the "classic" command-line switches of the yaAGC program for versions prior to 20090427.  I retain this description as-is for the benefit of those using one of those versions of yaAGC.  However, for versions 20090427 and later, the command-line switches with respect to to modes for debugging AGC programs have changed, and I'm not presently in a position to authoritatively describe those changes (which may be in a state of flux).  A more up-to-date description may be available at Onno Hommes website.  (In brief, however, to activate the command-line debugging mode which previously would have been gotten by invoking "yaAGC --debug --core=...", one would use "yaAGC --exec=...".)

yaAGC is a command-line program that requires no user interaction once started.  The syntax is

yaAGC [OPTIONS] --core=BinaryExecutable

The BinaryExecutable will be the name of a file containing an AGC core-rope binary image, either downloaded or else assembled from Luminary or Colossus source code using yaYUL.  If a complete pathname for BinaryExecutable is not specified, then yaAGC will look first in the current directory, and then (for software versions 05/06/2004 or later) in the installation directory (which is /usr/local/bin by default, but which may be changed when yaAGC is built).  The other currently-defined options are:

Displays a list of options (such as this one) and then quits.

The yaAGC program and programs simulating peripheral devices (such as yaDSKY) have a server/client relationship.  yaAGC listens on a set of ports (by default, 19697 through 19706) for client connection-requests.  The base (lowest) port number can be changed using the "--port" command-line switch.  (The number of ports scanned remains 10, however.  To change the number of scanned ports requires changing yaAGC's source code and recompiling the program.)  One might wish to change the base port if, for example, simultaneously running an instance of yaAGC for the CM and another instance of yaAGC for the LM.  The port ranges of the two instances of yaAGC shouldn't overlap, so one instance could be run (for example) with the command-line switch "--port=19707".

This setting is useful for debugging a DSKY simulation (such as yaDSKY).  This switch causes the "--core" setting to be ignored (in fact, the "--core" switch can be omitted).  Instead of running an AGC executable, yaAGC simply echoes command sequences back to the DSKY upon receiving keystrokes from the DSKY.  These command sequences are defined in the configuration file (see "--cfg" below), and can actually relate to any peripheral devices (not just the DSKY).

This setting is useful for debugging a DEDA simulation (such as yaDEDA).  Unlike --debug-dsky, yaAGC runs the AGC simulation as normal.  But in addition, it interprets communications from yaDEDA.  (In normal operation, of course, it completely ignores data originating from yaDEDA, or indeed any other messages in yaAGS format.)  For each communication received from yaDEDA (for key sequences such as CLR-OctalDigit-OctalDigit-OctalDigit-READOUT) it prints out a message indicating what was received.  For the specific key sequence just mentioned, it goes further and acts similarly to the AEA software, in that it interprets the 3 octal digits as an address in erasable memory, and outputs the value found at that address (in octal) every 1/2 second to yaDEDA.  The addresses most meaningfully observed in this fashion are timer registers like 25 (octal) which increment at 10 ms. intervals, and therefore increments by about 50 (62 octal) every 1/2 second.

This setting is used in conjunction with --debug-deda to eliminate the outputs from yaAGC to yaDEDA which --debug-deda normally creates.  In other words, lets yaAGC parse the messages being received from yaDEDA, but never to send any itself.

This presently has no effect unless used with "--debug-dsky".  It causes a configuration file to be loaded which defines the command sequences used in --debug-dsky mode.  The same directory assumptions are used in searching for the file as are used with the --core switch (see above).  Full instructions can be found within the provided sample files  (presently LM.ini, CM.ini, LM1.ini, and CM0.ini).  The configuration files are really provided for use with the yaDSKY program, and the same file should be selected for yaAGC as is selected for yaDSKY (if --debug-dsky is going to be used).   Only the "DEBUG" lines within the configuration files are relevant to yaAGC.  If no configuration file is selected, or if no DEBUG lines appear within the configuration file, then --debug-dsky will be non-functional.

Causes the AGC program to halt prior to executing its first instruction, and activates a debugging mode (very primitive) in which you can do things like examine AGC registers, single-step through the AGC program, etc.  This mode is described further below.   In Linux (though not necessarily in *BSD, MacOS X, or Win32), you can put yaAGC into debug mode without the --debug switch, simply by hitting the carriage-return key any time after starting the program; the AGC program will simply be halted wherever it is, and you can begin debugging at that point.

For versions 20050728 and later, yaYUL outputs symbol-table information that yaAGC can use in "--debug" mode to aid symbolic debugging.  In other words, if you load a symbol table into yaAGC, then in debug-mode you can sometimes use program labels and variable names rather than having to know the absolute numerical addresses for everything.  The --symtab switch is used to specify the name of the symbol-table file.  The same search path is used as for --core and --cfg.  Since the symbol tables for Luminary131 and Colossus249 (namely, Luminary131.symtab and Colossus249.symtab) are "installed" along with the executables, you can simply say "--symtab=Luminary131.symtab" or "--symtab=Colossus249.symtab".  However, if you want to assemble your own AGC source code, the symbol table output by yaYUL will be named the same as your source file, but with ".symtab" suffixed to it.  For example, if you assemble "MyFile.s", then the symbol table will be "MyFile.s.symtab".  In this case, you'll want to use the complete pathname for the symbol-table as the filename for --symtab.  This feature, and all of the debugging commands associated with it are courtesy of Jordan Slott.  (Thanks, Jordan.)

Normally when the emulator runs an AGC program it sets all i/o channels, erasable memory, and hidden CPU state variables to what it considers reasonable power-up defaults.  (But see "--dump-time", below.)  The --resume option instead allows these items to be loaded from a previously-created file.  (The file itself is created from --debug mode using the COREDUMP command as explained below.)  In effect, this allows execution to continue from the exact point in the AGC program at which the COREDUMP was made, rather than forcing the AGC program to its reset condition.  The file must be either in the current directory, or else a full pathname must be given for it.

For versions 20050705 and later, yaAGC attempts to save the contents of erasable memory, and to restore them automatically at startup (but not i/o channels and hidden CPU state variables).  This means that things like pad loads are preserved even when the AGC is "powered down", just as they would have been in the true AGC's ferrite-core memory.  In an effort to keep this from increasing system overhead too much, the saving is actually done only every N seconds (10, by default).  The data is saved either in a file called LM.core or CM.core, and is compatible with the "core dumps" described above for the "--resume" switch.  You can start with a clean system by erasing LM.core or CM.core.  Or, you can use "--resume=LM.core" or "--resume=CM.core" if you'd like to restore more than just the erasable memory.  Because separate files are used for the LM and CM, you can run both simulations at once without any conflict.  However, if you want to run more than one LM simulation (or more than one CM simulation), you'd better start them from different directories, to make sure that the .core files are stored in different directories.

On some PC's the act of checking the socket connections (i.e., the mechanism used by yaAGC to communicate with yaDSKY and/or other peripheral devices) can make the simulation very sluggish.  Therefore yaAGC only performs this check every N-th CPU instruction, where by default N=50.  Changing the value of N does not affect the reliability of the communication (i.e., no data is lost).  Making N smaller theoretically improves the responsiveness of the system, except on slow PC's where the overhead from checking the sockets may exceed the computing time taken by the simulation.  For example, a value of N=1 works fine on my ~2.5 GHz P4 Linux and Windows XP systems, but results in about a 10-to-1 slowdown of the simulation on my 450 MHz P2 Windows 98 system.  On the latter system, a value of N=10 seems to work perfectly.  Conversely, increasing N reduces the overhead, but results in a larger time-jitter in signalling, and (in theory) for large enough values a steadily-increasing backlog of data waiting to be delivered.  As far as time-jitter is concerned, it's important to realize that yaAGC does not actually execute a machine cycle every 11.7 microseconds, but merely keeps up appearances of doing so in a way not detectable by the user.  Therefore, there is a pretty large time-jitter anyway, and the amount of jitter is dependent on both the speed of the PC and on the operating system used by the PC.  The value N=50 has been chosen in the belief that it will work well for most PC's, and does work well on all of the example systems mentioned above.  (On my 150 MHz P1, on the other hand, the simulation runs about 50% slow no matter what the setting of --interlace.)  Nevertheless, the --interlace switch may be of value when fine-tuning of the timing is required.

Used only for debugging.  Causes a file called yaAGC.cdulog to be created, containing data related to the bandwidth-limiting of CDU inputs PCDU and MCDU.

Verification of yaAGC Correctness

The validity of the emulation provided by  yaAGC is questionable, of course,  particularly since I have no working AGC against which it can be compared.  If we cannot assure that yaAGC actually behaves identically to the actual AGC, then there's really not much point in having it.  Sadly, the complete answer to this question remains open.  I can, however, point out the following relevant facts:
  1. AGC behavior at the assembly-language level is described in two separate documents, mostly covering the same material, by Blair-Smith and by Savage & Drake.  While I would be lying to claim that either of these presents a complete and satisfactory explanation, comparing and reconciling the two is a very useful exercise whilst attempting to verify yaAGC behavior.
  2. The Blair-Smith documentation goes one step farther, in that it breaks down all or most AGC instructions into more primitive functionality called "pulse sequences", operating upon hidden registers of the CPU.  In cases of difficulty, therefore, one can explore the detailed action of the pulse sequences to obtain yet another description of any instruction's behavior.
  3. The built-in self-test of the Luminary or Colossus software provides a reasonably-detailed check of CPU operations. 
  4. A validation test-suite in AGC assembly language has been written from one of the original Apollo documents, "Block II AGC Self-Check and Show-Banksum" by Edwin Smally.  This test suite gives the CPU a pretty rigorous (if not 100% complete) going-over.
To understand points #3 and #4 better, note that the original AGC CPU was a homegrown device created from a large number of electronic components, rather than being a single "integrated circuit" as it likely would be today.  For this reason, it would have made sense for the original designers to provide extensive diagnostics for the CPU itself.  In other words, if the CPU was broken it would have to be repaired rather than simply being discarded and replaced, and to be repaired the fault would have to be localized.  As it happens, the designers did provide extensive runtime diagnostics in software for checking a multitude of CPU features.  These diagnostics were part of the unit's built-in self-test, and included checks like:
Unfortunately, many of these checks had to be removed eventually from Luminary and Colossus in order to save memory; but the flowcharts for the checks which have been removed still exist, and the tests they performed can be reconstructed.  Because of this oddity (by today's standards) the Luminary/Colossus software  and the validation suite verify the operation of many of the (from our standpoint trickier) CPU instructions!  While, as I said, this is not a 100% guarantee of completely correct operation, we can only regard it as helpful in the context of the present project.

Debugging Mode

Important Note!
The description that follows covers the "classic" debugging mode for versions prior to 20090427.  I retain this description as-is for the benefit of those using one of those versions of yaAGC.  However, for versions 20090427 and later, command-line debugging has changed to a style more closely related to that of the widely used gdb program, and the "classic" mode described below is not longer available.  Since these changes have been driven by Onno Hommes, we have agreed that Onno will maintain documentation for the new debugging mode at his website.

When the "--debug" command-line switch is used, a mode is entered in which AGC programs can be debugged.  This mode is very primitive compared (for example) to the facilities provided by a debugging program like gdb, but has been pretty useful for my purposes, and may conceivably be useful for yours.  You are unlikely to find this mode (or my description of the mode!) of any use unless you are very familiar with AGC assembly language, and are writing/debugging AGC code.  In this mode, rather than simply running the software contained within the core-rope binary image, yaAGC halts prior to executing the first instruction of the program and allows you to interactively determine its further actions.  You are presented with a status message and a prompt from which you can enter commands.

The debugging mode's status display may look something like this:

A=00010         L=00000         Q=00000         EB=01400        FB=12000        Z=02675         BB=12103
ARUPT=00000     LRUPT=00000     QRUPT=00000     ZRUPT=00000     BBRUPT=00000    BRUPT=00000     CHAN07=00000
CYR=00000       SR=00000        CYL=00000       EDOP=00000
Index=00000     Extend=1        Interrupts=0    Overflow=0      Cycles=29
05,02675        12701           BZF     2701

In the first three of these status lines, we see the current values (in octal) of various important CPU registers, and in input channel 7.  In fact all numerical values displayed by the debugger are in octal, because octal notation is used almost exclusively throughout  existing AGC code, and because almost all of the numerical values reported by the YUL assembler were in octal.

The next line shows information that may be from hidden CPU registers or may be known only to the debugger:
The final status line is, of course, a disassembly of the next instruction scheduled to be executed.  It shows the current address (05,02675), the octal value of the instruction (12701), and a disassembly of that octal value into assembly-language (BZF 2701).  The debugging mode does not currently understand any labels defined within the AGC program itself; therefore, understanding code like "BZF 2701" as something like "BZF ADDONE" (involving labels) is aided by having a symbol table or assembly listing at hand.

The debugger understands addresses in one of three formats:
  1. Addresses within "unswitched-erasable" memory or "fixed-fixed" memory are represented by a single octal number, such as 1234.  Unswitched-erasable addresses are in the range 0000-1377, while fixed-fixed addresses are in the range 4000-7777.
  2. Addresses within "common-fixed" memory are represented by a pair of octal numbers separated by a comma, such as 03,2345.  The first number is the bank number, in the range 00-43.  The second number is the address within the memory bank, and is in the range 2000-3777.
  3. Addresses within "switched-erasable" memory are similar, but are prefixed by 'E', such as E7,1456.  The first number is again a bank, but is in the range 0-7.  The second number is again the address within the memory bank, but is in the range 1400-1777.
Additionally, in some cases you may need to identify i/o channels rather than memory locations:
  1. Addresses within "i/o channel" space are single octal numbers prefixed by 'C', as in C7.  The number is in the range 000-777.
These same notations are used within the status display's instruction-disassembly, except that the distinction between memory locations and i/o channels is always obvious in that context, and so i/o channel numbers are not prefixed by 'C' in disassemblies.

The user-commands which are currently recognized by the debugger are:
Bit Number
Octal Mask
The Extracode bit. 
1 if the INDEX is non-zero.
1 if the Accumulator contains + overflow.
1 if the Accumulator contains - overflow.
1 if the Accumulator is -.
1 if the sign of the Accumulator does not match the sign of L.
1 if within an interrupt-service routine.
Presently 0.

Note that the INDEX (if any) is added to the instruction code prior to the comparison.  The net effect of this, with proper selection of V and M, is to allow halting upon execution of a given instruction type, and to be able optionally to select only INDEXed or non-INDEXed instances.   Both V and M are in octal.  For example, with "PATTERN 170000 170000", the program will halt upon encountering the MP instruction.
Any symbol whose name contains "NOT".
Any symbol whose name begins with "NOT".
Any symbol whose name ends with "NOT".
The symbol "NOT".
Any symbol whose name begins or ends with "NOT".
SYM-DUMP ^((A)|(B)|(C))
Any symbol whose name begins with 'A', 'B', or 'C'.
Any symbol whose name begins with 'N' followed by 1 or more occurrences of 'O'.
Any symbol whose name begins with 'N' followed by 0 or more occurrences of 'O'.
Any symbol whose name contains a '1' followed by a '2', with any other character in between.
Any symbol whose name contains a '1' followed by a '2', with '.' (specifically) in between.
Print the source lines following the current program counter.
Print the source lines preceding the current program counter.
LIST label
Print the source lines at (and surrounding) the specified program label.
LIST lineno
Print the source lines at (and surrounding) the specified line number in the source file containing the current program counter.
LIST fromline,toline
Print the source lines from the specified starting line number to the specified ending line number in the source file containing the corrent program counter.
LIST filename:lineno
Print the source lines at (and surrounding) the specified line number in the specified source file.  Note that you only need the actual filename of the source file, and you can omit the name of the directory containing the source file.

Last modified by Ronald Burkey on 2009-08-17.

Virtual AGC is hosted by ibiblio.org