initial import

This commit is contained in:
Sascha Nitsch 2022-07-21 19:55:40 +02:00
parent b5359d7548
commit 31baee1015
16 changed files with 1282 additions and 0 deletions

84
addrregister.svg Normal file
View file

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg">
<g id="root" class="addrregister logicblock">
<rect width="80" height="210" x="-40" y="-90" class="outer" />
<circle color="#000000" cx="40" cy="-80" r="2"/>
<text x="20" y="-77" font-size="10">O15</text>
<circle color="#000000" cx="40" cy="-70" r="2"/>
<text x="20" y="-67" font-size="10">O14</text>
<circle color="#000000" cx="40" cy="-60" r="2"/>
<text x="20" y="-57" font-size="10">O13</text>
<circle color="#000000" cx="40" cy="-50" r="2"/>
<text x="20" y="-47" font-size="10">O12</text>
<circle color="#000000" cx="40" cy="-40" r="2"/>
<text x="20" y="-37" font-size="10">O11</text>
<circle color="#000000" cx="40" cy="-30" r="2"/>
<text x="20" y="-27" font-size="10">O10</text>
<circle color="#000000" cx="40" cy="-20" r="2"/>
<text x="25" y="-17" font-size="10">O9</text>
<circle color="#000000" cx="40" cy="-10" r="2"/>
<text x="25" y="-7" font-size="10">O8</text>
<circle color="#000000" cx="40" cy="0" r="2"/>
<text x="25" y="3" font-size="10">O7</text>
<circle color="#000000" cx="40" cy="10" r="2"/>
<text x="25" y="13" font-size="10">O6</text>
<circle color="#000000" cx="40" cy="20" r="2"/>
<text x="25" y="23" font-size="10">O5</text>
<circle color="#000000" cx="40" cy="30" r="2"/>
<text x="25" y="33" font-size="10">O4</text>
<circle color="#000000" cx="40" cy="40" r="2"/>
<text x="25" y="43" font-size="10">O3</text>
<circle color="#000000" cx="40" cy="50" r="2"/>
<text x="25" y="53" font-size="10">O2</text>
<circle color="#000000" cx="40" cy="60" r="2"/>
<text x="25" y="63" font-size="10">O1</text>
<circle color="#000000" cx="40" cy="70" r="2"/>
<text x="25" y="73" font-size="10">O0</text>
<circle color="#000000" cx="40" cy="80" r="2"/>
<text x="17" y="83" font-size="10">CLK</text>
<circle color="#000000" cx="40" cy="90" r="2"/>
<path d="M17,85 h 20"/>
<text x="17" y="93" font-size="10">CLK</text>
<circle color="#000000" cx="40" cy="100" r="2"/>
<text x="31" y="103" font-size="10">R</text>
<circle color="#000000" cx="40" cy="110" r="2"/>
<text x="28" y="113" font-size="10">W</text>
<circle color="#000000" cx="-40" cy="-80" r="2"/>
<text x="-35" y="-77" font-size="10">A7</text>
<circle color="#000000" cx="-40" cy="-70" r="2"/>
<text x="-35" y="-67" font-size="10">A6</text>
<circle color="#000000" cx="-40" cy="-60" r="2"/>
<text x="-35" y="-57" font-size="10">A5</text>
<circle color="#000000" cx="-40" cy="-50" r="2"/>
<text x="-35" y="-47" font-size="10">A4</text>
<circle color="#000000" cx="-40" cy="-40" r="2"/>
<text x="-35" y="-37" font-size="10">A3</text>
<circle color="#000000" cx="-40" cy="-30" r="2"/>
<text x="-35" y="-27" font-size="10">A2</text>
<circle color="#000000" cx="-40" cy="-20" r="2"/>
<text x="-35" y="-17" font-size="10">A1</text>
<circle color="#000000" cx="-40" cy="-10" r="2"/>
<text x="-35" y="-7" font-size="10">A0</text>
<circle color="#000000" cx="-40" cy="10" r="2"/>
<text x="-35" y="13" font-size="10">B7</text>
<circle color="#000000" cx="-40" cy="20" r="2"/>
<text x="-35" y="23" font-size="10">B6</text>
<circle color="#000000" cx="-40" cy="30" r="2"/>
<text x="-35" y="33" font-size="10">B5</text>
<circle color="#000000" cx="-40" cy="40" r="2"/>
<text x="-35" y="43" font-size="10">B4</text>
<circle color="#000000" cx="-40" cy="50" r="2"/>
<text x="-35" y="53" font-size="10">B3</text>
<circle color="#000000" cx="-40" cy="60" r="2"/>
<text x="-35" y="63" font-size="10">B2</text>
<circle color="#000000" cx="-40" cy="70" r="2"/>
<text x="-35" y="73" font-size="10">B1</text>
<circle color="#000000" cx="-40" cy="80" r="2"/>
<text x="-35" y="83" font-size="10">B0</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

96
addrregister.ts Normal file
View file

