Add debug_module bus device.
authorTim Newsome <tim@sifive.com>
Sun, 24 Apr 2016 15:54:19 +0000 (08:54 -0700)
committerTim Newsome <tim@sifive.com>
Mon, 23 May 2016 19:12:11 +0000 (12:12 -0700)
This should replace the ROM hack I implemented earlier, but for now both
exist together.

Back to the point where gdb connects, core jumps to ROM->RAM->ROM.

18 files changed:
debug_rom/Makefile
debug_rom/debug_rom.S
debug_rom/debug_rom.h
riscv/debug_module.cc [new file with mode: 0644]
riscv/debug_module.h [new file with mode: 0644]
riscv/decode.h
riscv/devices.cc
riscv/devices.h
riscv/execute.cc
riscv/gdbserver.cc
riscv/gdbserver.h
riscv/mmu.cc
riscv/mmu.h
riscv/processor.cc
riscv/processor.h
riscv/riscv.mk.in
riscv/sim.cc
riscv/sim.h

index d66b84f2feac76716f6055968fcc64bc0a27119f..9d286c9dc74b61c36e3671cc66de6c6c048dd7b5 100644 (file)
@@ -5,7 +5,7 @@ CC = $(RISCV)/bin/riscv64-unknown-elf-gcc
 OBJCOPY = $(RISCV)/bin/riscv64-unknown-elf-objcopy
 
 %.o:   %.S
-       $(CC) -c $<
+       $(CC) -I.. -c $<
 
 debug_rom.h:   debug_rom.raw
        xxd -i $^ | sed "s/^unsigned/static const unsigned/" > $@
index 577edbb50c266a596ed6443889b68faac90b9182..7130364b8f7ba163cd7d575eedba64491b14cfe9 100755 (executable)
@@ -1,6 +1,8 @@
 # This code should be functional. Doesn't have to be optimal.
 # I'm writing it to prove that it can be done.
 
+#include "riscv/encoding.h"
+
 # TODO: Update these constants once they're finalized in the doc.
 
 #define DCSR                    0x790
 
 #define DSCRATCH                0x792
 
-#define MCPUID                  0xf00
-#define MHARTID                 0xf10
-
 # TODO: Should be 0x400
 #define DEBUG_RAM               (-0x400)
 #define DEBUG_RAM_SIZE          64
 
-#define SETHALTNOT              0x100
-#define CLEARHALTNOT            0x104
-#define CLEARDEBINT             0x108
+# TODO: Should be 0x100, 0x108
+#define SETHALTNOT              (-0x100)
+#define CLEARDEBINT             (-0x108)
 
         .global entry
         .global resume
@@ -31,7 +30,7 @@ entry:  j       _entry
 resume:
         # Clear debug interrupt.
 clear_debint:
-        csrr    s1, MHARTID
+        csrr    s1, CSR_MHARTID
         sw      s1, CLEARDEBINT(zero)
 clear_debint_loop:
         csrr    s1, DCSR
@@ -39,7 +38,7 @@ clear_debint_loop:
         bnez    s1, clear_debint_loop
 
         # Restore s1.
-        csrr    s1, MCPUID
+        csrr    s1, CSR_MISA
         bltz    s1, restore_not_32
 restore_32:
         lw      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 4)(zero)
@@ -78,7 +77,7 @@ _entry:
 
 jdebugram:
         # Save s1 so that the debug program can use two registers.
-        csrr    s0, MCPUID
+        csrr    s0, CSR_MISA
         bltz    s0, save_not_32
 save_32:
         sw      s1, (DEBUG_RAM + DEBUG_RAM_SIZE - 4)(zero)
@@ -94,7 +93,7 @@ save_128:
         jr      zero, DEBUG_RAM
 
 spontaneous_halt:
-        csrr    s0, MHARTID
+        csrr    s0, CSR_MHARTID
         sw      s0, SETHALTNOT(zero)
         csrsi   DCSR, DCSR_HALT_OFFSET
 
