aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/target/riscv/batch.c7
-rw-r--r--src/target/riscv/batch.h11
-rw-r--r--src/target/riscv/riscv-013.c47
-rw-r--r--src/target/riscv/riscv.c56
-rw-r--r--src/target/riscv/riscv.h2
5 files changed, 83 insertions, 40 deletions
diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c
index 94cb16e..c83ff97 100644
--- a/src/target/riscv/batch.c
+++ b/src/target/riscv/batch.c
@@ -89,7 +89,8 @@ bool riscv_batch_full(struct riscv_batch *batch)
return riscv_batch_available_scans(batch) == 0;
}
-int riscv_batch_run(struct riscv_batch *batch)
+int riscv_batch_run(struct riscv_batch *batch, bool resets_delays,
+ size_t reset_delays_after)
{
if (batch->used_scans == 0) {
LOG_TARGET_DEBUG(batch->target, "Ignoring empty batch.");
@@ -104,7 +105,9 @@ int riscv_batch_run(struct riscv_batch *batch)
else
jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE);
- if (batch->idle_count > 0)
+ const bool delays_were_reset = resets_delays
+ && (i >= reset_delays_after);
+ if (batch->idle_count > 0 && !delays_were_reset)
jtag_add_runtest(batch->idle_count, TAP_IDLE);
}
diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h
index 954c470..b3a45e5 100644
--- a/src/target/riscv/batch.h
+++ b/src/target/riscv/batch.h
@@ -55,8 +55,15 @@ void riscv_batch_free(struct riscv_batch *batch);
/* Checks to see if this batch is full. */
bool riscv_batch_full(struct riscv_batch *batch);
-/* Executes this scan batch. */
-int riscv_batch_run(struct riscv_batch *batch);
+/* Executes this batch of JTAG DTM DMI scans.
+ *
+ * If resets_delays is true, the algorithm will stop inserting idle cycles
+ * (JTAG Run-Test Idle) after "reset_delays_after" number of scans is
+ * performed. This is useful for stress-testing of RISC-V algorithms in
+ * OpenOCD that are based on batches.
+ */
+int riscv_batch_run(struct riscv_batch *batch, bool resets_delays,
+ size_t reset_delays_after);
/* Adds a DM register write to this batch. */
void riscv_batch_add_dm_write(struct riscv_batch *batch, uint64_t address, uint32_t data,
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index adb0206..71cfcd6 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -496,6 +496,24 @@ static void increase_dmi_busy_delay(struct target *target)
dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, NULL /* discard result */);
}
+static void decrement_reset_delays_counter(struct target *target, size_t finished_scans)
+{
+ RISCV_INFO(r);
+ if (r->reset_delays_wait < 0) {
+ assert(r->reset_delays_wait == -1);
+ return;
+ }
+ if ((size_t)r->reset_delays_wait >= finished_scans) {
+ r->reset_delays_wait -= finished_scans;
+ return;
+ }
+ r->reset_delays_wait = -1;
+ LOG_TARGET_DEBUG(target,
+ "resetting learned delays (reset_delays_wait counter expired)");
+ RISCV013_INFO(info);
+ info->dmi_busy_delay = 0;
+ info->ac_busy_delay = 0;
+}
/**
* exec: If this is set, assume the scan results in an execution, so more
* run-test/idle cycles may be required.
@@ -505,7 +523,6 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
bool exec)
{
riscv013_info_t *info = get_info(target);
- RISCV_INFO(r);
unsigned num_bits = info->abits + DTM_DMI_OP_LENGTH + DTM_DMI_DATA_LENGTH;
size_t num_bytes = (num_bits + 7) / 8;
uint8_t in[num_bytes];
@@ -517,14 +534,7 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
};
riscv_bscan_tunneled_scan_context_t bscan_ctxt;
- if (r->reset_delays_wait >= 0) {
- r->reset_delays_wait--;
- if (r->reset_delays_wait < 0) {
- LOG_TARGET_DEBUG(target, "reset_delays_wait done");
- info->dmi_busy_delay = 0;
- info->ac_busy_delay = 0;
- }
- }
+ decrement_reset_delays_counter(target, 1);
memset(in, 0, num_bytes);
memset(out, 0, num_bytes);
@@ -2617,19 +2627,16 @@ static int sb_write_address(struct target *target, target_addr_t address,
(uint32_t)address, false, ensure_success);
}
-static int batch_run(const struct target *target, struct riscv_batch *batch)
+static int batch_run(struct target *target, struct riscv_batch *batch)
{
- RISCV013_INFO(info);
RISCV_INFO(r);
- if (r->reset_delays_wait >= 0) {
- r->reset_delays_wait -= batch->used_scans;
- if (r->reset_delays_wait <= 0) {
- batch->idle_count = 0;
- info->dmi_busy_delay = 0;
- info->ac_busy_delay = 0;
- }
- }
- return riscv_batch_run(batch);
+ const int result = riscv_batch_run(batch, /*resets_delays*/ r->reset_delays_wait >= 0,
+ r->reset_delays_wait);
+ /* TODO: `finished_scans` should be the number of scans that have
+ * finished, not the number of scans scheduled. */
+ const size_t finished_scans = batch->used_scans;
+ decrement_reset_delays_counter(target, finished_scans);
+ return result;
}
static int sba_supports_access(struct target *target, unsigned int size_bytes)
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index 8fe416d..d610b33 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -450,6 +450,7 @@ static int riscv_init_target(struct command_context *cmd_ctx,
LOG_TARGET_DEBUG(target, "riscv_init_target()");
RISCV_INFO(info);
info->cmd_ctx = cmd_ctx;
+ info->reset_delays_wait = -1;
select_dtmcontrol.num_bits = target->tap->ir_length;
select_dbus.num_bits = target->tap->ir_length;
@@ -1415,6 +1416,7 @@ static int riscv_add_breakpoint(struct target *target, struct breakpoint *breakp
TARGET_PRIxADDR, breakpoint->length, breakpoint->address);
return ERROR_FAIL;
}
+ breakpoint->is_set = true;
} else if (breakpoint->type == BKPT_HARD) {
struct trigger trigger;
@@ -1422,12 +1424,13 @@ static int riscv_add_breakpoint(struct target *target, struct breakpoint *breakp
int const result = add_trigger(target, &trigger);
if (result != ERROR_OK)
return result;
+
+ int trigger_idx = find_first_trigger_by_id(target, breakpoint->unique_id);
+ breakpoint_hw_set(breakpoint, trigger_idx);
} else {
LOG_TARGET_INFO(target, "OpenOCD only supports hardware and software breakpoints.");
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
}
-
- breakpoint->is_set = true;
return ERROR_OK;
}
@@ -1521,7 +1524,9 @@ int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint)
int result = add_trigger(target, &trigger);
if (result != ERROR_OK)
return result;
- watchpoint->is_set = true;
+
+ int trigger_idx = find_first_trigger_by_id(target, watchpoint->unique_id);
+ watchpoint_set(watchpoint, trigger_idx);
return ERROR_OK;
}
@@ -1709,15 +1714,26 @@ static int oldriscv_step(struct target *target, int current, uint32_t address,
return tt->step(target, current, address, handle_breakpoints);
}
-static int old_or_new_riscv_step(struct target *target, int current,
- target_addr_t address, int handle_breakpoints)
+static int riscv_openocd_step_impl(struct target *target, int current,
+ target_addr_t address, int handle_breakpoints, int handle_callbacks);
+
+static int old_or_new_riscv_step_impl(struct target *target, int current,
+ target_addr_t address, int handle_breakpoints, int handle_callbacks)
{
RISCV_INFO(r);
LOG_TARGET_DEBUG(target, "handle_breakpoints=%d", handle_breakpoints);
if (!r->get_hart_state)
return oldriscv_step(target, current, address, handle_breakpoints);
else
- return riscv_openocd_step(target, current, address, handle_breakpoints);
+ return riscv_openocd_step_impl(target, current, address, handle_breakpoints,
+ handle_callbacks);
+}
+
+static int old_or_new_riscv_step(struct target *target, int current,
+ target_addr_t address, int handle_breakpoints)
+{
+ return old_or_new_riscv_step_impl(target, current, address,
+ handle_breakpoints, true /* handle callbacks*/);
}
static int riscv_examine(struct target *target)
@@ -2091,7 +2107,8 @@ static int resume_prep(struct target *target, int current,
/* To be able to run off a trigger, we perform a step operation and then
* resume. If handle_breakpoints is true then step temporarily disables
* pending breakpoints so we can safely perform the step. */
- if (old_or_new_riscv_step(target, current, address, handle_breakpoints) != ERROR_OK)
+ if (old_or_new_riscv_step_impl(target, current, address, handle_breakpoints,
+ false /* callbacks are not called */) != ERROR_OK)
return ERROR_FAIL;
}
@@ -3294,8 +3311,8 @@ int riscv_openocd_poll(struct target *target)
return ERROR_OK;
}
-int riscv_openocd_step(struct target *target, int current,
- target_addr_t address, int handle_breakpoints)
+static int riscv_openocd_step_impl(struct target *target, int current,
+ target_addr_t address, int handle_breakpoints, int handle_callbacks)
{
LOG_TARGET_DEBUG(target, "stepping hart");
@@ -3361,14 +3378,25 @@ _exit:
if (success) {
target->state = TARGET_RUNNING;
- target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+ if (handle_callbacks)
+ target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+
target->state = TARGET_HALTED;
target->debug_reason = DBG_REASON_SINGLESTEP;
- target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+ if (handle_callbacks)
+ target_call_event_callbacks(target, TARGET_EVENT_HALTED);
}
+
return success ? ERROR_OK : ERROR_FAIL;
}
+int riscv_openocd_step(struct target *target, int current,
+ target_addr_t address, int handle_breakpoints)
+{
+ return riscv_openocd_step_impl(target, current, address, handle_breakpoints,
+ true /* handle_callbacks */);
+}
+
/* Command Handlers */
COMMAND_HANDLER(riscv_set_command_timeout_sec)
{
@@ -3850,10 +3878,8 @@ COMMAND_HANDLER(riscv_reset_delays)
{
int wait = 0;
- if (CMD_ARGC > 1) {
- LOG_ERROR("Command takes at most one argument");
+ if (CMD_ARGC > 1)
return ERROR_COMMAND_SYNTAX_ERROR;
- }
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], wait);
@@ -6455,7 +6481,7 @@ int riscv_init_registers(struct target *target)
return ERROR_OK;
}
-void riscv_add_bscan_tunneled_scan(struct target *target, struct scan_field *field,
+void riscv_add_bscan_tunneled_scan(struct target *target, const struct scan_field *field,
riscv_bscan_tunneled_scan_context_t *ctxt)
{
jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE);
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index cdfd98e..7a95af6 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -454,7 +454,7 @@ void riscv_semihosting_init(struct target *target);
enum semihosting_result riscv_semihosting(struct target *target, int *retval);
-void riscv_add_bscan_tunneled_scan(struct target *target, struct scan_field *field,
+void riscv_add_bscan_tunneled_scan(struct target *target, const struct scan_field *field,
riscv_bscan_tunneled_scan_context_t *ctxt);
int riscv_read_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer);