This short paper is a supplement to the series of articles appearing on the IBM developerWorks website describing the creation of a computing engine called "The Heath Robinson Rube Goldberg (HRRG) Multifarious Technology Computer." As described in these articles, this machine is to be formed using a variety of implementation technologies, including (but not limited to) relays, vacuum tubes, transistors, and simple integrated circuits – also mechanical, magnetic, pneumatic, and fluidic logic – and possibly some even more esoteric technologies.

Main Topics



 
A Slight Repartitioning
As was noted in Part 2 of the HRRG series on the IBM website, the physical cabinets forming "The Beast" communicate by passing packets of information via a network. In the original HRRG specification, it was intended that the Clock Generator cabinet in charge of providing the system clock signal would issue an on-going series of packets essentially containing alternating "tick" and "tock" signals. Under this original architecture, a purely physical system would have looked something like the following:

Original architecture - clock generator on the network

However, it was subsequently decided that the output from the Clock Generator should be a signal that is plugged directly into the Control Logic cabinet. In addition to cutting down on the traffic bouncing around the network, this also makes it easier to ensure that two cabinets don’t try to "talk" at the same time (one of these cabinets being the clock cabinet itself). Thus, under this new architecture, a purely physical system now looks like the following:

New architecture - clock generator feeding the control logic

This means that the Clock Generator and Control Logic cabinets have to be resident in the same domain: both virtual or both physical. Also, they have to be in the same location: on the same host computer (if virtual) or in the same room (if physical).

The internals of the Clock Generator cabinet can be created using any implementation technology. The main requirements being that the signal coming out of the Clock Generator cabinet toggles back and forth between 0V and 5V and that it should have a reasonably symmetrical mark-space ratio (that is, it should spend approximately the same amount of time at each level). It should also be possible to control the frequency of the clock signal (all of these points will be discussed in more detail later in the series).




 
GPIO Cards and General-Purpose Packets
Each of the physical cabinets (apart from the clock cabinet) contains a General-Purpose Input/Output (GPIO) card. These cards receive packets from the network, present the appropriate data to the contents of their cabinets, gather results from the contents of their cabinets, and transmit these packets over the network to the other cabinets. (Virtual cabinets running in the HRRG Emulator have virtual equivalents to the GPIO card).

The first byte of a packet specifies the type of that packet. There are currently six types of packets as follows (the dollar character is used to indicate a hexadecimal value):

     $00 =  General-purpose communications packet
     $01 =  Configuration setup (mode 1). Used to configure local devices (virtual or physical)
     $02 =  Configuration setup (mode 2). Used to set the identity of a physical GPIO card
     $03 =  Configuration request (the targeted unit is requested to transmit its current configuration).
     $04 =  Configuration response (the targeted unit responds by transmitting its current configuration).
     $05 =  Special communications packet that interconnects remote sites running over TCP/IP

For the purposes of these discussions, we shall be concentrating on the general-purpose communications packet; a high-level view of this packet type is as follows:

High-level view of general-purpose communications packet

Packet Type
$00 = General communications packet

MAC Address
This is a six-byte unique MAC address of the unit transmitting this packet.

Source Unit Type
This specifies the type of functional unit that originated the packet as summarized in the following table. In addition to the cabinet types we've discussed thus far, there are two additional types: a Complete CPU and a PC Interface Card. As its name suggests, the Complete CPU cabinet allows for someone who wishes to implement the entire CPU in a single cabinet. Meanwhile, the PC Interface Card is a special type of unit that allows a PC to present configuration (and other) packets to the physical system.

Summary of different unit/cabinet types

Info Type
This specifies the active classes of information that are contained in the packet. These bits are active-high (a 1 means that type of info is being transmitted). All of the GPIO cards power-up with these signals set to a default value of 0.

     Bit 0 = Address
     Bit 1 = Data
     Bit 2 = Status
     Bit 3 = Control
     Bit 4 = Instruction

CPU Signals
These signals reflect the state of the physical CPU interface. All of the GPIO cards power-up with certain default values on these signals (these default values are shown in parentheses below).

     Bit 0 = ~IACK = Interrupt acknowledge (1 = inactive)
     Bit 1 = ~IRQ = Interrupt request (1 = inactive)
     Bit 2 = ~RESET = System reset (0 = active)
     Bit 3 = ~BUSY = Busy (see next topic) (1 = inactive)
     Bit 4 = ~WR = Write (1 = inactive)
     Bit 5 = ~RD = Read (1 = inactive)