index 10c4fef905eabd16cd8e7072babe1ab4e182ef22..79162c2e140837093b9b7093a4ad832d0d4f3757 100644 (file)
@@ -1,17 +1,17 @@
 static const unsigned char debug_rom_raw[] = {
-  0x6f, 0x00, 0x40, 0x05, 0xf3, 0x24, 0x00, 0xf1, 0x23, 0x24, 0x90, 0x10,
+  0x6f, 0x00, 0x40, 0x05, 0xf3, 0x24, 0x50, 0xf1, 0x23, 0x2c, 0x90, 0xee,
   0xf3, 0x24, 0x00, 0x79, 0x93, 0xf4, 0x04, 0x40, 0xe3, 0x9c, 0x04, 0xfe,
-  0xf3, 0x24, 0x00, 0xf0, 0x63, 0xc6, 0x04, 0x00, 0x83, 0x24, 0xc0, 0xc3,
+  0xf3, 0x24, 0x00, 0xf1, 0x63, 0xc6, 0x04, 0x00, 0x83, 0x24, 0xc0, 0xc3,
   0x6f, 0x00, 0x80, 0x01, 0x93, 0x94, 0x14, 0x00, 0x63, 0xc6, 0x04, 0x00,
   0x83, 0x34, 0x80, 0xc3, 0x6f, 0x00, 0x80, 0x00, 0x13, 0x00, 0x00, 0x00,
   0x73, 0x24, 0x00, 0x79, 0x13, 0x74, 0x84, 0x00, 0x63, 0x04, 0x04, 0x00,
   0x6f, 0x00, 0x40, 0x05, 0x73, 0x24, 0x20, 0x79, 0x73, 0x00, 0x00, 0x10,
   0x73, 0x10, 0x24, 0x79, 0x73, 0x24, 0x00, 0x79, 0x13, 0x74, 0x74, 0x00,
-  0x13, 0x04, 0xd4, 0xff, 0x63, 0x16, 0x04, 0x02, 0x73, 0x24, 0x00, 0xf0,
+  0x13, 0x04, 0xd4, 0xff, 0x63, 0x16, 0x04, 0x02, 0x73, 0x24, 0x00, 0xf1,
   0x63, 0x46, 0x04, 0x00, 0x23, 0x2e, 0x90, 0xc2, 0x67, 0x00, 0x00, 0xc0,
   0x13, 0x14, 0x14, 0x00, 0x63, 0x46, 0x04, 0x00, 0x23, 0x3c, 0x90, 0xc2,
   0x67, 0x00, 0x00, 0xc0, 0x13, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0xc0,
-  0x73, 0x24, 0x00, 0xf1, 0x23, 0x20, 0x80, 0x10, 0x73, 0xe0, 0x01, 0x79,
+  0x73, 0x24, 0x50, 0xf1, 0x23, 0x20, 0x80, 0xf0, 0x73, 0xe0, 0x01, 0x79,
   0x73, 0x24, 0x00, 0x79, 0x13, 0x74, 0x04, 0x40, 0xe3, 0x0c, 0x04, 0xfe,
   0x6f, 0xf0, 0x1f, 0xfc
 };
diff --git a/riscv/debug_module.cc b/riscv/debug_module.cc
new file mode 100644 (file)
index 0000000..b31c4a6
--- /dev/null
@@ -0,0 +1,69 @@
+#include <cassert>
+
+#include "debug_module.h"
+#include "mmu.h"
+
+#include "debug_rom/debug_rom.h"
+
+debug_module_t::debug_module_t()
+{
+  /* Copy Debug ROM into the page. */
+  memcpy(raw_page + DEBUG_ROM_START - DEBUG_START,
+      debug_rom_raw, debug_rom_raw_len);
+}
+
+bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
+{
+  addr = DEBUG_START + addr;
+
+  fprintf(stderr, "ERROR: invalid load from debug module: %ld bytes at 0x%lx\n",
+      len, addr);
+  return false;
+}
+
+bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
+{
+  addr = DEBUG_START + addr;
+
+  if (addr & (len-1)) {
+    fprintf(stderr, "ERROR: unaligned store to debug module: %ld bytes at 0x%lx\n",
+        len, addr);
+    return false;
+  }
+
+  if (addr >= DEBUG_RAM_START && addr + len <= DEBUG_RAM_END) {
+    memcpy(raw_page + addr - DEBUG_START, bytes, len);
+    return true;
+  } else if (len == 4 && addr == DEBUG_CLEARDEBINT) {
+    clear_interrupt(bytes[4] | (bytes[5] << 8) |
+        (bytes[6] << 16) | (bytes[7] << 24));
+    return true;
+  }
+
+  fprintf(stderr, "ERROR: invalid store to debug module: %ld bytes at 0x%lx\n",
+      len, addr);
+  return false;
+}
+
+void debug_module_t::ram_write32(unsigned int index, uint32_t value)
+{
+  char* base = raw_page + DEBUG_RAM_START - DEBUG_START + index * 4;
+  base[0] = value & 0xff;
+  base[1] = (value >> 8) & 0xff;
+  base[2] = (value >> 16) & 0xff;
+  base[3] = (value >> 24) & 0xff;
+}
+
+char* debug_module_t::page(reg_t paddr)
+{
+  fprintf(stderr, "dm::page(0x%lx)\n", paddr);
+
+  assert(PGSHIFT == 12);
+
+  if (paddr == (DEBUG_START & PGMASK)) {
+    return raw_page;
+  }
+
+  fprintf(stderr, "ERROR: invalid page to debug module at 0x%lx\n", paddr);
+  return NULL;
+}
diff --git a/riscv/debug_module.h b/riscv/debug_module.h
new file mode 100644 (file)
index 0000000..10554a8
--- /dev/null
@@ -0,0 +1,37 @@
+// See LICENSE for license details.
+#ifndef _RISCV_DEBUG_MODULE_H
+#define _RISCV_DEBUG_MODULE_H
+
+#include <set>
+
+#include "devices.h"
+
+class debug_module_t : public abstract_device_t
+{
+  public:
+    debug_module_t();
+
+    bool load(reg_t addr, size_t len, uint8_t* bytes);
+    bool store(reg_t addr, size_t len, const uint8_t* bytes);
+    char* page(reg_t paddr);
+
+    void ram_write32(unsigned int index, uint32_t value);
+
+    void set_interrupt(uint32_t hartid) {
+      interrupt.insert(hartid);
+    }
+    void clear_interrupt(uint32_t hartid) {
+      interrupt.erase(hartid);
+    }
+    bool get_interrupt(uint32_t hartid) const {
+      return interrupt.find(hartid) != interrupt.end();
+    }
+
+  private:
+    // Track which interrupts from module to debugger are set.
+    std::set<uint32_t> interrupt;
+    // TODO: use PGSIZE, which requires solving some circular include dependencies.
+    char raw_page[4096];
+};
+
+#endif
index 9b9df5baa896a52e9f8efc65c888cc5b8fe0919a..5732a0d1c5b62bdff96468f2639f30fc3c0d3585 100644 (file)
@@ -14,7 +14,6 @@
 #include "config.h"
 #include "common.h"
 #include <cinttypes>
-#include "debug_rom/debug_rom.h"
 
 typedef int64_t sreg_t;
 typedef uint64_t reg_t;
@@ -238,11 +237,15 @@ private:
 #define DCSR_CAUSE_HALT         5
 
 #define DEBUG_START             0xfffffffffffff000
-#define DEBUG_RAM_START         0xfffffffffffffc00       // TODO: 0x400
-#define DEBUG_RAM_END           (DEBUG_RAM_START + 64)
 #define DEBUG_ROM_START         0xfffffffffffff800       // TODO: 0x800
+#define DEBUG_ROM_RESUME        (DEBUG_ROM_START + 4)
 #define DEBUG_ROM_END           (DEBUG_ROM_START + debug_rom_raw_len)
+#define DEBUG_RAM_START         0xfffffffffffffc00       // TODO: 0x400
+#define DEBUG_RAM_SIZE          64
+#define DEBUG_RAM_END           (DEBUG_RAM_START + DEBUG_RAM_SIZE)
 #define DEBUG_END               0xffffffffffffffff
+#define DEBUG_CLEARDEBINT       0xfffffffffffffef8
+#define DEBUG_SETHALTNOT        0xffffffffffffff00
 #define DEBUG_SIZE              (DEBUG_END - DEBUG_START + 1)
 
 #endif
index c7a63b0044b87e5a9a5dbd3df2958abd95699cd5..e6f5d7d0912b1672d8fda9f9adfec8710a856105 100644 (file)
@@ -20,3 +20,11 @@ bool bus_t::store(reg_t addr, size_t len, const uint8_t* bytes)
     return false;
   return it->second->store(addr - -it->first, len, bytes);
 }
