summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-12-07 19:18:04 -0600
committerAlejandro Soto <alejandro@34project.org>2022-12-07 19:51:41 -0600
commitc39552375661e495b344e8386649ade92a4d45b2 (patch)
tree45623ce35964e43ae7d8804c1ef1c6dedb3ba7a1
parentb1761b8eac5777c09723bbc8cd31cc05d8ec35ae (diff)
Implement single-stepping
-rw-r--r--conspiracion.qsf3
-rw-r--r--rtl/core/arm810.sv7
-rw-r--r--rtl/core/control/control.sv6
-rw-r--r--rtl/core/control/debug.sv25
-rw-r--r--rtl/core/control/issue.sv2
-rw-r--r--rtl/core/decode/decode.sv1
-rw-r--r--rtl/core/decode/mux.sv1
-rw-r--r--rtl/core/fetch/fetch.sv6
-rw-r--r--rtl/core/fetch/prefetch.sv6
-rw-r--r--rtl/core/porch/porch.sv8
-rw-r--r--rtl/core/uarch.sv1
-rw-r--r--rtl/top/conspiracion.sv1
-rw-r--r--sim/gdbstub.py24
-rwxr-xr-xsim/sim.py5
-rw-r--r--tb/top/conspiracion.cpp9
15 files changed, 78 insertions, 27 deletions
diff --git a/conspiracion.qsf b/conspiracion.qsf
index c6252b9..5dab632 100644
--- a/conspiracion.qsf
+++ b/conspiracion.qsf
@@ -212,6 +212,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/control.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/coproc.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/cycles.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/data.sv
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/debug.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/exception.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/issue.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/core/control/mul.sv
@@ -364,4 +365,4 @@ set_global_assignment -name SIGNALTAP_FILE bus_test.stp
-set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file
+set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
diff --git a/rtl/core/arm810.sv b/rtl/core/arm810.sv
index 05bce76..1771464 100644
--- a/rtl/core/arm810.sv
+++ b/rtl/core/arm810.sv
@@ -6,6 +6,7 @@ module arm810
rst_n,
irq,
halt,
+ step,
output ptr bus_addr,
output logic bus_start,
@@ -21,19 +22,21 @@ module arm810
ptr fetch_insn_pc, fetch_head, insn_addr;
word fetch_insn;
- logic stall, flush, prefetch_flush, insn_start;
+ logic fetch_nop, stall, flush, prefetch_flush, insn_start;
//TODO
- assign prefetch_flush = 0;
+ assign prefetch_flush = halt;
core_fetch #(.PREFETCH_ORDER(2)) fetch
(
+ .nop(fetch_nop),
.addr(insn_addr),
.insn(fetch_insn),
.fetch(insn_start),
.fetched(insn_ready),
.insn_pc(fetch_insn_pc),
.fetch_data(insn_data_rd),
+ .porch_insn_pc(insn_pc),
.*
);
diff --git a/rtl/core/control/control.sv b/rtl/core/control/control.sv
index 92e27d6..7658ee9 100644
--- a/rtl/core/control/control.sv
+++ b/rtl/core/control/control.sv
@@ -5,6 +5,7 @@ module core_control
input logic clk,
rst_n,
halt,
+ step,
input insn_decode dec,
input ptr insn_pc,
@@ -156,4 +157,9 @@ module core_control
.*
);
+ core_control_debug ctrl_dbg
+ (
+ .*
+ );
+
endmodule
diff --git a/rtl/core/control/debug.sv b/rtl/core/control/debug.sv
new file mode 100644
index 0000000..35b1334
--- /dev/null
+++ b/rtl/core/control/debug.sv
@@ -0,0 +1,25 @@
+`include "core/uarch.sv"
+
+module core_control_debug
+(
+ input logic clk,
+ rst_n,
+ step,
+
+ input ctrl_cycle next_cycle,
+ input logic issue,
+ next_bubble,
+ input insn_decode dec,
+
+ output logic breakpoint
+);
+
+ logic stable, step_trigger;
+
+ assign stable = next_cycle.issue && !dec.ctrl.nop && !next_bubble;
+ assign breakpoint = stable && (dec.ctrl.bkpt || step_trigger);
+
+ always @(posedge clk or negedge rst_n)
+ step_trigger <= !rst_n ? 0 : step && (step_trigger || stable) && !breakpoint;
+
+endmodule
diff --git a/rtl/core/control/issue.sv b/rtl/core/control/issue.sv
index b8cf3ff..ffdf250 100644
--- a/rtl/core/control/issue.sv
+++ b/rtl/core/control/issue.sv
@@ -18,7 +18,6 @@ module core_control_issue
output logic issue,
undefined,
- breakpoint,
output ptr pc,
pc_visible,
next_pc_visible
@@ -28,7 +27,6 @@ module core_control_issue
assign valid = !next_bubble && !halt;
assign issue = next_cycle.issue && dec.ctrl.execute && valid;
- assign breakpoint = issue && dec.ctrl.bkpt;
assign next_pc_visible = insn_pc + 2;
always_ff @(posedge clk or negedge rst_n)
diff --git a/rtl/core/decode/decode.sv b/rtl/core/decode/decode.sv
index 6534897..c4ffd52 100644
--- a/rtl/core/decode/decode.sv
+++ b/rtl/core/decode/decode.sv
@@ -26,6 +26,7 @@ module core_decode
assign dec.branch = dec_branch;
assign dec.coproc = dec_coproc;
+ assign dec_ctrl.nop = 0;
assign dec_ctrl.mul = mul;
assign dec_ctrl.psr = psr;
assign dec_ctrl.ldst = ldst;
diff --git a/rtl/core/decode/mux.sv b/rtl/core/decode/mux.sv
index f05b711..25e390b 100644
--- a/rtl/core/decode/mux.sv
+++ b/rtl/core/decode/mux.sv
@@ -262,7 +262,6 @@ module core_decode_mux
mul = 1'bx;
psr = 1'bx;
- bkpt = 1'bx;
ldst = 1'bx;
branch = 1'bx;
coproc = 1'bx;
diff --git a/rtl/core/fetch/fetch.sv b/rtl/core/fetch/fetch.sv
index acc8e9d..c024e7d 100644
--- a/rtl/core/fetch/fetch.sv
+++ b/rtl/core/fetch/fetch.sv
@@ -11,18 +11,20 @@ module core_fetch
wr_pc,
prefetch_flush,
input ptr branch_target,
+ porch_insn_pc,
input word wr_current,
fetch_data,
output logic fetch,
flush,
+ nop,
output word insn,
output ptr insn_pc,
addr,
fetch_head
);
- ptr next_pc, hold_addr, target;
+ ptr hold_addr, target;
logic branch, prefetch_ready, fetched_valid, discard, pending, next_pending;
assign fetch = prefetch_ready && !discard;
@@ -44,7 +46,7 @@ module core_fetch
if(branch)
fetch_head = target;
else if(prefetch_flush)
- fetch_head = next_pc;
+ fetch_head = porch_insn_pc;
else
fetch_head = {30{1'bx}};
diff --git a/rtl/core/fetch/prefetch.sv b/rtl/core/fetch/prefetch.sv
index 2f0a866..1b5a4c5 100644
--- a/rtl/core/fetch/prefetch.sv
+++ b/rtl/core/fetch/prefetch.sv
@@ -13,15 +13,17 @@ module core_prefetch
output word insn,
output ptr insn_pc,
- next_pc,
- output logic fetch
+ output logic fetch,
+ nop
);
localparam SIZE = (1 << ORDER) - 1;
+ ptr next_pc;
logic[31:0] prefetch[SIZE];
logic[ORDER - 1:0] valid;
+ assign nop = flush ? 1 : ~|valid;
assign insn = flush ? `NOP : prefetch[0];
assign next_pc = ~stall & |valid ? insn_pc + 1 : insn_pc;
assign fetch = !stall || ~&valid;
diff --git a/rtl/core/porch/porch.sv b/rtl/core/porch/porch.sv
index 238da88..4369836 100644
--- a/rtl/core/porch/porch.sv
+++ b/rtl/core/porch/porch.sv
@@ -9,6 +9,7 @@ module core_porch
input psr_flags flags,
input word fetch_insn,
+ input logic fetch_nop,
input ptr fetch_insn_pc,
fetch_head,
input insn_decode fetch_dec,
@@ -18,12 +19,13 @@ module core_porch
output insn_decode dec
);
- logic execute, conditional, undefined;
+ logic execute, conditional, undefined, nop;
insn_decode hold_dec;
always_comb begin
dec = hold_dec;
- dec.ctrl.execute = !flush && dec.ctrl.execute && execute;
+ dec.ctrl.nop = nop;
+ dec.ctrl.execute = !flush && dec.ctrl.execute && execute && !nop;
dec.ctrl.undefined = !flush && (dec.ctrl.undefined || undefined);
dec.ctrl.conditional = !flush && (dec.ctrl.conditional || conditional);
end
@@ -35,10 +37,12 @@ module core_porch
always_ff @(posedge clk or negedge rst_n)
if(!rst_n) begin
+ nop <= 0; // Even though it is a NOP
insn <= `NOP;
insn_pc <= 0;
hold_dec <= {$bits(hold_dec){1'b0}};
end else if(flush || !stall) begin
+ nop <= flush ? 1 : fetch_nop;
insn <= flush ? `NOP : fetch_insn;
insn_pc <= flush ? fetch_head : fetch_insn_pc;
hold_dec <= fetch_dec;
diff --git a/rtl/core/uarch.sv b/rtl/core/uarch.sv
index ac3b567..74e536b 100644
--- a/rtl/core/uarch.sv
+++ b/rtl/core/uarch.sv
@@ -88,6 +88,7 @@ typedef struct packed
ldst,
mul,
psr,
+ nop,
bkpt;
} ctrl_decode;
diff --git a/rtl/top/conspiracion.sv b/rtl/top/conspiracion.sv
index 507a74c..c9e940f 100644
--- a/rtl/top/conspiracion.sv
+++ b/rtl/top/conspiracion.sv
@@ -3,6 +3,7 @@ module conspiracion
input wire clk_clk,
input wire rst_n,
input wire halt,
+ input wire step,
output wire cpu_halted,
output wire breakpoint,
output wire [12:0] memory_mem_a,
diff --git a/sim/gdbstub.py b/sim/gdbstub.py
index e214a73..75c15cb 100644
--- a/sim/gdbstub.py
+++ b/sim/gdbstub.py
@@ -22,8 +22,8 @@ def halt():
if haltFromStop:
reply(b'S05')
- haltFromStop = False
+ haltFromStop = True
while True:
data = client.recv(4096)
if not data:
@@ -52,9 +52,8 @@ def halt():
if data == b'?':
out = b'S05'
- elif data[0] == b'c'[0]:
- assert not data[1:] #TODO
- break
+ elif data == b'c':
+ return 'continue'
elif data == b'D':
out = b'OK'
elif data == b'g':
@@ -74,14 +73,14 @@ def halt():
elif data[0] == b'p'[0]:
reg = gdb_reg(int(data[1:], 16))
out = hexout(read_reg(reg) if reg is not None else None)
+ elif data == b's':
+ return 'step'
else:
- print('unhandled packet:', data)
+ print('unhandled packet:', data, file=sys.stderr)
out = b''
reply(out)
- haltFromStop = True
-
def reply(out):
client.send(b'$' + out + b'#' + hexout(sum(out) & 0xff, 1))
@@ -100,26 +99,27 @@ def gdb_reg(n):
if mode == 0b10001:
regs = (r8_fiq, r9_fiq, r10_fiq, r11_fiq, r12_fiq)
else:
- regs = (r8_fiq, r9_fiq, r10_fiq, r11_fiq, r12_fiq)
+ regs = (r8_usr, r9_usr, r10_usr, r11_usr, r12_usr)
return regs[n - 8]
if 13 <= n < 15:
if mode == 0b10011:
regs = (r13_svc, r14_svc)
- if mode == 0b10111:
+ elif mode == 0b10111:
regs = (r13_abt, r14_abt)
- if mode == 0b11011:
+ elif mode == 0b11011:
regs = (r13_und, r14_und)
- if mode == 0b10010:
+ elif mode == 0b10010:
regs = (r13_irq, r14_irq)
- if mode == 0b10001:
+ elif mode == 0b10001:
regs = (r13_fiq, r14_fiq)
else:
regs = (r13_usr, r14_usr)
return regs[n - 13]
+ print('bad gdb regnum:', n, file=sys.stderr)
return None
def hexout(data, size=4):
diff --git a/sim/sim.py b/sim/sim.py
index 16ceb54..be846fb 100755
--- a/sim/sim.py
+++ b/sim/sim.py
@@ -343,11 +343,12 @@ while True:
else:
break
+ mode = None
halted = True
if halt:
- halt()
+ mode = halt()
- print('continue', file=sim_end, flush=True)
+ print('step' if mode == 'step' else 'continue', file=sim_end, flush=True)
if not halt:
break
diff --git a/tb/top/conspiracion.cpp b/tb/top/conspiracion.cpp
index 96fd57f..bd1086a 100644
--- a/tb/top/conspiracion.cpp
+++ b/tb/top/conspiracion.cpp
@@ -391,6 +391,7 @@ int main(int argc, char **argv)
ttyJ0.takeover();
}
+ top.step = 0;
top.halt = start_halted;
top.rst_n = 0;
cycle();
@@ -458,6 +459,9 @@ int main(int argc, char **argv)
if(top.cpu_halted)
{
+ top.step = 0;
+ top.halt = 0;
+
do_reg_dump();
std::fputs("=== halted ===\n", ctrl);
@@ -486,7 +490,10 @@ int main(int argc, char **argv)
const char *cmd = std::strtok(line, " ");
if(!std::strcmp(cmd, "continue"))
{
- top.halt = 0;
+ break;
+ } else if(!std::strcmp(cmd, "step"))
+ {
+ top.step = 1;
break;
} else if(!std::strcmp(cmd, "dump-mem"))
{