When a design progresses from simulation to hardware implementation, a user’s control and understanding of the system’s current state drops dramatically. To help bring up and debug low level software and hardware, it is critical to have good debugging support built into the hardware. When a robust OS is running on a core, software can handle many debugging tasks. However, in many scenarios, hardware support is essential.
This document outlines a standard architecture for debug support on RISC-V hardware platforms. This architecture allows a variety of implementations and tradeoffs, which is complementary to the wide range of RISC-V implementations. At the same time, this specification defines common interfaces to allow debugging tools and components to target a variety of hardware platforms based on the RISC-V ISA.
System designers may choose to add additional hardware debug support, but this specification defines a standard interface for common functionality.
- advanced feature
-
An advanced feature for advanced users. Most users will not be able to take advantage of it.
- AMO
-
Atomic Memory Operation.
- BYPASS
-
JTAG instruction that selects a single bit data register, also called BYPASS.
- component
-
A RISC-V core, or other part of a hardware platform. Typically all components will be connected to a single system bus.
- CSR
-
Control and Status Register.
- DM
-
Debug Module (see [dm]).
- DMI
-
Debug Module Interface (see [dmi]).
- DR
-
JTAG Data Register.
- DTM
-
Debug Transport Module (see [dtm]).
- DXLEN
-
Debug XLEN, which is the widest XLEN a hart supports, ignoring the current value of
mxl
inmisa
. - essential feature
-
An essential feature must be present in order for debug to work correctly.
- GPR
-
General Purpose Register.
- hardware platform
-
A single system consisting of one or more components.
- hart
-
A hardware thread in a RISC-V core.
- IDCODE
-
32-bit Identification CODE, and a JTAG instruction that returns the IDCODE value.
- IR
-
JTAG Instruction Register.
- JTAG
-
Refers to work done by IEEE’s Joint Test Action Group, described in IEEE 1149.1.
- legacy feature
-
A legacy feature should only be implemented to support legacy hardware that is present in a system.
- Minimal RISC-V Debug Specification
-
A subset of the full Debug Specification that allows for very small implementations. See [dm].
- NAPOT
-
Naturally Aligned Power-Of-Two.
- NMI
-
Non-Maskable Interrupt.
- physical address
-
address that is directly usable on the system bus.
- recommended feature
-
A recommended feature is not required for debug to work correctly, but it is so useful that it should not be omitted without good reason.
- SBA
-
System Bus Access (see [systembusaccess]).
- specialized feature
-
A specialized feature, that only makes sense in the context of some specific hardware.
- TAP
-
Test Access Port, defined in IEEE 1149.1.
- TM
-
Trigger Module (see [trigger]).
- virtual address
-
An address as a hart sees it. If the hart is using address translation this may be different from the physical address. If there is no translation then it will be the same.
- xepc
-
The exception program counter CSR (e.g. ) that is appropriate for the mode being trapped to.
This specification attempts to support all RISC-V ISA extensions that have, roughly, been ratified through the first half of 2023. In particular, though, this specification specifically addresses features in the following extensions:
-
A
-
C
-
D
-
F
-
H
-
Sm1p13
-
Ss1p13
-
Smstateen
-
V
-
Zawrs
-
Zcmp
-
Zicbom
-
Zicboz
-
Zicbop
Version 0.13 of this document was ratified by the RISC-V Foundation’s board. Versions 0.13.\(x\) are bug fix releases to that ratified specification.
Version 0.14 was a working version that was never officially ratified.
Version 1.0 is almost entirely forwards and backwards compatible with Version 0.13.
Changes that fix a bug in the spec:
-
Fix order of operations described in {dm-sbdata0}. #392
-
Resume ack is set after resume, in [runcontrol]. #400
-
{textra32-sselect} applies to {textra32-svalue} . #402
-
{tcontrol-mte} only applies when action=0. #411
-
{accessmemory-aamsize} does not affect Argument Width. #420
-
Clarify that harts halt out of reset if {dmcontrol-haltreq} =1. #419
Changes that are not backwards-compatible. Debuggers or hardware implementations that implement 0.13 will have to change something in order to implement 1.0:
-
Make haltsum0 optional if there is only one hart. #505
-
System bus autoincrement only happens if an access actually takes place. ({dm-sbdata0}) #507
-
Bump {tinfo-version} to 3. #512 , Require debugger to poll {dmcontrol-dmactive} after lowering it. #566
-
Add {icount-pending} to {csr-icount} . #574
-
When a selected trigger is disabled, {csr-tdata2} and {csr-tdata3} can be written with any value supported by any of the types this trigger supports. #721
-
{csr-tcontrol} fields only apply to breakpoint traps, not any trap. #723
-
If {tinfo-version} is greater than 0, then {mcontrol6-hit0} (previously called {csr-mcontrol}.
hit
) now contains 0 when a trigger fires more than one instruction after the instruction that matched. (This information is now reflected in .) #795 -
If {tinfo-version} is greater than 0, then bit 20 of {csr-mcontrol6} is no longer used for timing information. (Previously the bit was called {csr-mcontrol}.
timing
.) #807 -
If {tinfo-version} is greater than 0, then the encodings of {mcontrol6-size} for sizes greater than 64 bit have changed. #807
Changes that slightly modify defined behavior. Technically backwards incompatible, but unlikely to be noticeable:
-
{dcsr-stopcount} only applies to hart-local counters. #405
-
{tinfo-version} may be invalid when {dmcontrol-dmactive}=0. #414
-
Address triggers ({csr-mcontrol}) may fire on any accessed address. #421
-
All Trigger Module registers ([tab:trigger]) are optional. #431
-
When extending IR, {dtm-bypass} still is all ones. #437
-
{dcsr-ebreaks} and {dcsr-ebreaku} are WARL. #458
-
NMIs are disabled by {dcsr-stepie}. #465
-
R/W1C fields should be cleared by writing every bit high. #472
-
Specify trigger priorities in [tab:priority] relative to exceptions. #478
-
Time may pass before {dmcontrol-dmactive} becomes high. #500
-
Clear MPRV when resuming into lower privilege mode. #503
-
Halt state may not be preserved across reset. #504
-
Hardware should clear trigger action when {tdata1-dmode} is cleared and action is 1. #501
-
Change quick access exceptions to halt the target in [ac-quickaccess]. #585
-
Writing 0 to {csr-tdata1} forces a state where {csr-tdata2} and {csr-tdata3} are writable. #598
-
Solutions to deal with reentrancy in [nativetrigger] prevent triggers from matching, not merely firing. This primarily affects behavior. #722
-
Attempts to access an unimplemented CSR raise an illegal instruction exception. #791
New backwards-compatible feature that did not exist before:
-
Add halt groups and external triggers in [hrgroups]. #404
-
Reserve some DMI space for non-standard use. See {dm-custom}, and {dm-custom0} through . #406
-
Reserve trigger {tdata1-type} values for non-standard use. #417
-
Recommend matching on every accessed address. #449
-
Add resume groups in [hrgroups]. #506
-
Add {abstractcs-relaxedpriv} . #536
-
Move {csr-scontext}, renaming original to {csr-mscontext}, and create {csr-hcontext}. #535
-
Add {csr-mcontrol6}, deprecating {csr-mcontrol}. #538
-
Add hypervisor support: {dcsr-ebreakvs}, {dcsr-ebreakvu}, {dcsr-v}, {csr-hcontext}, {csr-mcontrol}, {csr-mcontrol6}, and {virt-priv}. #549
-
Optionally make {dmstatus-anyunavail} and {dmstatus-allunavail} sticky, controlled by {dmstatus-stickyunavail}. #520
-
Add {csr-tmexttrigger} to support trigger module external trigger inputs. #543
-
Describe {csr-mcontrol} and {csr-mcontrol6} behavior with atomic instructions. #561
-
Trigger hit bits must be set on fire, may be set on match. #593
-
Add {textra32-sbytemask} and {textra32-sbytemask} to {csr-textra32} and {csr-textra64}. #588
-
Allow debugger to request harts stay alive with keepalive bit in {dmcontrol-setkeepalive}. #592
-
Add {dmstatus-ndmresetpending} to allow a debugger to determine when ndmreset is complete. #594
-
Add {tmexttrigger-intctl} to support triggers from an interrupt controller. #599
Backwards-incompatible changes between two versions that are both called 1.0 stable.
-
{itrigger-nmi} was moved from {csr-etrigger} to {csr-itrigger}, and is now subject to the mode bits in that trigger.
-
#728 introduced Message Registers, which were later removed in #878.
-
It may not be possible to read the contents of the Program Buffer using the
progbuf
registers. #731 -
{csr-tcontrol} fields apply to all traps, not just breakpoint traps. This reverts #723. #880
Backwards-incompatible changes between 1.0.0-rc1 and 1.0.0-rc2.
-
#981 made {csr-scontext}.{scontext-data}, {csr-mcontext}.{mcontext-hcontext}, {textra64-sbytemask}, and {csr-textra64}.
svalue
narrower. This avoids confusion about the contents of {csr-scontext} and {csr-mcontext} when XLEN is reduced and increased again.
This document contains two parts. The main part of the document is the specification, which is given in the numbered chapters. The second part of the document is a set of appendices. The information in the appendices is intended to clarify and provide examples, but is not part of the actual specification.
This specification contains both ISA and non-ISA parts. The ISA parts define self-contained ISA extensions. The other parts of the document describe the non-ISA external debug extension. Chapters whose contents are solely one or the other are labeled as such in their title. Chapters without such a label apply to both ISA and non-ISA.
All register definitions in this document follow the format shown below. A simple graphic shows which fields are in the register. The upper and lower bit indices are shown to the top left and top right of each field. The total number of bits in the field are shown below it.
After the graphic follows a table which for each field lists its name, description, allowed accesses, and reset value. The allowed accesses are listed in Register Access Abbreviations. The reset value is either a constant or "Preset." The latter means it is an implementation-specific legal value.
Parts of the register which are currently unused are labeled with the number 0. Software must only write 0 to those fields, and ignore their value while reading. Hardware must return 0 when those fields are read, and ignore the value written to them.
Note
|
This behavior enables us to use those fields later without having to increase the values in the version fields. |
Names of registers and their fields are hyperlinks to their definition, and are also listed in the [index].
R |
Read-only. |
R/W |
Read/Write. |
R/W1C |
Read/Write Ones to Clear. Writing 0 to every bit has no effect. Writing 1 to every bit clears the field. The result of other writes is undefined. |
WARZ |
Write any, read zero. A debugger may write any value. When read this field returns 0. |
W1 |
Write-only. Only writing 1 has an effect. When read the returned value should be 0. |
WARL |
Write any, read legal. A debugger may write any value. If a value is unsupported, the implementation converts the value to one that is supported. |
There are several use cases for dedicated debugging hardware, both in native debug and external debug. Native debug (sometimes called self-hosted debug) refers to debug software running on a RISC-V platform which debugs the same platform. The optional Trigger Module provides features that are useful for native debug. External debug refers to debug software running somewhere else, debugging the RISC-V platform via a debug transport like JTAG. The entire document provides features that are useful for external debug.
This specification addresses the use cases listed below. Implementations can choose not to implement every feature, which means some use cases might not be supported.
-
Accessing hardware on a hardware platform without a working CPU. (External debug.)
-
Bootstrapping a hardware platform to test, configure, and program components before there is any executable code path in the hardware platform. (External debug.)
-
Debugging low-level software in the absence of an OS or other software. (External debug.)
-
Debugging issues in the OS itself. (External or native debug.)
-
Debugging processes running on an OS. (Native or external debug.)
The debug interface described in this specification supports the following features:
-
All hart registers (including CSRs) can be read/written.
-
Memory can be accessed either from the hart’s point of view, through the system bus directly, or both.
-
RV32, RV64, and future RV128 are all supported.
-
Any hart in the hardware platform can be independently debugged.
-
A debugger can discover almost [1] everything it needs to know itself, without user configuration.
-
Each hart can be debugged from the very first instruction executed.
-
A RISC-V hart can be halted when a software breakpoint instruction is executed.
-
Hardware single-step can execute one instruction at a time.
-
Debug functionality is independent of the debug transport used.
-
The debugger does not need to know anything about the microarchitecture of the harts it is debugging.
-
Arbitrary subsets of harts can be halted and resumed simultaneously. (Optional)
-
Arbitrary instructions can be executed on a halted hart. That means no new debug functionality is needed when a core has additional or custom instructions or state, as long as there exist programs that can move that state into GPRs. (Optional)
-
Registers can be accessed without halting. (Optional)
-
A running hart can be directed to execute a short sequence of instructions, with little overhead. (Optional)
-
A system bus manager allows memory access without involving any hart. (Optional)
-
A RISC-V hart can be halted when a trigger matches the PC, read/write address/data, or an instruction opcode. (Optional)
-
Harts can be grouped, and harts in the same group will all halt when any of them halts. These groups can also react to or notify external triggers. (Optional)
This document does not suggest a strategy or implementation for hardware test, debugging or error detection techniques. Scan, built-in self test (BIST), etc. are out of scope of this specification, but this specification does not intend to limit their use in RISC-V systems.
It is possible to debug code that uses software threads, but there is no special debug support for it.