+
+char* bus_t::page(reg_t paddr)
+{
+  auto it = devices.lower_bound(-paddr);
+  if (it == devices.end())
+    return NULL;
+  return it->second->page(paddr);
+}
index cb3b6d962cbe8c649c4e35560f1358c27839137f..83781884b9910aa7fd8934efee25b538194a85ae 100644 (file)
@@ -11,6 +11,9 @@ class abstract_device_t {
  public:
   virtual bool load(reg_t addr, size_t len, uint8_t* bytes) = 0;
   virtual bool store(reg_t addr, size_t len, const uint8_t* bytes) = 0;
+  // Return a pointer to the start of the page that addr falls in, or NULL if
+  // there is no IO device at that address.
+  virtual char* page(reg_t addr) { return NULL; }
   virtual ~abstract_device_t() {}
 };
 
@@ -18,6 +21,9 @@ class bus_t : public abstract_device_t {
  public:
   bool load(reg_t addr, size_t len, uint8_t* bytes);
   bool store(reg_t addr, size_t len, const uint8_t* bytes);
+  // Return a pointer to the start of the page that addr falls in, or NULL if
+  // there is no IO device at that address.
+  char* page(reg_t paddr);
   void add_device(reg_t addr, abstract_device_t* dev);
 
  private:
index 1796c3884ba2a2d2761ddd7512dada25c7cd4b92..25d1d51f2aa5507b96048d1491e1c4ca70f98961 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "processor.h"
 #include "mmu.h"
+#include "sim.h"
 #include <cassert>
 
 
@@ -53,10 +54,18 @@ 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)
 {
-  if (state.dcsr.debugint && state.dcsr.cause == DCSR_CAUSE_NONE) {
+  // 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) {
+    // In Debug Mode, just do 100 steps at a time. Otherwise we're going to be
+    // spinning the rest of the time anyway.
+    n = std::max(n, (size_t) 100);
+  }
+
   while (n > 0) {
     size_t instret = 0;
     reg_t pc = state.pc;
index 4d6df08561e2e3ec9c15b2751bf2aad3604c2c8f..6840cb785e38a30df0d8233533185d22191bd135 100644 (file)
 // Functions to generate RISC-V opcodes.
 // TODO: Does this already exist somewhere?
 
+#define S1      3
 static uint32_t bits(uint32_t value, unsigned int hi, unsigned int lo) {
   return (value >> lo) & ((1 << (hi+1-lo)) - 1);
 }
+
 static uint32_t bit(uint32_t value, unsigned int b) {
   return (value >> b) & 1;
 }
@@ -36,7 +38,26 @@ static uint32_t jal(unsigned int rd, uint32_t imm) {
     (bit(imm, 11) << 20) |
     (bits(imm, 19, 12) << 12) |
     (rd << 7) |
-    0x6f;
+    MATCH_JAL;
+}
+
+static uint32_t csrsi(unsigned int csr, uint8_t imm) {
+  return (csr << 20) |
+    (bits(imm, 4, 0) << 15) |
+    MATCH_CSRRSI;
+}
+
+static uint32_t csrr(unsigned int rd, unsigned int csr) {
+  return (csr << 20) | (rd << 15) | MATCH_CSRRS;
+}
+
+static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 5) << 25) |
+    (src << 20) |
+    (base << 15) |
+    (bits(offset, 4, 0) << 7) |
+    MATCH_SW;
 }
 
 template <typename T>
@@ -143,11 +164,20 @@ gdbserver_t::gdbserver_t(uint16_t port, sim_t *sim) :
 
 void gdbserver_t::write_debug_ram(unsigned int index, uint32_t value)
 {
-  char *ram = sim->debug_ram() + 4 * index;
-  ram[0] = value & 0xff;
-  ram[1] = (value >> 8) & 0xff;
-  ram[2] = (value >> 16) & 0xff;
-  ram[3] = (value >> 24) & 0xff;
+  sim->debug_module.ram_write32(index, value);
+}
+
+void gdbserver_t::halt()
+{
+  processor_t *p = sim->get_core(0);
+  write_debug_ram(0, csrsi(DCSR_ADDRESS, DCSR_HALT_OFFSET));
+  write_debug_ram(1, csrr(S1, DPC_ADDRESS));
+  write_debug_ram(2, sw(S1, 0, (uint16_t) DEBUG_RAM_START));
+  write_debug_ram(3, csrr(S1, DCSR_ADDRESS));
+  write_debug_ram(4, sw(S1, 0, (uint16_t) DEBUG_RAM_START + 8));
+  write_debug_ram(5, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*5))));
+  sim->debug_module.set_interrupt(p->id);
+  state = STATE_HALTING;
 }
 
 void gdbserver_t::accept()
