|
Virtual AGC — AGS — LVDC — Gemini
yaAGC
The AGC Simulation Software
|
|
|
|
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?
- The yaAGC and yaDSKY programs simulate the center
two blocks in the figure above. The actual Block II AGC measured
24"×12.5"×6", weighed 70.1 pounds, and 2.5A of current at
28V DC. The DSKY measured 8"×8"×7" and weighed 17.5
pounds.
- The CPU had a memory cycling time (MCT) of 11.7
microseconds. The
modern reader, reading this, probably imagines that by "CPU" we are
referring to a single integrated circuit (or "chip"). In fact,
integrated circuits were too new and too risky (as well as too
expensive) at that time to be used. At some point, a few
integrated circuits were added to act as "flip-flops" for some of the
CPU registers; but the CPU itself was not, by any stretch of the
imagination, an integrated circuit. The
instruction timing varies from 1 MCT up to 6 MCT, but most instructions
execute in 2 MCT. The 11.7 microsecond cycle is subdivided at
the hardware level into 12 shorter time-periods derived from a 1024 KHz
clock. However, for the purpose of the yaAGC
simulation, only the basic
11.7 microsecond cycle-time is of interest.The instruction set of
the AGC is apparently implemented as a kind of microcode, and the
microcode instructions are executed in the 12 subdivisions of the
clock cycle. Since the microcode and the hidden register set it uses
are not accessible to programmers, I've not bothered to carry the
simulation down to the microcode level. However, examining the
microcode is useful in understanding the detailed workings of some of
the assembly-language operations.
- Memory and registers are 16 bits, consisting of 15 bits of data,
plus one bit of odd parity (used for detection of memory errors). The
parity bit is not simulated by yaAGC.
- Fixed
memory—i.e.,
memory which cannot be modified at runtime, for program code,
constants, and so forth. There are 38912 15-bit words of ROM at
addresses 4000-117777 (octal). This ROM was implemented not in
integrated circuits, but in "core" memory—consisting of many small
ferromagnetic doughnuts threaded into a braid of extremely fine wires.
This made the cost of program changes very high, since changes could
only be incorporated by having Raytheon Corp. rebuild the core-memory
assembly. Each of the cores could encode as many as 64 bits of
memory, since 64 wires could be threaded through each core, so that
even though over 600,000 bits needed to be coded, less than 10,000
cores were used. A small portion of the core rope is seen below.
- Erasable
memory—i.e., memory which can be modified at runtime.
There are 2048 15-bit words of erasable memory at addresses
0-3777
(octal). Locations 0-17 (octal) correspond to what might be
thought of as CPU registers, while 20-57 (octal) are "counters",
and 60-3777 (octal) are general-purpose RAM. The erasable
memory was implemented by means of ferromagnetic cores, but not the
same as the core-rope seen at the right.
- Memory banks. It is important to note that while erasable and
fixed memory formed a space of continous memory, logically addressed
from 0-117777 (octal), that 16 addressing bits are needed but that no
register in the AGC (including the program-counter) is 16-bits wide. To
get around this problem, extra addressing bits are taken from special
bank-selection registers and combined with the program counter or with
addresses embedded within program instructions to provide full 16-bit
addresses.
- I/O channels. There were potentially 512 i/o ports with "channel
numbers" from 0-777 (octal). Some few of the i/o channels correspond to
erasable-memory locations. The others were used to address
peripheral devices (such as the DSKY) for telemetry uplink/downlink,
and so on.
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.)
|
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
welded—not soldered—onto the leads to interconnect the
components. (Photo by Stephan Hotto, taken at the Computer
Historic Museum in Palo Alto, California.)
|
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:
--help
Displays a list of options (such as
this one) and then quits.
--port=Portnum
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".
--debug-dsky
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).
--debug-deda
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.
--deda-quiet
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.
--cfg=Filename
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.
--debug
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.
--symtab=Filename
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.)
--resume=Filename
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.
--dump-time=N
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.
--interlace=N
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.
--cdu-log
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:
- 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.
- 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.
- The built-in self-test of the Luminary
or Colossus software provides
a reasonably-detailed check of CPU operations.
- 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:
- Do branch instructions work?
- Do multiply and divide work?
- Do interrupts work?
- etc.
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:
- Index is a value
that will be added to the next instruction (except for EXTEND) prior to executing that
instruction. It is set to a non-zero value when the
assembly-language instruction INDEX
is executed, and then cleared after it has been used.
- Extend is non-zero
when the next instruction will be interpreted as "extracode". It
is set when the assembly-language instruction EXTEND is executed, and then
cleared after it has been used.
- Interrupts is
non-zero when interrupts are enabled. It is affected by the INHINT and RELINT assembly-language
instructions.
- Overflow is set when
an arithmetical overflow occurs in relevant assembly-language
instructions like DAS.
- Cycles is a count of
the number of machine cycles used so far in executing instructions.
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:
- 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.
- 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.
- 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:
- 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:
- #Anything — (i.e., any
string beginning with the character '#' in the first column) a comment,
which is discarded without a warning message. This is principally
useful for writing scripts for the FROMFILE command.
- BACKTRACES — displays the most recent (100) backtrace points
(i.e., points at which the program branched).
- BACKTRACE N —
restores the state of the system (CPU, erasable memory, i/o channels)
to backtrace point #N (from
the list displayed by the BACKTRACES command).
- BREAK *A — (Changed in versions 2005-07-31 and
later! Previously, did not have the asterisk.) Defines a
new breakpoint at address A
(using one of the memory-location formats described above). The
program will halt upon encountering an instruction at the address of
the breakpoint. Note:
The AGC's unswitched-erasable memory coincides with switched-erasable
banks 0, 1, and 2, while fixed-fixed memory coincides with common-fixed
banks 2 and 3. The breakpoints are specific to not only the
address but also to the specific type
of memory. This means that if you define a breakpoint at (say)
address 4010 in fixed-fixed memory, the program will break upon hitting
address 4010 but not upon
hitting address 02,2010 in common-fixed memory which coincides with
address 4010. However, you can set two separate breakpoints if
you want to catch both of these conditions.
- BREAK L -- (Versions
2005-07-31 and after.) If you have loaded a symbol table via
"--symtab"
or SYMBOL-FILE, then you can set a breakpoint with L being either a line number within
the current source file, or else a program label.
- BREAKPOINTS — displays all currently-defined breakpoints,
watchpoints, and patterns. For versions 2005-07-28 and after, if
you have loaded a symbol table
via "--symtab" or SYMBOL-FILE, the printout will include symbolic names
for program labels and variables in addition to absolute numerical
addresses.
- CONT — begin running the program. The program will simply
run until encountering a breakpoint. Alternately, in Linux, you
can halt the program after it's running by hitting the carriage-return
key on the keyboard. (I don't know if this works in *BSD or MacOS
X, so you'll just have to try it and see. Presently, under Win32
there is no interactive way
to break execution
once it gets started, so you really need to be sure that the program is
actually going to hit a breakpoint eventually when using the CONT
command.)
- COREDUMP F — creates
a "core-dump" file of the AGC program on disk, using filename F. (Note that in pre-07/01/04
versions, F will be in
all-caps, regardless
of whether upper or lower case was used when inputting it.) The
"core-dump" file contains a snapshot of erasable memory, i/o
channels,and hidden CPU state-variables. Loading the core-dump
file later using yaAGC's
"--resume" command-line switch allows execution to continue from the
point at which the core-dump file was made, rather than forcing the
program to a reset state. (An exception to this is if you have
used EDIT to modify values in fixed memory. These changes won't
be stored in the core-dump file, and therefore will be lost.)
- DELETE — without an address, DELETE simply deletes all existing
breakpoints and watchpoints.
- DELETE A — deletes
the breakpoint or watchpoint (if any) currently defined at address A. Note: The same comments about
the usage of coinciding memory locations apply as for the BREAK command
(see above). For example, if you have set breakpoints both at
4010 and at the coinciding address 02,2010, then "DELETE 4010" will
delete only one of these breakpoints, leaving the other one in
effect. To delete both of the breakpoints, you would have to use
two DELETE commands, "DELETE 4010" and "DELETE 02,2010". For
versions 2005-07-28 and after, if you have loaded a symbol table
via "--symtab" or SYMBOL-FILE, you can also use the symbolic program
labels rather than addresses.
- DELETE V M — deletes
the pattern (if any) corresponding to value V and mask M. (See also the PATTERN
command.)
- DUMP — without arguments (i.e, no N and no A), a dump is performed using the
last N and A previously used.
- DUMP [N] A — displays the current contents
of N successive memory
locations or i/o channels, starting at address A. The formats allowed in A are described above. N is shown in brackets to indicate
that it is optional. If N
is omitted, it defaults to 1. The dump cannot go past the
end of the memory bank, and will be truncated to fit the bank if you
attempt to do so. Example: "DUMP 5 03,2005" displays the
contents of memory locations 03,2005, 03,2006, 03,2007, 03,2010, and
03,2011. As special cases, note that all CPU registers are memory
mapped, so "DUMP 0" will display the contents of the 'A' register,
"DUMP 1" will display the contents of the 'L' register, and so forth.
- EDIT A V — sets the current value of
memory location or i/o channel A
to the octal value V.
The allowed formats for A are
as described earlier.
- FROMFILE Filename —
(06/30/04 and later) begins accepting input from a file rather than the
keyboard. When
the file is exhausted, keyboard input is accepted again. (Hitting
the return key does have an effect, however, in that it interrupts
program execution.) The FROMFILE commands can be nested (i.e., a
file referenced by FROMFILE can itself contain FROMFILE commands) up to
10 levels deep. In the directory yaAGC/DebugModeScripts, I've
provided a bunch of keystroke files which can be used with FROMFILE to
set up patterns that trap upon executing given types of
instructions. For example, "FROMFILE TC.PAT" sets up a trap that
is triggered by subsequently executing the TC instruction. The files
are cunningly contrived so they trap only "normal" uses of the
instruction, and not the special "implied address" versions of
instructions. Thus, TC.PAT does not trap RETURN (which compiles as "TC Q"), RELINT (which compiles as "TC EB"), etc. To trap
these instructions, one would use RETURN.PAT, RELINT.PAT, etc.
For each instruction.PAT
file, there is also a file called instruction.PAT.DEL,
which can be used to delete the patterns associated with the
instruction.
- GETOCT Expression —
converts hexadecimal or decimal (including floating point) numbers to
the AGC CPU's native octal format, or converts from the AGC CPU's
native octal format to a decimal number. This is available only
for versions 05/09/2004 or later. The HELP command gives more
detail about the supported Expression
formats.
- HELP — shows a list of the available debugger commands.
- INTERRUPTS — displays the current interrupt-request
flags, and the masks the debugger is applying to them (see
below). There are 10 flags, and their meanings are listed on the developer
page.
- INTOFF N — clears
the CPU's interrupt-request flag #N.
- INTON N — sets
the CPU's interrupt-request flag #N.
- LOG N — creates a
file called yaAGC.log, and logs the next N (decimal) instructions executed
to the file. The log is a simple ASCII file, in which there is a
line for each instruction. Each line contains two octal numbers,
of which the first is the BB register logically-ORed with i/o channel
7, and the second is the Z register. The purpose of this log is
primarily for regression testing. Logs can be created for two
versions of yaAGC and then
compared with standard text-comparison utilities like diff to determine where the point
execution path differs. With that information, hopefully, the
debugger can determine the exact reasons for the differences.
- MASKOFF N — the
debugger stops blocking interrupt type N.
- MASKON N — the
debugger (independently of the CPU) will block interrupt type N from occurring. If N=0, then all interrupts are blocked.
- PATTERN V M —
(06/30/04 and later) sets a
"pattern" with value V and
mask M. A pattern is
similar to a breakpoint, except that it uses the instruction code
rather than the program counter. In other words, execution is
halted upon finding that the instruction code is equal to the value V. The instruction code is
logically bitwise-ANDed with the mask M
prior to the comparison, so that only selected fields in the
instruction code are really used. Even though any given location
in memory can only contain 15 bits, the value and mask are really
32 bits, and the additional 17 bits represent additional conditions
that
can be checked. The presently-defined extra bits are:
Bit
Number
|
Octal
Mask
|
Description
|
16
|
00100000
|
The
Extracode bit.
|
17
|
00200000
|
1 if the INDEX is non-zero.
|
18
|
00400000
|
1 if the
Accumulator contains + overflow.
|
19
|
01000000
|
1 if the
Accumulator contains - overflow.
|
20
|
02000000
|
1 if the
Accumulator is -.
|
21
|
04000000
|
1 if the
sign of the Accumulator does not match the sign of L.
|
22
|
10000000
|
1 if within
an interrupt-service routine.
|
23-31
|
n/a
|
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.
- QUIT or EXIT — exits yaAGC.
- STEP [N] or NEXT [N] — executes the next N assembly-language
instructions. If N is
omitted, then it defaults to 1. Note that this command can be
abbreviated as 'S' or as 'N'.
- WATCH A — (06/08/2004
and after) defines a
new watchpoint at erasable-memory address A
(using one of the memory-location formats described above). The
program will halt after
executing an instruction that changes the value stored at the address
of
the watchpoint. Note:
The AGC's unswitched-erasable memory coincides with switched-erasable
banks 0, 1, and 2. The watchpoints are specific to not only the
address but also to the specific type
of memory. This means that if you define a watchpoint at (say)
address 010 in unswitched erasable memory, the program will halt upon
hitting
address 010 but not upon
noting a change in the value stored at address E0,010 in switched
erasable memory (which coincides with
address 010). However, you can set two separate watchpoints if
you want to catch both of these conditions. For versions
2005-10-17 and after, if you have loaded a symbol table
via "--symtab" or SYMBOL-FILE, you can also use the symbolic program
labels rather than addresses.
- WATCH A V —
(2005-08-23 and later) is similar to "WATCH A", except that it breaks upon
finding a specific octal
value V.
- VIEW A — (2005-10-17
and later) is similar to "WATCH A",
except that it displays the value stored in the variable or numerical
address in real time rather than interrupting program execution when
the value changes. It is only meaningful to use this command on
erasable memory, since values stored in fixed memory do not change.
- SYMBOL-FILE Filename —
(2005-07-28 and after.) To use the symbol table generated by yaYUL, there are two equivalent
methods. One is to specify the symbol table (such as
Luminary131.symtab or Colossus249.symtab) via the "--symtab"
command-line switch. The other is to specify it via the
SYMBOL-FILE command.
- PRINT Variable —
(2005-07-28 and after.) If a symbol table has been loaded (via
"--symtab" or the SYMBOL-FILE command), prints the octal value stored
in Variable. This is
similar to the DUMP command, except that the variable is referenced by
its symbolic name rather than by its absolute address. For
example, in Luminary131, the
variable NOTBIT12 is at address 40,3736. The command "PRINT
NOTBIT12" gives the same result as "DUMP 40,3736".
- WHATIS Symbol —
(2005-07-28
and after.) If a symbol table has been loaded (via "--symtab" or the
SYMBOL-FILE command), displays info about the Symbol. The info includes
items such as the symbol's numerical address (if a variable or program
label), its value (if a constant), its class (label, variable,
constant, etc.), and the source-code file and line-number at which it
is defined.
- SYM-DUMP RegularExpression
— (2005-07-28 and after.) If a symbol table has been loaded (via
"--symtab" or the
SYMBOL-FILE command), displays info about all of the symbols whose
names match the RegularExpression.
The printout is truncated after 25 symbols, in which case you might
want to tighten up the search by making RegularExpression more
specific. The regular expressions are "extended" POSIX regular
expressions, and are not case-sensitive. (If you don't know
anything about regular expressions and want to learn more, the wikipedia
is a reasonable place to start.) Here are some examples that
might help:
SYM-DUMP NOT
|
Any symbol whose name
contains
"NOT".
|
SYM-DUMP ^NOT
|
Any symbol whose name begins
with "NOT".
|
SYM-DUMP NOT$
|
Any symbol whose name ends
with "NOT".
|
SYM-DUMP ^NOT$
|
The symbol "NOT".
|
SYM-DUMP (^NOT)|(NOT$)
|
Any symbol whose name begins
or ends with "NOT".
|
SYM-DUMP ^[ABC]
or
SYM-DUMP ^((A)|(B)|(C))
|
Any symbol whose name begins
with 'A', 'B', or 'C'.
|
SYM-DUMP ^NO+
|
Any symbol whose name begins
with 'N' followed by 1 or more occurrences of 'O'.
|
SYM-DUMP ^NO*
|
Any symbol whose name begins
with 'N' followed by 0 or more occurrences of 'O'.
|
SYM-DUMP 1.2
|
Any symbol whose name
contains a '1' followed by a '2', with any other character in between.
|
SYM-DUMP 1\.2
|
Any symbol whose name
contains a '1' followed by a '2', with '.' (specifically) in between.
|
- LIST — (2005-07-30 and after.)
Provides a symbolic disassembly of the code, if a symbol table has been
loaded (via "--symtab" or the
SYMBOL-FILE command), and if the source-code files are present.
The source files must be in the same directory as they were when yaYUL created the symbol table; if
copied to a different directory, yaAGC
will not be able to find them. There are several variations of
this command:
LIST
|
Print the source lines following
the current program counter.
|
LIST -
|
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.
|
- FILES RegularExpression
— (2005-07-31 and later.) Lists the names of the AGC source-code
files. A regular expression is used to determine which filenames
are listed, just as described above in the SYM-DUMP command.
Last modified by Ronald Burkey on 2009-08-17.