Funding for this project has been provided by the Rice Undergraduate Scholars Program. Joel Cyprus was the faculty advisor.
The other goal of the machine was to do research into how computers should be built. In the years following John von Neumann's death, the Atomic Energy Commission became quite interested in funding computer research: Salsburg's request came at a time when the AEC's goals could be better met by funding the development of a new system than by offering to build a copy of MANIAC II or to buy a stock IBM computer.
Graham designed the hardware of the Rice Computer, and most of his plans were implemented by Joe Bighorse, the project's head technician. "Joe Bighorse," claimed Graham, "is the best technician I ever had work for me. Anywhere."[2] The combination of a skilled engineer and an excellent technician--as well a Rice alumnus's donation of the use of his tool and die shop for the machining of the computer--produced an extremely well-engineered machine at all levels of design. Since Rice was getting custom machining, the physical layout was designed to hardware requirements rather than having hardware made to fit off-the-shelf structural components. Construction on the machine proceeded from 1958-1961. A copy of the machine was also built at the University of Oklahoma.
Parts of the machine began functioning in 1959, and the computer finally became fully operational in 1961. While not the first computer on campus--a Litton LGP-30 shared by the Mechanical Engineering and Chemical Engineering departments was in use in 1957[3]--it quickly became Rice's primary computer and remained in that role until supplanted by an IBM 7040, followed by a Burroughs B5500, in the late 1960's[4]. Graham took a year-long sabbatical at the University of California at Berkeley in 1964; when he returned in 1965, he ran afoul of departmental politics and the Dean of the School of Engineering[5], and returned to Berkeley on a permanent basis in 1966. Sigsby Rusk assumed the leadership of the Computer Project. Most of the graduate students who had helped with the construction of the machine, such as Ted Schutz, Joel Cyprus, Phil Deck, and Dwayne Chesnut, had left by 1964, and Joe Bighorse departed shortly after Graham.
The R1 was decommissioned in 1971 when the cost of maintaining and powering it had become prohibitively expensive for the limited amount of computation it was able to provide. The R1 was initially named "The Rice Institute Computer" and then became "The Rice University Computer". It acquired the "R1" moniker when it was being used in the design of the Rice Research Computer, a tagged-architecture ECL machine modeled on John Iliffe's Basic Language Machine[6]. Presumably "R2" was a convenient designation for the Rice Research Computer, as Rice's second machine, and "R1" was thus coined as the obvious label for Rice's first computer.
The indirect addressing modes were designed into the machine at the request of John Kilpatrick. He was influenced, in turn, by IBM's advertising for its 709 line of machines, which touted indirect addressing as its major new feature. However, the Rice machine delivered far more powerful indirect addressing modes than IBM's product.[7]
Shell, as part of the funding agreement, had the right to know what the R1 project was doing, whether or not the results were ever published. Bob Barton, the head of Shell's research division left for Burroughs in the early `60's; it is probably not coincidental that the architecture of the Burroughs B5000--designed by Barton--closely resembles the Rice Computer[8,9]. In fact its "descriptor" addressing is very nearly the same as the R1's codeword scheme[10], and the use of tag bits was similar in each machine.
The codeword was the lasting legacy of the Rice machine; it became the basis for capability-based protection, which appeared in Iliffe's Basic Language Machine. The segmentation that codewords allowed was a major factor in the development of the CTS system, one of the earliest multiprogramming environments. While the R1 did not have much direct evolutionary influence on the history of computer design, its large register set (for the time), its indirect addressing capability, and its use of codewords all had significant influence on subsequent generations of computers.
Control information and program input for the machine took place through a paper tape reader and through the console switches and console typewriter. The paper tape was prepared offline on a Frieden Flexowriter. Output could be routed to a line printer, a paper tape punch, or the console typewriter. Two magnetic tape units were available early in the project; later, two more tape units and a limited disk subsystem were attached[13]. Additional devices were added by and for various users throughout the machine's lifespan.
Single Sided Gate
Circuit. Rice, 1958, Appendix A![[Picture]](ssgate_inline.jpg)
Circuit used to connect multiple input gates B[1-4].
Rice, 1958, Appendix A.![[Picture]](minga_inline.jpg)
The Rice computer ran at a logic speed of approximately 1 MHz.[14] The basic design was asynchronous: the machine signaled that an operation had completed by setting an internal voltage. For example, the adder had one capacitor per stage; since capacitor current is the derivative of voltage with respect to time, when the voltage levels in the adder had stabilized, no current would come through the capacitor bank, and a flag would be raised signifying that the machine had finished with the addition and carry[15].
The memory was structured in an 8x8 array of tubes providing 63 memory tubes and a display CRT. The 64th tube was used for debugging the other tubes: when memory errors began to accumulate, test leads could be clipped to the offending tube and a picture of its bit pattern would appear on the display tube. Memory access time was on the order of ten microseconds, and a write to memory took twenty microseconds[17].
The memory was surprisingly reliable, although its quality did drop off radically as it aged. The only major problem reported with the tubes during the early years of the project was one in which no bits from a certain tube could be read. Examination of the tube with the diagnostic leads revealed that the bit pattern had shrunk significantly from its proper size. Upon examination, the problem was traced to a faulty resistor: the voltage divider on the accelerator had burned out, raising the acceleration voltage from 15 kV to 20 kV and thereby decreasing the electron deflection radius.[18]
Since reading a bit from the tube target is slightly destructive, tight loops could cause read-around errors, as bits that had previously been turned on would get weaker and weaker each time the nearby bits were read. The operations manual addresses this: "as a general safety rule one should not try to read one particular word more than 1000 times within one continuous 50 millisecond period."[19]
In 1966, an 8K bank of RCA core memory was added to the Rice computer; it had an access time of one microsecond and a cycle time of two microseconds. In 1967, 16K of Ampex core (1 microsecond cycle, 400 ns access) was added, bringing the machine to its full capacity of 32K words. Shortly thereafter, the original electrostatic memory was decommissioned, as it had become extremely error-prone due to its age.
The R1 was designed with a line printer capable of 300 lines per minute. The printer used a six-bit character code and printed 108 characters per line. A print image was constructed by arranging 18 words per half-line in a continuous memory block and then issuing a "print left" or a "print right" instruction. A full line could be printed by arranging two 18-word blocks and then issuing a "print left (do not advance paper)" instruction and then a "print right" instruction[20].
The tape system of the R1 never functioned very reliably. While 4 tape drives were provided for, no more than two were generally working at any one time. Tape data was randomly accessible and its block format functioned something like a rudimentary file system: for example, the AP1 PLACER program was defined to exist at block 100.02 of the MT system tape[21]. The large hydraulically-actuated Bryant disk (which had mammoth 39-inch platters) was added in 1967 or 1968, but was even less reliable than the tape drives and was generally felt to be more trouble than it was worth[22]. Additional I/O was added to the machine more or less on an ad hoc basis: Sigsby Rusk designed an A/D converter in `62 or `63 from fast ECL logic, capable of 8-bit resolution at 100kHz, and wireframe animations of a sort were produced using a D/A converter to drive an oscilloscope, which was then photographed one frame at a time on a 16mm movie camera. The very flexible nature of the R1's instruction set made it easy to connect any of these peripherals to the system and add instructions to communicate with them.
| Address | Abbreviation | Use |
|---|---|---|
| 0 | 0 | Zero register (constant zero) |
| 1 | U | Universal (math) register (55 bits--contained overflow bit) |
| 2 | R | Remainder (for math operations) |
| 3 | S | Storage (for math operations) |
| 4-7 | T4-7 | Fast temporary storage |
The Zero register was not really a register at all, but a quick way to get the constant zero. The U register was used in all math operations as the object acted upon, and would, after the operation was performed, contain the result. R was primarily used for intermediate calculation results, the remainder after a division, and the lower half of a product after multiplication; a general mechanism existed to use U and R together as a double-length register. S was used as the actor in all math operations: the subtrahend, the divisor, or the multiplier, for instance.[27]
The 16-bit[28] B registers, which were primarily used for indirect addressing, were as follows:
| Address | Abbreviation | Use |
|---|---|---|
| 0 | CC | Control (Program) Counter |
| 1-6 | B1-6 | B-register1-6 |
| 7 | PF1 | Pathfinder (subroutine return) register 1 |
CC was used as the fifteen-bit location that told the program the absolute memory address being executed. Since this was a general-purpose register, relocatable code was made very easy, since the program "always [knew] where it [was]"[29] and the contents of CC could be examined and modified by the program. The B-registers could be individually specified in the instruction such that the program would fetch its instruction from (CC + Bx), which allowed for relocatable subroutines. On any transfer of control, the contents of CC would be put into PF1 and the contents of PF1 into PF2. This allowed hardware maintenance of the program execution stack and made shallowly nested subroutines very fast.
There were additionally the I (Instruction) 54-bit register, which held the instruction for decoding, the SL and ML (sense light and mode light) 15-bit registers, which contained the settings of console switches controlling machine operation, the 16-bit X (increment) register, which could be used as an addend to the B-registers, which was useful for indirect addressing), and PF2, the second pathfinder register, which, as described above, was to PF1 as PF1 was to CC.
The mode light register allowed the programmer to specify the mechanism by which rounding of numbers would take place, whether to trap to a specified address on encountering a tag, whether to repeat a single instruction indefinitely, and other control functions.
Fixed point numbers followed the same format, but ignored the exponent and its sign, thus restricting the absolute value of the number to the range between (1 - 2-47) and zero, but allowing forty-eight, rather than forty, bits of precision.
| Field | Digits | Use |
|---|---|---|
| 1 | 1 | Inflection on F |
| 2 | F address | |
| 2 | 3 | Instruction class |
| 4-7 | Four operation Triads | |
| 3 | 8 | Inflection on store |
| 9 | Store address | |
| 4 | 10 | Inflection on Memory address |
| 11-13 | 1 bit: Indirect Address bit 8 bits: B Modification of M | |
| 14-18 | Memory Address |
While a brief description of the function of the various fields of the instruction word is given below, the full analysis of the instruction architecture is too long to be presented here. The Rice Computer was basically a microprogrammed machine: the instruction set was so rich and regular that each "instruction" could itself be programmed to some degree.[31] However, since each instruction had to access memory, which was very slow compared to the computer's cycle time, overall machine performance suffered.
| Value | Meaning |
|---|---|
| 0 | Test or Transfer |
| 1 | Arithmetic |
| 2 | Fetch, Store, or Tag Operations |
| 3 | Reserved for Future Use (never used) |
| 4 | B-Register, Console Lights, and Special Register Operations, and Shifts |
| 5 | Bitwise Logical Operations |
| 6 | Input/Output Commands |
| 7 | Special Functions (by 1964, Analog Input Commands) |
The remainder of the field was 12 bits of instruction code. Their use varied wildly with the instruction class. For example, in Class 2 operations, if the first triad was 0, the contents of U were stored in the memory location pointed to in field 4. If it were 2, the memory location would get the contents of U added to the contents of S. Other values caused other operations to be performed.
Tagged data was more complex. A common use was to delimit sparse matrices or matrices made up of variable-length rows; one tag could be used to mark "end of row", and a second tag as "end of matrix". Another clever use was to provide for operations on a vector of data with a single instruction. A trap would be set so that, upon encountering a tag, the machine would come out of repeat mode. Then the instruction would be set up to turn on repeat mode and operate on a word indexed through an automatically incremented B-register. Thus, a single instruction would operate on each word in the vector until it encountered the "end of vector" tag, whereupon repeat mode would be turned off and the program would move ahead to the next instruction.
The use of codewords encouraged the use of an "object-oriented" view of program design which decoupled the physical extent and existence of entities from the operations applied to them.[33]
Codewords also allowed dynamic memory allocation, and, had there been a way to ensure that memory references had to be made through codewords, would have easily allowed implementation of a security system and multiprogramming. Codeword use will be further discussed under SPIREL, as it was only within the SPIREL system that codewords were made available.
Dynamic memory allocation took place through either the TAKE SPIREL command or through the SETX command. TAKE was a mere five words long and grabbed a linear block of memory whose length was specified by the programmer; there was no corresponding instruction to return this memory once done.
SETX was by far the more interesting command. Once activated it overwrote TAKE, which then became unavailable. SETX, while also a mechanism to allocate a given length memory block, provided much more functionality. Memory, once allocated, could be freed. Further, if the total free space in the machine was enough to satisfy a memory allocation request but the memory was not in a contiguous block, SETX would automatically shuffle storage blocks around to provide a sufficiently large contiguous memory block. This was possible only by using the codeword mechanism: since memory was accessed through its associated codeword, to move the location of an object, the system had only to copy the data from one memory block to another and then patch the codeword to point at the new block. Similarly, memory blocks could be lengthened or shortened on the fly by patching the length descriptor in the codeword. A stack, starting at address 176008, pointing to codewords referencing allocated memory, was kept in a codeword referenced by the B6 register, and interface routines to push and pop the stack were given in SPIREL as SAVE (*136) and UNSAVE (*137).
The only major problem with this approach is that programs which used the pathfinder registers could easily conflict with SPIREL's use of memory: the pathfinder registers returned absolute addresses rather than codewords, and hence, loading programs after allocating memory via SETX could cause a routine to be placed in the middle of data pointed to by a codeword. The workaround was to load all programs before calling SETX to allocate memory.[35]
A program could therefore request and free just the amount of memory it needed for its objects at run-time; each memory block could map directly to a high-level program object, and there was no need to determine the object's maximum size at all. This naturally leads to an object-oriented programming model, but one that is enforced in the machine's architecture, rather than "stuck on at the end by C++"[36].
"Undoubtedly, dynamic memory allocation based on logical units of program was the major innovation [of the R1],"[37] claims Iliffe. Codewords also provided a basis for implementing multiprogramming and security, although these were not actually done on the R1, as there was no way to enforce access solely through the codeword mechanism. They did, however, surface in that role on Iliffe's Basic Language Machine[38,39].
There were actually two versions of the assembler: AP1 and AP2. AP1 was designed to produce standalone programs, while AP2 was used for inline code within Genie. They were nearly identical in form, differing chiefly in their representation of numbers--AP1 assumed numbers were in octal unless a "d" was prepended, while AP2 assumed decimal unless a "+" was prepended[41].
Both included a number of pseudoinstructions to insert remarks or octal or decimal data into a program, or to include printer or Flexowriter output.[42]
Genie "definition sets" could consist of any number of programs, although it was usual to only have one program per definition set. Names (variables, functions, named constants, etc.) could be up to five characters. There were three categories of variables: internal, external, and parametric. Internal variables were global only to the program in which they appeared, and could only be statement labels, integers, floating point numbers, or booleans--in other words, scalar quantities.
External variables could be scalar or non-scalar. Non-scalar variables would refer to a program, a vector, or a matrix. These variables would simply point to a codeword, which would then reference some object in memory. External variables were accessible to all programs in the machine, as they were memory structures pointed to by symbolically-named codewords.
Finally, parameters were used for passing information to and from programs within a definition set; they would be internal or external variables to the calling function. Any data type was acceptable as a parameter.
Since functions could be passed as generic codewords, this made an object-oriented view of problems to be solved a very natural approach. One surprising feature of Genie was that, while "[e]very Genie program is a function [and] may be used as such by any other Genie program...it may not use itself."[43] This seems odd, as tail recursion appears to be a very intuitive mechanism to use with such a calling convention, and the overhead of saving context would not have been large.
Arithmetic operations were fairly standard. The only surprising feature to modern eyes is that exponential operations were actually indicated with superscription[44] using the superscription capability of the Flexowriter. Similarly, accessing an element of a vector or matrix was done using the subscription capability of the Flexowriter[45].
Control transfer was provided with what was essentially a GO TO: the statement was CC = #LABEL, where LABEL was a statement label within the program; conditional branching was handled by CC = #A1 if P1, #A2 if P2, ... , #An if Pn, thus providing a rudimentary switch statement[46]. Loop structuring was fairly advanced for the time: a FOR...REPEAT construct was given[47], and FOR loops could be nested.
Execution of functions could be either implicit or explicit. With a function that returned a single value, implicit execution--for example, "A = F(P) + 2" was allowed. For a function returning multiple values, "EXECUTE F(P)" would have been required[48].
A set of instructions to read from paper or magnetic tape, to punch tape, or to print, were also included, as was support for inline assembly code in the AP2 format. An interesting feature of Genie was that, if compilation required more physical memory than was available, a scratch tape was mounted and the tape would be used as temporary storage for code. In that manner, programs of arbitrary length could be compiled.
Genie would typically have been used for complex mathematical programs that did not require complicated data structures. Assuming that the only entities the programmer wanted to use were supported Genie data types, it would have been easier to code a program in Genie. If the program needed only a few features not available in Genie, it would have been possible to code a program in Genie with additional functionality added in AP2. AP1 would only have been necessary to get Genie implemented and to write programs which extensively used features of the machine not supported by Genie, such as the Mode Light Register. The assembler would also have been used to write programs which bypassed SPIREL entirely and ran on the bare hardware.[49]
Since the R1 was built and maintained at Rice, it could be extraordinarily responsive to users' needs. Monte Carlo circuitry was added to the machine for Kilpatrick and Chesnut's work. Jean-Claude DeBremaeker added a digital seismograph to the Rice Computer and a new tape mode to drive it. This was made easy through the availability of Class 7 (Special Function) Instructions and through the mode lights. When a disagreement arose over the best way to do something, such as how to best implement floating-point zeroes, the mode lights were useful in effecting a compromise. This became a battle between Graham and Kilpatrick: should a zero result in a floating point calculation be represented as a zero mantissa with the original exponent, to show the precision to which it was zero (Kilpatrick's sentiment), or should it be represented as a zero mantissa with a zero exponent, so that it would be represented by the machine as a "real" zero, identical to the contents of the zero register (Graham's feeling)?[52] The arithmetic unit was wired both ways and attached to a mode switch, allowing the user to choose which way he wanted to run the machine.
In the later years of the R1's existence, more projects were attempted on it as it became less a research machine and more a general-purpose workhorse. An ALGOL compiler was attempted but never completed. Gary Sitton attempted a voice-recognition program for his Master's Thesis[53], using Sigsby Rusk's analog-digital converter.
Finally, the R1 was an integral part of the design of the R2. The R2 was to have been implemented using ECL logic. The ECL flatpacks were to be mounted in plastic carriers from which protruded "combs" of metal teeth connecting to the pins of the packages; if an electrical connection was to be made, the tooth would be left attached. If not, it was to be punched off. Layers of these carriers were to be sandwiched together to provide a complex three-dimensional structure implementing the computer's logic. The antiquated R1 was used to deduce the optimal layout for the interconnected combs which supported the R2's ECL logic, print the wiring map, and punch the tape which drove the die that would punch the teeth off the combs[54].
Chesnut recounts that he once noticed an intermittent floating point error that seemed to occur once a minute while he was using the machine. The only other sixty-second clock he could think of was the key; the problem, in fact, was that the lead carrying the pulse of data from the key had been routed too close to the accumulator and would scramble its contents.[56]
There was no distinctive culture surrounding the Rice Machine. While there was a certain esprit de corps, there was nothing like the atmosphere of MIT's Tech Model Railway Club, which became the progenitor of modern hackish culture. Phil Deck provided the only distinct saying connected with the R1. Apparently, in any situation in which blame could conceivably be assessed, Deck would ask, "What you mean-um we, kemosabe?"[59] This behavior was both endemic enough and obnoxious enough that it is vividly remembered 35 years later.[60]
Joel Cyprus at work on the Arithmetic Unit, July 29, 1960.![[Picture]](cyprus_inline.jpg)
The R1 was a fascinating machine; evolutionarily, it spanned a huge range of technologies, from the vacuum tubes used in its initial construction to the high-speed ECL used in its later peripherals. Graham's and Iliffe's perspectives on it differ interestingly--Graham speaks from a hardware viewpoint and believes "the electronics were really pretty good." [64] The quality of the machine's assembly and the usefulness of indirect addressing were the features that he particularly stresses, as well as the extensibility inherent in a computer with a microprogrammed instruction set in which the hardware could be modified freely. Graham strongly defends the choice of technologies as the best decision available at the time of construction.
Iliffe, on the other hand, remembers the codeword as the most significant thing about the Rice Computer: "Undoubtedly, dynamic memory allocation based on logical units of program was the major innovation."[65] He, in fact, feels that the B-register indirection scheme, while "cute"[66], could easily have been replaced by more efficient code. One suspects the fact that the hardware indexing mechanism got in the way of codewords contributes to his feelings. The ease with which the machine was modified is also a bone of contention: Iliffe, far from viewing this as a way to make the machine responsive to user needs, feels that the special-purpose hardware badly hurt the computer's reliability.[67].
The R1 was a tool for ten years of research at Rice. Over the course of its extraordinarily long lifespan it was used for everything from solving the pentomino problem, to optimizing synthesis of boolean logic, to molecular dynamics, to speech recognition. The quality of the technical team assembled to design and build its hardware and software has rarely been equaled. In the final analysis, it is remarkable that such a computer, whose basic technology was obsolete before the machine was fully online, built with a small budget, worked so well for so long.
Tracing the machine's genealogy through the Burroughs B5000 and determining to what extent codeword segmentation influenced early experiments in multiprogramming promises to be another rich area of inquiry. It would also prove worthwhile to try to track down schematics and technical descriptions--if such still exist--for the peripherals added to the R1 late in its lifetime. It would also be interesting to trace the role of the R1 in the development of the R2 and to try to assemble a picture of the R2 project in its entirety. Such a project would be another significant step towards preserving the history of computer research at Rice.