aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2018-12-04 13:46:35 -0800
committerTim Newsome <tim@sifive.com>2018-12-13 12:52:03 -0800
commit5c1849722546813bae3fe6002ce8961dfd14f2f1 (patch)
treef80f549a647ae59c405120949d334f0dc14c4b91
parent65c8ac48af16235097084b413c10c7bff576b331 (diff)
downloadspike-5c1849722546813bae3fe6002ce8961dfd14f2f1.zip
spike-5c1849722546813bae3fe6002ce8961dfd14f2f1.tar.gz
spike-5c1849722546813bae3fe6002ce8961dfd14f2f1.tar.bz2
Add --dmi-rti and --abstract-rti to test OpenOCD.
Optionally make spike behave more like real hardware, to automatically test OpenOCD's handling of such hardware.
-rw-r--r--riscv/debug_module.cc17
-rw-r--r--riscv/debug_module.h15
-rw-r--r--riscv/jtag_dtm.cc70
-rw-r--r--riscv/jtag_dtm.h9
-rw-r--r--riscv/sim.cc6
-rw-r--r--riscv/sim.h3
-rw-r--r--spike_main/spike.cc16
7 files changed, 98 insertions, 38 deletions
diff --git a/riscv/debug_module.cc b/riscv/debug_module.cc
index 96de3c8..081b606 100644
--- a/riscv/debug_module.cc
+++ b/riscv/debug_module.cc
@@ -18,11 +18,12 @@
///////////////////////// debug_module_t
debug_module_t::debug_module_t(sim_t *sim, unsigned progbufsize, unsigned max_bus_master_bits,
- bool require_authentication) :
+ bool require_authentication, unsigned abstract_rti) :
progbufsize(progbufsize),
program_buffer_bytes(4 + 4*progbufsize),
max_bus_master_bits(max_bus_master_bits),
require_authentication(require_authentication),
+ abstract_rti(abstract_rti),
debug_progbuf_start(debug_data_start - program_buffer_bytes),
debug_abstract_start(debug_progbuf_start - debug_abstract_size*4),
custom_base(0),
@@ -183,7 +184,7 @@ bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
if (dmcontrol.hartsel == id) {
if (0 == (debug_rom_flags[id] & (1 << DEBUG_ROM_FLAG_GO))){
if (dmcontrol.hartsel == id) {
- abstractcs.busy = false;
+ abstract_command_completed = true;
}
}
}
@@ -488,6 +489,16 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
return true;
}
+void debug_module_t::run_test_idle()
+{
+ if (rti_remaining > 0) {
+ rti_remaining--;
+ }
+ if (rti_remaining == 0 && abstractcs.busy && abstract_command_completed) {
+ abstractcs.busy = false;
+ }
+}
+
bool debug_module_t::perform_abstract_command()
{
if (abstractcs.cmderr != CMDERR_NONE)
@@ -629,6 +640,8 @@ bool debug_module_t::perform_abstract_command()
}
debug_rom_flags[dmcontrol.hartsel] |= 1 << DEBUG_ROM_FLAG_GO;
+ rti_remaining = abstract_rti;
+ abstract_command_completed = false;
abstractcs.busy = true;
} else {
diff --git a/riscv/debug_module.h b/riscv/debug_module.h
index 5b43ed6..472ae8e 100644
--- a/riscv/debug_module.h
+++ b/riscv/debug_module.h
@@ -81,9 +81,13 @@ class debug_module_t : public abstract_device_t
* follows:
* 1. Read a 32-bit value from authdata:
* 2. Write the value that was read back, plus one, to authdata.
+ *
+ * abstract_rti is extra run-test/idle cycles that each abstract command
+ * takes to execute. Useful for testing OpenOCD.
*/
- debug_module_t(sim_t *sim, unsigned progbufsize, unsigned max_bus_master_bits,
- bool require_authentication);
+ debug_module_t(sim_t *sim, unsigned progbufsize,
+ unsigned max_bus_master_bits, bool require_authentication,
+ unsigned abstract_rti);
~debug_module_t();
void add_device(bus_t *bus);
@@ -97,6 +101,9 @@ class debug_module_t : public abstract_device_t
bool dmi_read(unsigned address, uint32_t *value);
bool dmi_write(unsigned address, uint32_t value);
+ // Called for every cycle the JTAG TAP spends in Run-Test/Idle.
+ void run_test_idle();
+
// Called when one of the attached harts was reset.
void proc_reset(unsigned id);
@@ -110,6 +117,7 @@ class debug_module_t : public abstract_device_t
unsigned program_buffer_bytes;
unsigned max_bus_master_bits;
bool require_authentication;
+ unsigned abstract_rti;
static const unsigned debug_data_start = 0x380;
unsigned debug_progbuf_start;
@@ -159,6 +167,9 @@ class debug_module_t : public abstract_device_t
processor_t *current_proc() const;
void reset();
bool perform_abstract_command();
+
+ bool abstract_command_completed;
+ unsigned rti_remaining;
};
#endif
diff --git a/riscv/jtag_dtm.cc b/riscv/jtag_dtm.cc
index 365528a..3e44c5e 100644
--- a/riscv/jtag_dtm.cc
+++ b/riscv/jtag_dtm.cc
@@ -38,8 +38,8 @@ enum {
#define DMI_OP_WRITE 2
#define DMI_OP_RESERVED 3
-jtag_dtm_t::jtag_dtm_t(debug_module_t *dm) :
- dm(dm),
+jtag_dtm_t::jtag_dtm_t(debug_module_t *dm, unsigned required_rti_cycles) :
+ dm(dm), required_rti_cycles(required_rti_cycles),
_tck(false), _tms(false), _tdi(false), _tdo(false),
dtmcontrol((abits << DTM_DTMCS_ABITS_OFFSET) | 1),
dmi(DMI_OP_STATUS_SUCCESS << DTM_DMI_OP_OFFSET),
@@ -49,6 +49,9 @@ jtag_dtm_t::jtag_dtm_t(debug_module_t *dm) :
void jtag_dtm_t::reset() {
_state = TEST_LOGIC_RESET;
+ busy_stuck = false;
+ rti_remaining = 0;
+ dmi = 0;
}
void jtag_dtm_t::set_pins(bool tck, bool tms, bool tdi) {
@@ -88,6 +91,11 @@ void jtag_dtm_t::set_pins(bool tck, bool tms, bool tdi) {
}
_state = next[_state][_tms];
switch (_state) {
+ case RUN_TEST_IDLE:
+ if (rti_remaining > 0)
+ rti_remaining--;
+ dm->run_test_idle();
+ break;
case TEST_LOGIC_RESET:
ir = IR_IDCODE;
break;
@@ -151,34 +159,40 @@ 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, DMI_OP);
- uint32_t data = get_field(dr, DMI_DATA);
- unsigned address = get_field(dr, DMI_ADDRESS);
-
- dmi = dr;
-
- bool success = true;
- if (op == DMI_OP_READ) {
- uint32_t value;
- if (dm->dmi_read(address, &value)) {
- dmi = set_field(dmi, DMI_DATA, value);
- } else {
- success = false;
- }
- } else if (op == DMI_OP_WRITE) {
- success = dm->dmi_write(address, data);
- }
-
- if (success) {
- dmi = set_field(dmi, DMI_OP, DMI_OP_STATUS_SUCCESS);
+ if (ir == IR_DTMCONTROL) {
+ if (dr & DTMCONTROL_DBUSRESET)
+ reset();
+ } else if (ir == IR_DBUS) {
+ if (rti_remaining > 0 || busy_stuck) {
+ dmi = DMI_OP_STATUS_BUSY;
+ busy_stuck = true;
+ } else {
+ unsigned op = get_field(dr, DMI_OP);
+ uint32_t data = get_field(dr, DMI_DATA);
+ unsigned address = get_field(dr, DMI_ADDRESS);
+
+ dmi = dr;
+
+ bool success = true;
+ if (op == DMI_OP_READ) {
+ uint32_t value;
+ if (dm->dmi_read(address, &value)) {
+ dmi = set_field(dmi, DMI_DATA, value);
} else {
- dmi = set_field(dmi, DMI_OP, DMI_OP_STATUS_FAILED);
+ success = false;
}
- D(fprintf(stderr, "dmi=0x%lx\n", dmi));
+ } else if (op == DMI_OP_WRITE) {
+ success = dm->dmi_write(address, data);
}
- break;
+
+ if (success) {
+ dmi = set_field(dmi, DMI_OP, DMI_OP_STATUS_SUCCESS);
+ } else {
+ dmi = set_field(dmi, DMI_OP, DMI_OP_STATUS_FAILED);
+ }
+ D(fprintf(stderr, "dmi=0x%lx\n", dmi));
+
+ rti_remaining = required_rti_cycles;
+ }
}
}
diff --git a/riscv/jtag_dtm.h b/riscv/jtag_dtm.h
index 063e3f4..3482b8a 100644
--- a/riscv/jtag_dtm.h
+++ b/riscv/jtag_dtm.h
@@ -29,7 +29,7 @@ class jtag_dtm_t
static const unsigned idcode = 0xdeadbeef;
public:
- jtag_dtm_t(debug_module_t *dm);
+ jtag_dtm_t(debug_module_t *dm, unsigned required_rti_cycles);
void reset();
void set_pins(bool tck, bool tms, bool tdi);
@@ -40,6 +40,9 @@ class jtag_dtm_t
private:
debug_module_t *dm;
+ // The number of Run-Test/Idle cycles required before a DMI access is
+ // complete.
+ unsigned required_rti_cycles;
bool _tck, _tms, _tdi, _tdo;
uint32_t ir;
const unsigned ir_length = 5;
@@ -51,6 +54,10 @@ class jtag_dtm_t
const unsigned abits = 6;
uint32_t dtmcontrol;
uint64_t dmi;
+ // Number of Run-Test/Idle cycles needed before we call this access
+ // complete.
+ unsigned rti_remaining;
+ bool busy_stuck;
jtag_state_t _state;
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 44223a7..ddc9bce 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -28,11 +28,13 @@ sim_t::sim_t(const char* isa, size_t nprocs, bool halted, reg_t start_pc,
std::vector<std::pair<reg_t, mem_t*>> mems,
const std::vector<std::string>& args,
std::vector<int> const hartids, unsigned progsize,
- unsigned max_bus_master_bits, bool require_authentication)
+ unsigned max_bus_master_bits, bool require_authentication,
+ suseconds_t abstract_delay_usec)
: htif_t(args), mems(mems), procs(std::max(nprocs, size_t(1))),
start_pc(start_pc), current_step(0), current_proc(0), debug(false),
histogram_enabled(false), dtb_enabled(true), remote_bitbang(NULL),
- debug_module(this, progsize, max_bus_master_bits, require_authentication)
+ debug_module(this, progsize, max_bus_master_bits, require_authentication,
+ abstract_delay_usec)
{
signal(SIGINT, &handle_signal);
diff --git a/riscv/sim.h b/riscv/sim.h
index e42808b..6521573 100644
--- a/riscv/sim.h
+++ b/riscv/sim.h
@@ -23,7 +23,8 @@ public:
sim_t(const char* isa, size_t _nprocs, bool halted, reg_t start_pc,
std::vector<std::pair<reg_t, mem_t*>> mems,
const std::vector<std::string>& args, const std::vector<int> hartids,
- unsigned progsize, unsigned max_bus_master_bits, bool require_authentication);
+ unsigned progsize, unsigned max_bus_master_bits,
+ bool require_authentication, suseconds_t abstract_delay_usec);
~sim_t();
// run the simulation to completion
diff --git a/spike_main/spike.cc b/spike_main/spike.cc
index 3e5c7e6..fa974d0 100644
--- a/spike_main/spike.cc
+++ b/spike_main/spike.cc
@@ -42,6 +42,10 @@ static void help()
fprintf(stderr, " --debug-sba=<bits> Debug bus master supports up to "
"<bits> wide accesses [default 0]\n");
fprintf(stderr, " --debug-auth Debug module requires debugger to authenticate\n");
+ fprintf(stderr, " --dmi-rti=<n> Number of Run-Test/Idle cycles "
+ "required for a DMI access [default 0]\n");
+ fprintf(stderr, " --abstract-rti=<n> Number of Run-Test/Idle cycles "
+ "required for an abstract command to execute [default 0]\n");
exit(1);
}
@@ -98,6 +102,8 @@ int main(int argc, char** argv)
unsigned progsize = 2;
unsigned max_bus_master_bits = 0;
bool require_authentication = false;
+ unsigned dmi_rti = 0;
+ unsigned abstract_rti = 0;
std::vector<int> hartids;
auto const hartids_parser = [&](const char *s) {
@@ -145,6 +151,10 @@ int main(int argc, char** argv)
[&](const char* s){max_bus_master_bits = atoi(s);});
parser.option(0, "debug-auth", 0,
[&](const char* s){require_authentication = true;});
+ parser.option(0, "dmi-rti", 1,
+ [&](const char* s){dmi_rti = atoi(s);});
+ parser.option(0, "abstract-rti", 1,
+ [&](const char* s){abstract_rti = atoi(s);});
auto argv1 = parser.parse(argv);
std::vector<std::string> htif_args(argv1, (const char*const*)argv + argc);
@@ -155,9 +165,11 @@ int main(int argc, char** argv)
help();
sim_t s(isa, nprocs, halted, start_pc, mems, htif_args, std::move(hartids),
- progsize, max_bus_master_bits, require_authentication);
+ progsize, max_bus_master_bits, require_authentication,
+ abstract_rti);
std::unique_ptr<remote_bitbang_t> remote_bitbang((remote_bitbang_t *) NULL);
- std::unique_ptr<jtag_dtm_t> jtag_dtm(new jtag_dtm_t(&s.debug_module));
+ std::unique_ptr<jtag_dtm_t> jtag_dtm(
+ new jtag_dtm_t(&s.debug_module, dmi_rti));
if (use_rbb) {
remote_bitbang.reset(new remote_bitbang_t(rbb_port, &(*jtag_dtm)));
s.set_remote_bitbang(&(*remote_bitbang));