Browse Source

OpenOCD does a dmi read and gets dummy value back.

pull/94/head
Tim Newsome 10 years ago
parent
commit
94277648d5
  1. 17
      riscv/debug_module.cc
  2. 5
      riscv/debug_module.h
  3. 100
      riscv/jtag_dtm.cc
  4. 42
      riscv/jtag_dtm.h
  5. 11
      riscv/remote_bitbang.cc
  6. 3
      riscv/sim.h
  7. 2
      spike_main/spike.cc

17
riscv/debug_module.cc

@ -5,6 +5,12 @@
#include "debug_rom/debug_rom.h" #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) bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
{ {
addr = DEBUG_START + addr; addr = DEBUG_START + addr;
@ -72,3 +78,14 @@ uint32_t debug_module_t::ram_read32(unsigned int index)
(((uint32_t) base[3]) << 24); (((uint32_t) base[3]) << 24);
return value; 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));
}

5
riscv/debug_module.h

@ -35,6 +35,11 @@ class debug_module_t : public abstract_device_t
return halt_notification.find(hartid) != halt_notification.end(); 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: private:
// Track which interrupts from module to debugger are set. // Track which interrupts from module to debugger are set.
std::set<uint32_t> interrupt; std::set<uint32_t> interrupt;

100
riscv/jtag_dtm.cc

