From a3f53824375360c043e7a62f6185f4c2d3a96bcb Mon Sep 17 00:00:00 2001 From: MatCat Date: Mon, 5 Apr 2021 23:49:23 -0700 Subject: [PATCH] Memory now follows the location, shows red when writing to RAM and GREEN when reading, yellow when the address bus just happens to be sitting on the address but not actively reading or writing. --- index.html | 6 ++- js/asm_compiler.js | 113 +++++++++++++++++++++++++++++++++++++++ js/cpu.js | 84 +++++++++++++++++------------ js/main.js | 12 ++--- js/microcode_compiler.js | 9 ++++ 5 files changed, 181 insertions(+), 43 deletions(-) create mode 100644 js/asm_compiler.js diff --git a/index.html b/index.html index da91aec..a829b92 100644 --- a/index.html +++ b/index.html @@ -41,11 +41,12 @@
- 0 0x + 0 0x + Clock Interval: mS
Text Output (0x8000-0x83ff):
- +
RAM : []
@@ -57,5 +58,6 @@ + \ No newline at end of file diff --git a/js/asm_compiler.js b/js/asm_compiler.js new file mode 100644 index 0000000..0d57cfe --- /dev/null +++ b/js/asm_compiler.js @@ -0,0 +1,113 @@ +class ASM_Compiler { + constructor(assemblycode) { + this.ASM = assemblycode.replace(/ +/g, ' ').replace(/\\t+/g, ' ').replace(/\\r+/g, ''); + this.Labels = new Array(); + this.Directives = { + Globals: new Array() + }; + this.Sections = new Array(); + this.CompileError = false; + this.CompileErrorReason = ""; + } + firstPass() { + let codeLines = this.ASM.split("\n"); + let currentSection = ""; + console.log(`There are ${codeLines.length} lines`); + for (let linenum = 0; linenum < codeLines.length; linenum++) { + console.log(`Line ${linenum}: ${codeLines[linenum]}`); + let globalDeclared = false; + let sectionDeclared = false; + let lineColumns = codeLines[linenum].split(" "); + for (let colnum = 0; colnum < lineColumns.length; colnum++) { + console.log(`Column ${colnum}: ${lineColumns[colnum]}`); + switch (colnum) { + case 0: { // Labels + if (currentSection === "" && lineColumns[colnum] !== "") { + // error, shouldn't be anything here in the directives section + this.CompileError = true; + this.CompileErrorReason = "Unexpected label in directives section: " + lineColumns[colnum]; + this.CompileErrorLine = linenum+1; + return false; + } + break; + } + case 1: { // Instructions + if (currentSection === "" && lineColumns[colnum] === "") { + // Error, in directive there should be SOMETHING here + this.CompileError = true; + this.CompileErrorReason = "Missing Directive"; + this.CompileErrorLine = linenum+1; + return false; + } + + if (currentSection === "") { + switch (lineColumns[colnum].toLowerCase()) { + case "global": { + if (colnum === lineColumns.length - 1) { + this.CompileError = true; + this.CompileErrorReason = "Missing Global Label"; + this.CompileErrorLine = linenum + 1; + return false; + } + globalDeclared = true; + break; + } + case "section": { + if (colnum === lineColumns.length - 1) { + this.CompileError = true; + this.CompileErrorReason = "Missing section type"; + this.CompileErrorLine = linenum + 1; + return false; + } + sectionDeclared = true; + break; + } + default: { + this.CompileError = true; + this.CompileErrorReason = "Unknown directive: " + lineColumns[colnum]; + this.CompileErrorLine = linenum + 1; + return false; + } + } + break; + } else { + if (!FindInstructon({Instruction:lineColumns[colnum]})) { + this.CompileError = true; + this.CompileErrorReason = "Unknown instruction: " + lineColumns[colnum]; + this.CompileErrorLine = linenum + 1; + return false; + } + } + } + case 2: { // Operands + if (currentSection === "" && lineColumns[colnum] === "" && (globalDeclared === true || sectionDeclared === true)) { + // There should be a label here! + this.CompileError = true; + if (globalDeclared) this.CompileErrorReason = "Missing Global Label"; + if (sectionDeclared) this.CompileErrorReason = "Missing Section type"; + this.CompileErrorLine = linenum+1; + return false; + } + + if (globalDeclared) { + let globallabel = { + Label: lineColumns[colnum].replace(":", ""), + Address: 0 + }; + this.Directives.Globals.push(globallabel); + } + if (sectionDeclared) { + let sectionType = { + Label: lineColumns[colnum].replace(".", ""), + Address: 0 + }; + currentSection = sectionType; + this.Sections.push(currentSection); + } + break; + } + } + } + } + } +} \ No newline at end of file diff --git a/js/cpu.js b/js/cpu.js index d268e44..6829d52 100644 --- a/js/cpu.js +++ b/js/cpu.js @@ -66,9 +66,9 @@ function GetMnemonic(mcarray,instruction) { function generateClocks(clk_cnt) { for (let a = 0; a < clk_cnt; a++) { cpu.CLOCK(true); - updateHTML(); + clk_count++; + clk_counter.innerText = clk_count; cpu.CLOCK(false); - updateHTML(); } } @@ -79,17 +79,23 @@ function generateClocks_Interval() { cpu.CLOCK(true); }*/ cpu.CLOCK(true); + clk_count++; + clk_counter.innerText = clk_count; cpu.CLOCK(false); - updateHTML(); if (cpu.ADDRBUS === breakpt) clearInterval(intval); } +function drawCPUInfo() { + updateHTML(); + window.requestAnimationFrame(drawCPUInfo); +} + function RunUntilBreak(addr) { breakpt = addr; intval = setInterval(function(){ generateClocks_Interval(); - }, 1); + }, parseInt(clkinterval.value)); } function printTextOut(ram,startaddr,endaddr) { @@ -101,14 +107,22 @@ function printTextOut(ram,startaddr,endaddr) { } function printRAM(ram) { + let startADDR = (cpu.ADDRBUS & 0xfff0) - 0x80; + if (startADDR < 0) startADDR = 0; + if (startADDR > 0xFEFF) startADDR = 0xFF00; let sp_ram = document.getElementById("RAM"); let ramtext = "ADDR  :   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
"; - for (let a = 0; a < 16; a++) { - ramtext += "0x" + formatHex(a*16,4) + ": "; + for (let a = startADDR; a < (startADDR+255); a+=16) { + ramtext += "0x" + formatHex(a,4) + ": "; for (let b = 0; b < 16; b++) { - if (cpu.ADDRBUS === (a*16)+b) ramtext += ''; - ramtext += formatHex(ram[(a*16)+b],4) + " "; - if (cpu.ADDRBUS === (a*16)+b) ramtext += ''; + if (cpu.ADDRBUS === (a)+b) { + let bgcolor = "#ffff55"; + if ((cpu.MC_Controls & CONTROL_OUT_RO) === CONTROL_OUT_RO) bgcolor = "#55ff55"; + if (cpu.MC_Controls & CONTROL_RI) bgcolor = "#ff5555"; + ramtext += ``; + } + ramtext += formatHex(ram[(a)+b],4) + " "; + if (cpu.ADDRBUS === (a)+b) ramtext += ''; } ramtext += "
"; } @@ -116,7 +130,7 @@ function printRAM(ram) { let sp_stackram = document.getElementById("STACK-RAM"); ramtext = "ADDR  :   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
"; - for (let a = 0xffa0; a < 0x10000; a+=16) { + for (let a = 0xffe0; a < 0x10000; a+=16) { ramtext += "0x" + formatHex(a,4) + ": "; for (let b = 0; b < 16; b++) { if (cpu.ADDRBUS === (a)+b) ramtext += ''; @@ -283,7 +297,7 @@ class CPU_8SA1 { OUTMUX |= (this.MC_Controls & CONTROL_OEM0) ? 0b00001 : 0; if (OUTMUX === OECONTROL_RO) { - console.log("DATABUS = RAM"); + //console.log("DATABUS = RAM"); this.DATABUS = this.RAM[this.ADDRBUS]; if (this.DATABUS === undefined) this.DATABUS = 0; } @@ -322,12 +336,12 @@ class CPU_8SA1 { let MC_Controls = this.MCRAM[mcra]; if (MC_Controls & CONTROL_MCL0) this.MCC = 0; if (MC_Controls & CONTROL_MCL8) this.MCC = 8; - if (MC_Controls & CONTROL_MCL0) console.log(`Reset microcode counter to 0`); - if (MC_Controls & CONTROL_MCL8) console.log(`Reset microcode counter to 8`); + //if (MC_Controls & CONTROL_MCL0) console.log(`Reset microcode counter to 0`); + //if (MC_Controls & CONTROL_MCL8) console.log(`Reset microcode counter to 8`); mcra = ((this.IR & 0b0000001111111111) << 4) | this.MCC | ((this.SR & 0b00000011) << 14); MC_Controls = this.MCRAM[mcra]; if (MC_Controls === undefined) MC_Controls = 0; - console.log(`[${mcra.toString(2)}] Control Lines: ${MC_Controls.toString(2)}`); + //console.log(`[${mcra.toString(2)}] Control Lines: ${MC_Controls.toString(2)}`); if (MC_Controls !== this.MC_Controls) { if (MC_Controls & CONTROL_OEME) { // Set the DATABUS based on whatever output we are controlling @@ -337,46 +351,46 @@ class CPU_8SA1 { OUTMUX |= (MC_Controls & CONTROL_OEM1) ? 0b00010 : 0; OUTMUX |= (MC_Controls & CONTROL_OEM0) ? 0b00001 : 0; - console.log(`OUTPUT MUX: ${OUTMUX.toString(2)}`); + //console.log(`OUTPUT MUX: ${OUTMUX.toString(2)}`); switch (OUTMUX) { case OECONTROL_PC: { this.DATABUS = this.PC; - console.log("DATABUS = PC"); + //console.log("DATABUS = PC"); break; } case OECONTROL_SP: { this.DATABUS = this.SP; - console.log("DATABUS = SP"); + //console.log("DATABUS = SP"); break; } case OECONTROL_AL: { this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.GPA & BITMASK_8); - console.log("DATABUS LOW = A"); + //console.log("DATABUS LOW = A"); break; } case OECONTROL_AH: { this.DATABUS = ((this.GPA & BITMASK_8) << 8) | (this.DATABUS & BITMASK_8); - console.log("DATABUS HIGH = A"); + //console.log("DATABUS HIGH = A"); break; } case OECONTROL_BL: { this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.GPB & BITMASK_8); - console.log("DATABUS LOW = B"); + //console.log("DATABUS LOW = B"); break; } case OECONTROL_BH: { this.DATABUS = ((this.GPB & BITMASK_8) << 8) | (this.DATABUS & BITMASK_8); - console.log("DATABUS HIGH = B"); + // console.log("DATABUS HIGH = B"); break; } case OECONTROL_CL: { this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.GPC & BITMASK_8); - console.log("DATABUS LOW = C"); + //console.log("DATABUS LOW = C"); break; } case OECONTROL_CH: { this.DATABUS = ((this.GPC & BITMASK_8) << 8) | (this.DATABUS & BITMASK_8); - console.log("DATABUS HIGH = C"); + //console.log("DATABUS HIGH = C"); break; } case OECONTROL_DL: { @@ -389,7 +403,7 @@ class CPU_8SA1 { } case OECONTROL_AB: { this.DATABUS = ((this.GPB & BITMASK_8) << 8) | (this.GPA & BITMASK_8); - console.log("DATABUS = AB"); + //console.log("DATABUS = AB"); break; } case OECONTROL_AC: { @@ -437,7 +451,7 @@ class CPU_8SA1 { break; } case OECONTROL_AE: { - console.log("ALU Enable"); + //console.log("ALU Enable"); this.DATABUS = (this.GPB << 8) | this.GPA; let ALU_A = this.DATABUS & BITMASK_8; let ALU_B = (this.DATABUS & (BITMASK_8 << 8)) >> 8; @@ -446,7 +460,7 @@ class CPU_8SA1 { let ALUMUX = (MC_Controls & CONTROL_ALUM1) ? 0b10 : 0; ALUMUX |= (MC_Controls & CONTROL_ALUM0) ? 0b01 : 0; - console.log(`ALU: A=${ALU_A}, B=${ALU_B}, MUX: ${ALUMUX}`); + //console.log(`ALU: A=${ALU_A}, B=${ALU_B}, MUX: ${ALUMUX}`); if (MC_Controls & CONTROL_ALUI) console.log("ALU Inverting B"); let SHIFTING = false; if (MC_Controls & CONTROL_ALUSL) SHIFTING = true; @@ -504,17 +518,17 @@ class CPU_8SA1 { } case OECONTROL_AO: { this.DATABUS = (this.DATABUS & (BITMASK_8 << 8)) | this.ALUSUM; - console.log("DATABUS = SUM"); + //console.log("DATABUS = SUM"); break; } case OECONTROL_SR: { this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.SR & BITMASK_8); - console.log("DATABUS = STATUS REGISTER"); + //console.log("DATABUS = STATUS REGISTER"); break; } case OECONTROL_RO: { // We dont actually want to do anything here since ram outputs on CLK - console.log("DATABUS = RAM (on CLK)"); + //console.log("DATABUS = RAM (on CLK)"); break; } } @@ -570,32 +584,32 @@ class CPU_8SA1 { GPA_In_LOW_CLK() { this.GPA = this.DATABUS & 0x00ff; - console.log(`GPA = DATABUS LOW`); + //console.log(`GPA = DATABUS LOW`); } GPA_In_HIGH_CLK() { this.GPA = (this.DATABUS & 0xff00) >> 8; - console.log(`GPA = DATABUS HIGH`); + //console.log(`GPA = DATABUS HIGH`); } GPB_In_LOW_CLK() { this.GPB = this.DATABUS & 0x00ff; - console.log(`GPB = DATABUS LOW`); + //console.log(`GPB = DATABUS LOW`); } GPB_In_HIGH_CLK() { this.GPB = (this.DATABUS & 0xff00) >> 8; - console.log(`GPB = DATABUS HIGH`); + //console.log(`GPB = DATABUS HIGH`); } GPC_In_LOW_CLK() { this.GPC = this.DATABUS & 0x00ff; - console.log(`GPC = DATABUS LOW`); + //console.log(`GPC = DATABUS LOW`); } GPC_In_HIGH_CLK() { this.GPC = (this.DATABUS & 0xff00) >> 8; - console.log(`GPC = DATABUS HIGH`); + //console.log(`GPC = DATABUS HIGH`); } GPD_In_LOW_CLK() { diff --git a/js/main.js b/js/main.js index b7a42a2..674ee72 100644 --- a/js/main.js +++ b/js/main.js @@ -36,7 +36,7 @@ cpu.RAM[4] = is_CMP.Bytecode; */ cpu.RAM[0] = is_LDAB_i.Bytecode; -cpu.RAM[1] = 0x0050; +cpu.RAM[1] = 0x0100; cpu.RAM[2] = is_PHAB.Bytecode; cpu.RAM[3] = is_JSR.Bytecode; cpu.RAM[4] = 0x00D0; @@ -89,12 +89,13 @@ cpu.RAM[0xFC] = is_RTS.Bytecode; -stringToRAM("Blackbeard420 is a Butt Fuckers",cpu.RAM,0x50); +stringToRAM("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc maximus erat mollis, fermentum quam at, blandit turpis. Pellentesque arcu tortor, smoke weed guam sagittis ac, posuere ut ipsum. Nulla facilisi. Mauris eget urna id sem porttitor consequat ultrices porttitor magna. Quisque condimentum porta viverra. Suspendisse ac condimentum ante. Duis accumsan augue urna, at ultricies nunc accumsan eget. Nullam eleifend.",cpu.RAM,0x100); updateHTML(); let btn_clk = document.getElementById("btn_clk"); let btn_runtil = document.getElementById("btn_runtil"); let brkpt = document.getElementById("addrbrk"); +let clkinterval = document.getElementById("clkinterval"); let btn_rst = document.getElementById("btn_rst"); let clk_counter = document.getElementById("clk_counter"); let clk_count = 0; @@ -103,12 +104,10 @@ btn_clk.addEventListener('mousedown', function(evt) { cpu.CLOCK(true); clk_count++; clk_counter.innerText = clk_count; - updateHTML(); }); btn_clk.addEventListener('mouseup', function(evt) { cpu.CLOCK(false); - updateHTML(); }); btn_runtil.addEventListener('click', function(evt) { @@ -134,5 +133,6 @@ btn_rst.addEventListener('click', function(evt) { clk_count = 0; clk_counter.innerText = clk_count; - updateHTML(); -}); \ No newline at end of file +}); + +window.requestAnimationFrame(drawCPUInfo); \ No newline at end of file diff --git a/js/microcode_compiler.js b/js/microcode_compiler.js index 7d9078d..ef88db6 100644 --- a/js/microcode_compiler.js +++ b/js/microcode_compiler.js @@ -59,6 +59,15 @@ const CONTROL_ALU_XNOR = CONTROL_OUT_AE | CONTROL_ALUM1 | CONTROL_ALUM0 | CONTRO let Instructions = new Array(); +function FindInstructon(ins) { + for (let a = 0; a < Instructions.length; a++) { + if (Instructions[a].Mnemonic.toLowerCase() === ins.Instruction.toLowerCase()) { + return Instructions[a]; + } + } + return false; +} + function GenerateMicrocode(mcarray,cpu) { for (let a = 0; a < mcarray.length; a++) {