Merge pull request #95 from riscv/memread
Fix block memory reads on slow targets.
This commit is contained in:
commit
322669ca98
|
@ -44,6 +44,11 @@ bool riscv_batch_full(struct riscv_batch *batch)
|
||||||
|
|
||||||
void riscv_batch_run(struct riscv_batch *batch)
|
void riscv_batch_run(struct riscv_batch *batch)
|
||||||
{
|
{
|
||||||
|
if (batch->used_scans == 0) {
|
||||||
|
LOG_DEBUG("Ignoring empty batch.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DEBUG("running a batch of %ld scans", (long)batch->used_scans);
|
LOG_DEBUG("running a batch of %ld scans", (long)batch->used_scans);
|
||||||
riscv_batch_add_nop(batch);
|
riscv_batch_add_nop(batch);
|
||||||
|
|
||||||
|
|
|
@ -1351,18 +1351,18 @@ static int read_memory(struct target *target, target_addr_t address,
|
||||||
riscv_addr_t cur_addr = 0xbadbeef;
|
riscv_addr_t cur_addr = 0xbadbeef;
|
||||||
riscv_addr_t fin_addr = address + (count * size);
|
riscv_addr_t fin_addr = address + (count * size);
|
||||||
riscv_addr_t prev_addr = ((riscv_addr_t) address) - size;
|
riscv_addr_t prev_addr = ((riscv_addr_t) address) - size;
|
||||||
bool first = true;
|
bool ignore_prev_addr = true;
|
||||||
bool this_is_last_read = false;
|
bool this_is_last_read = false;
|
||||||
LOG_DEBUG("reading until final address 0x%" PRIx64, fin_addr);
|
LOG_DEBUG("reading until final address 0x%" PRIx64, fin_addr);
|
||||||
while (count > 1 && !this_is_last_read) {
|
while (count > 1 && !this_is_last_read) {
|
||||||
cur_addr = riscv_read_debug_buffer_x(target, d_addr);
|
cur_addr = riscv_read_debug_buffer_x(target, d_addr);
|
||||||
LOG_DEBUG("transferring burst starting at address 0x%" TARGET_PRIxADDR
|
|
||||||
" (previous burst was 0x%" TARGET_PRIxADDR ")", cur_addr,
|
|
||||||
prev_addr);
|
|
||||||
assert(first || prev_addr < cur_addr);
|
|
||||||
first = false;
|
|
||||||
prev_addr = cur_addr;
|
|
||||||
riscv_addr_t start = (cur_addr - address) / size;
|
riscv_addr_t start = (cur_addr - address) / size;
|
||||||
|
LOG_DEBUG("reading burst at address 0x%" TARGET_PRIxADDR
|
||||||
|
"; prev_addr=0x%" TARGET_PRIxADDR "; start=0x%"
|
||||||
|
TARGET_PRIxADDR, cur_addr, prev_addr, start);
|
||||||
|
assert(ignore_prev_addr || prev_addr < cur_addr);
|
||||||
|
prev_addr = cur_addr;
|
||||||
|
ignore_prev_addr = false;
|
||||||
assert (cur_addr >= address);
|
assert (cur_addr >= address);
|
||||||
struct riscv_batch *batch = riscv_batch_alloc(
|
struct riscv_batch *batch = riscv_batch_alloc(
|
||||||
target,
|
target,
|
||||||
|
@ -1407,10 +1407,11 @@ static int read_memory(struct target *target, target_addr_t address,
|
||||||
info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
|
info->cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
|
||||||
switch (info->cmderr) {
|
switch (info->cmderr) {
|
||||||
case CMDERR_NONE:
|
case CMDERR_NONE:
|
||||||
LOG_DEBUG("successful (partial?) memory write");
|
LOG_DEBUG("successful (partial?) memory read");
|
||||||
break;
|
break;
|
||||||
case CMDERR_BUSY:
|
case CMDERR_BUSY:
|
||||||
LOG_DEBUG("memory write resulted in busy response");
|
LOG_DEBUG("memory read resulted in busy response; "
|
||||||
|
"this_is_last_read=%d", this_is_last_read);
|
||||||
riscv013_clear_abstract_error(target);
|
riscv013_clear_abstract_error(target);
|
||||||
increase_ac_busy_delay(target);
|
increase_ac_busy_delay(target);
|
||||||
retry_batch_transaction = true;
|
retry_batch_transaction = true;
|
||||||
|
@ -1425,7 +1426,23 @@ static int read_memory(struct target *target, target_addr_t address,
|
||||||
riscv_batch_free(batch);
|
riscv_batch_free(batch);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
if (retry_batch_transaction) continue;
|
if (retry_batch_transaction) {
|
||||||
|
this_is_last_read = false;
|
||||||
|
ignore_prev_addr = true;
|
||||||
|
|
||||||
|
switch (riscv_xlen(target)) {
|
||||||
|
case 64:
|
||||||
|
riscv013_write_debug_buffer(target, d_addr + 4, (cur_addr - size) >> 32);
|
||||||
|
case 32:
|
||||||
|
riscv013_write_debug_buffer(target, d_addr, (cur_addr - size));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR("unknown XLEN %d", riscv_xlen(target));
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = start; i < start + reads; ++i) {
|
for (size_t i = start; i < start + reads; ++i) {
|
||||||
riscv_addr_t offset = size*i;
|
riscv_addr_t offset = size*i;
|
||||||
|
@ -1435,8 +1452,11 @@ static int read_memory(struct target *target, target_addr_t address,
|
||||||
if (this_is_last_read && i == start + reads - 1) {
|
if (this_is_last_read && i == start + reads - 1) {
|
||||||
riscv013_set_autoexec(target, d_data, 0);
|
riscv013_set_autoexec(target, d_data, 0);
|
||||||
|
|
||||||
// access debug buffer without executing a program - this address logic was taken from program.c
|
// Access debug buffer without executing a program. This
|
||||||
int const off = (r_data - riscv_debug_buffer_addr(program.target)) / sizeof(program.debug_buffer[0]);
|
// address logic was taken from program.c.
|
||||||
|
int const off = (r_data -
|
||||||
|
riscv_debug_buffer_addr(program.target)) /
|
||||||
|
sizeof(program.debug_buffer[0]);
|
||||||
value = riscv_read_debug_buffer(target, off);
|
value = riscv_read_debug_buffer(target, off);
|
||||||
} else {
|
} else {
|
||||||
uint64_t dmi_out = riscv_batch_get_dmi_read(batch, rereads);
|
uint64_t dmi_out = riscv_batch_get_dmi_read(batch, rereads);
|
||||||
|
|
Loading…
Reference in New Issue