cardiograph-computer/src/sketch.cpu.js

198 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* CPU sketch */
class CPU {
constructor () {
this.reset();
}
IP = 0;
A = 0;
flags = 0b00000000;
instruction = 0x00;
operand = 0x00;
//What do I want for interrupts…?
// interruptRequest = 0;
// TODO: can it be a simple setup with fixed instruction cycle length pls?
_instructionCycleStep = 0;
_decodedOp = {};
_calculatedIP = 0;
tickClock () {
console.log('cpu tick');
if (connections.cpuWait) return false;
switch (this._instructionCycleStep) {
// Fetch - instruction
case 0:
// initiate read
connections.addressBus = this.IP;
connections.memoryReadSignal = 1;
this._calculatedIP += 2;
break;
case 1:
// complete read
connections.memoryReadSignal = 0;
this.instruction = connections.dataBus;
break;
// Fetch - operand
case 2:
// initiate read
connections.addressBus = this.IP;
connections.memoryReadSignal = 1;
break;
case 3:
// complete read
connections.memoryReadSignal = 0;
this.operand = connections.dataBus;
break;
// Decode
case 4:
// decode
this._decode();
break;
// Execute
case 5:
this._ops[this._decodedOp]();
break;
case 4:
// execute more
break;
}
this._instructionCycleStep = (this._instructionCycleStep + 1) % 4;
}
reset () {
this.IP = 0xFE;
this.A = 0;
this.flags = 0b00000000;
connections.dataBus = 0b00000000;
this._instructionCycleStep = 0;
this.debug.running = true;
}
_decode (instruction) {
/*
// gg aa iiii
let group = 0b11000000 & instruction;
let mode = 0b00110000 & instruction;
let instr = 0b00001111 & instruction;
console.log(group, mode, instr);
*/
let mode = (0b00110000 & instruction) === 16 ? 'indirect' : 'direct';
const instrs = {
0x00 : 'END',
0x01 : 'NOP',
0x50 : 'STO_indirect',
0x51 : 'LDA_indirect',
0x52 : 'ADD_indirect',
0x53 : 'SUB_indirect',
0x54 : 'HOP_indirect',
0x55 : 'JMP_indirect',
0x56 : 'FTG_indirect',
0x57 : 'FHP_indirect',
0x60 : 'STO_direct',
0x61 : 'LDA_direct',
0x62 : 'ADD_direct',
0x63 : 'SUB_direct',
0x64 : 'HOP_direct',
0x65 : 'JMP_direct',
0x66 : 'FTG_direct',
0x67 : 'FHP_direct',
};
// return { instruction: instrs[instruction], mode: mode };
this._decodedOp = instruction;
}
_ops = {
JMP_direct: (lit) => {
this.debug.currentMnemonic = 'JMP lit';
this._calculatedIP = lit;
},
JMP_indirect: (addr) => {
this.debug.currentMnemonic = 'JMP addr';
this._calculatedIP = addr;
},
}
debug = {
// TODO include the rest of the stuff that I have here in the current version
running: false,
}
}
class Memory {
// ROM format: { addr: nn, data: nn }
constructor (sizeInBytes, ROM) {
// memory format: [ { data: nn, type: str } ]
this.memory = new Array(sizeInBytes);
ROM.forEach((byte) => {
this.memory[byte.address] = { data: byte.data, type: 'ROM' };
})
}
tickClock () {
if (connections.memoryReadSignal) this._read();
if (connections.memoryWriteSignal) this._write();
}
_read () {
connections.dataBus = this.memory[connections.addressBus].data;
}
_write () {
if (this.memory[connections.addressBus].type === 'ROM') throw new Error('Attempted write to ROM');
this.memory[connections.addressBus].data = connections.dataBus;
}
}
/** DMA controller for screen, keypad... **/
class IO {
// TODO…
constructor (connections) {
// ...
}
}
class Connections {
dataBus = 0;
addressBus = 0;
memoryReadSignal = 0;
memoryWriteSignal = 0;
cpuWait = 0;
}
// let rom = // TODO read in…
const rom = [
{ address: 0xFE, data: 0x55, },
{ address: 0xFF, data: 0x00, },
{ address: 0x00, data: 0x51, },
{ address: 0x01, data: 0x0F, },
{ address: 0x02, data: 0x62, },
{ address: 0x03, data: 0x01, },
{ address: 0x04, data: 0x00, },
];
let connections = new Connections();
let memory = new Memory(256, rom);
let cpu = new CPU();
let intervalTimer = setInterval( () => {
cpu.tickClock();
memory.tickClock();
}, 500);
console.log(intervalTimer);