Welcome to the Datatron 205 and 220 Blog

This blog is a companion to T J Sawyer's Web Page that outlines the history of the Burroughs Datatron 205 and Paul Kimpel's incredible 205 and 220 emulators. Please visit those sites and return here to post any comments.
Showing posts with label ElectroData. Show all posts
Showing posts with label ElectroData. Show all posts

Sunday, May 10, 2020

retro-205 Emulator Version 1.03 Released

I am pleased to announce that version 1.03 of the retro-205 emulator has been released. This version introduces two significant enhancements, one to the Flexowriter output device, the other to have multiple, selectable system configurations.

These changes have been committed to the project's source repository on GitHub and uploaded to the project's hosting site from which you can run the emulator. The project wiki also has corresponding updates.

Flexowriter 203/204 Character Encoding


Tom Sawyer requested this enhancement for a project he has been pursuing, but explaining it requires a little background. The original ElectroData Datatron 203 computer (as well as the CEC models 30-201 and 30-202 that preceded it) had only primitive input/output devices -- a high-speed paper-tape reader, a significantly slower paper-tape punch, a Flexowriter electric typewriter, and a decimal keypad that could be used to enter instructions and data into the system via the Control Console.

The paper tape and keypad devices were numeric-only, operating with four-bit binary-coded decimal (BCD) digits. The Flexowriter, however, was an alphanumeric device. It could print signed numeric data directly from BCD digits supplied via the processor's A register, but could also print alphanumerically in mixed case, with the characters specified by pairs of adjacent digits. The assignment of the two codes closely matched the internal mechanism of the Flexowriter, with some codes serving to control non-printing functions, i.e., shifting between upper and lower-case, carriage-return, horizontal tabulation, backspacing, and shifting the ribbon between black and red colors.

When the Datatron 204 was introduced with support for magnetic tape, the same Flexowriter character encoding was carried forward. When the Datatron 205 was introduced with the Cardatron interface to IBM punched-card equipment, however, a different character-encoding scheme was adopted that mapped more directly to the zone/numeric scheme used with punched cards. It was also the case that the IBM equipment supported only upper-case letters and fewer special characters than the Flexowriter. As a result, the 205 used a modified Flexowriter that had been adapted to the Cardatron character set.

Prior to this release, the retro-205 emulator has used the 205's Cardatron character encoding scheme. The project that Tom has been working on involves a program that had been written for the 204, which meant that when it printed alphanumeric data to the Flexowriter, it printed gibberish. He needed the ability to switch the Flexowriter between the 205 and 203/204 character-encoding schemes.

