diff --git a/spec/schemas/csr_schema.json b/spec/schemas/csr_schema.json index ee55b58b01..5309b415de 100644 --- a/spec/schemas/csr_schema.json +++ b/spec/schemas/csr_schema.json @@ -248,7 +248,7 @@ "virtual_address": true, "$comment": "Conditionally required; see below", "priv_mode": { - "enum": ["M", "S", "U", "VS"] + "enum": ["M", "S", "U", "VS", "D"] }, "length": { "description": "Length, in bits, of the CSR. Can either be a 32, 64 or MXLEN, SXLEN, VSXLEN to indicate that it is dependent on the effective XLEN for a given mode. XLEN here refers to the effective XLEN in the current execution mode.", diff --git a/spec/std/isa/csr/dcsr.yaml b/spec/std/isa/csr/dcsr.yaml new file mode 100644 index 0000000000..9c38bf7fa8 --- /dev/null +++ b/spec/std/isa/csr/dcsr.yaml @@ -0,0 +1,276 @@ +# Copyright (c) Katherine Hsu +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../schemas/csr_schema.json + +$schema: "csr_schema.json#" +kind: csr +name: dcsr +long_name: Debug Control and Status Register +address: 0x7B0 +priv_mode: D +length: 32 +description: | + Upon entry into Debug Mode, v and prv are updated with the privilege level the hart was previously in, + and cause is updated with the reason for Debug Mode entry. Other than these fields and nmip, the + other fields of dcsr are only writable by the external debugger. + + Priority of reasons for entering Debug Mode from highest to lowest is shown below. + 5:: resethaltreq + 6:: halt group + 3:: haltreq + 2:: trigger + 1:: ebreak + 4:: step + + For compatibility with old versions of this spec, resethaltreq and + haltreq are allowed to be at different positions than shown as long as: + 1. resethaltreq is higher priority than haltreq + 2. the relative order of the other four causes is maintained + + This CSR is read/write. + +definedBy: Sdext +fields: + DEBUGVER: + location: 31-28 + type: RO + description: | + 0 (none):: There is no debug support. + 4 (1.0):: Debug support exists as it is described in this document. + 15 (custom):: There is debug support, but it does not conform to any available version of this spec. + reset_value: UNDEFINED_LEGAL + EXTCAUSE: + location: 26-24 + type: RO + description: | + When cause is 7, this optional field contains the value of a more specific halt reason than "other." + Otherwise it contains 0. + + 0 (critical error):: The hart entered a critical error state, as defined in the Smdbltrp extension. + + All other values are reserved for future versions of this spec, or for use by other RISC-V extensions. + reset_value: 0 + CETRIG: + location: 19 + type: RW + definedBy: Smdbltrp + description: | + This bit is part of Smdbltrp and only exists when that extension is implemented. + 0 (disabled):: A hart in a critical error state does not enter + Debug Mode but instead asserts the critical-error signal to + the platform. + 1 (enabled):: A hart in a critical error state enters Debug + Mode instead of asserting the critical-error signal to the + platform. Upon such entry into Debug Mode, the cause + field is set to 7, and the extcause field is set to 0, indicating + a critical error triggered the Debug Mode entry. This cause + has the highest priority among all reasons for entering + Debug Mode. Resuming from Debug Mode following an + entry from the critical error state returns the hart to the + critical error state. + + When cetrig is 1, resuming from Debug Mode following an entry due to a critical + error will result in an immediate re-entry into Debug Mode due to the critical error. + The debugger may resume with cetrig set to 0 to allow the platform defined actions on + critical-error signal to occur. Other possible actions include initiating a hart or platform + reset using the Debug Module reset control. + reset_value: 0 + PELP: + location: 18 + type: RW + definedBy: Zicfilp + description: | + This bit is part of Zicfilp and only exists when that extension is implemented. + 0 (NO_LP_EXPECTED):: No landing pad instruction expected. + 1 (LP_EXPECTED):: A landing pad instruction is expected. + reset_value: 0 + EBREAKVS: + location: 17 + type: RW + definedBy: H + description: | + 0 (exception):: ebreak instructions in VS-mode behave as described in the Privileged Spec. + 1 (debug mode):: ebreak instructions in VS-mode enter Debug Mode. + This bit is hardwired to 0 if the hart does not support virtualization mode. + reset_value: 0 + EBREAKVU: + location: 16 + type: RW + definedBy: H + description: | + 0 (exception):: ebreak instructions in VU-mode behave as described in the Privileged Spec. + 1 (debug mode):: ebreak instructions in VU-mode enter Debug Mode. + This bit is hardwired to 0 if the hart does not support virtualization mode. + reset_value: 0 + EBREAKM: + location: 15 + type: RW + description: | + 0 (exception):: ebreak instructions in M-mode behave as described in the Privileged Spec. + 1 (debug mode):: ebreak instructions in M-mode enter Debug Mode. + reset_value: 0 + EBREAKS: + location: 13 + type: RW + definedBy: S + description: | + 0 (exception):: ebreak instructions in S-mode behave as described in the Privileged Spec. + 1 (debug mode):: ebreak instructions in S-mode enter Debug Mode. + This bit is hardwired to 0 if the hart does not support S-mode. + reset_value: 0 + EBREAKU: + location: 12 + type: RW + definedBy: U + description: | + 0 (exception):: ebreak instructions in U-mode behave as described in the Privileged Spec. + 1 (debug mode):: ebreak instructions in U-mode enter Debug Mode. + This bit is hardwired to 0 if the hart does not support U-mode. + reset_value: 0 + STEPIE: + location: 11 + description: | + 0 (interrupts disabled):: Interrupts (including NMI) are disabled during single stepping with step set. + This value should be supported. + 1 (interrupts enabled):: Interrupts (including NMI) are enabled during single stepping with step set. + 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. + type(): | + if (DCSR_STEPIE_TYPE == "read-only-0" || DCSR_STEPIE_TYPE == "read-only-1") { + return CsrFieldType::RO; + } + assert(DCSR_STEPIE_TYPE == "rw", "Unhandled DCSR_STEPIE_TYPE value"); + return CsrFieldType::RW; + reset_value(): | + if (DCSR_STEPIE_TYPE == "read-only-0") { + return 0; + } else if (DCSR_STEPIE_TYPE == "read-only-1") { + return 1; + } + assert(DCSR_STEPIE_TYPE == "rw", "Unhandled DCSR_STEPIE_TYPE value"); + return UNDEFINED_LEGAL; + STOPCOUNT: + location: 10 + description: | + 0 (normal):: Increment counters as usual. + 1 (freeze):: Don’t increment any hart-local counters while in Debug Mode or on ebreak instructions + that cause entry into Debug Mode. These counters include the instret CSR. On single-hart cores cycle + should be stopped, but on multi-hart cores it must keep incrementing. + An implementation may hardwire this bit to 0 or 1. + type(): | + if (DCSR_STOPCOUNT_TYPE == "read-only-0" || DCSR_STOPCOUNT_TYPE == "read-only-1") { + return CsrFieldType::RO; + } + assert(DCSR_STOPCOUNT_TYPE == "rw", "Unhandled DCSR_STOPCOUNT_TYPE value"); + return CsrFieldType::RW; + reset_value(): | + if (DCSR_STOPCOUNT_TYPE == "read-only-0") { + return 0; + } else if (DCSR_STOPCOUNT_TYPE == "read-only-1") { + return 1; + } + assert(DCSR_STOPCOUNT_TYPE == "rw", "Unhandled DCSR_STOPCOUNT_TYPE value"); + return UNDEFINED_LEGAL; + STOPTIME: + location: 9 + description: | + 0 (normal):: time continues to reflect mtime. + 1 (freeze):: time is frozen at the time that Debug Mode was entered. When leaving Debug Mode, + time will reflect the latest value of mtime again. + While all harts have stoptime=1 and are in Debug Mode, mtime is allowed to stop incrementing. + An implementation may hardwire this bit to 0 or 1. + type(): | + if (DCSR_STOPTIME_TYPE == "read-only-0" || DCSR_STOPTIME_TYPE == "read-only-1") { + return CsrFieldType::RO; + } + assert(DCSR_STOPTIME_TYPE == "rw", "Unhandled DCSR_STOPTIME_TYPE value"); + return CsrFieldType::RW; + reset_value(): | + if (DCSR_STOPTIME_TYPE == "read-only-0") { + return 0; + } else if (DCSR_STOPTIME_TYPE == "read-only-1") { + return 1; + } + assert(DCSR_STOPTIME_TYPE == "rw", "Unhandled DCSR_STOPTIME_TYPE value"); + return UNDEFINED_LEGAL; + CAUSE: + location: 8-6 + type: RO + description: | + Explains why Debug Mode was entered. + When there are multiple reasons to enter Debug Mode in a + single cycle, hardware should set cause to the cause with + the highest priority. + 1 (ebreak):: An ebreak instruction was executed. + 2 (trigger):: A Trigger Module trigger fired with action=1. + 3 (haltreq):: The debugger requested entry to Debug Mode + using haltreq. + 4 (step):: The hart single stepped because step was set. + 5 (resethaltreq):: The hart halted directly out of reset due to + resethaltreq It is also acceptable to report 3 when this + happens. + 6 (group):: The hart halted because it’s part of a halt group. + Harts may report 3 for this cause instead. + 7 (other):: The hart halted for a reason other than the ones + mentioned above. extcause may contain a more specific + reason. + reset_value: 0 + V: + location: 5 + type: RW + definedBy: H + description: | + Extends the prv field with the virtualization mode the hart was operating in + when Debug Mode was entered. A debugger can change this value to change the + hart’s virtualization mode when exiting Debug Mode. This bit is hardwired to 0 on harts + that do not support virtualization mode. + reset_value: 0 + MPRVEN: + location: 4 + description: | + 0 (disabled):: mprv in mstatus is ignored in Debug Mode. + 1 (enabled):: mprv in mstatus takes effect in Debug Mode. + Implementing this bit is optional. It may be tied to either 0 or 1. + type(): | + if (DCSR_MPRVEN_TYPE == "read-only-0" || DCSR_MPRVEN_TYPE == "read-only-1") { + return CsrFieldType::RO; + } + assert(DCSR_MPRVEN_TYPE == "rw", "Unhandled DCSR_MPRVEN_TYPE value"); + return CsrFieldType::RW; + reset_value(): | + if (DCSR_MPRVEN_TYPE == "read-only-0") { + return 0; + } else if (DCSR_MPRVEN_TYPE == "read-only-1") { + return 1; + } + assert(DCSR_MPRVEN_TYPE == "rw", "Unhandled DCSR_MPRVEN_TYPE value"); + return UNDEFINED_LEGAL; + NMIP: + location: 3 + type: RO + description: | + 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. + reset_value: 0 + STEP: + location: 2 + type: RW + description: | + When set and not in Debug Mode, the hart will only execute a single instruction + and then enter Debug Mode. + The debugger must not change the value of this bit while the hart is running. + reset_value: 0 + PRV: + location: 1-0 + type: RW + description: | + Contains the privilege mode the hart was operating in when Debug Mode was entered. + A debugger can change this value to change the hart’s privilege mode when exiting + Debug Mode. + + Not all privilege modes 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 mode. + reset_value: 3 diff --git a/spec/std/isa/csr/dpc.yaml b/spec/std/isa/csr/dpc.yaml new file mode 100644 index 0000000000..b740449253 --- /dev/null +++ b/spec/std/isa/csr/dpc.yaml @@ -0,0 +1,42 @@ +# Copyright (c) Katherine Hsu +# SPDX-License-Identifier: BSD-3-Clause-Clear + +# yaml-language-server: $schema=../../schemas/csr_schema.json + +$schema: "csr_schema.json#" +kind: csr +name: dpc +long_name: Debug PC Register +address: 0x7B1 +priv_mode: D +length: MXLEN +description: | + Upon entry to debug mode, dpc is updated with the virtual address of the next instruction to be executed. + + Executing the Program Buffer may cause the value of dpc to become UNSPECIFIED. If that is the case, + it must be possible to read/write dpc using an abstract command with postexec not set. The debugger + must attempt to save dpc between halting and executing a Program Buffer, and then restore dpc before + leaving Debug Mode. + + If the Access Register abstract command supports reading dpc while the hart is running, then the + value read should be the address of a recently executed instruction. + + If the Access Register abstract command supports writing dpc while the hart is running, then the + executing program should jump to the written address shortly after the write occurs. + + The writability of dpc follows the same rules as mepc as defined in the Privileged Spec. In particular, + dpc must be able to hold all valid virtual addresses and the writability of the low bits depends on + IALIGN. + + When resuming, the hart’s PC is updated to the virtual address stored in dpc. A debugger may write + dpc to change where the hart resumes. + + This CSR is read/write. +definedBy: Sdext +fields: + DPC: + location_rv32: 31-0 + location_rv64: 63-0 + type: RW + description: Debug PC Value + reset_value: UNDEFINED_LEGAL diff --git a/spec/std/isa/ext/Sdext.yaml b/spec/std/isa/ext/Sdext.yaml index 0382b73219..874ef723f2 100644 --- a/spec/std/isa/ext/Sdext.yaml +++ b/spec/std/isa/ext/Sdext.yaml @@ -13,4 +13,53 @@ type: privileged versions: - version: "1.0.0" state: ratified - ratification_date: null + ratification_date: 2025-02 +params: + DCSR_MPRVEN_TYPE: + schema: + type: string + enum: [read-only-0, read-only-1, rw] + description: | + Implementation of dcsr.MPRVEN is optional. + It may be tied to either 0 or 1. + + Behavior of the dcsr.MPRVEN bit: + * 'read-only-0': tied to 0 + * 'read-only-1': tied to 1 + * 'rw': read-write + DCSR_STEPIE_TYPE: + schema: + type: string + enum: [read-only-0, read-only-1, rw] + description: | + Implementation of dcsr.STEPIE is optional. + It may be tied to either 0 or 1. + + Behavior of the dcsr.STEPIE bit: + * 'read-only-0': tied to 0 + * 'read-only-1': tied to 1 + * 'rw': read-write + DCSR_STOPCOUNT_TYPE: + schema: + type: string + enum: [read-only-0, read-only-1, rw] + description: | + Implementation of dcsr.STOPCOUNT is optional. + It may be tied to either 0 or 1. + + Behavior of the dcsr.STOPCOUNT bit: + * 'read-only-0': tied to 0 + * 'read-only-1': tied to 1 + * 'rw': read-write + DCSR_STOPTIME_TYPE: + schema: + type: string + enum: [read-only-0, read-only-1, rw] + description: | + Implementation of dcsr.STOPTIME is optional. + It may be tied to either 0 or 1. + + Behavior of the dcsr.STOPTIME bit: + * 'read-only-0': tied to 0 + * 'read-only-1': tied to 1 + * 'rw': read-write diff --git a/spec/std/isa/isa/globals.isa b/spec/std/isa/isa/globals.isa index f732e8e233..858cac5521 100644 --- a/spec/std/isa/isa/globals.isa +++ b/spec/std/isa/isa/globals.isa @@ -35,14 +35,18 @@ Bits<67> ILLEGAL_WLRL = 67'h40000000000000000; # maximum instruction encoding size U32 INSTR_ENC_SIZE = 32; -# encoded as defined in the privilege spec +# encoding defined by concatenation of { D, MPV, MPP }: +# - D : debug mode (1b) +# - MPV: mstatus.MPV (1b) +# - MPP: mstatus.MPP (2b) enum PrivilegeMode { - M 0b011 - S 0b001 - HS 0b001 # alias for S when H extension is used - U 0b000 - VS 0b101 - VU 0b100 + M 0b0011 + S 0b0001 + HS 0b0001 # alias for S when H extension is used + U 0b0000 + VS 0b0101 + VU 0b0100 + D 0b1011 } enum MemoryOperation { diff --git a/tools/ruby-gems/udb/lib/udb/cfg_arch.rb b/tools/ruby-gems/udb/lib/udb/cfg_arch.rb index ad791b2ab8..3688b32b06 100644 --- a/tools/ruby-gems/udb/lib/udb/cfg_arch.rb +++ b/tools/ruby-gems/udb/lib/udb/cfg_arch.rb @@ -166,6 +166,8 @@ def multi_xlen_in_mode?(mode) else raise "Unexpected configuration state" end + when "D" + mxlen.nil? else raise ArgumentError, "Bad mode" end diff --git a/tools/ruby-gems/udb/lib/udb/obj/csr.rb b/tools/ruby-gems/udb/lib/udb/obj/csr.rb index f4bd52980d..5cbc672c28 100644 --- a/tools/ruby-gems/udb/lib/udb/obj/csr.rb +++ b/tools/ruby-gems/udb/lib/udb/obj/csr.rb @@ -396,6 +396,8 @@ def modes_with_access ["M", "S", "U", "VS", "VU"] when "VS" ["M", "S", "VS"] + when "D" + ["M", "D"] else raise "unexpected priv mode" end