@ -0,0 +1,96 @@
// Address Register component for the LogicSimulator used on the 8-bit-computer
// Copyright (C) 2022 Sascha Nitsch
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class AddrRegister extends BaseComponent {
private r = 0;
private R = false;
private W = false;
private CLK = false;
private oldCLK = false;
constructor(simulator: Simulator, id: string, param: BaseComponentParam) {
super(simulator, id, param);
for (let i = 0; i < 8; ++i) {
this.pins.set('A' + (7 - i), new TriState(this, -40, i * 10 - 80));
this.pins.set('B' + (7 - i), new TriState(this, -40, i * 10 + 10));
this.stateMapBool.set('A' + (7 - i), false);
this.stateMapBool.set('B' + (7 - i), false);
}
this.pins.set('R', new TriState(this, 40, 100));
this.pins.set('W', new TriState(this, 40, 110));
this.pins.set('CLK', new TriState(this, 40, 80));
this.pins.set('invCLK', new TriState(this, 40, 90));
for (let i = 0; i < 16; ++i) {
this.pins.set('O' + (15 - i), new TriState(this, 40, i * 10 - 80));
this.stateMapBool.set('O' + (15 - i), false);
}
}
setup(canvas: SVGElement) {
super.doSetup('addrregister', canvas);
}
update(): boolean {
let i;
let value;
// is R set ? then send out to addrbus
if (this.R) {
// which register is selected via R3...R0
value = this.r;
for (i = 0; i < 16; ++i) {
this.getPin('O' + i).setBool((value & (1 << i)) > 0 ? true : false);
}
}
const rising = this.CLK && this.oldCLK === false;
this.oldCLK = this.CLK;
// is W set ? read from bus on raising clock edge
if (this.W && rising) {
this.r =
this.asint(this.getStateBool('A7'), 32768) +
this.asint(this.getStateBool('A6'), 16384) +
this.asint(this.getStateBool('A5'), 8192) +
this.asint(this.getStateBool('A4'), 4096) +
this.asint(this.getStateBool('A3'), 2048) +
this.asint(this.getStateBool('A2'), 1024) +
this.asint(this.getStateBool('A1'), 512) +
this.asint(this.getStateBool('A0'), 256) +
this.asint(this.getStateBool('B7'), 128) +
this.asint(this.getStateBool('B6'), 64) +
this.asint(this.getStateBool('B5'), 32) +
this.asint(this.getStateBool('B4'), 16) +
this.asint(this.getStateBool('B3'), 8) +
this.asint(this.getStateBool('B2'), 4) +
this.asint(this.getStateBool('B1'), 2) +
this.asint(this.getStateBool('B0'), 1);
}
return false;
}
io() {
this.CLK = this.binary(this.getPin('CLK').getAndReset(), true);
this.getPin('invCLK').getAndReset();
this.R = this.binary(this.getPin('R').getAndReset(), true);
this.W = this.binary(this.getPin('W').getAndReset(), true);
for (let i = 0; i < 8; ++i) {
this.stateMapBool.set('A' + i, this.binary(this.getPin('A' + i).getAndReset(), true));
this.stateMapBool.set('B' + i, this.binary(this.getPin('B' + i).getAndReset(), true));
}
for (let i = 0; i < 16; ++i) {
this.stateMapBool.set('O' + i, this.binary(this.getPin('O' + i).getAndReset(), true));
}
}
}

27
chipselect.svg Normal file
View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg">
<g id="root" class="chipselect logicblock">
<rect width="80" height="90" x="-40" y="-45" class="outer" />
<circle color="#000000" cx="40" cy="-35" r="2"/>
<text x="10" y="-32" font-size="10">RAM</text>
<circle color="#000000" cx="40" cy="-25" r="2"/>
<text x="10" y="-22" font-size="10">ROM</text>
<circle color="#000000" cx="-40" cy="-35" r="2"/>
<text x="-35" y="-32" font-size="10">A15</text>
<circle color="#000000" cx="-40" cy="-25" r="2"/>
<text x="-35" y="-22" font-size="10">A14</text>
<circle color="#000000" cx="-40" cy="-15" r="2"/>
<text x="-35" y="-12" font-size="10">A13</text>
<circle color="#000000" cx="-40" cy="-5" r="2"/>
<text x="-35" y="-2" font-size="10">A12</text>
<circle color="#000000" cx="-40" cy="5" r="2"/>
<text x="-35" y="8" font-size="10">A11</text>
<circle color="#000000" cx="-40" cy="15" r="2"/>
<text x="-35" y="18" font-size="10">A10</text>
<circle color="#000000" cx="-40" cy="25" r="2"/>
<text x="-35" y="28" font-size="10">A9</text>
<circle color="#000000" cx="-40" cy="35" r="2"/>
<text x="-35" y="38" font-size="10">A8</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

65
chipselect.ts Normal file
View file

@ -0,0 +1,65 @@
// Chip select component for the LogicSimulator used on the 8-bit-computer
// Copyright (C) 2022 Sascha Nitsch
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class ChipSelect extends BaseComponent {
private addr = 0;
private rom = true;
private ram = true;
constructor(simulator: Simulator, id: string, param: BaseComponentParam) {
super(simulator, id, param);
for (let a = 0; a < 8; ++a) {
this.pins.set('A' + (15 - a), new TriState(this, -40, a * 10 - 35));
}
this.pins.set('rom', new TriState(this, 40, -25));
this.pins.set('ram', new TriState(this, 40, -35));
}
setup(canvas: SVGElement) {
super.doSetup('chipselect', canvas);
}
update(): boolean {
const addr = this.addr;
let changed = false;
if (addr < 0x3fff) {
// ROM
changed ||= this.rom !== false || this.ram !== true;
this.getPin('rom').setBool(false);
this.getPin('ram').setBool(true);
} else if (addr < 0x7fff) {
// RAM
changed ||= this.rom !== false || this.ram !== true;
this.getPin('rom').setBool(true);
this.getPin('ram').setBool(false);
} else {
this.getPin('rom').setBool(true);
this.getPin('ram').setBool(true);
}
return changed;
}
io() {
this.getPin('rom').getAndReset();
this.getPin('ram').getAndReset();
this.addr = 0;
let multi = 256;
for (let i = 8; i < 16; ++i) {
this.addr += this.asint(this.binary(this.getPin('A' + i).getAndReset(), true), multi);
multi <<= 1;
}
}
}

9
dynamicclock.svg Normal file
View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg">
<g id="root" class="dynamicclock logicblock">
<rect width="40" height="40" x="-20" y="-20" class="outer" />
<path d="M 20,0 L 30,0" />
<path d="M -10,5 L -5,5 L -5,-5, L 0,-5, L 5,-5, L5,5, L10,5" />
<text x="-2" y="5"></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 355 B

76
dynamicclock.ts Normal file
View file