This proved to be not very difficult to do. The character encoding for the Flexowriter can now be changed in two ways:
  1. On the system configuration page (accessed from the emulator's home page, webUI/D205.html), in the Console Unit Selection section, there is a new check box, "Use 203/204 Flexowriter encoding." When this box is ticked, the Flexowriter will use the original encoding for the Datatron 203/204. When the box is not ticked, the device will use the 205 Cardatron encoding. This setting is preserved across emulator restarts. Note that the configuration page can be accessed only when the emulator is in a "power off" state.
  2. On the Flexowriter's browser window, there is a new button below the logo that indicates the encoding scheme currently in effect. This is initialized to the setting from the configuration page when the emulator is started. Clicking the button will toggle between the 203/204 and 205 Cardatron schemes. This button allows the encoding scheme to be changed while the emulator is running, even in the midst of the Flexowriter printing. Changes made using this button are not preserved across an emulator restart -- the setting will revert to that from the configuration page.
Character codes used with the 203/204 are shown starting in Section 3 page 21 of ElectroData Technical Bulletin 3040, Datatron Programming and Coding Manual. Note that there is an error in this table for code 33 -- for lower case it prints the apostrophe (') as shown; for upper case, however, it prints the double-quote (").

Character codes used with the 205, Cardatron, and modified Flexowriter are shown on the Burroughs 220 Pocket Card -- the 205 and 220 used the same Cardatron codes. The codes are also shown in Figure 2 of United States Patent 3,000,556.

When printing in 203/204 mode, the emulator supports all character glyphs except the 1/2 (one-half) symbol, which prints as the crosshatch (#). It supports the control codes for upper- and lower-case, carriage return, horizontal tab (with stops at every eight positions), backspace (overwriting rather than overprinting any existing characters), and the black/red color shift. It ignores the stop code, 07.

Multiple System Configurations


Since version 0.06, the emulator has supported customization of its input/output configuration -- console devices, magnetic tape drives, and Cardatron punched-card equipment. There was only one configuration, however -- if you wanted a different arrangement, you had to modify the configuration and save it, which overwrote any prior arrangement.

This next enhancement also originated from a request by Tom Sawyer. He wanted the ability to store multiple configurations and a way to select easily among them. In particular, he wanted the emulator to support some number of predefined configurations so that users of the emulator could easily choose one.

The emulator now supports multiple configurations. There is a "Default" configuration, which is created automatically when the emulator is first loaded to an instance of a browser. This is equivalent to the single configuration that existed previously, and is initialized to the same settings. When running version 1.03 or later for the first time, any existing single configuration will be transferred to the Default one. You can modify this configuration in any way you wish, but you cannot delete it.

In addition, there is -- initially -- one predefined configuration named "Basic203." This configuration, as its name implies, gives you the input/output devices you would have had on a Datatron 203 -- paper-tape reader and punch, plus the Flexowriter printer with 203/204 character encoding enabled. This is what Tom needed for his 204-vintage program. You can neither modify nor delete predefined configurations, but you can clone a new configuration from it and modify the clone, as discussed below. We may be implementing additional predefined configurations in future releases of the emulator.

You configure the emulator the same way as in the past, by clicking the Configure System button on the emulator home page. This can be done only when the emulator is in a "power off" state. Clicking the button opens the configuration page in a separate window, which has changed somewhat from previous releases:

retro-205 Configuration Page

The buttons have been moved and two new ones added. To the left of the buttons is a new pull-down list that holds the available configurations and shows which one is presently selected. You can also see the new check box for 203/204 Flexowriter character encoding discussed earlier in this post.

The buttons work as follows:
  • CANCEL -- Closes the configuration page without saving any changes you have made. You can accomplish the same thing by clicking the close-window icon on the page's title bar (i.e., the "X" on Microsoft Windows systems).
  • SAVE -- Saves any changes you have made on the page to the currently-selected configuration, makes that configuration the current one for the emulator, and closes the configuration page. An alert box will pop up confirming this fact.
  • DELETE -- Deletes the currently-selected configuration and makes the "Default" configuration the current one. You cannot delete the "Default" configuration or any of the predefined ones.
  • CLONE -- Creates a copy of the currently-selected configuration under a new name and makes the new copy the currently-selected configuration. The page will prompt you for the new name. The page stays open after this so that you can customize the new configuration. All cloned configurations can be modified and deleted later.
Thus, to switch to a different configuration that already exists, you need only select the configuration's name from the pull-down list and click the SAVE button.

There is no fixed upper limit on the number of configurations you can have. The configuration data is stored by the browser on your workstation using a standard mechanism known as LocalStorage. The limiting factor is how much data the browser will allow for an entry in LocalStorage. For most modern browsers, this is a figure in the low megabytes. Most configurations require only 2000-3000 bytes.

In addition to its setting on the configuration page, the name of currently-selected configuration is shown under the blue buttons on the retro-205 emulator home page and in the lower-right corner of the Supervisory Panel window.

There is a second method that can be used to select the configuration under which the emulator will run. You can include the name of the configuration in the query string of the URL that opens the emulator home page, e.g.,
http://www.phkimpel.us/ElectroData-205/webUI/D205.html?config=Basic203
The query string is the portion of the URL that begins with "?". The "config" key is case-insensitive, but the configuration name must be written exactly as it is stated in the configuration list, including case and any internal spacing. This will make the named configuration (if it exists) the current one, exactly as if you had selected it on the System Configuration window. If that configuration name does not exist, the emulator displays an alert and opens with its currently-selected configuration.

The idea behind this second method is that it's an easy way to send someone a link that will run a specific emulator configuration.

No further additional features are planned for the retro-205 emulator at present, but occasionally bugs crop us, and we do have a few items of software that are in various stages of restoration, so we aren't done with this system yet.

Tuesday, February 11, 2020

retro-205 Emulator Version 1.02 Released

The retro-205 emulator for the ElectroData/Burroughs Datatron 205 has been stable and operating nicely now for almost three years. I occasionally find small problems to fix, or come across a reference that sheds new light on the operation of the system that prompts a programming change. Enough of these have accumulated that I recently pushed out a new release, version 1.02.

This post describes the changes in 1.02. These changes have been committed to the project's source repository on GitHub and uploaded to the project's hosting site from which you can run the emulator. The project wiki also has a few minor updates.

Application Cache Feature Removed


Support for the browser Application Cache ("appcache") feature has been removed from the emulator. This feature allowed the browser to load the entire emulator into local storage, and once the code was loaded, run it without requiring access to the host web site, or even to a network connection. Alas, this feature was not well-accepted by web developers and was deprecated as a standard a few years ago. Some browsers may no longer support it.

The impact of this on most users should range from minor to none. The browser will still require network access to the host web site, either to load the code or verify that the copies in its cache are still current. Once loaded into the browser and running, the emulator requires no further access to the host site, as before. If you want to run the emulator from a location that cannot access your host site, a possible option is to set up a web server on your local workstation. Only a very simple web server is needed. See "Setting Up a Web Server" in the Getting Started wiki for more information.

Floating Point Issues Corrected


I came across a set of floating-point diagnostic test routines at the Charles Babbage Institute (CBI) during a visit in October 2019. These looked interesting, so I transcribed them and got them to run in the retro-205 emulator. That exercise uncovered one bug in the emulator's implementation of floating-point arithmetic, and one aspect of the implementation that was incorrect, but relatively benign.
  • Floating Divide (FDIV, 83) should set the Overflow Toggle when dividing by zero. It was not doing this, however, when the mantissas of both the divisor and dividend were zero. This bug was due to testing the mantissas of the two operands for zero in the wrong order.
  • The emulator included code to pre-normalize the operands, i.e., shift the mantissa left and decrement the exponent until the high-order digit was non-zero. This was code carried over from the retro-b5500 emulator, which I used as a base for the implementation of floating point in retro-205. I discovered that the 205 always assumed the operands were normalized and did not adjust them before commencing an operation. All pre-normalization code has therefore been removed from the emulator.
The floating-point diagnostic routines are interesting, and I plan a future blog post to discuss them in more detail.

Breakpoint Switch on Control Console Corrected


In the process of getting the floating-point diagnostic routines to work, I discovered that the Breakpoint switch on the Control Console was not working correctly. Setting the switch to the "4" position did not cause the processor to halt after it executed an instruction having the 4-bit set in the fourth digit of the instruction word. Having the switch in the "2" position worked correctly. Having it in the "1" position also worked, but only accidentally -- a case of two errors canceling each other out. This bug was introduced version 0.04e (July 2015) as part of the change that caused the Breakpoint switch to reverse when it was clicked at either end of its travel. It is now fixed.

Rogue Paper-Tape Reader Brought to Heel


During the floating-point routine testing, I also discovered that the paper-tape reader stayed "hot" after clearing the system. If the device was hanging on a read command, waiting for a paper-tape image file to be loaded, then even though the processor had been halted and the system cleared, the reader would immediately start reading when a paper-tape file was loaded into it. It now detects the system clear operation and does not start reading the tape until specifically commanded to do so.

External Control Instruction Corrected


The External Control instruction (EXC, 71) was implemented in the 205 as a potential means for the system to control external equipment. There were eight external switches in the Model 421 External Switching Unit that could be set from the high-order eight digits (not including sign) of the memory word fetched by the instruction's operand address. See the DATATRON Command List (Bulletin 3030C, which follows the DATATRON 204 Central Computer Handbook at the link) for details.

The change in this release is a detail that Bulletin 3030C did not discuss, viz, if the low-order bit of the operand word's sign bit is set, the computer will halt in the same manner as for the Breakpoint switch, i.e., at the end of the instruction. This detail was discovered in a copy of Bulletin 3031, External Switching Unit Model 421 and Output Selector Unit Model 420 (Preliminary Edition), ElectroData Division of Burroughs Corporation, 1956.

Note that although the emulator implements the EXC instruction, it presently doesn't do anything except set flags internally in the Processor corresponding to the switches. In the future it could be possible to use these flags to control some new mechanism.

Cardatron Reader Format Lockout Corrected


The Cardatron interface to IBM punched-card equipment had a feature when reading cards termed "format lockout" that would prohibit the next card from being read automatically. It was triggered by an 8-punch on the card in the column used to determine which format band would convert the card punches to 205 memory words. Since the emulator uses ordinary ASCII text files as card decks, the concept of an "8 punch" does not translate well, and instead the emulator uses specific ASCII characters to encode the 8-punch along with another punch in rows 1-7 that indicates the format band to be selected.

Two of those ASCII characters were not represented properly in the code, the grave accent (`) for the 1-8 punch and the apostrophe (') for the 5-8 punch. This problem has been corrected. See the Cardatron wiki for the full list of format lockout codes.

Sunday, July 29, 2018

Algol-58 – The International Algebraic Language

By the early 1950s, the number and variety of electronic computers were increasing, the scope of their application to science, business, and government was rapidly expanding, and the demand for the programming those applications required was expanding in concert. This demand stimulated the need for increasingly efficient and effective ways to prepare programs, which in turn led to the development of higher-level programming languages.

One of the first attempts at designing a universal programming language, at least for numeric computation, was the International Algebraic Language (IAL), also known as Algol-58. The Burroughs Algebraic Compiler (BALGOL) for the 220 computer system was an early dialect of Algol-58. To prepare for a detailed discussion of BALGOL on the 220 in the next post [1], this post will discuss the development of Algol-58 and present an overview of the language.

Background


Initially, preparation of the program steps for machine execution was done entirely on the machine's terms. Instructions were prepared directly using the numeric or alphanumeric code required by the hardware. Hence the popular use of "code" and "coding" as synonyms for programs and programming. There is a lot of manual bookkeeping involved in programming at this level, especially in keeping track of addresses within the code for data storage and branch locations. That bookkeeping task is compounded when changes must be made to an existing program.

Mnemonic notations arose fairly quickly to ease the clerical task of coding, along with a number of higher-level abstractions, such as flowcharting, to aid in the overall conception and design of programs. Not long after, people began to realize that the machine itself could assist with the clerical aspects of generating code, especially in keeping track of address assignments. This led to the development of assembly languages and the assembler programs to process them.

From the very beginning of automated computing, though, there has been a strong desire to be able to approach programming more on our terms, in a way that is more in keeping with the way we think about the applications to which we want to apply a computer. Since most early applications involved numerical calculations based on mathematical formulae, there was an obvious desire to express programs using standard notations from mathematics. FORTRAN is one of the earliest and best known realizations of this desire, but as Donald Knuth made clear in his 2003 lecture, "A Dozen Precursors of FORTRAN" [2], attempts to express programs using higher-level abstractions can be traced all the way back to Konrad Zuse during the 1940s.

A parallel desire has been to be able to express programs in a more general way than in the coding for a specific type of machine. The half-life of a given computer design in the 1950s was only a couple of years, so as new designs came along, existing programs had to be completely redone using the instruction coding for each new machine. Being able to express programs in a way that was not specific to any particular machine would ease this burden. It would also open the possibility of more easily adapting programs written for one machine so that they could run on entirely different ones.

Many efforts towards translation of standard arithmetic expressions into machine instructions were going on, starting in the early 1950s. A preliminary report on FORTRAN was available by 1954, but other languages were starting to appear, such as Alick Glennie's Autocode, Alan Perlis' Internal Translator (IT, also known as the Purdue Compiler), and Grace Hopper's A0 and MATH-MATIC. There were also a number of interpretive expression evaluators, such as the Whirlwind Algebraic Interpreter. By the second half of the 1950s, the number of different (and incompatible) programming notations was beginning to proliferate.

In 1955, the German Association for Applied Mathematics and Mechanics (GAMM) held a meeting in Darmstadt on electronic computers. This resulted in the formation of a committee to work on formula translation. Then in May 1957, the Association for Computing Machinery (ACM), SHARE (the IBM user organization), USE (the Sperry Univac user organization), and DUO (the ElectroData/Burroughs user organization) held a conference in Los Angeles to explore the exchange of computing information. The group concluded that a single, universal programming language would be very desirable, and recommended that the ACM form a committee to pursue the idea. A few months later, the GAMM group reached a similar conclusion and contacted the ACM to suggest a joint conference that would make recommendations on a common language.

By April 1958, both the ACM and GAMM committees had independently developed proposals for a universal language and met to exchange them. They found they had much in common, so arranged to hold a joint working session between representatives of each group to combine their proposals and resolve the differences. That joint session was charged with the following objectives [3]:
  1. The new language should be as close as possible to standard mathematical notation and be readable with little further explanation.
  2. It should be possible to use it for the description of computing processes in publications.
  3. The language should be translatable into machine programs.
The joint ACM-GAMM meeting was held in May 1958 at ETH in Zurich, Switzerland. The product of that meeting was the "Preliminary Report—International Algebraic Language" [3]. The language was initially referred to as the IAL, but the name was soon determined to be unsuitable, and Algol, short for "algorithic language," was suggested instead. The successor to the preliminary IAL was known as Algol from the start, so to distinguish them, the IAL eventually became known as Algol-58 and its successor as Algol-60.

FORTRAN had been released by IBM for almost a year by the time of the 1958 ACM-GAMM joint session in Zurich. FORTRAN was being received warmly, especially by the scientific community. It was not exactly an attractive notation, though, and was certainly not an ideal way to exchange definitions of algorithmic processes, especially among people accustomed to the elegance of mathematics. Even John Backus, the driving force behind FORTRAN, could not have been completely pleased with it, as he was one of the ACM representatives to the Zurich joint session. Thus, there was motivation to come up with something much better.

Overview of Algol-58



This section attempts to describe the IAL as presented in the Preliminary Report in somewhat informal terms. It largely follows the structure of that Report.

Symbology

 
Algol-58 uses a 63-character set, which allowed for a number of traditional mathematical symbols, and may have been influenced by six-bit codes for teletype and punched paper-tape equipment. Early FORTRAN, of course, had been limited by the 48-character set used in IBM punched-card equipment.

The basic symbols defined for the language are:
  • The 26 English letters: A-Z [including both upper and lower case; the report is silent on the subject of case sensitivity]
  • The decimal digits: 0-9
  • Arithmetic operators: +     ×   /
  • Relational operators: <      =      >  
  • Logical operators: ¬ [not]   [or]   [and]   [equivalence]
  • Sequential operators: go to,   do,   return,   stop,   for,   if,   or,   if either,   or if
  • Separators: .   ,   :   ;   :=   =:      10   begin   end
  • Brackets: (   )   [   ]     
  • Declarators: procedure,   array,   switch,   type,   comment
The role of spaces is not described in the Preliminary Report. It seems likely the intent is that, as in FORTRAN, spaces can be inserted for readability, but they do not serve as delimiters, and their presence or absence does not affect the interpretation of the program text.

Note that, as with Algol-60, the boldface words in the lists above are considered not to be identifiers or sequences of characters, but atomic symbols in their own right. Thus, "go to" is not two words or five characters, but a unique symbol in the language. The subscripted "10" is used to indicate the power-of-10 scaling factor for numbers in scientific notation.

Also note that this is the symbol set for the reference language, which is intended to specify the language itself and not necessarily be used for coding programs or publishing algorithms. The report anticipated that a more restricted set of characters, a hardware representation, would need to be used by an actual compiler targeting a real machine. It also anticipated that an expanded set of characters might be used in a publication language used to communicate algorithms in the literature. Each instance of a publication language or hardware representation is to be accompanied by a set of transliteration rules for mapping to and from the reference language.

Data Types and Declarations


The Algol-58 report specifies three data types – integer, real (floating-point), and Boolean (logical) values, plus arrays of these entities. It appears to anticipate the use of additional types, but is silent on how they should be handled.

Literals


Numeric literals have the general form I.F10±E, where I is a whole integer, .F is a decimal fraction, and 10±E is a scaling factor as a power of ten. The fraction and scale factor are optional, as is the sign preceding the exponent of the scaling factor. A number could also be expressed as simply a scaling factor by omitting the integer 1 before it, e.g., "10-3" for 0.001.

Boolean literals are represented as the integer literals 0 [false] and 1 [true].

Identifiers and and Types


Identifiers are defined in the usual way, starting with a letter and optionally followed by a string of letters and decimal digits. No maximum length for an identifier is specified.

By default, all identifiers are considered to refer to variables of type real. A type declaration can be used to specify that an identifier refers to an integer or Boolean variable. Note that the type declaration does not define a variable or assign it storage. The declaration merely associates a type with an identifier. Variables are declared upon first reference to their identifiers, which need not appear in any type declaration.
integer (i, j, k); Boolean (on, off);

Array Declarations


Array declarations name a list of identifiers to be considered as arrays and to specify the bounds of each array's dimensions. The bounds notation is a little different from Algol-60 -- all of the lower bounds are specified first in a comma-delimited list, then a colon (:), then the corresponding upper bounds are specified in a second comma-delimited list. The Report specifies the bounds to be "integers," so it appears that dynamic array sizing is not supported. Multiple array identifiers can be associated with a common set of bounds, as in Algol-60. If an array is to be of a type other than real, it must appear in a type declaration, and must be followed by square brackets containing sufficient commas to indicate the dimensionality of the array:
integer i, j, m[], n[,,];
array a, b, c[1:10], d[0, 0:7,19], m[-7:7], n[1,1:9,9];

Switch Declarations


A switch defines a multi-way branch, after the idea of the computed go-to in FORTRAN, but essentially the same as switches in Algol-60. Note that it is a declaration, not a statement. It defines an ordinal list of designational expressions, which are either simple statement labels or indexed switch identifiers. A statement label may be an identifier or a literal integer.

A switch is used by the go to statement, which takes as its target not a label, but the more general designational expression construct. The index used with a switch identifier is evaluated dynamically, not only for a switch named in a go to statement, but also for any switch identifiers used in designational expressions within switch declarations. Thus the evaluation of a designational expression may result in a cascade of switches being evaluated before a label is finally encountered and the destination of a branch determined.
switch s1:= (start, 44, s2[i×j-1], s1[k]);
switch s2:= (5, 4, 3, 2, 1, blastoff);

go to s1[3];

Comment Declarations


Algol-58 considers a comment to be a declaration. It can appear between any instance of other declarations and statements, but otherwise has no effect on the meaning of the program. Like the Algol-60 comment, it starts with the symbol comment and continues until the next semicolon (;) is encountered.

Function Declarations


Algol-58 supports the declaration of an expression as a function, similar to the in-line function of FORTRAN. The function defines a list of parameters, the actual values of which will be substituted into the expression. Any variables in the expression not named in the parameter list are referenced globally in the containing program.

toRads(degrees) := degrees×3.1415926/180;
Pythagorean(a, b) := sqrt(a↑2↓ + b↑2↓);

length := Pythagorean(base, height);
The language also supports procedure declarations and calls. These are a more complex subject, and are discussed in a separate section below.

Expressions


Expressions in Algol-58 are formed in the usual way, from combinations of variable references, function calls, and operators of various types. The values of scalar variables are referenced as simple identifiers. Elements of arrays are referenced as the identifier for the array, followed by a comma-delimited list of subscripts in square brackets ([ ]). Subscripts can be general arithmetic expressions, which are rounded to integers before indexing into the array.

Functions (and procedures that return values as a function) are evaluated by naming the function, followed by a comma-delimited list of expressions in parentheses corresponding by position to the parameters of the function, as shown in the example for the Pythagorean function declaration above.

Arithmetic Expressions


An arithmetic expression, A, may take any of the following forms:
  • A numeric literal, e.g., "123.456"
  • A simple identifier, e.g., "alpha"
  • A subscripted identifier, e.g., "points[i, j]"
  • A function call, e.g., "Pythagorean(x, y)"
  • An arithmetic expression prefixed by "+" or "–", e.g., "–A"
  • Two arithmetic expressions joined by an arithmetic operator (+ - × /), e.g., "A/7.0"
  • One arithmetic expression followed by a second arithmetic expression in up/down arrow brackets to indicate the first expression raised to the power of the second expression, e.g., "A1↑A2↓"
  • An arithmetic expression in parentheses, e.g., "(A)"
Evaluation of arithmetic expressions is by default from left to right, with multiplication and division having precedence over addition and subtraction. The Report is silent on the precedence of exponentiation, but presumably it is higher than multiplication/division. Parentheses may be used to alter or make clear the precedence by which operators are to be applied to values.
alpha
alpha + beta / gamma
(alpha + beta) / gamma
a↑2↓ / 2↑b-1↓
(m[i] + n[j, k])×(m[j] - n[k, i])

Boolean Expressions


A Boolean expression, B, may take the following forms:
  • The literal value for false, e.g., 0
  • The literal value for true, e.g., 1
  • A simple or subscripted identifier, e.g., "empty" or "flags[k]" 
  • A function call, e.g., "testValid(assertions())"
  • An arithmetic relation, consisting of two arithmetic expressions (A) separated by a relational operator (< = > ) and enclosed in parentheses, e.g., (A1 < A2)
  • A Boolean expression prefixed by the not operator, e.g., ¬B
  • Two Boolean expressions separated by a Boolean operator ( ), e.g., B1 B2
Evaluation of Boolean expressions is strictly left to right. Parentheses must be used to specify any operator precedence. The not operator applies only to the expression immediately to its right.
(alpha ≥ beta) (gamma ≠ epsilon) override

Statements


The individual operations of a program are defined by statements. As is typical, statements are executed sequentially unless directed otherwise by a containing statement. Algol-58 is a free-form notation, without particular line-length or columnar conventions. Statements are separated by (not terminated by) the semicolon (;). The end of a line or record in the program text has no syntactic significance.

Algol-58 introduced the idea of a compound statement by using the symbols begin and end to bracket a sequence of individual statements. The compound statement may then be used in any place that an individual statement can be used, e.g., as the object of an if or for statement. There is no provision for an empty or null statement, so strictly speaking, a semicolon cannot precede an end.

Statements can be prefixed by a label and a colon (":"), which serves to declare the label. The label can be an identifier or an integer literal. If a compound statement has a label, then the terminating end of the compound statement may optionally repeat the label to indicate the span of the compound statement, e.g.,
start:
        begin
       
x:= x+1;
        if (x < 100);
                go to start;
        end start
Declarations may be interspersed with statements. The order and placement of declarations within a program is immaterial. Algol-58 did not support the Algol-60 concept of blocks, where declarations within a compound statement create a nested identifier scope, which has visibility of the identifier scopes of all containing blocks. Declarations embedded within compound statements are interpreted as if they were placed outside any compound statement.

Assignment Statements


The assignment statement works similar to that in most languages. The identifier of a variable (possibly subscripted) on the left is assigned the value of the expression on the right. The assignment operator is ":=", a standalone equal sign ("=") being reserved for use in arithmetic relations.

If the variable on the left of the assignment operator is of an arithmetic type, the expression on the right must yield an arithmetic value. The Report implies that the value of the expression will be coerced as necessary to the type of the assignment variable, but does not explicitly say so. Mixed integer/real expressions are permitted, but the Report does not say how the resulting type of an expression should be determined.

If the variable on the left is arithmetic and the expression on the right is Boolean, the truth value of the expression will be converted to an integer 0 if it is false or 1 if it is true. The converse is not true, however -- only Boolean expressions can be assigned to Boolean variables.

Go To Statements


The go to works as in most languages, except that as noted earlier, the operand of a go to is a designational expression. Thus you can branch to a simple label or to an indexed switch identifier. As also mentioned earlier, all designational expressions in switches are evaluated dynamically using the current values of their index expressions. Index expressions are ordinal (i.e., one-relative). The Report is silent on the behavior of a switch when its index is less than one or greater than the number of designational expressions in its declaration.

If Statements and Alternative Statements


The if statement works as in most languages, except that it serves only as a guard for the next statement. There is no else in Algol-58. The guarded statement may of course be a compound statement. The condition to be tested may be any Boolean expression.
if (i > 0);
        if (j < i);
                j := i+1;
Algol-58 implements a variant of the if statement that functions as a skip-chain. Each if either or or if is evaluated in sequence, the statement associated with the first condition that evaluates true is executed, and any remaining conditions and statements are skipped. There is no provision for a default or catch-all statement if none of the specified conditions is met:
if either (i = 1);
        j := i+1;
or if (i = 2);
        j := i+2;
or if (i = 3);
        j := j+i;
or if (i > 3);
        begin
        if (j > 0);
                j := i;
        if (j < 0);
                j := 0;
        end
end

For Statements


The only iterative statement in Algol-58 is the for statement, which extended FORTRAN's idea and anticipated the complex for statement of Algol-60. Specification of the sequence of values over which iteration will occur has two forms. The first is a simply comma-delimited list of arithmetic expressions. The control variable is assigned the value of the next expression in the list at the start of each iteration. When the end of the list is reached, the loop terminates:
for x := 2, 4, 5, 9, 16, 27, 31, -1;
        cell[x] := cell[x]×3;
The second form is more like that of FORTRAN, with initial, increment, and final values for the control variable. Each value may be an arithmetic expression. The middle expression in parentheses is the increment value:
for x := 1 (1) n-1;
        begin
    
   if (cell[x] < 0);
                cell[x] := -cell[x];
        if (cell[x] > 0);
                cell[x] := 1
       end
The two forms can be combined to iterate over a complex sequence of values:
for x := 1, 5, 8, 99 (-7) 9, 101, 127, i (j) k, 255;
        begin ... end

Do Statements


The do statement is not so much an executable statement as a generator of executable statements. It is more in keeping with the idea of a macro. This is best illustrated with a simple example:
first: A := (B) / (C);
last:  go to D;
...
do first, last (resultA, alpha×beta-1B, gammaC, topD)
The do statement names a range of other statements identified by the labels of the first and last statements in the range. A one-statement range may be specified using a single label. The entire do statement is replaced by a copy of that range of statements, less the bracketing labels and any embedded declarations. Within the copy, each of the identifiers on the right of an arrow ("") is replaced by the corresponding sequence of symbols on the left of the arrow. In the example above, the do statement would be replaced by:
result := (alpha×beta-1) / gamma;
go to  top;
The range of statements copied by a do statement can itself contain do statements, in which case any nested do statements are replaced first, so that the final text contains no do statements.

Stop Statements


The stop statement terminates execution of the program. No resumption of execution from the stop is possible.

Procedure Declarations and Procedure Calls


The concept of a procedure in Algol-58 is that of a closed subroutine having possibly multiple entry and exit points. All identifiers referenced within the body of a procedure refer either to locally-declared variables and labels or to the formal parameters of the procedure. Global variables in the containing program are not visible within the procedure unless they are passed as parameters. Variables local to the procedure body are not visible outside the procedure.

Procedure Declaration


Parameters to a procedure are classified as either input parameters or output parameters and are specified in separate parameter lists delimited by a "=:" symbol. The general form of a procedure declaration is:
procedure I1 (Pi1) =: (Po1),    I2 (Pi2) =: (Po2),    I3 (Pi3) =: (Po3), ...
where the In are the identifiers of entry points within the procedure. Each such identifier must also be a label within the body of the procedure that defines the location where that entry point will commence execution.

The Pin are lists of formal input parameters that supply values to the procedure, and the Pon are lists of formal output parameters that receive results from the procedure. The formal variables in the lists can, of course, be different for the different entry points.

Formal input parameters may consist of a scalar identifier, an array identifier followed by some number of empty subscript positions in square brackets (to indicate the dimensionality), or a function or procedure identifier followed by some number of empty parameter positions within parentheses (to indicate the number of parameters to the formal function or procedure).

Formal output parameters may consist of a scalar identifier, an array identifier with empty subscript positions as for input parameters, or a label identifier. The output parameter list and its preceding "=:" can be omitted, in which case the procedure can be called as a function and be used within an expression. The return value is defined by assigning it to the entry label identifier as if it were an ordinary scalar variable, similar to the method used in Algol-60. See the example below for an illustration of this.

Following the procedure heading defining the entry points and parameter lists, there can be a set of declarations supplying type information for the formal input and output parameters. The type for label parameters is deduced from the context of their use in the body of the procedure. Surprisingly, array declarations for formal parameters can have expressions in their bounds lists, provided any identifiers in the expressions are formal parameters Undeclared formal parameters are of type real, as usual. The body of the procedure follows this, and must be enclosed in a begin/end pair. Any declarations within the body of the procedure refer only to local variables.

Procedure Call Statement


A procedure call statement states the identifier of a procedure entry point, followed by input and output lists for the actual parameters, with the two lists again delimited by "=:". The Report specifies that in the call, the replacement of formal parameters by actual parameters "may be considered to be a replacement of every occurrence within the procedure of the symbols (or sets of symbols) listed in formal parameters, by the symbols (or sets of symbols) listed as actual parameters in the corresponding positions of the procedure statement, after enclosing in parentheses every expression not enclosed completely in parentheses already." This seems to be an early form of call by name, which was more fully developed in Algol-60. There is no call by value, even for input parameters.

The report allows array slices to be passed to array parameters. The dimensionality of the actual parameter slice must match that of the formal parameter, i.e., the number of empty subscript positions in the actual and formal parameters must be the same. More interestingly, functions and procedures passed as actual parameters may have a mixture of supplied and empty parameters. Again, the number of empty parameters must match between the actual and formal parameters. This appears to imply support for currying or closures.

Exit from a procedure is accomplished using either the return statement (which can only occur within the body of a procedure) or a go to statement referencing (perhaps indirectly through a switch) a formal label in the output parameter list. Providing multiple exits from a subroutine was a common technique in machine-language programming at the time, so label parameters attempt to provide a similar facility. Each path of execution from an entry point must eventually reach a return or a go to referencing a formal label. The behavior if execution runs off the end of the procedure body without executing a return or a go to referencing a formal label is not defined.

Example Procedure


The Report show an example procedure declaration for Simpson's Rule integration. It is reproduced below, without its comments, with semicolons inserted between statements, and reformatted into a more modern style. Note that "F()" indicates a formal function with one parameter, and "abs()" is an intrinsic function defined by the Report with the customary meaning of absolute value:
procedure Simps (F(), a, b, delta, V);
        begin
Simps:
        Ibar := V×(b-a);
        n := 1;
        h := (b-a)/2;
        J := h×(F(a) + F(b));
J1:
        S := 0;
        for k := 1 (1) n;
                S := S+F(a + (2×k-1)×h);
        I := J + 4×h×S;
        if (delta < abs(I-Ibar));
                begin
                Ibar := I;
                J := (I+J)/4;
                n := 2×n;
                h := h/2;
                go to J1
                end;
        Simps := I/3;
        return;
        integer (k, n)
        end Simps
A call on this procedure might look like this, where "poly()" is some function or value-returning procedure defined elsewhere in the program:
area := Simps(poly(), x, x+20, 210-5, 51025);

Impact of the Preliminary Report


Perhaps the most enduring impact of the Preliminary Report was upon the continuing effort to refine the language, resulting two years later in publication of the 1960 "Report on the Algorithmic Language ALGOL 60" [4], followed by the 1963 "Revised Report on the Algorithmic Language Algol-60" [5].

As should be clear from comments in the overview above, the Algol-58 Preliminary Report is not a complete specification for a programming language, nor was it ever intended to be. The first sentence in the report makes this clear:
Note: In the interest of immediate circulation of the results of the ACM-GAMM committee work on an algebraic programming language, this preliminary report is presented. ... This report has not been thoroughly examined for errors and inconsistencies.
The Report leaves many things unsaid, and not a few unclear. It should be viewed for what it was, a progress report on an effort to define a universal algorithmic language. Many ideas that became more fully developed in Algol-60 appear in this Report, and no doubt a great deal was learned from its preparation about how a language should be specified, leading to the development of Backus-Naur Form and the elegant syntax-and-semantics presentation of the Algol-60 report.

Nonetheless, the Report was good enough, and the ideas in it attractive enough, to get a lot of creative juices flowing.

The first compiler for Algol-58 was running by the end of 1958 on a Zuse Z22 computer in Mainz, Germany. It was constructed by the so-called ZMMD group, consisting of Friedrich Bauer, Hermann Bottenbruch, Heinz Rutishauser, and Klaus Samelson, the GAMM representatives to the joint working session that produced the Report. That this compiler was available only six months after the joint session may indicate the extent to which the GAMM proposals formed the core of the preliminary language and how far along the ZMMD group was towards creating a compiler at the time of the joint session.

Availability of the Preliminary Report quickly launched the development of many other hardware implementations of Algol-58, all deviating in greater or lesser degrees from the reference language described by the Report. The best known of these are:
  • ALGO (Bendix Corporation, Los Angeles, California: Bendix G-15)
  • ALGOL 30 (Dartmouth College, Hanover, New Hampshire: Librascope LGP-30)
  • BALGOL (Burroughs Corporation, Pasadena, California: Burroughs 220)
  • JOVIAL (System Development Corporation, Santa Monica, California: multiple targets)
  • MAD (University of Michigan, Ann Arbor, Michigan: IBM 7090, Univac 1108)
  • NELIAC (Naval Electronics Laboratory, San Diego, California: multiple targets)
BALGOL followed the syntax and semantics Preliminary Report quite closely and implemented most of its features, although sometimes with slightly different syntax. In the next post [1], we will examine BALGOL in some detail and see its adaptation of Algol-58.

References


[1] "BALGOL – the Burroughs Algebraic Compiler,"
http://datatron.blogspot.com/2018/08/balgol-burroughs-algebraic-compiler.html
[2] "A Dozen Precursors of FORTRAN," Donald Knuth, lecture on 2003-12-03, Computer History Museum, http://www.computerhistory.org/collections/catalog/102622137.
[3] "Preliminary Report--International Algebraic Language," Communications of the ACM, vol. 1 #12, December 1958, pp. 8-22,
http://www.softwarepreservation.org/projects/ALGOL/report/Algol58_preliminary_report_CACM.pdf.
[4] "Report on the Algorithmic Language ALGOL 60", ed. Peter Naur, Communications of the ACM, vol. 3, #5, May 1960, p.299-314,
http://www.softwarepreservation.org/projects/ALGOL/standards/report/Algol60_report_CACM_1960_June.pdf.
[5] "Revised Report on the Algorithmic Language Algol-60," ed. P. Naur, Communications of the ACM, vol. 6 #1, January 1963, p. 1-17,
http://www.softwarepreservation.org/projects/ALGOL/report/Algol60_report_CACM_1960_June.pdf.


Wednesday, February 28, 2018

Introducing the Burroughs 220

The Burroughs 220 was a late-1950s decimal, vacuum-tube, core-memory computer system. It was the successor to the ElectroData/Burroughs Datatron 205 system. It shared many of the 205's characteristics while improving upon several others. It was also the first new system to be released under the Burroughs name after Burroughs acquired ElectroData in mid-1956.

The 220 was perhaps the last major vacuum-tube computer design to reach the market. It did so as IBM, Philco, and Univac were announcing, and in some cases delivering, transistor designs. Because of this, the 220 did not sell particularly well, but it was popular with universities and research establishments, and it laid groundwork for the much more successful Burroughs systems that followed it, particularly the B5500.

This blog was re-titled for the Burroughs 205 and 220 a year ago, and we haven't said a peep about the 220 -- until now. This is Paul Kimpel with our initial post on that computer system. It will introduce the architecture and components of the 220, compare them to the earlier 205, and give a brief overview of our project to build an emulator and recover software for the machine.


Genesis of the Burroughs 220


By the mid-1950s, the ElectroData 205 had become a successful product. It was a relatively low-cost computer system for its day, but due to its drum memory and digit-sequential internal operation, it was also relatively slow. It had robust magnetic tape and punched-card facilities, however, and even though it had originally been designed with scientific computation in mind, these input-output facilities gave it an entry into businesses with a need to process large repositories of data -- the field of "commercial" data processing.

ElectroData needed to pursue these commercial customers and workloads if it was to stay in the computer business, and for that they would need a new, larger, faster system. They saw an opportunity to produce a larger system at a lower price point than competing systems of comparable size. The problem was that they were extremely strapped for capital just to continue their current operations, let alone to design and build a new system. The situation was so acute that, by early 1956, ElectroData was seriously considering terminating operations and closing the business. It was precisely at that point that Burroughs, having significantly more capital, and looking for an acquisition to boost their attempts at entry into the commercial computer business, came calling.

Prior to this, ElectroData had studied the possibility of modifying the 205 to use magnetic core memory instead of a drum. That idea proved not to be viable, for both technical and economic reasons, but it did initiate some preliminary work on a design, known as Project 737, for a new system that would use core memory.

As ElectroData's acquisition by Burroughs was closing, this new design was chosen over the BEAM IV, a system designed under the direction of Issac Auerbach at the Burroughs Research Center in Paoli, Pennsylvania. Project 737 became the Burroughs 220. While Paoli had their BEAM IV canceled, they did get to build the core memory for the 220.

The 205 and 220 are sometimes referred to as the B205 and B220. This is incorrect. The Burroughs B200-series systems, which eventually expanded to the B100/200/300/500-series, came immediately after the 220, ca. 1960. They were small, transistorized, variable field-length, character-addressable computers. Architecturally, they were very different from the 205 and 220. They were, however, somewhat similar to -- and competed against -- the IBM 1401.

Since the 220 is an outgrowth of the 205, and retained a number of the 205's characteristics, let us first review the architecture of the 205 and then see how the 220 differed.


A Review of the ElectroData 205


The 205 was initially conceived at Consolidated Electrodynamics Corporation (CEC) as a digital calculator. CEC made mass spectrometers, and analysis of the data coming from these instruments requires solving systems of simultaneous linear equations. By the mid-1940s, CEC had built analog devices that could solve  systems with up to 12 unknowns, but to solve larger problems they needed to go digital.

CEC recognized early that the calculator would have additional potential if developed as a fully-programmable computer, so they expanded their scope and designed a system initially known as the CEC 30-201. The development proceeded through models -202 and -203, at which point CEC spun off the computer business as ElectoData, and the 30-203 became the Datatron 203. The 203 had only paper-tape input/output, plus a 10-character per second Flexowriter printer. Enhancements to support magnetic tape resulted in the Datatron 204, and finally adding the Cardatron punched-card interface resulted in the Datatron 205.

ElectroData/Burroughs 205 System

205 Drum Memory


The design of the 201 through 205 systems was oriented around their drum memory. Data was stored on the drum as 44-bit words, with each word organized as 11 four-bit BCD digits. The high order digit was used as the sign, with the low-order bit of that digit indicating positive (0) or negative (1). The other three bits of the sign digit were not generally defined for internal processor operations, but did have significance in some I/O operations. The remaining 10 digits of a word represented either a signed-magnitude decimal number or five alphanumeric characters. As an option, the later systems supported floating-point arithmetic, which used the high-order two digits of a word as an exponent biased by 50 and the low-order eight digits as a fractional mantissa. The sign digit retained its meaning in floating point as for integer values.

The memory drum was organized in 24 tracks of 200 words each. It rotated at 3750 RPM, so a full revolution took 16.8 milliseconds. Switching between tracks took negligible time, but the average latency until a desired word came under the read/write head was half a revolution, or 8.4ms. This was slow -- compare it to the IBM 650's drum, which rotated at 12,500 RPM. The choice of a slower drum was apparently made for reasons of cost and reliability.

205 Memory Drum


20 of the tracks on the drum formed the computer's main memory of 4000 words. To help compensate for the slow access time, the other four tracks were organized as recirculating delay lines, termed the high-speed loops, with the read and write heads separated by one-tenth of a revolution. This allowed storage of only one-tenth the number of words (20) per track, but with one-tenth the access time (0.84ms average). Special instructions could block 20 words in the main memory to or from one of the loops in a single drum rotation. Executing instructions and accessing data in the loops was almost ten times as fast as main memory. Doing so was highly desirable, but programming for it was complicated by the need to block and unblock words explicitly between the loops and main memory.

The drum was so central to the design of the system that even the clock signals for the electronics came from it. Prerecorded tracks provided pulses for digit and word timing, plus a once-per-revolution signal to assure that the processor's address coincidence logic stayed in sync with the drum. These timing tracks gave the 205 an effective clock rate of 142.8 KHz.

205 Registers and Data Flow


The 205 had the following major registers:
  • A -- the accumulator.
  • R -- the "remainder" or accumulator extension of 10 digits. Digits could be shifted between this register and A, but R could not be loaded or stored directly. The Multiply instruction multiplied A by a value in memory, producing a 20-digit product in A and R. The Divide instruction divided the 20-digit value in A and R by a value in memory, leaving the quotient in A and the remainder in R. R was also used to store the return address in subroutine-branch instructions.
  • B -- the index register. The ElectroData 203/204/205 were the first commercial systems in the U.S. to offer this form of address abstraction, although the idea appears to have come from the UK Manchester Mark 1 by way of Harry Huskey, who consulted with the original CEC design team.
  • C -- the "command" register holding the current instruction. This 10-digit register held the two-digit operation code, the four-digit effective operand address, and the four-digit address of the next instruction to be executed. By default, the instruction address incremented automatically during fetch of an instruction into C. Branch instructions simply replaced this default address with the effective address from the branch instruction.
  • D -- the "data" register. It buffered a word coming from memory or a peripheral device.
Each track on the drum was recorded bit-parallel but digit-sequential. That is, each digit-wide logical track consisted of four bit-wide physical tracks. Data entered the processor from memory or the peripheral devices one digit at a time into the D register. Data exited the processor for storage in memory or writing to peripheral devices one digit at a time through the A register. Because words entered the processor low-order digit first, buffering an incoming word in this register also allowed the processor to examine the sign -- which arrived from the drum last -- before commencing an arithmetic operation.

Since the data came into and left the processor in a digit-sequential manner, all internal processing was done digit-sequential as well. The adder was only one digit wide, and all inter-register transfers occurred one digit at a time. In fact, all inter-register transfers went through the adder, which would actually add or not, depending on the operation. The digit-sequential design also reduced the complexity of the electronics, helping keep the size and cost of the system down.

Burroughs 205 Processor Data Flow

205 Instruction Format


Words holding executable instructions had the following format:

± CCCB PP AAAA

where:
  • ± is the sign digit. If the low-order bit of this digit is 1 (negative), the contents of the B register are added to the AAAA field as it is transferred into the C register, thus indexing the operand address prior to instruction execution.
  • CCC are the so-called "control" digits. These had significance primarily for I/O instructions.
  • B is the breakpoint-skip digit. Bits in this digit would cause the computer to halt or skip the instruction based on switches set on the Control Console. It was used for program debugging.
  • PP is the operation code, e.g., 74 for Add or 20 for Change [Branch] Unconditionally.
  • AAAA is the operand address. In most instructions it referenced an address on the drum, but in some instructions, such as shifts, it signified a count, and in others it had no significance. B-register modification of this field would occur regardless of its significance.
With this background on the 205, we can now examine how the design of the 220 differed.

The Burroughs 220 Architecture


Both architecturally and electronically, the 220 was quite similar to the 205. It was still a decimal, vacuum-tube design. The 220 retained the 205's 11-digit word format, instruction format, and numeric representation. Core memory replaced the drum. Memory sizes could range from 2,000 to 10,000 words in 1,000-word increments. A typical memory size was 5,000 words. There being no drum, the clock was supplied by an oscillator circuit, and at 200 KHz, was only slightly faster than the 205's 142.8 KHz rate.

The Operational Characteristics manual describes the architecture, instruction set, and input/output devices in detail.

While the 220 retained the instruction word format of the 205 and many instructions worked similarly, the operation codes and control (now termed "variant") digits were entirely different. Programs for the 205 had to be rewritten to run on the 220. That said, the 220 was a much easier system to program than the 205, first because the design headache of blocking 20 words at a time into the high-speed loops was no longer an issue, and second because the 220 had a more powerful instruction set.

Burroughs 220 System

220 Registers and Data Flow


The 220 retained the same major registers as the 205, but with a few changes and additions:
  • The A and D registers were the same, except that now data both entered and left the processor through D.
  • The R register had the same function in arithmetic and shift operations, but was expanded to 11 digits to accommodate a sign digit. It no longer stored the return address for a subroutine call. R could also be loaded and stored directly from and to memory, and could be compared directly to a word in memory.
  • The C register was still 10 digits and held the op code and effective address, but not the address of the next instruction to be executed (see P below). It was a copy of the instruction word from memory, without the sign, and after any B-register indexing of the address field had been applied. Therefore, it also held the variant digits from the instruction word.
  • The B register was the same, although there were additional instructions for loading, incrementing, decrementing, and branching based on its value.
  • A new register, P, was implemented to hold the next-instruction address.
  • A new register, E, was implemented to hold the address of a word to be loaded from or stored to the core memory.
  • A new register, IB (input buffer), was implemented to hold the word loaded from or stored to memory. Words were generally transferred to and from this register and the D register, but not always.
  • A new register, S, was implemented to replace the function of the breakpoint digit in instruction words. You could set an address in this register and enable it with switches on the console. When execution reached that address, the processor would halt.
 All of these registers except for IB were shown on the 220's rather fancy console:

220 Control Console


The 44 bits of a word were transferred in parallel between the core memory and the IB register in a single five-microsecond clock cycle. Then the data moved between IB and D, and through the other registers, in the same digit-sequential fashion as in the 205. The adder was still only one digit wide, and most inter-register movement continued to be gated through it.

220 Processor Data Flow

This sequential operation and the only modestly-faster clock meant that the internal performance of the 220 was little better than that of the 205. Most of the system's speed increase came from eliminating the latency of the drum memory.

Retention of digit-sequential operation appears to have been a conscious decision, probably to reduce the cost of the system and allow it to come to market more quickly. An internal ElectroData memo from 5 June 1956, after the Burroughs acquisition was announced but before it closed, stated:
The basic configuration of the 220 will be the same as the 204, with the exception of the Core Memory. New circuitry in the 220 will be held to a minimum. Generally the plug-in [vacuum tube] packages will remain the same.

We do know that the concept of the 220 was not fully realized in the design that was finally built, at least in the mind of its chief logician, Edward (Ted) Glaser. In his 1973 oral biography, on file at the Smithsonian National Museum of American History, he had this to say (page 24):
It turns out that what the 220 was supposed to be was the 205, with the loops removed, the recirculating loops, and a small core memory put in. That was my assignment. And it became quite clear that with the speed of core that was then available, this couldn't be done and it was a ridiculous balance. There was no way I could prove that to anyone. So I did one of the lowest-down, dirtiest tricks I've ever done. I designed five machines before I told anybody about any of them. And each one had glaring faults. And I was able to escalate Burroughs from one machine to the next. Well, it turned out we got stuck on four. We didn't build five. So four -- 220 was the fourth in the series. It was not the machine I really wanted to build, but it was close to it.
At that point, Glaser appeared to start to talk about the fifth design, but the interview was interrupted, and it never came back to this topic. So we'll never know what he had in mind for his fifth design, or the ways in which he thought the 220 as built was still deficient.

220 Partial-Word Operations


Aside from the advantages that retaining the digit-sequential operation had for cost and time to market, the most beneficial was that it enabled a very useful new feature -- operation on partial words.

The digits in a 220 word are numbered as follows:

±   1 2 3 4   5 6   7 8 9 0

where ± is the sign digit and "0" is interpreted as 10. A "partial word" is a contiguous field of digits denoted by a two-digit pair, referred to as sL (start-Length). The first digit of the pair specifies the starting digit in the field; the second digit specifies the field length. The field therefore consists of the digit numbered s and the L-1 digits to its left. A length of zero is also interpreted as 10.

Thus, the operation code in a word can be referred to as the 62-field -- digit #6 and the digit to its left. The low-order four digits comprising the operand address are the 04-field. The entire numeric portion of the word (all but the sign) is the 00-field. The sign could not be the starting digit of a field, but in most contexts could be included in a partial-word field. Field overflow was not permitted, however -- the sign digit was as far to the left as a field could go. If an sL digit pair had L > s+1, the processor would halt with a Program Check alarm. An sL = 12 field is valid; a 13 field is not.

Partial-word operations were implemented as variations on shifting. Like the 205, the 220 could physically shift or rotate its registers only to the right. Left shifts were actually rotates to the right for the complementary number of digits. In a partial-word operation, the word is simply rotated to the right until the s digit is in the low-order or "0" position, from which it can be transferred to and from the adder. Then it and the next L digits are operated upon (add, transfer, etc.), and finally any remaining digits are again simply rotated until the word is back in its original position. This behavior was mechanized using a special register, DC, the Digit Counter.

Partial-word fields were supported in the following operations:
  • Branch on equality of a two-digit value compared circularly to a field in register A or R.
  • Compare a field in A or R to a corresponding field in a memory word and set the Compare Indicator, from which branches could be made based on a low, equal, or high condition.
  • Increase or decrease a field in a memory word by a four-digit value, leaving the other digits in the word unaffected.
  • Decrease a field in a memory word by a four-digit value (possibly zero), then load the high-order digits of the resulting value in the field into the high-order digits of B.
  • Store a field from A, R, or B to a corresponding field in a memory word, leaving the other digits in the memory word unaffected.
Being able to operate intrinsically on partial words often eliminated additional instructions that would otherwise be needed to shift and extract digits before manipulating or storing them. This increased the efficiency of both execution and memory usage, partially offsetting the overhead of digit-sequential processing.

The partial-word facilities also provided convenient and efficient ways to modify operand addresses, variant digits, and even op codes in instruction words. A common trick was to implement a switch by adding or subtracting 29 to the 62-field in a word -- toggling the op code between 01 (No-Op) and 30 (Branch Unconditional). Partial-word facilities could also be used to pack multiple values into a single word, allowing programs to maintain larger numbers of values -- a not-insignificant advantage in the days of severely-constrained memory sizes. This was particularly important in the implementation of the Burroughs Algebraic Compiler (BALGOL), which will be discussed in future blog posts.

Additional 220 Enhancements


There were several other notable enhancements to the 220 instruction set over the 205:
  • The A, R, and B registers could be cleared to zero individually or in any combination with one instruction. The 205 could clear only A and R, and A only as a side effect of a store.
  • R could be loaded and stored directly without affecting A. The 205 could load and store R only by shifting values between A and R. This improved the setup for integer multiply/divide operations and allowed R to be used more conveniently as temporary storage. Stores could be of a partial word.
  • Similarly B could be loaded and stored directly, either as a whole or partial word.
  • A word in memory could be cleared to zero with a single instruction.
  • Instructions to compare A and R to a whole or partial word in memory replaced the 205's awkward branch-on-sign-difference mechanism. 
  • The sign digit of the A register could be tested against or replaced by a literal digit value.
  • Loop control was considerably enhanced. The 220 supported the 205's ability to decrement B and branch if it had not underflowed below 0000, but the decrement value could be 0000-9999 instead of just 1. Similarly, there was an instruction to increment B by 0000-9999 and branch if the result had not overflowed past 9999.
  • Looping could also be controlled using a new element, the Repeat Toggle. This was set by instructions that could increment or decrement a partial-word field in a memory word by 00-99. The toggle was set if the operation did not overflow or underflow, respectively, the designated field. The Branch Repeat instruction would branch or not based on the state of this toggle.
  • Subroutine call was supported on the 220 by the Store P instruction, which would store the value of the instruction counter, plus one, into the low-order four digits of the word at the instruction's operand address. This effectively stored a return address, and would typically be followed by a branch instruction to enter the subroutine. Compare this to the 205's Change-and-Record instructions, which stored the return address in the upper four digits of the R register.
  • The 220 supported a full complement of shift operations. Right shifts discarded digits off the low end of the register; left shifts acted as rotates (and as mentioned above, were implemented internally as right rotates). Register A could be shifted left or right, with or without participation by the sign digits. A and R could be shifted together left or right for up to 20 digits. The sign digit did not participate in the twin-register shifts, but it did get copied from A to R or R to A, depending on the direction of the shift.
  • The 220 had a Record Transfer instruction that could move from one to 100 words between locations in memory. The instruction's operand address specified the starting source location; the B register specified the destination address. At the end, B had been incremented to the address after the last word transferred, allowing multiple consecutive transfers to move larger blocks of data.
  • On the 205, overflow in an arithmetic instruction caused the processor to halt if the next instruction was not a conditional branch. On the 220, this behavior could be turned on or off programmatically. There was also an explicit Branch on Overflow instruction to test for overflow and reset the indicator if the branch was taken.
  • The 220 had an explicit No-Op (no operation) instruction that did nothing. On the 205, any unassigned op-code was treated as a No-Op. On the 220, executing an unassigned op-code caused the processor to halt with a Program Check Alarm.

220 Input-Output Facilities


 The 220 supported the same types of input-output devices as the 205, although the I/O instructions and the capabilities of the devices in some cases were quite different.

Console Devices


The so-called console devices included teletype printers, paper-tape readers, and paper-tape punches. A system could support up to 10 readers, up to ten teletypes or punches in any combination, and one special teletype termed the Supervisory Printer, or SPO (pronounced "spoh"). Teletype units could be substituted for punches and vice versa.

The 205's Frieden Flexowriter was replaced by a Teletype Model 28 RO (Receive Only) teleprinter, which operated at 10 characters per second. The Model 28 had the advantage that it used a moving type box to position characters on a line rather than the Flexowriter's moving typewriter carriage. The SPO was identical to the other teletype devices and was interchangeable with them. The SPO was addressed by a different instruction in the processor, however, and that instruction had an automatic decimal-point insertion feature that instructions for the other teletypes did not.

ElectroData designed and built their own high-speed paper-tape equipment, using 7/8-inch (22mm) tape and a seven-level code compatible with the IBM Eight-Channel Tape Code for the Type 046 Tape to Card Converter (a variant of the 026 keypunch). The reader was photoelectric and operated at a switch-selectable 500 or 1000 characters per second. It could stop in the space of a single character. The punch operated at 60 characters per second.

As an option, each teletype device could be configured with a paper tape reader, but this could be used only for off-line printing of paper tapes.

The paper-tape punches, teletypes, and SPO were connected to the processor in a daisy-chain. Switches in the device cabinets designated their unit number, 1-10, or SPO. The first device in the chain with a designation that matched that of an output instruction received and acted upon the data. The teletypes and SPO could each respond to multiple unit numbers, so it was possible for the software to address multiple devices but have the output come out on a smaller number of them.

On the 205, words were output to console devices one at a time from the A register. They were formatted as numeric or alphanumeric based on the values of address digits in the instruction words. On the 220, a single instruction could output up to 100 words directly from memory. The 2-bit in the sign digit of a word indicated whether it should be formatted as numeric (0) or alphanumeric (1). Thus, words with signs of 2 were considered to hold five alphanumeric characters, and words of mixed numeric and alphanumeric data could be output by the same instruction. This alpha vs. numeric behavior was effective only for the console devices, however.

Punched Card Devices


The Cardatron punched-card subsystem originally developed for the 205 was adapted for the 220 with very little change. The Cardatron was an interface between the 220 and IBM punched-card equipment. It translated between card or printer columns on the IBM machines and words in the 220 memory, It provided low-level editing of the data during transfer by means of digit strings termed "format bands" that were loaded to the interface from the 220's memory. It could also buffer one card or line image per IBM machine, allowing the processor to continue running while the machine operated on that card or line.

A 220 could have one Cardatron subsystem, which could support up to seven IBM machines. The Type 087 collator was used as a 240-card/minute reader, the Type 523 could be used as a 100-card/minute reader or punch (but not both at the same time), and the Type 407 was used as a 150-line/minute printer.

 The only significant differences between the Cardatron for the 205 and the 220 were (a) the ability to specify a sign of 2 for a word during input translation from a card reader, and (b) data transfer between the 220 memory and Cardatron units went from high to low addresses. That is, Cardatron instructions specified the ending address of the buffer area in memory. The Cardatron processed card and print columns backwards, so the descending addressing allowed the data in memory to be in ascending order. On the 205, data transfer was in ascending sequence, which meant that the words in memory were reversed with respect to their order on the card or print line.

For more information on the Cardatron and its features, see these two posts on this blog for the 205 version:

Magnetic Tape Devices


The 220 took the basic idea of the 205's magnetic tape subsystem and significantly extended it. The 205 used 3/4-inch (19mm) plastic tape on 2500-foot (762m) reels. The tape had two parallel lanes that each stored digit-wide frames at 100 bits/inch and moved at 60 inches/second. Only one lane could be read or written at a time, but the lane was programmatically selectable. Data was recorded in fixed-length blocks of 20 words each. Individual blocks could be overwritten in place. A full reel of tape could hold 10,000 blocks. Each block was assigned a four-digit number. The tape subsystem could search bidirectionally for a specified block number independently and asynchronously from the processor.

The 220 enhanced the 205 tape implementation in the following ways:
  • The tape was physically identical, but came on 3500-foot (1067m) reels.
  • The tape still had two parallel lanes, but data was recorded at 208.33 bits/inch and the tape moved at 120 inches/second -- twice as dense and twice as fast.
  • Blocks could be 10-100 words in length, and a tape could have mixed block sizes. Blocks could still be overwritten in place, but once a block of a certain size was written on tape, that size could not be changed. The entire tape had to be erased (a process known as "editing") and rewritten in order to change block sizes.
  • Up to ten blocks could be read or written in a single instruction. Variants of the instructions allowed reading and writing sequences of mixed block sizes. Tapes could also be spaced forward or backward up to ten blocks at a time.
  • Instead of block numbers, the first word in each block was considered to be its identifier or "keyword". The tape subsystem could search a tape bidirectionally and asynchronously for the block with the highest keyword that was less than or equal to a specified value. Optionally, the match could be made on a partial-word field. The search stopped with the tape positioned to read the matching block. In order for the search to work as intended, the keywords had to be unique and written in ascending order, but it was not a requirement that tapes be created in that particular fashion.
  • In addition to the bidirectional keyword search, the tape subsystem could search asynchronously in the forward direction for a block where a specified word in the first ten of the block matched a value. This was termed a "scan." This match could also be made on a partial-word field. As with search, a scan stopped with the tape positioned to read the matching block.
  • Instead of a simple end-of-file mark like the IBM tapes had, the 220 could write and sense two types of special blocks on the tape:
    1. An End-of-Tape block was typically written at the end of information on a tape, but could be placed anywhere. It contained a single control word (although the block physically occupied ten words on tape) that held two addresses:
      • The 64-field of that control word was the address of a word in memory where the values of the P register and 04-field of the C register would be stored.
      • The 04-field of the control word was the address to which the processor would branch when the block was read.
      An EOT block would terminate a search or scan operation, but the control word would not be acted upon until the block was actually read.
    2. A Control Block was one where the sign digit of its keyword was 7. When this type of block was read, all words in the block except the last were transferred to memory. The last word was not transferred to memory, but was acted on in the same way as the control word in an EOT block, storing fields from the P and C registers and branching to a specified address.
Like the 205, the 220 had two types of tape drives. The first was a traditional free-standing, reel-to-reel unit. It had an unusual design -- waist-high, with a slanted tape deck that held the reels, heads, and vacuum columns, as shown in this image from the Georgia Tech installation:

220 Free-standing Tape Drives
The second type of tape drive was the DataFile, a pre-disk design intended to provide faster random access to large data sets. It was another waist-high cabinet, but with 50 parallel bins instead of reels, each bin holding a 270-foot tape strip. The strips looped over a set of rods that supported a head assembly on a moving carriage.

220 DataFile Tape Unit
The carriage could position to any one of the tape strips within 1.5 seconds and drive that strip forward or backward. Except for their shorter length, the tapes, recording characteristics, and tape operations were identical to those for the free-standing units. While tape in the free-standing drives had two lanes, the DataFile acted as if it had a tape with 100 lanes. The tapes were not removable except for maintenance, so the DataFile was used more like a disk drive than a tape unit, albeit one with a large access latency.

This image shows the interior of a 205 DataFile, but the internal mechanism for the 220 was similar:

205 DataFile Showing Tape Strips


High-Speed Printers


Burroughs developed an early electrostatic printer named the Whippet that could output about 250 characters per second. It used coated paper and heat to fix a dry ink to the surface of the paper. It was originally developed for the U.S. Army Signal Corps, but at least a few units were installed at non-government sites, including one at CalTech. It could substitute for one of the teletypes.

Burroughs also developed its own high-speed drum printer for the 220, a design that continued to be refined and used into the 1970s with the B-series computer systems. The printer for the 220 could be used in two ways. It could be attached directly to the system and driven programmatically. It could also be used off-line, with a separate control unit that read data from a free-standing tape drive. The control unit was configured through a plugboard and was designed with the intent that data could be formatted and printed directly from master files, avoiding tying up the rest of the system for long print runs. The idea of off-line printing did not survive beyond the 220 era, however.


The retro-220 Project


I started a project in late 2016, having as its main goal the development of a web-browser based emulator for the 220, along the same lines as the retro-205 project for the 205. The emulator is written in Javascript and uses standard HTML and CSS to create a user interface within the browser. Due to the similarities between elements of the 205 and 220, I was able to port quite a bit of the code for the 205 emulator over to the 220.

Like my earlier emulation projects, the retro-220 emulator is open source and available for anyone to use. The emulator itself and all but the magnetic tape implementation were substantially complete by late Spring 2017. The 220 tape subsystem proved to be a significant challenge, and was not completed until late 2017. At this writing, the emulator is at version 0.06, and is complete except for the DataFile and high-speed drum printer devices.

This screen shot shows the emulator in action:

retro-220 Emulator Running from the Firefox Browser


The second goal for this project has been reconstruction of the Burroughs Algebraic Compiler for the 220, better known as BALGOL. This was an early implementation of the Algol-58 language, the predecessor to the better-known Algol-60. The compiler was first released in March 1960. Donald Knuth, who participated in its development, has donated a scan of the compiler and library listing to the Computer History Museum in Mountain View, California. An earlier, less complete listing is also available on bitsavers.org.

I have used Professor Knuth's listing to transcribe the assembly language source code for the compiler and its library, and have written two cross-assemblers to generate 220 object code from those transcriptions. The reconstructed compiler is now starting to work and is presently undergoing further testing and validation. The current state of its development can be found in the retro-220 project repository.

At this point, I am starting to work on a wiki for the emulator and compiler that will be available on the repository web site. I am also preparing additional blog posts on the project. The next one will be an introduction to the emulator and its user interface, so stay tuned.