From 529c1cc2496e24c6282c3fa9e0a45272b7f500b6 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sun, 2 May 2021 16:58:46 -0700 Subject: Add a bunch of microcoded instructions. This is a minimum viable PDP-8 that can print "Hello, world!" and halt. --- hdl/core.sv | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- sim/main.cpp | 21 ++++++++------ 2 files changed, 103 insertions(+), 11 deletions(-) diff --git a/hdl/core.sv b/hdl/core.sv index 5bee974..02ff231 100644 --- a/hdl/core.sv +++ b/hdl/core.sv @@ -115,6 +115,7 @@ always_ff @(posedge clk) begin if (`lag(mem_read_valid)) begin state = FETCH; {opcode, operand} = `lag(mem_read_data); + $display("%d decode %x: %b %b", $time, pc-1, opcode, operand); {i, z, wip} = operand; if (z) address = {page, wip}; @@ -130,6 +131,89 @@ always_ff @(posedge clk) begin pc = address; end end + 'b111: begin + casez (operand) + 'b0????????: begin + automatic bit cla, cll, cma, cml, rar, ral, bsw, iac; + {cla, cll, cma, cml, rar, ral, bsw, iac} = operand[7:0]; + if (cla) acc = 0; + if (cll) link = 0; + if (cma) acc = ~acc; + if (cml) link = ~link; + if (iac) {link, acc} += 1; + if (rar && !ral) begin + {link, acc} = {acc[0], link, acc[11:1]}; + if (bsw) {link, acc} = {acc[0], link, acc[11:1]}; + end + if (ral && !rar) begin + {link, acc} = {acc, link}; + if (bsw) {link, acc} = {acc, link}; + end + if (bsw && !(rar || ral)) acc = {acc[5:0], acc[11:6]}; + end + 'b1????0??0: begin + automatic bit cla, sma, sza, snl, osr, hlt; + automatic bit skip; + {cla, sma, sza, snl, osr, hlt} = {operand[7:4], operand[2:1]}; + skip = 0; + if (sma && acc[11]) skip = 1; + if (sza && acc == 0) skip = 1; + if (snl && link != 0) skip = 1; + if (skip) pc++; + if (cla) acc = 0; + if (osr) begin + $display("unsupported front panel switch test"); + $finish; + end + if (hlt) state = HALT; + end + 'b1????1??0: begin + automatic bit cla, spa, sna, szl, osr, hlt; + automatic bit skip; + {cla, spa, sna, szl, osr, hlt} = {operand[7:4], operand[2:1]}; + skip = 1; + if (spa && acc[11]) skip = 0; + if (sna && acc == 0) skip = 0; + if (szl && link != 0) skip = 0; + if (skip && (spa || sna || szl)) pc++; + if (cla) acc = 0; + if (osr) begin + $display("unsupported front panel switch test"); + $finish; + end + if (hlt) state = HALT; + end + default: begin + $display("%d decoded unknown opcode %x: %b %b", $time, pc-1, opcode, operand); + $finish; + end + endcase + end + 'b110: begin + case (operand[8:3]) + 'b000100: begin + case (operand[2:0]) + 'b001: if (!tx_valid) pc++; + 'b110: begin + tx_valid = 1; + tx_data = {1'b0, acc[6:0]}; + end + default: begin + $display("unsupported device op %b", operand[2:0]); + $finish; + end + endcase + end + default: begin + $display("unsupported device %b", operand[8:3]); + $finish; + end + endcase + end + default: begin + $display("%d decoded unknown opcode %x: %b %b", $time, pc-1, opcode, operand); + $finish; + end endcase end end @@ -170,8 +254,8 @@ always_ff @(posedge clk) begin mem_write = 1; mem_write_data = address[DATA_BITS-1:0]; case (opcode) - 'b000, 'b001, 'b010: state = `lag(mem_ready) ? PREINC : AGEN; - 'b011, 'b100, 'b101: state = `lag(mem_ready) ? PREINC : EXEC; + 'b000, 'b001, 'b010: state = `lag(mem_ready) ? AGEN : PREINC; + 'b011, 'b100, 'b101: state = `lag(mem_ready) ? EXEC : PREINC; endcase end @@ -231,7 +315,10 @@ always_ff @(posedge clk) begin MEMWAIT: state = `lag(mem_ready) ? FETCH : MEMWAIT; - HALT: $finish; + HALT: begin + $display("%d halt state reached", $time); + $finish; + end endcase end end diff --git a/sim/main.cpp b/sim/main.cpp index f082464..cc1c596 100644 --- a/sim/main.cpp +++ b/sim/main.cpp @@ -5,6 +5,13 @@ #include "Vtop.h" +std::uint64_t phases = 0; + +double sc_time_stamp() +{ + return (double)phases / 2; +} + int main(int argc, const char *argv[]) { Verilated::commandArgs(argc, argv); @@ -21,31 +28,29 @@ int main(int argc, const char *argv[]) std::cout << "*** RESET SEQUENCE ***\n"; - std::uint64_t time = 0; - top.native_clk = 0; top.reset_n = 0; top.eval(); - vcd.dump(++time); + vcd.dump(++phases); top.native_clk = 1; top.eval(); - vcd.dump(++time); + vcd.dump(++phases); top.native_clk = 0; top.reset_n = 1; top.eval(); - vcd.dump(++time); + vcd.dump(++phases); std::cout << "*** MAIN LOOP ***\n"; - for (unsigned int i = 0; i < 100000 && !Verilated::gotFinish(); ++i) { + for (unsigned int i = 0; i < 10000 && !Verilated::gotFinish(); ++i) { top.native_clk = 1; top.eval(); - vcd.dump(++time); + vcd.dump(++phases); top.native_clk = 0; top.eval(); - vcd.dump(++time); + vcd.dump(++phases); } std::cout << "\n"; -- cgit v1.2.3