Added a test, too.
// 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);
#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);
run = !value;
state.reset();
+ state.dcsr.halt = halt_on_reset;
+ halt_on_reset = false;
set_csr(CSR_MSTATUS, state.mstatus);
if (ext)
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);
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;
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));
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")
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()