|
From: <ge...@op...> - 2018-06-25 21:59:59
|
This is an automated email from Gerrit. Tim Newsome (ti...@si...) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/4578 -- gerrit commit d894fffa5354e00fd6115d163a3cfaf4c0b0c122 Author: Tim Newsome <ti...@si...> Date: Mon Jun 25 14:53:05 2018 -0700 Add RISC-V support. This supports both 0.11 and 0.13 versions of the debug spec. Support for `-rtos riscv` will come in a separate commit since it was easy to separate out, and is likely to be more controversial. Flash support for the SiFive boards will also come in a later commit. Change-Id: I1d38fe669c2041b4e21a5c54a091594aac3e2190 Signed-off-by: Tim Newsome <ti...@si...> diff --git a/src/helper/log.h b/src/helper/log.h index 512bcc5..d60587f 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -149,6 +149,8 @@ extern int debug_level; */ #define ERROR_FAIL (-4) #define ERROR_WAIT (-5) +/* ERROR_TIMEOUT is already taken by winerror.h. */ +#define ERROR_TIMEOUT_REACHED (-6) #endif /* OPENOCD_HELPER_LOG_H */ diff --git a/src/target/Makefile.am b/src/target/Makefile.am index fcc23ad..ad5e162 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -21,6 +21,7 @@ noinst_LTLIBRARIES += %D%/libtarget.la $(NDS32_SRC) \ $(STM8_SRC) \ $(INTEL_IA32_SRC) \ + $(RISCV_SRC) \ %D%/avrt.c \ %D%/dsp563xx.c \ %D%/dsp563xx_once.c \ @@ -136,6 +137,14 @@ INTEL_IA32_SRC = \ %D%/lakemont.c \ %D%/x86_32_common.c +RISCV_SRC = \ + %D%/riscv/riscv-011.c \ + %D%/riscv/riscv-013.c \ + %D%/riscv/riscv.c \ + %D%/riscv/riscv_semihosting.c \ + %D%/riscv/program.c \ + %D%/riscv/batch.c + %C%_libtarget_la_SOURCES += \ %D%/algorithm.h \ %D%/arm.h \ diff --git a/src/target/riscv/asm.h b/src/target/riscv/asm.h new file mode 100644 index 0000000..d81aa02 --- /dev/null +++ b/src/target/riscv/asm.h @@ -0,0 +1,38 @@ +#ifndef TARGET__RISCV__ASM_H +#define TARGET__RISCV__ASM_H + +#include "riscv.h" + +/*** Version-independent functions that we don't want in the main address space. ***/ + +static uint32_t load(const struct target *target, unsigned int rd, + unsigned int base, uint16_t offset) __attribute__ ((unused)); +static uint32_t load(const struct target *target, unsigned int rd, + unsigned int base, uint16_t offset) +{ + switch (riscv_xlen(target)) { + case 32: + return lw(rd, base, offset); + case 64: + return ld(rd, base, offset); + } + assert(0); + return 0; /* Silence -Werror=return-type */ +} + +static uint32_t store(const struct target *target, unsigned int src, + unsigned int base, uint16_t offset) __attribute__ ((unused)); +static uint32_t store(const struct target *target, unsigned int src, + unsigned int base, uint16_t offset) +{ + switch (riscv_xlen(target)) { + case 32: + return sw(src, base, offset); + case 64: + return sd(src, base, offset); + } + assert(0); + return 0; /* Silence -Werror=return-type */ +} + +#endif diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c new file mode 100644 index 0000000..9327cb3 --- /dev/null +++ b/src/target/riscv/batch.c @@ -0,0 +1,172 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "batch.h" +#include "debug_defines.h" +#include "riscv.h" + +#define get_field(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 1))) +#define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask))) + +static void dump_field(const struct scan_field *field); + +struct riscv_batch *riscv_batch_alloc(struct target *target, size_t scans, size_t idle) +{ + scans += 4; + struct riscv_batch *out = malloc(sizeof(*out)); + memset(out, 0, sizeof(*out)); + out->target = target; + out->allocated_scans = scans; + out->used_scans = 0; + out->idle_count = idle; + out->data_out = malloc(sizeof(*out->data_out) * (scans) * sizeof(uint64_t)); + out->data_in = malloc(sizeof(*out->data_in) * (scans) * sizeof(uint64_t)); + out->fields = malloc(sizeof(*out->fields) * (scans)); + out->last_scan = RISCV_SCAN_TYPE_INVALID; + out->read_keys = malloc(sizeof(*out->read_keys) * (scans)); + out->read_keys_used = 0; + return out; +} + +void riscv_batch_free(struct riscv_batch *batch) +{ + free(batch->data_in); + free(batch->data_out); + free(batch->fields); + free(batch); +} + +bool riscv_batch_full(struct riscv_batch *batch) +{ + return batch->used_scans > (batch->allocated_scans - 4); +} + +int riscv_batch_run(struct riscv_batch *batch) +{ + if (batch->used_scans == 0) { + LOG_DEBUG("Ignoring empty batch."); + return ERROR_OK; + } + + keep_alive(); + + LOG_DEBUG("running a batch of %ld scans", (long)batch->used_scans); + riscv_batch_add_nop(batch); + + for (size_t i = 0; i < batch->used_scans; ++i) { + jtag_add_dr_scan(batch->target->tap, 1, batch->fields + i, TAP_IDLE); + if (batch->idle_count > 0) + jtag_add_runtest(batch->idle_count, TAP_IDLE); + } + + LOG_DEBUG("executing queue"); + if (jtag_execute_queue() != ERROR_OK) { + LOG_ERROR("Unable to execute JTAG queue"); + return ERROR_FAIL; + } + + for (size_t i = 0; i < batch->used_scans; ++i) + dump_field(batch->fields + i); + + return ERROR_OK; +} + +void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data) +{ + assert(batch->used_scans < batch->allocated_scans); + struct scan_field *field = batch->fields + batch->used_scans; + field->num_bits = riscv_dmi_write_u64_bits(batch->target); + field->out_value = (void *)(batch->data_out + batch->used_scans * sizeof(uint64_t)); + field->in_value = (void *)(batch->data_in + batch->used_scans * sizeof(uint64_t)); + riscv_fill_dmi_write_u64(batch->target, (char *)field->out_value, address, data); + riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value); + batch->last_scan = RISCV_SCAN_TYPE_WRITE; + batch->used_scans++; +} + +size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address) +{ + assert(batch->used_scans < batch->allocated_scans); + struct scan_field *field = batch->fields + batch->used_scans; + field->num_bits = riscv_dmi_write_u64_bits(batch->target); + field->out_value = (void *)(batch->data_out + batch->used_scans * sizeof(uint64_t)); + field->in_value = (void *)(batch->data_in + batch->used_scans * sizeof(uint64_t)); + riscv_fill_dmi_read_u64(batch->target, (char *)field->out_value, address); + riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value); + batch->last_scan = RISCV_SCAN_TYPE_READ; + batch->used_scans++; + + /* FIXME We get the read response back on the next scan. For now I'm + * just sticking a NOP in there, but this should be coelesced away. */ + riscv_batch_add_nop(batch); + + batch->read_keys[batch->read_keys_used] = batch->used_scans - 1; + LOG_DEBUG("read key %u for batch 0x%p is %u (0x%p)", + (unsigned) batch->read_keys_used, batch, (unsigned) (batch->used_scans - 1), + batch->data_in + sizeof(uint64_t) * (batch->used_scans + 1)); + return batch->read_keys_used++; +} + +uint64_t riscv_batch_get_dmi_read(struct riscv_batch *batch, size_t key) +{ + assert(key < batch->read_keys_used); + size_t index = batch->read_keys[key]; + assert(index <= batch->used_scans); + uint8_t *base = batch->data_in + 8 * index; + return base[0] | + ((uint64_t) base[1]) << 8 | + ((uint64_t) base[2]) << 16 | + ((uint64_t) base[3]) << 24 | + ((uint64_t) base[4]) << 32 | + ((uint64_t) base[5]) << 40 | + ((uint64_t) base[6]) << 48 | + ((uint64_t) base[7]) << 56; +} + +void riscv_batch_add_nop(struct riscv_batch *batch) +{ + assert(batch->used_scans < batch->allocated_scans); + struct scan_field *field = batch->fields + batch->used_scans; + field->num_bits = riscv_dmi_write_u64_bits(batch->target); + field->out_value = (void *)(batch->data_out + batch->used_scans * sizeof(uint64_t)); + field->in_value = (void *)(batch->data_in + batch->used_scans * sizeof(uint64_t)); + riscv_fill_dmi_nop_u64(batch->target, (char *)field->out_value); + riscv_fill_dmi_nop_u64(batch->target, (char *)field->in_value); + batch->last_scan = RISCV_SCAN_TYPE_NOP; + batch->used_scans++; + LOG_DEBUG(" added NOP with in_value=0x%p", field->in_value); +} + +void dump_field(const struct scan_field *field) +{ + static const char * const op_string[] = {"-", "r", "w", "?"}; + static const char * const status_string[] = {"+", "?", "F", "b"}; + + if (debug_level < LOG_LVL_DEBUG) + return; + + assert(field->out_value != NULL); + uint64_t out = buf_get_u64(field->out_value, 0, field->num_bits); + 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); + unsigned int in_address = in >> DTM_DMI_ADDRESS_OFFSET; + + log_printf_lf(LOG_LVL_DEBUG, + __FILE__, __LINE__, __PRETTY_FUNCTION__, + "%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__, __PRETTY_FUNCTION__, "%db %s %08x @%02x -> ?", + field->num_bits, op_string[out_op], out_data, out_address); + } +} diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h new file mode 100644 index 0000000..70690a6 --- /dev/null +++ b/src/target/riscv/batch.h @@ -0,0 +1,64 @@ +#ifndef TARGET__RISCV__SCANS_H +#define TARGET__RISCV__SCANS_H + +#include "target/target.h" +#include "jtag/jtag.h" + +enum riscv_scan_type { + RISCV_SCAN_TYPE_INVALID, + RISCV_SCAN_TYPE_NOP, + RISCV_SCAN_TYPE_READ, + RISCV_SCAN_TYPE_WRITE, +}; + +/* A batch of multiple JTAG scans, which are grouped together to avoid the + * overhead of some JTAG adapters when sending single commands. This is + * designed to support block copies, as that's what we actually need to go + * fast. */ +struct riscv_batch { + struct target *target; + + size_t allocated_scans; + size_t used_scans; + + size_t idle_count; + + uint8_t *data_out; + uint8_t *data_in; + struct scan_field *fields; + + /* In JTAG we scan out the previous value's output when performing a + * scan. This is a pain for users, so we just provide them the + * illusion of not having to do this by eliding all but the last NOP. + * */ + enum riscv_scan_type last_scan; + + /* The read keys. */ + size_t *read_keys; + size_t read_keys_used; +}; + +/* Allocates (or frees) a new scan set. "scans" is the maximum number of JTAG + * scans that can be issued to this object, and idle is the number of JTAG idle + * cycles between every real scan. */ +struct riscv_batch *riscv_batch_alloc(struct target *target, size_t scans, size_t idle); +void riscv_batch_free(struct riscv_batch *batch); + +/* Checks to see if this batch is full. */ +bool riscv_batch_full(struct riscv_batch *batch); + +/* Executes this scan batch. */ +int riscv_batch_run(struct riscv_batch *batch); + +/* Adds a DMI write to this batch. */ +void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint64_t data); + +/* DMI reads must be handled in two parts: the first one schedules a read and + * provides a key, the second one actually obtains the value of that read .*/ +size_t riscv_batch_add_dmi_read(struct riscv_batch *batch, unsigned address); +uint64_t riscv_batch_get_dmi_read(struct riscv_batch *batch, size_t key); + +/* Scans in a NOP. */ +void riscv_batch_add_nop(struct riscv_batch *batch); + +#endif diff --git a/src/target/riscv/debug_defines.h b/src/target/riscv/debug_defines.h new file mode 100644 index 0000000..d6ddd4f --- /dev/null +++ b/src/target/riscv/debug_defines.h @@ -0,0 +1,1414 @@ +#define DTM_IDCODE 0x01 +/* +* Identifies the release version of this part. + */ +#define DTM_IDCODE_VERSION_OFFSET 28 +#define DTM_IDCODE_VERSION_LENGTH 4 +#define DTM_IDCODE_VERSION (0xfU << DTM_IDCODE_VERSION_OFFSET) +/* +* Identifies the designer's part number of this part. + */ +#define DTM_IDCODE_PARTNUMBER_OFFSET 12 +#define DTM_IDCODE_PARTNUMBER_LENGTH 16 +#define DTM_IDCODE_PARTNUMBER (0xffffU << DTM_IDCODE_PARTNUMBER_OFFSET) +/* +* Identifies the designer/manufacturer of this part. Bits 6:0 must be +* bits 6:0 of the designer/manufacturer's Identification Code as +* assigned by JEDEC Standard JEP106. Bits 10:7 contain the modulo-16 +* count of the number of continuation characters (0x7f) in that same +* Identification Code. + */ +#define DTM_IDCODE_MANUFID_OFFSET 1 +#define DTM_IDCODE_MANUFID_LENGTH 11 +#define DTM_IDCODE_MANUFID (0x7ffU << DTM_IDCODE_MANUFID_OFFSET) +#define DTM_IDCODE_1_OFFSET 0 +#define DTM_IDCODE_1_LENGTH 1 +#define DTM_IDCODE_1 (0x1U << DTM_IDCODE_1_OFFSET) +#define DTM_DTMCS 0x10 +/* +* Writing 1 to this bit does a hard reset of the DTM, +* causing the DTM to forget about any outstanding DMI transactions. +* In general this should only be used when the Debugger has +* reason to expect that the outstanding DMI transaction will never +* complete (e.g. a reset condition caused an inflight DMI transaction to +* be cancelled). + */ +#define DTM_DTMCS_DMIHARDRESET_OFFSET 17 +#define DTM_DTMCS_DMIHARDRESET_LENGTH 1 +#define DTM_DTMCS_DMIHARDRESET (0x1U << DTM_DTMCS_DMIHARDRESET_OFFSET) +/* +* Writing 1 to this bit clears the sticky error state +* and allows the DTM to retry or complete the previous +* transaction. + */ +#define DTM_DTMCS_DMIRESET_OFFSET 16 +#define DTM_DTMCS_DMIRESET_LENGTH 1 +#define DTM_DTMCS_DMIRESET (0x1U << DTM_DTMCS_DMIRESET_OFFSET) +/* +* This is a hint to the debugger of the minimum number of +* cycles a debugger should spend in +* Run-Test/Idle after every DMI scan to avoid a `busy' +* return code (\Fdmistat of 3). A debugger must still +* check \Fdmistat when necessary. +* +* 0: It is not necessary to enter Run-Test/Idle at all. +* +* 1: Enter Run-Test/Idle and leave it immediately. +* +* 2: Enter Run-Test/Idle and stay there for 1 cycle before leaving. +* +* And so on. + */ +#define DTM_DTMCS_IDLE_OFFSET 12 +#define DTM_DTMCS_IDLE_LENGTH 3 +#define DTM_DTMCS_IDLE (0x7U << DTM_DTMCS_IDLE_OFFSET) +/* +* 0: No error. +* +* 1: Reserved. Interpret the same as 2. +* +* 2: An operation failed (resulted in \Fop of 2). +* +* 3: An operation was attempted while a DMI access was still in +* progress (resulted in \Fop of 3). + */ +#define DTM_DTMCS_DMISTAT_OFFSET 10 +#define DTM_DTMCS_DMISTAT_LENGTH 2 +#define DTM_DTMCS_DMISTAT (0x3U << DTM_DTMCS_DMISTAT_OFFSET) +/* +* The size of \Faddress in \Rdmi. + */ +#define DTM_DTMCS_ABITS_OFFSET 4 +#define DTM_DTMCS_ABITS_LENGTH 6 +#define DTM_DTMCS_ABITS (0x3fU << DTM_DTMCS_ABITS_OFFSET) +/* +* 0: Version described in spec version 0.11. +* +* 1: Version described in spec version 0.13 (and later?), which +* reduces the DMI data width to 32 bits. +* +* 15: Version not described in any available version of this spec. + */ +#define DTM_DTMCS_VERSION_OFFSET 0 +#define DTM_DTMCS_VERSION_LENGTH 4 +#define DTM_DTMCS_VERSION (0xfU << DTM_DTMCS_VERSION_OFFSET) +#define DTM_DMI 0x11 +/* +* Address used for DMI access. In Update-DR this value is used +* to access the DM over the DMI. + */ +#define DTM_DMI_ADDRESS_OFFSET 34 +#define DTM_DMI_ADDRESS_LENGTH abits +#define DTM_DMI_ADDRESS (((1L<<abits)-1) << DTM_DMI_ADDRESS_OFFSET) +/* +* The data to send to the DM over the DMI during Update-DR, and +* the data returned from the DM as a result of the previous operation. + */ +#define DTM_DMI_DATA_OFFSET 2 +#define DTM_DMI_DATA_LENGTH 32 +#define DTM_DMI_DATA (0xffffffffULL << DTM_DMI_DATA_OFFSET) +/* +* When the debugger writes this field, it has the following meaning: +* +* 0: Ignore \Fdata and \Faddress. (nop) +* +* Don't send anything over the DMI during Update-DR. +* This operation should never result in a busy or error response. +* The address and data reported in the following Capture-DR +* are undefined. +* +* 1: Read from \Faddress. (read) +* +* 2: Write \Fdata to \Faddress. (write) +* +* 3: Reserved. +* +* When the debugger reads this field, it means the following: +* +* 0: The previous operation completed successfully. +* +* 1: Reserved. +* +* 2: A previous operation failed. The data scanned into \Rdmi in +* this access will be ignored. This status is sticky and can be +* cleared by writing \Fdmireset in \Rdtmcs. +* +* This indicates that the DM itself responded with an error. +* Note: there are no specified cases in which the DM would +* respond with an error, and DMI is not required to support +* returning errors. +* +* 3: An operation was attempted while a DMI request is still in +* progress. The data scanned into \Rdmi in this access will be +* ignored. This status is sticky and can be cleared by writing +* \Fdmireset in \Rdtmcs. If a debugger sees this status, it +* needs to give the target more TCK edges between Update-DR and +* Capture-DR. The simplest way to do that is to add extra transitions +* in Run-Test/Idle. +* +* (The DTM, DM, and/or component may be in different clock domains, +* so synchronization may be required. Some relatively fixed number of +* TCK ticks may be needed for the request to reach the DM, complete, +* and for the response to be synchronized back into the TCK domain.) + */ +#define DTM_DMI_OP_OFFSET 0 +#define DTM_DMI_OP_LENGTH 2 +#define DTM_DMI_OP (0x3ULL << DTM_DMI_OP_OFFSET) +#define CSR_DCSR 0x7b0 +/* +* 0: There is no external debug support. +* +* 4: External debug support exists as it is described in this document. +* +* 15: There is external debug support, but it does not conform to any +* available version of this spec. + */ +#define CSR_DCSR_XDEBUGVER_OFFSET 28 +#define CSR_DCSR_XDEBUGVER_LENGTH 4 +#define CSR_DCSR_XDEBUGVER (0xfU << CSR_DCSR_XDEBUGVER_OFFSET) +/* +* When 1, {\tt ebreak} instructions in Machine Mode enter Debug Mode. + */ +#define CSR_DCSR_EBREAKM_OFFSET 15 +#define CSR_DCSR_EBREAKM_LENGTH 1 +#define CSR_DCSR_EBREAKM (0x1U << CSR_DCSR_EBREAKM_OFFSET) +/* +* When 1, {\tt ebreak} instructions in Supervisor Mode enter Debug Mode. + */ +#define CSR_DCSR_EBREAKS_OFFSET 13 +#define CSR_DCSR_EBREAKS_LENGTH 1 +#define CSR_DCSR_EBREAKS (0x1U << CSR_DCSR_EBREAKS_OFFSET) +/* +* When 1, {\tt ebreak} instructions in User/Application Mode enter +* Debug Mode. + */ +#define CSR_DCSR_EBREAKU_OFFSET 12 +#define CSR_DCSR_EBREAKU_LENGTH 1 +#define CSR_DCSR_EBREAKU (0x1U << CSR_DCSR_EBREAKU_OFFSET) +/* +* 0: Interrupts are disabled during single stepping. +* +* 1: Interrupts are enabled during single stepping. +* +* Implementations may hard wire this bit to 0. +* The debugger must read back the value it +* writes to check whether the feature is supported. If not +* supported, interrupt behavior can be emulated by the debugger. + */ +#define CSR_DCSR_STEPIE_OFFSET 11 +#define CSR_DCSR_STEPIE_LENGTH 1 +#define CSR_DCSR_STEPIE (0x1U << CSR_DCSR_STEPIE_OFFSET) +/* +* 0: Increment counters as usual. +* +* 1: Don't increment any counters while in Debug Mode or on {\tt +* ebreak} instructions that cause entry into Debug Mode. These +* counters include the {\tt cycle} and {\tt instret} CSRs. This is +* preferred for most debugging scenarios. +* +* An implementation may choose not to support writing to this bit. +* The debugger must read back the value it writes to check whether +* the feature is supported. + */ +#define CSR_DCSR_STOPCOUNT_OFFSET 10 +#define CSR_DCSR_STOPCOUNT_LENGTH 1 +#define CSR_DCSR_STOPCOUNT (0x1U << CSR_DCSR_STOPCOUNT_OFFSET) +/* +* 0: Increment timers as usual. +* +* 1: Don't increment any hart-local timers while in Debug Mode. +* +* An implementation may choose not to support writing to this bit. +* The debugger must read back the value it writes to check whether +* the feature is supported. + */ +#define CSR_DCSR_STOPTIME_OFFSET 9 +#define CSR_DCSR_STOPTIME_LENGTH 1 +#define CSR_DCSR_STOPTIME (0x1U << CSR_DCSR_STOPTIME_OFFSET) +/* +* Explains why Debug Mode was entered. +* +* When there are multiple reasons to enter Debug Mode in a single +* cycle, hardware should set \Fcause to the cause with the highest +* priority. +* +* 1: An {\tt ebreak} instruction was executed. (priority 3) +* +* 2: The Trigger Module caused a breakpoint exception. (priority 4) +* +* 3: The debugger requested entry to Debug Mode. (priority 2) +* +* 4: The hart single stepped because \Fstep was set. (priority 1) +* +* Other values are reserved for future use. + */ +#define CSR_DCSR_CAUSE_OFFSET 6 +#define CSR_DCSR_CAUSE_LENGTH 3 +#define CSR_DCSR_CAUSE (0x7U << CSR_DCSR_CAUSE_OFFSET) +/* +* When 1, \Fmprv in \Rmstatus takes effect during debug mode. +* When 0, it is ignored during debug mode. +* Implementing this bit is optional. +* If not implemented it should be tied to 0. + */ +#define CSR_DCSR_MPRVEN_OFFSET 4 +#define CSR_DCSR_MPRVEN_LENGTH 1 +#define CSR_DCSR_MPRVEN (0x1U << CSR_DCSR_MPRVEN_OFFSET) +/* +* When set, there is a Non-Maskable-Interrupt (NMI) pending for the hart. +* +* Since an NMI can indicate a hardware error condition, +* reliable debugging may no longer be possible once this bit becomes set. +* This is implementation-dependent. + */ +#define CSR_DCSR_NMIP_OFFSET 3 +#define CSR_DCSR_NMIP_LENGTH 1 +#define CSR_DCSR_NMIP (0x1U << CSR_DCSR_NMIP_OFFSET) +/* +* When set and not in Debug Mode, the hart will only execute a single +* instruction and then enter Debug Mode. +* If the instruction does not complete due to an exception, +* the hart will immediately enter Debug Mode before executing +* the trap handler, with appropriate exception registers set. + */ +#define CSR_DCSR_STEP_OFFSET 2 +#define CSR_DCSR_STEP_LENGTH 1 +#define CSR_DCSR_STEP (0x1U << CSR_DCSR_STEP_OFFSET) +/* +* Contains the privilege level the hart was operating in when Debug +* Mode was entered. The encoding is described in Table +* \ref{tab:privlevel}. A debugger can change this value to change +* the hart's privilege level when exiting Debug Mode. +* +* Not all privilege levels are supported on all harts. If the +* encoding written is not supported or the debugger is not allowed to +* change to it, the hart may change to any supported privilege level. + */ +#define CSR_DCSR_PRV_OFFSET 0 +#define CSR_DCSR_PRV_LENGTH 2 +#define CSR_DCSR_PRV (0x3U << CSR_DCSR_PRV_OFFSET) +#define CSR_DPC 0x7b1 +#define CSR_DPC_DPC_OFFSET 0 +#define CSR_DPC_DPC_LENGTH MXLEN +#define CSR_DPC_DPC (((1L<<MXLEN)-1) << CSR_DPC_DPC_OFFSET) +#define CSR_DSCRATCH0 0x7b2 +#define CSR_DSCRATCH1 0x7b3 +#define CSR_TSELECT 0x7a0 +#define CSR_TSELECT_INDEX_OFFSET 0 +#define CSR_TSELECT_INDEX_LENGTH MXLEN +#define CSR_TSELECT_INDEX (((1L<<MXLEN)-1) << CSR_TSELECT_INDEX_OFFSET) +#define CSR_TDATA1 0x7a1 +/* +* 0: There is no trigger at this \Rtselect. +* +* 1: The trigger is a legacy SiFive address match trigger. These +* should not be implemented and aren't further documented here. +* +* 2: The trigger is an address/data match trigger. The remaining bits +* in this register act as described in \Rmcontrol. +* +* 3: The trigger is an instruction count trigger. The remaining bits +* in this register act as described in \Ricount. +* +* 4: The trigger is an interrupt trigger. The remaining bits +* in this register act as described in \Ritrigger. +* +* 5: The trigger is an exception trigger. The remaining bits +* in this register act as described in \Retrigger. +* +* 15: This trigger exists (so enumeration shouldn't terminate), but +* is not currently available. +* +* Other values are reserved for future use. +* +* When this field is written to an unsupported value, it takes on its +* reset value instead. The reset value is any one of the types +* supported by the trigger selected by \Rtselect. + */ +#define CSR_TDATA1_TYPE_OFFSET (MXLEN-4) +#define CSR_TDATA1_TYPE_LENGTH 4 +#define CSR_TDATA1_TYPE (0xfULL << CSR_TDATA1_TYPE_OFFSET) +/* +* 0: Both Debug and M Mode can write the {\tt tdata} registers at the +* selected \Rtselect. +* +* 1: Only Debug Mode can write the {\tt tdata} registers at the +* selected \Rtselect. Writes from other modes are ignored. +* +* This bit is only writable from Debug Mode. + */ +#define CSR_TDATA1_DMODE_OFFSET (MXLEN-5) +#define CSR_TDATA1_DMODE_LENGTH 1 +#define CSR_TDATA1_DMODE (0x1ULL << CSR_TDATA1_DMODE_OFFSET) +/* +* Trigger-specific data. + */ +#define CSR_TDATA1_DATA_OFFSET 0 +#define CSR_TDATA1_DATA_LENGTH (MXLEN - 5) +#define CSR_TDATA1_DATA (((1L<<MXLEN - 5)-1) << CSR_TDATA1_DATA_OFFSET) +#define CSR_TDATA2 0x7a2 +#define CSR_TDATA2_DATA_OFFSET 0 +#define CSR_TDATA2_DATA_LENGTH MXLEN +#define CSR_TDATA2_DATA (((1L<<MXLEN)-1) << CSR_TDATA2_DATA_OFFSET) +#define CSR_TDATA3 0x7a3 +#define CSR_TDATA3_DATA_OFFSET 0 +#define CSR_TDATA3_DATA_LENGTH MXLEN +#define CSR_TDATA3_DATA (((1L<<MXLEN)-1) << CSR_TDATA3_DATA_OFFSET) +#define CSR_TINFO 0x7a4 +/* +* One bit for each possible \Ftype enumerated in \Rtdataone. Bit N +* corresponds to type N. If the bit is set, then that type is +* supported by the currently selected trigger. +* +* If the currently selected trigger doesn't exist, this field +* contains 1. +* +* If \Ftype is not writable, this register may be unimplemented, in +* which case reading it causes an illegal instruction exception. In +* this case the debugger can read the only supported type from +* \Rtdataone. + */ +#define CSR_TINFO_INFO_OFFSET 0 +#define CSR_TINFO_INFO_LENGTH 16 +#define CSR_TINFO_INFO (0xffffULL << CSR_TINFO_INFO_OFFSET) +#define CSR_MCONTROL 0x7a1 +#define CSR_MCONTROL_TYPE_OFFSET (MXLEN-4) +#define CSR_MCONTROL_TYPE_LENGTH 4 +#define CSR_MCONTROL_TYPE (0xfULL << CSR_MCONTROL_TYPE_OFFSET) +#define CSR_MCONTROL_DMODE_OFFSET (MXLEN-5) +#define CSR_MCONTROL_DMODE_LENGTH 1 +#define CSR_MCONTROL_DMODE (0x1ULL << CSR_MCONTROL_DMODE_OFFSET) +/* +* Specifies the largest naturally aligned powers-of-two (NAPOT) range +* supported by the hardware when \Fmatch is 1. The value is the +* logarithm base 2 of the +* number of bytes in that range. A value of 0 indicates that only +* exact value matches are supported (one byte range). A value of 63 +* corresponds to the maximum NAPOT range, which is $2^{63}$ bytes in +* size. + */ +#define CSR_MCONTROL_MASKMAX_OFFSET (MXLEN-11) +#define CSR_MCONTROL_MASKMAX_LENGTH 6 +#define CSR_MCONTROL_MASKMAX (0x3fULL << CSR_MCONTROL_MASKMAX_OFFSET) +/* +* If this optional bit is implemented, the hardware sets it when this +* trigger matches. The trigger's user can set or clear it at any +* time. The trigger's user can use this bit to determine which +* trigger(s) matched. If the bit is not implemented, it is always 0 +* and writing it has no effect. + */ +#define CSR_MCONTROL_HIT_OFFSET 20 +#define CSR_MCONTROL_HIT_LENGTH 1 +#define CSR_MCONTROL_HIT (0x1ULL << CSR_MCONTROL_HIT_OFFSET) +/* +* 0: Perform a match on the virtual address. +* +* 1: Perform a match on the data value loaded/stored, or the +* instruction executed. + */ +#define CSR_MCONTROL_SELECT_OFFSET 19 +#define CSR_MCONTROL_SELECT_LENGTH 1 +#define CSR_MCONTROL_SELECT (0x1ULL << CSR_MCONTROL_SELECT_OFFSET) +/* +* 0: The action for this trigger will be taken just before the +* instruction that triggered it is executed, but after all preceding +* instructions are are committed. +* +* 1: The action for this trigger will be taken after the instruction +* that triggered it is executed. It should be taken before the next +* instruction is executed, but it is better to implement triggers and +* not implement that suggestion than to not implement them at all. +* +* Most hardware will only implement one timing or the other, possibly +* dependent on \Fselect, \Fexecute, \Fload, and \Fstore. This bit +* primarily exists for the hardware to communicate to the debugger +* what will happen. Hardware may implement the bit fully writable, in +* which case the debugger has a little more control. +* +* Data load triggers with \Ftiming of 0 will result in the same load +* happening again when the debugger lets the hart run. For data load +* triggers, debuggers must first attempt to set the breakpoint with +* \Ftiming of 1. +* +* A chain of triggers that don't all have the same \Ftiming value +* will never fire (unless consecutive instructions match the +* appropriate triggers). + */ +#define CSR_MCONTROL_TIMING_OFFSET 18 +#define CSR_MCONTROL_TIMING_LENGTH 1 +#define CSR_MCONTROL_TIMING (0x1ULL << CSR_MCONTROL_TIMING_OFFSET) +/* +* The action to take when the trigger fires. The values are explained +* in Table~\ref{tab:action}. + */ +#define CSR_MCONTROL_ACTION_OFFSET 12 +#define CSR_MCONTROL_ACTION_LENGTH 6 +#define CSR_MCONTROL_ACTION (0x3fULL << CSR_MCONTROL_ACTION_OFFSET) +/* +* 0: When this trigger matches, the configured action is taken. +* +* 1: While this trigger does not match, it prevents the trigger with +* the next index from matching. +* +* Because \Fchain affects the next trigger, hardware must zero it in +* writes to \Rmcontrol that set \Fdmode to 0 if the next trigger has +* \Fdmode of 1. +* In addition hardware should ignore writes to \Rmcontrol that set +* \Fdmode to 1 if the previous trigger has both \Fdmode of 0 and +* \Fchain of 1. Debuggers must avoid the latter case by checking +* \Fchain on the previous trigger if they're writing \Rmcontrol. +* +* Implementations that wish to limit the maximum length of a trigger +* chain (eg. to meet timing requirements) may do so by zeroing +* \Fchain in writes to \Rmcontrol that would make the chain too long. + */ +#define CSR_MCONTROL_CHAIN_OFFSET 11 +#define CSR_MCONTROL_CHAIN_LENGTH 1 +#define CSR_MCONTROL_CHAIN (0x1ULL << CSR_MCONTROL_CHAIN_OFFSET) +/* +* 0: Matches when the value equals \Rtdatatwo. +* +* 1: Matches when the top M bits of the value match the top M bits of +* \Rtdatatwo. M is MXLEN-1 minus the index of the least-significant +* bit containing 0 in \Rtdatatwo. +* +* 2: Matches when the value is greater than (unsigned) or equal to +* \Rtdatatwo. +* +* 3: Matches when the value is less than (unsigned) \Rtdatatwo. +* +* 4: Matches when the lower half of the value equals the lower half +* of \Rtdatatwo after the lower half of the value is ANDed with the +* upper half of \Rtdatatwo. +* +* 5: Matches when the upper half of the value equals the lower half +* of \Rtdatatwo after the upper half of the value is ANDed with the +* upper half of \Rtdatatwo. +* +* Other values are reserved for future use. + */ +#define CSR_MCONTROL_MATCH_OFFSET 7 +#define CSR_MCONTROL_MATCH_LENGTH 4 +#define CSR_MCONTROL_MATCH (0xfULL << CSR_MCONTROL_MATCH_OFFSET) +/* +* When set, enable this trigger in M mode. + */ +#define CSR_MCONTROL_M_OFFSET 6 +#define CSR_MCONTROL_M_LENGTH 1 +#define CSR_MCONTROL_M (0x1ULL << CSR_MCONTROL_M_OFFSET) +/* +* When set, enable this trigger in S mode. + */ +#define CSR_MCONTROL_S_OFFSET 4 +#define CSR_MCONTROL_S_LENGTH 1 +#define CSR_MCONTROL_S (0x1ULL << CSR_MCONTROL_S_OFFSET) +/* +* When set, enable this trigger in U mode. + */ +#define CSR_MCONTROL_U_OFFSET 3 +#define CSR_MCONTROL_U_LENGTH 1 +#define CSR_MCONTROL_U (0x1ULL << CSR_MCONTROL_U_OFFSET) +/* +* When set, the trigger fires on the virtual address or opcode of an +* instruction that is executed. + */ +#define CSR_MCONTROL_EXECUTE_OFFSET 2 +#define CSR_MCONTROL_EXECUTE_LENGTH 1 +#define CSR_MCONTROL_EXECUTE (0x1ULL << CSR_MCONTROL_EXECUTE_OFFSET) +/* +* When set, the trigger fires on the virtual address or data of a store. + */ +#define CSR_MCONTROL_STORE_OFFSET 1 +#define CSR_MCONTROL_STORE_LENGTH 1 +#define CSR_MCONTROL_STORE (0x1ULL << CSR_MCONTROL_STORE_OFFSET) +/* +* When set, the trigger fires on the virtual address or data of a load. + */ +#define CSR_MCONTROL_LOAD_OFFSET 0 +#define CSR_MCONTROL_LOAD_LENGTH 1 +#define CSR_MCONTROL_LOAD (0x1ULL << CSR_MCONTROL_LOAD_OFFSET) +#define CSR_ICOUNT 0x7a1 +#define CSR_ICOUNT_TYPE_OFFSET (MXLEN-4) +#define CSR_ICOUNT_TYPE_LENGTH 4 +#define CSR_ICOUNT_TYPE (0xfULL << CSR_ICOUNT_TYPE_OFFSET) +#define CSR_ICOUNT_DMODE_OFFSET (MXLEN-5) +#define CSR_ICOUNT_DMODE_LENGTH 1 +#define CSR_ICOUNT_DMODE (0x1ULL << CSR_ICOUNT_DMODE_OFFSET) +/* +* If this optional bit is implemented, the hardware sets it when this +* trigger matches. The trigger's user can set or clear it at any +* time. The trigger's user can use this bit to determine which +* trigger(s) matched. If the bit is not implemented, it is always 0 +* and writing it has no effect. + */ +#define CSR_ICOUNT_HIT_OFFSET 24 +#define CSR_ICOUNT_HIT_LENGTH 1 +#define CSR_ICOUNT_HIT (0x1ULL << CSR_ICOUNT_HIT_OFFSET) +/* +* When count is decremented to 0, the trigger fires. Instead of +* changing \Fcount from 1 to 0, it is also acceptable for hardware to +* clear \Fm, \Fs, and \Fu. This allows \Fcount to be hard-wired +* to 1 if this register just exists for single step. + */ +#define CSR_ICOUNT_COUNT_OFFSET 10 +#define CSR_ICOUNT_COUNT_LENGTH 14 +#define CSR_ICOUNT_COUNT (0x3fffULL << CSR_ICOUNT_COUNT_OFFSET) +/* +* When set, every instruction completed or exception taken in M mode decrements \Fcount +* by 1. + */ +#define CSR_ICOUNT_M_OFFSET 9 +#define CSR_ICOUNT_M_LENGTH 1 +#define CSR_ICOUNT_M (0x1ULL << CSR_ICOUNT_M_OFFSET) +/* +* When set, every instruction completed or exception taken in S mode decrements \Fcount +* by 1. + */ +#define CSR_ICOUNT_S_OFFSET 7 +#define CSR_ICOUNT_S_LENGTH 1 +#define CSR_ICOUNT_S (0x1ULL << CSR_ICOUNT_S_OFFSET) +/* +* When set, every instruction completed or exception taken in U mode decrements \Fcount +* by 1. + */ +#define CSR_ICOUNT_U_OFFSET 6 +#define CSR_ICOUNT_U_LENGTH 1 +#define CSR_ICOUNT_U (0x1ULL << CSR_ICOUNT_U_OFFSET) +/* +* The action to take when the trigger fires. The values are explained +* in Table~\ref{tab:action}. + */ +#define CSR_ICOUNT_ACTION_OFFSET 0 +#define CSR_ICOUNT_ACTION_LENGTH 6 +#define CSR_ICOUNT_ACTION (0x3fULL << CSR_ICOUNT_ACTION_OFFSET) +#define CSR_ITRIGGER 0x7a1 +#define CSR_ITRIGGER_TYPE_OFFSET (MXLEN-4) +#define CSR_ITRIGGER_TYPE_LENGTH 4 +#define CSR_ITRIGGER_TYPE (0xfULL << CSR_ITRIGGER_TYPE_OFFSET) +#define CSR_ITRIGGER_DMODE_OFFSET (MXLEN-5) +#define CSR_ITRIGGER_DMODE_LENGTH 1 +#define CSR_ITRIGGER_DMODE (0x1ULL << CSR_ITRIGGER_DMODE_OFFSET) +/* +* If this optional bit is implemented, the hardware sets it when this +* trigger matches. The trigger's user can set or clear it at any +* time. The trigger's user can use this bit to determine which +* trigger(s) matched. If the bit is not implemented, it is always 0 +* and writing it has no effect. + */ +#define CSR_ITRIGGER_HIT_OFFSET (MXLEN-6) +#define CSR_ITRIGGER_HIT_LENGTH 1 +#define CSR_ITRIGGER_HIT (0x1ULL << CSR_ITRIGGER_HIT_OFFSET) +/* +* When set, enable this trigger for interrupts that are taken from M +* mode. + */ +#define CSR_ITRIGGER_M_OFFSET 9 +#define CSR_ITRIGGER_M_LENGTH 1 +#define CSR_ITRIGGER_M (0x1ULL << CSR_ITRIGGER_M_OFFSET) +/* +* When set, enable this trigger for interrupts that are taken from S +* mode. + */ +#define CSR_ITRIGGER_S_OFFSET 7 +#define CSR_ITRIGGER_S_LENGTH 1 +#define CSR_ITRIGGER_S (0x1ULL << CSR_ITRIGGER_S_OFFSET) +/* +* When set, enable this trigger for interrupts that are taken from U +* mode. + */ +#define CSR_ITRIGGER_U_OFFSET 6 +#define CSR_ITRIGGER_U_LENGTH 1 +#define CSR_ITRIGGER_U (0x1ULL << CSR_ITRIGGER_U_OFFSET) +/* +* The action to take when the trigger fires. The values are explained +* in Table~\ref{tab:action}. + */ +#define CSR_ITRIGGER_ACTION_OFFSET 0 +#define CSR_ITRIGGER_ACTION_LENGTH 6 +#define CSR_ITRIGGER_ACTION (0x3fULL << CSR_ITRIGGER_ACTION_OFFSET) +#define CSR_ETRIGGER 0x7a1 +#define CSR_ETRIGGER_TYPE_OFFSET (MXLEN-4) +#define CSR_ETRIGGER_TYPE_LENGTH 4 +#define CSR_ETRIGGER_TYPE (0xfULL << CSR_ETRIGGER_TYPE_OFFSET) +#define CSR_ETRIGGER_DMODE_OFFSET (MXLEN-5) +#define CSR_ETRIGGER_DMODE_LENGTH 1 +#define CSR_ETRIGGER_DMODE (0x1ULL << CSR_ETRIGGER_DMODE_OFFSET) +/* +* If this optional bit is implemented, the hardware sets it when this +* trigger matches. The trigger's user can set or clear it at any +* time. The trigger's user can use this bit to determine which +* trigger(s) matched. If the bit is not implemented, it is always 0 +* and writing it has no effect. + */ +#define CSR_ETRIGGER_HIT_OFFSET (MXLEN-6) +#define CSR_ETRIGGER_HIT_LENGTH 1 +#define CSR_ETRIGGER_HIT (0x1ULL << CSR_ETRIGGER_HIT_OFFSET) +/* +* When set, enable this trigger for exceptions that are taken from M +* mode. + */ +#define CSR_ETRIGGER_M_OFFSET 9 +#define CSR_ETRIGGER_M_LENGTH 1 +#define CSR_ETRIGGER_M (0x1ULL << CSR_ETRIGGER_M_OFFSET) +/* +* When set, enable this trigger for exceptions that are taken from S +* mode. + */ +#define CSR_ETRIGGER_S_OFFSET 7 +#define CSR_ETRIGGER_S_LENGTH 1 +#define CSR_ETRIGGER_S (0x1ULL << CSR_ETRIGGER_S_OFFSET) +/* +* When set, enable this trigger for exceptions that are taken from U +* mode. + */ +#define CSR_ETRIGGER_U_OFFSET 6 +#define CSR_ETRIGGER_U_LENGTH 1 +#define CSR_ETRIGGER_U (0x1ULL << CSR_ETRIGGER_U_OFFSET) +/* +* The action to take when the trigger fires. The values are explained +* in Table~\ref{tab:action}. + */ +#define CSR_ETRIGGER_ACTION_OFFSET 0 +#define CSR_ETRIGGER_ACTION_LENGTH 6 +#define CSR_ETRIGGER_ACTION (0x3fULL << CSR_ETRIGGER_ACTION_OFFSET) +#define DMI_DMSTATUS 0x11 +/* +* If 1, then there is an implicit {\tt ebreak} instruction at the +* non-existent word immediately after the Program Buffer. This saves +* the debugger from having to write the {\tt ebreak} itself, and +* allows the Program Buffer to be one word smaller. +* +* This must be 1 when \Fprogbufsize is 1. + */ +#define DMI_DMSTATUS_IMPEBREAK_OFFSET 22 +#define DMI_DMSTATUS_IMPEBREAK_LENGTH 1 +#define DMI_DMSTATUS_IMPEBREAK (0x1U << DMI_DMSTATUS_IMPEBREAK_OFFSET) +/* +* This field is 1 when all currently selected harts have been reset but the reset has not been acknowledged. + */ +#define DMI_DMSTATUS_ALLHAVERESET_OFFSET 19 +#define DMI_DMSTATUS_ALLHAVERESET_LENGTH 1 +#define DMI_DMSTATUS_ALLHAVERESET (0x1U << DMI_DMSTATUS_ALLHAVERESET_OFFSET) +/* +* This field is 1 when any currently selected hart has been reset but the reset has not been acknowledged. + */ +#define DMI_DMSTATUS_ANYHAVERESET_OFFSET 18 +#define DMI_DMSTATUS_ANYHAVERESET_LENGTH 1 +#define DMI_DMSTATUS_ANYHAVERESET (0x1U << DMI_DMSTATUS_ANYHAVERESET_OFFSET) +/* +* This field is 1 when all currently selected harts have acknowledged +* the previous resume request. + */ +#define DMI_DMSTATUS_ALLRESUMEACK_OFFSET 17 +#define DMI_DMSTATUS_ALLRESUMEACK_LENGTH 1 +#define DMI_DMSTATUS_ALLRESUMEACK (0x1U << DMI_DMSTATUS_ALLRESUMEACK_OFFSET) +/* +* This field is 1 when any currently selected hart has acknowledged +* the previous resume request. + */ +#define DMI_DMSTATUS_ANYRESUMEACK_OFFSET 16 +#define DMI_DMSTATUS_ANYRESUMEACK_LENGTH 1 +#define DMI_DMSTATUS_ANYRESUMEACK (0x1U << DMI_DMSTATUS_ANYRESUMEACK_OFFSET) +/* +* This field is 1 when all currently selected harts do not exist in this system. + */ +#define DMI_DMSTATUS_ALLNONEXISTENT_OFFSET 15 +#define DMI_DMSTATUS_ALLNONEXISTENT_LENGTH 1 +#define DMI_DMSTATUS_ALLNONEXISTENT (0x1U << DMI_DMSTATUS_ALLNONEXISTENT_OFFSET) +/* +* This field is 1 when any currently selected hart does not exist in this system. + */ +#define DMI_DMSTATUS_ANYNONEXISTENT_OFFSET 14 +#define DMI_DMSTATUS_ANYNONEXISTENT_LENGTH 1 +#define DMI_DMSTATUS_ANYNONEXISTENT (0x1U << DMI_DMSTATUS_ANYNONEXISTENT_OFFSET) +/* +* This field is 1 when all currently selected harts are unavailable. + */ +#define DMI_DMSTATUS_ALLUNAVAIL_OFFSET 13 +#define DMI_DMSTATUS_ALLUNAVAIL_LENGTH 1 +#define DMI_DMSTATUS_ALLUNAVAIL (0x1U << DMI_DMSTATUS_ALLUNAVAIL_OFFSET) +/* +* This field is 1 when any currently selected hart is unavailable. + */ +#define DMI_DMSTATUS_ANYUNAVAIL_OFFSET 12 +#define DMI_DMSTATUS_ANYUNAVAIL_LENGTH 1 +#define DMI_DMSTATUS_ANYUNAVAIL (0x1U << DMI_DMSTATUS_ANYUNAVAIL_OFFSET) +/* +* This field is 1 when all currently selected harts are running. + */ +#define DMI_DMSTATUS_ALLRUNNING_OFFSET 11 +#define DMI_DMSTATUS_ALLRUNNING_LENGTH 1 +#define DMI_DMSTATUS_ALLRUNNING (0x1U << DMI_DMSTATUS_ALLRUNNING_OFFSET) +/* +* This field is 1 when any currently selected hart is running. + */ +#define DMI_DMSTATUS_ANYRUNNING_OFFSET 10 +#define DMI_DMSTATUS_ANYRUNNING_LENGTH 1 +#define DMI_DMSTATUS_ANYRUNNING (0x1U << DMI_DMSTATUS_ANYRUNNING_OFFSET) +/* +* This field is 1 when all currently selected harts are halted. + */ +#define DMI_DMSTATUS_ALLHALTED_OFFSET 9 +#define DMI_DMSTATUS_ALLHALTED_LENGTH 1 +#define DMI_DMSTATUS_ALLHALTED (0x1U << DMI_DMSTATUS_ALLHALTED_OFFSET) +/* +* This field is 1 when any currently selected hart is halted. + */ +#define DMI_DMSTATUS_ANYHALTED_OFFSET 8 +#define DMI_DMSTATUS_ANYHALTED_LENGTH 1 +#define DMI_DMSTATUS_ANYHALTED (0x1U << DMI_DMSTATUS_ANYHALTED_OFFSET) +/* +* 0 when authentication is required before using the DM. 1 when the +* authentication check has passed. On components that don't implement +* authentication, this bit must be preset as 1. + */ +#define DMI_DMSTATUS_AUTHENTICATED_OFFSET 7 +#define DMI_DMSTATUS_AUTHENTICATED_LENGTH 1 +#define DMI_DMSTATUS_AUTHENTICATED (0x1U << DMI_DMSTATUS_AUTHENTICATED_OFFSET) +/* +* 0: The authentication module is ready to process the next +* read/write to \Rauthdata. +* +* 1: The authentication module is busy. Accessing \Rauthdata results +* in unspecified behavior. +* +* \Fauthbusy only becomes set in immediate response to an access to +* \Rauthdata. + */ +#define DMI_DMSTATUS_AUTHBUSY_OFFSET 6 +#define DMI_DMSTATUS_AUTHBUSY_LENGTH 1 +#define DMI_DMSTATUS_AUTHBUSY (0x1U << DMI_DMSTATUS_AUTHBUSY_OFFSET) +/* +* 1 if this Debug Module supports halt-on-reset functionality +* controllable by the \Fsetresethaltreq and \Fclrresethaltreq bits. +* 0 otherwise. + */ +#define DMI_DMSTATUS_HASRESETHALTREQ_OFFSET 5 +#define DMI_DMSTATUS_HASRESETHALTREQ_LENGTH 1 +#define DMI_DMSTATUS_HASRESETHALTREQ (0x1U << DMI_DMSTATUS_HASRESETHALTREQ_OFFSET) +/* +* 0: \Rdevtreeaddrzero--\Rdevtreeaddrthree hold information which +* is not relevant to the Device Tree. +* +* 1: \Rdevtreeaddrzero--\Rdevtreeaddrthree registers hold the address of the +* Device Tree. + */ +#define DMI_DMSTATUS_DEVTREEVALID_OFFSET 4 +#define DMI_DMSTATUS_DEVTREEVALID_LENGTH 1 +#define DMI_DMSTATUS_DEVTREEVALID (0x1U << DMI_DMSTATUS_DEVTREEVALID_OFFSET) +/* +* 0: There is no Debug Module present. +* +* 1: There is a Debug Module and it conforms to version 0.11 of this +* specification. +* +* 2: There is a Debug Module and it conforms to version 0.13 of this +* specification. +* +* 15: There is a Debug Module but it does not conform to any +* available version of this spec. + */ +#define DMI_DMSTATUS_VERSION_OFFSET 0 +#define DMI_DMSTATUS_VERSION_LENGTH 4 +#define DMI_DMSTATUS_VERSION (0xfU << DMI_DMSTATUS_VERSION_OFFSET) +#define DMI_DMCONTROL 0x10 +/* +* Writes the halt request bit for all currently selected harts. +* When set to 1, each selected hart will halt if it is not currently +* halted. +* +* Writing 1 or 0 has no effect on a hart which is already halted, but +* the bit must be cleared to 0 before the hart is resumed. +* +* Writes apply to the new value of \Fhartsel and \Fhasel. + */ +#define DMI_DMCONTROL_HALTREQ_OFFSET 31 +#define DMI_DMCONTROL_HALTREQ_LENGTH 1 +#define DMI_DMCONTROL_HALTREQ (0x1U << DMI_DMCONTROL_HALTREQ_OFFSET) +/* +* Writes the resume request bit for all currently selected harts. +* When set to 1, each selected hart will resume if it is currently +* halted. +* +* The resume request bit is ignored while the halt request bit is +* set. +* +* Writes apply to the new value of \Fhartsel and \Fhasel. + */ +#define DMI_DMCONTROL_RESUMEREQ_OFFSET 30 +#define DMI_DMCONTROL_RESUMEREQ_LENGTH 1 +#define DMI_DMCONTROL_RESUMEREQ (0x1U << DMI_DMCONTROL_RESUMEREQ_OFFSET) +/* +* This optional field writes the reset bit for all the currently +* selected harts. To perform a reset the debugger writes 1, and then +* writes 0 to deassert the reset signal. +* +* If this feature is not implemented, the bit always stays 0, so +* after writing 1 the debugger can read the register back to see if +* the feature is supported. +* +* Writes apply to the new value of \Fhartsel and \Fhasel. + */ +#define DMI_DMCONTROL_HARTRESET_OFFSET 29 +#define DMI_DMCONTROL_HARTRESET_LENGTH 1 +#define DMI_DMCONTROL_HARTRESET (0x1U << DMI_DMCONTROL_HARTRESET_OFFSET) +/* +* Writing 1 to this bit clears the {\tt havereset} bits for +* any selected harts. +* +* Writes apply to the new value of \Fhartsel and \Fhasel. + */ +#define DMI_DMCONTROL_ACKHAVERESET_OFFSET 28 +#define DMI_DMCONTROL_ACKHAVERESET_LENGTH 1 +#define DMI_DMCONTROL_ACKHAVERESET (0x1U << DMI_DMCONTROL_ACKHAVERESET_OFFSET) +/* +* Selects the definition of currently selected harts. +* +* 0: There is a single currently selected hart, that selected by \Fhartsel. +* +* 1: There may be multiple currently selected harts -- that selected by \Fhartsel, +* plus those selected by the hart array mask register. +* +* An implementation which does not implement the hart array mask register +* must tie this field to 0. A debugger which wishes to use the hart array +* mask register feature should set this bit and read back to see if the functionality +* is supported. + */ +#define DMI_DMCONTROL_HASEL_OFFSET 26 +#define DMI_DMCONTROL_HASEL_LENGTH 1 +#define DMI_DMCONTROL_HASEL (0x1U << DMI_DMCONTROL_HASEL_OFFSET) +/* +* The low 10 bits of \Fhartsel: the DM-specific index of the hart to +* select. This hart is always part of the currently selected harts. + */ +#define DMI_DMCONTROL_HARTSELLO_OFFSET 16 +#define DMI_DMCONTROL_HARTSELLO_LENGTH 10 +#define DMI_DMCONTROL_HARTSELLO (0x3ffU << DMI_DMCONTROL_HARTSELLO_OFFSET) +/* +* The high 10 bits of \Fhartsel: the DM-specific index of the hart to +* select. This hart is always part of the currently selected harts. + */ +#define DMI_DMCONTROL_HARTSELHI_OFFSET 6 +#define DMI_DMCONTROL_HARTSELHI_LENGTH 10 +#define DMI_DMCONTROL_HARTSELHI (0x3ffU << DMI_DMCONTROL_HARTSELHI_OFFSET) +/* +* This optional field writes the halt-on-reset request bit for all +* currently selected harts. +* When set to 1, each selected hart will halt upon the next deassertion +* of its reset. The halt-on-reset request bit is not automatically +* cleared. The debugger must write to \Fclrresethaltreq to clear it. +* +* Writes apply to the new value of \Fhartsel and \Fhasel. +* +* If \Fhasresethaltreq is 0, this field is not implemented. + */ +#define DMI_DMCONTROL_SETRESETHALTREQ_OFFSET 3 +#define DMI_DMCONTROL_SETRESETHALTREQ_LENGTH 1 +#define DMI_DMCONTROL_SETRESETHALTREQ (0x1U << DMI_DMCONTROL_SETRESETHALTREQ_OFFSET) +/* +* This optional field clears the halt-on-reset request bit for all +* currently selected harts. +* +* Writes apply to the new value of \Fhartsel and \Fhasel. + */ +#define DMI_DMCONTROL_CLRRESETHALTREQ_OFFSET 2 +#define DMI_DMCONTROL_CLRRESETHALTREQ_LENGTH 1 +#define DMI_DMCONTROL_CLRRESETHALTREQ (0x1U << DMI_DMCONTROL_CLRRESETHALTREQ_OFFSET) +/* +* This bit controls the reset signal from the DM to the rest of the +* system. The signal should reset every part of the system, including +* every hart, except for the DM and any logic required to access the +* DM. +* To perform a system reset the debugger writes 1, +* and then writes 0 +* to deassert the reset. + */ +#define DMI_DMCONTROL_NDMRESET_OFFSET 1 +#define DMI_DMCONTROL_NDMRESET_LENGTH 1 +#define DMI_DMCONTROL_NDMRESET (0x1U << DMI_DMCONTROL_NDMRESET_OFFSET) +/* +* This bit serves as a reset signal for the Debug Module itself. +* +* 0: The module's state, including authentication mechanism, +* takes its reset values (the \Fdmactive bit is the only bit which can +* be written to something other than its reset value). +* +* 1: The module functions normally. +* +* No other mechanism should exist that may result in resetting the +* Debug Module after power up, including the platform's system reset +* or Debug Transport reset signals. +* +* A debugger may pulse this bit low to get the Debug Module into a +* known state. +* +* Implementations may use this bit to aid debugging, for example by +* preventing the Debug Module from being power gated while debugging +* is active. + */ +#define DMI_DMCONTROL_DMACTIVE_OFFSET 0 +#define DMI_DMCONTROL_DMACTIVE_LENGTH 1 +#define DMI_DMCONTROL_DMACTIVE (0x1U << DMI_DMCONTROL_DMACTIVE_OFFSET) +#define DMI_HARTINFO 0x12 +/* +* Number of {\tt dscratch} registers available for the debugger +* to use during program buffer execution, starting from \Rdscratchzero. +* The debugger can make no assumptions about the contents of these +* registers between commands. + */ +#define DMI_HARTINFO_NSCRATCH_OFFSET 20 +#define DMI_HARTINFO_NSCRATCH_LENGTH 4 +#define DMI_HARTINFO_NSCRATCH (0xfU << DMI_HARTINFO_NSCRATCH_OFFSET) +/* +* 0: The {\tt data} registers are shadowed in the hart by CSR +* registers. Each CSR register is MXLEN bits in size, and corresponds +* to a single argument, per Table~\ref{tab:datareg}. +* +* 1: The {\tt data} registers are shadowed in the hart's memory map. +* Each register takes up 4 bytes in the memory map. + */ +#define DMI_HARTINFO_DATAACCESS_OFFSET 16 +#define DMI_HARTINFO_DATAACCESS_LENGTH 1 +#define DMI_HARTINFO_DATAACCESS (0x1U << DMI_HARTINFO_DATAACCESS_OFFSET) +/* +* If \Fdataaccess is 0: Number of CSR registers dedicated to +* shadowing the {\tt data} registers. +* +* If \Fdataaccess is 1: Number of 32-bit words in the memory map +* dedicated to shadowing the {\tt data} registers. +* +* Since there are at most 12 {\tt data} registers, the value in this +* register must be 12 or smaller. + */ +#define DMI_HARTINFO_DATASIZE_OFFSET 12 +#define DMI_HARTINFO_DATASIZE_LENGTH 4 +#define DMI_HARTINFO_DATASIZE (0xfU << DMI_HARTINFO_DATASIZE_OFFSET) +/* +* If \Fdataaccess is 0: The number of the first CSR dedicated to +* shadowing the {\tt data} registers. +* +* If \Fdataaccess is 1: Signed address of RAM where the {\tt data} +* registers are shadowed, to be used to access relative to \Rzero. + */ +#define DMI_HARTINFO_DATAADDR_OFFSET 0 +#define DMI_HARTINFO_DATAADDR_LENGTH 12 +#define DMI_HARTINFO_DATAADDR (0xfffU << DMI_HARTINFO_DATAADDR_OFFSET) +#define DMI_HAWINDOWSEL 0x14 +/* +* The high bits of this field may be tied to 0, depending on how large +* the array mask register is. Eg. on a system with 48 harts only bit 0 +* of this field may actually be writable. + */ +#define DMI_HAWINDOWSEL_HAWINDOWSEL_OFFSET 0 +#define DMI_HAWINDOWSEL_HAWINDOWSEL_LENGTH 15 +#define DMI_HAWINDOWSEL_HAWINDOWSEL (0x7fffU << DMI_HAWINDOWSEL_HAWINDOWSEL_OFFSET) +#define DMI_HAWINDOW 0x15 +#define DMI_HAWINDOW_MASKDATA_OFFSET 0 +#define DMI_HAWINDOW_MASKDATA_LENGTH 32 +#define DMI_HAWINDOW_MASKDATA (0xffffffffU << DMI_HAWINDOW_MASKDATA_OFFSET) +#define DMI_ABSTRACTCS 0x16 +/* +* Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16. + */ +#define DMI_ABSTRACTCS_PROGBUFSIZE_OFFSET 24 +#define DMI_ABSTRACTCS_PROGBUFSIZE_LENGTH 5 +#define DMI_ABSTRACTCS_PROGBUFSIZE (0x1fU << DMI_ABSTRACTCS_PROGBUFSIZE_OFFSET) +/* +* 1: An abstract command is currently being executed. +* +* This bit is set as soon as \Rcommand is written, and is +* not cleared until that command has completed. + */ +#define DMI_ABSTRACTCS_BUSY_OFFSET 12 +#define DMI_ABSTRACTCS_BUSY_LENGTH 1 +#define DMI_ABSTRACTCS_BUSY (0x1U << DMI_ABSTRACTCS_BUSY_OFFSET) +/* +* Gets set if an abstract command fails. The bits in this field remain set until +* they are cleared by writing 1 to them. No abstract command is +* started until the value is reset to 0. +* +* 0 (none): No error. +* +* 1 (busy): An abstract command was executing while \Rcommand, +* \Rabstractcs, \Rabstractauto was written, or when one +* of the {\tt data} or {\tt progbuf} registers was read or written. +* +* 2 (not supported): The requested command is not supported, +* regardless of whether the hart is running or not. +* +* 3 (exception): An exception occurred while executing the command +* (eg. while executing the Program Buffer). +* +* 4 (halt/resume): The abstract command couldn't execute because the +* hart wasn't in the required state (running/halted). +* +* 7 (other): The command failed for another reason. + */ +#define DMI_ABSTRACTCS_CMDERR_OFFSET 8 +#define DMI_ABSTRACTCS_CMDERR_LENGTH 3 +#define DMI_ABSTRACTCS_CMDERR (0x7U << DMI_ABSTRACTCS_CMDERR_OFFSET) +/* +* Number of {\tt data} registers that are implemented as part of the +* abstract command interface. Valid sizes are 0 - 12. + */ +#define DMI_ABSTRACTCS_DATACOUNT_OFFSET 0 +#define DMI_ABSTRACTCS_DATACOUNT_LENGTH 4 +#define DMI_ABSTRACTCS_DATACOUNT (0xfU << DMI_ABSTRACTCS_DATACOUNT_OFFSET) +#define DMI_COMMAND 0x17 +/* +* The type determines the overall functionality of this +* abstract command. + */ +#define DMI_COMMAND_CMDTYPE_OFFSET 24 +#define DMI_COMMAND_CMDTYPE_LENGTH 8 +#define DMI_COMMAND_CMDTYPE (0xffU << DMI_COMMAND_CMDTYPE_OFFSET) +/* +* This field is interpreted in a command-specific manner, +* described for each abstract command. + */ +#define DMI_COMMAND_CONTROL_OFFSET 0 +#define DMI_COMMAND_CONTROL_LENGTH 24 +#define DMI_COMMAND_CONTROL (0xffffffU << DMI_COMMAND_CONTROL_OFFSET) +#define DMI_ABSTRACTAUTO 0x18 +/* +* When a bit in this field is 1, read or write accesses to the corresponding {\tt progbuf} word +* cause the command in \Rcommand to be executed again. + */ +#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET 16 +#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_LENGTH 16 +#define DMI_ABSTRACTAUTO_AUTOEXECPROGBUF (0xffffU << DMI_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET) +/* +* When a bit in this field is 1, read or write accesses to the corresponding {\tt data} word +* cause the command in \Rcommand to be executed again. + */ +#define DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET 0 +#define DMI_ABSTRACTAUTO_AUTOEXECDATA_LENGTH 12 +#define DMI_ABSTRACTAUTO_AUTOEXECDATA (0xfffU << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET) +#define DMI_DEVTREEADDR0 0x19 +#define DMI_DEVTREEADDR0_ADDR_OFFSET 0 +#define DMI_DEVTREEADDR0_ADDR_LENGTH 32 +#define DMI_DEVTREEADDR0_ADDR (0xffffffffU << DMI_DEVTREEADDR0_ADDR_OFFSET) +#define DMI_DEVTREEADDR1 0x1a +#define DMI_DEVTREEADDR2 0x1b +#define DMI_DEVTREEADDR3 0x1c +#define DMI_NEXTDM 0x1d +#define DMI_NEXTDM_ADDR_OFFSET 0 +#define DMI_NEXTDM_ADDR_LENGTH 32 +#define DMI_NEXTDM_ADDR (0xffffffffU << DMI_NEXTDM_ADDR_OFFSET) +#define DMI_DATA0 0x04 +#define DMI_DATA0_DATA_OFFSET 0 +#define DMI_DATA0_DATA_LENGTH 32 +#define DMI_DATA0_DATA (0xffffffffU << DMI_DATA0_DATA_OFFSET) +#define DMI_DATA11 0x0f +#define DMI_PROGBUF0 0x20 +#define DMI_PROGBUF0_DATA_OFFSET 0 +#define DMI_PROGBUF0_DATA_LENGTH 32 +#define DMI_PROGBUF0_DATA (0xffffffffU << DMI_PROGBUF0_DATA_OFFSET) +#define DMI_PROGBUF15 0x2f +#define DMI_AUTHDATA 0x30 +#define DMI_AUTHDATA_DATA_OFFSET 0 +#define DMI_AUTHDATA_DATA_LENGTH 32 +#define DMI_AUTHDATA_DATA (0xffffffffU << DMI_AUTHDATA_DATA_OFFSET) +#define DMI_HALTSUM0 0x40 +#define DMI_HALTSUM0_HALTSUM0_OFFSET 0 +#define DMI_HALTSUM0_HALTSUM0_LENGTH 32 +#define DMI_HALTSUM0_HALTSUM0 (0xffffffffU << DMI_HALTSUM0_HALTSUM0_OFFSET) +#define DMI_HALTSUM1 0x13 +#define DMI_HALTSUM1_HALTSUM1_OFFSET 0 +#define DMI_HALTSUM1_HALTSUM1_LENGTH 32 +#define DMI_HALTSUM1_HALTSUM1 (0xffffffffU << DMI_HALTSUM1_HALTSUM1_OFFSET) +#define DMI_HALTSUM2 0x34 +#define DMI_HALTSUM2_HALTSUM2_OFFSET 0 +#define DMI_HALTSUM2_HALTSUM2_LENGTH 32 +#define DMI_HALTSUM2_HALTSUM2 (0xffffffffU << DMI_HALTSUM2_HALTSUM2_OFFSET) +#define DMI_HALTSUM3 0x35 +#define DMI_HALTSUM3_HALTSUM3_OFFSET 0 +#define DMI_HALTSUM3_HALTSUM3_LENGTH 32 +#define DMI_HALTSUM3_HALTSUM3 (0xffffffffU << DMI_HALTSUM3_HALTSUM3_OFFSET) +#define DMI_SBADDRESS3 0x37 +/* +* Accesses bits 127:96 of the physical address in {\tt sbaddress} (if +* the system address bus is that wide). + */ +#define DMI_SBADDRESS3_ADDRESS_OFFSET 0 +#define DMI_SBADDRESS3_ADDRESS... [truncated message content] |