@ -0,0 +1,76 @@
// Clock generator component for the LogicSimulator used on the 8-bit-computer
// Copyright (C) 2022 Sascha Nitsch
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
interface DynamicClockParam extends BaseComponentParam {
speed?: string;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class DynamicClock extends BaseComponent {
private q = false;
private clockState = false;
private speed: number;
private input = '';
private speedInput: HTMLInputElement | null = null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private timer: any;
constructor(simulator: Simulator, id: string, param: DynamicClockParam) {
super(simulator, id, param);
this.pins.set('q', new TriState(this, 30, 0));
if (param.speed) {
this.speed = 0;
this.input = param.speed;
} else {
this.speed = 1;
}
}
tick() {
this.clockState = !this.clockState;
this.simulator.tick();
}
setup(canvas: SVGElement) {
super.doSetup('dynamicclock', canvas);
if (this.speed === 0) {
this.speedInput = <HTMLInputElement>document.getElementById(this.input);
if (this.speedInput) {
this.speedInput.addEventListener('change', this.changeSpeed.bind(this));
this.speed = parseFloat(this.speedInput.value);
this.timer = setInterval(this.tick.bind(this), 500 / this.speed);
}
} else {
this.timer = setInterval(this.tick.bind(this), 500 / this.speed);
}
}
update(): boolean {
const oldstate = this.q;
this.q = this.clockState;
this.getPin('q').setBool(this.q);
return oldstate !== this.q;
}
changeSpeed() {
if (!this.speedInput) return;
this.speed = parseFloat(this.speedInput.value);
clearInterval(this.timer);
this.timer = setInterval(this.tick.bind(this), 500 / this.speed);
}
close() {
clearInterval(this.timer);
}
}

61
eightbitalu.svg Normal file
View file

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg">
<g id="root" class="eightbitalu logicblock">
<rect width="80" height="180" x="-40" y="-90" class="outer" />
<circle color="#000000" cx="40" cy="-70" r="2"/>
<text x="25" y="-67" font-size="10">D7</text>
<circle color="#000000" cx="40" cy="-50" r="2"/>
<text x="25" y="-47" font-size="10">D6</text>
<circle color="#000000" cx="40" cy="-30" r="2"/>
<text x="25" y="-27" font-size="10">D5</text>
<circle color="#000000" cx="40" cy="-10" r="2"/>
<text x="25" y="-7" font-size="10">D4</text>
<circle color="#000000" cx="40" cy="10" r="2"/>
<text x="25" y="13" font-size="10">D3</text>
<circle color="#000000" cx="40" cy="30" r="2"/>
<text x="25" y="33" font-size="10">D2</text>
<circle color="#000000" cx="40" cy="50" r="2"/>
<text x="25" y="53" font-size="10">D1</text>
<circle color="#000000" cx="40" cy="70" r="2"/>
<text x="25" y="73" font-size="10">D0</text>
<circle color="#000000" cx="-40" cy="-80" r="2"/>
<text x="-35" y="-77" font-size="10">A7</text>
<circle color="#000000" cx="-40" cy="-70" r="2"/>
<text x="-35" y="-67" font-size="10">A6</text>
<circle color="#000000" cx="-40" cy="-60" r="2"/>
<text x="-35" y="-57" font-size="10">A5</text>
<circle color="#000000" cx="-40" cy="-50" r="2"/>
<text x="-35" y="-47" font-size="10">A4</text>
<circle color="#000000" cx="-40" cy="-40" r="2"/>
<text x="-35" y="-37" font-size="10">A3</text>
<circle color="#000000" cx="-40" cy="-30" r="2"/>
<text x="-35" y="-27" font-size="10">A2</text>
<circle color="#000000" cx="-40" cy="-20" r="2"/>
<text x="-35" y="-17" font-size="10">A1</text>
<circle color="#000000" cx="-40" cy="-10" r="2"/>
<text x="-35" y="-7" font-size="10">A0</text>
<circle color="#000000" cx="-40" cy="10" r="2"/>
<text x="-35" y="13" font-size="10">B7</text>
<circle color="#000000" cx="-40" cy="20" r="2"/>
<text x="-35" y="23" font-size="10">B6</text>
<circle color="#000000" cx="-40" cy="30" r="2"/>
<text x="-35" y="33" font-size="10">B5</text>
<circle color="#000000" cx="-40" cy="40" r="2"/>
<text x="-35" y="43" font-size="10">B4</text>
<circle color="#000000" cx="-40" cy="50" r="2"/>
<text x="-35" y="53" font-size="10">B3</text>
<circle color="#000000" cx="-40" cy="60" r="2"/>
<text x="-35" y="63" font-size="10">B2</text>
<circle color="#000000" cx="-40" cy="70" r="2"/>
<text x="-35" y="73" font-size="10">B1</text>
<circle color="#000000" cx="-40" cy="80" r="2"/>
<text x="-35" y="83" font-size="10">B0</text>
<circle color="#000000" cx="-15" cy="90" r="2"/>
<text x="-20" y="86" font-size="10">SUB</text>
<circle color="#000000" cx="20" cy="90" r="2"/>
<text x="5" y="86" font-size="10">WRITE</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

83
eightbitalu.ts Normal file
View file

@ -0,0 +1,83 @@
// Breadboard component for the LogicSimulator used on the 8-bit-computer
// Copyright (C) 2022 Sascha Nitsch
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class EightBitALU extends BaseComponent {
private write: boolean | string;
private sub: boolean | string;
private ret: number;
private a = 0;
private b = 0;
private r = 0;
constructor(simulator: Simulator, id: string, param: BaseComponentParam) {
super(simulator, id, param);
this.pins.set('sub', new TriState(this, -15, 90));
this.sub = 'float';
this.pins.set('write', new TriState(this, 20, 90));
this.write = 'float';
this.ret = 0;
for (let i = 0; i < 8; ++i) {
this.pins.set('A' + (7 - i), new TriState(this, -40, i * 10 - 80));
this.pins.set('B' + (7 - i), new TriState(this, -40, i * 10 + 10));
this.pins.set('D' + (7 - i), new TriState(this, 40, i * 20 - 70));
this.stateMapBool.set('A' + (7 - i), true);
this.stateMapBool.set('B' + (7 - i), true);
this.stateMapBool.set('D' + (7 - i), true);
}
}
setup(canvas: SVGElement) {
super.doSetup('eightbitalu', canvas);
}
io() {
for (let i = 0; i < 8; ++i) {
this.stateMapBool.set('A' + i, this.binary(this.getPin('A' + i).getAndReset(), true));
this.stateMapBool.set('B' + i, this.binary(this.getPin('B' + i).getAndReset(), true));
this.stateMapBool.set('D' + i, this.binary(this.getPin('D' + i).getAndReset(), true));
}
this.sub = this.binary(this.getPin('sub').getAndReset(), true);
this.write = this.binary(this.getPin('write').getAndReset(), true);
this.a =
this.asint(this.getStateBool('A7'), 128) +
this.asint(this.getStateBool('A6'), 64) +
this.asint(this.getStateBool('A5'), 32) +
this.asint(this.getStateBool('A4'), 16) +
this.asint(this.getStateBool('A3'), 8) +
this.asint(this.getStateBool('A2'), 4) +
this.asint(this.getStateBool('A1'), 2) +
this.asint(this.getStateBool('A0'), 1);
this.b =
this.asint(this.getStateBool('B7'), 128) +
this.asint(this.getStateBool('B6'), 64) +
this.asint(this.getStateBool('B5'), 32) +
this.asint(this.getStateBool('B4'), 16) +
this.asint(this.getStateBool('B3'), 8) +
this.asint(this.getStateBool('B2'), 4) +
this.asint(this.getStateBool('B1'), 2) +
this.asint(this.getStateBool('B0'), 1);
}
update(): boolean {
const oldret = this.ret;
this.ret = (this.sub ? this.a - this.b : this.a + this.b) & 0xff;
for (let i = 0; i < 8; ++i) {
const v = (this.ret >> i) & 1 ? WireState.high : WireState.low;
this.getPin('D' + i).setState(this.write ? v : WireState.float);
}
return oldret !== this.ret;
}
}

19
eightbitclock.svg Normal file
View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg">
<g id="root" class="eightbitclock logicblock">
<rect width="60" height="110" x="-30" y="-55" class="outer" />
<path d="M 20,-20 l 10,0" />
<path d="M 20,20 l 10,0" />
<path d="M -20,-35 l 10,0 l 0,-10, l 10,0, l 0,10, l 10,0" />
<g class="auto">
<text x="-22" y="-17" class="label"></text>
<rect x="-20" y="-15" width="20" height="20" class="outer"/>
<text x="-16" y="-1" class="inner">0</text>
</g>
<g class="manual">
<text x="-22" y="28 " class="label"></text>
<rect x="-20" y="30" width="20" height="20" class="outer"/>
<text x="-16" y="44" class="inner">0</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 752 B

142
eightbitclock.ts Normal file
View file

@ -0,0 +1,142 @@
// Clock generation component for the LogicSimulator used on the 8-bit-computer
// Copyright (C) 2022 Sascha Nitsch
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function EightBitClockInit() {
interface EightBitClockText {
auto: string;
manual: string;
}
interface EightBitClockParam extends BaseComponentParam {
speed?: string;
mode?: string;
auto?: string;
manual?: string;
}
class EightBitClock extends LogicBase {
private clockState: boolean;
private speed: number;
private input: string;
private runAuto: boolean;
private texts: EightBitClockText;
private manual: NodeListOf<Element> | undefined;
private speedInput: HTMLInputElement | null = null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private timer: any = undefined;
private auto: NodeListOf<Element> | undefined;
private CLK = false;
constructor(simulator: Simulator, id: string, param: EightBitClockParam) {
super(simulator, id, param);
this.pins.set('CLK', new TriState(this, 30, -20));
this.pins.set('invCLK', new TriState(this, 30, 20));
this.clockState = false;
if (param.speed) {
this.speed = 0;
this.input = param.speed;
} else {
this.speed = 1;
this.input = 'undefined';
}
this.runAuto = param.mode ? param.mode === 'auto' : false;
this.texts = {
auto: param.auto ? param.auto : 'auto',
manual: param.manual ? param.manual : 'manual',
};
this.auto = undefined;
this.manual = undefined;
}
tick(): void {
this.clockState = !this.clockState;
if (this.manual) {
this.manual[0].textContent = this.clockState ? '1' : '0';
}
this.simulator.tick();
}
setup(canvas: SVGElement) {
super.doSetup('eightbitclock', canvas);
if (this.speed === 0) {
this.speedInput = <HTMLInputElement | null>document.getElementById(this.input);
if (this.speedInput) {
this.speedInput.addEventListener('change', this.changeSpeed.bind(this));
this.speed = parseFloat(this.speedInput.value);
if (this.runAuto) {
this.timer = setInterval(this.tick.bind(this), 500 / this.speed);
}
}
} else {
this.timer = setInterval(this.tick.bind(this), 500 / this.speed);
}
if (this.element) {
const gAuto = this.element.querySelectorAll('g.auto')[0];
this.auto = gAuto.querySelectorAll('text.inner');
gAuto.querySelectorAll('.label')[0].innerHTML = this.texts.auto;
gAuto.addEventListener('mousedown', this.toggleAuto.bind(this));
const gManual = this.element.querySelectorAll('g.manual')[0];
this.manual = gManual.querySelectorAll('text.inner');
gManual.querySelectorAll('.label')[0].innerHTML = this.texts.manual;
gManual.addEventListener('mousedown', this.toggleManual.bind(this));
}
}
update() {
const oldstate = this.CLK;
this.CLK = this.clockState;
this.getPin('CLK').setBool(this.clockState);
this.getPin('invCLK').setBool(!this.clockState);
return oldstate !== this.clockState;
}
changeSpeed() {
if (this.speedInput) {
this.speed = parseFloat(this.speedInput.value);
}
if (this.runAuto) {
clearInterval(this.timer);
this.timer = setInterval(this.tick.bind(this), 500 / this.speed);
}
}
close() {
clearInterval(this.timer);
}
toggleAuto(e: Event) {
e.preventDefault();
if (this.runAuto) {
clearInterval(this.timer);
} else {
this.timer = setInterval(this.tick.bind(this), 500 / this.speed);
}
this.runAuto = !this.runAuto;
if (this.auto) {
this.auto[0].textContent = this.runAuto ? '1' : '0';
}
}
toggleManual(e: Event) {
e.preventDefault();
this.tick();
}
}
window.EightBitClock = EightBitClock;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function EightBitClockDepends() {
return 'LogicBase';
}

10
logicrisingedge.svg Normal file
View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg">
<g id="root" class="raisingedge logicblock">
<rect width="40" height="40" x="-20" y="-20" class="outer" />
<path d="M -30.0, 0 L -20, 0" />
<path d="M 25,0 L 30,0" />
<path d="M -5,5 L 0,5 L 0,-5, L 5,-5" />
<text x="-2" y="5"></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 367 B

55
logicrisingedge.ts Normal file
View file

@ -0,0 +1,55 @@
// Logic Rising Edge component for the LogicSimulator used on the 8-bit-Computer
// Copyright (C) 2022 Sascha Nitsch
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
interface LogicRisingEdgeParam extends BaseComponentParam {
delay?: number;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class LogicRisingEdge extends BaseComponent {
private a = false;
private olda = false;
private q = false;
private delay: number;
private activeDelay = 0;
constructor(simulator: Simulator, id: string, param: LogicRisingEdgeParam) {
super(simulator, id, param);
this.pins.set('a', new TriState(this, -30, 0));
this.pins.set('q', new TriState(this, 30, 0));
this.delay = param.delay || 0;
}
setup(canvas: SVGElement) {
super.doSetup('logicraisingedge', canvas);
}
io() {
this.a = this.binary(this.getPin('a').getAndReset(), true);
}
update(): boolean {
const oldstate = this.q;
if (this.olda === false && this.a === true) {
this.activeDelay = this.delay;
}
this.q = this.activeDelay > 0;
this.getPin('q').setBool(this.q);
this.olda = this.a;
if (this.activeDelay > 0) {
this.activeDelay--;
}
return oldstate !== this.q || this.q === true;
}
}

99
memory.svg Normal file
View file

@ -0,0 +1,99 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg">
<g id="root" class="memory logicblock">
<rect width="80" height="170" x="-40" y="-85" class="outer" />
<circle color="#000000" cx="40" cy="-75" r="2"/>
<text x="25" y="-72" font-size="10">D7</text>
<circle color="#000000" cx="40" cy="-65" r="2"/>
<text x="25" y="-62" font-size="10">D6</text>
<circle color="#000000" cx="40" cy="-55" r="2"/>
<text x="25" y="-52" font-size="10">D5</text>
<circle color="#000000" cx="40" cy="-45" r="2"/>
<text x="25" y="-42" font-size="10">D4</text>
<circle color="#000000" cx="40" cy="-35" r="2"/>
<text x="25" y="-32" font-size="10">D3</text>
<circle color="#000000" cx="40" cy="-25" r="2"/>
<text x="25" y="-22" font-size="10">D2</text>
<circle color="#000000" cx="40" cy="-15" r="2"/>
<text x="25" y="-12" font-size="10">D1</text>
<circle color="#000000" cx="40" cy="-5" r="2"/>
<text x="25" y="-2" font-size="10">D0</text>
<circle color="#000000" cx="40" cy="5" r="2"/>
<text x="17" y="8" font-size="10">CLK</text>
<circle color="#000000" cx="40" cy="25" r="2"/>
<text x="31" y="28" font-size="10">R</text>
<g class="w">
<circle color="#000000" cx="40" cy="35" r="2"/>
<text x="28" y="38" font-size="10">W</text>
</g>
<circle color="#000000" cx="40" cy="45" r="2"/>
<path d="M24,40 h 14"/>
<text x="24" y="48" font-size="10">EN</text>
<g class="a15">
<circle color="#000000" cx="-40" cy="-75" r="2"/>
<text x="-35" y="-72" font-size="10">A15</text>
</g>
<g class="a14">
<circle color="#000000" cx="-40" cy="-65" r="2"/>
<text x="-35" y="-62" font-size="10">A14</text>
</g>
<g class="a13">
<circle color="#000000" cx="-40" cy="-55" r="2"/>
<text x="-35" y="-52" font-size="10">A13</text>
</g>
<g class="a12">
<circle color="#000000" cx="-40" cy="-45" r="2"/>
<text x="-35" y="-42" font-size="10">A12</text>
</g>
<g class="a11">
<circle color="#000000" cx="-40" cy="-35" r="2"/>
<text x="-35" y="-32" font-size="10">A11</text>
</g>
<g class="a10">
<circle color="#000000" cx="-40" cy="-25" r="2"/>
<text x="-35" y="-22" font-size="10">A10</text>
</g>
<g class="a9">
<circle color="#000000" cx="-40" cy="-15" r="2"/>
<text x="-35" y="-12" font-size="10">A9</text>
</g>
<g class="a8">
<circle color="#000000" cx="-40" cy="-5" r="2"/>
<text x="-35" y="-2" font-size="10">A8</text>
</g>
<g class="a7">
<circle color="#000000" cx="-40" cy="5" r="2"/>
<text x="-35" y="8" font-size="10">A7</text>
</g>
<g class="a6">
<circle color="#000000" cx="-40" cy="15" r="2"/>
<text x="-35" y="18" font-size="10">A6</text>
</g>
<g class="a5">
<circle color="#000000" cx="-40" cy="25" r="2"/>
<text x="-35" y="28" font-size="10">A5</text>
</g>
<g class="a4">
<circle color="#000000" cx="-40" cy="35" r="2"/>
<text x="-35" y="38" font-size="10">A4</text>
</g>
<g class="a3">
<circle color="#000000" cx="-40" cy="45" r="2"/>
<text x="-35" y="48" font-size="10">A3</text>
</g>
<g class="a2">
<circle color="#000000" cx="-40" cy="55" r="2"/>
<text x="-35" y="58" font-size="10">A2</text>
</g>
<g class="a1">
<circle color="#000000" cx="-40" cy="65" r="2"/>
<text x="-35" y="68" font-size="10">A1</text>
</g>
<g class="a0">
<circle color="#000000" cx="-40" cy="75" r="2"/>
<text x="-35" y="78" font-size="10">A0</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

206
memory.ts Normal file
View file

@ -0,0 +1,206 @@
// Memory RAM and ROM component for the LogicSimulator used on the 8-bit-computer
// Copyright (C) 2022 Sascha Nitsch
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
interface MemoryParam extends BaseComponentParam {
type: string;
size: number;
source: string;
content?: string;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class Memory extends BaseComponent {
private writeable: boolean;
private size: number;
private source: string;
private r: number[] = [];
private W = false;
private R = false;
private D = 0;
private endaddr: number;
private CLK = false;
private oldCLK = false;
private invEnable = true;
private memory: HTMLTextAreaElement | null = null;
private addr = 0;
constructor(simulator: Simulator, id: string, param: MemoryParam) {
super(simulator, id, param);
this.writeable = param.type === 'RAM';
this.size = param.size;
this.source = param.source;
if (param.content === null) {
for (let r = 0; r < this.size; ++r) {
this.r[r] = 0;
}
}
if (param.content === 'rising') {
for (let r = 0; r < this.size; ++r) {
this.r[r] = r & 255;
}
}
if (param.content === 'random') {
for (let r = 0; r < this.size; ++r) {
this.r[r] = Math.round(Math.random() * 255);
}
}
this.endaddr = 15;
let threshold = 65536;
// disable addr lines if needed
while (this.size < threshold) {
--this.endaddr;
threshold = threshold / 2;
}
for (let a = 0; a < 8; ++a) {
this.pins.set('D' + (7 - a), new TriState(this, 40, a * 10 - 75));
}
this.pins.set('R', new TriState(this, 40, 25));
if (this.writeable) {
this.pins.set('W', new TriState(this, 40, 35));
}
this.pins.set('CLK', new TriState(this, 40, 5));
this.pins.set('invEnable', new TriState(this, 40, 45));
for (let i = 0; i <= this.endaddr; ++i) {
this.pins.set('A' + (this.endaddr - i), new TriState(this, -40, i * 10 - 75));
}
}
setup(canvas: SVGElement) {
super.doSetup('memory', canvas);
if (this.element === null) {
return;
}
const offset = -(15 - this.endaddr) * 10;
for (let i = 0; i < 16; ++i) {
const e = this.element.getElementsByClassName('a' + i);
if (i <= this.endaddr) {
// move up
if (offset !== 0) {
e[0].setAttribute('transform', 'translate(0,' + offset + ')');
}
} else {
e[0].classList.add('hidden');
}
}
// resize box
const height = Math.max(170 + offset, 140);
this.element.getElementsByClassName('outer')[0].setAttribute('height', height.toString());
if (!this.writeable) {
this.element.getElementsByClassName('w')[0].classList.add('hidden');
}
this.memory = <HTMLTextAreaElement>document.getElementById(this.source);
const memorysave = document.getElementById(this.source + 'save');
if (memorysave) {
memorysave.addEventListener('mousedown', this.updateMem.bind(this));
}
this.updateText();
}
updateMem() {
if (this.memory === null) return;
const txt = this.memory.value.split('\n');
let addr = 0;
for (let i = 0; i < txt.length - 1; ++i) {
const cells = txt[i].split(' ');
for (let j = 0; j < 36; ++j) {
if (j % 9 === 0) continue;
this.r[addr] = parseInt(cells[j], 16);
++addr;
}
}
this.simulator.manualtick();
}
update(): boolean {
// is R set ? then send out to databus
if (this.R && this.invEnable === false) {
// which address is selected
const value = this.r[this.addr];
for (let i = 0; i < 8; ++i) {
this.getPin('D' + i).setBool((value & (1 << i)) > 0 ? true : false);
}
}
const rising = this.CLK && this.oldCLK === false;
this.oldCLK = this.CLK;
// is W set ? read from bus on raising clock edge
if (this.writeable && this.W && this.invEnable === false && rising) {
this.r[this.addr] = this.D;
// update text input
this.updateText();
}
return false;
}
hex(d: number, padding: number) {
let hex = d.toString(16).toUpperCase();
while (hex.length < padding) {
hex = '0' + hex;
}
return hex;
}
updateText() {
let txt = '';
for (let i = 0; i < this.size; ++i) {
if (i % 32 !== 0) {
txt += ' ';
if (i % 8 === 0) {
txt += '0x' + this.hex(i, 4) + ': ';
}
} else {
txt += '0x' + this.hex(i, 4) + ': ';
}
txt += (this.r[i] >> 4).toString(16) + (this.r[i] & 15).toString(16);
if (i % 32 === 31) {
txt += '\n';
}
}
if (this.memory) {
this.memory.value = txt;
}
}
io() {
this.addr = 0;
if (this.endaddr >= 15) this.addr += this.asint(this.binary(this.getPin('A15').getAndReset(), true), 32768);
if (this.endaddr >= 14) this.addr += this.asint(this.binary(this.getPin('A14').getAndReset(), true), 16384);
if (this.endaddr >= 13) this.addr += this.asint(this.binary(this.getPin('A13').getAndReset(), true), 8192);
if (this.endaddr >= 12) this.addr += this.asint(this.binary(this.getPin('A12').getAndReset(), true), 4096);
if (this.endaddr >= 11) this.addr += this.asint(this.binary(this.getPin('A11').getAndReset(), true), 2048);
if (this.endaddr >= 10) this.addr += this.asint(this.binary(this.getPin('A10').getAndReset(), true), 1024);
if (this.endaddr >= 9) this.addr += this.asint(this.binary(this.getPin('A9').getAndReset(), true), 512);
if (this.endaddr >= 8) this.addr += this.asint(this.binary(this.getPin('A8').getAndReset(), true), 256);
if (this.endaddr >= 7) this.addr += this.asint(this.binary(this.getPin('A7').getAndReset(), true), 128);
if (this.endaddr >= 6) this.addr += this.asint(this.binary(this.getPin('A6').getAndReset(), true), 64);
if (this.endaddr >= 5) this.addr += this.asint(this.binary(this.getPin('A5').getAndReset(), true), 32);
if (this.endaddr >= 4) this.addr += this.asint(this.binary(this.getPin('A4').getAndReset(), true), 16);
if (this.endaddr >= 3) this.addr += this.asint(this.binary(this.getPin('A3').getAndReset(), true), 8);
if (this.endaddr >= 2) this.addr += this.asint(this.binary(this.getPin('A2').getAndReset(), true), 4);
if (this.endaddr >= 1) this.addr += this.asint(this.binary(this.getPin('A1').getAndReset(), true), 2);
if (this.endaddr >= 0) this.addr += this.asint(this.binary(this.getPin('A0').getAndReset(), true), 1);
this.CLK = this.binary(this.getPin('CLK').getAndReset(), true);
this.R = this.binary(this.getPin('R').getAndReset(), true);
this.invEnable = this.binary(this.getPin('invEnable').getAndReset(), true);
if (this.writeable) {
this.W = this.binary(this.getPin('W').getAndReset(), true);
}
this.D = 0;
for (let i = 0; i < 8; ++i) {
this.D += this.asint(this.binary(this.getPin('D' + i).getAndReset(), true), 1 << i);
}
}
}

103
multiregister.svg Normal file
View file

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg">
<g id="root" class="multiregister logicblock">
<rect width="80" height="270" x="-40" y="-90" class="outer" />
<circle color="#000000" cx="40" cy="-80" r="2"/>
<text x="25" y="-77" font-size="10">D7</text>
<circle color="#000000" cx="40" cy="-70" r="2"/>
<text x="25" y="-67" font-size="10">D6</text>
<circle color="#000000" cx="40" cy="-60" r="2"/>
<text x="25" y="-57" font-size="10">D5</text>
<circle color="#000000" cx="40" cy="-50" r="2"/>
<text x="25" y="-47" font-size="10">D4</text>
<circle color="#000000" cx="40" cy="-40" r="2"/>
<text x="25" y="-37" font-size="10">D3</text>
<circle color="#000000" cx="40" cy="-30" r="2"/>
<text x="25" y="-27" font-size="10">D2</text>
<circle color="#000000" cx="40" cy="-20" r="2"/>
<text x="25" y="-17" font-size="10">D1</text>
<circle color="#000000" cx="40" cy="-10" r="2"/>
<text x="25" y="-7" font-size="10">D0</text>
<circle color="#000000" cx="40" cy="0" r="2"/>
<text x="17" y="3" font-size="10">CLK</text>
<circle color="#000000" cx="40" cy="10" r="2"/>
<path d="M17,5 h 20"/>
<text x="17" y="13" font-size="10">CLK</text>
<circle color="#000000" cx="40" cy="30" r="2"/>
<text x="25" y="33" font-size="10">R3</text>
<circle color="#000000" cx="40" cy="40" r="2"/>
<text x="25" y="43" font-size="10">R2</text>
<circle color="#000000" cx="40" cy="50" r="2"/>
<text x="25" y="53" font-size="10">R1</text>
<circle color="#000000" cx="40" cy="60" r="2"/>
<text x="25" y="63" font-size="10">R0</text>
<circle color="#000000" cx="40" cy="70" r="2"/>
<text x="16" y="73" font-size="10">RON</text>
<circle color="#000000" cx="40" cy="80" r="2"/>
<text x="22" y="83" font-size="10">W3</text>
<circle color="#000000" cx="40" cy="90" r="2"/>
<text x="22" y="93" font-size="10">W2</text>
<circle color="#000000" cx="40" cy="100" r="2"/>
<text x="22" y="103" font-size="10">W1</text>
<circle color="#000000" cx="40" cy="110" r="2"/>
<text x="22" y="113" font-size="10">W0</text>
<circle color="#000000" cx="40" cy="120" r="2"/>
<text x="13" y="123" font-size="10">WON</text>
<circle color="#000000" cx="-40" cy="-80" r="2"/>
<text x="-35" y="-77" font-size="10">A7</text>
<circle color="#000000" cx="-40" cy="-70" r="2"/>
<text x="-35" y="-67" font-size="10">A6</text>
<circle color="#000000" cx="-40" cy="-60" r="2"/>
<text x="-35" y="-57" font-size="10">A5</text>
<circle color="#000000" cx="-40" cy="-50" r="2"/>
<text x="-35" y="-47" font-size="10">A4</text>
<circle color="#000000" cx="-40" cy="-40" r="2"/>
<text x="-35" y="-37" font-size="10">A3</text>
<circle color="#000000" cx="-40" cy="-30" r="2"/>
<text x="-35" y="-27" font-size="10">A2</text>
<circle color="#000000" cx="-40" cy="-20" r="2"/>
<text x="-35" y="-17" font-size="10">A1</text>
<circle color="#000000" cx="-40" cy="-10" r="2"/>
<text x="-35" y="-7" font-size="10">A0</text>
<circle color="#000000" cx="-40" cy="10" r="2"/>
<text x="-35" y="13" font-size="10">B7</text>
<circle color="#000000" cx="-40" cy="20" r="2"/>
<text x="-35" y="23" font-size="10">B6</text>
<circle color="#000000" cx="-40" cy="30" r="2"/>
<text x="-35" y="33" font-size="10">B5</text>
<circle color="#000000" cx="-40" cy="40" r="2"/>
<text x="-35" y="43" font-size="10">B4</text>
<circle color="#000000" cx="-40" cy="50" r="2"/>
<text x="-35" y="53" font-size="10">B3</text>
<circle color="#000000" cx="-40" cy="60" r="2"/>
<text x="-35" y="63" font-size="10">B2</text>
<circle color="#000000" cx="-40" cy="70" r="2"/>
<text x="-35" y="73" font-size="10">B1</text>
<circle color="#000000" cx="-40" cy="80" r="2"/>
<text x="-35" y="83" font-size="10">B0</text>
<circle color="#000000" cx="-40" cy="100" r="2"/>
<text x="-35" y="103" font-size="10">ALU_A3</text>
<circle color="#000000" cx="-40" cy="110" r="2"/>
<text x="-35" y="113" font-size="10">ALU_A2</text>
<circle color="#000000" cx="-40" cy="120" r="2"/>
<text x="-35" y="123" font-size="10">ALU_A1</text>
<circle color="#000000" cx="-40" cy="130" r="2"/>
<text x="-35" y="133" font-size="10">ALU_A0</text>
<circle color="#000000" cx="-40" cy="140" r="2"/>
<text x="-35" y="143" font-size="10">ALU_B3</text>
<circle color="#000000" cx="-40" cy="150" r="2"/>
<text x="-35" y="153" font-size="10">ALU_B2</text>
<circle color="#000000" cx="-40" cy="160" r="2"/>
<text x="-35" y="163" font-size="10">ALU_B1</text>
<circle color="#000000" cx="-40" cy="170" r="2"/>
<text x="-35" y="173" font-size="10">ALU_B0</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.7 KiB

147
multiregister.ts Normal file
View file

@ -0,0 +1,147 @@
// Multiple register component for the LogicSimulator used by the 8-bit-computer
// Copyright (C) 2022 Sascha Nitsch
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
interface MultiRegisterParam extends BaseComponentParam {
count?: number;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function MultiRegisterInit() {
class MultiRegister extends LogicBase {
private regcount: number;
private r: number[];
private oldCLK: boolean;
private CLK: boolean;
private RON: boolean;
private WON: boolean;
constructor(simulator: Simulator, id: string, param: MultiRegisterParam) {
super(simulator, id, param);
this.regcount = param.count || 1;
this.r = [];
for (let a = 0; a < 4; ++a) {
this.pins.set('R' + (3 - a), new TriState(this, 40, a * 10 + 30));
this.pins.set('W' + (3 - a), new TriState(this, 40, a * 10 + 80));
this.pins.set('ALU_A' + (3 - a), new TriState(this, -40, a * 10 + 100));
this.pins.set('ALU_B' + (3 - a), new TriState(this, -40, a * 10 + 140));
}
this.pins.set('RON', new TriState(this, 40, 70));
this.pins.set('WON', new TriState(this, 40, 120));
this.pins.set('CLK', new TriState(this, 40, 0, undefined, { id: 'CLK' }));
this.pins.set('invCLK', new TriState(this, 40, 10));
for (let i = 0; i < 8; ++i) {
this.pins.set('D' + (7 - i), new TriState(this, 40, i * 10 - 80));
this.pins.set('A' + (7 - i), new TriState(this, -40, i * 10 - 80));
this.pins.set('B' + (7 - i), new TriState(this, -40, i * 10 + 10));
}
for (let b = 0; b < this.regcount; ++b) {
this.r[b] = 0;
}
this.oldCLK = false;
this.CLK = false;
this.RON = false;
this.WON = false;
}
setup(canvas: SVGElement) {
super.doSetup('multiregister', canvas);
}
update(): boolean {
let i;
let r;
let value;
// is R_ON set ? then send out to databus
if (this.RON) {
// which register is selected via R3...R0
r =
this.asint(this.getStateBool('R3'), 8) +
this.asint(this.getStateBool('R2'), 4) +
this.asint(this.getStateBool('R1'), 2) +
this.asint(this.getStateBool('R0'), 1);
value = this.r[r];
for (i = 0; i < 8; ++i) {
this.getPin('D' + i).setBool((value & (1 << i)) > 0 ? true : false);
}
}
const rising = this.CLK && this.oldCLK === false;
this.oldCLK = this.CLK;
// is W_ON set ? read from bus on raising clock edge
if (this.WON && rising) {
r =
this.asint(this.getStateBool('W3'), 8) +
this.asint(this.getStateBool('W2'), 4) +
this.asint(this.getStateBool('W1'), 2) +
this.asint(this.getStateBool('W0'), 1);
value =
this.asint(this.getStateBool('D7'), 128) +
this.asint(this.getStateBool('D6'), 64) +
this.asint(this.getStateBool('D5'), 32) +
this.asint(this.getStateBool('D4'), 16) +
this.asint(this.getStateBool('D3'), 8) +
this.asint(this.getStateBool('D2'), 4) +
this.asint(this.getStateBool('D1'), 2) +
this.asint(this.getStateBool('D0'), 1);
this.r[r] = value;
}
// output to alu A
const alu_a =
this.asint(this.getStateBool('ALU_A3'), 8) +
this.asint(this.getStateBool('ALU_A2'), 4) +
this.asint(this.getStateBool('ALU_A1'), 2) +
this.asint(this.getStateBool('ALU_A0'), 1);
//console.log("Alu A set to", alu_a);
value = this.r[alu_a];
for (i = 0; i < 8; ++i) {
this.getPin('A' + i).setBool((value & (1 << i)) > 0 ? true : false);
}
// output to alu B
const alu_b =
this.asint(this.getStateBool('ALU_B3'), 8) +
this.asint(this.getStateBool('ALU_B2'), 4) +
this.asint(this.getStateBool('ALU_B1'), 2) +
this.asint(this.getStateBool('ALU_B0'), 1);
value = this.r[alu_b];
for (i = 0; i < 8; ++i) {
this.getPin('B' + i).setBool((value & (1 << i)) > 0 ? true : false);
}
return false;
}
io() {
this.CLK = this.binary(this.getPin('CLK').getAndReset(), false);
this.getPin('invCLK').getAndReset();
this.RON = this.binary(this.getPin('RON').getAndReset(), false);
this.WON = this.binary(this.getPin('WON').getAndReset(), false);
for (let i = 0; i < 8; ++i) {
this.stateMapBool.set('D' + i, this.binary(this.getPin('D' + i).getAndReset(), true));
this.stateMapBool.set('A' + i, this.binary(this.getPin('A' + i).getAndReset(), true));
this.stateMapBool.set('B' + i, this.binary(this.getPin('B' + i).getAndReset(), true));
}
for (let a = 0; a < 4; ++a) {
this.stateMapBool.set('R' + a, this.binary(this.getPin('R' + a).getAndReset(), true));
this.stateMapBool.set('W' + a, this.binary(this.getPin('W' + a).getAndReset(), true));
this.stateMapBool.set('ALU_A' + a, this.binary(this.getPin('ALU_A' + a).getAndReset(), true));
this.stateMapBool.set('ALU_B' + a, this.binary(this.getPin('ALU_B' + a).getAndReset(), true));
}
}
}
window.MultiRegister = MultiRegister;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function MultiRegisterDepends() {
return 'LogicBase';
}