@@ -168,9 +198,7 @@ void gdbserver_t::accept()
     extended_mode = false;
 
     // gdb wants the core to be halted when it attaches.
-    processor_t *p = sim->get_core(0);
-    write_debug_ram(0, jal(0, (uint32_t) (DEBUG_ROM_START + 4 - DEBUG_RAM_START)));
-    p->set_debug_int();
+    halt();
   }
 }
 
@@ -544,7 +572,7 @@ void gdbserver_t::handle_continue(const std::vector<uint8_t> &packet)
   }
 
   // TODO p->set_halted(false, HR_NONE);
-  running = true;
+  // TODO running = true;
 }
 
 void gdbserver_t::handle_step(const std::vector<uint8_t> &packet)
@@ -559,7 +587,7 @@ void gdbserver_t::handle_step(const std::vector<uint8_t> &packet)
   }
 
   // TODO: p->set_single_step(true);
-  running = true;
+  // TODO running = true;
 }
 
 void gdbserver_t::handle_kill(const std::vector<uint8_t> &packet)
@@ -724,13 +752,20 @@ void gdbserver_t::handle_interrupt()
   processor_t *p = sim->get_core(0);
   // TODO p->set_halted(true, HR_INTERRUPT);
   send_packet("S02");   // Pretend program received SIGINT.
