From fda3a38b998908ad584006a6d21b176e806575c7 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sun, 31 Oct 2021 13:47:24 -0700 Subject: Implement single-stepping the core. --- hdl/core.sv | 490 +++++++++++++++++++++++++++++++----------------------------- hdl/top.sv | 3 + 2 files changed, 260 insertions(+), 233 deletions(-) (limited to 'hdl') diff --git a/hdl/core.sv b/hdl/core.sv index eceea78..43a4a1a 100644 --- a/hdl/core.sv +++ b/hdl/core.sv @@ -8,6 +8,9 @@ module core , input bit reset , input bit switch_cont + , input bit switch_stop + , input bit switch_sing_step + , input bit switch_sing_inst // verilator lint_off UNDRIVEN , output bit [ADDR_BITS-1:0] led_pc @@ -40,6 +43,7 @@ module core ); bit run; +bit switch_cont_observed; assign led_run = run; bit mem_ready; @@ -47,6 +51,7 @@ bit mem_valid; bit mem_write; bit [ADDR_BITS-1:0] mem_address; bit [DATA_BITS-1:0] mem_write_data; +assign led_current_address = mem_valid; assign led_df = 0; assign led_if = 0; @@ -106,7 +111,6 @@ bit [8:0] operand; bit [DATA_BITS-1:0] acc; bit link; -assign led_pc = pc; assign led_acc = acc; assign led_link = link; @@ -147,17 +151,28 @@ assign led_pause = state == MEMWAIT || state == HALT; always_ff @(posedge clk) begin if (reset) begin run = 0; + switch_cont_observed = 0; mem_valid = 0; rx_ready = 0; tx_valid = 0; tx_data = 0; pc = 'o200; + led_pc = pc; acc = 0; link = 1; kbd_valid = 0; state = state.first; - end else if (run || switch_cont) begin - run = 1; + end else begin + if (switch_cont && !switch_cont_observed) begin + run = 1; + switch_cont_observed = 1; + end + + if (!switch_cont) + switch_cont_observed = 0; + + if (switch_stop) + run = 0; if (`lag(tx_ready)) tx_valid = 0; if (rx_ready && `lag(rx_valid)) begin @@ -165,259 +180,268 @@ always_ff @(posedge clk) begin kbd_data = {4'b0, 1'b1, `lag(rx_data[6:0])}; end - case (state) - FETCH: begin - mem_valid = 1; - mem_address = pc; - mem_write = 0; - if (`lag(mem_ready)) begin - state = DECODE; - page = pc[ADDR_BITS-1:7]; - ++pc; + if (run) begin + case (state) + FETCH: begin + mem_valid = 1; + mem_address = pc; + mem_write = 0; + if (`lag(mem_ready)) begin + state = DECODE; + page = pc[ADDR_BITS-1:7]; + led_pc = pc; + ++pc; + end end - end - - DECODE: begin - mem_valid = 0; - mem_write = 0; - if (`lag(mem_read_valid)) begin - state = FETCH; - led_memdata = `lag(mem_read_data); - {opcode, operand} = `lag(mem_read_data); -// $display("%o: decode %o %o", pc-1, opcode, operand); - // verilator lint_off WIDTH -// $display("%o %b %o 0000", 14'(pc-1), link, acc); - // verilator lint_on WIDTH - {i, z, wip} = operand; - if (z) - address = {page, wip}; - else - address = {5'b0, wip}; - case (opcode) - 'o0, 'o1, 'o2: state = i ? INDIRECT : AGEN; - 'o3, 'o4: state = i ? INDIRECT : EXEC; - 'o5: begin - if (i) begin - state = INDIRECT; - end else begin - pc = address; - end - end - 'o7: 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("%o: unsupported front panel switch test", pc); - $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) pc++; - if (cla) acc = 0; - if (osr) begin - $display("%o: unsupported front panel switch test", pc); - $finish; - end - if (hlt) state = HALT; - end - default: begin - $display("%o: decoded unknown opcode %o %o", pc-1, opcode, operand); - $finish; - end - endcase - end - 'o6: begin - case (operand[8:3]) - 'o00: begin - case (operand[2:0]) - 'o0, 'o1: ; - default: $display("%o: unsupported 600%o op", pc-1, operand[2:0]); - endcase + + DECODE: begin + mem_valid = 0; + mem_write = 0; + if (`lag(mem_read_valid)) begin + state = FETCH; + led_memdata = `lag(mem_read_data); + {opcode, operand} = `lag(mem_read_data); + // $display("%o: decode %o %o", pc-1, opcode, operand); + // verilator lint_off WIDTH + // $display("%o %b %o 0000", 14'(pc-1), link, acc); + // verilator lint_on WIDTH + {i, z, wip} = operand; + if (z) + address = {page, wip}; + else + address = {5'b0, wip}; + case (opcode) + 'o0, 'o1, 'o2: state = i ? INDIRECT : AGEN; + 'o3, 'o4: state = i ? INDIRECT : EXEC; + 'o5: begin + if (i) begin + state = INDIRECT; + end else begin + pc = address; end - 'o03: begin - case (operand[2:0]) - 'o1: if (kbd_valid) pc++; - 'o6: begin - acc = kbd_data; - kbd_valid = 0; + end + 'o7: 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 - default: begin - $display("%o: unsupported keyboard op %o", pc-1, operand[2:0]); - $finish; + if (ral && !rar) begin + {link, acc} = {acc, link}; + if (bsw) {link, acc} = {acc, link}; end - endcase - end - 'o04: begin - case (operand[2:0]) - 'o1: if (!tx_valid) pc++; - 'o6: begin - tx_valid = 1; - tx_data = {1'b0, acc[6:0]}; + 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("%o: unsupported front panel switch test", pc); + $finish; end - default: begin - $display("%o: unsupported tty op %o", pc-1, operand[2:0]); + 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) pc++; + if (cla) acc = 0; + if (osr) begin + $display("%o: unsupported front panel switch test", pc); $finish; end - endcase - end - default: begin - $display("%o: unsupported device %o (operation %o)", pc-1, operand[8:3], operand[2:0]); + if (hlt) state = HALT; + end + default: begin + $display("%o: decoded unknown opcode %o %o", pc-1, opcode, operand); + $finish; + end + endcase + end + 'o6: begin + case (operand[8:3]) + 'o00: begin + case (operand[2:0]) + 'o0, 'o1: ; + default: $display("%o: unsupported 600%o op", pc-1, operand[2:0]); + endcase + end + 'o03: begin + case (operand[2:0]) + 'o1: if (kbd_valid) pc++; + 'o6: begin + acc = kbd_data; + kbd_valid = 0; + end + default: begin + $display("%o: unsupported keyboard op %o", pc-1, operand[2:0]); + $finish; + end + endcase + end + 'o04: begin + case (operand[2:0]) + 'o1: if (!tx_valid) pc++; + 'o6: begin + tx_valid = 1; + tx_data = {1'b0, acc[6:0]}; + end + default: begin + $display("%o: unsupported tty op %o", pc-1, operand[2:0]); + $finish; + end + endcase + end + default: begin + $display("%o: unsupported device %o (operation %o)", pc-1, operand[8:3], operand[2:0]); + end + endcase + end + default: begin + $display("%o: decoded unknown opcode %o %o", pc-1, opcode, operand); + $finish; + end + endcase + end + end + + INDIRECT: begin + mem_valid = 1; + mem_write = 0; + mem_address = address; + state = `lag(mem_ready) ? INDIRECTED : INDIRECT; + end + + INDIRECTED: begin + if (`lag(mem_ready)) begin + mem_valid = 0; + mem_write = 0; + end + if (`lag(mem_read_valid)) begin + if (address[7:3] == 5'b00001) begin + led_memdata = `lag(mem_read_data); + address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; + address += 1; + state = PREINC; + end else begin + led_memdata = `lag(mem_read_data); + address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; + case (opcode) + 'o0, 'o1, 'o2: state = AGEN; + 'o3, 'o4: state = EXEC; + 'o5: begin + pc = address; + state = FETCH; end endcase end - default: begin - $display("%o: decoded unknown opcode %o %o", pc-1, opcode, operand); - $finish; - end - endcase + end end - end - INDIRECT: begin - mem_valid = 1; - mem_write = 0; - mem_address = address; - state = `lag(mem_ready) ? INDIRECTED : INDIRECT; - end + PREINC: begin + mem_valid = 1; + mem_write = 1; + mem_write_data = address[DATA_BITS-1:0]; + led_memdata = mem_write_data; + case (opcode) + 'o0, 'o1, 'o2: state = `lag(mem_ready) ? AGEN : PREINC; + 'o3, 'o4, 'o5: state = `lag(mem_ready) ? EXEC : PREINC; + endcase + end - INDIRECTED: begin - if (`lag(mem_ready)) begin - mem_valid = 0; - mem_write = 0; + AGEN: begin + mem_valid = 1; + case (opcode) + 'o0, 'o1, 'o2: mem_write = 0; + endcase + mem_address = address; + state = `lag(mem_ready) ? EXEC : AGEN; end - if (`lag(mem_read_valid)) begin - if (address[7:3] == 5'b00001) begin - led_memdata = `lag(mem_read_data); - address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; - address += 1; - state = PREINC; - end else begin - led_memdata = `lag(mem_read_data); - address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `lag(mem_read_data)}; + + EXEC: begin + automatic bit stall = 0; + if (`lag(mem_ready)) begin + mem_valid = 0; + mem_write = 0; + end else if (mem_valid) begin + stall = 1; + end + case (opcode) + 'o0, 'o1, 'o2: if (! `lag(mem_read_valid)) stall = 1; + endcase + if (! stall) begin + state = FETCH; case (opcode) - 'o0, 'o1, 'o2: state = AGEN; - 'o3, 'o4: state = EXEC; - 'o5: begin - pc = address; - state = FETCH; + 'o0: begin led_memdata = `lag(mem_read_data); acc &= `lag(mem_read_data); end + 'o1: begin led_memdata = `lag(mem_read_data); {link, acc} += {1'b0, `lag(mem_read_data)}; end + 'o2: begin + mem_valid = 1; + mem_address = address; + mem_write = 1; + mem_write_data = `lag(mem_read_data) + 1; + led_memdata = mem_write_data; + if (mem_write_data == 0) ++pc; + state = MEMWAIT; + end + 'o3: begin + mem_valid = 1; + mem_address = address; + mem_write = 1; + mem_write_data = acc; + led_memdata = mem_write_data; + acc = 0; + state = MEMWAIT; end + 'o4: begin + mem_valid = 1; + mem_address = address; + mem_write = 1; + mem_write_data = pc[DATA_BITS-1:0]; + led_memdata = mem_write_data; + pc = address + 1; + state = MEMWAIT; + end + 'o5: pc = address; endcase end end - end - - PREINC: begin - mem_valid = 1; - mem_write = 1; - mem_write_data = address[DATA_BITS-1:0]; - led_memdata = mem_write_data; - case (opcode) - 'o0, 'o1, 'o2: state = `lag(mem_ready) ? AGEN : PREINC; - 'o3, 'o4, 'o5: state = `lag(mem_ready) ? EXEC : PREINC; - endcase - end - - AGEN: begin - mem_valid = 1; - case (opcode) - 'o0, 'o1, 'o2: mem_write = 0; - endcase - mem_address = address; - state = `lag(mem_ready) ? EXEC : AGEN; - end - - EXEC: begin - automatic bit stall = 0; - if (`lag(mem_ready)) begin - mem_valid = 0; - mem_write = 0; - end else if (mem_valid) begin - stall = 1; - end - case (opcode) - 'o0, 'o1, 'o2: if (! `lag(mem_read_valid)) stall = 1; - endcase - if (! stall) begin - state = FETCH; - case (opcode) - 'o0: begin led_memdata = `lag(mem_read_data); acc &= `lag(mem_read_data); end - 'o1: begin led_memdata = `lag(mem_read_data); {link, acc} += {1'b0, `lag(mem_read_data)}; end - 'o2: begin - mem_valid = 1; - mem_address = address; - mem_write = 1; - mem_write_data = `lag(mem_read_data) + 1; - led_memdata = mem_write_data; - if (mem_write_data == 0) ++pc; - state = MEMWAIT; - end - 'o3: begin - mem_valid = 1; - mem_address = address; - mem_write = 1; - mem_write_data = acc; - led_memdata = mem_write_data; - acc = 0; - state = MEMWAIT; - end - 'o4: begin - mem_valid = 1; - mem_address = address; - mem_write = 1; - mem_write_data = pc[DATA_BITS-1:0]; - led_memdata = mem_write_data; - pc = address + 1; - state = MEMWAIT; - end - 'o5: pc = address; - endcase + + MEMWAIT: state = `lag(mem_ready) ? FETCH : MEMWAIT; + + HALT: begin + $display("\nhalt state reached"); + $finish; end - end + endcase - MEMWAIT: state = `lag(mem_ready) ? FETCH : MEMWAIT; + if (switch_sing_step) + run = 0; - HALT: begin - $display("\nhalt state reached"); - $finish; - end - endcase + if (state == FETCH && switch_sing_inst) + run = 0; - rx_ready = !kbd_valid; + rx_ready = !kbd_valid; + end end end diff --git a/hdl/top.sv b/hdl/top.sv index 214ea1b..00225ee 100644 --- a/hdl/top.sv +++ b/hdl/top.sv @@ -114,6 +114,9 @@ core cpu , .reset(reset) , .switch_cont(switch_cont) + , .switch_stop(switch_stop) + , .switch_sing_step(switch_sing_step) + , .switch_sing_inst(switch_sing_inst) , .led_pc(led_pc) , .led_memaddr(led_memaddr) -- cgit v1.2.3