Observe that there is no system clock signal. This is because &ndashl as was discussed earlierin thsi paper – the system clock is plugged directly into the control cabinet. Everything occurs on rising edges of the system clock (such as packets being transmitted from the control cabinet), so to the outside world it would appear that this signal was always logic 1.

Address, Data, and Status
These signals reflect the state of the 16-bit address bus, the 8-bit data bus, and the 5-bit status word. All of the GPIO cards power-up with all of these signals set to a default value of 0.

Control Word
These signals, which are generated by the Control Logic unit, are used to control the other cabinets forming the CPU (the ALU Logic, the Status Logic, and the Address Logic). Different units use different signals. All clocks are positive-edge active; all tri-state enable signals are active-low; the ~set_im (set interrupt mask) and ~clr_im (clear interrupt mask) control signals are active-low. All of the GPIO cards power-up with certain default values on these signals (these default values are shown in parentheses below).

     Bits Signal Name Default Function Target Unit
     Bits 0-4 inst[4:0] (00000) ALU Instruction ALU Logic
     Bit 5 clk_alu_acc    (0) ACC clock ALU Logic
     Bit 6 clk_alu_tmp    (0) TMP clock ALU Logic
     Bit 7 ~ena_alu_tbuf    (1) Tri-state enable ALU Logic
     
     Bit 8 clk_status_i    (0) Clock for I bit Status logic
     Bit 9 clk_status_o    (0) Clock for O bit Status logic
     Bit 10 clk_status_n   ( 0) Clock for N bit Status logic
     Bit 11 clk_status_z    (0) Clock for Z bit Status logic
     Bit 12 clk_status_c    (0) Clock for C bit Status logic
     Bit 13 ~set_im    (1) Set interrupt mask Status Logic
     Bit 14 ~clr_im    (1) Clear interrupt mask Status Logic
     Bit 15 sel_status_2_1    (1) Mux control Status Logic
     Bit 16 ~ena_status_tbuf    (1) Tri-state enable Status Logic
     
     Bit 17 clk_addr_pc_ms    (0) PC MS clock Address Logic
     Bit 18 clk_addr_pc_ls    (0) PC LS clock Address Logic
     Bit 19 clk_addr_tpca_ms    (0) TMP PCA MS clock Address Logic
     Bit 20 clk_addr_tpca_ls    (0) TMP PCA LS clock Address Logic
     Bit 21 clk_addr_tpcb_ms    (0) TMP PCB MS clock Address Logic
     Bit 22 clk_addr_tpcb_ls    (0) TMP PCB LS clock Address Logic
     Bit 23 clk_addr_sp_ms    (0) SP MS clock Address Logic
     Bit 24 clk_addr_sp_ls    (0) SP LS clock Address Logic
     Bit 25 clk_addr_iv_ms    (0) IV MS clock Address Logic
     Bit 26 clk_addr_iv_ls    (0) IV LS clock Address Logic
     Bit 27 clk_addr_x_ms    (0) X MS clock Address Logic
     Bit 28 clk_addr_x_ls    (0) X LS clock Address Logic
     Bit 29 clk_addr_latch    (0) Address latch clock Address Logic
     Bit 30 sel_addr_2_1_in    (0) Input mux control Address Logic
     Bit 31 sel_addr_2_1_out    (0) Output mux control Address Logic
     Bits 32-34 sel_addr_5_1[2:0]  (000) Adder mux control Address Logic
     Bits 35-37 sel_addr_6_1[2:0]  (000)  Address mux control Address Logic
     Bit 38 ~ena_addr_tbuf_ms    (1) Tri-state enable (MS) Address Logic
     Bit 39 ~ena_addr_tbuf_ls    (1) Tri-state enable (LS) Address Logic

Every GPIO card has a set of outputs that map onto the CPU Signals, Address, Data, Status, and Control Word fields. These outputs are actually driven by a shift register with an output latch; values are loaded into this register in a serial fashion, and then all of the outputs are updated and presented to the outside word in parallel. When a GPIO card receives a packet from the outside world, it may update any or all of these signals as discussed later in this document. The logic for each cabinet type will typically only use a subset of these signals – any unused outputs can be left unconnected.

The GPIO Card

Similarly, every GPIO card has a set of inputs that map onto the CPU Signals, Address, Data, Status, and Control fields. The logic for each cabinet/unit will only generate a subset of these signals – any unused inputs should be connected via a pull-down resistor to logic 0.




 
The ~BUSY Signal
Consider a high-level view of one of the memory cabinets – say a RAM cabinet – as shown below:

High-level view of physical RAM cabinet

In this case, we absolutely require the ~RD (active-low read) and ~WR (active-low write) CPU signals going into the RAM logic, along with the contents of the 16-bit address bus and 8-bit data bus. In the case of a read operation, the only thing that has to come out of this cabinet is an 8-bit data value.

Now, observe the active-low CPU signal ~BUSY. The GPIO card itself will always see ~BUSY signals in incoming packets and set appropriate ~BUSY values in outgoing packets. However, whether or not the GPIO card actually passes the ~BUSY signal into the cabinet's logic and/or reads a corresponding ~BUSY signal coming out of that cabinet's logic is optional for every type of cabinet.

The point is that some physical implementations will be faster or slower than others. A memory cabinet (implemented using vacuum tubes, for example) might respond relatively quickly to a request from the control cabinet. By comparison, an ALU cabinet (implemented using trained hamsters racing round mazes, for example) might respond relatively slowly to a request from the control cabinet.

One possibility would be to slow the system clock down to accommodate the slowest cabinet. But this has a disadvantage in that one type of cabinet (say an Output Port cabinet) that is used relatively infrequently may be MUCH slower than all of the other cabinets. In this case, the system would be running slower than it could be operating for most of the time.

Ideally the system should run as fast as possible. The solution decided upon is that when the control cabinet issues a packet to which it expects a response, it sets the ~BUSY signal to its active (logic 0) state. Once the ~BUSY signal is in its active state, the control cabinet will ignore any subsequent clock signals until it receives a return packet from the target cabinet; amongst other things, this packet will have the ~BUSY signal returned to its inactive (logic 1) state.

Now consider a cabinet containing some RAM as shown in the previous illustration. Assume the Control Logic issues a packet requesting a read of the data from one of the locations in this cabinet (this packet will have the ~BUSY signal set to its active state). When the system was originally set up, the GPIO card in this cabinet will have been initialized to handle the ~BUSY signal in one of two ways (each GPIO card will be configured appropriately to handle the contents of its own cabinet).

The first technique is for the GPIO card to wait a pre-programmed amount of time (this can be set from zero to tens of seconds). At the end of this delay, the GPIO card will sample the signals coming out of its cabinet, gather them together, and transmit its response packet to the outside world (this response will include the ~BUSY signal being returned to its inactive state). This is the simplest arrangement, but it fails to address situations where a cabinet may respond with variable speed. For example, consider a memory cabinet in which data is stored in a carousel-type arrangement (like a "wheel"). If the required data is in the "basket" that is currently at the "reader", then the response will be relatively fast. By comparison, if the required data is in a basket that is at the far side of the "wheel" from the "reader", the response will be much slower.

In order to address such a variable-delay scenario, the GPIO card can be programmed to present a copy of the incoming ~BUSY signal to logic in the cabinet. The GPIO will then poll (keep on sampling) a corresponding ~BUSY signal coming out of the logic in the cabinet until this signal indicated that the cabinet has completed its operation, at which point the GPIO card will sample the other signals coming out of the logic, gather them together, and transmit its response packet to the outside world (the actual mechanism behind all of this will be presented in more detail later.)




 
The ALU Logic
A high-level view of the physical ALU cabinet is as follows:

High-level view of the physical ALU cabinet

For the purposes of these discussions, however, we'll assume that the GPIO card has been programmed such that it does not write/read the ~BUSY signal to/from the physical logic. This means that:

The input signals that are actually used by the ALU Logic are:
     data[7:0] The main data bus (from wherever)
     Ci The carry-in status flag (from the Status Logic)
     inst[4:0] The ALU Instruction (from the Control Logic)
     clk_alu_acc The ACC clock (from the Control Logic)
     clk_alu_tmp The TMP clock (from the Control Logic)
     ~ena_alu_tbuf The tri-state enable (from the Control Logic)

The output signals that are generated by the ALU logic are:
     data[7:0]        The main data bus (to whichever cabinets are interested)
     O The overflow flag (used by the Status Logic)
     N The negative flag (used by the Status Logic)
     Z The zero flag (used by the Status Logic)
     Co The carry-out flag (used by the Status Logic)

Note: When the GPIO card in the ALU Logic decides to transmit a packet containing data[7:0] values to the rest of the system, it must also update its own data[7:0] signals being fed into the ALU Logic (this is because it might require these signals for something like an INCA or DECA instruction).

