Blog

In Memoriam: R. Hannes Beinert

I learned that my friend R. Hannes Beinert (“Hannes”) passed away during the first day of January, 2024. As he was about eight years my junior, this was quite a shock. Although we had not been in contact for a few years, I still counted him among my friends, and I will miss him.

In the early 1970’s I tended to hang around the University of Wisconsin (UW) Computer Systems Lab (CSL). My friend Paul Pierce, a student at the time, was employed there. The computers at CSL were free to use on a sign-up basis, and time was regularly available. In those early years there were cables that ran between the PDP-11/20 and the Datacraft 6024 to a home-grown switch box that allowed one to switch simple peripherals, like paper tape, a printer, and a card reader, between the two. Hannes, a high school student at the time, would sometimes step on the cables, and we used to call him out on it and tease him mercilessly about it.

A year or two later, UW CSL was running UNIX 6th edition on a PDP-11/45 that was on loan from the Wisconsin state printing office. Hannes adopted the user name “oracle” (later he had an email address “oracle@dodona.com” as well.)

We played D & D together, Hannes, Paul, Steve LaMotte and myself first with Paul Trandel as our dungeon master, and later as Steve took over that role. Hannes and I also played ping pong at Union South. One evening we got into a friendly tussle, and Hannes accidentally ripped the pocket of my winter coat a bit. He felt badly about it, and gave me some of his D&D materials as recompense. Also during those years we took a raft trip down the Wolf river in Wisconsin, in part through the Menominee reservation, including a tumble over “Big Smokey” falls. Hannes, myself and my wife were in the same raft when we went over the falls — something over a 10 foot drop — and managed to stay upright. (In those days there were no helmets, either. 😉 ).

Around that time UW CSL purchased a PDP-11/70 to use for course instructional work, a machine well suited to running UNIX. Trouble was, it had no other software, and the UNIX we had, 7th edition, did not have a standalone program to support the tape drive it had to load the system onto disk, and although a tape drive that would have been supported existed on the CSL VAX 11/780, for some reason it was not a good idea to borrow it. I was already employed by Wisconsin DOT at the time, but we both (mostly Hannes) worked into the wee hours to get it loaded – I wrote the tape read routine, and Hannes the disk write routine. We assembled the code on the PDP-11/20 to get printed listings – the PDP-11/70 had no card reader, teletype or paper tape reader, just a 120cps DecWriter. I left about 2AM, and stopped in about 7:30 AM on my way into work to check in. Hannes had stayed all night and had the UNIX 7th edition booted up. (I used that system to work on Small-C for the IBM mainframe.)

During his high school and college years Hannes also became an accomplished sailor, sailing with the Hoofer Sailing Club. Somewhere along the line, Hannes also served as Fleet Captain for the Hoofer Sailing Club 470 fleet. Later he also raced, along with others in the Hoofer sailing club, on Lake Michigan on a sailboat known as “Marika” owned by Don Stitt, a member of the state’s legislature. In 1989 I had a kind of epiphany with respect to being more active, and Hannes offered to take me and my wife out on “Maria”, the Santa Cruz 33 foot sailboat owned by the Hoofer Sailing Club. (The plan had been to go out on Marika, I had taken the day off, but Hannes had kind of forgotten, and the weather on Lake Michigan that day was a bit windy anyway). I was hooked. A couple of weeks later he took me out on an M-20 Scow (I think it was the yellow one, that I later crewed on in Mendota Yacht Club races) and I was really hooked. I joined the club, and sailed actively for about 20 years – I last went out in 2019 before the pandemic hit. Hannes maintained the UW Outdoor Rentals Mooring field for a few years as well.

During those years Hannes studied and obtained his Masters license with a sail endorsement. He served as crew aboard the sailing vessel Rose (later renamed the Surprise), and he also served as boatswain on the sail training vessel Pogoria (wikipedia) from Poland for a trip across the Atlantic. We both attended the early meetings in the development of the sailing vessel Denis Sullivan, originally sailing out of Milwaukee, as well – that vessel has since relocated to Boston. A bit later Hannes served on the research vessel “R/V Acoustic Pioneer” doing sonar work off the cost of Alaska.

Hannes helped immensely in the acquisition of many of the minicomputers that are in my collection. He drove the trucks as I had no experience with them, and helped me carry equipment down our steps into the basement. Machines he helped with included the Data General Eclipse S/140, the PDP-11/24 (which we hauled out of Bascom Hall at UW), and a number of machines that had been in Professor Marleau’s electrical engineering computer lab at UW – including a PDP-11/20 (which I had used when I was in sch0ol), a PDP-11/40 and a PDP-11/45, and with the PDP-12 as well. Hannes and my friend Pete Mooney also once showed up in the evening with a truckload of gear, including a Data General Eclipse S/130, a Data General Nova 4, a Data General Nova 3 (since donated to the Large Scale System Museum) a Commodore PET and a Cromemco Z-2 S100 system.

One time, while Hannes was out of town, I got a call from his then girlfriend indicating that they were about to throw out a PDP-11/20. I rescued the “guts”, and Hannes later loaded the rack into the back of his parent’s Toyota Corolla station wagon to transport it to my house. I thus named this particular PDP-11/20 as the “Hannes’ PDP-11/20“.

In later years he served as caregiver at home for his mother (whom he referred to as “Mutti”) who suffered greatly with cancer and he continued to live in their house with his father, Helmut Beinert.

