Implement hartstatus field.
[riscv-isa-sim.git] / riscv / debug_module.cc
index 318ef9692bf38c5cc67c3466b58aff39a0af1a0e..ba30603b5c2fc69df99e33863e5471dfb343e187 100644 (file)
@@ -1,6 +1,7 @@
 #include <cassert>
 
 #include "debug_module.h"
+#include "debug_defines.h"
 #include "mmu.h"
 
 #include "debug_rom/debug_rom.h"
 #  define D(x)
 #endif
 
+debug_module_t::debug_module_t(sim_t *sim) :
+  sim(sim),
+  dmcontrol(1 << DMI_DMCONTROL_VERSION_OFFSET |
+      1 << DMI_DMCONTROL_AUTHENTICATED_OFFSET),
+  abstractcs(datacount << DMI_ABSTRACTCS_DATACOUNT_OFFSET)
+{
+}
+
 bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
 {
   addr = DEBUG_START + addr;
@@ -79,13 +88,56 @@ uint32_t debug_module_t::ram_read32(unsigned int index)
   return value;
 }
 
-uint32_t debug_module_t::dmi_read(unsigned address)
+bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
 {
-  D(fprintf(stderr, "dmi_read(0x%x)\n", address));
-  return 0xfeed;
+  D(fprintf(stderr, "dmi_read(0x%x) -> ", address));
+  if (address >= DMI_DATA0 && address < DMI_DATA0 + datacount) {
+    *value = data[address - DMI_DATA0];
+  } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
+    *value = ibuf[address - DMI_IBUF0];
+  } else {
+    switch (address) {
+      case DMI_DMCONTROL:
+        {
+          processor_t *proc = sim->get_core(get_field(dmcontrol,
+                DMI_DMCONTROL_HARTSEL));
+          if (proc) {
+            D(fprintf(stderr, "(halted=%d) ", proc->halted()));
+            if (proc->halted()) {
+              dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HARTSTATUS, 0);
+            } else {
+              dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HARTSTATUS, 1);
+            }
+          } else {
+            dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HARTSTATUS, 3);
+          }
+          *value = dmcontrol;
+        }
+        break;
+      case DMI_ABSTRACTCS:
+        *value = abstractcs;
+        break;
+      case DMI_ACCESSCS:
+        *value = progsize << DMI_ACCESSCS_PROGSIZE_OFFSET;
+        break;
+      default:
+        D(fprintf(stderr, "error\n"));
+        return false;
+    }
+  }
+  D(fprintf(stderr, "0x%x\n", *value));
+  return true;
 }
 
-void debug_module_t::dmi_write(unsigned address, uint32_t value)
+bool debug_module_t::dmi_write(unsigned address, uint32_t value)
 {
   D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
+  if (address >= DMI_DATA0 && address < DMI_DATA0 + datacount) {
+    data[address - DMI_DATA0] = value;
+    return true;
+  } else if (address >= DMI_IBUF0 && address < DMI_IBUF0 + progsize) {
+    ibuf[address - DMI_IBUF0] = value;
+    return true;
+  }
+  return false;
 }