|
6 | 6 |
|
7 | 7 | #include "batch.h" |
8 | 8 | #include "debug_defines.h" |
| 9 | +#include "debug_reg_printer.h" |
9 | 10 | #include "riscv.h" |
10 | 11 | #include "field_helpers.h" |
11 | 12 |
|
@@ -142,6 +143,83 @@ static int get_delay(const struct riscv_batch *batch, size_t scan_idx, |
142 | 143 | return delay; |
143 | 144 | } |
144 | 145 |
|
| 146 | +static unsigned int decode_dmi(const struct target *target, char *text, uint32_t address, uint32_t data) |
| 147 | +{ |
| 148 | + static const struct { |
| 149 | + uint32_t address; |
| 150 | + enum riscv_debug_reg_ordinal ordinal; |
| 151 | + } description[] = { |
| 152 | + {DM_DMCONTROL, DM_DMCONTROL_ORDINAL}, |
| 153 | + {DM_DMSTATUS, DM_DMSTATUS_ORDINAL}, |
| 154 | + {DM_ABSTRACTCS, DM_ABSTRACTCS_ORDINAL}, |
| 155 | + {DM_COMMAND, DM_COMMAND_ORDINAL}, |
| 156 | + {DM_SBCS, DM_SBCS_ORDINAL} |
| 157 | + }; |
| 158 | + |
| 159 | + for (unsigned int i = 0; i < ARRAY_SIZE(description); i++) { |
| 160 | + if (riscv_get_dmi_address(target, description[i].address) == address) { |
| 161 | + const riscv_debug_reg_ctx_t context = { |
| 162 | + .XLEN = { .value = 0, .is_set = false }, |
| 163 | + .DXLEN = { .value = 0, .is_set = false }, |
| 164 | + .abits = { .value = 0, .is_set = false }, |
| 165 | + }; |
| 166 | + return riscv_debug_reg_to_s(text, description[i].ordinal, |
| 167 | + context, data, RISCV_DEBUG_REG_HIDE_ALL_0); |
| 168 | + } |
| 169 | + } |
| 170 | + if (text) |
| 171 | + text[0] = '\0'; |
| 172 | + return 0; |
| 173 | +} |
| 174 | + |
| 175 | +static void riscv_log_dmi_scan(const struct target *target, int idle, |
| 176 | + const struct scan_field *field) |
| 177 | +{ |
| 178 | + static const char * const op_string[] = {"-", "r", "w", "?"}; |
| 179 | + static const char * const status_string[] = {"+", "?", "F", "b"}; |
| 180 | + |
| 181 | + if (debug_level < LOG_LVL_DEBUG) |
| 182 | + return; |
| 183 | + |
| 184 | + assert(field->out_value); |
| 185 | + const uint64_t out = buf_get_u64(field->out_value, 0, field->num_bits); |
| 186 | + const unsigned int out_op = get_field(out, DTM_DMI_OP); |
| 187 | + const uint32_t out_data = get_field(out, DTM_DMI_DATA); |
| 188 | + const uint32_t out_address = out >> DTM_DMI_ADDRESS_OFFSET; |
| 189 | + |
| 190 | + if (field->in_value) { |
| 191 | + const uint64_t in = buf_get_u64(field->in_value, 0, field->num_bits); |
| 192 | + const unsigned int in_op = get_field(in, DTM_DMI_OP); |
| 193 | + const uint32_t in_data = get_field(in, DTM_DMI_DATA); |
| 194 | + const uint32_t in_address = in >> DTM_DMI_ADDRESS_OFFSET; |
| 195 | + |
| 196 | + LOG_DEBUG("%db %s %08" PRIx32 " @%02" PRIx32 " -> %s %08" PRIx32 " @%02" PRIx32 "; %di", |
| 197 | + field->num_bits, op_string[out_op], out_data, out_address, |
| 198 | + status_string[in_op], in_data, in_address, idle); |
| 199 | + |
| 200 | + if (in_op == DTM_DMI_OP_SUCCESS) { |
| 201 | + char in_decoded[decode_dmi(target, NULL, in_address, in_data) + 1]; |
| 202 | + decode_dmi(target, in_decoded, in_address, in_data); |
| 203 | + /* FIXME: The current code assumes that the hardware |
| 204 | + * provides the read address in the dmi.address field |
| 205 | + * when returning the dmi.data. That is however not |
| 206 | + * required by the spec, and therefore not guaranteed. |
| 207 | + * See https://github.com/riscv-collab/riscv-openocd/issues/1043 |
| 208 | + */ |
| 209 | + LOG_DEBUG("read: %s", in_decoded); |
| 210 | + } |
| 211 | + } else { |
| 212 | + LOG_DEBUG("%db %s %08" PRIx32 " @%02" PRIx32 " -> ?; %di", |
| 213 | + field->num_bits, op_string[out_op], out_data, out_address, |
| 214 | + idle); |
| 215 | + } |
| 216 | + if (out_op == DTM_DMI_OP_WRITE) { |
| 217 | + char out_decoded[decode_dmi(target, NULL, out_address, out_data) + 1]; |
| 218 | + decode_dmi(target, out_decoded, out_address, out_data); |
| 219 | + LOG_DEBUG("write: %s", out_decoded); |
| 220 | + } |
| 221 | +} |
| 222 | + |
145 | 223 | int riscv_batch_run_from(struct riscv_batch *batch, size_t start_idx, |
146 | 224 | const struct riscv_scan_delays *delays, bool resets_delays, |
147 | 225 | size_t reset_delays_after) |
|
0 commit comments