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_op = get_field(out, DTM_DMI_OP);
|
||||||
unsigned int out_data = get_field(out, DTM_DMI_DATA);
|
unsigned int out_data = get_field(out, DTM_DMI_DATA);
|
||||||
unsigned int out_address = out >> DTM_DMI_ADDRESS_OFFSET;
|
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);
|
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_op = get_field(in, DTM_DMI_OP);
|
||||||
unsigned int in_data = get_field(in, DTM_DMI_DATA);
|
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,
|
field->num_bits,
|
||||||
op_string[out_op], out_data, out_address,
|
op_string[out_op], out_data, out_address,
|
||||||
status_string[in_op], in_data, in_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)
|
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;
|
uint8_t *out = scans->out + data_offset;
|
||||||
field->num_bits = info->abits + DMI_OP_SIZE + DMI_DATA_SIZE;
|
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;
|
field->out_value = out;
|
||||||
|
|
||||||
buf_set_u64(out, DMI_OP_START, DMI_OP_SIZE, DMI_OP_WRITE);
|
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 = {
|
struct scan_field field = {
|
||||||
.num_bits = info->abits + DMI_OP_SIZE + DMI_DATA_SIZE,
|
.num_bits = info->abits + DMI_OP_SIZE + DMI_DATA_SIZE,
|
||||||
.out_value = out,
|
.out_value = out,
|
||||||
.in_value = in
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (address_in || data_in) {
|
||||||
|
field.in_value = in;
|
||||||
|
}
|
||||||
|
|
||||||
assert(info->abits != 0);
|
assert(info->abits != 0);
|
||||||
|
|
||||||
buf_set_u64(out, DMI_OP_START, DMI_OP_SIZE, op);
|
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;
|
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,
|
static int write_memory(struct target *target, uint32_t address,
|
||||||
uint32_t size, uint32_t count, const uint8_t *buffer)
|
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)
|
if (result != ERROR_OK)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
int dmi_error = check_dmi_error(target);
|
||||||
|
|
||||||
|
// Clear autoexec.
|
||||||
dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
|
dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
|
||||||
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
uint32_t abstractcs = dmi_read(target, DMI_ABSTRACTCS);
|
||||||
unsigned cmderr = get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
|
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) {
|
} else if (cmderr) {
|
||||||
LOG_ERROR("cmderr=%d", get_field(abstractcs, DMI_ABSTRACTCS_CMDERR));
|
LOG_ERROR("cmderr=%d", get_field(abstractcs, DMI_ABSTRACTCS_CMDERR));
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
} else {
|
} else if (!dmi_error) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue