Merge pull request #1028 from en-sc/en-sc/busy-reset-batch

target/riscv: reset delays during batch scans
This commit is contained in:
Evgeniy Naydanov 2024-05-02 10:55:16 +03:00 committed by GitHub
commit 6a72b323da
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 45 additions and 29 deletions

View File

@ -89,7 +89,8 @@ bool riscv_batch_full(struct riscv_batch *batch)
return riscv_batch_available_scans(batch) == 0; 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) { if (batch->used_scans == 0) {
LOG_TARGET_DEBUG(batch->target, "Ignoring empty batch."); LOG_TARGET_DEBUG(batch->target, "Ignoring empty batch.");
@ -104,7 +105,9 @@ int riscv_batch_run(struct riscv_batch *batch)
else else
jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE); 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); jtag_add_runtest(batch->idle_count, TAP_IDLE);
} }

View File

@ -55,8 +55,15 @@ void riscv_batch_free(struct riscv_batch *batch);
/* Checks to see if this batch is full. */ /* Checks to see if this batch is full. */
bool riscv_batch_full(struct riscv_batch *batch); bool riscv_batch_full(struct riscv_batch *batch);
/* Executes this scan batch. */ /* Executes this batch of JTAG DTM DMI scans.
int riscv_batch_run(struct riscv_batch *batch); *
* 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. */ /* Adds a DM register write to this batch. */
void riscv_batch_add_dm_write(struct riscv_batch *batch, uint64_t address, uint32_t data, void riscv_batch_add_dm_write(struct riscv_batch *batch, uint64_t address, uint32_t data,

View File

@ -496,6 +496,24 @@ static void increase_dmi_busy_delay(struct target *target)
dtmcontrol_scan(target, DTM_DTMCS_DMIRESET, NULL /* discard result */); 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 * exec: If this is set, assume the scan results in an execution, so more
* run-test/idle cycles may be required. * 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) bool exec)
{ {
riscv013_info_t *info = get_info(target); riscv013_info_t *info = get_info(target);
RISCV_INFO(r);
unsigned num_bits = info->abits + DTM_DMI_OP_LENGTH + DTM_DMI_DATA_LENGTH; unsigned num_bits = info->abits + DTM_DMI_OP_LENGTH + DTM_DMI_DATA_LENGTH;
size_t num_bytes = (num_bits + 7) / 8; size_t num_bytes = (num_bits + 7) / 8;
uint8_t in[num_bytes]; 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; riscv_bscan_tunneled_scan_context_t bscan_ctxt;
if (r->reset_delays_wait >= 0) { decrement_reset_delays_counter(target, 1);
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;
}
}
memset(in, 0, num_bytes); memset(in, 0, num_bytes);
memset(out, 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); (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); RISCV_INFO(r);
if (r->reset_delays_wait >= 0) { const int result = riscv_batch_run(batch, /*resets_delays*/ r->reset_delays_wait >= 0,
r->reset_delays_wait -= batch->used_scans; r->reset_delays_wait);
if (r->reset_delays_wait <= 0) { /* TODO: `finished_scans` should be the number of scans that have
batch->idle_count = 0; * finished, not the number of scans scheduled. */
info->dmi_busy_delay = 0; const size_t finished_scans = batch->used_scans;
info->ac_busy_delay = 0; decrement_reset_delays_counter(target, finished_scans);
} return result;
}
return riscv_batch_run(batch);
} }
static int sba_supports_access(struct target *target, unsigned int size_bytes) static int sba_supports_access(struct target *target, unsigned int size_bytes)

View File

@ -450,6 +450,7 @@ static int riscv_init_target(struct command_context *cmd_ctx,
LOG_TARGET_DEBUG(target, "riscv_init_target()"); LOG_TARGET_DEBUG(target, "riscv_init_target()");
RISCV_INFO(info); RISCV_INFO(info);
info->cmd_ctx = cmd_ctx; info->cmd_ctx = cmd_ctx;
info->reset_delays_wait = -1;
select_dtmcontrol.num_bits = target->tap->ir_length; select_dtmcontrol.num_bits = target->tap->ir_length;
select_dbus.num_bits = target->tap->ir_length; select_dbus.num_bits = target->tap->ir_length;
@ -3877,10 +3878,8 @@ COMMAND_HANDLER(riscv_reset_delays)
{ {
int wait = 0; int wait = 0;
if (CMD_ARGC > 1) { if (CMD_ARGC > 1)
LOG_ERROR("Command takes at most one argument");
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
if (CMD_ARGC == 1) if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], wait); COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], wait);
@ -6482,7 +6481,7 @@ int riscv_init_registers(struct target *target)
return ERROR_OK; 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) riscv_bscan_tunneled_scan_context_t *ctxt)
{ {
jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE); jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE);

View File

@ -454,7 +454,7 @@ void riscv_semihosting_init(struct target *target);
enum semihosting_result riscv_semihosting(struct target *target, int *retval); 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); 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); int riscv_read_by_any_size(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer);