Use the dram cache to save some scans.
parent
dce4a992a3
commit
04cfc35147
|
@ -838,10 +838,13 @@ int default_interface_jtag_execute_queue(void)
|
||||||
|
|
||||||
int result = jtag->execute_queue();
|
int result = jtag->execute_queue();
|
||||||
|
|
||||||
|
// TODO: I like these better than some of the other JTAG debug statements,
|
||||||
|
// but having both is silly.
|
||||||
struct jtag_command *cmd = jtag_command_queue;
|
struct jtag_command *cmd = jtag_command_queue;
|
||||||
while (debug_level >= LOG_LVL_DEBUG && cmd) {
|
while (debug_level >= LOG_LVL_DEBUG && cmd) {
|
||||||
switch (cmd->type) {
|
switch (cmd->type) {
|
||||||
case JTAG_SCAN:
|
case JTAG_SCAN:
|
||||||
|
#if 0
|
||||||
LOG_DEBUG("JTAG %s SCAN to %s",
|
LOG_DEBUG("JTAG %s SCAN to %s",
|
||||||
cmd->cmd.scan->ir_scan ? "IR" : "DR",
|
cmd->cmd.scan->ir_scan ? "IR" : "DR",
|
||||||
tap_state_name(cmd->cmd.scan->end_state));
|
tap_state_name(cmd->cmd.scan->end_state));
|
||||||
|
@ -868,6 +871,8 @@ int default_interface_jtag_execute_queue(void)
|
||||||
free(str);
|
free(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
{
|
||||||
uint8_t *buf = NULL;
|
uint8_t *buf = NULL;
|
||||||
int scan_bits = jtag_build_buffer(cmd->cmd.scan, &buf);
|
int scan_bits = jtag_build_buffer(cmd->cmd.scan, &buf);
|
||||||
char *str_out = buf_to_str(buf, scan_bits, 16);
|
char *str_out = buf_to_str(buf, scan_bits, 16);
|
||||||
|
@ -887,18 +892,23 @@ int default_interface_jtag_execute_queue(void)
|
||||||
last_field->num_bits, str_in);
|
last_field->num_bits, str_in);
|
||||||
free(str_in);
|
free(str_in);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case JTAG_TLR_RESET:
|
case JTAG_TLR_RESET:
|
||||||
|
#if 0
|
||||||
LOG_DEBUG("JTAG TLR RESET to %s",
|
LOG_DEBUG("JTAG TLR RESET to %s",
|
||||||
tap_state_name(cmd->cmd.statemove->end_state));
|
tap_state_name(cmd->cmd.statemove->end_state));
|
||||||
|
#endif
|
||||||
LOG_DEBUG("vvv jtag_tlr_reset(%d); // %s",
|
LOG_DEBUG("vvv jtag_tlr_reset(%d); // %s",
|
||||||
cmd->cmd.statemove->end_state,
|
cmd->cmd.statemove->end_state,
|
||||||
tap_state_name(cmd->cmd.statemove->end_state));
|
tap_state_name(cmd->cmd.statemove->end_state));
|
||||||
break;
|
break;
|
||||||
case JTAG_RUNTEST:
|
case JTAG_RUNTEST:
|
||||||
|
#if 0
|
||||||
LOG_DEBUG("JTAG RUNTEST %d cycles to %s",
|
LOG_DEBUG("JTAG RUNTEST %d cycles to %s",
|
||||||
cmd->cmd.runtest->num_cycles,
|
cmd->cmd.runtest->num_cycles,
|
||||||
tap_state_name(cmd->cmd.runtest->end_state));
|
tap_state_name(cmd->cmd.runtest->end_state));
|
||||||
|
#endif
|
||||||
LOG_DEBUG("vvv jtag_runtest(%d, %d); // %s",
|
LOG_DEBUG("vvv jtag_runtest(%d, %d); // %s",
|
||||||
cmd->cmd.runtest->num_cycles,
|
cmd->cmd.runtest->num_cycles,
|
||||||
cmd->cmd.runtest->end_state,
|
cmd->cmd.runtest->end_state,
|
||||||
|
@ -906,35 +916,32 @@ int default_interface_jtag_execute_queue(void)
|
||||||
break;
|
break;
|
||||||
case JTAG_RESET:
|
case JTAG_RESET:
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
const char *reset_str[3] = {
|
const char *reset_str[3] = {
|
||||||
"leave", "deassert", "assert"
|
"leave", "deassert", "assert"
|
||||||
};
|
};
|
||||||
LOG_DEBUG("JTAG RESET %s TRST, %s SRST",
|
LOG_DEBUG("JTAG RESET %s TRST, %s SRST",
|
||||||
reset_str[cmd->cmd.reset->trst + 1],
|
reset_str[cmd->cmd.reset->trst + 1],
|
||||||
reset_str[cmd->cmd.reset->srst + 1]);
|
reset_str[cmd->cmd.reset->srst + 1]);
|
||||||
|
#endif
|
||||||
LOG_DEBUG("vvv jtag_reset(%d, %d);",
|
LOG_DEBUG("vvv jtag_reset(%d, %d);",
|
||||||
cmd->cmd.reset->trst, cmd->cmd.reset->srst);
|
cmd->cmd.reset->trst, cmd->cmd.reset->srst);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case JTAG_PATHMOVE:
|
case JTAG_PATHMOVE:
|
||||||
LOG_DEBUG("JTAG PATHMOVE (TODO)");
|
LOG_DEBUG("JTAG PATHMOVE (TODO)");
|
||||||
abort();
|
|
||||||
break;
|
break;
|
||||||
case JTAG_SLEEP:
|
case JTAG_SLEEP:
|
||||||
LOG_DEBUG("JTAG SLEEP (TODO)");
|
LOG_DEBUG("JTAG SLEEP (TODO)");
|
||||||
abort();
|
|
||||||
break;
|
break;
|
||||||
case JTAG_STABLECLOCKS:
|
case JTAG_STABLECLOCKS:
|
||||||
LOG_DEBUG("JTAG STABLECLOCKS (TODO)");
|
LOG_DEBUG("JTAG STABLECLOCKS (TODO)");
|
||||||
abort();
|
|
||||||
break;
|
break;
|
||||||
case JTAG_TMS:
|
case JTAG_TMS:
|
||||||
LOG_DEBUG("JTAG STABLECLOCKS (TODO)");
|
LOG_DEBUG("JTAG STABLECLOCKS (TODO)");
|
||||||
abort();
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR("Unknown JTAG command: %d", cmd->type);
|
LOG_ERROR("Unknown JTAG command: %d", cmd->type);
|
||||||
abort();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cmd = cmd->next;
|
cmd = cmd->next;
|
||||||
|
|
|
@ -230,6 +230,7 @@ static dbus_status_t dbus_scan(struct target *target, uint64_t *data_in,
|
||||||
|
|
||||||
static const char *op_string[] = {"nop", "r", "w", "cw"};
|
static const char *op_string[] = {"nop", "r", "w", "cw"};
|
||||||
static const char *status_string[] = {"+", "nw", "F", "b"};
|
static const char *status_string[] = {"+", "nw", "F", "b"};
|
||||||
|
/*
|
||||||
LOG_DEBUG("vvv $display(\"hardware: dbus scan %db %s %01x:%08x @%02x -> %s %01x:%08x @%02x\");",
|
LOG_DEBUG("vvv $display(\"hardware: dbus scan %db %s %01x:%08x @%02x -> %s %01x:%08x @%02x\");",
|
||||||
field.num_bits,
|
field.num_bits,
|
||||||
op_string[buf_get_u32(out, 0, 2)],
|
op_string[buf_get_u32(out, 0, 2)],
|
||||||
|
@ -238,7 +239,7 @@ static dbus_status_t dbus_scan(struct target *target, uint64_t *data_in,
|
||||||
status_string[buf_get_u32(in, 0, 2)],
|
status_string[buf_get_u32(in, 0, 2)],
|
||||||
buf_get_u32(in, 34, 2), buf_get_u32(in, 2, 32),
|
buf_get_u32(in, 34, 2), buf_get_u32(in, 2, 32),
|
||||||
buf_get_u32(in, 36, info->addrbits));
|
buf_get_u32(in, 36, info->addrbits));
|
||||||
/*
|
*/
|
||||||
LOG_DEBUG("dbus scan %db %s %01x:%08x @%02x -> %s %01x:%08x @%02x",
|
LOG_DEBUG("dbus scan %db %s %01x:%08x @%02x -> %s %01x:%08x @%02x",
|
||||||
field.num_bits,
|
field.num_bits,
|
||||||
op_string[buf_get_u32(out, 0, 2)],
|
op_string[buf_get_u32(out, 0, 2)],
|
||||||
|
@ -247,7 +248,6 @@ static dbus_status_t dbus_scan(struct target *target, uint64_t *data_in,
|
||||||
status_string[buf_get_u32(in, 0, 2)],
|
status_string[buf_get_u32(in, 0, 2)],
|
||||||
buf_get_u32(in, 34, 2), buf_get_u32(in, 2, 32),
|
buf_get_u32(in, 34, 2), buf_get_u32(in, 2, 32),
|
||||||
buf_get_u32(in, 36, info->addrbits));
|
buf_get_u32(in, 36, info->addrbits));
|
||||||
*/
|
|
||||||
|
|
||||||
//debug_scan(target);
|
//debug_scan(target);
|
||||||
|
|
||||||
|
@ -313,21 +313,31 @@ static uint32_t dtminfo_read(struct target *target)
|
||||||
|
|
||||||
static uint32_t dram_read32(struct target *target, unsigned int index)
|
static uint32_t dram_read32(struct target *target, unsigned int index)
|
||||||
{
|
{
|
||||||
|
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||||
// TODO: check cache to see if this even needs doing.
|
// TODO: check cache to see if this even needs doing.
|
||||||
uint16_t address = dram_address(index);
|
uint16_t address = dram_address(index);
|
||||||
return dbus_read(target, address, address);
|
uint32_t value = dbus_read(target, address, address);
|
||||||
|
info->dram_valid |= (1<<index);
|
||||||
|
info->dram[index] = value;
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dram_write32(struct target *target, unsigned int index, uint32_t value,
|
static void dram_write32(struct target *target, unsigned int index, uint32_t value,
|
||||||
bool set_interrupt)
|
bool set_interrupt)
|
||||||
{
|
{
|
||||||
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||||
// TODO: check cache to see if this even needs doing.
|
|
||||||
|
if (info->dram_valid & (1<<index) && info->dram[index] == value) {
|
||||||
|
LOG_DEBUG("DRAM cache hit: 0x%x @%d", value, index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t dbus_value = DMCONTROL_HALTNOT | value;
|
uint64_t dbus_value = DMCONTROL_HALTNOT | value;
|
||||||
if (set_interrupt)
|
if (set_interrupt)
|
||||||
dbus_value |= DMCONTROL_INTERRUPT;
|
dbus_value |= DMCONTROL_INTERRUPT;
|
||||||
dbus_write(target, dram_address(index), dbus_value);
|
dbus_write(target, dram_address(index), dbus_value);
|
||||||
info->dram_valid |= (1<<index);
|
info->dram_valid |= (1<<index);
|
||||||
|
info->dram[index] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
@ -479,9 +489,13 @@ static void update_reg_list(struct target *target)
|
||||||
static int register_get(struct reg *reg)
|
static int register_get(struct reg *reg)
|
||||||
{
|
{
|
||||||
struct target *target = (struct target *) reg->arch_info;
|
struct target *target = (struct target *) reg->arch_info;
|
||||||
|
riscv_info_t *info = (riscv_info_t *) target->arch_info;
|
||||||
|
|
||||||
// TODO: S0 and S1
|
// TODO: S0 and S1
|
||||||
if (reg->number <= REG_XPR31) {
|
if (reg->number == ZERO) {
|
||||||
|
buf_set_u64(reg->value, 0, info->xlen, 0);
|
||||||
|
return ERROR_OK;
|
||||||
|
} else if (reg->number <= REG_XPR31) {
|
||||||
dram_write32(target, 0, sw(reg->number - REG_XPR0, ZERO, DEBUG_RAM_START), false);
|
dram_write32(target, 0, sw(reg->number - REG_XPR0, ZERO, DEBUG_RAM_START), false);
|
||||||
dram_write_jump(target, 1, true);
|
dram_write_jump(target, 1, true);
|
||||||
} else if (reg->number == REG_PC) {
|
} else if (reg->number == REG_PC) {
|
||||||
|
@ -1128,9 +1142,6 @@ static int riscv_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)
|
||||||
{
|
{
|
||||||
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
|
jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE);
|
||||||
// TODO: save/restore T0
|
|
||||||
|
|
||||||
// Set up the address.
|
|
||||||
|
|
||||||
// Write program.
|
// Write program.
|
||||||
dram_write32(target, 0, lw(S1, ZERO, DEBUG_RAM_START + 16), false);
|
dram_write32(target, 0, lw(S1, ZERO, DEBUG_RAM_START + 16), false);
|
||||||
|
|
Loading…
Reference in New Issue