Unfortunately over the years we slowly drifted apart, and had only occasional contact. I regret that now, and he will be missed.

IBM 1410 FPGA: Input Check

The next issue to fix was another instruction check, this one after a console input instruction finished where the number of input characters was less than or equal to the number of expected input characters.

The basic problem was that as I/O was ending, the I CYCLE CTRL signal goes active while E CH UNOVERLAP IN PROCESS is also active.

The problem can be seen in this waveform capture:

Instruction Check during completion of console input where the number of characters entered is less than or equal to the number of expected characters.
Instruction Check during completion of console input where the number of characters entered is less than or equal to the number of expected characters.

What made this problem a bit more interesting was that this error did not occur if the number of characters entered was more than the available buffer (i.e., from the address specified in the read instruction up to and not including the group mark with a word mark that marks the end of the input buffer:

NO Instruction Check during completion of console input where the number of characters entered is greater than the number of expected characters.
NO Instruction Check during completion of console input where the number of characters entered is greater than the number of expected characters.

I spent quite a few days looking at this and that and trying this and that, without making much headway. And in the process I discovered a couple of interesting errors in the IBM CE documentation for the 1410.

One thing I noticed was that the logic for an Instruction Check that is shown in the IBM 1410 System Fundamentals manual, S223-2589 and is quite simple would not have caused this Instruction Check, and that the logic in the Instruction Logic Diagrams, R23-2936 does have logic that would trigger an error under these circumstances and is more complex. The latter matches (more or less — more on that later) the ALD and triggers this error from either of the bottom two sets of (ILD) AND/OR gates in the lower left hand corner of Figure 58 of the ILD. (In reality, these are implemented using AND/NOR gates – aka And/Or/Invert gates).

The second thing I noticed was that in the I-O sequence diagram on page 43 of the 1411 I/O Operations Manual 223-2692 depicts +S I CYCLE CTRL indeed overlapping +S E CH UNOVERLAP IN PROCESS – in contradiction to what is on the ILDs.

Finally, in comparing the ILD to the ALD I did spot one error in the ILD. In the bottom most And/Or gate on the ILD, there is an OR gate for signals E CH OVERLAP IN PROCESS and I CYC CTRL. In fact, that one is F CH on the ALD (which make more sense).

So, what to do. I had some concern that the change I made earlier to ALD page 12.12.62.1 to inhibit E Cycle Required during Logic Gate A might be a problem, but thought experiments didn’t bear that out. Also, the condition seemed to be benign, in that once the I/O completed, E CH UNOVERLAP IN PROCESS would be de-asserted. Finally, I wondered it this might be another case where the speed of the FPGA logic for multiple layers via LUTs – look up tables – might be causing a race condition.

In the end, I decided on a simple approach. I created a variant of card type DHL, called DHLJ, with an extra direct input to the NOR gate, using otherwise unused pin K. I then fed in the I-O LAST EXEC CYC signal into ALD logic blocks 4E and 4H, which resolved the Instruction Check.

This is shown in the following timing diagram:

Input Instruction Check fixed by inhibiting an instruction check when IO is finishing up and +S I-O LAST EX CYCLE is active.
Input Instruction Check fixed by inhibiting an instruction check when IO is finishing up and +S I-O LAST EX CYCLE is active.

This isn’t the most satisfactory thing in the world, but given the contradictory nature of the IBM materials, I didn’t feel like I’d be able to sort it out properly – at least for now. (Also note in the above timing diagram the “notch” in +S E CYCLE REQUIRED during Logic Gate A, caused by the earlier fix.)

With this fix, there are no more problems running the 1410 diagnostic CU01C, nor the 1401 Mode diagnostic M011, including console input.

There is still much to do, including replicating the E Channel fix to ALD 15.41.10.1 into the F channel. After that, I think I will spend some time cleaning up console operations, where there are lots of things to change on the PC Support program software side, as well as some hardware issues, like the improper prompt character during the start of a console Display operation (and other operations as well), and some possible issues during address set and storage load and regen operations.

IBM 1410 FPGA: No. 5 sez: Need More Input

As mentioned in the previous post, during testing of the 1401 compatibility of the IBM 1410 I discovered that console input was not working properly for the machine in either 1410 or 1401 mode. The 1411 CPU would accept the characters, but only the first was entered into storage (if that), and pressing Inquiry Release or Inquiry Cancel did not terminate the I/O operation. After some trial and error signal examination, I discovered that the E1 Register Full latch was “oscillating”, and the cause seemed to be a simultaneous set and reset signals.

In the original hardware, this was unlikely to occur, given multiple layers of logic gates, signal travel times on the backplane wiring, and so on. But in a simulation, or in an FPGA the combinatorial logic signals are implemented using look up tables (LUTs) making instantaneously simultaneous combinatorial signals a likely possibility.

Timing Diagram showing problem with E1 Reg Full being set and reset at the same time, resulting in an unstable latch.
Timing Diagram showing problem with E1 Reg Full being set and reset at the same time.

So, how to prevent that? The first, more or less obvious thing, was to condition one or both of the set and reset signals to give one or the other priority. I found that if I gave the reset signal priority (by inhibiting set when reset was active) that console output was negatively affected, because this change affected both input and output.

However, if I added an inhibit from the set signal to the logic block at 5A, so that set for just input had priority, the problem went away – I could type characters into the console and they were properly entered into memory.

But I also noticed that doing the fix that way I ended up with second pulse of +S SET E2 REG during the cycle. While this didn’t seem to cause any real problems, I was nervous about possible future effects. In addition, it left the E1 FULL signal active for longer than it needed to be.

First attempt to fix E1 Set/Reset Latch problem resulting in duplication of +S SET E2 REG
First attempt to fix E1 Set/Reset Latch problem resulting in duplication of +S SET E2 REG

While looking at ALD page 15.62.04.1, which generates signal +S SET E2 REG, I noticed another signal, delayed by 1 IBM 1410 clock pulse, +S SET E2 REG DELAYED. Feeding that into the logic block 5A on ALD page 15.41.10.1 instead of +S SET E2 REG allowed an earlier reset of the E1 REG FULL latch to the time where it really should be happening, and prevented the extra +S SET E2 REG pulse from occurring.

Fix for E1 REG FULL latch problem by using +S SET E2 REG DELAYED
Fix for E1 REG FULL latch problem by using +S SET E2 REG DELAYED

I am a little concerned about the +S E CYCLE REQUIRED being inactive during Logic Gate A, but it doesn’t seem to be causing any problems so far.

However, there is still one remaining issue with console input. If I enter more characters than are allocated in the buffer (terminated by a Group Mark with a Word Mark), the M%T0xxxxxR instruction ends normally. But if I enter fewer characters or the exact number of characters expected, the instruction ends with an Instruction Check, I think because I CYCLE CTRL and E CH UNOVERLAP IN PROCESS are both active at the same time. In the CE instructional text manuals, this check is not present in the logic, however in the ILDs it is present. The question is whether the test should not be implemented the way it is (perhaps by adding some signal to the logic), or if it is just an inopportune appearance of a Error Sample pulse at that time.

IBM 1410 FPGA: We ain’t got no 1401 Overflow anymore?

The last issue that I had running the 1401 diagnostic (aside from Console I/O input working in neither 1410 nor 1401 mode) was “ERR ?3S” in diagnostic M011A, which corresponds to diagnostic location 07032 (the routine actually starts at location 06980). This is test RN111, the very last test in the diagnostic.

The diagnostic comment block says it all:

RN111
TURN ON OVFVLW IND WITH ADD INSTR
EXECUTE BR INSTR WITH UNITS PSN OF
A ADDR CONTAINING Z
TEST FOR OVLW IND STILL ON

Trouble was, the overflow indicator was indeed off after executing the branch instruction at location 7016 (which branches to location 7899, which was set up to just branch right back to location 7020.) What is so special about the “Z”? Well, it turns out the “Z” is the d-character for a B(I)Z instruction – branch on overflow (a sample of which is at location 7027). But why should that ever be in the Op Modifier register for an unconditional branch instruction that has no “d” character?

Well, it turns out that the 1401 mode instruction readout often places a character from the address into the Op Modifier register, as noted in the IBM 1401-1410 Compatibility CE Instructional Manual, Figure 3B on page 9.

There were a few possibilities for this problem, and a few possible cures for this. In the end, some simulation runs demonstrated that the reset occurred because “Z” was indeed still in the Op Modifier register when the unconditional branch was set up.

Simulation trace showing the Overflow indicator being reset during readout of a Branch Unconditional instruction with "Z" as the last character of the address.
Simulation trace showing the Overflow indicator being reset during readout of a Branch Unconditional instruction with “Z” as the last character of the address.

There were several possible cures that might have fixed this, focused on the fact that in a normal B(I)d conditional branch the d character is read out later in the I cycle – so maybe one could reset the Op Modifier register after the address was read out and the following character had a word mark – indicating that the branch had not “d” character at all. But in thinking about it I wondered why this very specific test was in the diagnostic – and as the last test, which maybe meant this was an issue that was uncovered in the field (and perhaps only on machines with the Accelerator special feature).

The reset of the Op Modifier register is controlled on ALD 15.38.04.1. Interestingly, a very relevant signal, +S CHAR TEST BRANCH OP CODE that this page says originates on page 13.13.05.1, does not show up on page 15.38.04.1 as a destination. I had had to “add” that signal into the signal list when I came to page 15.38.04.1 when I entered the data for that page into the database. Perhaps more interestingly, the Instructional Logic Diagram for this ALD, part of ILD Figure 26, shows the signal as instead being +S 1401 COND TEST OP CODE , and is designed to reset the Op Modifier register when:

  • +S 1401 COND TEST OP CODE is active AND
  • In 1401 Mode AND
  • The B Channel has a WM Bit (i.e., end of the instruction) AND
  • Logic Gate D AND
  • I Ring 8 Time

Well gee whiz… this was exactly the kind of signal I was looking for to fix this problem. So, to fix it, all I did was change +S CHAR TEST BRANCH OP CODE on the ALD to the one the ILD specified, +S 1401 COND TEST OP CODE, and the problem was cured, with no side effects causing other problems.

Simulation trace showing the reset of the Op Modifier register during I8 time during readout of an unconditional branch instruction.
Simulation trace showing the reset of the Op Modifier register during I8 time during readout of an unconditional branch instruction.

So this was presumably a case of either a) a mismatch between a page denoting it is for the ACC feature (15.38.04.1) and the source page of 13.13.05.1 which does not call out the ACC feature, or, perhaps, page 15.38.04.1 being “down level” – not having a necessary ECO t fix this. When I did the change, I set up an “ECO” JRJ005 in the database.