Note: When the GPIO card in the ALU logic decides to transmit a packet containing status information (a) it should set the interrupt mask (I) flag to a default value of 0 because it cannot affect this flag (nothing will use this ALU-generated version of the signal anyway) and (b) it should not update its own carry-in (Ci) status flag because the ultimate state of this signal is determined by the Status Logic cabinet itself.

Note: When the GPIO card in the ALU logic sees an incoming general-purpose communications packet its actions depend on the unit in which the packet originated and the type of information it contains (this will be discussed in more detail in Part 3).

OK, now let's take a slightly closer look at what's inside the ALU as shown in the following illustration. Observe that this illustration shows only the mail elements forming the ALU (the 8-bit accumulator, an 8-bit temporary register, the ALU itself, and an 8-bit tri-state buffer). The point is that this illustration doesn’t pre-suppose any particular detailed implementation.

We'll plunge deeper into the ALU in Part 3 of this series, at which time we'll describe one possible implementation for this little rascal. Next, based on this implementation, we'll walk through the pseudo-code representation that is used as the basis for our virtual ALU cabinet as used in the HRRG emulator. But for the moment, we'll just note that the five ALU instruction bits inst[4:0] in the control word coming from the Control Logic equate to the following ALU operations (the values 10100 through 11111 aren’t used in this implementation):

Decoding the ALU instruction bits



 
The Status Logic
A high-level view of the physical Status Logic cabinet is as follows:

High-level view of the physical Status Logic cabinet

For the purposes of these discussions, however, we'll assume that the GPIO card has been programmed such that it does not write/read the ~BUSY signal to/from the physical logic.

The input signals that are actually used by the Status Logic are:
     data[7:0] The main data bus (from the memory)
     O, N, Z, C The flags generated by the ALU Logic
     clk_status_i Clock for I bit
     clk_status_o Clock for O bit
     clk_status_n Clock for N bit
     clk_status_z Clock for Z bit
     clk_status_c Clock for C bit
     sel_status_2_1 Mux control
     ~set_im Set interrupt mask
     ~clr_im Clear interrupt mask
     ~ena_status_tbuf Tri-state enable

The output signals that are generated by the Status logic are:
     data[7:0]             The main data bus (to whichever cabinets are interested)
     status[4:0] The status flags (used by the Control Logic)

Note: When the GPIO card in the ALU Logic decides to transmit a packet containing data[7:0] values to the rest of the system, only the least-significant five bits contains the status flags, so the three most-significant bits are padded with zeros.

Note: When the GPIO card in the ALU logic decides to transmit a packet containing status information (a) it should set the interrupt mask (I) flag to a default value of 0 because it cannot affect this flag (nothing will use this ALU-generated version of the signal anyway) and (b) it should not update its own carry-in (Ci) status flag because the ultimate state of this signal is determined by the Status Logic cabinet itself.

A slightly closer look at what's inside the Status Logic cabinet is as shown in the following illustration. Most of the time, the O, N, Z, and C status flags coming from the ALU cabinet will be the primary data inputs to this cabinet (signals from the Control Logic determine which of these values are actually loaded into the Status registers). The data[7:0] inputs are used in the case of a POPSR ("pop the status register off the stack") instruction (only the least-significant five bits (data[4:0]) are actually used; the most-significant three bits are simply left unconnected). Also, the Control Logic can use its ~set_im and ~clr_im signals to load the I flag with 1 or 0 respectively [the Control Logic uses these signals to implement the SETIM ("set interrupt mask") and CLRIM ("clear interrupt mask") instructions].

More detailed view of the status logic

Most of the time, the I, O, N, Z, and C signals coming from the status registers will be the primary outputs from this cabinet (the C signal is used by the ALU cabinet; all of the signals are used by the Control Logic). The data[7:0] outputs are used in the case of a PUSHSR ("push the ststus register onto the stack") instruction (only the least-significant five bits (data[4:0]) contain the status flags, the most-significant three bits are padded with zero values).




 
The Addressing Logic
A high-level view of the physical Addressing Logic cabinet is as follows:

High-level view of the physical addressing logic cabinet

For the purposes of these discussions, however, we'll assume that the GPIO card has been programmed such that it does not write/read the ~BUSY signal to/from the physical logic.

We'll discuss the way in which this cabinet works in more detail in Part 3.




 
The Control Logic
A high-level view of the physical Control Logic cabinet is as follows:

High-level view of the physical control logic cabinet

For the purposes of these discussions, however, we'll assume that the GPIO card has been programmed such that it does not write/read the ~BUSY signal to/from the physical logic.

We'll discuss the way in which this cabinet works in more detail in Part 3.