From 9b8b9b69d0b2560b2727330d5a20b5133af140af Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 6 May 2016 12:14:22 -0700 Subject: [PATCH] Make -H halt the core right out of reset. Added a test, too. --- riscv/execute.cc | 15 ++++++++------- riscv/processor.cc | 7 +++++-- riscv/processor.h | 3 ++- riscv/sim.cc | 4 +--- tests/gdbserver.py | 36 ++++++++++++++++++++++++++++++++++++ 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 instructions; std::map 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() -- 2.30.2