With this, the 1401 diagnostic M011A runs to completion without errors, as does the 1410 CPU diagnostic CU01.

During this testing, however, I discovered an issue affecting both 1410 and 1401 mode: Console I/O Input does not work – the characters don’t seem to make it into “core”, and when Inquiry Release is pressed, the I/O operation does not complete. This could be something as simple as a support console software bug or, more likely, an issue in the interface between the 1415 console emulation VHDL and the 1411 CPU Channel, since 1415 Console Input during console control operations (setting addresses, memory data, etc. all seem to work mostly OK). Time will tell.

IBM 1410 FPGA: S’more SAR Instruction Issues

So, not the yummy treats, but a new problem that showed up with the SAR instruction.

The fix to ERR 60J was pretty easy. That was a gate for feature S10 – a 10K 1410 that needed removing (and its output replaced by a logic ‘1’) on page 14.30.05.1. QED.

However, after fixing that, I then experienced an error near another Store A Address (SAR) instruction, at (just before) location 8624, exhibiting A Channel, Assembly Channel and Address Exit validity checks, with garbage in the B Address Register. However, when I ran the same instructions in the same place in the address space (but with memory otherwise all blanks) it seemed to work just fine. How could this be?

The first blind alley was either that the print chain used for the diagnostic listing printed the 1410 characters “?” and “!” as “&” and “-” respectively, or there was a bug in the listing version that was fixed on tape. So much for that hypothesis.