@ -1,6 +1,8 @@
#include <stdio.h> #include <stdio.h>
#include "decode.h"
#include "jtag_dtm.h" #include "jtag_dtm.h"
#include "debug_module.h"
#if 1 #if 1
# define D(x) x # define D(x) x
@ -8,7 +10,64 @@
# define D(x) # define D(x)
#endif #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) { 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) { if (!_tck && tck) {
// Positive clock edge. // Positive clock edge.
@ -27,7 +86,7 @@ void jtag_dtm_t::set_pins(bool tck, bool tms, bool tdi) {
state = next[state][_tms]; state = next[state][_tms];
switch (state) { switch (state) {
case TEST_LOGIC_RESET: case TEST_LOGIC_RESET:
ir = idcode_ir; ir = IR_IDCODE;
break; break;
case CAPTURE_DR: case CAPTURE_DR:
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; _tck = tck;
_tms = tms; _tms = tms;
_tdi = tdi; _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() void jtag_dtm_t::capture_dr()
{ {
switch (ir) { switch (ir) {
case idcode_ir: case IR_IDCODE:
dr = 0xdeadbeef; dr = idcode;
dr_length = 32; dr_length = 32;
break; break;
case dtmcontrol_ir: case IR_DTMCONTROL:
dr = dtmcontrol; dr = dtmcontrol;
dr_length = 32; dr_length = 32;
break;
case IR_DBUS:
dr = dbus;
dr_length = abits + 34;
break;
default: default:
D(fprintf(stderr, "Unsupported IR: 0x%x\n", ir)); D(fprintf(stderr, "Unsupported IR: 0x%x\n", ir));
break; break;
@ -78,4 +142,26 @@ void jtag_dtm_t::capture_dr()
void jtag_dtm_t::update_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;
}
} }

42
riscv/jtag_dtm.h

@ -3,6 +3,8 @@
#include <stdint.h> #include <stdint.h>
class debug_module_t;
typedef enum { typedef enum {
TEST_LOGIC_RESET, TEST_LOGIC_RESET,
RUN_TEST_IDLE, RUN_TEST_IDLE,
@ -24,58 +26,34 @@ typedef enum {
class jtag_dtm_t class jtag_dtm_t
{ {
static const unsigned idcode_ir = 1; static const unsigned idcode = 0xdeadbeef;
static const unsigned idcode_dr = 0xdeadbeef;
static const unsigned dtmcontrol_ir = 0x10;
public: public:
jtag_dtm_t() : jtag_dtm_t(debug_module_t *dm);
dtmcontrol( void reset();
(6 << 4) | // abits
1 // version
),
state(TEST_LOGIC_RESET) {}
void reset() {
state = TEST_LOGIC_RESET;
}
void set_pins(bool tck, bool tms, bool tdi); void set_pins(bool tck, bool tms, bool tdi);
bool tdo() const { return _tdo; } bool tdo() const { return _tdo; }
private: private:
debug_module_t *dm;
bool _tck, _tms, _tdi, _tdo; bool _tck, _tms, _tdi, _tdo;
uint32_t ir; uint32_t ir;
const unsigned ir_length = 5; const unsigned ir_length = 5;
uint64_t dr; uint64_t dr;
unsigned dr_length; 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 dtmcontrol;
uint32_t dbus;
jtag_state_t state; jtag_state_t state;
void capture_dr(); void capture_dr();
void update_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 #endif

11
riscv/remote_bitbang.cc

@ -91,6 +91,7 @@ void remote_bitbang_t::execute_commands()
char send_buf[buf_size]; char send_buf[buf_size];
unsigned total_received = 0; unsigned total_received = 0;
ssize_t bytes = read(client_fd, recv_buf, buf_size); ssize_t bytes = read(client_fd, recv_buf, buf_size);
bool quit = false;
while (bytes > 0) { while (bytes > 0) {
total_received += bytes; total_received += bytes;
unsigned send_offset = 0; unsigned send_offset = 0;
@ -98,8 +99,8 @@ void remote_bitbang_t::execute_commands()
uint8_t command = recv_buf[i]; uint8_t command = recv_buf[i];
switch (command) { switch (command) {
case 'B': fprintf(stderr, "*BLINK*\n"); break; case 'B': /* fprintf(stderr, "*BLINK*\n"); */ break;
case 'b': fprintf(stderr, "_______\n"); break; case 'b': /* fprintf(stderr, "_______\n"); */ break;
case 'r': tap->reset(); break; case 'r': tap->reset(); break;
case '0': tap->set_pins(0, 0, 0); break; case '0': tap->set_pins(0, 0, 0); break;
case '1': tap->set_pins(0, 0, 1); 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 '6': tap->set_pins(1, 1, 0); break;
case '7': tap->set_pins(1, 1, 1); break; case '7': tap->set_pins(1, 1, 1); break;
case 'R': send_buf[send_offset++] = tap->tdo() ? '1' : '0'; break; case 'R': send_buf[send_offset++] = tap->tdo() ? '1' : '0'; break;
case 'Q': quit = true; break;
default: default:
fprintf(stderr, "remote_bitbang got unsupported command '%c'\n", fprintf(stderr, "remote_bitbang got unsupported command '%c'\n",
command); command);
@ -125,7 +127,7 @@ void remote_bitbang_t::execute_commands()
sent += bytes; sent += bytes;
} }
if (total_received > buf_size) { if (total_received > buf_size || quit) {
// Don't go forever, because that could starve the main simulation. // Don't go forever, because that could starve the main simulation.
break; break;
} }
@ -140,7 +142,8 @@ void remote_bitbang_t::execute_commands()
strerror(errno), errno); strerror(errno), errno);
abort(); abort();
} }
} else if (bytes == 0) { }
if (bytes == 0 || quit) {
// The remote disconnected. // The remote disconnected.
close(client_fd); close(client_fd);
client_fd = 0; client_fd = 0;

3
riscv/sim.h

@ -35,6 +35,8 @@ public:
const char* get_config_string() { return config_string.c_str(); } const char* get_config_string() { return config_string.c_str(); }
processor_t* get_core(size_t i) { return procs.at(i); } processor_t* get_core(size_t i) { return procs.at(i); }
debug_module_t debug_module;
private: private:
char* mem; // main memory char* mem; // main memory
size_t memsz; // memory size in bytes size_t memsz; // memory size in bytes
@ -44,7 +46,6 @@ private:
std::unique_ptr<rom_device_t> boot_rom; std::unique_ptr<rom_device_t> boot_rom;
std::unique_ptr<rtc_t> rtc; std::unique_ptr<rtc_t> rtc;
bus_t bus; bus_t bus;
debug_module_t debug_module;
processor_t* get_core(const std::string& i); processor_t* get_core(const std::string& i);
void step(size_t n); // step through simulation void step(size_t n); // step through simulation

2
spike_main/spike.cc

@ -79,7 +79,7 @@ int main(int argc, char** argv)
auto argv1 = parser.parse(argv); auto argv1 = parser.parse(argv);
std::vector<std::string> htif_args(argv1, (const char*const*)argv + argc); std::vector<std::string> htif_args(argv1, (const char*const*)argv + argc);
sim_t s(isa, nprocs, mem_mb, halted, htif_args); 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; std::unique_ptr<remote_bitbang_t> remote_bitbang;
if (rbb_port) { if (rbb_port) {
remote_bitbang.reset(new remote_bitbang_t(rbb_port, &(*jtag_dtm))); remote_bitbang.reset(new remote_bitbang_t(rbb_port, &(*jtag_dtm)));

Loading…
Cancel
Save