Implement hartstatus field.
[riscv-isa-sim.git] / riscv / debug_module.cc
index 8ad95137c1a4134fed985740a5b615ce3d240d1c..ba30603b5c2fc69df99e33863e5471dfb343e187 100644 (file)
@@ -1,10 +1,25 @@
 #include <cassert>
 
 #include "debug_module.h"
+#include "debug_defines.h"
 #include "mmu.h"
 
 #include "debug_rom/debug_rom.h"
 
+#if 1
+#  define D(x) x
+#else
+#  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;
@@ -19,8 +34,8 @@ bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
     return true;
   }
 
-  fprintf(stderr, "ERROR: invalid load from debug module: %ld bytes at 0x%lx\n",
-      len, addr);
+  fprintf(stderr, "ERROR: invalid load from debug module: %zd bytes at 0x%016"
+          PRIx64 "\n", len, addr);
   return false;
 }
 
@@ -29,8 +44,8 @@ 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);
+    fprintf(stderr, "ERROR: unaligned store to debug module: %zd bytes at 0x%016"
+            PRIx64 "\n", len, addr);
     return false;
   }
 
@@ -47,8 +62,8 @@ bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
     return true;
   }
 
-  fprintf(stderr, "ERROR: invalid store to debug module: %ld bytes at 0x%lx\n",
-      len, addr);
+  fprintf(stderr, "ERROR: invalid store to debug module: %zd bytes at 0x%016"
+          PRIx64 "\n", len, addr);
   return false;
 }
 
@@ -72,3 +87,57 @@ uint32_t debug_module_t::ram_read32(unsigned int index)
     (((uint32_t) base[3]) << 24);
   return value;
 }
+
+bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
+{
+  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;
+}
+
+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;
+}