OpenOCD does a dmi read and gets dummy value back.
authorTim Newsome <tim@sifive.com>
Tue, 7 Feb 2017 19:27:48 +0000 (11:27 -0800)
committerTim Newsome <tim@sifive.com>
Tue, 7 Feb 2017 19:27:48 +0000 (11:27 -0800)
riscv/debug_module.cc
riscv/debug_module.h
riscv/jtag_dtm.cc
riscv/jtag_dtm.h
riscv/remote_bitbang.cc
riscv/sim.h
spike_main/spike.cc

index 8bcc60eada8d9eb5fbbdd8833e2463a16ae72c09..318ef9692bf38c5cc67c3466b58aff39a0af1a0e 100644 (file)
@@ -5,6 +5,12 @@
 
 #include "debug_rom/debug_rom.h"
 
+#if 1
+#  define D(x) x
+#else
+#  define D(x)
+#endif
+
 bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
 {
   addr = DEBUG_START + addr;
@@ -72,3 +78,14 @@ uint32_t debug_module_t::ram_read32(unsigned int index)
     (((uint32_t) base[3]) << 24);
   return value;
 }
+
+uint32_t debug_module_t::dmi_read(unsigned address)
+{
+  D(fprintf(stderr, "dmi_read(0x%x)\n", address));
+  return 0xfeed;
+}
+
+void debug_module_t::dmi_write(unsigned address, uint32_t value)
+{
+  D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
+}
index 53b32db9a8e6eebadaa88f3c1d2e7ead2c6b0949..0f9fff47e100e8bd4ec9f040e46432b67035c0ff 100644 (file)
@@ -35,6 +35,11 @@ class debug_module_t : public abstract_device_t
       return halt_notification.find(hartid) != halt_notification.end();
     }
 
+    // Debug Module Interface that the debugger (in our case through JTAG DTM)
+    // uses to access the DM.
+    uint32_t dmi_read(unsigned address);
+    void dmi_write(unsigned address, uint32_t value);
+
   private:
     // Track which interrupts from module to debugger are set.
     std::set<uint32_t> interrupt;
index c099e3307b2ea1f14abd3bc6f56e76a55736567b..5fcc30305dd3082e6a6b899e6ea2f0bf183b876d 100644 (file)
@@ -1,6 +1,8 @@
 #include <stdio.h>
 
+#include "decode.h"
 #include "jtag_dtm.h"
+#include "debug_module.h"
 
 #if 1
 #  define D(x) x
@@ -8,7 +10,64 @@
 #  define D(x)
 #endif
 
