1
0
mirror of https://github.com/pkimpel/retro-220.git synced 2026-01-13 15:18:24 +00:00

1. Commit initial register/FF definitions for B220Processor.

2. Commit minor enhancements to B220ControlConsole and organ switch image.
This commit is contained in:
Paul Kimpel 2017-01-29 09:10:21 -08:00
parent 44f685bb51
commit b7a68153ed
12 changed files with 507 additions and 383 deletions

View File

@ -10,26 +10,24 @@
* Instance variables in all caps generally refer to register or flip-flop (FF)
* entities in the processor hardware. See the following documents:
*
* Burroughs 205 Handbook
* (Bulletin 3021, Burroughs Corporation, 1956).
* Programming and Coding Manual, Datatron
* (Bulletin 3040A, ElectroData Corporation, 1954).
* Handbook of Operating Procedures for the Burroughs 205
* (Bulletin 3034A, Burroughs Corporation, May 1960).
* Burroughs 220 Operational Characterists Manual
* (Bulletin 5020A, Burroughs Corporation, revised August 1960).
* Handbook of Operating Procedures for the Burroughs 220
* (Bulletin 5023, Burroughs Corporation, November 1959).
* Burroughs 220 Schematics
* (Technical Manual 4053-1, Burroughs Corporation, December 1958).
* Datatron 220 Schematics, Section I [CPU.pdf]
* (Technical Manual 4053, Burroughs Corporation, December 1958).
*
* available at:
* http://bitsavers.org/pdf/burroughs/electrodata/205/
* http://bitsavers.org/pdf/burroughs/electrodata/220/
*
* also:
*
* TM4001 Datatron 205 Computer (Training Edition)
* (Burroughs Corporation, December,1956).
* Burroughs 205 Handbook: Floating Point Control Unit Model 36044
* (Bulletin 3028, Burroughs Corporation 1957).
* Engineering Description of the ElectroData Digital Computer, J. C. Alrich,
* (IRE Transactions on Electronic Computers, vol EC-4, Number 1, March 1955).
* An Introduction to Coding the Burroughs 220
* (Bulletin 5019, Burroughs Corporation, December, 1958).
*
* Datatron 205 word format:
* Burroughs 220 word format:
* 44 bits, encoded as binary-coded decimal (BCD); non-decimal codes are invalid
* and cause the computer to stop with a Forbidden Combination (FC) alarm.
* High-order 4 bits are the "sign digit":
@ -44,7 +42,7 @@
* Instruction word format:
* Low-order 4 digits: operand address
* Next-higher 2 digits: operation code
* Next-higher 4 digits: breakpoint and special-function codes
* Next-higher 4 digits: control and variant digits used by some instructions
* Sign digit: odd value indicates the B register is to be added to the
* operand address prior to execution.
*
@ -53,7 +51,7 @@
*
************************************************************************
* 2017-01-01 P.Kimpel
* Original version, cloned from a bit of retro-205 code.
* Original version, cloned from retro-205 emulator/D205Processor.js.
***********************************************************************/
"use strict";
@ -72,25 +70,133 @@ function B220Processor(config, devices) {
this.successor = null; // Current delayed-action successor function
// Memory
this.memoryDrum = new ArrayBuffer(4080*8); // Drum: 4080 64-bit FP words
this.MM = new Float64Array(this.memoryDrum, 0, 4000); // Main memory, 4000 words
this.L4 = new Float64Array(this.memoryDrum, 4000*8, 20); // 4000 loop, 20 words
this.L5 = new Float64Array(this.memoryDrum, 4020*8, 20); // 5000 loop, 20 words
this.L6 = new Float64Array(this.memoryDrum, 4040*8, 20); // 6000 loop, 20 words
this.L7 = new Float64Array(this.memoryDrum, 4060*8, 20); // 7000 loop, 20 words
this.MM = new Float64Array(config.getNode("memorySize")); // Main memory, 11-digit words
// Supervisory Panel switches
this.sswLockNormal = 0; // Lock/Normal switch
this.sswStepContinuous = 0; // Step/Continuous switch
this.sswAudibleAlarm = 0; // Audible alarm
// Processor throttling control
this.runTime = 0; // Running time for processor, ms
this.scheduler = 0; // Current setCallback token
this.procStart = 0; // Javascript time that the processor started running, ms
this.procTime = 0; // Total processor running time, ms
// Control Console switches
this.cswPOSuppress = 0; // Print-out suppress
this.cswSkip = 0; // Skip instruction
this.cswAudibleAlarm = 0; // Audible alarm
this.cswOutput = 0; // Output knob: 0=Off, 1=Page, 2=Tape (mapped from actual knob values)
this.cswInput = 0; // Input knob: 0=Mechanical reader, 1=Optical reader, 2=Keyboard
this.cswBreakpoint = 0; // Breakpoint knob: 0=Off, 1, 2, 4
this.delayDeltaAvg = 0; // Average difference between requested and actual setCallback() delays, ms
this.delayLastStamp = 0; // Timestamp of last setCallback() delay, ms
this.delayRequested = 0; // Last requested setCallback() delay, ms
// Primary Registers
this.A = new B220Processor.Register(11*4, this, false);
this.B = new B220Processor.Register( 4*4, this, false);
this.C = new B220Processor.Register(10*4, this, false);
this.D = new B220Processor.Register(11*4, this, false);
this.E = new B220Processor.Register( 4*4, this, false);
this.P = new B220Processor.Register( 4*4, this, false);
this.R = new B220Processor.Register(11*4, this, false);
this.S = new B220Processor.Register( 4*4, this, false);
// Control Console Lamps
this.digitCheckAlarm = new B220Processor.FlipFlop(this, false);
this.programCheckAlarm = new B220Processor.FlipFlop(this, false);
this.storageAlarm = new B220Processor.FlipFlop(this, false);
this.magneticTapeAlarm = new B220Processor.FlipFlop(this, false);
this.paperTapeAlarm = new B220Processor.FlipFlop(this, false);
this.cardatronAlarm = new B220Processor.FlipFlop(this, false);
this.systemNotReady = new B220Processor.FlipFlop(this, false);
this.computerNotReady = new B220Processor.FlipFlop(this, false);
this.computerNotReady.set(1); // initial state after power-up
// Control Console Switches
this.PC1SW = 0; // Program control switches 1-10
this.PC2SW = 0;
this.PC3SW = 0;
this.PC4SW = 0;
this.PC5SW = 0;
this.PC6SW = 0;
this.PC7SW = 0;
this.PC8SW = 0;
this.PC9SW = 0;
this.PC0SW = 0;
this.SONSW = 0; // S "On" switch
this.SUNITSSW = 0; // S units switch
this.STOCSW = 0; // S to C switch
this.STOPSW = 0; // S to P switch
// Left-Hand Maintenance Panel Switches
this.HOLDPZTZEROSW = 0;
this.LEADINGZEROESSW = 0;
this.PAPERTAPESUMSW = 0;
this.ORDERCOMPLEMENTSW = 0;
this.MEMORYLOCKOUTSW = 0;
this.DCLOCKOUTSW = 0;
this.SPDPHOLDSW = 0;
this.HOLDSEQUENCE1SW = 0;
this.HOLDSEQUENCE2SW = 0;
this.HOLDSEQUENCE4SW = 0;
this.HOLDSEQUENCE8SW = 0;
// Left-Hand Maintenance Panel Registers & Flip-Flops
this.CI = new B220Processor.Register(5, this, false); // carry inverters
this.DC = new B220Processor.Register(6, this, false); // digit counter (modulo 20)
this.SC = new B220Processor.Register(4, this, false); // sequence counter
this.SI = new B220Processor.Register(4, this, false); // sum inverters
this.X = new B220Processor.Register(4, this, false); // adder X input
this.Y = new B220Processor.Register(4, this, false); // adder Y input
this.Z = new B220Processor.Register(4, this, false); // decimal sum inverters, adder output
this.C10 = new B220Processor.FlipFlop(this, false); // decimal carry toggle
this.DST = new B220Processor.FlipFlop(this, false); // D-sign toggle
this.LT1 = new B220Processor.FlipFlop(this, false); // logical toggle 1
this.LT2 = new B220Processor.FlipFlop(this, false); // logical toggle 2
this.LT3 = new B220Processor.FlipFlop(this, false); // logical toggle 3
this.SCI = new B220Processor.FlipFlop(this, false); // sequence counter inverter
this.SGT = new B220Processor.FlipFlop(this, false); // sign toggle
this.SUT = new B220Processor.FlipFlop(this, false); // subtract toggle
this.TBT = new B220Processor.FlipFlop(this, false); // tape busy toggle
this.TCT = new B220Processor.FlipFlop(this, false); // tape clock toggle
this.TPT = new B220Processor.FlipFlop(this, false); // tape pulse toggle
this.TWT = new B220Processor.FlipFlop(this, false); // tape write toggle
// Right-Hand Maintenance Panel Switches
this.MULTIPLEACCESSSW = 0;
this.V1V2V3COUNTSW = 0;
this.AUDIBLEALARMSW = 0;
this.PCOUNTSW = 0;
this.DIGITCHECKSW = 0;
this.ALARMSW = 0;
this.ADCOUNTSW = 0;
this.IDLEALARMSW = 0;
this.FREQUENCYSELECTSW = 0;
this.SINGLEPULSESW = 0;
this.FETCHEXECUTELOCKSW = 0;
// Right-Hand Maintenance Panel Registers & Flip-Flops
this.AX = new B220Processor.Register(10, this, false); // AX register
this.BI = new B220Processor.Register( 8, this, false); // paper tape decoder
this.DX = new B220Processor.Register( 8, this, false); // DX register
this.PA = new B220Processor.Register( 8, this, false); // PA register
this.ALT = new B220Processor.FlipFlop(this, false); // program check alarm toggle
this.AST = new B220Processor.FlipFlop(this, false); // asynchronous toggle
this.CCT = new B220Processor.FlipFlop(this, false); // ?? toggle
this.CRT = new B220Processor.FlipFlop(this, false); // Cardatron alarm toggle
this.DPT = new B220Processor.FlipFlop(this, false); // ?? digit pulse toggle
this.EWT = new B220Processor.FlipFlop(this, false); // end of word toggle
this.EXT = new B220Processor.FlipFlop(this, false); // fetch(0)/execute(1) toggle
this.HAT = new B220Processor.FlipFlop(this, false); // ?? toggle
this.HCT = new B220Processor.FlipFlop(this, false); // ?? toggle
this.HIT = new B220Processor.FlipFlop(this, false); // high comparison toggle
this.MAT = new B220Processor.FlipFlop(this, false); // multiple access toggle
this.MET = new B220Processor.FlipFlop(this, false); // memory (storage) alarm toggle
this.MNT = new B220Processor.FlipFlop(this, false); // manual toggle
this.OFT = new B220Processor.FlipFlop(this, false); // overflow toggle
this.PAT = new B220Processor.FlipFlop(this, false); // paper tape alarm toggle
this.PRT = new B220Processor.FlipFlop(this, false); // paper tape read toggle
this.PZT = new B220Processor.FlipFlop(this, false); // paper tape zone toggle
this.RPT = new B220Processor.FlipFlop(this, false); // repeat toggle
this.RUT = new B220Processor.FlipFlop(this, false); // run toggle
this.SST = new B220Processor.FlipFlop(this, false); // single-step toggle
this.TAT = new B220Processor.FlipFlop(this, false); // magnetic tape alarm toggle
this.UET = new B220Processor.FlipFlop(this, false); // unequal comparison toggle (HIT=UET=0 => off)
// Mag-Tape Control Unit switch
this.tswSuppressB = 0; // Suppress B-register modification on input
@ -117,66 +223,31 @@ function B220Processor(config, devices) {
this.boundMagTapeSendBlock = B220Processor.bindMethod(this, B220Processor.prototype.magTapeSendBlock);
this.boundMagTapeTerminateSend = B220Processor.bindMethod(this, B220Processor.prototype.magTapeTerminateSend);
// Processor throttling control
this.scheduler = 0; // Current setCallback token
this.procStart = 0; // Javascript time that the processor started running, ms
this.procTime = 0; // Total processor running time, ms
// External switches [used by EXC (71)]
this.externalSwitch = [0, 0, 0, 0, 0, 0, 0, 0];
// Register average-intensity accumulators
this.glowTimer = null;
this.toggleGlow = {
glowA: new Float64Array(44),
glowB: new Float64Array(16),
glowC: new Float64Array(40),
glowD: new Float64Array(44),
glowR: new Float64Array(40),
glowCtl: new Float64Array(40),
glowADDER: new Float64Array(4),
glowCT: new Float64Array(5),
glowTiming: 0,
glowOverflow: 0,
glowTWA: 0,
glow3IO: 0,
glowMAIN: 0,
glowRWM: 0,
glowRWL: 0,
glowWDBL: 0,
glowACTION: 0,
glowACCESS: 0,
glowLM: 0,
glowL4: 0,
glowL5: 0,
glowL6: 0,
glowL7: 0};
this.clear(); // Create and initialize the processor state
this.loadDefaultProgram(); // Preload a default program
//this.loadDefaultProgram(); // Preload a default program
}
/**************************************/
/* Global constants */
B220Processor.version = "0.00a";
B220Processor.version = "0.00b";
B220Processor.drumRPM = 3570; // memory drum speed, RPM
B220Processor.trackSize = 200; // words per drum revolution
B220Processor.loopSize = 20; // words per high-speed loop
B220Processor.wordTime = 60000/B220Processor.drumRPM/B220Processor.trackSize;
// one word time, about 0.084 ms at 3570rpm (=> 142.8 KHz)
B220Processor.wordsPerMilli = 1/B220Processor.wordTime;
// word times per millisecond
B220Processor.neonPersistence = 1000/30;
// persistence of neon bulb glow [ms]
B220Processor.maxGlowTime = B220Processor.neonPersistence*B220Processor.wordsPerMilli;
// panel bulb glow persistence [word-times]
B220Processor.maxGlowTime = B220Processor.neonPersistence;
// panel bulb glow persistence [ms]
B220Processor.lampGlowInterval = 50; // background lamp sampling interval (ms)
B220Processor.adderGlowAlpha = B220Processor.wordTime/12/B220Processor.neonPersistence;
B220Processor.adderGlowAlpha = B220Processor.neonPersistence/12;
// adder and carry toggle glow decay factor,
// based on one digit (1/12 word) time
// based on one digit (1/12 word) time [ms]
B220Processor.cyclesPerMilli = 1000; // clock cycles per millisecond (1000 => 1.0 MHz)
B220Processor.timeSlice = 4000; // this.run() time-slice, clocks
B220Processor.delayAlpha = 0.001; // decay factor for exponential weighted average delay
B220Processor.delayAlpha1 = 1-B220Processor.delayAlpha;
B220Processor.slackAlpha = 0.0001; // decay factor for exponential weighted average slack
B220Processor.slackAlpha1 = 1-B220Processor.slackAlpha;
B220Processor.pow2 = [ // powers of 2 from 0 to 52
0x1, 0x2, 0x4, 0x8,
@ -216,55 +287,97 @@ B220Processor.prototype.clear = function clear() {
this.clearControl();
// Registers
this.A = 0; // A register - accumulator
this.B = 0; // B register - index, loop control
this.C = 0; // C register - current operator, control counter
this.D = 0; // D register - input buffer from memory and I/O
this.R = 0; // R register - accumulator extension
// Primary Registers
this.A.set(0);
this.B.set(0);
this.C.set(0);
this.D.set(0);
this.E.set(0);
this.P.set(0);
this.R.set(0);
this.S.set(0);
// Control Console Lamps
this.digitCheckAlarm.set(0);
this.programCheckAlarm.set(0);
this.storageAlarm.set(0);
this.magneticTapeAlarm.set(0);
this.paperTapeAlarm.set(0);
this.cardatronAlarm.set(0);
this.systemNotReady.set(0);
this.computerNotReady.set(0);
// Left-Hand Maintenance Panel Registers & Flip-Flops
this.CI.set(0);
this.DC.set(0);
this.SC.set(0);
this.SI.set(0);
this.X.set(0);
this.Y.set(0);
this.Z.set(0);
this.C10.set(0);
this.DST.set(0);
this.LT1.set(0);
this.LT2.set(0);
this.LT3.set(0);
this.SCI.set(0);
this.SGT.set(0);
this.SUT.set(0);
this.TBT.set(0);
this.TCT.set(0);
this.TPT.set(0);
this.TWT.set(0);
// Right-Hand Maintenance Panel Registers & Flip-Flops
this.AX.set(0);
this.BI.set(0);
this.DX.set(0);
this.PA.set(0);
this.ALT.set(0);
this.AST.set(0);
this.CCT.set(0);
this.CRT.set(0);
this.DPT.set(0);
this.EWT.set(0);
this.EXT.set(1); // clear to fetch state
this.HAT.set(0);
this.HCT.set(0);
this.HIT.set(0);
this.MAT.set(0);
this.MET.set(0);
this.MNT.set(0);
this.OFT.set(0);
this.PAT.set(0);
this.PRT.set(0);
this.PZT.set(0);
this.RPT.set(0);
this.RUT.set(0);
this.SST.set(0);
this.TAT.set(0);
this.UET.set(0);
this.COP = 0; // copy of C register op code (2 digits)
this.CADDR = 0; // copy of C register operand address (4 digits)
this.CCONTROL = 0; // copy of C register control address (4 digits)
this.CEXTRA = 0; // high-order four digits of instruction word + sign
// Adder registers
this.ADDER = 0; // The adder
this.CT = 0; // Carry toggles for the adder
// Timing control and statistics
this.cycleCount = 0; // Cycle count for current instruction
this.cycleLimit = 0; // Cycle limit for this.run()
this.normalCycles = 0; // Current normal-state cycle count (for UI display)
this.runCycles = 0; // Current cycle count for this.run()
this.totalCycles = 0; // Total cycles executed on this processor
this.procStart = 0; // Javascript time that the processor started running, ms
this.procTime = 0.001; // Total processor running time, ms
this.procSlack = 0; // Total processor throttling delay, ms
this.procSlackAvg = 0; // Average slack time per time slice, ms
this.procRunAvg = 0; // Average run time per time slice, ms
// Operational toggles
this.togTiming = 1; // Timing toggle: 0=execute, 1=fetch
this.togCST = 1; // Computer Stop toggle (?)
this.cctContinuous = 0; // Console step(0) / continuous(1) toggle
// Halt/error toggles
this.stopOverflow = 0; // Halted due to overflow
this.stopSector = 0; // Halted due to sector alarm
this.stopForbidden = 0; // Halted due to forbidden combination
this.stopControl = 0; // Halted due to Stop operator (08) or overflow
this.stopBreakpoint = 0; // Halted due to breakpoint
this.stopIdle = 1; // Halted or in step mode
// Memory control toggles
this.memMAIN = 0; // Access is to main memory
this.memRWM = 0; // Read/write main memory
this.memRWL = 0; // Read/write loop memory
this.memWDBL = 0; // Word or block transfer
this.memACTION = 0; // Memory access ACTION toggle
this.memACCESS = 0; // Memory access active toggle
this.memLM = 0; // Loop/main access toggle
this.memL4 = 0; // 4000 loop access
this.memL5 = 0; // 5000 loop access
this.memL6 = 0; // 6000 loop access
this.memL7 = 0; // 7000 loop access
// Statistics timers
this.lastGlowTime = 0; // Last panel lamp intensity update time [word-times]
this.memoryStartTime = 0; // Start of last memory access [word-times]
this.memoryStopTime = 0; // End of last memory access [word-times]
this.setTimingToggle(0); // set to Execute initially
this.sampleLamps(1.0, 1.0); // initialize the lamp-glow averages
//this.setTimingToggle(0); // set to Execute initially
//this.sampleLamps(1.0, 1.0); // initialize the lamp-glow averages
// Kill any pending action that may be in process
if (this.scheduler) {
@ -335,6 +448,104 @@ B220Processor.prototype.clearControl = function clearControl() {
this.selectedUnit = 0; // currently-selected unit number
};
/***********************************************************************
* Generic Register Class *
***********************************************************************/
B220Processor.Register = function Register(bits, p, invisible) {
/* Constructor for the generic Register class. Defines a binary register
of "bits" bits. "p" is a reference to the Processor object, used to access
the timing members. "invisible" should be true if the register does not
have a visible presence in the UI -- this will inhibit computing average
lamp glow values for the register */
this.bits = bits; // number of bits in register
this.visible = (invisible ? false : true);
this.lastRunTime = 0; // time register was last set
this.p = p; // processor instance
this.value = 0; // binary value of register: read-only externally
this.glow = new Float64Array(bits); // average lamp glow values
};
/**************************************/
B220Processor.Register.prototype.set = function set(value) {
/* Set a binary value into the register. Use this rather than setting
the value member directly so that average lamp glow can be computed.
Returns the new value */
var alpha = Math.max(Math.max(this.p.runTime-this.lastRunTime, 1)/B220Processor.maxGlowTime, 1.0);
var alpha1 = 1.0-alpha;
var b = 0;
var bit;
var v = this.value;
// Update the lamp glow for the former state.
if (this.visible) {
while (v) {
bit = v % 2;
v = (v-bit)/2;
this.glow[b] = this.glow[b]*alpha1 + bit*alpha;
++b;
}
while (b < this.bits) {
this.glow[b] *= alpha1;
++b;
}
}
// Set the new state.
this.value = value;
this.lastRunTime = this.p.runTime;
return this.value;
};
/***********************************************************************
* Generic Flip-Flop Class *
***********************************************************************/
B220Processor.FlipFlop = function FlopFlop(p, invisible) {
/* Constructor for the generaic FlipFlop class. "p" is a reference to the
Processor object, used to access the timing members. "invisible" should be
true if the FF does not have a visible presence in the UI -- this will
inhibit computing the average lamp glow value for it */
this.visible = (invisible ? false : true);
this.lastRunTime = 0; // time register was last set
this.p = p; // processor instance
this.value = 0; // binary value of register: read-only externally
this.glow = 0; // average lamp glow value
};
/**************************************/
B220Processor.FlipFlop.prototype.set = function set(value) {
/* Set the value of the FF. Use this rather than setting the value member
directly so that average lamp glow can be computed. Returns the new value */
var alpha = Math.min(Math.max(this.p.runTime-this.lastRunTime, 1)/B220Processor.maxGlowTime, 1.0);
var alpha1 = 1.0-alpha;
var v = this.value;
// Update the lamp glow for the former state.
if (this.visible) {
this.glow = this.glow*alpha1 + value*alpha;
}
// Set the new state.
this.value = (value ? 1 : 0);
this.lastRunTime = this.p.runTime;
return this.value;
};
/**************************************/
B220Processor.FlipFlop.prototype.flip = function flip() {
/* Complement the value of the FF. Returns the new value */
return this.set(this.value ? 0 : 1);
};
/***********************************************************************
* Utility Functions *
***********************************************************************/
@ -750,7 +961,7 @@ B220Processor.prototype.bcdAdd = function bcdAdd(a, d, complement, initialCarry)
// compute the carry toggle register (just for display)
ct = (((ad & dd) | (ad & ct) | (dd & ct)) << 1) + carry;
this.updateAdderGlow(adder, ct);
//this.updateAdderGlow(adder, ct);
// rotate the adder into the sign digit
am += adder*0x10000000000;
@ -1384,7 +1595,7 @@ B220Processor.prototype.readMemoryFinish = function readMemoryFinish() {
function. Note: the word has already been stored in D by readMemory() */
this.scheduler = 0;
this.stopMemoryTiming();
//this.stopMemoryTiming();
this.successor();
};
@ -1431,7 +1642,7 @@ B220Processor.prototype.readMemory = function readMemory(successor) {
latency = (addr%trackSize - drumTime%trackSize + trackSize)%trackSize;
this.procTime += latency+1; // emulated time at end of drum access
this.memACTION = 1;
this.startMemoryTiming(drumTime);
//this.startMemoryTiming(drumTime);
this.successor = successor;
this.scheduler = setCallback(cbCategory, this,
(this.procTime-drumTime)/B220Processor.wordsPerMilli, this.readMemoryFinish);
@ -1444,7 +1655,7 @@ B220Processor.prototype.writeMemoryFinish = function writeMemoryFinish(clearA) {
memory control toggles, and calls the current successor function */
this.scheduler = 0;
this.stopMemoryTiming();
//this.stopMemoryTiming();
if (clearA) {
this.A = 0;
}
@ -1495,7 +1706,7 @@ B220Processor.prototype.writeMemory = function writeMemory(successor, clearA) {
latency = (addr%trackSize - drumTime%trackSize + trackSize)%trackSize;
this.procTime += latency+1; // emulated time at end of drum access
this.memACTION = 1;
this.startMemoryTiming(drumTime);
//this.startMemoryTiming(drumTime);
this.successor = successor;
this.scheduler = setCallback(cbCategory, this,
(this.procTime-drumTime)/B220Processor.wordsPerMilli, this.writeMemoryFinish, clearA);
@ -1558,7 +1769,7 @@ B220Processor.prototype.blockFromLoop = function blockFromLoop(loop, successor)
B220Processor.trackSize)%B220Processor.trackSize;
this.procTime += latency+B220Processor.loopSize; // emulated time at end of drum access
this.memACTION = 1;
this.startMemoryTiming(drumTime);
//this.startMemoryTiming(drumTime);
this.successor = successor;
this.scheduler = setCallback("MEMM", this,
(this.procTime-drumTime)/B220Processor.wordsPerMilli, this.writeMemoryFinish, false);
@ -1631,7 +1842,7 @@ B220Processor.prototype.blockToLoop = function blockToLoop(loop, successor) {
B220Processor.trackSize)%B220Processor.trackSize;
this.procTime += latency+B220Processor.loopSize; // emulated time at end of drum access
this.memACTION = 1;
this.startMemoryTiming(drumTime);
//this.startMemoryTiming(drumTime);
this.successor = successor;
this.scheduler = setCallback("MEMM", this,
(this.procTime-drumTime)/B220Processor.wordsPerMilli, this.writeMemoryFinish, false);
@ -1642,7 +1853,7 @@ B220Processor.prototype.searchMemoryFinish = function searchMemoryFinish() {
/* Handles completion of a search memory operation and resets the memory
toggle and timing state */
this.stopMemoryTiming();
//this.stopMemoryTiming();
this.executionComplete();
};
@ -1678,7 +1889,7 @@ B220Processor.prototype.searchMemory = function searchMemory(high) {
if (!this.memACCESS) {
this.memACCESS = this.memACTION = this.memMAIN = this.memLM = 1;
this.startMemoryTiming(performance.now()*B220Processor.wordsPerMilli);
//this.startMemoryTiming(performance.now()*B220Processor.wordsPerMilli);
}
addr = B220Processor.bcdBinary(this.CADDR % 0x4000);
@ -3240,7 +3451,7 @@ B220Processor.prototype.powerUp = function powerUp() {
this.cardatron = this.devices.CardatronControl;
this.magTape = this.devices.MagTapeControl;
this.lastGlowTime = performance.now()*B220Processor.wordsPerMilli;
this.glowTimer = setInterval(this.boundUpdateLampGlow, B220Processor.lampGlowInterval);
//this.glowTimer = setInterval(this.boundUpdateLampGlow, B220Processor.lampGlowInterval);
}
};
@ -3261,6 +3472,73 @@ B220Processor.prototype.powerDown = function powerDown() {
}
}
};
/**************************************/
B220Processor.prototype.schedule = function schedule() {
/* Schedules the processor running time and attempts to throttle performance
to approximate that of a real B220. It establishes
a timeslice in terms of a number of processor "cycles" of 5 microseconds
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 processor remains active,
this routine will reschedule itself after an appropriate delay, thereby
throttling the performance and allowing other modules a chance at the
single Javascript execution thread */
var clockOff = performance.now(); // ending time for the delay and the run() call, ms
var delayTime; // delay from/until next run() for this processor, ms
var runTime; // real-world processor running time, ms
this.scheduler = 0;
delayTime = clockOff - this.delayLastStamp;
this.procSlack += delayTime;
// Compute the exponential weighted average of scheduling delay
this.delayDeltaAvg = (delayTime - this.delayRequested)*B220Processor.delayAlpha +
this.delayDeltaAvg*B220Processor.delayAlpha1;
this.procSlackAvg = B220Processor.slackAlpha*delayTime +
this.procSlackAvg*B220Processor.slackAlpha1;
if (this.busy) {
this.cycleLimit = B220Processor.timeSlice;
this.run(); // execute instructions for the timeslice
clockOff = performance.now();
this.procRunAvg = (clockOff - this.delayLastStamp)*B220Processor.slackAlpha +
this.procRunAvg*B220Processor.slackAlpha1;
this.delayLastStamp = clockOff;
this.totalCycles += this.runCycles;
if (!this.busy) {
this.delayRequested = 0;
} else {
runTime = this.procTime;
while (runTime < 0) {
runTime += clockOff;
}
delayTime = this.totalCycles/B220Processor.cyclesPerMilli - runTime;
// delayTime is the number of milliseconds the processor is running ahead of
// real-world time. Web browsers have a certain minimum setTimeout() delay. If the
// delay is less than our estimate of that minimum, setCallback will yield to
// the event loop but otherwise continue (real time should eventually catch up --
// we hope). If the delay is greater than the minimum, setCallback will reschedule
// us after that delay.
this.delayRequested = delayTime;
this.scheduler = setCallback(this.mnemonic, this, delayTime, this.schedule);
}
}
};
/**************************************/
B220Processor.prototype.step = function step() {
/* Single-steps the processor. Normally this will cause one instruction to
be executed, but note that in the case of an interrupt or char-mode CRF, one
or two injected instructions (e.g., SFI followed by ITI) could also be executed */
this.cycleLimit = 1;
this.run();
this.totalCycles += this.runCycles;
};
/**************************************/
B220Processor.prototype.loadDefaultProgram = function loadDefaultProgram() {

View File

@ -232,25 +232,25 @@ DIV.orangeLit5 {
DIV.orangeLit {
background-image: radial-gradient(circle, #F93, #E93, #960)}
DIV.greenLamp {
DIV.blueLamp {
position: absolute;
width: 24px;
height: 24px;
font-size: 4px;
border-radius: 50%;
background-image: radial-gradient(circle, #090, #030)}
DIV.greenLit1 {
background-image: radial-gradient(circle, #0A0, #090, #040)}
DIV.greenLit2 {
background-image: radial-gradient(circle, #0B0, #0A0, #050)}
DIV.greenLit3 {
background-image: radial-gradient(circle, #0C0, #0B0, #060)}
DIV.greenLit4 {
background-image: radial-gradient(circle, #0D0, #0C0, #070)}
DIV.greenLit5 {
background-image: radial-gradient(circle, #0E0, #0D0, #080)}
DIV.greenLit {
background-image: radial-gradient(circle, #0F0, #0E0, #090)}
background-image: radial-gradient(circle, #039, #003)}
DIV.blueLit1 {
background-image: radial-gradient(circle, #03A, #039, #004)}
DIV.blueLit2 {
background-image: radial-gradient(circle, #03B, #03A, #005)}
DIV.blueLit3 {
background-image: radial-gradient(circle, #04C, #04C, #006)}
DIV.blueLit4 {
background-image: radial-gradient(circle, #05D, #05D, #007)}
DIV.blueLit5 {
background-image: radial-gradient(circle, #06E, #06E, #008)}
DIV.blueLit {
background-image: radial-gradient(circle, #07F, #07F, #009)}
DIV.coloredLampTopCaption {
position: absolute;

View File

@ -11,15 +11,15 @@
* Original version, from D205SupervisoryPanel.css
***********************************************************************/
#BurroughsMeatball {
#BurroughsLogo {
position: absolute;
left: 12px;
top: 6px;
height: 36px}
#BurroughsLogo {
#BurroughsMeatball {
position: absolute;
left: 100px;
left: 334px;
top: 6px;
height: 36px}
@ -87,13 +87,13 @@
height: 128px}
#RRegPanel {
left: 372px;
left: calc(50% - 156px);
top: 48px;
width: 312px;
height: 128px}
#DRegPanel {
left: 732px;
right: 12px;
top: 48px;
width: 312px;
height: 128px}
@ -111,19 +111,19 @@
height: 128px}
#CRegPanel {
left: 384px;
left: calc(50% - 144px);
top: 208px;
width: 288px;
height: 128px}
#ERegPanel {
left: 732px;
right: 180px;
top: 208px;
width: 144px;
height: 128px}
#SRegPanel {
left: 900px;
right: 12px;
top: 208px;
width: 144px;
height: 128px}
@ -216,7 +216,7 @@
/***** Operation Panel *****/
#OperationPanel {
left: 452px;
left: calc(50% - 77px);
top: 368px;
width: 154px;
height: 64px}
@ -254,7 +254,7 @@
/***** Status Panel *****/
#StatusPanel {
left: 662px;
right: 12px;
top: 368px;
width: 382px;
height: 64px}
@ -430,7 +430,7 @@
/***** Operation Switch Panel *****/
#OperationSwitchPanel {
left: 452px;
left: calc(50% - 77px);
top: 464px;
width: 154px;
height: 80px}
@ -478,7 +478,7 @@
/***** Miscellaneous Switch Panel *****/
#MiscellaneousSwitchPanel {
left: 662px;
right: 12px;
top: 464px;
width: 382px;
height: 80px}
@ -571,6 +571,19 @@
width: 32px}
/***** Diagnostics Panel (DEBUG) *****/
#Diagnostics {
display: none}
#CallbackTable {
position: relative;
top: 1ex;
visibility: visible;
border-collapse: collapse;
border-spacing: 0}
/***** Old Stuff *****/
#PowerOnBtn {
@ -580,127 +593,3 @@
left: 600px;
top: 360px;
width: 24px}
#PowerLamp {
left: 600px;
top: 378px}
#ComputerStopCaption {
left: 478px;
top: 300px;
width: 160px}
#ResetOverflowBtn {
left: 461px;
top: 416px}
#ResetOverflowCaption {
left: 461px;
top: 456px;
width: 34px}
#SectorLamp {
left: 506px;
top: 330px}
#SectorLampCaption {
left: 497px;
top: 360px;
width: 40px}
#ResetSectorBtn {
left: 501px;
top: 416px}
#ResetSectorCaption {
left: 501px;
top: 456px;
width: 34px}
#ControlLamp {
left: 546px;
top: 330px}
#ControlLampCaption {
left: 537px;
top: 360px;
width: 40px}
#ResetControlBtn {
left: 541px;
top: 416px}
#ResetControlCaption {
left: 541px;
top: 456px;
width: 34px}
#FCLamp {
left: 586px;
top: 330px}
#FCLampCaption {
left: 586px;
top: 360px;
width: 24px}
#IdleLamp {
left: 626px;
top: 330px}
#IdleLampCaption {
left: 626px;
top: 360px;
width: 24px}
#AudibleAlarmSwitch {
position: absolute;
left: 626px;
top: 420px;
width: 24px}
#AudibleAlarmOn {
left: 626px;
top: 408px;
width: 24px}
#AudibleAlarmOff {
left: 608px;
top: 456px;
line-height: 130%;
width: 60px}
#ClearBtn {
left: 710px;
top: 374px}
#ClearBtnCaption {
left: 710px;
top: 300px;
width: 32px}
#LockNormalSwitch {
position: absolute;
left: 808px;
top: 378px;
width: 24px}
#LockNormalOn {
left: 808px;
top: 370px;
width: 24px}
#LockNormalOff {
left: 802px;
top: 408px;
width: 36px}
#TimingToggleCaption {
left: 844px;
top: 300px;
width: 64px}
#OperationCaption {
left: 950px;
top: 300px;
width: 88px}
#StepContinuousSwitch {
position: absolute;
left: 950px;
top: 378px;
width: 24px}
#StepContinuousOn {
left: 932px;
top: 370px;
width: 60px}
#StepContinuousOff {
left: 932px;
top: 408px;
width: 60px}

View File

@ -28,7 +28,7 @@
<div id=PanelSurface class=panelSurface>
<img id=BurroughsMeatball src="resources/Burroughs-Meatball.png">
<img id=BurroughsLogo src="resources/Burroughs-Logo.jpg">
<img id=BurroughsLogo src="resources/Burroughs-Logo.png">
<div id=B220Logo>2 2 0</div>
<div id=IntervalTimerResetCaption class=caption>ZERO TIMER</div>
@ -153,67 +153,18 @@
<button id=TCUClearSwitchLabel class=panelLabel>TCU CLEAR</button>
</div>
<!--
<div id=ComputerStopCaption class=panelCaption>
<span class=panelSpan>COMPUTER STOP</span>
</div>
<div id=OverflowLampCaption class=caption>OVERFLOW</div>
<div id=ResetOverflowBtn class=blackButton1>&nbsp;</div>
<div id=ResetOverflowCaption class=caption>RESET</div>
<div id=SectorLampCaption class=caption>SECTOR</div>
<div id=ResetSectorBtn class=blackButton1>&nbsp;</div>
<div id=ResetSectorCaption class=caption>RESET</div>
<div id=ControlLampCaption class=caption>CONTROL</div>
<div id=ResetControlBtn class=blackButton1>&nbsp;</div>
<div id=ResetControlCaption class=caption>RESET</div>
<div id=FCLampCaption class=caption>F.C.</div>
<div id=IdleLampCaption class=caption>IDLE</div>
<div id=AudibleAlarmOn class=caption>ON</div>
<div id=AudibleAlarmOff class=caption>AUD. ALARM<br>DISABLE</div>
<div id=ClearBtn class=redButton1>&nbsp;</div>
<div id=ClearBtnCaption class=caption>CLEAR</div>
<div id=LockNormalOn class=caption>LOCK</div>
<div id=LockNormalOff class=caption>NORMAL</div>
<div id=ExecuteBtn class=blackButton1>&nbsp;</div>
<div id=FetchBtn class=blackButton1>&nbsp;</div>
<div id=TimingToggleCaption class=caption>TIMING TOGGLE</div>
<div id=ExecuteLampCaption class=caption>EXECUTE</div>
<div id=FetchLampCaption class=caption>FETCH</div>
<div id=OperationCaption class=caption>OPERATION</div>
<div id=StepContinuousOn class=caption>CONTINUOUS</div>
<div id=StepContinuousOff class=caption>STEP</div>
<div id=StartBtn class=blackButton3>&nbsp;</div>
<div id=StartCaption class=caption>START</div>
-->
<div id=VersionDiv class=caption>
retro-220 <span id=EmulatorVersion>?.??</span>
</div>
</div>
<div id=Diagnostics style="display:none">
<div id=Diagnostics>
<br>
Proc Delta: <input id=ProcDelta class="rj" type=text size=10>
&nbsp;&nbsp;
Latency: <input id=LastLatency class="rj" type=text size=10>
<table id=CallbackTable
style="position:relative; top:1ex; visibility:visible; border-collapse:collapse; border-spacing:0">
<table id=CallbackTable>
<thead>
<tr>
<th>ID

