8-bit-computer/multiregister.ts

148 lines
5.8 KiB
TypeScript
Raw Permalink Normal View History

2022-07-21 19:55:40 +02:00
// 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';
}