aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2017-02-22 16:04:36 -0800
committerTim Newsome <tim@sifive.com>2017-02-22 16:04:36 -0800
commit3bd661b679995ec3316fbe87593b3026ffcfcb55 (patch)
tree44eba489ca0a24cefbcd7813b706c32cabc852c8
parentf9168b09d0e4640e9806a6a9f4c102f4065738a6 (diff)
downloadriscv-openocd-3bd661b679995ec3316fbe87593b3026ffcfcb55.zip
riscv-openocd-3bd661b679995ec3316fbe87593b3026ffcfcb55.tar.gz
riscv-openocd-3bd661b679995ec3316fbe87593b3026ffcfcb55.tar.bz2
Speed things up by ignoring return values.
The remote bitbang implementation is really slow when reading back data. During many operations, like writing a block of memory, we don't need to see the return data. By communicating this to the lower layers, we get huge speedups. Downloads to spike now are 295KB/s. That means the gdbserver.py download test now runs to completion, unfortunately it fails. Everything else is still passing, though, so I'm committing this change. Change-Id: I44cc9db1ade0908c1a12d09b23fc8e529a802d88
-rw-r--r--src/target/riscv/riscv-013.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index ac954ff..d3ff660 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -218,17 +218,24 @@ static void dump_field(const struct scan_field *field)
unsigned int out_op = get_field(out, DTM_DMI_OP);
unsigned int out_data = get_field(out, DTM_DMI_DATA);
unsigned int out_address = out >> DTM_DMI_ADDRESS_OFFSET;
- uint64_t in = buf_get_u64(field->in_value, 0, field->num_bits);
- unsigned int in_op = get_field(in, DTM_DMI_OP);
- unsigned int in_data = get_field(in, DTM_DMI_DATA);
- unsigned int in_address = in >> DTM_DMI_ADDRESS_OFFSET;
- log_printf_lf(LOG_LVL_DEBUG,
- __FILE__, __LINE__, "scan",
- "%db %s %08x @%02x -> %s %08x @%02x",
- field->num_bits,
- op_string[out_op], out_data, out_address,
- status_string[in_op], in_data, in_address);
+ if (field->in_value) {
+ uint64_t in = buf_get_u64(field->in_value, 0, field->num_bits);
+ unsigned int in_op = get_field(in, DTM_DMI_OP);
+ unsigned int in_data = get_field(in, DTM_DMI_DATA);
+ unsigned int in_address = in >> DTM_DMI_ADDRESS_OFFSET;
+
+ log_printf_lf(LOG_LVL_DEBUG,
+ __FILE__, __LINE__, "scan",
+ "%db %s %08x @%02x -> %s %08x @%02x",
+ field->num_bits,
+ op_string[out_op], out_data, out_address,
+ status_string[in_op], in_data, in_address);
+ } else {
+ log_printf_lf(LOG_LVL_DEBUG,
+ __FILE__, __LINE__, "scan", "%db %s %08x @%02x -> ?",
+ field->num_bits, op_string[out_op], out_data, out_address);
+ }
}
static riscv013_info_t *get_info(const struct target *target)
@@ -309,7 +316,9 @@ static void scans_add_dmi_write(scans_t *scans, unsigned address,
uint8_t *out = scans->out + data_offset;
field->num_bits = info->abits + DMI_OP_SIZE + DMI_DATA_SIZE;
- field->in_value = scans->in + data_offset;
+ // We gain a lot of speed in remote bitbang by not looking at the return
+ // value.
+ field->in_value = NULL;
field->out_value = out;
buf_set_u64(out, DMI_OP_START, DMI_OP_SIZE, DMI_OP_WRITE);
@@ -466,9 +475,12 @@ static dmi_status_t dmi_scan(struct target *target, uint16_t *address_in,
struct scan_field field = {
.num_bits = info->abits + DMI_OP_SIZE + DMI_DATA_SIZE,
.out_value = out,
- .in_value = in
};
+ if (address_in || data_in) {
+ field.in_value = in;
+ }
+
assert(info->abits != 0);
buf_set_u64(out, DMI_OP_START, DMI_OP_SIZE, op);
@@ -2098,6 +2110,23 @@ static int read_memory(struct target *target, uint32_t address,
return ERROR_OK;
}
+/**
+ * If there was a DMI error, clear that error and return 1.
+ * Otherwise return 0.
+ */
+static int check_dmi_error(struct target *target)
+{
+ dmi_status_t status = dmi_scan(target, NULL, NULL, DMI_OP_NOP, 0, 0,
+ false);
+ if (status != DMI_STATUS_SUCCESS) {
+ // Clear errors.
+ dtmcontrol_scan(target, DTM_DTMCONTROL_DMIRESET);
+ increase_dmi_busy_delay(target);
+ return 1;
+ }
+ return 0;
+}
+
static int write_memory(struct target *target, uint32_t address,
uint32_t size, uint32_t count, const uint8_t *buffer)
{
@@ -2163,6 +2192,9 @@ static int write_memory(struct target *target, uint32_t address,
if (result != ERROR_OK)
return result;
+ int dmi_error = check_dmi_error(target);
+
+ // Clear autoexec.
dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
unsigned cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
@@ -2172,7 +2204,7 @@ static int write_memory(struct target *target, uint32_t address,
} else if (cmderr) {
LOG_ERROR("cmderr=%d", get_field(abstractcs, DMI_ABSTRACTCS_CMDERR));
return ERROR_FAIL;
- } else {
+ } else if (!dmi_error) {
break;
}
}