-  running = false;
+  // TODO running = false;
 }
 
 void gdbserver_t::handle()
 {
   if (client_fd > 0) {
     processor_t *p = sim->get_core(0);
+
+    if (state == STATE_HALTING && sim->debug_module.get_interrupt(p->id) == 0) {
+      // gdb requested a halt and now it's done.
+      send_packet("T05");
+      state = STATE_HALTED;
+    }
+
     /* TODO
     if (running && p->halted) {
       // The core was running, but now it's halted. Better tell gdb.
index b75e990e786478363947947fd5cbf54c95b8831f..7ac8823e739980a64939fd5aa2716358e283c626 100644 (file)
@@ -82,6 +82,8 @@ public:
 
   bool connected() const { return client_fd > 0; }
 
+  void halt();
+
 private:
   sim_t *sim;
   int socket_fd;
@@ -94,6 +96,12 @@ private:
   // Used to track whether we think the target is running. If we think it is
   // but it isn't, we need to tell gdb about it.
   bool running;
+  enum {
+    STATE_UNKNOWN,
+    STATE_RUNNING,
+    STATE_HALTING,
+    STATE_HALTED
+  } state;
 
   std::map <reg_t, software_breakpoint_t> breakpoints;
 
index 5fb72bf64c8a976f5649fe27b58825f2853e22eb..514547cafbacaea8f80a3554081c1f8cfb74689e 100644 (file)
@@ -51,16 +51,44 @@ reg_t mmu_t::translate(reg_t addr, access_type type)
   return walk(addr, type, mode > PRV_U, pum) | (addr & (PGSIZE-1));
 }
 
-const uint16_t* mmu_t::fetch_slow_path(reg_t addr)
+const char* mmu_t::fill_from_mmio(reg_t vaddr, reg_t paddr)
 {
-  reg_t paddr = translate(addr, FETCH);
+  reg_t rv_start = paddr & PGMASK;
+  char* spike_start = proc->sim->mmio_page(rv_start);
+
+  if (!spike_start)
+    return NULL;
+
+  // TODO: refactor with refill_tlb()
+  reg_t idx = (vaddr >> PGSHIFT) % TLB_ENTRIES;
+  reg_t expected_tag = vaddr >> PGSHIFT;
+
+  if (tlb_load_tag[idx] != expected_tag) tlb_load_tag[idx] = -1;
+  if (tlb_store_tag[idx] != expected_tag) tlb_store_tag[idx] = -1;
+  if (tlb_insn_tag[idx] != expected_tag) tlb_insn_tag[idx] = -1;
+
+  tlb_insn_tag[idx] = expected_tag;
+  tlb_data[idx] = spike_start - DEBUG_START;
+
+  return spike_start + (paddr & ~PGMASK);
+}
+
+const uint16_t* mmu_t::fetch_slow_path(reg_t vaddr)
+{
+  reg_t paddr = translate(vaddr, FETCH);
+
+  // mmu_t::walk() returns -1 if it can't find a match. Of course -1 could also
+  // be a valid address.
+  if (paddr == ~(reg_t) 0 && vaddr != ~(reg_t) 0) {
+    throw trap_instruction_access_fault(vaddr);
+  }
 
   if (sim->addr_is_mem(paddr)) {
-    refill_tlb(addr, paddr, FETCH);
+    refill_tlb(vaddr, paddr, FETCH);
     return (const uint16_t*)sim->addr_to_mem(paddr);
   } else {
     if (!sim->mmio_load(paddr, sizeof fetch_temp, (uint8_t*)&fetch_temp))
-      throw trap_instruction_access_fault(addr);
+      throw trap_instruction_access_fault(vaddr);
     return &fetch_temp;
   }
 }
index b6aa2cab91e87179fa90f0d6652769c9fd34f135..a87b6af30480ec5d51ddea728bf9d83f1fc76253 100644 (file)
@@ -16,6 +16,7 @@
 // virtual memory configuration
 #define PGSHIFT 12
 const reg_t PGSIZE = 1 << PGSHIFT;
+const reg_t PGMASK = ~(PGSIZE-1);
 
 struct insn_fetch_t
 {
@@ -153,8 +154,9 @@ private:
   reg_t tlb_load_tag[TLB_ENTRIES];
   reg_t tlb_store_tag[TLB_ENTRIES];
 
-  // finish translation on a TLB miss and upate the TLB
+  // finish translation on a TLB miss and update the TLB
   void refill_tlb(reg_t vaddr, reg_t paddr, access_type type);
+  const char* fill_from_mmio(reg_t vaddr, reg_t paddr);
 
   // perform a page table walk for a given VA; set referenced/dirty bits
   reg_t walk(reg_t addr, access_type type, bool supervisor, bool pum);
@@ -172,7 +174,7 @@ private:
       return (uint16_t*)(tlb_data[vpn % TLB_ENTRIES] + addr);
     return fetch_slow_path(addr);
   }
-  
+
   friend class processor_t;
 };
 
index 7c5c0fbfac8c583ff47fa00b0576560295d918bb..3cb2f5a993f828e077923d65f7066c6c15444fbd 100644 (file)
@@ -8,6 +8,7 @@
 #include "mmu.h"
 #include "htif.h"
 #include "disasm.h"
+#include "gdbserver.h"
 #include <cinttypes>
 #include <cmath>
 #include <cstdlib>
@@ -119,11 +120,6 @@ void state_t::reset()
   load_reservation = -1;
 }
 
-void processor_t::set_debug_int()
-{
-  state.dcsr.debugint = true;
-}
-
 void processor_t::set_debug(bool value)
 {
   debug = value;
@@ -481,7 +477,7 @@ reg_t processor_t::get_csr(int which)
           (0 << DCSR_FULLRESET_OFFSET) |
           (state.dcsr.prv << DCSR_PRV_OFFSET) |
           (state.dcsr.step << DCSR_STEP_OFFSET) |
-          (state.dcsr.debugint << DCSR_DEBUGINT_OFFSET) |
+          (sim->debug_module.get_interrupt(id) << DCSR_DEBUGINT_OFFSET) |
           (0 << DCSR_STOPCYCLE_OFFSET) |
           (0 << DCSR_STOPTIME_OFFSET) |
           (state.dcsr.ebreakm << DCSR_EBREAKM_OFFSET) |
index 1eabee4fabdbb5c511b233eeb8bb14c0933a6cd0..3511d303e351ab99c987abbe24400bc0bb481a76 100644 (file)
@@ -35,7 +35,6 @@ typedef struct
 {
   uint8_t prv;
   bool step;
-  bool debugint;
   bool ebreakm;
   bool ebreakh;
   bool ebreaks;
@@ -97,7 +96,6 @@ public:
   processor_t(const char* isa, sim_t* sim, uint32_t id);
   ~processor_t();
 
-  void set_debug_int();
   void set_debug(bool value);
   void set_histogram(bool value);
   void reset(bool value);
index c7d84f794559b48dc7ab76c5b2a93b909f3966b4..279fbde8130e17656bf7a29a18e5ba2a23a17831 100644 (file)
@@ -25,6 +25,7 @@ riscv_hdrs = \
        insn_template.h \
        mulhi.h \
        gdbserver.h \
+       debug_module.h \
 
 riscv_precompiled_hdrs = \
        insn_template.h \
@@ -47,6 +48,7 @@ riscv_srcs = \
        rom.cc \
        rtc.cc \
        gdbserver.cc \
+       debug_module.cc \
        $(riscv_gen_srcs) \
 
 riscv_test_srcs =
index 7c50425e5a9baf6ac90398738f9e66d67129fe94..b09e7208433675f832919ce31030114a257dca5b 100644 (file)
@@ -3,6 +3,7 @@
 #include "sim.h"
 #include "mmu.h"
 #include "htif.h"
+#include "gdbserver.h"
 #include <map>
 #include <iostream>
 #include <sstream>
@@ -41,13 +42,6 @@ sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, bool halted,
     fprintf(stderr, "warning: only got %lu bytes of target mem (wanted %lu)\n",
             (unsigned long)memsz, (unsigned long)memsz0);
 
-  /* Copy Debug ROM into the end of the allocated block, because we surely
-   * didn't succeed in allocating 0xfffffffff800 bytes. */
-  /* TODO: Once everything uses the new memory map, just put this at the
-   * address that it actually belongs at. */
-  memcpy(mem + memsz - DEBUG_SIZE + DEBUG_ROM_START - DEBUG_START,
-          debug_rom_raw, debug_rom_raw_len);
-
   debug_mmu = new mmu_t(this, NULL);
 
   for (size_t i = 0; i < procs.size(); i++) {
@@ -58,6 +52,8 @@ sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, bool halted,
 
   rtc.reset(new rtc_t(procs));
   make_config_string();
+
+  bus.add_device(DEBUG_START, &debug_module);
 }
 
 sim_t::~sim_t()
@@ -153,6 +149,11 @@ bool sim_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes)
   return bus.store(addr, len, bytes);
 }
 
