Remove old sketches
This commit is contained in:
parent
1c8722c65e
commit
e09bd9a66f
|
|
@ -1,300 +0,0 @@
|
|||
// This is a sketch of a simulator for my paper computer,
|
||||
// made for two purposes:
|
||||
//
|
||||
// (1) figuring out the basic structure for a simple simulator
|
||||
// (2) testing some simple programs (hopefully)
|
||||
//
|
||||
// NOTA BENE: this simple version makes naive use of
|
||||
// Javascript numbers for opcodes, and a Javascript array
|
||||
// for the computer's "memory." This may cause some problems.
|
||||
|
||||
function CPU(mem) {
|
||||
this.memory = mem;
|
||||
this.running = false;
|
||||
this.instructionPointer = 0;
|
||||
this.carryFlag = 0;
|
||||
this.acc = 0;
|
||||
|
||||
this.instructions = {
|
||||
end: () => {
|
||||
console.log('END');
|
||||
this.running = false
|
||||
},
|
||||
|
||||
store_lit: (lit) => {
|
||||
console.log('STO lit#');
|
||||
this.memory[lit] = this.acc;
|
||||
log_table_with_title(this.memory, 'Current memory');
|
||||
this.instructionPointer = this.instructionPointer += 1;
|
||||
},
|
||||
|
||||
store_addr: (addr) => {
|
||||
console.log('STO addr');
|
||||
this.memory[this.memory[addr]] = this.acc;
|
||||
log_table_with_title(this.memory, 'Memory');
|
||||
this.instructionPointer = this.instructionPointer += 1;
|
||||
},
|
||||
|
||||
load_lit: (lit) => {
|
||||
console.log('LDA lit#');
|
||||
this.acc = lit;
|
||||
this.instructionPointer = this.instructionPointer += 1;
|
||||
},
|
||||
|
||||
load_addr: (addr) => {
|
||||
console.log('LDA addr');
|
||||
console.log('mem at addr: ', this.memory[addr]);
|
||||
this.acc = this.memory[addr];
|
||||
this.instructionPointer = this.instructionPointer += 1;
|
||||
},
|
||||
|
||||
add_lit: (lit) => {
|
||||
console.log("ADD lit");
|
||||
if ( (this.acc + lit) > 15 ) { this.carryFlag = 1; }
|
||||
this.acc = ((this.acc + lit) % 15);
|
||||
this.instructionPointer = this.instructionPointer += 1;
|
||||
},
|
||||
|
||||
add_addr: (addr) => {
|
||||
console.log("ADD addr");
|
||||
if ( (this.acc + this.memory[addr]) > 15 ) { this.carryFlag = 1; }
|
||||
this.acc = ((this.acc + this.memory[addr]) % 15);
|
||||
this.instructionPointer = this.instructionPointer += 1;
|
||||
},
|
||||
|
||||
sub_lit: (lit) => { // TODO: carry flag
|
||||
console.log("SUB lit");
|
||||
this.acc = this.acc - lit;
|
||||
this.instructionPointer = this.instructionPointer += 1;
|
||||
},
|
||||
|
||||
sub_addr: (addr) => { // TODO: carry flag
|
||||
console.log("SUB addr");
|
||||
this.acc = this.acc - this.memory[addr];
|
||||
this.instructionPointer = this.instructionPointer += 1;
|
||||
},
|
||||
|
||||
hop_lit: (lit) => {
|
||||
console.log("HOP lit");
|
||||
console.log(" ↳ Memory at IP+1:", this.memory[this.instructionPointer+1]);
|
||||
if (this.acc === lit) {
|
||||
this.instructionPointer += 2;
|
||||
} else {
|
||||
this.instructionPointer += 1;
|
||||
}
|
||||
},
|
||||
|
||||
hop_addr: (addr) => {
|
||||
console.log("HOP addr");
|
||||
if (this.acc === this.memory[addr]) {
|
||||
this.instructionPointer += 2;
|
||||
} else {
|
||||
this.instructionPointer += 1;
|
||||
}
|
||||
},
|
||||
|
||||
jump_lit: (lit) => {
|
||||
console.log("JMP lit");
|
||||
this.instructionPointer = lit;
|
||||
},
|
||||
|
||||
jump_addr: (addr) => {
|
||||
console.log("JMP addr");
|
||||
this.instructionPointer = this.memory[addr];
|
||||
},
|
||||
|
||||
carry_clear: () => {
|
||||
console.log("CFC");
|
||||
this.carryFlag = 0;
|
||||
this.instructionPointer += 1;
|
||||
},
|
||||
|
||||
carry_hop: () => {
|
||||
console.log("CHP");
|
||||
if (this.carryFlag != 0) {
|
||||
this.instructionPointer += 2;
|
||||
} else {
|
||||
this.instructionPointer += 1;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
this.perform_operation = (opcode, arg) => {
|
||||
switch (opcode) {
|
||||
case 0:
|
||||
this.instructions.end(arg);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
this.instructions.store_lit(arg);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
this.instructions.store_addr(arg);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
this.instructions.load_lit(arg);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
this.instructions.load_addr(arg);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
this.instructions.add_lit(arg);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
this.instructions.add_addr(arg);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
this.instructions.sub_lit(arg);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
this.instructions.sub_addr(arg);
|
||||
break;
|
||||
|
||||
case 9:
|
||||
this.instructions.hop_lit(arg);
|
||||
break;
|
||||
|
||||
case 10:
|
||||
this.instructions.hop_addr(arg);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
this.instructions.jump_lit(arg);
|
||||
break;
|
||||
|
||||
case 12:
|
||||
this.instructions.jump_addr(arg);
|
||||
break;
|
||||
|
||||
case 13:
|
||||
this.instructions.carry_clear(arg);
|
||||
break;
|
||||
|
||||
case 14:
|
||||
this.instructions.carry_hop(arg);
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error( `Invalid opcode: ${opcode} with argument ${arg}` );
|
||||
}
|
||||
}
|
||||
|
||||
this.run_program = () => {
|
||||
const initialMemory = JSON.parse(JSON.stringify(this.memory)); // Hack to make a copy-by-value -- https://stackoverflow.com/questions/18829099/copy-a-variables-value-into-another
|
||||
console.log();
|
||||
console.log("————————————————————————————————————————");
|
||||
let time = new Date();
|
||||
console.log( `Running at ${time.toLocaleTimeString('en-US')}` );
|
||||
console.log("————————————————————————————————————————");
|
||||
log_debug_state();
|
||||
|
||||
this.running = true;
|
||||
|
||||
for (let i = 1; i < 16; i++) {
|
||||
if ( this.running &&
|
||||
(this.instructionPointer < this.memory.length) ) {
|
||||
let op_arg_tuple = this.memory[this.instructionPointer];
|
||||
console.group("Proccessing instruction");
|
||||
console.log( op_arg_tuple );
|
||||
// console.log( `processing opcode ${op_arg_tuple[0]} with arg ${op_arg_tuple[1]}` );
|
||||
this.perform_operation(op_arg_tuple[0], op_arg_tuple[1]);
|
||||
log_debug_state();
|
||||
console.groupEnd("Processing instruction");
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
memoryAtStart: initialMemory,
|
||||
memoryAtEnd: this.memory
|
||||
}
|
||||
}
|
||||
|
||||
log_debug_state = () => {
|
||||
console.log();
|
||||
console.group('CPU state');
|
||||
console.log( `Acc: ${this.acc} IP: ${this.instructionPointer} CF: ${this.carryFlag} ${this.running ? "running" : "halted" }` );
|
||||
console.log();
|
||||
console.groupEnd('CPU state');
|
||||
};
|
||||
};
|
||||
|
||||
log_table_with_title = (memory, tableTitle) => {
|
||||
console.log();
|
||||
console.group(tableTitle);
|
||||
console.table(memory);
|
||||
console.groupEnd(tableTitle);
|
||||
};
|
||||
|
||||
|
||||
// TESTS
|
||||
|
||||
let halt_and_catch_fire = [
|
||||
[0, 0],
|
||||
[1, 0],
|
||||
];
|
||||
|
||||
let test_lda_sto = [
|
||||
[3, 8], // LDA lit
|
||||
[1, 5], // STO lit
|
||||
[4, 5], // LDA addr
|
||||
[2, 6], // STO addr
|
||||
[0, 0], // END
|
||||
];
|
||||
|
||||
let test_add_sub_nocarry = [
|
||||
[5, 6], // ADD lit ... acc = 6
|
||||
[7, 1], // SUB lit ... acc = 5
|
||||
[1, 8], // STO lit ... mem[8] = 5
|
||||
[6, 8], // ADD addr ... acc = 10
|
||||
[8, 8], // SUB addr ... acc = 5
|
||||
[0, 0], // END
|
||||
]
|
||||
let test_add_sub = [
|
||||
[5, 26], // ADD lit
|
||||
[0, 0], // END
|
||||
]
|
||||
|
||||
let test_hop = [
|
||||
[5, 8], // ADD lit ... acc = 8
|
||||
[9, 8], // HOP lit ... hop over next op if acc = 8
|
||||
[0, 0], // END ... (hopped over)
|
||||
[7, 8], // SUB lit ... acc = 0
|
||||
[0, 0]
|
||||
]
|
||||
|
||||
let test_jmp = [
|
||||
[11, 4], // 0
|
||||
[0, 0], // 1 ... END ... JMP'd over
|
||||
[0, 0], // 2
|
||||
[0, 0], // 3
|
||||
[5, 8], // 4 ... ADD lit ... acc = 8
|
||||
[0, 0], // 5 ... END
|
||||
]
|
||||
|
||||
let test_chp = [
|
||||
[5, 8], // ADD lit ... acc = 8
|
||||
[14, 0], // CHP ... shouldn't hop (CF = 0)
|
||||
[5, 1], // ADD lit ... acc = 9
|
||||
[5, 8], // ADD lit ... acc = 1 and CF = 1
|
||||
[14, 0], // CHP ... hop! (CF = 1)
|
||||
[0, 0], // END
|
||||
[7, 1], // SUB lit ... acc = 0
|
||||
[13, 0], // CFC ... CF = 0
|
||||
[0, 0], // END
|
||||
]
|
||||
|
||||
//let comp = new CPU(test_chp);
|
||||
|
||||
let comp = new CPU(test_lda_sto);
|
||||
let memory_snapshots = comp.run_program();
|
||||
log_table_with_title(memory_snapshots.memoryAtEnd, 'Memory after running');
|
||||
log_table_with_title(memory_snapshots.memoryAtStart, 'Memory before running');
|
||||
|
||||
// TODO: TEST HOP_addr
|
||||
|
|
@ -1,274 +0,0 @@
|
|||
// NOTES:
|
||||
//
|
||||
// - instructions are two bytes long:
|
||||
// one byte for the opcode, one for the argument
|
||||
|
||||
// STATE
|
||||
|
||||
const CPU = {
|
||||
running: false,
|
||||
IP: 0,
|
||||
CF: 0,
|
||||
Acc: 0,
|
||||
memory: null,
|
||||
loadMemory: (data) => { // data: Uint8Array
|
||||
// TODO: check length of data
|
||||
CPU.memory = data;
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
// FUNCTIONS THAT MODIFY STATE
|
||||
|
||||
const Instructions = {
|
||||
end: () => {
|
||||
console.log('END');
|
||||
CPU.running = false;
|
||||
},
|
||||
|
||||
store_lit: (lit) => {
|
||||
console.log('STO lit#');
|
||||
CPU.memory[lit] = CPU.Acc;
|
||||
logTableTitled(CPU.memory, 'Current memory');
|
||||
CPU.IP = CPU.IP += 2;
|
||||
},
|
||||
|
||||
store_addr: (addr) => {
|
||||
console.log('STO addr');
|
||||
CPU.memory[CPU.memory[addr]] = CPU.Acc;
|
||||
logTableTitled(CPU.memory, 'Memory');
|
||||
CPU.IP = CPU.IP += 2;
|
||||
},
|
||||
|
||||
load_lit: (lit) => {
|
||||
console.log('LDA lit#');
|
||||
CPU.Acc = lit;
|
||||
CPU.IP = CPU.IP += 2;
|
||||
},
|
||||
|
||||
load_addr: (addr) => {
|
||||
console.log('LDA addr');
|
||||
console.log('mem at addr: ', CPU.memory[addr]);
|
||||
CPU.Acc = CPU.memory[addr];
|
||||
CPU.IP = CPU.IP += 2;
|
||||
},
|
||||
|
||||
add_lit: (lit) => {
|
||||
console.log("ADD lit");
|
||||
let sum = CPU.Acc + lit;
|
||||
if (sum > 15) {
|
||||
CPU.CF = 1;
|
||||
CPU.Acc = (sum % 15) - 1;
|
||||
} else {
|
||||
CPU.CF = 0;
|
||||
CPU.Acc = sum;
|
||||
}
|
||||
CPU.IP = CPU.IP += 2;
|
||||
},
|
||||
|
||||
add_addr: (addr) => {
|
||||
console.log("ADD addr");
|
||||
let sum = CPU.Acc + CPU.memory[addr];
|
||||
if (sum > 15) {
|
||||
CPU.CF = 1;
|
||||
CPU.Acc = (sum % 15) - 1;
|
||||
} else {
|
||||
CPU.CF = 0;
|
||||
CPU.Acc = sum;
|
||||
}
|
||||
CPU.IP = CPU.IP += 2;
|
||||
},
|
||||
|
||||
sub_lit: (lit) => { // TODO: carry flag
|
||||
console.log("SUB lit");
|
||||
CPU.Acc = CPU.Acc - lit;
|
||||
CPU.IP = CPU.IP += 2;
|
||||
},
|
||||
|
||||
sub_addr: (addr) => { // TODO: carry flag
|
||||
console.log("SUB addr");
|
||||
CPU.Acc = CPU.Acc - CPU.memory[addr];
|
||||
CPU.IP = CPU.IP += 2;
|
||||
},
|
||||
|
||||
hop_lit: (lit) => {
|
||||
console.log("HOP lit");
|
||||
console.log(` ↳ Memory at IP+2 and +3: ${CPU.memory[CPU.IP+2]}, ${CPU.memory[CPU.IP+3]}`);
|
||||
if (CPU.Acc === lit) {
|
||||
CPU.IP += 4;
|
||||
} else {
|
||||
CPU.IP += 2;
|
||||
}
|
||||
},
|
||||
|
||||
hop_addr: (addr) => {
|
||||
console.log("HOP addr");
|
||||
if (CPU.Acc === CPU.memory[addr]) {
|
||||
CPU.IP += 4;
|
||||
} else {
|
||||
CPU.IP += 2;
|
||||
}
|
||||
},
|
||||
|
||||
jump_lit: (lit) => {
|
||||
console.log("JMP lit");
|
||||
CPU.IP = lit;
|
||||
},
|
||||
|
||||
jump_addr: (addr) => {
|
||||
console.log("JMP addr");
|
||||
CPU.IP = CPU.memory[addr];
|
||||
},
|
||||
|
||||
carry_clear: () => {
|
||||
console.log("CFC");
|
||||
CPU.CF = 0;
|
||||
CPU.IP += 2;
|
||||
},
|
||||
|
||||
carry_hop: () => {
|
||||
console.log("CHP");
|
||||
console.log(` ↳ Memory at IP+2 and +3: ${CPU.memory[CPU.IP+2]}, ${CPU.memory[CPU.IP+3]}`);
|
||||
console.table(CPU.memory);
|
||||
if (CPU.CF != 0) {
|
||||
CPU.IP += 4;
|
||||
} else {
|
||||
CPU.IP += 2;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const opcodes2mnemonics = {
|
||||
0: (arg) => Instructions.end(arg),
|
||||
1: (arg) => Instructions.store_lit(arg),
|
||||
2: (arg) => Instructions.store_addr(arg),
|
||||
3: (arg) => Instructions.load_lit(arg),
|
||||
4: (arg) => Instructions.load_addr(arg),
|
||||
5: (arg) => Instructions.add_lit(arg),
|
||||
6: (arg) => Instructions.add_addr(arg),
|
||||
7: (arg) => Instructions.sub_lit(arg),
|
||||
8: (arg) => Instructions.sub_addr(arg),
|
||||
9: (arg) => Instructions.hop_lit(arg),
|
||||
10: (arg) => Instructions.hop_addr(arg),
|
||||
11: (arg) => Instructions.jump_lit(arg),
|
||||
12: (arg) => Instructions.jump_addr(arg),
|
||||
13: (arg) => Instructions.carry_clear(arg),
|
||||
14: (arg) => Instructions.carry_hop(arg),
|
||||
};
|
||||
|
||||
function stepCPU() {
|
||||
console.group("Step CPU");
|
||||
let opcode = CPU.memory[CPU.IP];
|
||||
let argument = CPU.memory[CPU.IP+1];
|
||||
|
||||
console.log(`OP: ${opcode} ARG: ${argument}`);
|
||||
|
||||
let instruction = opcodes2mnemonics[opcode];
|
||||
instruction(argument);
|
||||
|
||||
logCPUState();
|
||||
console.groupEnd("Step CPU");
|
||||
}
|
||||
|
||||
function runCPU() {
|
||||
const initialMemory = JSON.parse(JSON.stringify(CPU.memory)); // Hack to make a copy-by-value -- https://stackoverflow.com/questions/18829099/copy-a-variables-value-into-another
|
||||
console.log();
|
||||
console.log("————————————————————————————————————————");
|
||||
let time = new Date();
|
||||
console.log( `Running at ${time.toLocaleTimeString('en-US')}` );
|
||||
console.log("————————————————————————————————————————");
|
||||
logCPUState();
|
||||
|
||||
CPU.running = true;
|
||||
for (let i = 0; i < 255; i++) { // FIXME: temporary limit as a lazy way to halt infinite loops
|
||||
if (!CPU.running) break;
|
||||
if (CPU.IP >= CPU.memory.length) break;
|
||||
stepCPU();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// FUNCTIONS THAT PULL INFO FROM STATE TO DISPLAY
|
||||
|
||||
function logCPUState() {
|
||||
console.log();
|
||||
console.group('CPU state');
|
||||
console.log( `Acc: ${CPU.Acc} IP: ${CPU.IP} CF: ${CPU.CF} ${CPU.running ? "running" : "halted" }` );
|
||||
console.log();
|
||||
console.groupEnd('CPU state');
|
||||
};
|
||||
|
||||
|
||||
// FUNCTIONS FOR DISPLAYING DATA
|
||||
|
||||
function num2hex(num) { return num.toString(16) };
|
||||
function hex2num(hex) { return parseInt(hex, 16) };
|
||||
|
||||
logTableTitled = (memory, tableTitle) => {
|
||||
console.log();
|
||||
console.group(tableTitle);
|
||||
console.table(memory);
|
||||
console.groupEnd(tableTitle);
|
||||
};
|
||||
|
||||
|
||||
// RUN IT !
|
||||
|
||||
const test_lda_sto = new Uint8Array([
|
||||
3, 17, // LDA lit ... Acc = 17
|
||||
1, 14, // STO lit ... @14 = Acc = 17
|
||||
3, 16, // LDA lit ... Acc = 16
|
||||
1, 15, // STO lit ... @15 = Acc = 16
|
||||
2, 15, // STO addr ... @[@15] = Acc = 16 ... mem[mem[addr]] <- Acc
|
||||
4, 0, // LDA addr ... Acc = @00 = 03
|
||||
0, 0, // END
|
||||
0, 0, // DATA
|
||||
]);
|
||||
|
||||
let test_add_sub_nocarry = new Uint8Array([
|
||||
5, 6, // ADD lit ... acc = 6
|
||||
7, 1, // SUB lit ... acc = 5
|
||||
1, 15, // STO lit ... mem[15] = 5
|
||||
6, 15, // ADD addr ... acc = 10
|
||||
8, 15, // SUB addr ... acc = 5
|
||||
0, 0, // END
|
||||
0, 0,
|
||||
0, 0,
|
||||
]);
|
||||
|
||||
let test_hop = new Uint8Array([
|
||||
5, 8, // ADD lit ... acc = 8
|
||||
9, 8, // HOP lit ... hop over next op if acc = 8
|
||||
0, 0, // END ... (hopped over)
|
||||
7, 8, // SUB lit ... acc = 0
|
||||
0, 0
|
||||
]);
|
||||
|
||||
let test_jmp = new Uint8Array([
|
||||
11, 8, // 0 ... JMP lit
|
||||
0, 0, // 2 ... END ... JMP'd over
|
||||
0, 0, // 4
|
||||
0, 0, // 6
|
||||
5, 8, // 8 ... ADD lit ... acc = 8
|
||||
0, 0, // 10 ... END
|
||||
]);
|
||||
|
||||
|
||||
const test_chp = new Uint8Array([
|
||||
5, 8, // ADD lit ... Acc = 8
|
||||
14, 0, // CHP ... shouldn't hop (CF = 0)
|
||||
5, 1, // ADD lit ... Acc = 9
|
||||
5, 8, // ADD lit ... Acc = 1 and CF = 1
|
||||
14, 0, // CHP ... hop! (CF = 1)
|
||||
0, 0, // END
|
||||
7, 1, // SUB lit ... Acc = 0
|
||||
13, 0, // CFC ... CF = 0
|
||||
0, 0, // END
|
||||
]);
|
||||
|
||||
//CPU.loadMemory(test_lda_sto);
|
||||
//CPU.loadMemory(test_add_sub_nocarry);
|
||||
//CPU.loadMemory(test_hop);
|
||||
CPU.loadMemory(test_jmp);
|
||||
//CPU.loadMemory(test_chp);
|
||||
runCPU();
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
const readline = require('readline');
|
||||
|
||||
readline.emitKeypressEvents(process.stdin);
|
||||
|
||||
if (process.stdin.setRawMode != null) {
|
||||
process.stdin.setRawMode(true);
|
||||
}
|
||||
|
||||
process.stdin.on('keypress', (str, key) => {
|
||||
console.log(str)
|
||||
console.log(key)
|
||||
if (key.sequence === '\x03') process.exit();
|
||||
})
|
||||
|
||||
let i = 0;
|
||||
const loop = setInterval(async () => {
|
||||
console.log('loop #', i);
|
||||
if (i > 10) clearInterval(loop);
|
||||
i += 1;
|
||||
}, 250);
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
const readlineSync = require('readline-sync');
|
||||
|
||||
let key = readlineSync.keyIn('? ')
|
||||
console.log(key);
|
||||
|
||||
/* This works without external dependencies,
|
||||
* but it's for a full line at a time
|
||||
const readline = require('readline/promises');
|
||||
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
});
|
||||
|
||||
async function getInput(prompt) {
|
||||
let input = await rl.question(prompt)
|
||||
console.log(input);
|
||||
console.log("Later");
|
||||
rl.close();
|
||||
}
|
||||
|
||||
getInput('?');
|
||||
*/
|
||||
Loading…
Reference in New Issue