Showing posts with label MCP. Show all posts
Showing posts with label MCP. Show all posts

Sunday, November 20, 2016

Emulator Release 1.04

Nigel and I are pleased to announce that version 1.04 of the retro-B5500 emulator was released on 4 September 2016. All changes have been posted to the repository for our GitHub project. The hosting site has also been updated with this release, and for those of you running your own web server, a zip file of the source can be downloaded from the GitHub repository [updated 2022-05-07].

This is a minor release containing a number of enhancements and corrections for issues we have discovered since version 1.03 was released a little over a year ago.


Enhancements in Release 1.04


This release of the emulator supports the following enhancements.

New Single-Precision Add/Subtract Implementation


The B5500 uses a unified numeric format, which means that it does not have the typical distinction between integer and floating-point numbers that most computer architectures do. Integers are simply values that have been normalized so that their exponent is zero. For exaple, octal 0000000000000001 (the integer representation of 1) and 1141000000000000 (the normalized floating-point representation of 1.0, i.e., octal 1000000000000 × 8-12) are the same value as far as the B5500 numeric operators are concerned.

There is a document informally referred to as "The Flows," which contains a schematic representation of the logic equations for each operator syllable. Alas, we did not have access to this document when initially developing the emulator, and had to rely on its companion, the Processor Training Manual, which is a good, but not-quite-complete narrative guide to The Flows. As a result, the first implementation of single-precision arithmetic was something of a best-guess effort, and as reported previously in this blog, some of my early numeric benchmarks were producing results that had at best one significant digit of agreement with results from a real B5500.

After much frustrating research, that problem turned out to be improper rounding in single-precision Add and Subtract, which are implemented as the same instruction with some small differences in the treatment of signs. I finally fixed the problem empirically by generating results from 64 "interesting" numeric values and comparing the octal results to those from a modern Unisys MCP system, which uses the same numeric word format. That revealed many cases where rounding was being done improperly -- mostly during scaling of the smaller operand to make exponents equal. Fixing those cases allowed the benchmarks to agree with the results from a real B5500.

By the time I got around to implementing the double-precision arithmetic operators about a year later, The Flows had become available on bitsavers.org, and I followed them closely in implementing the double-precision operators. That gave me the idea that at some point I should go back and redo single-precision Add/Subtract with more rigorous attention to implementing them the way The Flows said they worked.

Earlier this year, I had a lengthy and very interesting exchange of correspondence with Reinhard Meyer in Germany, who was contemplating design of a B5500 emulator of his own and perhaps eventually producing an FPGA implementation of the machine. That exchange finally galvanized me to go back and re-implement single-precision Add/Subtract according to The Flows.

Rigorously following The Flows turned out to be considerably more of a challenge than I had originally anticipated. Digital logic tends to work in parallel, with many states changing at each clock pulse. Most of that translates fairly easily to the sequentially-executed code of a traditional programming language, but some of it does not, and you continuously need to be on guard that states set during one clock cycle do not become effective until the start of the next one.

The most frustrating problem that arose during this effort was one where subtracting two numbers of equal value generated a result that was not completely zero. The mantissa would be zero, but the sign or exponent would not. There is explicit logic in The Flows to test for this condition in the J05L block under the secondary control of Q04F/ (see index 1.01.1 page 2 of 2 in the document) and exit the operator early if the sign or exponent do not need to be cleared to zero. That test is based on the logic term W03L, which is defined as "A[39->37] = B[39->37]", meaning the high-order octade of the A-register mantissa (bits 39 through 37) equals the high-order octade of the B-register mantissa. The corresponding narrative in the Processor Training Manual (page 3.17-11) states, "If the 13th octade of the A and B registers do not equal each other (W03L/) it is not possible for the resultant sum of the complement addition to equal all zeros and the operator is terminated."

I implemented the code exactly that way. It didn't work. After staring at that portion of the logic for days, it finally occurred to me that neither the definition of W03L nor the statement in the Training Manual made sense -- it's entirely possible for the two high-order octades to be unequal and still sum to zero -- 7+1 (ignoring the carry), for example. That made me begin to wonder whether "equal" and "not equal" meant what I thought they did. To answer that question, I had to look at the document upon which The Flows are based, the Processor Equation Book, where on page 422.00, I found the term W03L/ to be defined as:

A39F*B39F + A39F/*B39F/ + A38F*B38F + A38F/*B38F/ + A37F*B37F + A37F/*B37F/

This is somewhat simplified from the notation in the Equation Book, which appears to refer to physical circuit elements. For the uninitiated, "*" means logical-AND, "+" means logical-OR, and "/" used as a suffix means logical-NOT. Operator precedence is NOT-AND-OR, highest to lowest. The numbers refer to bits in the registers, with 48 being high-order and 01 being low-order. A suffix of "F" means flip-flop.

That equation clearly does not determine inequality of the high-order A and B octades -- it determines the logical equivalence of the three pairs of bits in the octades and ORs those equivalences together. Logical equivalence is the complement of exclusive-OR. In other words, W03L/ is true if any of the three pairs of bits match. Equivalently, W03L is true if none of the three pairs of bits match. After making that change in the code, results with zero mantissas finally generated words of all zeroes.

After all the hard work to re-implement single-precision Add/Subtract from The Flows, it produced very little improvement over the results of the previous, empirically-corrected implementation. There were a few differences in the way that results are normalized, and a rounding difference if one of the values is octal 0161000000000000 and the other value is one of 0004444444444444, 0005555555555555, 0006666666666666, or 0007777777777777. On that basis, the effort invested in the new implementation was not worth the very slight improvement in results. On the other hand, it was a very interesting experience, and I learned a lot about digital logic and how the B5500 worked at the electronic level.

There is one other significant difference -- the new implementation runs noticeably slower, in terms of emulated clock time, than the prior one. For one heavily numeric benchmark that runs about ten minutes, the new implementation increases the emulated run time by 48 seconds -- a little over 8%.

Card Reader Enhancement


The implementation of the B129 card reader in the emulator allows you to load one or more text files into the reader as if they are card decks. Each line in a text file is treated as an 80-column card image. Thus, in order to read cards, you first must have a text file on your local system to hold the necessary card images.

This has proven to be a little inconvenient. If you have a file of source code you wish to compile, for example, you either need to modify that file and add the necessary B5500 control cards, or create a copy of the file and add the control cards to that.

Starting with this release, the user interface for the card reader now supports the ability to enter card images directly into the reader from your keyboard without creating a text file first. Card images entered this way can be interspersed with card images from text files. This allows you, among other things, to "wrap" existing files with control cards, compiler $-option cards, or anything else you need but don't have (or don't want) in a text file on disk.


The card reader's panel has a new button in the upper right-hand corner labeled KEY IN DECK. This button is disabled unless the reader is in a not-ready state. Clicking the button opens a sub-window that allows you to enter card images directly into the reader's buffer:


While the key-in window is open, the reader's START button is disabled.

The bulk of this window is occupied by a standard text area. You can enter text into this area from your keyboard or copy/paste text from another source. You can edit the text using the normal controls of your operating system. Clicking the Insert button at the bottom of the window appends the contents of the text area to the card reader's buffer and closes the window. Clicking the Cancel button simply closes the window without affecting the reader's buffer. Once text is inserted into the buffer, it cannot be modified or deleted, just as with inserting a text file into the buffer.

There are three white buttons along the bottom of the window with commonly-used control card images. Clicking one of these simply inserts the respective card image into the text area at the current cursor position. From there it can be appended to the reader's buffer by clicking the Insert button.

Miscellaneous Improvements


1. The size of the terminal adapter buffer in B5500DatacomUnit has been reduced from 112 to 56 characters to accommodate the requirements of the R/C interactive editor. Users of the Timesharing MCP (TSMCP) and CANDE will need to update their SYSTEM/DISK file with the new buffer size, e.g.,
?RUN SYSDISK/MAKER
?FILE LINE = LINE BACKUP DISK
?DATA CARD
LINE,0,0,56,0,0,7,0,
LINE,1,0,56,0,0,0,0,
STA,0,0,0,0,"0","0",0,0,
?END
2. We have discovered that the emulator now works with Apple Macintosh OS X using Safari versions 8 and above. Nothing has changed in the emulator to support this -- the issue was waiting for Safari to implement the IndexedDB API used by the emulated disk subsystem.

We continue to be unable to get the emulator to run in either Microsoft Windows Explorer or Edge. If anyone has tried the emulator in Opera or any other GUI browser, please let us know how that works. 

3. Despite a statement in the project wiki that the emulator must be loaded over HTTP from a web server, it appears to run just fine when loaded directly from your local file system, e.g., using a URL like this:
file:///C:/Projects/B5500/WIP-S1/webUI/B5500Console.html
The wiki has been corrected.

4. The alternate B5500SyllableDebugger user interface for the emulator has been enhanced with an Execute Single button. This executes the instruction currently in the T register, but differs from the Step button in that it does not advance the C and L instruction counter registers. This makes Execute Single a better choice than Step for testing and debugging a specific operator.

5. The default height of the SPO and line printer windows has been reduced to about a third of the screen height.

6. The tools/B5500DeleteStorageDB.html script can be used to remove the IndexedDB database for an emulated disk subsystem. Previously, this script could only remove the default data base, named B5500DiskUnit. The script now takes a "?db=" query string parameter with the name of the data base to remove.

7. The Algol Glyphs option for the card punch (CPA) has been set to false by default. Some text editors were corrupting the Unicode characters produced in Cold- and Cool-start decks when this option was set to true, making the decks useless for loading under CARD LOAD SELECT.

8. The exponential moving average computations for Delay Delta and Processor Slack in the Processor object have been adjusted slightly.

Corrections


1. Rounding in Integer Store operators has been corrected to produce a word of all zeroes if the mantissa is zero. Previously, non-zero sign and exponent fields could have been present when mantissa was scaled to zero.

2. BCL translation for alpha-mode (even parity) tape files has been corrected. Previously, the translation was being done twice -- once by the I/O Control Unit and once again by the tape drive. It is now handled entirely within the tape drive.

3. Both EOF and parity error are now reported by the tape units for any attempt to read beyond the end of a tape image.

4. The way that "green-bar" formatting was being done on the line printer was causing a blank line to be inserted every third line when copying text directly from the "paper" area of the printer's window. A different method is now used that does not result in extraneous lines in the copied text.

5. When the emulator was powered on, the browser windows for the individual peripheral devices were being created twice. This behavior was intentional, but dated from very early in the emulator's development when crashes and aborts were a frequent occurrence. The act of opening a window, closing it, and then reopening it served to close any windows left open by a crashed emulator instance. We are long past the need for that now, so the screwy open/close behavior has been removed. As part of this effort, de-registration of event handlers for the various windows has been implemented.

6. After almost five years, we are still finding errors in the transcription of the Mark XVI Algol compiler listing. Most of the errors that have come to light in the past few years have been in comments, but a few months ago we found a serious error in line 06073850 -- a plus sign had been transcribed as a minus. I doubt we are ever going to get all of the errors out of this transcription -- or of any other large transcription like this.


The B5500 Source Code Archive


We are starting to amass a significant amount of source code for the B5500. Most of this has been recovered by transcribing it from listings. Up to this point, we have been including the transcriptions we've done or received from others in the emulator project's repository. Rich Cornwell in North Carolina (US) and Jim Fehlinger in New Jersey (US) have been especially prolific in turning scanned listings into text files.

There are now multiple B5500 emulators, however, either in existence or under development. In addition to Sid McHarg's C++ emulator and this project, Rich Cornwell completed an emulator earlier this year that runs in the SimH framework, and Mark Lloyd in the UK continues to work on his Lazarus/Pascal version.

With multiple emulator projects and multiple sources of recovered source code, it has becoming less and less appropriate for that code to be embedded in a specific project. I have been thinking about this for a while, and a few months ago decided to set up a separate project on GitHub to serve as a common repository for all B5500 emulators:
https://github.com/retro-software/B5500-software
Rather than set this up under someone's personal account, I've created a GitHub "organization" to be the owner. This will make it easier to share and ultimately transfer responsibility for the archive, and also to create additional repositories in the future to maintain recovered source code for other systems. Initially, Nigel and I are the administrators of this organization and the B5500 archive, but hopefully that can be expanded in the future.

To seed this new repository, I have exported the source code transcriptions, and their history, from the retro-b5500 project and made that the initial contribution to the B5500-software project. In the process, I rearranged the directory structure into something that hopefully will be more maintainable over time. The source code in the retro-b5500 project will probably be deleted at some point down the road.

In a future blog post, I will propose some standards and procedures for maintaining the archive, but will be happy to receive comments and recommendations on this from others. I will also be happy to receive new contributions and will consider pull requests for updates. Each transcription should be accompanied by some text that describes it provenance and who did the transcription. See the README.txt files in the repository for examples of what I'd like to have in this regard.

I would like for all of the transcriptions to be faithful to their original sources, so please include sequence numbers if they are present in the original, and please do not correct spelling in comments, or even bugs in the code. Any original errors can be corrected in separate projects or branches from the transcriptions of the originals.

Monday, September 29, 2014

One Point Oh

Nigel and I are pleased to announce that version 1.00 of the retro-B5500 emulator was released on 29 September 2014. All changes have been posted to the Subversion repository for our Google Code project GitHub project. The hosting site has also been updated with this release, and for those of you running your own web server, a zip file of the source can be downloaded from the GitHub repository [updated 2022-05-07].

This release is a significant milestone in the development of the emulator. We have bumped the release level from 0.20 to 1.00 as we feel the emulator is now functionally complete. It is not finished, of course, and probably never will be. There are features of the B5500 that we still do not support (e.g., drums and paper tape devices), areas where significant improvements can be made (e.g., multiple datacom stations), and some areas that may not be practical to support in a browser-based emulator (e.g., File Protect Memory, shared disk systems, and additional datacom line-adapter types). Those issues can be pursued as our time and the desire of the user community permit.

This is also a very large release, with many new features and changes to existing ones. This blog post will attempt to introduce and summarize these changes, but there have been extensive updates to the wiki pages as well. The wiki now also has a table of contents, which can be displayed as a sidebar on the left of the wiki pages. We recommend that before using this new release, you peruse the following wiki pages in particular:

New System Configuration Mechanism


The most significant feature of this release is a completely new, and much more flexible configuration mechanism for the emulator.

Overview


In earlier releases, the system configuration was defined by a static Javascript file, emulator/B5500SystemConfiguration.js. If you were running your own web server, you could modify this file to alter the system configuration -- the processors, memory modules, I/O control units, and peripheral devices the emulator would use. If you were using the emulator from a web server hosted by someone else, however, you were stuck with whatever configuration was coded in the Javascript file on that server.

An additional restriction in earlier releases was that the configuration of the disk subsystem was fixed by the B5500ColdLoader.html script and could not be changed. The standard script created a disk subsystem with two Electronics Units (EUs) having a total of 400,000 sectors, or 96 million 6-bit characters of storage.

The new mechanism stores the system configuration in a small IndexedDB database within your browser. There is a new user interface (UI) that allows you to select the system components you want to make up a configuration. Since this data is stored locally on your workstation, each user can control their own configuration, even when the emulator files are hosted on an external web server. The Javascript file still exists, but its role is now to define the structure of the system configuration data. It is no longer used by the running emulator.

You can now also define multiple configurations and easily switch among them. Each configuration has a name that identifies it within the IndexedDB database. There is no practical limit to the number of configurations you can create. Switching between configurations is as easy as opening the configuration UI and selecting the desired name from a pull-down list.

In addition, the new configuration mechanism supports multiple disk subsystems. Each disk subsystem is implemented as a separate IndexedDB database within the browser. There are a number of uses for multiple disk subsystems. One is to support separate systems for the Datacom and Timesharing MCPs. Another is to maintain different levels of the MCP and easily switch among them.

You can specify the number of EUs in a disk subsystem and the number of Storage Units (SUs) independently for each EU. You can also modify the configuration of a subsystem at a later time to add more EUs or add more SUs to existing EUs. A disk subsystem can have up to 20 EUs (the B5500 maximum), although only the first ten EUs are addressable when the system configuration includes a Disk File Exchange (DFX) component.

The emulator now supports both the original Model-I SUs (40,000 sectors, 20ms average access time) and Model-IB SUs (80,000 sectors, 40ms average access time). The latter model was known as "bulk" or "slow" disk. All SUs for an EU must be the same model, but separate EUs can have different SU models.

You assign a name to each disk subsystem when you create it. That name also becomes the name of the subsystem's IndexedDB database. You use this name to assign the subsystem to a system configuration. A given system configuration can have only one disk subsystem associated with it at a time, but the subsystem associated with a system configuration can be changed at any time.

Using the New Configuration Interface


The emulator permits configuration changes to be made only when it is in a powered-off state. To access the configuration UI, simply click the "B5500" logo (below the Burroughs logo) on the right side of the Operator Console window. A System Configuration sub-window will open:

Emulator System Configuration Dialog

To change the set of components in a configuration, simply tick or un-tick the appropriate check boxes on the dialog and click the SAVE button. To switch to a different configuration, select it from the Configuration name list and click SAVE. To create a new system configuration, click the NEW button. The dialog will prompt you for the name of the new configuration and then fill the dialog with a default configuration, which you can modify as desired. Each time you click the SAVE button, the displayed configuration becomes the "current" configuration for the emulator. That will be the one used the next time the emulator is powered-on.

To delete a configuration, select its name from the pull-down list and click the DELETE button. The dialog will prompt you for confirmation of the delete, but once acknowledged, the deletion is permanent and cannot be undone.

Note that some elements on this dialog represent features that are not presently supported by the emulator. Their controls are disabled on the dialog.

You assign a disk subsystem to a system configuration by selecting the subsystem name from the Storage name pull-down list on the dialog. Saving the configuration associates that subsystem with that configuration. You can create or modify a disk subsystem by clicking the NEW or EDIT buttons next to the list of storage names. Doing so will open the Disk Storage Configuration dialog in a new sub-window:

Disk Storage Configuration Dialog


If you click the NEW button, the system configuration dialog will prompt you for the name of the new disk subsystem before opening the storage configuration dialog. To add EUs to the subsystem, simply tick their check boxes and select the number and model of SUs the EU should have. Click the SAVE button on this dialog to update the configuration, apply any necessary schema changes to the IndexedDB database, and associate this subsystem with the underlying system configuration.

Once you click SAVE, any storage you have added to the subsystem becomes a permanent part of the subsystem and cannot be removed later. The check boxes for the selected EUs will be disabled so that they cannot be un-ticked. You may not decrease the number of SUs, nor change Model-IB SUs to Model-I SUs, as either of those changes would reduce the amount of storage in the subsystem.

The reason for the restriction on removing storage from a subsystem is that the B5500 MCP considers all disk on the system to be a monolithic resource. Disk files are organized as a set of separately-allocated areas (extents), which may be spread across multiple EUs of the subsystem. Removing storage from the subsystem could cause some areas of files to disappear, so the emulator does not allow this.

To delete a disk subsystem, open it in the Storage Configuration dialog and click the DELETE button. The dialog will prompt you for confirmation, but once acknowledged, the IndexedDB database for the subsystem will be deleted from your workstation. This deletion cannot be undone.

Disk subsystems from earlier emulator releases can be used without change in 1.00 and later releases. These legacy subsystems have the name B5500DiskUnit. The legacy subsystems can continue to be used with earlier releases of the emulator if their configuration is not changed. Once you change the configuration of a disk subsystem, however, it can no longer be used by releases prior to 1.00. There two reasons for this:
  • Adding EUs to a disk subsystem requires a change to the IndexedDB database schema. This change increases the IndexedDB version property for the database. Releases prior to 1.00 required the database to be at version 1 and will not open a database having a higher version.
  • Each IndexedDB database for a disk subsystem contains a configuration table that describes the EUs in the subsystem. The format of that configuration table has changed for release 1.00 in a way that is incompatible with earlier releases. This also means that disk subsystems created by release 1.00 and later cannot be used with earlier emulator releases, even it their IndexedDB version is 1.

Updating from Earlier Releases


When you first power-on the 1.00 emulator in a browser with which the emulator was previously used, the emulator will create a default system configuration named "Default", having a set of components that is somewhat reduced from the default configuration in earlier releases. In particular, it has only one Disk File Control Unit (DKA) and one magnetic tape drive. The configuration will include any existing legacy B5500DiskUnit subsystem. You may wish to adjust this default configuration before proceeding further.

When you first power-on the 1.00 emulator in a browser where the emulator has not been previously used, the emulator will create both the default system configuration described above and a default disk subsystem named B5500DiskUnit. That configuration will have half the storage of previous default configurations -- one EU with 200,000 sectors, or 48 million characters.

Please see the Configuring the System wiki page for more details on the new configuration mechanism and how to use it.


New Cold Start Process


With the implementation of the new system configuration mechanism in this release, use of the B5500ColdLoader.html script is now deprecated. That script served to create the IndexedDB disk subsystem, initialize the disk directory structures, establish the bootstrap mechanism, and load the MCP and other system files from ".bcd" tape images. It dates from a very early point in the emulator development, long before card reader and magnetic tape peripheral devices were implemented.

We now recommend that disk subsystems be created using the new system configuration mechanism, and that they be initialized the old-fashioned way -- with a Cold Start card deck.

We have actually been able to Cold Start the system from a card deck for almost a year, ever since the initial tape drive implementation was made available in release 0.15 last November. We owe thanks to Tim Sirianni and Paul Cumberworth for pioneering the research in how to do this, using the ESPOL compiler to generate the necessary card-load decks from relevant symbol files, and assembling the decks with an appropriate set of parameter cards.

I have taken Tim's latest version of his deck, reworked the parameter cards somewhat, and created a default Cold Start deck you can load directly, or use as a base for customization. This deck is in the tools/ directory of the emulator files, and can also be downloaded from our hosting site at http://www.phkimpel.us/B5500/tools/COLDSTART-XIII.card.

The Cold Start deck consists of two "card-load-select" programs, the COLD Loader and Tape-to-Disk Loader, along with their respective control cards. At the end of the deck is a short MCP Library/Maintenance job that will load a minimal set of system files from the Mark-XIII SYSTEM tape image to disk.

To use the Cold Start deck, follow these steps:
  1. First download a copy of the deck to your local file system.
  2. If you wish, you can modify the parameter cards to suit your preferences, but be careful not to disturb the card images for the card-load programs themselves. Many of the settings on the parameter cards can be modified using SPO commands after the MCP is up and running, so you may want to leave the deck as is, at least initially.
  3. Load the emulator into your browser. Make sure you have the correct system configuration and disk subsystem selected. A Cold Start wipes out any existing disk directory on the disk subsystem, effectively destroying all B5500 files in the subsystem.
  4. Power-on the emulator.
  5. Load the Cold Start deck into card reader CRA and press the START button on the reader.
  6. Load the SYSTEM tape image into a tape drive (any available drive will do) and click the drive's REMOTE button to make it ready.
  7. On the Operator Console, click the yellow CARD LOAD SELECT button so that it illuminates.
  8. Click the LOAD button on the Console. The reader will load the one-card binary bootstrap on the front of the deck, which will then load the COLD Loader program into memory and start executing it. The COLD Loader will initialize the disk subsystem and create an empty disk directory. It will also process the parameter cards and store their values on disk. The program will then print "DIRECTRY BUILT" [sic] on the SPO and halt. The process should take about 30 seconds.
  9. Leave the CARD LOAD SELECT button illuminated. Click the HALT button, then click LOAD again. The reader will load another one-card binary bootstrap, which will in turn load the Tape-to-Disk Loader program and start executing it. You should see the tape spin as the loader searches for the MCP file and loads it to disk. After a successful load, the program will print "MCP FILE LOADED" on the SPO. It will then automatically boot the MCP just loaded.
  10. The standard parameter cards for the COLD Loader will set an MCP option that requires you to set the time of day after a halt/load. You should first set the date with the SPO DR command. Then once you set the time with a TR command, the MCP will read the cards for the Library/Maintenance job and load those files to disk.
  11. One of the files that job loads is the System Intrinsics, INT/DISK. Since the system was just Cold Started, you must specify the name of the Intrinsics file to the MCP using the SPO command "CI INT/DISK". The MCP will preserve that setting across future halt/loads.
  12. At this point the system is fully initialized and ready for use. You may wish to load additional files from the SYSTEM tape, or wait and load more files later as the need arises. It would be a good idea to click the CARD LOAD SELECT button at this time to turn it off.

The B5500ColdLoader.html script can still be used to initialize a disk subsystem for use with release 1.00, but it can only work with the disk subsystem named B5500DiskUnit in its legacy configuration. This script will be removed in a future release, so we strongly recommend that you stop using that script and switch to the new process described above.

Please see the Getting Started wiki page for more details on how to initialize the emulator environment using the new configuration mechanism and Cold Start card deck. That page also has links to the B5500 reference manuals that describe the card-load-select programs and their parameter cards.


Off-line Emulator Operation and the "Application Cache"


The emulator, like most non-trivial web applications, cannot be loaded into a browser from your local file system. Instead, it must be loaded over HTTP from a web server. Once loaded, however, the emulator runs completely within the browser, and the web server is not needed again until the next time you load or reload the emulator.

The continually-evolving HTML5 standards have established a browser feature known as the "Application Cache." This is a bit of a misnomer, as it is not so much a cache as it is a way to install a web application within a browser for off-line use. Once the application is installed, it can be run in the browser without access to the web server from which it is hosted, and even without the browser having access to a network connection at all. Both Google Chrome and Mozilla Firefox support this capability.

Not all web applications can take advantage of off-line operation, especially if they require access to Internet resources while they are running. It is perfectly suited to the emulator, however, since the emulator requires no network or Internet access once it is loaded into the browser. Thus, it is now possible to use a version of the emulator that is hosted on an external web server in situations where you have no access to that server. You load the emulator into the browser using the same URL you would if operating on-line, but the browser will load the emulator files from its local Application Cache rather than from the web server.

Installation and use of the emulator from the Application Cache is unconditional and completely automatic. The first time you load the emulator using release 1.00 or later, the browser will load the emulator files into its local storage. You will see messages displayed in the top-left of the Operator Console window as the application is installed and the complete set of emulator files is downloaded.

Once the emulator is installed within your browser in this way, it will continue to be served from the local Application Cache, even when your browser has network access and can reach the web server from which the emulator was originally hosted. Instead of loading the emulator files from the server when on-line, the browser will instead check the server to see if a newer version of the emulator is available. This check takes place asynchronously, in the background, and neither inhibits nor delays use of the emulator while it is taking place. You will see some messages display in the top-left of the Console while this check takes place.

If a newer version of the emulator is available on the server, the browser will download it, again asynchronously in the background. The new version will be installed automatically in the Application Cache, but the browser will continue to use the prior version until the next time the emulator is reloaded in the browser. At that point the new version of the emulator will be used by the browser and the prior version will no longer be available. This behavior is not unlike the way that most web browsers themselves are updated automatically from the Internet and made available the next time you restart them on your workstation.

Please see the Using the Operator Console wiki page for more details on off-line operation of the emulator and the messages that are displayed during the application installation and update process.


Peripheral I/O Device Changes


This release contains numerous changes and enhancements to the I/O devices and their user interfaces. The following discussion summarizes the differences from prior releases, but please see the respective wiki page on each device for details.

Line Printer


The line printer driver has been completely rewritten. The original driver was a quick-and-dirty implementation, literally thrown together as a debugging exercise. It worked well enough that we have continued to use it, but it had no operating controls and was missing several important features.

The new driver supports a user interface with controls similar to those of the B329 printer. There are now buttons to make the printer ready and not ready, and to manually perform single-space and form-feed operations. To keep printed output from flooding the memory of the browser, the printer has long limited the capacity of its "paper" area to 150,000 lines -- about the equivalent of a box of the pin-feed forms used with the real printers. The new driver now supports an end-of-paper indicator and a more realistic way of clearing the "paper" from the printer when its capacity is reached.

The B5500 used five special Algol characters that do not have ASCII equivalents -- left-arrow, multiplication, not-equal, less-than-or-equal, and greater-than-or-equal. As described in the wiki pages, we have assigned ASCII substitutes for these (e.g., left-arrow as "~"), but several people have expressed a desire to see the actual Algol glyphs, especially in printer output.

The Unicode standard has glyphs for all five special Algol characters, and many fonts available for workstation operating systems include these glyphs. The new line printer driver will now generate these Unicode glyphs, but an option on the printer UI allows you to turn this off and still obtain printed output with the ASCII substitute characters. The default setting for that option can be specified in the system configuration.

Card Reader


The card reader will now unconditionally accept the five Unicode code points for the special Algol characters in "deck" files that are loaded into it. Files may contain a mixture of both Unicode and the ASCII substitutions for the Algol characters. The reader will now also accept the underscore ("_") as an ASCII substitute for the left-arrow.

Card Punch


Similar to the new line-printer driver, the card punch will now optionally output the five special Algol characters using Unicode glyphs. The default setting for that option is also in the system configuration.

The card punch UI now has annunciators on the right side of its panel that will illuminate when one of the output stackers reaches its capacity of 850 cards.

SPO


The SPO interface has been redesigned to accept keyboard input using a standard HTML text box. Formerly, keystrokes were simply captured by the driver when the SPO window or its paper area had the focus. This works fine when you have a real keyboard, but not at all on mobile devices such as tablets that simulate a keyboard on their touch surface. Most of these devices only display the simulated keyboard in a browser when the focus is in a text box or other control that accepts text input. Since the original SPO did not use a text control, there was no way to get the keyboard to appear.

In the new implementation, the SPO driver will enable a border-less, yellow-shaded text box at the bottom of the paper area whenever an I/O Control Unit issues a read operation to the SPO. The MCP initiates a SPO read in response to you clicking the INPUT REQUEST button on the SPO window, or pressing the ESC key when the SPO window has the focus. This text box is disabled and made invisible when you end input to the SPO.

This new approach has solved several obscure, but long-standing problems with input to the SPO. It also has the advantage that you now see a cursor when keying text on the SPO, and you can use standard GUI editing and copy/paste operations during SPO input. It seems to work fine on the tablets we have tested. There are still numerous issues with running the emulator on a mobile device, however (e.g., the I/O devices open as tabs instead of windows), but we have seen significant improvement during the past few months in the ability of mobile devices to support the emulator, particularly with Google Chrome on Android devices.

As a part of the changes to implement the new text input mechanism, the paper area of the SPO is no longer implemented as an HTML <iframe> element. You can still select and copy portions of the SPO output with your pointing device, but as a consequence of this change, it is no longer possible to save or print the contents of the paper area directly from your browser. To help compensate for this, double-clicking anywhere in the paper area will cause a new window to be opened and the current contents of the paper area copied into it. You can then save or print the SPO output from this separate window. Simply close the window when you are finished with it.

The amount of scroll-back retained by the SPO remains at 1500 lines. Older lines are discarded once this limit is reached.

Additional enhancements to the SPO include:
  • Support for the Unicode Algol Glyphs on output has been implemented in a manner similar to that for the line printer and card punch. Unicode code points on input are not currently supported, however.
  • The underscore ("_") is now accepted as a substitute for "~" on input. Keying either of these characters acts as if the END OF MESSAGE button had been clicked.
  • When you resize the SPO window, the paper area will resize in concert. This is especially useful when running the emulator on a workstation with a relatively small screen. Below a certain minimum size, however, the paper area will no longer resize and the contents of the window will be clipped. The really interesting thing to me about this feature is that it was implemented entirely through CSS style sheet changes. No Javascript was harmed in the process.

Magnetic Tape


The tape loader window that is activated by clicking the LOAD button for a tape drive is now opened on top of the drive window. Previously it was opened in the center of the workstation screen, which could make it confusing to which drive the loader window applied.

Timing for the animation of the tape reel image on the drive window is now done at a more granular level. This should improve the quality of the animation and reduce the degree of visual beating between the simulated rotation of the reel and the screen refresh rate.

Disk


Disk devices do not have a user interface, but there have been a few significant improvements internally.
  • The driver has been updated to work with the new system configuration and disk subsystem mechanism. It now attaches to the IndexedDB database for the disk subsystem specified by the current system configuration and adapts to the configuration of that subsystem. 
  • The driver now supports Model-IB (slow) disks in addition to the original Model-I disks, including the difference in average access time.
  • The driver now supports both configurations with a Disk File Exchange (DFX) and those without a DFX. Without a DFX, the B5500 supports up to 20 EUs, with EU0-9 addressed by DKA and EU10-19 addressed by DKB. With the DFX enabled, the system can support only EU0-9, but both disk controls can address any disk.
  • The emulator will now refuse to do a disk load if DKA is not selected in the system configuration. This mimics the way the B5500 hardware worked.

Datacom


The way that keyboard input for the datacom terminal was handled has been extensively reworked for better compatibility with Google Chrome. A more tablet-friendly input mechanism, similar to that described above for the SPO, is under consideration, but it is much more difficult to implement for a datacom terminal, as the input mode is initiated by the user pressing any key, not by the I/O Control Unit.

General Improvements


In earlier releases, the NOT READY indicators on the I/O device windows were rendered in red. Closer inspection of some color photographs of actual B5500 installations has revealed that this is incorrect -- the lamps were white. All I/O device windows have been updated to reflect this.

Several device windows have progress bars on them to indicate things such as input or output capacity. These were being rendered with HTML <progress> elements, but this usage is an incorrect application of that type of element. These have been converted to <meter> elements, which are visually very similar.

As with the resizing feature for the SPO, most other device drivers now resize their widow contents when their windows are resized.

Other Changes and Enhancements

 

Flag Bit Errors


For some time we have had a problem with programs aborting due to Flag Bit interrupts. These typically occur during periods of intense system activity, which suggests the problem may be related to Presence Bit interrupts. It has been a difficult problem to track down.

More or less by accident, I discovered a bug in the Processor object, where the stack was not being properly adjusted during the indexing of a descriptor. The value of the A register was being used without assuring first that the AROF validity flip-flop was set. As part of that, I also reworked portions of the OPDC and DESC operators in the area that detects Flag Bit errors.

Improper stack adjustment could lead to Flag Bit errors. These changes appear to have reduced the incidence of Flag Bit errors when the system is very busy, but they still occur occasionally. The most recent cases I've examined appear to happen during procedure exit, where the processor is checking the Flag Bit [0:1] on the Return Control Word. This is the only known bug in the Processor at present, and remains an outstanding issue (#23 in the project's issue list).

Downloadable Web Fonts


Normally, web browsers render the contents of their windows using fonts that are installed locally on the workstation. Browsers have for some time supported downloadable fonts, however, so we have taken advantage of that feature in this release. The intent is to standardize the fonts used by the emulator, and to eliminate any dependency on fonts installed locally on the workstation.

We have chosen the open-source DejaVu Sans and DejaVu Sans Mono fonts for use with the emulator. The Mono font was specifically chosen because it supports the Unicode glyphs for the special Algol characters, and because it has a numeric "0" glyph that is clearly distinguished from the letter "O".

This release includes files for these two fonts in both Web Font (.woff) and TrueType (.ttf) formats. The font files are quite large, but due to their local storage by the Application Cache feature discussed above, and the fact that they never change, you should be burdened by their download only once.

Operator Console Improvements


Prior to this release the NOT READY lamp on the Console was not implemented. When the emulator is powered-on, this lamp will now be illuminated if certain minimum configuration requirements are not met, e.g., no Processor is enabled in the configuration, the selection for P1 (the control processor) is not valid, or memory module 0 is not enabled. This is not exactly how that lamp behaved on the B5500, but the current implementation follows its purpose in spirit.

In previous releases, clicking the NOT READY lamp would toggle Processor B into or out of the running configuration. That was always intended as a temporary feature, and it has been removed in this release. The presence of PB can now be controlled through the new system configuration mechanism.

The Console will now perform a brief lamp test when the POWER ON button is clicked. Please report any burned out lamps on the forum.

The names of the current system configuration and disk subsystem are now displayed in the top-right of the Console window when the Console is in "non-purist" mode. Clicking the Burroughs logo toggles the Console between the historically-accurate "purist" mode and the default "non-purist" mode, which shows additional legends and annunciators for system status.

Miscellaneous Changes


Many of the scripts and style sheets have been significantly cleaned up and refactored. The user interface now has a more standardized appearance, and this will be easier to maintain going forward.

Images and fonts have been moved into a new webUI/resources/ directory to separate them from the HTML, CSS and Javascript files in webUI/. A number of files in the webUI/tool/, tools/, tests/, and source/ directories have been moved to more logical locations within the project's Subversion repository.

All HTML <meta> Content-Type character sets have been changed from ISO-8859-1 to UTF-8 so that the Unicode glyphs could be supported. A problem with FireFox requiring the character set to be specified within the first 1024 characters of an HTML file has been corrected.

Looking Forward


We have a few ideas for further enhancements in the emulator, but none of them is particularly urgent. Of course, it is likely that we will uncover more bugs that will need to be corrected, but except for the problem with occasional Flag Bit errors, the emulator at present seems to be quite robust and reliable.

The focus on future work is likely to be acquisition and restoration of more software for the B5500. We already have quite a bit that exists in the form of scanned listings. Those need to be transcribed, proofed, and debugged in order to make them useful. That is a very labor-intensive and frustrating process, but Jim Fehlinger has made amazing progress in the past several months with an OCR-based technique that has improved the throughput and reliability of the transcription process substantially, although it is still quite labor-intensive.

Development of the emulator itself has been a closely-held project, but restoration of software is something in which anyone (and everyone) can easily participate. Nigel and I have been pleasantly surprised by the amount of interest this project has garnered, especially given that we have not done all that much to advertise it. We hope that people will continue to be interested in and volunteer to work towards the restoration of software for this very interesting system.

The 50th anniversary of first customer shipment of the B5500 will occur in February 2015. There needs to be a party.

Wednesday, July 9, 2014

Double Trouble: Version 0.20 Released

Nigel and I are pleased to announce that version 0.20 of the retro-B5500 emulator was released on 29 June. All changes have been posted to the Subversion repository for our Google Code project GitHub project. The hosting site has also been updated with this release, and for those of you running your own web server, a zip file of the source can be downloaded from the GitHub repository [updated 2022-05-07].

It has been five months since the previous version, 0.19, was released. That is far longer than any of us would have liked, but the main item in this release proved to be quite a challenge, as the following discussion will detail.


Double-Precision Arithmetic

The major enhancement in this release, and one that has been a long time coming, is a full implementation of the double-precision (DP) arithmetic operators, DLA, DLS, DLM, and DLD. These were the last operators left to be implemented in the Processor component of the emulator. Since the earliest releases they have been stubbed out by their single-precision (SP) equivalents, although a preliminary (and not very good) implementation of DP Add/Subtract has been available for more than a year.

There is actually one more operator that remains incompletely implemented, Initiate for Test (IFT, octal 5111). This is a diagnostic operator, and is available only in Control State. On the B5500, this operator had the ability to inject arbitrary state into the processor registers and initiate execution in the middle of an instruction. We do not emulate the B5500 at the clock level, however, and in particular we do not support the J register, which was used as a state variable to control stepping through execution of an instruction. Thus, we can't completely implement the IFT operator.

Coming into this project, I had suspected that the arithmetic operators were going to be difficult. In fact, I tried to hand them off to Nigel, but he was smart enough to hand them back. The SP operators were indeed a challenge, but that part of the instruction set proved to be very interesting to work on. If nothing else, I finally understood how long division works.

After getting the SP operators to work, I started to look at the DP operators, thinking they would be a straightforward extension of their SP equivalents. Oh, my... reading about the DP operators in the B2581 Processor Training Manual revealed that they were much, much more complex. In fact, they were downright intimidating. To understand why, we first need to look at how arithmetic is done in the B5500.

An Overview of Single Precision


The B5500 has a 48-bit word. That word can hold a single-precision numeric operand, or eight 6-bit characters, or a variety of control words. A SP numeric operand looks like this:

B5500 Single-precision Word Format
B5500 Single-precision Word Format
The high-order bit, numbered 0, is the flag bit, which is zero for operands and one for control words. Attempting to access a word as an operand in Word Mode that has its flag bit set will cause a (typically fatal) Flag Bit interrupt. In this sense the B5500 is a tagged-word architecture, but having the tag inside the word is quite awkward for processing character data -- when the high-order character has its high-order bit set and the processor is in Word Mode, it looks like a control word. Thus, character processing is normally done in Character Mode, which is not sensitive to the flag bit -- a characteristic that has its own set of problems. This awkwardness was resolved in the B6500 and later systems by expanding the tag and moving it to a separate field outside the 48-bit data portion of the word. In addition, character operations in the B6500 were combined with word operations into a single mode of processor operation.

Bit 1 is the sign of the mantissa, with a one indicating negative values. This is a signed-magnitude representation, so both positive and negative zero values are possible, although the arithmetic operators do not produce negative-zero results.

Bit 2 is the sign of the exponent, which also has a signed-magnitude representation.

The next six bits are the magnitude of the exponent, which is a power of eight. Therefore, when normalizing or scaling a floating-point value, the mantissa is shifted in three-bit groups, or octades.

The low-order 39 bits in the word are the mantissa. This size yields a precision of approximately 11.5 decimal digits.

With the exception of the flag bit, this looks like a fairly typical floating-point representation of the time, but there are two unusual things about it. The first is that the scaling point for the mantissa is not at the high-order end of the field, but rather at the low-order end. Unlike most floating-point representations that store the mantissa as a fraction, the B5500 represents its mantissa as an integer.

This leads to the second unusual characteristic. Not only is this the format of a floating-point operand, it is also the format for an integer operand. The B5500 has what is sometimes referred to as a unified numeric format. Integers are considered to be a subset of floating-point values, distinguished by having an exponent of zero. Most of the arithmetic operators attempt to keep the result of integer operands as an integer, but will automatically switch to a floating-point representation if the result overflows the integer range. Some floating-point results are not completely normalized, but that does not detract from their use in later calculations.

The idea for this unified format came either from the Bendix G-20 or the fertile mind of Bob Barton, depending on whose version of events you choose to believe. See the 1985 B5000 Oral History transcription for the story. The details of the formats for the two machines differ quite a bit, but the connection with the G-20 is plausible, as its predecessor, the G-15, was designed by Harry Huskey, who also consulted with Electrodata/Burroughs in the 1950s.

One consequence of this form of numeric representation is that you do not need separate instructions for integer and floating-point operations. To the hardware, there is no operational difference between 1 and 1.0, so a second consequence is that integer and floating operands can be mixed arbitrarily. A third consequence is that most integer values can be stored in multiple forms. For example, the value +1 has multiple representations, each with a different exponent value. The two most common are the one normalized as an integer [octal 0000000000000001], and the one fully-normalized as a floating-point value [octal 1141000000000000, i.e., (1×812) × (8-12)].

Doing arithmetic on mixed integer and floating-point values seems as if it might be quite complex, but its implementation on the B5500 is actually simpler than you may expect. The mechanization of the arithmetic operators is quite clever, and is discussed with headache-inducing detail in the Training Manual cited above. Here is a quick overview:
  • Addition and subtraction require that the exponents be equal. If both operands are in integer form, their exponents are zero, and therefore can simply be added or subtracted. If the exponents are unequal, the value with the larger exponent is normalized (shifted left with a decrease in exponent, if not already fully normalized) and the value with the smaller exponent is scaled (shifted right with an increase in exponent) until the exponents match or one of the mantissas goes to zero. If adding two integers yields a value that exceeds 39 bits, the result is automatically scaled, producing a floating-point result, with consequent loss of one octade of precision. A flip-flop keeps track of octades scaled off the low-order end of the word so the result can be rounded.
  • Multiplication notes whether both operands are initially in integer form, and if so, tries to produce an integer result, automatically overflowing to floating-point as necessary. Otherwise both operands are fully normalized before being multiplied.
  • Standard division, following the rules of Algol, always produces a real (floating-point) result, even with integer operands, and thus always normalizes its operands before commencing the division.
  • Integer division always normalizes its operands, but is mechanized in such a way as to produce either an integer result or an Integer Overflow interrupt.
  • Remainder division always normalizes its operands, and curiously, always produces a result in floating-point form. 5 mod 3 yields 2.0 in fully-normalized floating-point form. 3.3 mod 2 yields 1.3, or as close to it as you can represent with a binary fraction.
Variants of the store operators can normalize operands to integer representation when the semantics of the programming language require such. Fractional values are rounded during integerization. Attempting to integerize a single-precision value whose magnitude exceeds 39 bits results in an Integer Overflow interrupt.

Extending to Double Precision


So much for the single-precision representation and basic arithmetic behavior on the B5500. In terms of data representation, double-precision values are a straightforward extension of the single-precision format:

B5500 Double-precision Word Formats
B5500 Double-precision Word Formats
The first word of a DP value has the same representation as a SP value. The second word contains a 39-bit extension of the mantissa. The high-order nine bits of this second word are ignored by the processor. The scaling point remains at the low-order end of the first word -- the high-order mantissa is still an integer, but the low-order mantissa is effectively a fraction appended to that integer. The first word is generally stored at the lower address, but this is not required, as the processor must load and store the two words individually. Conveniently, a SP value can be converted to a DP value simply by appending a word of zeros to it.

This unified numeric representation worked well enough on the B5500 that it was carried forward into the B6500 and later systems. It is still used in the modern Unisys MCP systems. The data formats and numeric behavior in the modern systems are the same, with four exceptions:
  1. The flag bit is ignored, as its function was moved to the extra tag bits present in each word on the later systems.
  2. With the exception of the flag bit, the SP word format is the same, but in the second word used for DP operands, the high-order nine bits are used as a high-order extension to the exponent. Thus the first word has the low-order exponent and high-order mantissa, while the second word has the high-order exponent and low-order mantissa.
  3. Remainder divide with integer operands yields a result in integer form. This is a welcome refinement.
  4. Mechanization of the arithmetic functions is somewhat more sophisticated. The details of this have changed over the years, but current systems have extra guard digits, and will produce sub-normal numbers instead of Exponent Underflow interrupts the the very low end of the value range.

The Trouble with Double


So what is it that makes double precision so difficult in the B5500 emulator? The answer to that lies in the registers that are available inside the processor, or rather, the lack of them.

The B5500 processor has over 20 registers, but only four of them are larger than 15 bits. The two top-of-stack registers, A and B, hold 48 bits. These also serve roles similar to that of an accumulator on other machines. An extension register, X, holds 39 bits, large enough for a mantissa field. The fourth large register, P, is also 48 bits, but holds the current program word and is not involved in arithmetic operations.

Note that there is only one extension register, X. Therefore, it isn't possible for the processor internally to hold and operate on two full DP values at the same time. Double-precision arithmetic must be done in parts. What is worse, octades of the mantissa can be shifted only between the B and X registers, so when normalization or scaling of a DP operand is necessary, the operand must be present in B and X. The mantissa field of the A register can be transferred and exchanged with the X register, but shifting between those two registers is not possible.

These limitations lead to what I think of as The Dance of Insufficient Registers. The processor must go through a complex sequence of memory loads and stores during a double-precision operation, shuffling words between registers and the memory portion of the stack. In most cases, the memory portion of the stack actually grows temporarily as the operator pushes intermediate results, although the stack ultimately shrinks by two words as the operation consumes one of the DP operands, leaving the final DP result in the A and B registers.

Complicating the situation somewhat, the processor expects the high-order word of a DP operand to be on top of the stack, meaning the low-order word is in the stack at a lower address -- exactly the opposite order in which DP values are generally stored in memory. The rationale for this appears to be that it positions the words to make The Dance somewhat more efficient, but at the cost that setting up the operands in the stack is sometimes less efficient. The processor does not have double-precision load or store operations, so as mentioned previously, each half of a DP operand must be pushed or stored individually by software.

Thus, double precision on the B5500 is a mixed blessing. On one hand, it yields up to 78 bits of precision -- 23 decimal digits. On the other hand, you would need to really want that degree of precision, because double precision operations were not fast. A typical add operation may require 6 or more memory references, in addition to any required for the initial stack adjustment. Lots of clock cycles were required on top of that to normalize/scale the operands, and possibly the result. In the case of Multiply and Divide, lots more cycles were required to develop the 26-octade result.

Emulating Double Precision


In general, the emulator tries to do things the way the B5500 hardware did them, but unless you are trying to do a clock-level emulation (which probably isn't practical from a performance perspective in our web-based Javascript environment), the way that you mechanize an operator in software can be -- and sometimes must be -- quite a bit different from the way it is mechanized using digital logic. Circuits like to work in parallel, but software likes to work sequentially.

Our goal in this project has been to produce a "functional" emulation, meaning that at the end of each instruction, any state that may be needed by future instructions must have been developed and stored in the registers. Any "scratch state" that has no further use need not be preserved, and need not even be developed to begin with. In Word Mode, the state of the M, N, X, Y, and Z registers and most of the Q-register flip-flops fall into this scratch-state category. In some cases, we've developed and preserved this otherwise unneeded state for potential display purposes, but we haven't been very religious about it.

Thus, while the implementation of most operators in the emulator follows the general outline of their digital-logic implementation, the low-level details are often quite different, and are usually simpler. For example, multiplication is mechanized much the same way a person would do it by hand, multiplying the multiplicand by each digit (or rather, octade) of the multiplier in sequence, shifting the partial products, and adding them to produce the result. The B5500 hardware did the individual multiplications by repeated addition of the multiplicand, but the emulator does not need to operate at that primitive a level -- it just multiplies the multiplicand by the current octade of the multiplier. In general, the SP arithmetic operators work at a somewhat higher level of abstraction than did the B5500 hardware.

The big lesson from the work in the emulator on DP arithmetic operators, and the thing that has caused such a long delay in the most recent release, is that we've had to mechanize these operators much closer to the low-level way the B5500 hardware works than I had originally expected. It has also turned out that doing the actual arithmetic is a relatively small part of the job. A lot more effort has had to go into implementing The Dance, normalizing and scaling the operands and results, and the Mother of All Hair-Pullers, getting rounding to work properly.

Getting the rounding right is largely a function of how you keep track of octades shifted off the low end during scaling, which you would think is not that big a deal. Well, it isn't -- unless you have negative numbers -- in which case the rounding bit in some cases must be complemented. There are two operands and only one rounding bit (Q01F), and which operand gets scaled depends on the magnitude of their exponents, but only one operand at a time can be in the B and X registers to be scaled, and either one may or may not be negative -- you get the picture. Attempting to shortcut in software the way the digital logic worked turned out to be an exercise in futility.

I learned the hard way with the SP operators how important is is to get the rounding right. I had a B5500 Algol program that did orthonormalization of vectors in single precision, and results from a run of that program in 1970 that were formatted to 12 digits. I transcribed that program and ran it under the emulator, comparing its output to the 1970 listing. Alas, the results matched only to one significant digit, at most. This both astonished and annoyed me, and I spent weeks pouring over the code for the program, and over the code for the arithmetic operators in the emulator, trying to find what was causing the emulator to generate such poor results. It got me nowhere.

Finally, in desperation last Fall, I wrote an Algol program to try to thoroughly test the SP arithmetic operators in the emulator, especially in terms of overflow and rounding. That program used a table of 64 "interesting" numeric bit patterns. It worked by adding, subtracting, multiplying, and dividing all 64 patterns against each other, and dumping the results to a printer file in octal. Then I converted that program to modern Algol and ran it under the modern MCP. Comparing the output of the two showed that the results for SP Multiply and Divide were agreeing nicely. There were some normalization differences, and in some cases the B5500 generates Exponent Underflow interrupts (which the MCP converts to a zero result in the stack) while the modern system generates valid numbers (due to its larger exponent range), but otherwise the values were arithmetically equal.

For SP Add/Subtract, many of the results were equivalent, but the rest differed only in the low-order bit of the mantissa -- it was a rounding difference between the two systems. Fortunately, examining a few of those differing results showed where the emulator was not handling rounding properly, mostly during scaling. Fixing those few -- seemingly obscure -- rounding problems resolved all but a very few of the differences between the emulator and the modern MCP. Upon rerunning my orthonormalization program, the results from the emulator finally agreed with the 1970 listing, to the digit. That was both quite a relief, and a real lesson on the significance of rounding

Those with a background in numerical analysis are by now probably rolling their eyes or on the floor laughing. This certainly isn't the first floating-point implementation to suffer from bad rounding -- the original IBM 360 was notorious for its bad precision, due largely to the fact that it did not even try to round its results -- and it probably won't be the last. The IEEE 754 (ISO 60559) standard has done a lot to improve the precision of floating-point arithmetic, but that did not come along until more than 20 years after the B5500.

When I decided to start again on the DP operators earlier this year, rounding was thus very much on my mind, and I tried to apply the fixes from the SP operators to DP Add/Subtract. To test, I built a new program using those same 64 "interesting" bit patterns, but this time in pairs, to exercise the DP operators. I also converted that new program to modern Algol to generate results for comparison.

The initial results from this test were pretty disappointing. There were still rounding problems, the signs were often wrong, and it appeared that carries between the two halves of the mantissa weren't always working right. After tinkering with the original design quite a bit and getting nowhere, I decided that my high-level, software approach to mechanizing DP Add/Subtract wasn't going to work, and started to look much more closely at how the B5500 actually does arithmetic.

The Training Manual mentioned above is mostly a narrative guide to another document known as "the flows." These are state diagrams that show, on a clock-by-clock basis, how the logic levels in the processor cause changes in states of the registers and flip-flops. They are essentially a schematic representation of the logic equations for the system. We did not have access to the flows when starting the project, just the narrative description of them in the Training Manual, but they have since become available as the B5000 Processor Flow Chart document on bitsavers.org. The narrative in the Training Manual is pretty good, but it doesn't tell you everything. The flows are as close to The Truth about the B5500 as we are likely ever to get, and they have been invaluable in solving several problems with the emulator.

Thus, it was the flows that I turned to in order to fix the DP implementation. It has taken three complete rewrites of DP Add/Subtract, and some major rework on DP Divide. I couldn't reconcile my original approach to the flows, so each successive rewrite moved the implementation closer to being the state machine described in the flows. I now realize I could have saved myself a lot of trouble if I had just slavishly coded from the flows to begin with, but by more closely modeling the flows, the emulator now produces DP results that compare favorably with those from the modern MCP.

I confess that "compare favorably" is a bit of hand-waving on my part. The Add/Subtract tests match perfectly in many cases. In the remaining cases, they differ by the low-order bit. That looks like the same type of difference that got me into trouble with the SP arithmetic operators. In looking at several of cases, however, the emulator appears to be generating the result that the flows say it should -- assuming I'm reading the flows properly, of which I'm always in doubt.

The differences in the results for Multiply and Divide are mostly in the two low-order octades. DP Multiply is known to be imprecise at this level, however. Here is was the Training Manual has to say on the subject (page 3.23-1):
Twenty seven [octal] digits of the 52 digit product are retained. The product is normalized and truncated to a 26 digit result. The least significant two digits are not considered a precise part of the result because there may be a maximum error of 1 in the twenty-fifth digit position. [emphasis mine]

That nicely describes most of the differences I am seeing in the Multiply tests. DP Divide uses DP Multiply during its final stage of developing a quotient, so we should expect to see similar imprecision for division.

Another thing to keep in mind -- and something that I need to keep reminding myself -- is that matching results with a modern MCP implementation is not the goal. The goal is for the emulator to work the way a B5500 did. The only reasons for using the modern MCP as a basis for comparison are (a) it has a similar floating-point implementation, and (b) we don't presently have any double-precision results from a real B5500 to compare against. Thus, the modern MCP is the best standard we have to compare against, but it's highly likely that differs in some cases from what a B5500 would have generated.

Of course, it's also highly likely that emulator isn't quite right yet, either. I won't be the least bit surprised if we find flaws in the emulator's current DP implementation, but what we have seems to be good enough to release, and it's certainly in better shape that the original SP implementation was.


Those who may be interested in seeing the results of the tests with the 64 "interesting" bit pattens can view PDF comparisons at the following links. Be forewarned, though -- this is a lot more octal than any normal person should ever want to see.

Other Significant Changes in 0.20

1. The mechanism that schedules and manages the many asynchronous activities of the emulator -- running one or two processors, doing multiple I/Os, updating the console lights, and driving SPO and datacom output at ten characters/second -- has been heavily reworked in this release and implemented consistently across all of the emulator components. How this is done and the history of its development is worthy of a blog post on its own, so I won't go into details here. Suffice it to say that you should see somewhat better I/O behavior and snappier performance overall.

2. Character translation and keyboard filtering in the Datacom terminal device have been modified in an attempt to support CANDE and the TSS MCP better.

3. Button colors and the way they are illuminated has been standardized across the B5500 Console and I/O device windows.

4. Four tape drives (MTA-MTD) are now enabled in the default system configuration.

In Other News...

The B5500 emulator itself is nearing completion -- not that it will actually ever be completed, of course -- and effort is already beginning to shift from making the emulator work to having more things for it to work with. There is lots of interesting software already available, but most of it is in the form of scanned listings. Those listings must be transcribed into machine-readable source code. That is a tedious and error-prone task. We've already had about as much luck with 40-year old 7-track tapes as we are likely to have, so transcription is the best path to more applications for the B5500.

Fortunately, significant progress is being made towards making transcription easier and more reliable. Jim Fehlinger in New Jersey (USA) has managed to get an off-the-shelf OCR program to do a passable job of converting scanned listings from bitsavers.org. It is still a very labor-intensive process, involving lots of manual validation and correction of the OCR output, but it is producing usable source code much faster than any of us have been able to do before by simply keying the text.

One thing that we learned early on with the Mark XVI Algol and ESPOL compiler transcriptions is that a compiler is a better proofreader than most people are. I spent a full week carefully proofreading the original Algol compiler transcription, only to have my first attempt at compiling that code identify more typos than that week of very tedious effort had. A compiler isn't perfect for this -- it won't find typos in comments and literals, for example -- but it is a powerful proofing tool.

Jim has used this idea to good advantage. After OCR-ing and manually correcting several pages from a listing, he then compiles the source he has accumulated up to that point. He corrects any errors, and does additional compilation passes as necessary until there are no more errors left to be corrected. Then he goes back to OCR-ing, and the cycle continues. The process is not perfect, just a lot better than anything we've had up to now.

Thus far, Jim has managed to complete transcriptions of the following:
  • XBASIC, an interactive BASIC interpreter, developed by the Paisley College of Technology in the mid 1970s.
  • B6500/SIM, a simulator for the Burroughs B6500 that runs on the B5500. This was developed by the Burroughs B6500 engineering team in the mid/late-1960s. Its use awaits development of a variant of Algol, LONGALG, which did special array handling for the simulated B6500 memory. We do not have any materials for LONGALG, so are going to have to guess how it worked and try to patch the standard Algol compiler to replicate its behavior.
  • B6500 ESPOL, a cross-compiler for the B6500 that ran on the B5500. This was also developed by the Burroughs engineering team to create the initial B6500 MCP.
Jim is currently working on the source for the Mark I.0 B6500 MCP. He has been using the B6500 ESPOL cross-compiler to validate his scanning of the MCP. Since that ESPOL compiler is a product of his scanning process, it still had errors that a simple compile could not uncover, so he and I have had an interesting exchange over the past month. Jim uses the compiler as best he can until the compiler starts crashing or generating false syntax errors. He sends those to me, and I try to debug the compiler, sending him corrections so he can continue validating his OCR work. A remarkable number of the problems have been due to confusion between the plus-sign and the left-arrow. We have also had some really nasty bugs due to confusion between "I" and "1". We are slowly getting the compiler debugged, but the original compiler listing appears to have been of very poor quality, and there are sure to be more problems like this that we have not yet uncovered. I'm impressed that Jim has been able to convert the scan of that listing as well as he has.

Coming Attractions

The plan for the next release of the emulator is to make some improvements in the user interface, particularly in the area of system configuration control. This will probably take several weeks, so stay tuned.

Sunday, January 19, 2014

Emulator Version 0.19 Released

Nigel and I are pleased to announce that version 0.19 of the retro-B5500 emulator was released on 10 January. All changes have been posted to the Subversion repository for our Google Code project GitHub project. The hosting site has also been updated with this release, and for those of you running your own web server, a zip file of the source can be downloaded from the GitHub repository [updated 2022-05-07].

This release supports the ability to write to magnetic tape and to persist tape image data created by the emulator.

Background on Magnetic Tape Images

The emulator has had an initial magnetic tape implementation for the past few months. That initial implementation supported only reading tape images, and only from images in the ".bcd" format. This release expands on that initial one by supporting additional tape image formats and the ability to write to a tape image.

Tape images exist in the form of files in your local file system. The initial implementation allowed you to select an image file, which the emulator would load into memory and then parse into blocks in response to read commands from the I/O Unit. The ".bcd" format was originally supported because that was the one used for Sid McHarg's Mark XIII Burroughs release tapes.

Since the retro-B5500 emulator runs in a web browser, we must live with some limitations on the way that the browser is allowed to interact with your local file system. Modern browsers can read just about any file the user can select from a "file picker" form control, but at present there is not a useful way for a browser to write files under program control to the local file system. This restriction exists for very good security reasons -- without it, hackers would be able to play havoc with your local files -- but it makes getting data out of the browser environment difficult.

There are File System and FileWriter APIs that have been proposed as part of the HTML5 standards initiative, but they have two problems. First, only the Google Chrome and Opera browsers presently support them. Second, the files they create are "sand-boxed," i.e., the files exist within a virtual file system that is managed by the browser. Different browsers may format and manage this virtual file system differently. Worse, the files are generally hidden deep within the user profile directory used by the browser, are not named in obvious ways, and are difficult to find and use outside of the browser environment.

The only reasonably practical way we have found to output data from a browser is to format the data as text within a window and allow the user either to save the contents of that window to their local file system, or to copy/paste the contents into another program, such as a text editor, and save it from there. This process is neither automatic, nor very convenient for the user, but it is safe, and it works with all browsers.

Therefore, this new implementation for magnetic tape supports reading multiple tape image formats, but will output tape image data in only one format, ASCII text, as described in more detail below.

Loading Tape Images

Within the emulator, all tape image files are loaded in their entirety into a memory buffer. All tape reads and writes operate on that memory buffer. Depending on the block size used, a 2400-foot reel of 7-track tape could hold between about two and 22 million characters. It would probably be appalling to the original designers of the B5000 and B5500 that we would implement tape devices by sucking all of the data into "core" memory and operating on it exclusively there, but that turns out to be the easiest and most effective way to do it.

To support multiple tape image formats, the process of loading an image into a tape drive has changed slightly from the original implementation. The file picker control on the tape drive window has been replaced by a text box that will display the name of the image file after it is loaded. When you click the LOAD button on the tape drive window, a small dialog window now opens instead of activating the file picker as before. This window contains the file picker, a Format drop-down list to select the image format, a Write Ring check box to indicate whether the image is writable, and a Tape Length drop-down list to select the length of the tape reel:


To load an existing tape image, simply select it using the file picker. The emulator will attempt to infer the image format from the file name extension, as follows:
  • ".bcd" implies a ".bcd" tape image.
  • ".tap" is reserved for supporting the "tap" (or "taput") format in the future. See http://simh.trailing-edge.com/docs/simh_magtape.pdf for a specification of this format. It is not implemented at present.
  • All other extensions presently imply the "ASCII Odd Parity" format described below under Unloading Tape Images.
You can override the inferred tape format by making a selection from the Format drop-down list. Regardless of the format of a tape image you load into the emulator, it converts the image to the ".bcd" format and uses that format internally. The options presently available are:
  • (blank tape) -- This will load a blank tape image into the drive. Any file you previously selected with the file picker will be ignored.
  • .bcd image -- This will interpret the bytes in the selected file as a ".bcd" image and load it into the drive without conversion.
  • ASCII Even Parity -- This will interpret the bytes in the selected file as ASCII characters and convert them to an internal ".bcd" image with even-parity BCL codes.
  • ASCII Odd Parity -- This will interpret the bytes in the selected file as ASCII characters and convert them to an internal ".bcd" image with odd-parity B5500 Internal Code (BIC) codes.
Next to the Format list is a check box labeled Write Ring. If this box is checked, the internal tape image will be writable. The tape image on disk will not be affected by writing unless you later save the image over the original file when the tape is unloaded. If you merely want to read the tape, leave this box unchecked.

The last control is another drop-down list labeled Tape Length. It is relevant only when Write Ring is checked and is disabled otherwise. This specifies the length of tape on the virtual "reel" loaded into the drive. It defaults to 2400 feet, but lengths of 1200 and 600 feet are also selectable. The primary purpose of the length is to allow the drive to report it has passed the reflective EOT (end of tape) marker, which will signal the MCP that it is near the near to the end of the tape and that it should switch to a new reel. When Write Ring is not checked, the length of the tape is inferred from the size of the tape image data.

To load a blank tape into the drive, do not select a file using the file picker. Select a format of "(blank tape)," which is the default. The Write Ring box will be checked automatically and the tape length will default to 2400 feet. You may select a different tape length, if you wish. Any image file you previously selected with the file picker will be ignored.

If the Format list has a value other than "(blank tape)," you must select a file before clicking the OK button. When a file is selected using the file picker, the Format value is inferred from the file name extension, the Write Ring box is unchecked, and the Tape Length list is disabled. You may then alter the values of these controls before proceeding. The tape image is not loaded into memory until you click the OK button.

Unloading Tape Images

When a tape image is loaded with the Write Ring box unchecked, the image will be read-only, and writing to it will be inhibited. Later, when you click the UNLOAD button, that image data will simply be discarded by the drive, as it is still in the file from which it was loaded.

When the Write Ring box for an image is checked, the image will be writable, whether it was loaded as a blank tape or from an existing image file. Later, when you click the UNLOAD button, two things can happen:
  1. If the tape was not actually written to, the emulator will simply discard the image data, as for the case of a read-only image above.
  2. If the tape was written to, the emulator will ask whether you want to save the altered image data.
    • If you cancel out of this dialog, the image data will be discarded.
    • If you reply OK, however, the emulator will then open a new window and format the contents of the tape image as ASCII text. This may take several seconds for a full, 2400-foot reel of tape.
    • After the tape image text is formatted in the window, you may save it or copy/paste the data into another program. If you paste the text into another program, make sure that program will not trim trailing spaces from lines or compress multiple spaces using tab characters.
    • When you are finished with the image data, simply close the window.
 The ASCII tape image format is very simple:
  • The six-bit BCL or BIC character codes are translated to ASCII using the emulator's standard convention for the B5500 characters that do not have ASCII equivalents ("~" for left-arrow, "|" for the multiplication sign, "!" for not-equal, "{" for less-than-or-equal, and "}" for greater-than-or-equal).
  • Each tape block becomes one line of ASCII text. Lines are delimited by line-feed or carriage-return/line-feed characters, depending on the convention used by your browser.
  • An end-of-file (tape mark) is represented by a block containing a single "}" character.
  • All other blocks should be at least seven characters long, although the emulator does not enforce this.
Both even- and odd-parity tape image data converts to the same ASCII representation. The parity data is lost during this conversion.

An ASCII tape image may be loaded into a tape drive later as either "ASCII Even Parity" or "ASCII Odd Parity" format. These two formats will apply the appropriate parity to the data when it is converted to the ".bcd" format used by the drive internally.

Because the ASCII tape image format is just text, you can create tape images outside the emulator, either programmatically, or manually using an ordinary text editor.

See the Using the Magnetic Tape Drive wiki for more details on tape drive operation and the format of currently-supported tape image files.