From 48458198728a955c28428d83bfa31866be29c647 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 8 Feb 2017 19:47:57 -0800 Subject: [PATCH] Serve up a correct dmcontrol register. --- riscv/debug_defines.h | 633 ++++++++++++++++++++++++++++++++++++++++++ riscv/debug_module.cc | 25 +- riscv/debug_module.h | 9 +- riscv/jtag_dtm.cc | 29 +- riscv/jtag_dtm.h | 2 +- 5 files changed, 684 insertions(+), 14 deletions(-) create mode 100644 riscv/debug_defines.h diff --git a/riscv/debug_defines.h b/riscv/debug_defines.h new file mode 100644 index 0000000..6851bd0 --- /dev/null +++ b/riscv/debug_defines.h @@ -0,0 +1,633 @@ +#define ACCESS_REGISTER None +#define ACCESS_REGISTER_PREHALT_OFFSET 23 +#define ACCESS_REGISTER_PREHALT_LENGTH 1 +#define ACCESS_REGISTER_PREHALT (0x1 << ACCESS_REGISTER_PREHALT_OFFSET) +#define ACCESS_REGISTER_POSTRESUME_OFFSET 22 +#define ACCESS_REGISTER_POSTRESUME_LENGTH 1 +#define ACCESS_REGISTER_POSTRESUME (0x1 << ACCESS_REGISTER_POSTRESUME_OFFSET) +#define ACCESS_REGISTER_SIZE_OFFSET 19 +#define ACCESS_REGISTER_SIZE_LENGTH 3 +#define ACCESS_REGISTER_SIZE (0x7 << ACCESS_REGISTER_SIZE_OFFSET) +#define ACCESS_REGISTER_PREEXEC_OFFSET 18 +#define ACCESS_REGISTER_PREEXEC_LENGTH 1 +#define ACCESS_REGISTER_PREEXEC (0x1 << ACCESS_REGISTER_PREEXEC_OFFSET) +#define ACCESS_REGISTER_POSTEXEC_OFFSET 17 +#define ACCESS_REGISTER_POSTEXEC_LENGTH 1 +#define ACCESS_REGISTER_POSTEXEC (0x1 << ACCESS_REGISTER_POSTEXEC_OFFSET) +#define ACCESS_REGISTER_WRITE_OFFSET 16 +#define ACCESS_REGISTER_WRITE_LENGTH 1 +#define ACCESS_REGISTER_WRITE (0x1 << ACCESS_REGISTER_WRITE_OFFSET) +#define ACCESS_REGISTER_REGNO_OFFSET 0 +#define ACCESS_REGISTER_REGNO_LENGTH 16 +#define ACCESS_REGISTER_REGNO (0xffff << ACCESS_REGISTER_REGNO_OFFSET) +#define CSR_DCSR 0x7b0 +#define CSR_DCSR_XDEBUGVER_OFFSET 30 +#define CSR_DCSR_XDEBUGVER_LENGTH 2 +#define CSR_DCSR_XDEBUGVER (0x3 << CSR_DCSR_XDEBUGVER_OFFSET) +#define CSR_DCSR_EBREAKM_OFFSET 15 +#define CSR_DCSR_EBREAKM_LENGTH 1 +#define CSR_DCSR_EBREAKM (0x1 << CSR_DCSR_EBREAKM_OFFSET) +#define CSR_DCSR_EBREAKH_OFFSET 14 +#define CSR_DCSR_EBREAKH_LENGTH 1 +#define CSR_DCSR_EBREAKH (0x1 << CSR_DCSR_EBREAKH_OFFSET) +#define CSR_DCSR_EBREAKS_OFFSET 13 +#define CSR_DCSR_EBREAKS_LENGTH 1 +#define CSR_DCSR_EBREAKS (0x1 << CSR_DCSR_EBREAKS_OFFSET) +#define CSR_DCSR_EBREAKU_OFFSET 12 +#define CSR_DCSR_EBREAKU_LENGTH 1 +#define CSR_DCSR_EBREAKU (0x1 << CSR_DCSR_EBREAKU_OFFSET) +#define CSR_DCSR_STOPCYCLE_OFFSET 10 +#define CSR_DCSR_STOPCYCLE_LENGTH 1 +#define CSR_DCSR_STOPCYCLE (0x1 << CSR_DCSR_STOPCYCLE_OFFSET) +#define CSR_DCSR_STOPTIME_OFFSET 9 +#define CSR_DCSR_STOPTIME_LENGTH 1 +#define CSR_DCSR_STOPTIME (0x1 << CSR_DCSR_STOPTIME_OFFSET) +#define CSR_DCSR_CAUSE_OFFSET 6 +#define CSR_DCSR_CAUSE_LENGTH 3 +#define CSR_DCSR_CAUSE (0x7 << CSR_DCSR_CAUSE_OFFSET) +#define CSR_DCSR_STEP_OFFSET 2 +#define CSR_DCSR_STEP_LENGTH 1 +#define CSR_DCSR_STEP (0x1 << CSR_DCSR_STEP_OFFSET) +#define CSR_DCSR_PRV_OFFSET 0 +#define CSR_DCSR_PRV_LENGTH 2 +#define CSR_DCSR_PRV (0x3 << CSR_DCSR_PRV_OFFSET) +#define CSR_DPC 0x7b1 +#define CSR_DPC_DPC_OFFSET 0 +#define CSR_DPC_DPC_LENGTH XLEN +#define CSR_DPC_DPC (((1< #include "debug_module.h" +#include "debug_defines.h" #include "mmu.h" #include "debug_rom/debug_rom.h" @@ -11,6 +12,12 @@ # define D(x) #endif +debug_module_t::debug_module_t() : + dmcontrol(1 << DMI_DMCONTROL_VERSION_OFFSET | + 1 << DMI_DMCONTROL_AUTHENTICATED_OFFSET) +{ +} + bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes) { addr = DEBUG_START + addr; @@ -79,13 +86,23 @@ 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)); + switch (address) { + case DMI_DMCONTROL: + *value = dmcontrol; + 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)); + return false; } diff --git a/riscv/debug_module.h b/riscv/debug_module.h index 0f9fff4..d0fd2e1 100644 --- a/riscv/debug_module.h +++ b/riscv/debug_module.h @@ -9,6 +9,8 @@ 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); @@ -37,8 +39,9 @@ class debug_module_t : public abstract_device_t // 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); + // Return true for success, false for failure. + bool dmi_read(unsigned address, uint32_t *value); + bool dmi_write(unsigned address, uint32_t value); private: // Track which interrupts from module to debugger are set. @@ -46,6 +49,8 @@ class debug_module_t : public abstract_device_t // Track which halt notifications from debugger to module are set. std::set halt_notification; char debug_ram[DEBUG_RAM_SIZE]; + + uint32_t dmcontrol; }; #endif diff --git a/riscv/jtag_dtm.cc b/riscv/jtag_dtm.cc index 5fcc303..2605001 100644 --- a/riscv/jtag_dtm.cc +++ b/riscv/jtag_dtm.cc @@ -3,6 +3,7 @@ #include "decode.h" #include "jtag_dtm.h" #include "debug_module.h" +#include "debug_defines.h" #if 1 # define D(x) x @@ -38,8 +39,8 @@ enum { jtag_dtm_t::jtag_dtm_t(debug_module_t *dm) : dm(dm), - dtmcontrol((abits << 4) | 1), - dbus(0), + dtmcontrol((abits << DTM_DTMCONTROL_ABITS_OFFSET) | 1), + dbus(DBUS_OP_STATUS_FAILED << DTM_DBUS_OP_OFFSET), state(TEST_LOGIC_RESET) { } @@ -109,8 +110,11 @@ 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", + /* + 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; @@ -153,14 +157,25 @@ void jtag_dtm_t::update_dr() dbus = dr; + bool success = true; if (op == DBUS_OP_READ || op == DBUS_OP_READ_WRITE) { - dbus = set_field(dbus, DBUS_DATA, dm->dmi_read(address)); + uint32_t value; + if (dm->dmi_read(address, &value)) { + dbus = set_field(dbus, DBUS_DATA, value); + } else { + success = false; + } } - if (op == DBUS_OP_READ_WRITE) { - dm->dmi_write(address, data); + if (success && op == DBUS_OP_READ_WRITE) { + success = dm->dmi_write(address, data); } - dbus = set_field(dbus, DBUS_OP, DBUS_OP_STATUS_SUCCESS); + if (success) { + dbus = set_field(dbus, DBUS_OP, DBUS_OP_STATUS_SUCCESS); + } else { + dbus = set_field(dbus, DBUS_OP, DBUS_OP_STATUS_FAILED); + } + D(fprintf(stderr, "dbus=0x%lx\n", dbus)); } break; } diff --git a/riscv/jtag_dtm.h b/riscv/jtag_dtm.h index 2bb4549..6d89c04 100644 --- a/riscv/jtag_dtm.h +++ b/riscv/jtag_dtm.h @@ -48,7 +48,7 @@ class jtag_dtm_t // constructor. const unsigned abits = 6; uint32_t dtmcontrol; - uint32_t dbus; + uint64_t dbus; jtag_state_t state; -- 2.30.2