From 94277648d5a0bb0e8283bbb33e25f6faab11c0d6 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 7 Feb 2017 11:27:48 -0800 Subject: [PATCH] OpenOCD does a dmi read and gets dummy value back. --- riscv/debug_module.cc | 17 +++++++ riscv/debug_module.h | 5 ++ riscv/jtag_dtm.cc | 100 +++++++++++++++++++++++++++++++++++++--- riscv/jtag_dtm.h | 42 ++++------------- riscv/remote_bitbang.cc | 11 +++-- riscv/sim.h | 3 +- spike_main/spike.cc | 2 +- 7 files changed, 135 insertions(+), 45 deletions(-) diff --git a/riscv/debug_module.cc b/riscv/debug_module.cc index 8bcc60e..318ef96 100644 --- a/riscv/debug_module.cc +++ b/riscv/debug_module.cc @@ -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)); +} diff --git a/riscv/debug_module.h b/riscv/debug_module.h index 53b32db..0f9fff4 100644 --- a/riscv/debug_module.h +++ b/riscv/debug_module.h @@ -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 interrupt; diff --git a/riscv/jtag_dtm.cc b/riscv/jtag_dtm.cc index c099e33..5fcc303 100644 --- a/riscv/jtag_dtm.cc +++ b/riscv/jtag_dtm.cc @@ -1,6 +1,8 @@ #include +#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; + } } diff --git a/riscv/jtag_dtm.h b/riscv/jtag_dtm.h index e425c8e..2bb4549 100644 --- a/riscv/jtag_dtm.h +++ b/riscv/jtag_dtm.h @@ -3,6 +3,8 @@ #include +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 diff --git a/riscv/remote_bitbang.cc b/riscv/remote_bitbang.cc index 54bc6d7..648849c 100644 --- a/riscv/remote_bitbang.cc +++ b/riscv/remote_bitbang.cc @@ -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; diff --git a/riscv/sim.h b/riscv/sim.h index c8ba407..99b6809 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -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 boot_rom; std::unique_ptr 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 diff --git a/spike_main/spike.cc b/spike_main/spike.cc index 844d8e8..21e5dab 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -79,7 +79,7 @@ int main(int argc, char** argv) auto argv1 = parser.parse(argv); std::vector htif_args(argv1, (const char*const*)argv + argc); sim_t s(isa, nprocs, mem_mb, halted, htif_args); - std::unique_ptr jtag_dtm(new jtag_dtm_t()); + std::unique_ptr jtag_dtm(new jtag_dtm_t(&s.debug_module)); std::unique_ptr remote_bitbang; if (rbb_port) { remote_bitbang.reset(new remote_bitbang_t(rbb_port, &(*jtag_dtm))); -- 2.30.2