+enum {
+  IR_IDCODE=1,
+  IR_DTMCONTROL=0x10,
+  IR_DBUS=0x11
+};
+
+#define DTMCONTROL_VERSION      0xf
+#define DTMCONTROL_ABITS        (0x3f << 4)
+#define DTMCONTROL_DBUSSTAT     (3<<10)
+#define DTMCONTROL_IDLE         (7<<12)
+#define DTMCONTROL_DBUSRESET    (1<<16)
+
+#define DBUS_OP                 3
+#define DBUS_DATA               (0xffffffffL<<2)
+#define DBUS_ADDRESS            ((1L<<(abits+34)) - (1L<<34))
+
+#define DBUS_OP_STATUS_SUCCESS 0
+#define DBUS_OP_STATUS_RESERVED        1
+#define DBUS_OP_STATUS_FAILED  2
+#define DBUS_OP_STATUS_BUSY    3
+
+#define DBUS_OP_NOP            0
+#define DBUS_OP_READ           1
+#define DBUS_OP_READ_WRITE     2
+#define DBUS_OP_RESERVED       3
+
+jtag_dtm_t::jtag_dtm_t(debug_module_t *dm) :
+  dm(dm),
+  dtmcontrol((abits << 4) | 1),
+  dbus(0),
+  state(TEST_LOGIC_RESET)
+{
+}
+
+void jtag_dtm_t::reset() {
+  state = TEST_LOGIC_RESET;
+}
+
 void jtag_dtm_t::set_pins(bool tck, bool tms, bool tdi) {
+  const jtag_state_t next[16][2] = {
+    /* TEST_LOGIC_RESET */    { RUN_TEST_IDLE, TEST_LOGIC_RESET },
+    /* RUN_TEST_IDLE */       { RUN_TEST_IDLE, SELECT_DR_SCAN },
+    /* SELECT_DR_SCAN */      { CAPTURE_DR, SELECT_IR_SCAN },
+    /* CAPTURE_DR */          { SHIFT_DR, EXIT1_DR },
+    /* SHIFT_DR */            { SHIFT_DR, EXIT1_DR },
+    /* EXIT1_DR */            { PAUSE_DR, UPDATE_DR },
+    /* PAUSE_DR */            { PAUSE_DR, EXIT2_DR },
+    /* EXIT2_DR */            { SHIFT_DR, UPDATE_DR },
+    /* UPDATE_DR */           { RUN_TEST_IDLE, SELECT_DR_SCAN },
+    /* SELECT_IR_SCAN */      { CAPTURE_IR, TEST_LOGIC_RESET },
+    /* CAPTURE_IR */          { SHIFT_IR, EXIT1_IR },
+    /* SHIFT_IR */            { SHIFT_IR, EXIT1_IR },
+    /* EXIT1_IR */            { PAUSE_IR, UPDATE_IR },
+    /* PAUSE_IR */            { PAUSE_IR, EXIT2_IR },
+    /* EXIT2_IR */            { SHIFT_IR, UPDATE_IR },
+    /* UPDATE_IR */           { RUN_TEST_IDLE, SELECT_DR_SCAN }
+  };
+
   if (!_tck && tck) {
     // Positive clock edge.
 
@@ -27,7 +86,7 @@ void jtag_dtm_t::set_pins(bool tck, bool tms, bool tdi) {
     state = next[state][_tms];
     switch (state) {
       case TEST_LOGIC_RESET:
-        ir = idcode_ir;
+        ir = IR_IDCODE;
         break;
       case CAPTURE_DR:
         capture_dr();
@@ -50,24 +109,29 @@ void jtag_dtm_t::set_pins(bool tck, bool tms, bool tdi) {
     }
   }
 
+  D(fprintf(stderr, "state=%2d, tdi=%d, tdo=%d, tms=%d, tck=%d, ir=0x%02x, dr=0x%lx\n",
+        state, _tdi, _tdo, _tms, _tck, ir, dr));
+
   _tck = tck;
   _tms = tms;
   _tdi = tdi;
-
-  D(fprintf(stderr, "state=%2d tck=%d tms=%d tdi=%d tdo=%d ir=0x%x dr=0x%lx\n",
-        state, _tck, _tms, _tdi, _tdo, ir, dr));
 }
 
 void jtag_dtm_t::capture_dr()
 {
   switch (ir) {
-    case idcode_ir:
-      dr = 0xdeadbeef;
+    case IR_IDCODE:
+      dr = idcode;
       dr_length = 32;
       break;
-    case dtmcontrol_ir:
+    case IR_DTMCONTROL:
       dr = dtmcontrol;
       dr_length = 32;
+      break;
+    case IR_DBUS:
+      dr = dbus;
+      dr_length = abits + 34;
+      break;
     default:
       D(fprintf(stderr, "Unsupported IR: 0x%x\n", ir));
       break;
@@ -78,4 +142,26 @@ void jtag_dtm_t::capture_dr()
 
 void jtag_dtm_t::update_dr()
 {
+  D(fprintf(stderr, "Update DR; IR=0x%x, DR=0x%lx (%d bits)\n",
+        ir, dr, dr_length));
+  switch (ir) {
+    case IR_DBUS:
+      {
+        unsigned op = get_field(dr, DBUS_OP);
+        uint32_t data = get_field(dr, DBUS_DATA);
+        unsigned address = get_field(dr, DBUS_ADDRESS);
+
+        dbus = dr;
+
+        if (op == DBUS_OP_READ || op == DBUS_OP_READ_WRITE) {
+          dbus = set_field(dbus, DBUS_DATA, dm->dmi_read(address));
+        }
+        if (op == DBUS_OP_READ_WRITE) {
+          dm->dmi_write(address, data);
+        }
+
+        dbus = set_field(dbus, DBUS_OP, DBUS_OP_STATUS_SUCCESS);
+      }
+      break;
+  }
 }
index e425c8e976cbb51858339b61f779c304e2e06577..2bb45496f76f835950be46cc4c9354a98df0bdd4 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <stdint.h>
 
+class debug_module_t;
+
 typedef enum {
   TEST_LOGIC_RESET,
   RUN_TEST_IDLE,
@@ -24,58 +26,34 @@ typedef enum {
 
 class jtag_dtm_t
 {
-  static const unsigned idcode_ir = 1;
-  static const unsigned idcode_dr = 0xdeadbeef;
-  static const unsigned dtmcontrol_ir = 0x10;
+  static const unsigned idcode = 0xdeadbeef;
 
   public:
-    jtag_dtm_t() :
-      dtmcontrol(
-          (6 << 4) |        // abits
-          1                 // version
-          ),
-      state(TEST_LOGIC_RESET) {}
-
-    void reset() {
-      state = TEST_LOGIC_RESET;
-    }
+    jtag_dtm_t(debug_module_t *dm);
+    void reset();
 
     void set_pins(bool tck, bool tms, bool tdi);
 
     bool tdo() const { return _tdo; }
 
   private:
+    debug_module_t *dm;
     bool _tck, _tms, _tdi, _tdo;
     uint32_t ir;
     const unsigned ir_length = 5;
     uint64_t dr;
     unsigned dr_length;
 
+    // abits must come before dtmcontrol so it can easily be used in the
+    // constructor.
+    const unsigned abits = 6;
     uint32_t dtmcontrol;
+    uint32_t dbus;
 
     jtag_state_t state;
 
     void capture_dr();
     void update_dr();
-
-    const jtag_state_t next[16][2] = {
-      /* TEST_LOGIC_RESET */    { RUN_TEST_IDLE, TEST_LOGIC_RESET },
-      /* RUN_TEST_IDLE */       { RUN_TEST_IDLE, SELECT_DR_SCAN },
-      /* SELECT_DR_SCAN */      { CAPTURE_DR, SELECT_IR_SCAN },
-      /* CAPTURE_DR */          { SHIFT_DR, EXIT1_DR },
-      /* SHIFT_DR */            { SHIFT_DR, EXIT1_DR },
-      /* EXIT1_DR */            { PAUSE_DR, UPDATE_DR },
-      /* PAUSE_DR */            { PAUSE_DR, EXIT2_DR },
-      /* EXIT2_DR */            { SHIFT_DR, UPDATE_DR },
-      /* UPDATE_DR */           { RUN_TEST_IDLE, SELECT_DR_SCAN },
-      /* SELECT_IR_SCAN */      { CAPTURE_IR, TEST_LOGIC_RESET },
-      /* CAPTURE_IR */          { SHIFT_IR, EXIT1_IR },
-      /* SHIFT_IR */            { SHIFT_IR, EXIT1_IR },
-      /* EXIT1_IR */            { PAUSE_IR, UPDATE_IR },
-      /* PAUSE_IR */            { PAUSE_IR, EXIT2_IR },
-      /* EXIT2_IR */            { SHIFT_IR, UPDATE_IR },
-      /* UPDATE_IR */           { RUN_TEST_IDLE, SELECT_DR_SCAN }
-    };
 };
 
 #endif
index 54bc6d7e5aa1912fd9c3d99424d5ffb244177948..648849c8dbbffe4639fa0555ce010ba71364d7cd 100644 (file)
@@ -91,6 +91,7 @@ void remote_bitbang_t::execute_commands()
   char send_buf[buf_size];
   unsigned total_received = 0;
   ssize_t bytes = read(client_fd, recv_buf, buf_size);
+  bool quit = false;
   while (bytes > 0) {
     total_received += bytes;
     unsigned send_offset = 0;
@@ -98,8 +99,8 @@ void remote_bitbang_t::execute_commands()
       uint8_t command = recv_buf[i];
 
       switch (command) {
-        case 'B': fprintf(stderr, "*BLINK*\n"); break;
-        case 'b': fprintf(stderr, "_______\n"); break;
+        case 'B': /* fprintf(stderr, "*BLINK*\n"); */ break;
+        case 'b': /* fprintf(stderr, "_______\n"); */ break;
         case 'r': tap->reset(); break;
         case '0': tap->set_pins(0, 0, 0); break;
         case '1': tap->set_pins(0, 0, 1); break;
@@ -110,6 +111,7 @@ void remote_bitbang_t::execute_commands()
         case '6': tap->set_pins(1, 1, 0); break;
         case '7': tap->set_pins(1, 1, 1); break;
         case 'R': send_buf[send_offset++] = tap->tdo() ? '1' : '0'; break;
+        case 'Q': quit = true; break;
         default:
                   fprintf(stderr, "remote_bitbang got unsupported command '%c'\n",
                       command);
@@ -125,7 +127,7 @@ void remote_bitbang_t::execute_commands()
       sent += bytes;
     }
 
-    if (total_received > buf_size) {
+    if (total_received > buf_size || quit) {
       // Don't go forever, because that could starve the main simulation.
       break;
     }
@@ -140,7 +142,8 @@ void remote_bitbang_t::execute_commands()
           strerror(errno), errno);
       abort();
     }
-  } else if (bytes == 0) {
+  }
+  if (bytes == 0 || quit) {
     // The remote disconnected.
     close(client_fd);
     client_fd = 0;
index c8ba4073c02157538060c42cc4c9dd86ba98826c..99b6809d7deb9b26239e926377a9867a86ccde13 100644 (file)
@@ -35,6 +35,8 @@ public:
   const char* get_config_string() { return config_string.c_str(); }
   processor_t* get_core(size_t i) { return procs.at(i); }
 
+  debug_module_t debug_module;
+
 private:
   char* mem; // main memory
   size_t memsz; // memory size in bytes
@@ -44,7 +46,6 @@ 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
index 844d8e82d9aa927c0c2cf73215fee8f4397cc87c..21e5dab2cd9263789e0b49cf653a87eea1d6d732 100644 (file)
@@ -79,7 +79,7 @@ int main(int argc, char** argv)
   auto argv1 = parser.parse(argv);
   std::vector<std::string> htif_args(argv1, (const char*const*)argv + argc);
   sim_t s(isa, nprocs, mem_mb, halted, htif_args);
-  std::unique_ptr<jtag_dtm_t> jtag_dtm(new jtag_dtm_t());
+  std::unique_ptr<jtag_dtm_t> jtag_dtm(new jtag_dtm_t(&s.debug_module));
   std::unique_ptr<remote_bitbang_t> remote_bitbang;
   if (rbb_port) {
     remote_bitbang.reset(new remote_bitbang_t(rbb_port, &(*jtag_dtm)));