To figure this out it would be best if I could get it to fail under simulation (There is a scoping capability in the FPGA as well – but not as quick and easy to use.) As mentioned above, during initial testing for this problem, I just loaded the relevant instructions into the appropriate memory locations with memory from 10K up to 40K being blank characters and the failure did not occur. Further more, during testing I discovered that if I had only loaded the first 10K of the 1410 1401 mode diagnostic, M011, as the listing only went up to just under 9K, this problem also did not occur, and the only error ?3S (translated into address 07032). However, that diagnostic is ordinarily loaded from the 1410 diagnostic program TC50, and when I used the image that I have that goes up to 40K, all heck broke loose with the error noted above. I then changed my memory initialization to all ‘9’ characters aside from the instructions under test and was able to reproduce the issue under simulation.

This led me to an initial suspicion that something must be causing more than one B character register from “core” to read out simultaneously. Only one is supposed to read out at a time – and their outputs are OR’d together. If more than one read out at the same time, the results would be problematic. But how was this occuring?

After many simulation runs looking at various signals and what might be going on, I finally hit upon this one.

IBM 1410 1401 SAR Instruction Set / Reset Race with '9's in 10K-30K
IBM 1410 1401 SAR Instruction Set / Reset Race with ‘9’s in 10K-40K

Looking at the timing diagram one can see signal -Y MODIFY BY ZERO essentially “oscillating” starting shortly after 30.153 milliseconds. That in turn caused the Ten Thousands position to change quickly, resulting in the issues as that position is used to select among the B character registers from memory. That latch “oscillation” then in turn set up problems all over the place, particularly in the Address Channel.

Looking again at the same timing diagram, one might notice that +S ADDR MOD SET TO ZERO and +S RESET ADDR MOD CTRL LATCH are both active when +S RESET ADDR MOD LATCHES becomes inactive. Those two signals both impact the Modify By Zero CTRL latch at blocks 3A and 2A of ALD page 14.30.09.1, resulting in the signals trying to simultaneously set and reset that latch – a pair of cross connected NAND gates – a typical R/S latch. This is a big nono.

In my ALD page generation, these latches are recognized, and “D” flip flops are added after each gate involved. So instead of being undefined, in this kind of situation a kind of “oscillation” is set up at about 1/2 the FPGA clock speed of 100MHz (which is also the memory clock signal “MB 0 clka” in the diagram).

The general approach I took to fixing this was to either a) prevent a set during a time when the reset signal was present or b) prevent a reset during a time when the set signal was present.

To try the first approach, I added the +S ADDR MOD SET TO ZERO signal as an input to get logic block at 3C on page 14.30.09.1. This was done directly in the VHDL – much quicker than puzzling out where to find/fudge a logic block to add to the equation and test – especially if, as in this case, the fix doesn’t work. So, apparently this situation really needed to do a Modify Address by Zero operation (which it did: this, like the previous problem, occurred while copying the contents of the A Address Register to the B Address Register.)

So, then I went to the other approach, (undoing the first one), which was to add the +S ADDR MOD SET TO ZERO signal in so as to inhibit a reset while it was active. That indeed fixed the problem, and the change to the ALD was very easy: all I had to do was add the +S ADDR MOD SET TO ZERO signal into the existing “wired OR” at ALD coordinate 4E, as “ECO” JRJ004.

As for the original 1410 implementation, this could easily be another case where the fast FPGA logic causes an issue that never cropped up in the real hardware.

After doing this, the diagnostic worked OK except for the ERR ?3S. (I have not yet tried the manual part of M011 – testing the sense switches, etc.).

Getting close…

IBM 1410 FPGA: 1401 Mode SAR Instruction

Having fixed the 1401 Store B Register instruction and gotten further in the 1410 1401 mode diagnostic program M011, it was time to look at the Store A Address Register (SAR) instruction again.

