mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-02-11 10:55:09 +00:00
Commit initial I/O Unit development.
This commit is contained in:
@@ -26,7 +26,7 @@ function B5500CentralControl() {
|
||||
this.IO4 = null; // I/O unit 4
|
||||
|
||||
this.P1 = null; // Reference for Processor 1 (control) [PA or PB]
|
||||
this.P1 = null; // Reference for Processor 2 (slave) [PA or PB]
|
||||
this.P2 = null; // Reference for Processor 2 (slave) [PA or PB]
|
||||
|
||||
this.AddressSpace = [ // Array of memory module address spaces (8 x 32KB each)
|
||||
null, null, null, null, null, null, null, null];
|
||||
@@ -35,6 +35,7 @@ function B5500CentralControl() {
|
||||
|
||||
// Instance variables and flags
|
||||
this.poweredUp = 0; // System power indicator
|
||||
this.unitStatusMask = 0; // Peripheral unit ready-status bitmask
|
||||
|
||||
this.PB1L = 0; // 0=> PA is P1, 1=> PB is P1
|
||||
this.cardLoadSelect = 0; // 0=> load from disk/drum; 1=> load from cards
|
||||
@@ -385,15 +386,19 @@ B5500CentralControl.prototype.clearInterrupt = function() {
|
||||
break;
|
||||
case 0x17: // @27: I/O 1 finished
|
||||
this.CCI08F = 0;
|
||||
this.AD1F = 0; // make unit non-busy
|
||||
break;
|
||||
case 0x18: // @30: I/O 2 finished
|
||||
this.CCI09F = 0;
|
||||
this.AD2F = 0; // make unit non-busy
|
||||
break;
|
||||
case 0x19: // @31: I/O 3 finished
|
||||
this.CCI10F = 0;
|
||||
this.AD3F = 0; // make unit non-busy
|
||||
break;
|
||||
case 0x1A: // @32: I/O 4 finished
|
||||
this.CCI11F = 0;
|
||||
this.AD4F = 0; // make unit non-busy
|
||||
break;
|
||||
case 0x1B: // @33: P2 busy
|
||||
this.CCI12F = 0;
|
||||
@@ -510,16 +515,16 @@ B5500CentralControl.prototype.initiateP2 = function() {
|
||||
B5500CentralControl.prototype.initiateIO = function() {
|
||||
/* Selects an I/O unit and initiates an I/O */
|
||||
|
||||
if (this.IO1) {
|
||||
if (this.IO1 && this.IO1.REMF && !this.AD1F) {
|
||||
this.AD1F = 1;
|
||||
this.IO1.initiate();
|
||||
} else if (this.IO2) {
|
||||
} else if (this.IO2 && this.IO2.REMF && !this.AD2F) {
|
||||
this.AD2F = 1;
|
||||
this.IO2.initiate();
|
||||
} else if (this.IO3) {
|
||||
} else if (this.IO3 && this.IO3.REMF && !this.AD3F) {
|
||||
this.AD3F = 1;
|
||||
this.IO3.initiate();
|
||||
} else if (this.IO4) {
|
||||
} else if (this.IO4 && this.IO4.REMF && !this.AD4F) {
|
||||
this.AD4F = 1;
|
||||
this.IO4.initiate();
|
||||
} else {
|
||||
@@ -528,6 +533,68 @@ B5500CentralControl.prototype.initiateIO = function() {
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.interrogateIOChannel = function() {
|
||||
/* Returns a value as for the processor TIO syllable indicating the first
|
||||
available and non-busy I/O Unit */
|
||||
|
||||
if (this.IO1 && this.IO1.REMF && !this.AD1F) {
|
||||
return 1;
|
||||
} else if (this.IO2 && this.IO2.REMF && !this.AD2F) {
|
||||
return 2;
|
||||
} else if (this.IO3 && this.IO3.REMF && !this.AD3F) {
|
||||
return 3;
|
||||
} else if (this.IO4 && this.IO4.REMF && !this.AD4F) {
|
||||
return 4;
|
||||
} else {
|
||||
return 0; // All I/O Units busy
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.interrogateUnitStatus = function() {
|
||||
/* Returns a bitmask as for the processor TUS syllable indicating the
|
||||
ready status of all peripheral units */
|
||||
|
||||
return this.unitStatusMask;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.testUnitBusy = function(ioUnit, unit) {
|
||||
/* Determines whether the unit designate "unit" is currently in use by any other
|
||||
I/O Unit than the one designated by "ioUnit". Returns 0 if not busy */
|
||||
|
||||
if (ioUnit != "1" && this.IO1 && this.IO1.REMF && this.AD1F && this.IO1.Dunit == unit) {
|
||||
return 1;
|
||||
} else if (ioUnit != "2" && this.IO2 && this.IO2.REMF && this.AD2F && this.IO2.Dunit == unit) {
|
||||
return 2;
|
||||
} else if (ioUnit != "3" && this.IO3 && this.IO3.REMF && this.AD3F && this.IO3.Dunit == unit) {
|
||||
return 3;
|
||||
} else if (ioUnit != "4" && this.IO4 && this.IO4.REMF && this.AD4F && this.IO4.Dunit == unit) {
|
||||
return 4;
|
||||
} else {
|
||||
return 0; // peripheral unit not in use by any other I/O Unit
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.testUnitReady = function(unit) {
|
||||
/* Determines whether the unit designate "unit" is currently in ready status.
|
||||
Returns 0 if not ready */
|
||||
|
||||
if (ioUnit != "1" && this.IO1 && this.IO1.REMF && this.AD1F && this.IO1.Dunit == unit) {
|
||||
return 1;
|
||||
} else if (ioUnit != "2" && this.IO2 && this.IO2.REMF && this.AD2F && this.IO2.Dunit == unit) {
|
||||
return 2;
|
||||
} else if (ioUnit != "3" && this.IO3 && this.IO3.REMF && this.AD3F && this.IO3.Dunit == unit) {
|
||||
return 3;
|
||||
} else if (ioUnit != "4" && this.IO4 && this.IO4.REMF && this.AD4F && this.IO4.Dunit == unit) {
|
||||
return 4;
|
||||
} else {
|
||||
return 0; // peripheral unit not in use by any other I/O Unit
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CentralControl.prototype.halt = function() {
|
||||
/* Halts the processors. Any in-process I/Os are allowed to complete */
|
||||
@@ -560,11 +627,30 @@ B5500CentralControl.prototype.halt = function() {
|
||||
B5500CentralControl.prototype.loadComplete = function loadComplete() {
|
||||
/* Monitors an initial load I/O operation for complete status.
|
||||
When complete, initiates P1 */
|
||||
var completed = false; // true if some I/O Unit finished
|
||||
var that = loadComplete.that; // capture the current closure context
|
||||
|
||||
if (!that.CCI08F) {
|
||||
if (that.CCI08F) { // I/O Unit 1 finished
|
||||
completed = true;
|
||||
that.CCI08F = 0;
|
||||
that.AD1F = 0;
|
||||
} else if (that.CCI09F) { // I/O Unit 2 finished
|
||||
completed = true;
|
||||
that.CCI09F = 0;
|
||||
that.AD2F = 0;
|
||||
} else if (that.CCI10F) { // I/O Unit 3 finished
|
||||
completed = true;
|
||||
that.CCI10F = 0;
|
||||
that.AD3F = 0;
|
||||
} else if (that.CCI11F) { // I/O Unit 4 finished
|
||||
completed = true;
|
||||
that.CCI11F = 0;
|
||||
that.AD4F = 0;
|
||||
} else { // Nothing finished yet (or there was an error)
|
||||
that.loadTimer = setTimeout(that.loadComplete, 100);
|
||||
} else {
|
||||
}
|
||||
|
||||
if (completed) {
|
||||
that.loadTimer = null;
|
||||
that.LOFF = 0;
|
||||
that.P1.C = 0x10; // execute from address @20
|
||||
@@ -583,14 +669,27 @@ B5500CentralControl.prototype.loadComplete = function loadComplete() {
|
||||
B5500CentralControl.prototype.load = function() {
|
||||
/* Initiates a Load operation to start the system */
|
||||
|
||||
if ((this.PA && this.PA.busy) || (this.PB && this.PB.busy)) {
|
||||
if (this.P1 && !this.P1.busy) {
|
||||
this.clear();
|
||||
if (this.P1) {
|
||||
this.LOFF = 1;
|
||||
if (this.IO1) { // !! not sure about I/O selection here
|
||||
this.IO1.initiateLoad(this.cardLoadSelect);
|
||||
this.loadComplete();
|
||||
}
|
||||
this.LOFF = 1;
|
||||
if (this.IO1 && this.IO1.REMF && !this.AD1F) {
|
||||
this.AD1F = 1;
|
||||
this.IO1.initiateLoad(this.cardLoadSelect);
|
||||
this.loadComplete();
|
||||
} else if (this.IO2 && this.IO2.REMF && !this.AD2F) {
|
||||
this.AD2F = 1;
|
||||
this.IO2.initiateLoad(this.cardLoadSelect);
|
||||
this.loadComplete();
|
||||
} else if (this.IO3 && this.IO3.REMF && !this.AD3F) {
|
||||
this.AD3F = 1;
|
||||
this.IO3.initiateLoad(this.cardLoadSelect);
|
||||
this.loadComplete();
|
||||
} else if (this.IO4 && this.IO4.REMF && !this.AD4F) {
|
||||
this.AD4F = 1;
|
||||
this.IO4.initiateLoad(this.cardLoadSelect);
|
||||
this.loadComplete();
|
||||
} else {
|
||||
this.CCI04F = 1; // set I/O busy interrupt
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -679,12 +778,10 @@ B5500CentralControl.prototype.configureSystem = function() {
|
||||
|
||||
this.PB1L = (cfg.PB1L ? 1 : 0);
|
||||
|
||||
/*** enable once I/O exists ***
|
||||
if (cfg.IO1) {this.IO1 = new B5500IOUnit("1", this)};
|
||||
if (cfg.IO2) {this.IO2 = new B5500IOUnit("2", this)};
|
||||
if (cfg.IO3) {this.IO3 = new B5500IOUnit("3", this)};
|
||||
if (cfg.IO4) {this.IO4 = new B5500IOUnit("4", this)};
|
||||
***/
|
||||
|
||||
for (x=0; x<8; x++) {
|
||||
if (cfg.MemMod[x]) {
|
||||
|
||||
293
emulator/B5500IOUnit.js
Normal file
293
emulator/B5500IOUnit.js
Normal file
@@ -0,0 +1,293 @@
|
||||
/***********************************************************************
|
||||
* retro-b5500/emulator B5500IOUnit.js
|
||||
************************************************************************
|
||||
* Copyright (c) 2012, Nigel Williams and Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* B5500 Input/Output Unit module.
|
||||
*
|
||||
* Instance variables in all caps generally refer to register or flip-flop (FF)
|
||||
* entities in the processor hardware. See the Burroughs B5500 Reference Manual
|
||||
* (1021326, May 1967) and B5283 Input/Output Training Manual (1036993, January 1969)
|
||||
* for details:
|
||||
* http://bitsavers.org/pdf/burroughs/B5000_5500_5700/1021326_B5500_RefMan_May67.pdf
|
||||
* http://bitsavers.org/pdf/burroughs/B5000_5500_5700/1036993_B5283_TrainingMan_Jan69.pdf
|
||||
*
|
||||
* B5500 word format: 48 bits plus (hidden) parity.
|
||||
* Bit 0 is high-order, bit 47 is low-order, big-endian character ordering.
|
||||
* I/O and Result Descriptors have the following general format:
|
||||
* [0:1] Flag bit (1=descriptor)
|
||||
* [1:1] (0=descriptor)
|
||||
* [2:1] Presence bit (1=present and available in memory, 0=absent or unavailable)
|
||||
* [3:5] Unit designate
|
||||
* [8:10] Word count (optional, see [23:1])
|
||||
* [18:1] Memory inhibit bit (1=no data transfer)
|
||||
* [19:2] (not used by I/O Unit)
|
||||
* [21:1] Mode bit (0=alpha, 1=binary)
|
||||
* [22:1] Direction bit (0=forward, 1=reverse for mag tape, 120/132 col for printers)
|
||||
* [23:1] Word count bit (0=ignore, 1=use word count in [8:10])
|
||||
* [24:1] I/O bit (0=write, 1=read)
|
||||
* [25:1] (not used by I/O Unit)
|
||||
* [26:7] Control and error-reporting bits (depend on unit)
|
||||
* [33:15] Memory address
|
||||
*
|
||||
************************************************************************
|
||||
* 2012-12-08 P.Kimpel
|
||||
* Original version, from thin air.
|
||||
***********************************************************************/
|
||||
"use strict";
|
||||
|
||||
/**************************************/
|
||||
function B5500IOUnit(ioUnitID, cc) {
|
||||
/* Constructor for the I/O Unit object */
|
||||
|
||||
this.ioUnitID = ioUnitID; // I/O Unit ID ("1", "2", "3", or "4")
|
||||
this.cc = cc; // Reference back to Central Control module
|
||||
this.rdAddress = {"1": 0x0C, "2": 0x0D, "3": 0x0E, "4": 0x0F}[ioUnitID];
|
||||
|
||||
this.scheduler = null; // Reference to current setTimeout id
|
||||
this.accessor = { // Memory access control block
|
||||
requestorID: procID, // Memory requestor ID
|
||||
addr: 0, // Memory address
|
||||
word: 0, // 48-bit data word
|
||||
MAIL: 0, // Truthy if attempt to access @000-@777 in normal state
|
||||
MPED: 0, // Truthy if memory parity error
|
||||
MAED: 0 // Truthy if memory address/inhibit error
|
||||
};
|
||||
|
||||
this.schedule.that = this; // Establish context for when called from setTimeout()
|
||||
|
||||
// Establish a buffer for the peripheral modules to use during their I/O.
|
||||
// The size is sufficient for 63 disk sectors, rounded up to the next 8KB.
|
||||
this.bufferArea = new ArrayBuffer(16384);
|
||||
this.buffer = new UInt8Array(bufferArea);
|
||||
|
||||
this.clear(); // Create and initialize the processor state
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
|
||||
B5500IOUnit.timeSlice = 5000; // Standard run() timeslice, about 5ms (we hope)
|
||||
B5500IOUnit.memCycles = 6; // assume 6 us memory cycle time (the other option was 4 usec)
|
||||
|
||||
B5500IOUnit.BICtoANSI = [ // Index by 6-bit BIC to get 8-bit ANSI code
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", // 00-07, @00-07
|
||||
"8", "9", "#", "@", "?", ":", ">", "}", // 08-1F, @10-17
|
||||
"+", "A", "B", "C", "D", "E", "F", "G", // 10-17, @20-27
|
||||
"H", "I", ".", "[", "&", "(", "<", "~", // 18-1F, @30-37
|
||||
"|", "J", "K", "L", "M", "N", "O", "P", // 20-27, @40-47
|
||||
"Q", "R", "$", "*", "-", ")", ";", "{", // 28-2F, @50-57
|
||||
" ", "/", "S", "T", "U", "V", "W", "X", // 30-37, @60-67
|
||||
"Y", "Z", ",", "%", "!", "=", "]", "\""]; // 38-3F, @70-77
|
||||
|
||||
B5500IOUnit.ANSItoBIC = [ // Index by 8-bit ANSI to get 6-bit BIC (upcased, invalid=>"?")
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 00-0F
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 10-1F
|
||||
0x30,0x3C,0x3F,0x0A,0x2A,0x3B,0x1C,0x0C,0x1D,0x2D,0x2B,0x10,0x3A,0x2C,0x1A,0x31, // 20-2F
|
||||
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0D,0x2E,0x1E,0x3D,0x0E,0x0C, // 30-3F
|
||||
0x0B,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x21,0x22,0x23,0x24,0x25,0x26, // 40-4F
|
||||
0x27,0x28,0x29,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x1B,0x0C,0x3E,0x0C,0x0C, // 50-5F
|
||||
0x0C,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x21,0x22,0x23,0x24,0x25,0x26, // 60-6F
|
||||
0x27,0x28,0x29,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2F,0x20,0x0F,0x1F,0x0C, // 70-7F
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 80-8F
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 90-9F
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // A0-AF
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // B0-BF
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // C0-CF
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // D0-DF
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // E0-EF
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C]; // F0-FF
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.clear = function() {
|
||||
/* Initializes (and if necessary, creates) the processor state */
|
||||
|
||||
this.W = 0; // Memory buffer register
|
||||
this.D = 0; // I/O descriptor (control) register
|
||||
this.clearD(); // clear the D-register exploded fields
|
||||
|
||||
this.CC = 0; // Character counter (3 bits)
|
||||
this.IB = 0; // Input buffer register (6 bits+parity)
|
||||
this.IR = 0; // Tape read register (6 bits+parity)
|
||||
this.OB = 0; // Output buffer register (6 bits+parity)
|
||||
this.WB = 0; // Tape write register (6 bits+parity)
|
||||
this.LP = 0; // Longitudinal parity register (6 bits+parity)
|
||||
this.SC = 0; // Sequence counter (4 bits)
|
||||
this.PC = 0; // Pulse counter register (6 bits, 1MHz rate)
|
||||
|
||||
this.AOFF = 0; // Address overflow FF
|
||||
this.EXNF = 0; // W-contents FF (0=has address, 1=has descriptor)
|
||||
this.HOLF = 0; // Hold-over FF (for alpha vs. binary card read)
|
||||
this.LCHF = 0; // Last-character FF (triggers RD construction)
|
||||
this.LPWF = 0; // (unknown)
|
||||
this.MANF = 0; // Memory access needed FF
|
||||
this.MAOF = 0; // Memory access obtained FF
|
||||
this.OBCF = 0; // (unknown)
|
||||
this.STRF = 0; // Strobe FF
|
||||
|
||||
this.BKWF = 0; // Tape control FF
|
||||
this.FWDF = 0; // Tape control FF
|
||||
this.IM1F = 0; // Tape control FF
|
||||
this.IMFF = 0; // Tape control FF
|
||||
this.PUCF = 0; // Tape control FF
|
||||
this.RCNF = 0; // Tape control FF
|
||||
this.SHOF = 0; // Tape control FF
|
||||
this.SKFF = 0; // Tape control FF
|
||||
this.VRCF = 0; // Tape control FF
|
||||
|
||||
this.IMCF = 0; // (unknown)
|
||||
this.RECF = 0; // (unknown)
|
||||
this.REMF = 1; // Remote FF (0=local, 1=remote and available)
|
||||
|
||||
this.busy = 0; // I/O Unit is busy
|
||||
|
||||
this.cycleCount = 0; // Current cycle count for this.run()
|
||||
this.cycleLimit = 0; // Cycle limit for this.run()
|
||||
this.totalCycles = 0; // Total cycles executed on this I/O Unit
|
||||
this.ioUnitTime = 0; // Total I/O Unit running time, based on cycles executed
|
||||
this.ioUnitSlack = 0; // Total I/O Unit throttling delay, milliseconds
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.clearD = function() {
|
||||
/* Clears the D-register and the exploded field variables used internally */
|
||||
|
||||
this.D = 0;
|
||||
this.Dunit = 0; // Unit designate field (5 bits)
|
||||
this.DwordCount = 0; // Word count field (10 bits)
|
||||
this.D18F = 0; // Memory inhibit bit (0=transfer, 1=no transfer)
|
||||
this.D21F = 0; // Mode bit (0=alpha, 1=binary)
|
||||
this.D22F = 0; // Direction bit (0=forward), etc.
|
||||
this.D23F = 0; // Word counter bit (0=ignore, 1=use)
|
||||
this.D24F = 0; // I/O bit (0=write, 1=read)
|
||||
this.D26F = 0; // Memory address error bit
|
||||
this.D27F = 0; // Device error bit 1
|
||||
this.D28F = 0; // Device error bit 2
|
||||
this.D29F = 0; // Device error bit 3
|
||||
this.D30F = 0; // Unit not-ready bit
|
||||
this.D31F = 0; // Memory parity error on descriptor fetch bit
|
||||
this.D32F = 0; // Unit busy bit
|
||||
this.Daddress = 0; // Memory transfer address (15 bits)
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.fetch = function(addr) {
|
||||
/* Fetch a word from memory at address "addr" and leave it in the W register.
|
||||
Returns 1 if a memory access error occurred, 0 if no error */
|
||||
var acc = this.accessor; // get a local reference to the accessor object
|
||||
|
||||
acc.addr = addr;
|
||||
this.cc.fetch(acc);
|
||||
this.W = acc.word;
|
||||
|
||||
acc.addr = this.S;
|
||||
acc.MAIL = (this.S < 0x0200 && this.NCSF);
|
||||
acc.word = this.A;
|
||||
this.cc.store(acc);
|
||||
|
||||
this.cycleCount += B5500IOUnit.memCycles;
|
||||
if (acc.MAED) {
|
||||
this.D26F = 1; // memory address error
|
||||
return 1;
|
||||
} else if (acc.MPED) {
|
||||
this.D29F = 1; // memory parity error on data transfer
|
||||
return 1;
|
||||
} else {
|
||||
return 0; // no error
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.store = function(addr) {
|
||||
/* Store a word in memory at address "addr" from the W register.
|
||||
Returns 1 if a memory access error occurred, 0 if no error */
|
||||
var acc = this.accessor; // get a local reference to the accessor object
|
||||
|
||||
acc.addr = addr;
|
||||
acc.word = this.W;
|
||||
this.cc.store(acc);
|
||||
|
||||
this.cycleCount += B5500IOUnit.memCycles;
|
||||
if (acc.MAED) {
|
||||
this.D26F = 1; // memory address error
|
||||
return 1;
|
||||
} else {
|
||||
return 0; // no error
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.initiate = function() {
|
||||
/* Initiates an I/O operation on this I/O Unit */
|
||||
var addr; // memory address
|
||||
var x;
|
||||
|
||||
this.clearD();
|
||||
this.EXNF = 0;
|
||||
this.D31F = 1; // preset IOD fetch error condition (cleared if successful)
|
||||
if (this.fetch(0x08)) { // fetch the IOD address from @10
|
||||
... return descriptor ...
|
||||
} else {
|
||||
this.EXNF = 1;
|
||||
this.Daddress = addr = this.W % 0x7FFF;
|
||||
if (this.fetch(addr)) { // fetch the IOD from that address
|
||||
... return descriptor ...
|
||||
} else {
|
||||
this.D31F = 0; // reset the IOD-fetch error condition
|
||||
this.D = x = this.W; // explode the D-register into its fields
|
||||
this.Dunit = this.cc.fieldIsolate(x, 3, 5);
|
||||
this.DwordCount = this.cc.fieldIsolate(x, 8, 10);
|
||||
x = x % 0x40000000;
|
||||
this.D18F = (x >>> 29) & 1;
|
||||
this.D21F = (x >>> 26) & 1;
|
||||
this.D22F = (x >>> 25) & 1;
|
||||
this.D23F = (x >>> 24) & 1;
|
||||
this.D24F = (x >>> 23) & 1;
|
||||
this.Daddress = x % 0x7FFF;
|
||||
if (this.cc.testUnitBusy(this.ioUnitID, this.Dunit)) {
|
||||
this.D32F = 1; // set unit busy error
|
||||
... return descriptor ...
|
||||
} else if (!this.cc.testUnitReady(this.Dunit)) {
|
||||
this.D30F = 1; // set unit not-ready error
|
||||
... return descriptor ...
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.run = function() {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500IOUnit.prototype.schedule = function schedule() {
|
||||
/* Schedules the I/O Unit run time and attempts to throttle performance
|
||||
to approximate that of a real B5500. Well, at least we hope this will run
|
||||
fast enough that the performance will need to be throttled. It establishes
|
||||
a timeslice in terms of a number of I/O Unit "cycles" of 1 microsecond
|
||||
each and calls run() to execute at most that number of cycles. run()
|
||||
counts up cycles until it reaches this limit or some terminating event
|
||||
(such as a halt), then exits back here. If the I/O Unit remains active,
|
||||
this routine will reschedule itself for an appropriate later time, thereby
|
||||
throttling the performance and allowing other modules a chance at the
|
||||
Javascript execution thread. */
|
||||
var delayTime;
|
||||
var that = schedule.that;
|
||||
|
||||
that.scheduler = null;
|
||||
that.cycleLimit = B5500IOUnit.timeSlice;
|
||||
that.cycleCount = 0;
|
||||
|
||||
that.run();
|
||||
|
||||
that.totalCycles += that.cycleCount
|
||||
that.ioUnitTime += that.cycleCount;
|
||||
if (that.busy) {
|
||||
delayTime = that.ioUnitTime/1000 - new Date().getTime();
|
||||
that.ioUnitSlack += delayTime;
|
||||
that.scheduler = setTimeout(that.schedule, (delayTime < 0 ? 1 : delayTime));
|
||||
}
|
||||
};
|
||||
@@ -4,6 +4,8 @@
|
||||
* Copyright (c) 2012, Nigel Williams and Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* B5500 Processor (CPU) module.
|
||||
*
|
||||
* Instance variables in all caps generally refer to register or flip-flop (FF)
|
||||
* entities in the processor hardware. See the Burroughs B5500 Reference Manual
|
||||
@@ -14,15 +16,13 @@
|
||||
*
|
||||
* B5500 word format: 48 bits plus (hidden) parity.
|
||||
* Bit 0 is high-order, bit 47 is low-order, big-endian character ordering.
|
||||
* [0:1] Flag bit (1=descriptor)
|
||||
* [0:1] Flag bit (1=control word or descriptor)
|
||||
* [1:1] Mantissa sign bit (1=negative)
|
||||
* [2:1] Exponent sign bit (1=negative)
|
||||
* [3:6] Exponent (power of 8, signed-magnitude)
|
||||
* [9:39] Mantissa (signed-magnitude, scaling point after bit 47)
|
||||
*
|
||||
************************************************************************
|
||||
* B5500 Processor (CPU) module.
|
||||
************************************************************************
|
||||
* 2012-06-03 P.Kimpel
|
||||
* Original version, from thin air.
|
||||
***********************************************************************/
|
||||
@@ -3559,6 +3559,9 @@ B5500Processor.prototype.run = function() {
|
||||
break;
|
||||
|
||||
case 0x14: // 2431: TUS=interrogate peripheral status
|
||||
this.adjustAEmpty();
|
||||
this.A = this.cc.interrogateUnitStatus();
|
||||
this.AROF = 1;
|
||||
break;
|
||||
|
||||
case 0x21: // 4131: BBW=branch backward unconditional
|
||||
@@ -3581,6 +3584,9 @@ B5500Processor.prototype.run = function() {
|
||||
break;
|
||||
|
||||
case 0x34: // 6431: TIO=interrogate I/O channel
|
||||
this.adjustAEmpty();
|
||||
this.A = this.cc.interrogateIOChannel();
|
||||
this.AROF = 1;
|
||||
break;
|
||||
|
||||
case 0x38: // 7031: FBS=stack search for flag
|
||||
|
||||
73
tools/BIC-ANSI-xlateTest.html
Normal file
73
tools/BIC-ANSI-xlateTest.html
Normal file
@@ -0,0 +1,73 @@
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
var c;
|
||||
var d;
|
||||
var x;
|
||||
var y;
|
||||
|
||||
var BICtoANSI = [ // Index by 6-bit BIC to get 8-bit ANSI code
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", // 00-07, @00-07
|
||||
"8", "9", "#", "@", "?", ":", ">", "}", // 08-1F, @10-17
|
||||
"+", "A", "B", "C", "D", "E", "F", "G", // 10-17, @20-27
|
||||
"H", "I", ".", "[", "&", "(", "<", "~", // 18-1F, @30-37
|
||||
"|", "J", "K", "L", "M", "N", "O", "P", // 20-27, @40-47
|
||||
"Q", "R", "$", "*", "-", ")", ";", "{", // 28-2F, @50-57
|
||||
" ", "/", "S", "T", "U", "V", "W", "X", // 30-37, @60-67
|
||||
"Y", "Z", ",", "%", "!", "=", "]", "\""]; // 38-3F, @70-77
|
||||
|
||||
var ANSItoBIC = [ // Index by 8-bit ANSI to get 6-bit BIC (upcased, invalid=>"?")
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 00-0F
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 10-1F
|
||||
0x30,0x3C,0x3F,0x0A,0x2A,0x3B,0x1C,0x0C,0x1D,0x2D,0x2B,0x10,0x3A,0x2C,0x1A,0x31, // 20-2F
|
||||
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0D,0x2E,0x1E,0x3D,0x0E,0x0C, // 30-3F
|
||||
0x0B,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x21,0x22,0x23,0x24,0x25,0x26, // 40-4F
|
||||
0x27,0x28,0x29,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x1B,0x0C,0x3E,0x0C,0x0C, // 50-5F
|
||||
0x0C,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x21,0x22,0x23,0x24,0x25,0x26, // 60-6F
|
||||
0x27,0x28,0x29,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2F,0x20,0x0F,0x1F,0x0C, // 70-7F
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 80-8F
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 90-9F
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // A0-AF
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // B0-BF
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // C0-CF
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // D0-DF
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // E0-EF
|
||||
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C]; // F0-FF
|
||||
|
||||
function html(c) {
|
||||
switch(c) {
|
||||
case "<": return("<");
|
||||
case ">": return(">");
|
||||
case '"': return(""");
|
||||
case "&": return("&");
|
||||
default: return c;
|
||||
}
|
||||
}
|
||||
|
||||
document.write("<h3>Test BIC to ANSI</h3>");
|
||||
|
||||
for (x=0; x<64; x++) {
|
||||
c = BICtoANSI[x];
|
||||
y = ANSItoBIC[c.charCodeAt(0)];
|
||||
document.write("[" + x + "=" + y + "] = " + html(c) + "<br>");
|
||||
if (x != y) {
|
||||
alert("BICtoANSI mismatch: " + x + "!=" + y + ", " + html(c));
|
||||
}
|
||||
}
|
||||
|
||||
document.write("<h3>Test ANSI to BIC</h3>");
|
||||
|
||||
for (x=0; x<256; x++) {
|
||||
y = ANSItoBIC[x];
|
||||
d = String.fromCharCode(x);
|
||||
c = BICtoANSI[y];
|
||||
y = c.charCodeAt(0);
|
||||
document.write("[" + x + "=" + y + "] : " + html(c) + "=" + html(d) + "<br>");
|
||||
if (y != 63 && c != d.toUpperCase()) {
|
||||
alert("ANSItoBIC mismatch: " + x + "!=" + y + ", " + html(c));
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -10,6 +10,7 @@
|
||||
<script src="../emulator/B5500SystemConfiguration.js"></script>
|
||||
<script src="../emulator/B5500CentralControl.js"></script>
|
||||
<script src="../emulator/B5500Processor.js"></script>
|
||||
<script src="../emulator/B5500IOUnit.js"></script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<script src="../emulator/B5500SystemConfiguration.js"></script>
|
||||
<script src="../emulator/B5500CentralControl.js"></script>
|
||||
<script src="../emulator/B5500Processor.js"></script>
|
||||
<script src="../emulator/B5500IOUnit.js"></script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<script src="../emulator/B5500SystemConfiguration.js"></script>
|
||||
<script src="../emulator/B5500CentralControl.js"></script>
|
||||
<script src="../emulator/B5500Processor.js"></script>
|
||||
<script src="../emulator/B5500IOUnit.js"></script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<script src="../emulator/B5500SystemConfiguration.js"></script>
|
||||
<script src="../emulator/B5500CentralControl.js"></script>
|
||||
<script src="../emulator/B5500Processor.js"></script>
|
||||
<script src="../emulator/B5500IOUnit.js"></script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
Reference in New Issue
Block a user