aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riscv/execute.cc15
-rw-r--r--riscv/processor.cc7
-rw-r--r--riscv/processor.h3
-rw-r--r--riscv/sim.cc4
-rwxr-xr-xtests/gdbserver.py36
5 files changed, 52 insertions, 13 deletions
diff --git a/riscv/execute.cc b/riscv/execute.cc
index 03588f3..a0848d7 100644
--- a/riscv/execute.cc
+++ b/riscv/execute.cc
@@ -54,13 +54,14 @@ static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
// fetch/decode/execute loop
void processor_t::step(size_t n)
{
- // TODO: get_interrupt() isn't super fast. Does that matter?
- if (state.dcsr.cause == DCSR_CAUSE_NONE &&
- sim->debug_module.get_interrupt(id)) {
- enter_debug_mode(DCSR_CAUSE_DEBUGINT);
- }
-
- if (state.dcsr.cause != DCSR_CAUSE_NONE) {
+ if (state.dcsr.cause == DCSR_CAUSE_NONE) {
+ // TODO: get_interrupt() isn't super fast. Does that matter?
+ if (sim->debug_module.get_interrupt(id)) {
+ enter_debug_mode(DCSR_CAUSE_DEBUGINT);
+ } else if (state.dcsr.halt) {
+ enter_debug_mode(DCSR_CAUSE_HALT);
+ }
+ } else {
// In Debug Mode, just do 11 steps at a time. Otherwise we're going to be
// spinning the rest of the time anyway.
n = std::min(n, (size_t) 11);
diff --git a/riscv/processor.cc b/riscv/processor.cc
index d43defc..7f75471 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -21,9 +21,10 @@
#undef STATE
#define STATE state
-processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id)
+processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id,
+ bool halt_on_reset)
: debug(false), sim(sim), ext(NULL), disassembler(new disassembler_t),
- id(id), run(false)
+ id(id), run(false), halt_on_reset(halt_on_reset)
{
parse_isa_string(isa);
@@ -145,6 +146,8 @@ void processor_t::reset(bool value)
run = !value;
state.reset();
+ state.dcsr.halt = halt_on_reset;
+ halt_on_reset = false;
set_csr(CSR_MSTATUS, state.mstatus);
if (ext)
diff --git a/riscv/processor.h b/riscv/processor.h
index 721da2c..730ae78 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -101,7 +101,7 @@ struct state_t
class processor_t : public abstract_device_t
{
public:
- processor_t(const char* isa, sim_t* sim, uint32_t id);
+ processor_t(const char* isa, sim_t* sim, uint32_t id, bool halt_on_reset=false);
~processor_t();
void set_debug(bool value);
@@ -146,6 +146,7 @@ private:
std::string isa_string;
bool run; // !reset
bool histogram_enabled;
+ bool halt_on_reset;
std::vector<insn_desc_t> instructions;
std::map<reg_t,uint64_t> pc_histogram;
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 4b4eed4..d17289d 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -47,9 +47,7 @@ sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, bool halted,
debug_mmu = new mmu_t(this, NULL);
for (size_t i = 0; i < procs.size(); i++) {
- procs[i] = new processor_t(isa, this, i);
- if (halted)
- procs[i]->enter_debug_mode(DCSR_CAUSE_HALT);
+ procs[i] = new processor_t(isa, this, i, halted);
}
rtc.reset(new rtc_t(procs));
diff --git a/tests/gdbserver.py b/tests/gdbserver.py
index 2979606..0f9ee1d 100755
--- a/tests/gdbserver.py
+++ b/tests/gdbserver.py
@@ -6,6 +6,25 @@ import unittest
import tempfile
import time
+class InstantHaltTest(unittest.TestCase):
+ def setUp(self):
+ self.binary = testlib.compile("debug.c")
+ self.spike, self.port = testlib.spike(self.binary, halted=True)
+ self.gdb = testlib.Gdb()
+ self.gdb.command("file %s" % self.binary)
+ self.gdb.command("target extended-remote localhost:%d" % self.port)
+
+ def tearDown(self):
+ self.spike.kill()
+ self.spike.wait()
+
+ def test_instant_halt(self):
+ self.assertEqual(0x1000, self.gdb.p("$pc"))
+ # For some reason instret resets to 0.
+ self.assertLess(self.gdb.p("$instret"), 8)
+ self.gdb.command("stepi")
+ self.assertNotEqual(0x1000, self.gdb.p("$pc"))
+
class DebugTest(unittest.TestCase):
def setUp(self):
self.binary = testlib.compile("debug.c")
@@ -137,5 +156,22 @@ class RegsTest(unittest.TestCase):
self.assertEqual(9, self.gdb.p("$x1"))
self.assertEqual(9, self.gdb.p("$csr1"))
+#class MprvTest(unittest.TestCase):
+# def setUp(self):
+# self.binary = testlib.compile("mprv.S")
+# self.spike, self.port = testlib.spike(self.binary, halted=False)
+# self.gdb = testlib.Gdb()
+# self.gdb.command("file %s" % self.binary)
+# self.gdb.command("target extended-remote localhost:%d" % self.port)
+#
+# def tearDown(self):
+# self.spike.kill()
+# self.spike.wait()
+#
+# def test_mprv(self):
+# """Test that the debugger can access memory when MPRV is set."""
+# output = self.gdb.command("p/x data");
+# self.assertIn("0xbead", output)
+
if __name__ == '__main__':
unittest.main()