initial import
84
addrregister.svg
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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';
|
||||
}
|