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__archive__
parent
f9168b09d0
commit
3bd661b679
|
@ -218,6 +218,8 @@ 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;
|
||||
|
||||
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);
|
||||
|
@ -229,6 +231,11 @@ static void dump_field(const struct scan_field *field)
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue