From: OpenOCD-Gerrit <ope...@us...> - 2020-10-14 04:44:10
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via b68674a1da7249c52b00b511fe0ceb20ace5ae4d (commit) from fc7edd57ac6678d1113bc09265798de3fdc68347 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b68674a1da7249c52b00b511fe0ceb20ace5ae4d Author: Tim Newsome <ti...@si...> Date: Wed Aug 19 13:24:56 2020 -0700 Upstream tons of RISC-V changes. These are all the changes from https://github.com/riscv/riscv-openocd (approximately 91dc0c0c) made just to src/target/riscv/*. Some of the new code is disabled because it requires some other target-independent changes which I didn't want to include here. Built like this, OpenOCD passes: * All single-RV32 tests against spike. * All single-RV64 tests against spike. * Enough HiFive1 tests. (I suspect the failures are due to the test suite rotting.) * Many dual-RV32 (-rtos hwthread) against spike. * Many dual-RV64 (-rtos hwthread) against spike. I suspect this is an overall improvement compared to what's in mainline right now, and it gets me a lot closer to getting all the riscv-openocd work upstreamed. Change-Id: Ide2f80c9397400780ff6780d78a206bc6a6e2f98 Signed-off-by: Tim Newsome <ti...@si...> Reviewed-on: http://openocd.zylin.com/5821 Tested-by: jenkins Reviewed-by: Jan Matyas <ma...@co...> Reviewed-by: Antonio Borneo <bor...@gm...> Reviewed-by: Karl Palsson <ka...@tw...> diff --git a/doc/openocd.texi b/doc/openocd.texi index 90b49ee35..dba2a0afa 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9714,8 +9714,31 @@ This is used to access 64-bit floating point registers on 32-bit targets. @end deffn @deffn Command {riscv set_prefer_sba} on|off -When on, prefer to use System Bus Access to access memory. When off, prefer to -use the Program Buffer to access memory. +When on, prefer to use System Bus Access to access memory. When off (default), +prefer to use the Program Buffer to access memory. +@end deffn + +@deffn Command {riscv set_enable_virtual} on|off +When on, memory accesses are performed on physical or virtual memory depending +on the current system configuration. When off (default), all memory accessses are performed +on physical memory. +@end deffn + +@deffn Command {riscv set_enable_virt2phys} on|off +When on (default), memory accesses are performed on physical or virtual memory +depending on the current satp configuration. When off, all memory accessses are +performed on physical memory. +@end deffn + +@deffn Command {riscv resume_order} normal|reversed +Some software assumes all harts are executing nearly continuously. Such +software may be sensitive to the order that harts are resumed in. On harts +that don't support hasel, this option allows the user to choose the order the +harts are resumed in. If you are using this option, it's probably masking a +race condition problem in your code. + +Normal order is from lowest hart index to highest. This is the default +behavior. Reversed order is from highest hart index to lowest. @end deffn @deffn Command {riscv set_ir} (@option{idcode}|@option{dtmcs}|@option{dmi}) [value] @@ -9729,6 +9752,26 @@ When utilizing version 0.11 of the RISC-V Debug Specification, and DBUS registers, respectively. @end deffn +@deffn Command {riscv use_bscan_tunnel} value +Enable or disable use of a BSCAN tunnel to reach DM. Supply the width of +the DM transport TAP's instruction register to enable. Supply a value of 0 to disable. +@end deffn + +@deffn Command {riscv set_ebreakm} on|off +Control dcsr.ebreakm. When on (default), M-mode ebreak instructions trap to +OpenOCD. When off, they generate a breakpoint exception handled internally. +@end deffn + +@deffn Command {riscv set_ebreaks} on|off +Control dcsr.ebreaks. When on (default), S-mode ebreak instructions trap to +OpenOCD. When off, they generate a breakpoint exception handled internally. +@end deffn + +@deffn Command {riscv set_ebreaku} on|off +Control dcsr.ebreaku. When on (default), U-mode ebreak instructions trap to +OpenOCD. When off, they generate a breakpoint exception handled internally. +@end deffn + @subsection RISC-V Authentication Commands The following commands can be used to authenticate to a RISC-V system. Eg. a @@ -9752,7 +9795,7 @@ Write the 32-bit value to authdata. The following commands allow direct access to the Debug Module Interface, which can be used to interact with custom debug features. -@deffn Command {riscv dmi_read} +@deffn Command {riscv dmi_read} address Perform a 32-bit DMI read at address, returning the value. @end deffn diff --git a/src/helper/log.h b/src/helper/log.h index 0c6623f01..f2ba0daa6 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -154,6 +154,7 @@ extern int debug_level; #define ERROR_WAIT (-5) /* ERROR_TIMEOUT is already taken by winerror.h. */ #define ERROR_TIMEOUT_REACHED (-6) +#define ERROR_NOT_IMPLEMENTED (-7) #endif /* OPENOCD_HELPER_LOG_H */ diff --git a/src/target/riscv/asm.h b/src/target/riscv/asm.h index d81aa0285..6ceb8c9bd 100644 --- a/src/target/riscv/asm.h +++ b/src/target/riscv/asm.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + #ifndef TARGET__RISCV__ASM_H #define TARGET__RISCV__ASM_H diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c index d041ed119..43f2ffb8c 100644 --- a/src/target/riscv/batch.c +++ b/src/target/riscv/batch.c @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -9,21 +11,53 @@ #define get_field(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 1))) #define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask))) +#define DTM_DMI_MAX_ADDRESS_LENGTH ((1<<DTM_DTMCS_ABITS_LENGTH)-1) +#define DMI_SCAN_MAX_BIT_LENGTH (DTM_DMI_MAX_ADDRESS_LENGTH + DTM_DMI_DATA_LENGTH + DTM_DMI_OP_LENGTH) +#define DMI_SCAN_BUF_SIZE (DIV_ROUND_UP(DMI_SCAN_MAX_BIT_LENGTH, 8)) + static void dump_field(int idle, 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 = calloc(1, sizeof(*out)); + if (!out) + goto error0; out->target = target; out->allocated_scans = scans; 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->data_out = malloc(sizeof(*out->data_out) * (scans) * DMI_SCAN_BUF_SIZE); + if (!out->data_out) + goto error1; + out->data_in = malloc(sizeof(*out->data_in) * (scans) * DMI_SCAN_BUF_SIZE); + if (!out->data_in) + goto error2; out->fields = malloc(sizeof(*out->fields) * (scans)); + if (!out->fields) + goto error3; + if (bscan_tunnel_ir_width != 0) { + out->bscan_ctxt = malloc(sizeof(*out->bscan_ctxt) * (scans)); + if (!out->bscan_ctxt) + goto error4; + } out->last_scan = RISCV_SCAN_TYPE_INVALID; out->read_keys = malloc(sizeof(*out->read_keys) * (scans)); + if (!out->read_keys) + goto error5; return out; + +error5: + free(out->bscan_ctxt); +error4: + free(out->fields); +error3: + free(out->data_in); +error2: + free(out->data_out); +error1: + free(out); +error0: + return NULL; } void riscv_batch_free(struct riscv_batch *batch) @@ -31,6 +65,8 @@ void riscv_batch_free(struct riscv_batch *batch) free(batch->data_in); free(batch->data_out); free(batch->fields); + free(batch->bscan_ctxt); + free(batch->read_keys); free(batch); } @@ -51,7 +87,11 @@ int riscv_batch_run(struct riscv_batch *batch) 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 (bscan_tunnel_ir_width != 0) + riscv_add_bscan_tunneled_scan(batch->target, batch->fields+i, batch->bscan_ctxt+i); + else + 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); } @@ -61,6 +101,12 @@ int riscv_batch_run(struct riscv_batch *batch) return ERROR_FAIL; } + if (bscan_tunnel_ir_width != 0) { + /* need to right-shift "in" by one bit, because of clock skew between BSCAN TAP and DM TAP */ + for (size_t i = 0; i < batch->used_scans; ++i) + buffer_shr((batch->fields + i)->in_value, DMI_SCAN_BUF_SIZE, 1); + } + for (size_t i = 0; i < batch->used_scans; ++i) dump_field(batch->idle_count, batch->fields + i); @@ -72,8 +118,8 @@ void riscv_batch_add_dmi_write(struct riscv_batch *batch, unsigned address, uint 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)); + field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE); + field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE); 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; @@ -85,35 +131,35 @@ 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)); + field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE); + field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE); 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 coalesced away. */ - riscv_batch_add_nop(batch); - - batch->read_keys[batch->read_keys_used] = batch->used_scans - 1; + batch->read_keys[batch->read_keys_used] = batch->used_scans; return batch->read_keys_used++; } -uint64_t riscv_batch_get_dmi_read(struct riscv_batch *batch, size_t key) +unsigned riscv_batch_get_dmi_read_op(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; + uint8_t *base = batch->data_in + DMI_SCAN_BUF_SIZE * index; + /* extract "op" field from the DMI read result */ + return (unsigned)buf_get_u32(base, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH); +} + +uint32_t riscv_batch_get_dmi_read_data(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 + DMI_SCAN_BUF_SIZE * index; + /* extract "data" field from the DMI read result */ + return buf_get_u32(base, DTM_DMI_DATA_OFFSET, DTM_DMI_DATA_LENGTH); } void riscv_batch_add_nop(struct riscv_batch *batch) @@ -121,8 +167,8 @@ 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)); + field->out_value = (void *)(batch->data_out + batch->used_scans * DMI_SCAN_BUF_SIZE); + field->in_value = (void *)(batch->data_in + batch->used_scans * DMI_SCAN_BUF_SIZE); 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; @@ -151,13 +197,17 @@ void dump_field(int idle, const struct scan_field *field) log_printf_lf(LOG_LVL_DEBUG, __FILE__, __LINE__, __PRETTY_FUNCTION__, - "%db %di %s %08x @%02x -> %s %08x @%02x", - field->num_bits, idle, - op_string[out_op], out_data, out_address, - status_string[in_op], in_data, in_address); + "%db %s %08x @%02x -> %s %08x @%02x; %di", + field->num_bits, op_string[out_op], out_data, out_address, + status_string[in_op], in_data, in_address, idle); } else { log_printf_lf(LOG_LVL_DEBUG, - __FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %di %s %08x @%02x -> ?", - field->num_bits, idle, op_string[out_op], out_data, out_address); + __FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %s %08x @%02x -> ?; %di", + field->num_bits, op_string[out_op], out_data, out_address, idle); } } + +size_t riscv_batch_available_scans(struct riscv_batch *batch) +{ + return batch->allocated_scans - batch->used_scans - 4; +} diff --git a/src/target/riscv/batch.h b/src/target/riscv/batch.h index 70690a601..9c42ba81e 100644 --- a/src/target/riscv/batch.h +++ b/src/target/riscv/batch.h @@ -1,8 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + #ifndef TARGET__RISCV__SCANS_H #define TARGET__RISCV__SCANS_H #include "target/target.h" #include "jtag/jtag.h" +#include "riscv.h" enum riscv_scan_type { RISCV_SCAN_TYPE_INVALID, @@ -27,6 +30,11 @@ struct riscv_batch { uint8_t *data_in; struct scan_field *fields; + /* If in BSCAN mode, this field will be allocated (one per scan), + and utilized to tunnel all the scans in the batch. If not in + BSCAN mode, this field is unallocated and stays NULL */ + riscv_bscan_tunneled_scan_context_t *bscan_ctxt; + /* 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. @@ -54,11 +62,16 @@ int riscv_batch_run(struct riscv_batch *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 .*/ + * provides a key, the second one actually obtains the result of the read - + * status (op) and the actual data. */ 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); +unsigned riscv_batch_get_dmi_read_op(struct riscv_batch *batch, size_t key); +uint32_t riscv_batch_get_dmi_read_data(struct riscv_batch *batch, size_t key); /* Scans in a NOP. */ void riscv_batch_add_nop(struct riscv_batch *batch); +/* Returns the number of available scans. */ +size_t riscv_batch_available_scans(struct riscv_batch *batch); + #endif diff --git a/src/target/riscv/debug_defines.h b/src/target/riscv/debug_defines.h index d6ddd4ff1..cb518a891 100644 --- a/src/target/riscv/debug_defines.h +++ b/src/target/riscv/debug_defines.h @@ -1,22 +1,27 @@ +/* + * This file is auto-generated by running 'make debug_defines.h' in + * https://github.com/riscv/riscv-debug-spec/ (30b1a97) + */ + #define DTM_IDCODE 0x01 /* -* Identifies the release version of this part. + * 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. + * 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. + * 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 @@ -26,1389 +31,1892 @@ #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). + * Writing 1 to this bit does a hard reset of the DTM, + * causing the DTM to forget about any outstanding DMI transactions, and + * returning all registers and internal state to their reset value. + * 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. + * Writing 1 to this bit clears the sticky error state, but does + * not affect outstanding DMI transactions. */ #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. + * 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 (\FdtmDtmcsDmistat of 3). A debugger must still + * check \FdtmDtmcsDmistat 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). + * 0: No error. + * + * 1: Reserved. Interpret the same as 2. + * + * 2: An operation failed (resulted in \FdtmDmiOp of 2). + * + * 3: An operation was attempted while a DMI access was still in + * progress (resulted in \FdtmDmiOp 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. + * The size of \FdmSbaddressZeroAddress in \RdtmDmi. */ #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. + * 0: Version described in spec version 0.11. + * + * 1: Version described in spec version 0.13. + * + * 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. + * 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) +#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. + * 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.) + * When the debugger writes this field, it has the following meaning: + * + * 0: Ignore \FdmSbdataZeroData and \FdmSbaddressZeroAddress. (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 \FdmSbaddressZeroAddress. (read) + * + * 2: Write \FdmSbdataZeroData to \FdmSbaddressZeroAddress. (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 \RdtmDmi in + * this access will be ignored. This status is sticky and can be + * cleared by writing \FdtmDtmcsDmireset in \RdtmDtmcs. + * + * This indicates that the DM itself responded with an error. + * 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 \RdtmDmi in this access will be + * ignored. This status is sticky and can be cleared by writing + * \FdtmDtmcsDmireset in \RdtmDtmcs. 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. */ #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. + * 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. + * 0: {\tt ebreak} instructions in M-mode behave as described in the + * Privileged Spec. + * + * 1: {\tt ebreak} instructions in M-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. + * 0: {\tt ebreak} instructions in S-mode behave as described in the + * Privileged Spec. + * + * 1: {\tt ebreak} instructions in S-mode enter Debug Mode. + * + * This bit is hardwired to 0 if the hart does not support S 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. + * 0: {\tt ebreak} instructions in U-mode behave as described in the + * Privileged Spec. + * + * 1: {\tt ebreak} instructions in U-mode enter Debug Mode. + * + * This bit is hardwired to 0 if the hart does not support U 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. + * 0: Interrupts (including NMI) are disabled during single stepping. + * + * 1: Interrupts (including NMI) are enabled during single stepping. + * + * Implementations may hard wire this bit to 0. + * In that case interrupt behavior can be emulated by the debugger. + * + * The debugger must not change the value of this bit while the hart + * is running. */ #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. + * 0: Increment counters as usual. + * + * 1: Don't increment any hart-local counters while in Debug Mode or + * on {\tt ebreak} instructions that cause entry into Debug Mode. + * These counters include the {\tt instret} CSR. On single-hart cores + * {\tt cycle} should be stopped, but on multi-hart cores it must keep + * incrementing. + * + * An implementation may hardwire this bit to 0 or 1. */ #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. + * 0: Increment timers as usual. + * + * 1: Don't increment any hart-local timers while in Debug Mode. + * + * An implementation may hardwire this bit to 0 or 1. */ #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. + * Explains why Debug Mode was entered. + * + * When there are multiple reasons to enter Debug Mode in a single + * cycle, hardware should set \FcsrDcsrCause 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 using \FdmDmcontrolHaltreq. + * (priority 1) + * + * 4: The hart single stepped because \FcsrDcsrStep was set. (priority 0, lowest) + * + * 5: The hart halted directly out of reset due to \Fresethaltreq. It + * is also acceptable to report 3 when this happens. (priority 2) + * + * 6: The hart halted because it's part of a halt group. (priority 5, + * highest) Harts may report 3 for this cause instead. + * + * 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. + * 0: \FcsrMcontrolMprv in \Rmstatus is ignored in Debug Mode. + * + * 1: \FcsrMcontrolMprv in \Rmstatus takes effect in Debug Mode. + * + * Implementing this bit is optional. It may be tied to either 0 or 1. */ #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. + * 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. + * When set and not in Debug Mode, the hart will only execute a single + * instruction and then enter Debug Mode. See Section~\ref{stepBit} + * for details. + * + * The debugger must not change the value of this bit while the hart + * is running. */ #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. + * 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_DPC_DPC_LENGTH DXLEN +#define CSR_DPC_DPC (((1L << DXLEN) - 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_TSELECT_INDEX_LENGTH XLEN +#define CSR_TSELECT_INDEX (((1L << XLEN) - 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) + * 0: There is no trigger at this \RcsrTselect. + * + * 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 \RcsrMcontrol. + * + * 3: The trigger is an instruction count trigger. The remaining bits + * in this register act as described in \RcsrIcount. + * + * 4: The trigger is an interrupt trigger. The remaining bits + * in this register act as described in \RcsrItrigger. + * + * 5: The trigger is an exception trigger. The remaining bits + * in this register act as described in \RcsrEtrigger. + * + * 12--14: These trigger types are available for non-standard use. + * + * 15: This trigger exists (so enumeration shouldn't terminate), but + * is not currently available. + * + * Other values are reserved for future use. + */ +#define CSR_TDATA1_TYPE_OFFSET (XLEN-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) + * If \FcsrTdataOneType is 0, then this bit is hard-wired to 0. + * + * 0: Both Debug and M-mode can write the {\tt tdata} registers at the + * selected \RcsrTselect. + * + * 1: Only Debug Mode can write the {\tt tdata} registers at the + * selected \RcsrTselect. Writes from other modes are ignored. + * + * This bit is only writable from Debug Mode. + * When clearing this bit, the debugger should also clear the action field + * (whose location depends on \FcsrTdataOneType). + */ +#define CSR_TDATA1_DMODE_OFFSET (XLEN-5) #define CSR_TDATA1_DMODE_LENGTH 1 #define CSR_TDATA1_DMODE (0x1ULL << CSR_TDATA1_DMODE_OFFSET) /* -* Trigger-specific data. + * If \FcsrTdataOneType is 0, then this field is hard-wired to 0. + * + * 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_TDATA1_DATA_LENGTH (XLEN - 5) +#define CSR_TDATA1_DATA (((1L << XLEN - 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_TDATA2_DATA_LENGTH XLEN +#define CSR_TDATA2_DATA (((1L << XLEN) - 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_TDATA3_DATA_LENGTH XLEN +#define CSR_TDATA3_DATA (((1L << XLEN) - 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. + * One bit for each possible \FcsrTdataOneType enumerated in \RcsrTdataOne. 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. */ #define CSR_TINFO_INFO_OFFSET 0 #define CSR_TINFO_INFO_LENGTH 16 #define CSR_TINFO_INFO (0xffffULL << CSR_TINFO_INFO_OFFSET) +#define CSR_TCONTROL 0x7a5 +/* + * M-mode previous trigger enable field. + * + * When a trap into M-mode is taken, \FcsrTcontrolMpte is set to the value of + * \FcsrTcontrolMte. + */ +#define CSR_TCONTROL_MPTE_OFFSET 7 +#define CSR_TCONTROL_MPTE_LENGTH 1 +#define CSR_TCONTROL_MPTE (0x1ULL << CSR_TCONTROL_MPTE_OFFSET) +/* + * M-mode trigger enable field. + * + * 0: Triggers with action=0 do not match/fire while the hart is in M-mode. + * + * 1: Triggers do match/fire while the hart is in M-mode. + * + * When a trap into M-mode is taken, \FcsrTcontrolMte is set to 0. When {\tt + * mret} is executed, \FcsrTcontrolMte is set to the value of \FcsrTcontrolMpte. + */ +#define CSR_TCONTROL_MTE_OFFSET 3 +#define CSR_TCONTROL_MTE_LENGTH 1 +#define CSR_TCONTROL_MTE (0x1ULL << CSR_TCONTROL_MTE_OFFSET) +#define CSR_MCONTEXT 0x7a8 +/* + * Machine mode software can write a context number to this register, + * which can be used to set triggers that only fire in that specific + * context. + * + * An implementation may tie any number of upper bits in this field to + * 0. It's recommended to implement no more than 6 bits on RV32, and + * 13 on RV64. + */ +#define CSR_MCONTEXT_MCONTEXT_OFFSET 0 +#define CSR_MCONTEXT_MCONTEXT_LENGTH XLEN +#define CSR_MCONTEXT_MCONTEXT (((1L << XLEN) - 1) << CSR_MCONTEXT_MCONTEXT_OFFSET) +#define CSR_SCONTEXT 0x7aa +/* + * Supervisor mode software can write a context number to this + * register, which can be used to set triggers that only fire in that + * specific context. + * + * An implementation may tie any number of high bits in this field to + * 0. It's recommended to implement no more than 16 bits on RV32, and + * 34 on RV64. + */ +#define CSR_SCONTEXT_DATA_OFFSET 0 +#define CSR_SCONTEXT_DATA_LENGTH XLEN +#define CSR_SCONTEXT_DATA (((1L << XLEN) - 1) << CSR_SCONTEXT_DATA_OFFSET) #define CSR_MCONTROL 0x7a1 -#define CSR_MCONTROL_TYPE_OFFSET (MXLEN-4) +#define CSR_MCONTROL_TYPE_OFFSET (XLEN-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_OFFSET (XLEN-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. + * Specifies the largest naturally aligned powers-of-two (NAPOT) range + * supported by the hardware when \FcsrMcontrolMatch 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_OFFSET (XLEN-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. + * This field only exists when XLEN is at least 64. + * It contains the 2 high bits of the access size. The low bits + * come from \FcsrMcontrolSizelo. See \FcsrMcontrolSizelo for how this + * is used. + */ +#define CSR_MCONTROL_SIZEHI_OFFSET 21 +#define CSR_MCONTROL_SIZEHI_LENGTH 2 +#define CSR_MCONTROL_SIZEHI (0x3ULL << CSR_MCONTROL_SIZEHI_OFFSET) +/* + * If this bit is implemented, the hardware sets it when this + * trigger matches. The trigger's user can set or clear it at any + * time. It is used 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. + * 0: Perform a match on the lowest virtual address of the access. In + * addition, it is recommended that the trigger also fires if any of + * the other accessed virtual addresses match. + * (E.g. on a 32-bit read from 0x4000, the lowest address is 0x4000 + * and the other addresses are 0x4001, 0x4002, and 0x4003.) + * + * 1: Perform a match on the data value loaded or 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). + * 0: The action for this trigger will be taken just before the + * instruction that triggered it is executed, but after all preceding + * instructions are committed. \Rmepc or \RcsrDpc (depending on + * \FcsrMcontrolAction) must be set to the virtual address of the + * instruction that matched. + * + * If this is combined with \FcsrMcontrolLoad then a memory access will be + * performed (including any side effects of performing such an access) even + * though the load will not update its destination register. Debuggers + * should consider this when setting such breakpoints on, for example, + * memory-mapped I/O addresses. + * + * 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 imprecisely + * than to not implement them at all. + * \Rmepc or \RcsrDpc (depending on \FcsrMcontrolAction) must be set to + * the virtual address of the next instruction that must be executed to + * preserve the program flow. + * + * Most hardware will only implement one timing or the other, possibly + * dependent on \FcsrMcontrolSelect, \FcsrMcontrolExecute, + * \FcsrMcontrolLoad, and \FcsrMcontrolStore. 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 \FcsrMcontrolTiming 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 + * \FcsrMcontrolTiming of 1. + * + * If a trigger with \FcsrMcontrolTiming of 0 matches, it is + * implementation-dependent whether that prevents a trigger with + * \FcsrMcontrolTiming of 1 matching as well. */ #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}. + * This field contains the 2 low bits of the access size. The high bits come + * from \FcsrMcontrolSizehi. The combined value is interpreted as follows: + * + * 0: The trigger will attempt to match against an access of any size. + * The behavior is only well-defined if $|select|=0$, or if the access + * size is XLEN. + * + * 1: The trigger will only match against 8-bit memory accesses. + * + * 2: The trigger will only match against 16-bit memory accesses or + * execution of 16-bit instructions. + * + * 3: The trigger will only match against 32-bit memory accesses or + * execution of 32-bit instructions. + * + * 4: The trigger will only match against execution of 48-bit instructions. + * + * 5: The trigger will only match against 64-bit memory accesses or + * execution of 64-bit instructions. + * + * 6: The trigger will only match against execution of 80-bit instructions. + * + * 7: The trigger will only match against execution of 96-bit instructions. + * + * 8: The trigger will only match against execution of 112-bit instructions. + * + * 9: The trigger will only match against 128-bit memory accesses or + * execution of 128-bit instructions. + * + * An implementation must support the value of 0, but all other values + * are optional. It is recommended to support triggers for every + * access size the hart supports, as well as for every instruction + * size the hart supports. + */ +#define CSR_MCONTROL_SIZELO_OFFSET 16 +#define CSR_MCONTROL_SIZELO_LENGTH 2 +#define CSR_MCONTROL_SIZELO (0x3ULL << CSR_MCONTROL_SIZELO_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_ACTION_LENGTH 4 +#define CSR_MCONTROL_ACTION (0xfULL << 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. + * + * A trigger chain starts on the first trigger with $|chain|=1$ after + * a trigger with $|chain|=0$, or simply on the first trigger if that + * has $|chain|=1$. It ends on the first trigger after that which has + * $|chain|=0$. This final trigger is part of the chain. The action + * on all but the final trigger is ignored. The action on that final + * trigger will be taken if and only if all the triggers in the chain + * match at the same time. + * + * Because \FcsrMcontrolChain affects the next trigger, hardware must zero it in + * writes to \RcsrMcontrol that set \FcsrTdataOneDmode to 0 if the next trigger has + * \FcsrTdataOneDmode of 1. + * In addition hardware should ignore writes to \RcsrMcontrol that set + * \FcsrTdataOneDmode to 1 if the previous trigger has both \FcsrTdataOneDmode of 0 and + * \FcsrMcontrolChain of 1. Debuggers must avoid the latter case by checking + * \FcsrMcontrolChain on the previous trigger if they're writing \RcsrMcontrol. + * + * Implementations that wish to limit the maximum length of a trigger + * chain (eg. to meet timing requirements) may do so by zeroing + * \FcsrMcontrolChain in writes to \RcsrMcontrol 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. + * 0: Matches when the value equals \RcsrTdataTwo. + * + * 1: Matches when the top M bits of the value match the top M bits of + * \RcsrTdataTwo. M is XLEN-1 minus the index of the least-significant + * bit containing 0 in \RcsrTdataTwo. Debuggers should only write values + * to \RcsrTdataTwo such that M + \FcsrMcontrolMaskmax $\geq$ XLEN, otherwise it's + * undefined on what conditions the trigger will fire. + * + * 2: Matches when the value is greater than (unsigned) or equal to + * \RcsrTdataTwo. + * + * 3: Matches when the value is less than (unsigned) \RcsrTdataTwo. + * + * 4: Matches when the lower half of the value equals the lower half + * of \RcsrTdataTwo after the lower half of the value is ANDed with the + * upper half of \RcsrTdataTwo. + * + * 5: Matches when the upper half of the value equals the lower half + * of \RcsrTdataTwo after the upper half of the value is ANDed with the + * upper half of \RcsrTdataTwo. + * + * 8: Matches when \FcsrMcontrolMatch$=0$ would not match. + * + * 9: Matches when \FcsrMcontrolMatch$=1$ would not match. + * + * 12: Matches when \FcsrMcontrolMatch$=4$ would not match. + * + * 13: Matches when \FcsrMcontrolMatch$=5$ would not match. + * + * 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. + * 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. + * 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. + * 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. + * 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. + * When set, the trigger fires on the virtual address or data of any + * 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. + * When set, the trigger fires on the virtual address or data of any + * 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_OFFSET (XLEN-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_OFFSET (XLEN-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. + * If this bit is implemented, the hardware sets it when this + * trigger matches. The trigger's user can set or clear it at any + * time. It is used 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. + * When count is decremented to 0, the trigger fires. Instead of + * changing \FcsrIcountCount from 1 to 0, it is also acceptable for hardware to + * clear \FcsrMcontrolM, \FcsrMcontrolS, and \FcsrMcontrolU. This allows \FcsrIcountCount to be hard-wired + * to 1 if this register just exists for single step. */ #define CSR_ICOUNT_COUNT_OFFSET ... [truncated message content] |