The CE Instruction materials say:

“Therefore the A address left from the previous operation must move to the BAR before the new A address reads in. This is done during a B cycle that occurs just after the Q-op is detected at I-op time.”

The first timing diagram, below shows that the +S RO A AR signal that presumably ought to be making the AAR contents available becomes inactive before the BAR is reset, so the BAR never receives valid contents – it ends up with invalid binary zeros. (In the 1410, the address registers contain 2 out of 5 code – and having no bits set at all is invalid.) The result was a number of errors, halting the CPU, as would be expected – B Channel, Address Channel, and B Character Select (because the resulting memory address was invalid, none of the 10K “core” modules was selected.

Timing diagram showing lack of A Address Register Readout while +S SET B AR is active, resulting in invalid B Register contents.
Timing diagram showing issue reading out A Address when setting B Address

There is a signal which looks like maybe it was intended to force the readout of the A Address Register – -S 1401 Q OP TRANS, however once the B cycle starts, the B Character register was cleared and so the signals that relied on – the “Q” character with at wordmark were no there once the B data register was reset early in the B Cycle.

This does not seem to be a race condition. Rather, I suspect it is resulting from the fact that some of the pages for the signals involved are for a 1410 with the accelerator feature, and some without. My hunch is that on a 1410 with the accelerator feature, all of the needed activities to copy the AAR to the BAR occur during the I OP cycle, driven by the -S 1401 Q OP TRANS signal. However, when I tried to force it that way, I was not successful.

To work around the problem, I added logic to ALD page 14.71.30.1 (A Address Register Readout) to read out the AAR when signals +S 1401 MODE 1 AND +S STORE A AR OP CODE AND +S B CYCLE CONTROL are all active. The result was the timing diagram below (sorry that it is only half of the signals, but the important ones are there.) With that change, the +S RO AAR is active through the necessary part of the B Cycle so that the contents of the AAR are properly transferred to the BAR.

Timing diagram showing fix applied to ALD page 14.71.30.1 to read out a register during the (first and only) B Cycle of the 1401 Store A Address Register (SAR) Instruction.
Timing diagram showing fix to page 14.71.30.1 to read out AAR when setting BAR during B Cycle.

With that fix in place, the diagnostics mostly run but fail with console error message “ERR 601J”. So, on to the next fix…

IBM 1410 FPGA: (Address) Exit Stage Right

With the 1410 mode CPU running correctly, it was time to test out the 1401 side of things. The 1410 has a toggle switch, allowing the CPU to run as an IBM 1401 compatible with most 1401 programs. The 1410 and 1401 are similar, architecturally. The biggest difference is that the 1401 uses 3 character addresses, with the zone bits over the units and hundreds positions in order to address up to 16,000 characters, whereas the 1410 uses 4 character addresses, capable of addressing memory up to 100,000 characters.

The primary 1401 diagnostic is M011. Once I figured out a problem involving the 1401 addressing scheme, I turned my attention to the next failure: The Store A Address Register (SAR) instruction died a horrible death with B Channel, Address Channel and B Character Select Errors. That problem manifested as a failure to copy the A Address Register to the B Address Register for storing later. I tried for a bit to fix this first, but was not immediately successful, so I decided to try and NOP out the uses of SAR, that mostly had to do with storing the address of each test so it could print out a failure message.

Having done so, the next problem quickly cropped up: the partner instruction for the B address register, Store B Address Register (SBR) also failed – it is essentially the same as SAR, but without that first step of transferring the AAR to the BAR. And the failure error was different as well: an Address Chanel Exit error. The ALD for this circuit is 18.14.02.1 . The ILD is on figure 59 at coordinate 2B – however there is also an error in that ILD. It shows the GateOff input to trigger DEZ as ground (the usual ground symbol). However, on the ALD, the F input it connect to M, which is -12 Volts, and in my scheme, that is logic 0. (Logic 1 being 0V).

The timing diagram below shows the timing issue. The B Address Register read out and validity check look like they are OK with respect to the Address Exit flip flop ACSET signal. However, the problem was that the VHDL for implementing the SMS card type DEZ has a 3 clock cycle “silo” for ACSET, so that the flip flop is not really set until 3 clock cycles after its ACSET input. In addition, there was no such silo for the other inputs. This silo was put in place to give the ACSET signal some noise immunity – so that a 1 cycle glitch would not set the trigger. But the fact that the other inputs did not have a silo meant that they were sampled 3 clock cycles (FPGA_CLK) after ACSET, and by that time the B Address Register Readout signal (PS_RO_B_AR, i.e. +S RO B AR) had become inactive.

Timing diagram for 1401 mode Store B Register instruction showing the delay in setting the Address Exit Check with respect to the readout of the B Address Register.
Delay in the Address Exit Check inputs with respect to the readout of the B address Register, resulting in an Address Exit Check.

The relevant VHDL looked like this:

   SMS_DEZ_PROCESS: process(FPGA_CLK, ACSET, DCSET, DCRESET, DCRFORCE, DCSFORCE)
        begin
        if(rising_edge(FPGA_CLK)) then
           if(DCRESET = '0' OR DCRFORCE = '1') then
              OUTOFF <= '1';
              OUTON <= '0';
              SSTAGE1 <= ACSET;
              SSTAGE2 <= ACSET;
              SSTAGE3 <= ACSET;
           elsif(DCSET = '0' OR DCSFORCE = '1') then
              OUTON <= '1';
              OUTOFF <= '0';
              SSTAGE1 <= ACSET;
              SSTAGE2 <= ACSET;
              SSTAGE3 <= ACSET;
           else
              SSTAGE1 <= ACSET;
              SSTAGE2 <= SSTAGE1;
              SSTAGE3 <= SSTAGE2;
              if(GATEON = '1' AND SSTAGE2 = '1' AND 
                SSTAGE1 = '1' AND SSTAGE3 = '0') then
                  OUTON <= '1';
                  OUTOFF <= '0';
                elsif(GATEOFF = '1' AND SSTAGE2 = '1' AND
                  SSTAGE1 = '1' AND SSTAGE3 = '0') then
                   OUTOFF <= '1';
                   OUTON <= '0';               
               end if;
            end if;
        end if;
        end process;

Once I realized what was going on, the fix was pretty easy. Just add a 3 clock silo for the inputs as well as ACSET. I took the conservative approach, however, and created a separate special instance of SMS_DEZ.vhdl, called SMS_DEZ_SYNC.vhdl to use in the Address Exit validity check logic. This new implementation of DEZ would probably work fine across the board, but I am just using it in the one place, for now.

The timing diagram below shows that now the OUTON signal does not activate – no Address Exit Check, because now the inputs are sampled at the same time as ACSET, and those inputs are still active from the B Address Register readout.

Timing diagram for 1401 Mode Store B Register showing response after adding silos for all the inputs, and not just the clocks.
Timing diagram for 1401 mode SBR after fixes.

The relevant VHDL looks like this, for gate type SMS_DEZ_SYNC:

    SMS_DEZ_PROCESS: process(FPGA_CLK, ACSET, DCSET, DCRESET, DCRFORCE, DCSFORCE)
        begin
        if(rising_edge(FPGA_CLK)) then
           if(DCRESET = '0' OR DCRFORCE = '1') then
              OUTOFF <= '1';
              OUTON <= '0';
              SSTAGE1 <= ACSET;
              SSTAGE2 <= ACSET;
              SSTAGE3 <= ACSET;
              GON1 <= GATEON;
              GON2 <= GATEON;
              GON3 <= GATEON;
              GOFF1 <= GATEOFF;
              GOFF2 <= GATEOFF;
              GOFF3 <= GATEOFF;
           elsif(DCSET = '0' OR DCSFORCE = '1') then
              OUTON <= '1';
              OUTOFF <= '0';
              SSTAGE1 <= ACSET;
              SSTAGE2 <= ACSET;
              SSTAGE3 <= ACSET;
              GON1 <= GATEON;
              GON2 <= GATEON;
              GON3 <= GATEON;
              GOFF1 <= GATEOFF;
              GOFF2 <= GATEOFF;
              GOFF3 <= GATEOFF;
           else
              SSTAGE1 <= ACSET;
              SSTAGE2 <= SSTAGE1;
              SSTAGE3 <= SSTAGE2;
              GON1 <= GATEON;
              GON2 <= GON1;
              GON3 <= GON2;
              GOFF1 <= GATEOFF;
              GOFF2 <= GOFF1;
              GOFF3 <= GOFF2;
              if(GON3 = '1' AND GON2 = '1' AND GON1 = '1' AND GATEON = '1' AND
                SSTAGE2 = '1' AND  SSTAGE1 = '1' AND SSTAGE3 = '0') then
                  OUTON <= '1';
                  OUTOFF <= '0';
                elsif(GOFF3 = '1' AND GOFF2 = '1' AND GOFF1 = '1' and GATEOFF = '1' AND 
                  SSTAGE2 = '1' AND SSTAGE1 = '1' AND SSTAGE3 = '0') then
                   OUTOFF <= '1';
                   OUTON <= '0';               
               end if;
            end if;
        end if;
        end process;

With that out of the way, I could run M011 diagnostics quite far into the tests, until it needed to use the SAR instruction for more than just tracking the test address.

IBM 1410 FPGA: 1401 Mode “Zoned Out”

Having fixed the problem with the space, I continued to test out the IBM 1410 in 1401 mode. At first, I had thought that it was getting quite far in the diagnostic M011 – it would error out with the I register (instruction counter) at 6029. I spent the better part of a day chasing down an apparent problem with the Store A Address Register (SAR – opcode Q) instruction at the indicate location. However, when I placed a halt at the test before that, it still failed at the same place. How could that be?

So, I decided it would be worth the trouble to run the 1401 diagnostic in Instruction Fetch/Execute mode (I/E). The problem became apparent much more quickly than I had anticipated. After halting at the halt and branch instruction at location 2018, it ended up trying to fetch an instruction at a location near 06020. (My memory is just a little fuzzy on when that flying leap actually occurred, and I don’t have the output anymore.)

As you may know, the 1410 has 5 digit addresses, whereas the 1401 used 3 digit addresses plus zone bits to address up to 16K of memory. It was clear that somehow the translation from the 1401 style address to the 1410 address register had gone awry.

A little digging reminded me that there was one page of the automated logic diagrams (ALDs) associated with this translation, part of what is called the “Zone Adder” that was missing – page 14.18.04.1. After some time working with the xsim simulator under Vivado, I began to suspect a problem with my re-creation of the logic from that page.

  • Input “A”: -S ZONE ADDER A A DOT B A
  • Input “B”: +S ZONE ADDER B BITS EVEN
  • Output “O”: +S A NOT A DOT B A DOT B BITS EVEN

The output name is sufficiently complicated that the equation for this is not self-evident. Looking at the ILD figure 55, it looks like the following should be the equation:

O <= NOT A and NOT B — The NOT A is because A, above is -S not +S

Interestingly, page 14.18.04.1 is not referenced at all in the 1410 1401 Compatibility manual on page 7. On both the ILD and that manual, this signal is routed to the middle of a logical OR gate labeled “Zone Adder Carry”, which is laid out on page 14.18.06.1.

Regardless this VHDL caused the problem noted above. However, I had also penciled in on the ILD an additional inverter, which would be the signal without the added inverter (double negative and all that…). For that, the equation would be:

O <= NOT(NOT A and NOT B)

And it actually takes one less “fudged” gate, because the SDRTL provides this result outright.

It turns out that removing that inverter from the logic for that ALD (and thus implementing this second equation) cured that particular problem, both under xsim and running on the FPGA. But, at least superficially, this makes it look like it does not match the ILD — at least at first.

However, and finally, examining the page to which this signal is routed, 14.18.06.1, one sees that it is routed to a logical OR (physical NAND) gate where -S / -B active inputs generated the +S active output. So if one takes the two together, the end result is such that it does match the ILD.

The diagnostic didn’t get very much further, however, and now fails at location 2032 on a SAR instruction, similar to the failure after the “flying leap” problem, just at a different location. SAR is interesting in that it first copies the A Address Register to the B Address Register, and that is apparently failing.

IBM 1410 FPGA: “Space Cadet”

No, not that kind of cadet. Unlike the IBM 1620, the IBM 1410 does have adder circuits for doing addition (and multiplication and division as well). Instead, this issue had to do with the IBM 1415 space function.

I had thought that the principle instruction diagnostic, CU01, was working perfectly, but it was not quite so. I had noticed that even after finishing the diagnostic, I kept getting space characters sent to the PC support program, but figured that was just a software bug somewhere. However, when I started to run IBM 1410 1401 compatibility diagnostic M011, it stopped typing its instructional message to switch to 1401 mode on the console when it hit the first space character.

After some sleuthing, I discovered that the console typewriter logic never asked the channel for the character after the space – it just kept sending that space to the console typewriter again and again and again.

As one might expect, the issue turned out to be in the console typewriter Selectric emulation VHDL code. I had miss-interpreted the signal -V CON PRINTER SPACE NO to just involve console input via the space bar. a closer look at the related automated logic diagrams (ALDs) made me realize that in fact this was also the Selectric’s way of telling the 1411 that the space process had been completed, and that it really had nothing to do with input from the space bar.

At first I tried to just use the relevant states of the finite state machine (FSM) that controls spacing. That did not work right, however, because that same FSM also controls back-spacing. Qualifying the logic signal to only be active during a space, but not backspace, operation filled the bill.

IBM 1410 FPGA: Off to the Races??

Once the 1415 console emulation was up and running, I was able to run diagnostics. The first set of diagnostic failures arose in the Assembly Channel because the Automated Logic Diagrams I had for parts of the Assembly Channel were not for the 1410 Accelerator feature, unlike the vast majority of ALD pages I had.

Once I fixed that, diagnostic CU01 ran OK in non-overlapped non-priority (interrupt) mode. However, once I enabled overlapped I/O with the priority feature in the diagnostic settings, the diagnostic errored out with an Instruction Check. The overlapped I/O is that of the 1415 console. The diagnostic then monitors that (along with a priority interrupt) to make sure that the channel status information and the interrupt operate as expected.

The Assembly Channel issue had been reproducible using a single instruction, and I could set that instruction in the initialization of the first 10K memory module, so I was able to troubleshoot it using simulation. But not this one – it happens after 10s of thousands of instructions. I had been less than confident about using the built-in logic analyzer capability that Vivado affords for Xilinx chips, but this problem left me no choice. Fortunately, after just one false start, I was able to figure out how to make a change in the signals the logic analyzer had available, set triggers, and so on – so, not so bad.

Here is what the problem looked like that caused the Instruction Check. Note that the signal +S E CYCLE REQUIRED is going active (high) just after signal -S LOGIC GATE A. Now, that should not be a problem, except that +S ERROR SAMPLE is also high at this point, and since Logic Gate A is active, as well as E Cycle Required, the logic in the CPU sees that as a possible problem – knowing that if E Cycle Required is active, it ought to be activating Logic Gate R rather than Logic Gate A. (Note: At this point I had not included +S E CYCLE REQUIRED A (one of four different ways that +S E CYCLE REQUIRED can be asserted – and which turned out to be the “villan” in this case. Anyway, here is what the output of the logic analyzer looked like:

E Cycle Required Request with a Race Condition
E Cycle Required Request with a Race Condition

Now, this was not occurring on all or even anywhere near a majority of overlapped I/O operations. Below is an example (using the very same FPGA configuration) of a successful overlap. Note that in this example, +S E CYCLE REQUIRED is asserted much earlier – along with -S LOGIC GATE E so there is no race – E Cycle Required is ready and present long before the time of+S LOGIC GATE Z when the CPU makes the decision between Logic Gate A and Logic Gate R is made.

IBM 1410 FPGA Overlapped I/O Cycle With No Race Condition
IBM 1410 FPGA Overlapped I/O Cycle With No Race Condition

So, I went looking for possibilities:

  • Had I made a mistake when I entered the data for the associated ALDs?
  • Was this a race condition caused by the fact that I insert “D” flip flops to disconnect any timing loop identified by my generation code (within a single ALD) or by Vivado during synthesis (involving multiple ALDs)?
  • Was this a race condition caused because the FPGA gates are much faster than the original RTL logic SMS cards, and/or the fact that LUTs are used to collapse combinatorial logic into a decision table that may eliminate multiple levels of original gates?
  • Was this a very tight timing window in the original CPU?

During my investigation I came upon this tidbit in manual 226-2692, IBM Customer Engineering Instruction-Reference 1411 Input-Output Operations on page 46:

Service Note
Because close timing conditions occur in the areas listed below, excessive delay, or accumulated delays in the logic circuits may cause machine failures:
CHANNEL REGISTERS AND CONTROLS
E-cycle required
F-cycle required
E-cycle control
F-cycle control
Address channel

Well, do any of those look familiar? Like maybe the italicized one? While I have resolved the issue, I do not know, for sure, the exact nature of why I ran into it. The original CPU had the +S E CYCLE REQUIRED signal originating in (physical) Frame “D”, whereas the logic gate signals are created in Frame “C”, a couple of feet apart. As a guess I think it is most likely the the FPGA logic is faster than the original hardware in this area, such that +S E CYCLE REQUIRED could be being asserted earlier than the original engineers thought probable.

Regardless, I faced the issue of what to do about it. I had several choices:

  • I could try and tweak my generated logic in terms of speed, by adding delays, to see if I could resolve it that way.
  • I could inhibit +S E CYCLE REQUIRED A (the one that seemed problematic) in the presence of -S LOGIC GATE A so that in such a case, the E Cycle Required signal would not be asserted until near the end of the memory cycle of this enar miss.
  • I could inhibit +S E CYCLE REQUIRED (so, all four possibilities) in the presence of -S LOGIC GATE A

The first two choices might work, but would leave me in a situation where this problem could recur later on, in some other setting, whereas the third option would prevent it from happening a priori. The only downside that I could see would be that it might prevent a device from transferring data to memory quite as fast as the original.

So I investigated transfer speeds of various devices to see what they might be like:

  • Unit record devices have a core buffer in the IBM 1414 I/O Synchronizer, and are slow enough anyway, that it would not likely make any observable difference.
  • IBM 729 tape drives. The 729 IV transfers at 112.5 IPS at 556 CPI, the 729 VI at 112.6 IPS at 800 CPI. So, roughly, 112.6*800 = 90,080 cps, or a bit over 11 micro-seconds per character. So, every other cycle would be fine on a an 1410 with the Accelerator feature with 4.0 microsecond cycles – allowing it to “steal” every other core cycle.
  • IBM 7340 Hypertape Drives. Some models are 112.5 IPS / 170,000 cps tape drives (so, roughly 1500 CPI), or 5.9 microseconds/character. That would require making transfers in non-overlapped mode (see the 1302 disk drive, below). However, ones attached to a 1410 more likely operated at 34,000 cps – plenty slow enough.
  • A 1405 Disk Drive spins at 1200 RPM (so only 20 rps) and has a 1000 character track size (so, say 1200 to be conservative). That gives us about (1/20)/1200, or 50ms/1200, or 41 microseconds per character – lots of time.
  • A 1301 transfers characters at 90,100 cps, or 11 microseconds per character – so plenty of time using every other core storage cycle.
  • A 1302 transfers characters at 184,000 cps, or 5.4 microseconds per character. But on a 1410, these devices transfer data only in non-overlapped mode (even if the I/O instruction specifies overlapped mode) – because they must use consecutive storage cycles for their data.
  • A 1311 (the 2311 is not supported) has 2980 characters/track, and rotates at 40ms/revolution. this gives us roughly 13 microseconds per character.

These point to things being OK so long as the peripheral can “steal” every other core cycle. On top of that, the 1410 Channels are double buffered, so even if sometimes it takes 5 cycles to get two characters in or out, operation should not be affected. It would not seem the peripheral speed would prevent using the last option listed.

So, I made the changes, labeling them with a fictitious ECO “JRJ001” in the database and tested – diagnostic CU01 now passes without problems. Below is what the signals look like, timing wise. I believe (but cannot prove) that what happened is that +S E CYCLE REQUIRED ended up delaying until the next possible “last logic gate” (in a given memory cycle), which is typically logic gate E, as is the case in this capture.

E Cycle Required after Installing "ECO" JRJ001
E Cycle Required after Installing “ECO” JRJ001

So, what is next on the block?

  • Several enhancements to the console program, including merging what is now the main root window with the 1415 console form – no need to have them separate.
  • Run more diagnostics, by saving core images under my software simulator and transferring them to the FPGA memory to read them, as I did with CU01.
  • Experiments with speeds: how fast can I run the 1411 CPU before it fails its diagnostics?
  • Research into channel signals. I don’t have ALDs for the relevant IBM 1414 I/O Synchronizers, though I do have ILDs, which pretty well define the logic. But rather than parroting exactly what the 1414s would have done, I will likely just use VHDL using some of that ILD logic as a wrapper around communication to and from the PC support program, at least at first.