+char* sim_t::mmio_page(reg_t addr)
+{
+  return bus.page(addr);
+}
+
 void sim_t::make_config_string()
 {
   reg_t rtc_addr = EXT_IO_BASE;
index 2e7b214fd3a8ec06f8494013e3a0ca778f73de32..d3c9a6bb1288ee6784d2a3def262cf8fa519e88b 100644 (file)
@@ -8,10 +8,11 @@
 #include <memory>
 #include "processor.h"
 #include "devices.h"
-#include "gdbserver.h"
+#include "debug_module.h"
 
 class htif_isasim_t;
 class mmu_t;
+class gdbserver_t;
 
 // this class encapsulates the processors and memory in a RISC-V machine.
 class sim_t
@@ -46,6 +47,7 @@ private:
   std::unique_ptr<rom_device_t> boot_rom;
   std::unique_ptr<rtc_t> rtc;
   bus_t bus;
+  debug_module_t debug_module;
 
   processor_t* get_core(const std::string& i);
   void step(size_t n); // step through simulation
@@ -66,6 +68,9 @@ private:
   reg_t mem_to_addr(char* x) { return x - mem + DRAM_BASE; }
   bool mmio_load(reg_t addr, size_t len, uint8_t* bytes);
   bool mmio_store(reg_t addr, size_t len, const uint8_t* bytes);
+  // Return a pointer to the start of the page that addr falls in, or NULL if
+  // there is no IO device at that address.
+  char* mmio_page(reg_t addr);
   void make_config_string();
 
   // presents a prompt for introspection into the simulation
@@ -89,11 +94,6 @@ private:
   reg_t get_mem(const std::vector<std::string>& args);
   reg_t get_pc(const std::vector<std::string>& args);
 
-  // Return a pointer to Debug RAM in spike address space.
-  char *debug_ram() const {
-      return mem + memsz - DEBUG_SIZE + DEBUG_RAM_START - DEBUG_START;
-  }
-
   friend class htif_isasim_t;
   friend class processor_t;
   friend class mmu_t;