View File

@ -522,39 +522,39 @@ B220ControlConsole.prototype.consoleOnLoad = function consoleOnLoad() {
// Main Registers
this.regA = new PanelRegister(this.$$("ARegPanel"), 44, 4, "A_", "A");
this.regB = new PanelRegister(this.$$("BRegPanel"), 16, 4, "B_", "B");
this.regC = new PanelRegister(this.$$("CRegPanel"), 40, 4, "C_", "C");
this.regD = new PanelRegister(this.$$("DRegPanel"), 44, 4, "D_", "D");
this.regE = new PanelRegister(this.$$("ERegPanel"), 16, 4, "E_", "E");
this.regR = new PanelRegister(this.$$("RRegPanel"), 44, 4, "R_", "R");
this.regP = new PanelRegister(this.$$("PRegPanel"), 16, 4, "P_", "P");
this.regS = new PanelRegister(this.$$("SRegPanel"), 16, 4, "S_", "S");
this.regA = new PanelRegister(this.$$("ARegPanel"), 11*4, 4, "A_", "A");
this.regB = new PanelRegister(this.$$("BRegPanel"), 4*4, 4, "B_", "B");
this.regC = new PanelRegister(this.$$("CRegPanel"), 10*4, 4, "C_", "C");
this.regD = new PanelRegister(this.$$("DRegPanel"), 11*4, 4, "D_", "D");
this.regE = new PanelRegister(this.$$("ERegPanel"), 4*4, 4, "E_", "E");
this.regR = new PanelRegister(this.$$("RRegPanel"), 11*4, 4, "R_", "R");
this.regP = new PanelRegister(this.$$("PRegPanel"), 4*4, 4, "P_", "P");
this.regS = new PanelRegister(this.$$("SRegPanel"), 4*4, 4, "S_", "S");
// Status Panels
panel = this.$$("AlarmPanel");
this.digitCheckLamp = new ColoredLamp(panel, null, null, "DigitCheckLamp", "redLamp lampCollar", "redLit");
this.programCheck = new ColoredLamp(panel, null, null, "ProgramCheckLamp", "redLamp lampCollar", "redLit");
this.storageLamp = new ColoredLamp(panel, null, null, "StorageLamp", "redLamp lampCollar", "redLit");
this.magneticTapeLamp = new ColoredLamp(panel, null, null, "MagneticTapeLamp", "redLamp lampCollar", "redLit");
this.cardatronLamp = new ColoredLamp(panel, null, null, "CardatronLamp", "redLamp lampCollar", "redLit");
this.paperTapeLamp = new ColoredLamp(panel, null, null, "PaperTapeLamp", "redLamp lampCollar", "redLit");
this.digitCheckLamp = new ColoredLamp(panel, null, null, "DigitCheckLamp", "redLamp lampCollar", "redLit");
this.programCheck = new ColoredLamp(panel, null, null, "ProgramCheckLamp", "redLamp lampCollar", "redLit");
this.storageLamp = new ColoredLamp(panel, null, null, "StorageLamp", "redLamp lampCollar", "redLit");
this.magneticTapeLamp = new ColoredLamp(panel, null, null, "MagneticTapeLamp", "redLamp lampCollar", "redLit");
this.cardatronLamp = new ColoredLamp(panel, null, null, "CardatronLamp", "redLamp lampCollar", "redLit");
this.paperTapeLamp = new ColoredLamp(panel, null, null, "PaperTapeLamp", "redLamp lampCollar", "redLit");
this.highSpeedPrinterLamp = new ColoredLamp(panel, null, null, "HighSpeedPrinterLamp", "redLamp lampCollar", "redLit");
this.systemNotReadyLamp = new ColoredLamp(panel, null, null, "SystemNotReadyLamp", "redLamp lampCollar", "redLit");
this.systemNotReadyLamp = new ColoredLamp(panel, null, null, "SystemNotReadyLamp", "redLamp lampCollar", "redLit");
this.computerNotReadyLamp = new ColoredLamp(panel, null, null, "ComputerNotReadyLamp", "redLamp lampCollar", "redLit");
panel = this.$$("OperationPanel");
this.runLamp = new ColoredLamp(panel, null, null, "RunLamp", "redLamp lampCollar", "redLit");
this.fetchLamp = new ColoredLamp(panel, null, null, "FetchLamp", "redLamp lampCollar", "redLit");
this.executeLamp = new ColoredLamp(panel, null, null, "ExecuteLamp", "redLamp lampCollar", "redLit");
this.runLamp = new ColoredLamp(panel, null, null, "RunLamp", "blueLamp lampCollar", "blueLit");
this.fetchLamp = new ColoredLamp(panel, null, null, "FetchLamp", "blueLamp lampCollar", "blueLit");
this.executeLamp = new ColoredLamp(panel, null, null, "ExecuteLamp", "blueLamp lampCollar", "blueLit");
panel = this.$$("StatusPanel");
this.overflowLamp = new ColoredLamp(panel, null, null, "OverflowLamp", "redLamp lampCollar", "redLit");
this.repeatLamp = new ColoredLamp(panel, null, null, "RepeatLamp", "redLamp lampCollar", "redLit");
this.lowLamp = new ColoredLamp(panel, null, null, "LowLamp", "redLamp lampCollar", "redLit");
this.equalLamp = new ColoredLamp(panel, null, null, "EqualLamp", "redLamp lampCollar", "redLit");
this.highLamp = new ColoredLamp(panel, null, null, "HighLamp", "redLamp lampCollar", "redLit");
this.overflowLamp = new ColoredLamp(panel, null, null, "OverflowLamp", "blueLamp lampCollar", "blueLit");
this.repeatLamp = new ColoredLamp(panel, null, null, "RepeatLamp", "blueLamp lampCollar", "blueLit");
this.lowLamp = new ColoredLamp(panel, null, null, "LowLamp", "blueLamp lampCollar", "blueLit");
this.equalLamp = new ColoredLamp(panel, null, null, "EqualLamp", "blueLamp lampCollar", "blueLit");
this.highLamp = new ColoredLamp(panel, null, null, "HighLamp", "blueLamp lampCollar", "blueLit");
// Organ Switches

View File

@ -486,7 +486,7 @@ function OrganSwitch(parent, x, y, id, offImage, onImage, momentary) {
OrganSwitch.topCaptionClass = "OrganSwitchTopCaption";
OrganSwitch.bottomCaptionClass = "OrganSwitchBottomCaption";
OrganSwitch.momentaryPeriod = 250; // time for momentary switch to bounce back, ms
OrganSwitch.momentaryPeriod = 150; // time for momentary switch to bounce back, ms
/**************************************/
OrganSwitch.prototype.addEventListener = function addEventListener(eventName, handler, useCapture) {

View File

@ -55,6 +55,7 @@ B220SystemConfig.prototype.createConfigData = function createConfigData() {
this.configData = {
version: this.configVersion,
memorySize: 5000, // 11-digit words
SupervisoryPanel: {
pulseSourceSwitch: 0,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -24,28 +24,30 @@
id="defs4">
<linearGradient
inkscape:collect="always"
id="linearGradient3344">
id="linearGradient4299">
<stop
style="stop-color:#ffffff;stop-opacity:1"
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3346" />
id="stop4301" />
<stop
id="stop4142"
offset="0.57142907"
id="stop4307"
offset="0.63636404"
style="stop-color:#ffffff;stop-opacity:1" />
<stop
style="stop-color:#eee4d0;stop-opacity:1"
style="stop-color:#eee4d0;stop-opacity:0.50196081"
offset="1"
id="stop3348" />
id="stop4303" />
</linearGradient>
<linearGradient
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3344"
id="linearGradient4140"
x1="45"
y1="980.36218"
x2="45"
y2="1043.3622"
xlink:href="#linearGradient4299"
id="radialGradient4305"
cx="45"
cy="996.88269"
fx="45"
fy="996.88269"
r="36.5"
gradientTransform="matrix(1.2328767,-1.5759049e-7,1.7334949e-7,1.3561639,-10.479624,-353.57409)"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
@ -56,22 +58,25 @@
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="5.6"
inkscape:cx="46.701919"
inkscape:cy="27.79937"
inkscape:cx="46.27551"
inkscape:cy="57.578947"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
units="in"
width="1in"
inkscape:window-width="878"
inkscape:window-height="669"
inkscape:window-width="1188"
inkscape:window-height="862"
inkscape:window-x="31"
inkscape:window-y="29"
inkscape:window-maximized="0">
inkscape:window-maximized="0"
gridtolerance="1"
objecttolerance="1"
guidetolerance="1">
<inkscape:grid
type="xygrid"
id="grid3336"
snapvisiblegridlinesonly="true"
snapvisiblegridlinesonly="false"
units="in"
spacingx="4.5000001"
spacingy="4.5000002"
@ -96,13 +101,13 @@
transform="translate(0,-962.36221)">
<path
style="fill:#808080;fill-opacity:1;fill-rule:evenodd;stroke:#d0d0d0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 8.9999962,980.36221 c 0,0 -1.3040294,9.19309 0,13.5 1.5672478,5.17626 0.073215,43.53419 4.3571418,49.21429 4.821431,6.3929 58.107148,7.1071 62.750002,0.3571 3.97875,-5.7845 4.892856,-54.07139 4.892856,-54.07139 l 0,-9"
d="m 8.9999962,980.36221 c 0,0 -0.6036375,-1.62786 -0.3571429,8.85714 0.2464947,10.48501 0.4303579,48.17705 4.7142847,53.85715 4.821431,6.3929 58.107148,7.1071 62.750002,0.3571 3.97875,-5.7845 4.892856,-54.07139 4.892856,-54.07139 l 0,-9"
id="path3342"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsscc" />
sodipodi:nodetypes="czsscc" />
<path
style="fill:url(#linearGradient4140);fill-opacity:1;fill-rule:evenodd;stroke:#d0d0d0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 8.9999962,980.36221 c 0,0 -7e-7,57.60709 8.8214288,62.10709 8.82143,4.5001 44.821424,3.9644 54,0.1787 9.178576,-3.7858 9.178571,-62.28579 9.178571,-62.28579 z"
style="opacity:1;fill:url(#radialGradient4305);fill-opacity:1;fill-rule:evenodd;stroke:#d0d0d0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 8.9999962,980.36221 c 0,0 5e-7,58.49999 8.8214288,62.10709 8.821428,3.6071 45.178575,5.3929 54,0.1787 8.821425,-5.2142 9.178571,-62.28579 9.178571,-62.28579 z"
id="path3338"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czzcc"

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB