[[]]
== Debug Module (DM) (non-ISA extension)

The Debug Module implements a translation interface between abstract
debug operations and their specific implementation. It might support the
following operations:

. Give the debugger necessary information about the implementation.
(Required)
. Allow any individual hart to be halted and resumed. (Required)
. Provide status on which harts are halted. (Required)
. Provide abstract read and write access to a halted hart's GPRs.
(Required)
. Provide access to a reset signal that allows debugging from the very
first instruction after reset. (Required)
. Provide a mechanism to allow debugging harts immediately out of reset
(regardless of the reset cause). (Optional)
. Provide abstract access to non-GPR hart registers. (Optional)
. Provide a Program Buffer to force the hart to execute arbitrary
instructions. (Optional)
. Allow multiple harts to be halted, resumed, and/or reset at the same
time. (Optional)
. Allow memory access from a hart's point of view. (Optional)
. Allow direct System Bus Access. (Optional)
. Group harts. When any hart in the group halts, they all halt. (Optional)
. Respond to external triggers by halting each hart in a configured group.
(Optional)
. Signal an external trigger when a hart in a group halts. (Optional)

In order to be compatible with this specification an implementation
must:

. Implement all the required features listed above.
. Implement at least one of Program Buffer, System Bus Access, or Abstract
Access Memory command mechanisms.
. Do at least one of:
.. Implement the Program Buffer.
.. Implement abstract access to all registers that are visible to software
running on the hart including all the registers that are present on the
hart and listed in <<regno>>.
.. Implement abstract access to at least all GPRs, <<descr>>, and <<dpc>>, and advertise the implementation as conforming to the "Minimal RISC-V Debug
Specification", instead of the "RISC-V Debug Specification".

A single DM can debug up to latexmath:[$2^{20}$] harts.

[[i]]
=== Debug Module Interface (DMI)

Debug Modules are subordinates on a bus called the Debug Module
Interface (DMI). The bus manager is the Debug Transport Module(s). The
Debug Module Interface can be a trivial bus with one manager and one
subordinate (see <<dmi_signals>>), or use a more
full-featured bus like TileLink or the AMBA Advanced Peripheral Bus. The
details are left to the system designer.

The DMI uses between 7 and 32 address bits. Each address points at a
single 32-bit register that can be read or written. The bottom of the
address space is used for the first (and usually only) DM. Extra space
can be used for custom debug devices, other cores, additional DMs, etc.
If there are additional DMs on this DMI, the base address of the next DM
in the DMI address space is given in <<nextdm>>.

The Debug Module is controlled via register accesses to its DMI address
space.

[[reset]]
=== Reset Control

There are two methods that allow a debugger to reset harts. <<ndmreset>> resets all
the harts in the hardware platform, as well as all other parts of the
hardware platform except for the Debug Modules, Debug Transport Modules,
and Debug Module Interface. Exactly what is affected by this reset is
implementation dependent, but it must be possible to debug programs from
the first instruction executed. <<hartreset>> resets all the currently selected harts.
In this case an implementation may reset more harts than just the ones
that are selected. The debugger can discover which other harts are reset
(if any) by selecting them and checking <<anyhavereset>> and <<allhavereset>>.

To perform either of these resets, the debugger first asserts the bit,
and then clears it. The actual reset may start as soon as the bit is
asserted, but may start an arbitrarily long time after the bit is
deasserted. The reset itself may also take an arbitrarily long time.
While the reset is on-going, harts are either in the running state,
indicating it’s possible to perform some abstract commands during this
time, or in the unavailable state, indicating it’s not possible to
perform any abstract commands during this time. Once a hart's reset is
complete, `havereset` becomes set. When a hart comes out of reset and <<haltreq>> or <<resethaltreq>> 
are set, the hart will immediately enter Debug Mode (halted state).
Otherwise, if the hart was initially running it will execute normally
(running state) and if the hart was initially halted it should now be
running but may be halted.

[NOTE]
====
There is no general, reliable way for the debugger to know when reset
has actually begun.
====

The Debug Module's own state and registers should only be reset at
power-up and while <<dmactive>> in <<dmcontrol>> is 0. If there is another mechanism to reset the DM, this mechanism must also reset all the harts accessible to the DM.

Due to clock and power domain crossing issues, it might not be possible
to perform arbitrary DMI accesses across hardware platform reset. While <<ndmreset>>  or any external reset is asserted, the only supported DM operations are reading and writing <<dmcontrol>>. The behavior of other accesses is undefined.

When harts have been reset, they must set a sticky `havereset` state
bit. The conceptual `havereset` state bits can be read for selected
harts in <<anyhavereset>> and <<allhavereset>> in <<dmstatus>>. These bits must be set regardless of the cause of the
reset. The `havereset` bits for the selected harts can be cleared by
writing 1 to <<ackhavereset>> in <<dmcontrol>>. The `havereset` bits might or might not be cleared when <<dmactive>> is low.

[[selectingharts]]
=== Selecting Harts

Up to latexmath:[$2^{20}$] harts can be connected to a single DM.
Commands issued to the DM only apply to the currently selected harts.

To enumerate all the harts, a debugger must first determine `HARTSELLEN`
by writing all ones to (assuming the maximum size) and reading back the
value to see which bits were actually set. Then it selects each hart
starting from 0 until either <<anynonexistent>> in <<dmstatus>> is 1, or the highest index (depending on `HARTSELLEN`) is reached.

The debugger can discover the mapping between hart indices and by using
the interface to read , or by reading the hardware platform's
configuration structure.

==== Selecting a Single Hart

All debug modules must support selecting a single hart. The debugger can
select a hart by writing its index to <<hartsel>>. Hart indexes start at 0 and are
contiguous until the final index.

[[hartarraymask]]
==== Selecting Multiple Harts

Debug Modules may implement a Hart Array Mask register to allow
selecting multiple harts at once. The latexmath:[$n$]th bit in the Hart
Array Mask register applies to the hart with index latexmath:[$n$]. If
the bit is 1 then the hart is selected. Usually a DM will have a Hart
Array Mask register exactly wide enough to select all the harts it
supports, but it's allowed to tie any of these bits to 0.

The debugger can set bits in the hart array mask register using <<hawindowsel>> and <<hawindow>>,
then apply actions to all selected harts by setting <<hasel>>. If this feature is
supported, multiple harts can be halted, resumed, and reset
simultaneously. The state of the hart array mask register is not
affected by setting or clearing <<hasel>>.

Execution of Abstract Commands ignores this mechanism and only applies
to the hart selected by <<hartsel>>.

=== Hart DM States

Every hart that can be selected is in exactly one of the following four
DM states: non-existent, unavailable, running, or halted. Which state
the selected harts are in is reflected by <<allnonexistent>>, <<anynonexistent>>, <<allunavail>>, <<anyunavail>>, <<allrunning>>, <<anyrunning>>, <<allhalted>>, and <<anyhalted>>.

Harts are nonexistent if they will never be part of this hardware
platform, no matter how long a user waits. E.g. in a simple single-hart
hardware platform only one hart exists, and all others are nonexistent.
Debuggers may assume that a hardware platform has no harts with indexes
higher than the first nonexistent one.

Harts are unavailable if they might exist/become available at a later
time, or if there are other harts with higher indexes than this one.
Harts may be unavailable for a variety of reasons including being reset,
temporarily powered down, and not being plugged into the hardware
platform. That means harts might become available or unavailable at any
time, although these events should be rare in hardware platforms built
to be easily debugged. There are no guarantees about the state of the
hart when it becomes available.

Hardware platforms with very large number of harts may permanently
disable some during manufacturing, leaving holes in the otherwise
continuous hart index space. In order to let the debugger discover all
harts, they must show up as unavailable even if there is no chance of
them ever becoming available.

Harts are running when they are executing normally, as if no debugger
was attached. This includes being in a low power mode or waiting for an
interrupt, as long as a halt request will result in the hart being
halted.

Harts are halted when they are in Debug Mode, only performing tasks on
behalf of the debugger.

Which states a hart that is reset goes through is implementation
dependent. Harts may be unavailable while reset is asserted, and some
time after reset is deasserted. They might transition to running for
some time after reset is deasserted. Finally they end up either running
or halted, depending on <<haltreq>> and <<resethaltreq>>.

[[runcontrol]]
=== Run Control

For every hart, the Debug Module tracks 4 conceptual bits of state: halt
request, resume ack, halt-on-reset request, and hart reset. (The hart
reset and halt-on-reset request bits are optional.) These 4 bits reset
to 0, except for resume ack, which may reset to either 0 or 1. The DM
receives halted, running, and havereset signals from each hart. The
debugger can observe the state of resume ack in <<allresumeack>> and <<anyresumeack>>, and the state of halted, running, and havereset signals in <<allhalted>>, <<anyhalted>>, <<allrunning>>, <<anyrunning>>, <<allhavereset>>, and <<anyhavereset>>. The state of the other bits cannot be observed directly.

When a debugger writes 1 to <<haltreq>>, each selected hart's halt request bit is
set. When a running hart, or a hart just coming out of reset, sees its
halt request bit high, it responds by halting, deasserting its running
signal, and asserting its halted signal. Halted harts ignore their halt
request bit.

When a debugger writes 1 to <<resumereq>>, each selected hart's resume ack bit is
cleared and each selected, halted hart is sent a resume request. Harts
respond by resuming, clearing their halted signal, and asserting their
running signal. At the end of this process the resume ack bit is set.
These status signals of all selected harts are reflected in <<allresumeack>>, <<anyresumeack>>, <<allrunning>>, and <<anyrunning>>. Resume requests are ignored by running harts.

When halt or resume is requested, a hart must respond in less than one
second, unless it is unavailable. (How this is implemented is not
further specified. A few clock cycles will be a more typical latency).

The DM can implement optional halt-on-reset bits for each hart, which it
indicates by setting <<hasresethaltreq>> to 1. This means the DM implements the <<setresethaltreq>> and <<clrresethaltreq>> bits.  Writing 1 to <<setresethaltreq>> sets the halt-on-reset request bit for each selected hart.
When a hart's halt-on-reset request bit is set, the hart will
immediately enter debug mode on the next deassertion of its reset. This
is true regardless of the reset's cause. The hart's halt-on-reset
request bit remains set until cleared by the debugger writing 1 to <<clrresethaltreq>> while the hart is selected, or by DM reset.

If the DM is reset while a hart is halted, it is UNSPECIFIED whether that hart
resumes. Debuggers should use <<resumereq>> to explicitly resume harts before clearing <<dmactive>> and disconnecting.

[[hrgroups]]
=== Halt Groups, Resume Groups, and External Triggers

An optional feature allows a debugger to place harts into two kinds of
groups: halt groups and resume groups. It is also possible to add
external triggers to a halt and resume groups. At any given time, each
hart and each trigger is a member of exactly one halt group and exactly
one resume group.

In both halt and resume groups, group 0 is special. Harts in group 0
halt/resume as if groups aren’t implemented at all.

When any hart in a halt group halts:

. That hart halts normally, with <<cause>> reflecting the original cause of the
halt.
. All the other harts in the halt group that are running will quickly
halt. <<cause>> for those harts should be set to 6, but may be set to 3. Other
harts in the halt group that are halted but have started the process of
resuming must also quickly become halted, even if they do resume
briefly.
. Any external triggers in that group are notified.

Adding a hart to a halt group does not automatically halt that hart,
even if other harts in the group are already halted.

When an external trigger that's a member of the halt group fires:

. All the harts in the halt group that are running will quickly halt. <<cause>> for
those harts should be set to 6, but may be set to 3. Other harts in the
halt group that are halted but have started the process of resuming must
also quickly become halted, even if they do resume briefly.

When any hart in a resume group resumes:

. All the other harts in that group that are halted will quickly resume as
soon as any currently executing abstract commands have completed. Each
hart in the group sets its resume ack bit as soon as it has resumed.
Harts that are in the process of halting should complete that process
and stay halted.
. Any external triggers in that group are notified.

Adding a hart to a resume group does not automatically resume that hart,
even if other harts in the group are currently running.

When an external trigger that's a member of the resume group fires:

. All the harts in that group that are halted will quickly resume as soon
as any currently executing abstract commands have completed. Each hart
in the group sets its resume ack bit as soon as it has resumed. Harts
that are in the process of halting should complete that process and stay
halted.

External triggers are abstract concepts that can signal the DM and/or
receive signals from the DM. This configuration is done through <<dmcs2>>, where
external triggers are referred to by a number. Commonly, external
triggers are capable of sending a signal from the hardware platform into
the DM, as well as receiving a signal from the DM to take their own
action on. It is also allowable for an external trigger to be input-only
or output-only. By convention external triggers 0-7 are bidirectional,
triggers 8-11 are input-only, and triggers 12-15 are output-only but
this is not required.

[NOTE]
====
External triggers could be used to implement near simultaneous
halting/resuming of all cores in a hardware platform, when not all cores
are RISC-V cores.
====

When the DM is reset, all harts must be placed in the lowest-numbered
halt and resume groups that they can be in. (This will usually be group
0.)

Some designs may choose to hardcode hart groups to a group other than
group 0, meaning it is never possible to halt or resume just a single
hart. This is explicitly allowed. In that case it must be possible to
discover the groups by using <<dmcs2>> even if it's not possible to change the
configuration.

[[abstractcommands]]
=== Abstract Commands

The DM supports a set of abstract commands, most of which are optional.
Depending on the implementation, the debugger may be able to perform
some abstract commands even when the selected hart is not halted.
Debuggers can only determine which abstract commands are supported by a
given hart in a given state (running, halted, or held in reset) by
attempting them and then looking at <<cmderr>> in <<abstractcs>> to see if they were successful. Commands may be supported with some options set, but not with other
options set. If a command has unsupported options set or if bits that
are defined as 0 aren't 0, then the DM must set <<smderr>> to 2 (not supported).

[NOTE]
====
Example: Every DM must support the Access Register command, but might
not support accessing CSRs. If the debugger requests to read a CSR in
that case, the command will return "not supported".
====

Debuggers execute abstract commands by writing them to <<command>>. They can
determine whether an abstract command is complete by reading <<busy>> in <<abstractcs>>. If the debugger starts a new command while <<busy>> is set, <<cmderr>> becomes 1 (busy), the
currently executing command still gets to run to completion, but any
error generated by the currently executing command is lost. After
completion, <<smderr>> indicates whether the command was successful or not.
Commands may fail because a hart is not halted, not running,
unavailable, or because they encounter an error during execution.

If the command takes arguments, the debugger must write them to the
`data` registers before writing to <<command>>. If a command returns results, the
Debug Module must ensure they are placed in the `data` registers before <<busy>>
is cleared. Which `data` registers are used for the arguments is
described in <<datareg>>. In all cases the
least-significant word is placed in the lowest-numbered `data` register.
The argument width depends on the command being executed, and is DXLEN
where not explicitly specified.

[[datareg]]
.Use of Data Registers
[%autowidth,float="center",align="center",cols="^,<,<,<",options="header"]
|===
| Argument Width | arg0/return value | arg1 | arg2
| 32 | <<data0>> | `data1` | `data2`
| 64 | <<data0>>, `data1` | `data2`, `data3` | `data4`, `data5`
|128 | <<data0>>-`data3` | `data4`-`data7` | `data8`-`data11`
|===

[NOTE]
====
The Abstract Command interface is designed to allow a debugger to write
commands as fast as possible, and then later check whether they
completed without error. In the common case the debugger will be much
slower than the target and commands succeed, which allows for maximum
throughput. If there is a failure, the interface ensures that no
commands execute after the failing one. To discover which command
failed, the debugger has to look at the state of the DM (e.g. contents
of <<data0>>) or hart (e.g. contents of a register modified by a Program Buffer program) to determine which one failed.
====

Before starting an abstract command, a debugger must ensure that <<haltreq>>, <<resumereq>>, and <<ackhavereset>> are all 0.

While an abstract command is executing (<<busy>> in <abstractcs>> is high), a debugger must not change <<hartset>>, and must not write 1 to <<haltreq>>, <<resumereq>>, <<ackhavereset>>, <<setresethaltreq>>, or <<clrresethaltreq>>.

If an abstract command does not complete in the expected time and
appears to be hung, the debugger can try to reset the hart (using <<hartreset>> or <<ndmreset>>).
If that doesn't clear <<busy>>, then it can try resetting the Debug Module
(using <<dmactive>>).

If an abstract command is started while the selected hart is unavailable
or if a hart becomes unavailable while executing an abstract command,
then the Debug Module may terminate the abstract command, setting <<busy>> low,
and <<cmderr>> to 4 (halt/resume). Alternatively, the command could just appear to
be hung (<<busy>> never goes low).

==== Abstract Command Listing

This section describes each of the different abstract commands and how
their fields should be interpreted when they are written to <<command>>.

Each abstract command is a 32-bit value. The top 8 bits contain which
determines the kind of command. <<cmdtype>> lists all commands.

.Meaning of <<cmdtype>>
[%autowidth,float="center",align="center",cols=">,<,<",options="header"]
|===
| <<cmdtype>> | Command | Page
| 0 | Access Register Command |
| 1 | Quick Access |
| 2 | Access Memory Command |
|===

include::build/abstract_commands.adoc[]

[[programbuffer]]
=== Program Buffer

To support executing arbitrary instructions on a halted hart, a Debug
Module can include a Program Buffer that a debugger can write small
programs to. DMs that support all necessary functionality using abstract
commands only may choose to omit the Program Buffer.

A debugger can write a small program to the Program Buffer, and then
execute it exactly once with the Access Register Abstract Command,
setting the <<postexec>> bit in <<command>>. The debugger can write whatever program it likes
(including jumps out of the Program Buffer), but the program must end
with `ebreak` or `c.ebreak`. An implementation may support an implicit
`ebreak` that is executed when a hart runs off the end of the Program
Buffer. This is indicated by . With this feature, a Program Buffer of
just 2 32-bit words can offer efficient debugging.

While these programs are executed, the hart does not leave Debug Mode
(see <<debugmode>>). If an exception is
encountered during execution of the Program Buffer, no more instructions
are executed, the hart remains in Debug Mode, and <<cmderr>> is set to 3
(`exception error`). If the debugger executes a program that doesn’t
terminate with an `ebreak` instruction, the hart will remain in Debug
Mode and the debugger will lose control of the hart.

If <<progbufsize>> is 1 then the following apply:

. <<impebreak>> must be 1.
. If the debugger writes a compressed instruction into the Program Buffer,
it must be placed into the lower 16 bits and accompanied by a compressed
`nop` in the upper 16 bits.

[NOTE]
====
This requirement on the debugger for the case of <<progbufsize>> equal to 1 is to
accommodate hardware designs that prefer to stuff instructions directly
into the pipeline when halted, instead of having the Program Buffer
exist in the address space somewhere.
====

The Program Buffer may be implemented as RAM which is accessible to the
hart. A debugger can determine if this is the case by executing small
programs that attempt to write and read back relative to while executing
from the Program Buffer. If so, the debugger has more flexibility in
what it can do with the program buffer.

=== Overview of Hart Debug States

<<abstract_sm>> shows a conceptual view of the states
passed through by a hart during run/halt debugging as influenced by the
different fields of <<dmcontrol>>, <<abstractcs>>, <<abstractauto>>, and <<command>>.

[[systembusaccess]]
=== System Bus Access

A debugger can access memory from a hart's point of view using a Program
Buffer or the Abstract Access Memory command. (Both these features are
optional.) A Debug Module may also include a System Bus Access block to
provide memory access without involving a hart, regardless of whether
Program Buffer is implemented. The System Bus Access block uses physical
addresses.

The System Bus Access block may support 8-, 16-, 32-, 64-, and 128-bit
accesses. <<sbdatabits>> shows which bits in `sbdata` are used for each access size.

<<<

[[sbdatabits]]
.System Bus Data Bits
[%autowidth,align="center",float="center",cols=">,<",options="header"]
|===
|Access Size | Data Bits
| 8 | <<sbdata0>> bits 7:0
| 16 | <<sbdata0>> bits 15:0
| 32 | <<sbdata0>>
| 64 | <<sbdata1>>, <<sbdata0>>
| 128 | <<sbdata3>>, <<sbdata2>>, <<sbdata1>>, <<sbdata0>>
|===

Depending on the microarchitecture, data accessed through System Bus
Access might not always be coherent with that observed by each hart. It
is up to the debugger to enforce coherency if the implementation does
not. This specification does not define a standard way to do this.
Possibilities may include writing to special memory-mapped locations, or
executing special instructions via the Program Buffer.

[NOTE]
====
Implementing a System Bus Access block has several benefits even when a
Debug Module also implements a Program Buffer. First, it is possible to
access memory in a running system with minimal impact. Second, it may
improve performance when accessing memory. Third, it may provide access
to devices that a hart does not have access to.
====

//[[abstract_sm]]
//.Run/Halt Debug State Machine for single-hart hardware platforms. As only a small amount of state is visible to the debugger, the states and transitions are conceptual.

//FIXME::image:images/abstract_commands.svg[]

=== Minimally Intrusive Debugging

Depending on the task it is performing, some harts can only be halted
very briefly. There are several mechanisms that allow accessing
resources in such a running system with a minimal impact on the running
hart.

First, an implementation may allow some abstract commands to execute
without halting the hart.

Second, the Quick Access abstract command can be used to halt a hart,
quickly execute the contents of the Program Buffer, and let the hart run
again. Combined with instructions that allow Program Buffer code to
access the `data` registers, as described in <<hartinfo>>, this can be used to
quickly perform a memory or register access. For some hardware platforms
this will be too intrusive, but many hardware platforms that can't be
halted can bear an occasional hiccup of a hundred or less cycles.

Third, if the System Bus Access block is implemented, it can be used
while a hart is running to access system memory.

=== Security

To protect intellectual property it may be desirable to lock access to
the Debug Module. To allow access during a manufacturing process and not
afterwards, a reasonable solution could be to add a fuse bit to the
Debug Module that can be used to be permanently disable it. Since this
is technology specific, it is not further addressed in this spec.

Another option is to allow the DM to be unlocked only by users who have
an access key. Between <<authenticated>>, <<authbusy>>, and <<authdata>> arbitrarily complex authentication
mechanism can be supported. When <<authenticated>> is clear, the DM must not interact with
the rest of the hardware platform, nor expose details about the harts
connected to the DM. All DM registers should read 0, while writes should
be ignored, with the following mandatory exceptions:

. <<authenticated>> in <<dmstatus>> is readable.
. <<authbusy>> in <<dmstatus>> is readable.
. <<version>> in <<dmstatus>> is readable.
. <<dmactive>> in <<dmcontrol>> is readable and writable.
. <<authdata>> is readable and writable.

Implementations where it's not possible to unlock the DM by using <<authdata>> should not implement that register.

=== Version Detection

To detect the version of the Debug Module with a minimum of side
effects, use the following procedure:

. Read <<dmcontrol>>.
. If <<dmactive>> is 0 or <<ndmreset>> is 1:
.. Write <<dmcontrol>>, preserving <<hartreset>>, <<hasel>>, <<hartsello>>, and <<hartselhi>> from the value that was read, setting <<dmactive>>, and clearing all the other bits.
.. Read <<dmstatus>>until <<dmactive>> is high.
. Read <<dmstatus>>, which contains <<version>>.

If it was necessary to clear <<ndmreset>>, this might have the following  
side effects:

. <<haltreq>> is cleared, potentially preventing a halt request made by a previous debugger from taking effect.
. <<resumereq>> is cleared, potentially preventing a resume request made by a previous debugger from taking effect.
. <<ndmreset>> is deasserted, releasing the hardware platform from reset if a previous debugger had set it.
. <<dmactive>> is asserted, releasing the DM from reset. This in itself is not
observable by any harts.

This procedure is guaranteed to work in future versions of this spec.
The meaning of the <<dmcontrol>> bits where <<hartreset>>, <<hasel>>, <<hartsello>>, and <<hardselhi>> currently reside might change,
but preserving them will have no side effects. Clearing the bits of <<dmcontrol>> not explicitly mentioned here will have no side effects beyond the ones mentioned above.

[[debbus]]
=== Debug Module Registers

The registers described in this section are accessed over the DMI bus.
Each DM has a base address (which is 0 for the first DM). The register
addresses below are offsets from this base address.

Debug Module DMI Registers that are unimplemented or not mentioned in
the table below return 0 when read. Writing them has no effect.

[[]]
.Debug Module Debug Bus Registers
[%autowidth,float="center",align="center",cols=">,<,<",options="header"]
|===
|Address |Name |Page
|0x04 |Abstract Data 0 (`data0`) |<<data0>>
|0x05 |Abstract Data 1 (`data1`) |
|0x06 |Abstract Data 2 (`data2`) |
|0x07 |Abstract Data 3 (`data3`) |
|0x08 |Abstract Data 4 (`data4`) |
|0x09 |Abstract Data 5 (`data5`) |
|0x0a |Abstract Data 6 (`data6`) |
|0x0b |Abstract Data 7 (`data7`) |
|0x0c |Abstract Data 8 (`data8`) |
|0x0d |Abstract Data 9 (`data9`) |
|0x0e |Abstract Data 10 (`data10`) |
|0x0f |Abstract Data 11 (`data11`) |
|0x10 |Debug Module Control (`dmcontrol`) |<<dmcontrol>>
|0x11 |Debug Module Status (`dmstatus`) |<<dmstatus>>
|0x12 |Hart Info (`hartinfo`) |<<hartinfo>>
|0x13 |Halt Summary 1 (`haltsum1`) |
|0x14 |Hart Array Window Select (`hawindowsel`) |
|0x15 |Hart Array Window (`hawindow`) |
|0x16 |Abstract Control and Status (`abstractcs`) |
|0x17 |Abstract Command (`command`) |
|0x18 |Abstract Command Autoexec (`abstractauto`) |
|0x19 |Configuration Structure Pointer 0 (`confstrptr0`) |<<confstrptr0>>
|0x1a |Configuration Structure Pointer 1 (`confstrptr1`) |<<confstrptr1>>
|0x1b |Configuration Structure Pointer 2 (`confstrptr2`) |<<confstrptr2>>
|0x1c |Configuration Structure Pointer 3 (`confstrptr3`) |<<confstrptr3>>
|0x1d |Next Debug Module (`nextdm`) |<<nextdm>>
|0x1f |Custom Features (`custom`) |<<custom>>
|0x20 |Program Buffer 0 (`progbuf0`) |<<progbuf0>>
|0x21 |Program Buffer 1 (`progbuf1`) |
|0x22 |Program Buffer 2 (`progbuf2`) |
|0x23 |Program Buffer 3 (`progbuf3`) |
|0x24 |Program Buffer 4 (`progbuf4`) |
|0x25 |Program Buffer 5 (`progbuf5`) |
|0x26 |Program Buffer 6 (`progbuf6`) |
|0x27 |Program Buffer 7 (`progbuf7`) |
|0x28 |Program Buffer 8 (`progbuf8`) |
|0x29 |Program Buffer 9 (`progbuf9`) |
|0x2a |Program Buffer 10 (`progbuf10`) |
|0x2b |Program Buffer 11 (`progbuf11`) |
|0x2c |Program Buffer 12 (`progbuf12`) |
|0x2d |Program Buffer 13 (`progbuf13`) |
|0x2e |Program Buffer 14 (`progbuf14`) |
|0x2f |Program Buffer 15 (`progbuf15`) |
|0x30 |Authentication Data (`authdata`) |<<authdata>>
|0x32 |Debug Module Control and Status 2 (`dmcs2`) |<<dmcs2>>
|0x34 |Halt Summary 2 (`haltsum2`) |<<haltsum2>>
|0x35 |Halt Summary 3 (`haltsum3`) |<<haltsum3>>
|0x37 |System Bus Address 127:96 (`sbaddress3`) |<<sbaddress3>>
|0x38 |System Bus Access Control and Status (`sbcs`) |<<sbcs>>
|0x39 |System Bus Address 31:0 (`sbaddress0`) |<<sbaddress0>>
|0x3a |System Bus Address 63:32 (`sbaddress1`) |<<sbaddress1>>
|0x3b |System Bus Address 95:64 (`sbaddress2`) |<<sbaddress2>>
|0x3c |System Bus Data 31:0 (`sbdata0`) |<<sbdata0>>
|0x3d |System Bus Data 63:32 (`sbdata1`) |<<sbdata1>>
|0x3e |System Bus Data 95:64 (`sbdata2`) |<<sbdata2>>
|0x3f |System Bus Data 127:96 (`sbdata3`) |<<sbdata3>>
|0x40 |Halt Summary 0 (`haltsum0`) |<<haltsum0>>
|0x70 |Custom Features 0 (`custom0`) |<<custom0>>
|0x71 |Custom Features 1 (`custom1`) |
|0x72 |Custom Features 2 (`custom2`) |
|0x73 |Custom Features 3 (`custom3`) |
|0x74 |Custom Features 4 (`custom4`) |
|0x75 |Custom Features 5 (`custom5`) |
|0x76 |Custom Features 6 (`custom6`) |
|0x77 |Custom Features 7 (`custom7`) |
|0x78 |Custom Features 8 (`custom8`) |
|0x79 |Custom Features 9 (`custom9`) |
|0x7a |Custom Features 10 (`custom10`) |
|0x7b |Custom Features 11 (`custom11`) |
|0x7c |Custom Features 12 (`custom12`) |
|0x7d |Custom Features 13 (`custom13`) |
|0x7e |Custom Features 14 (`custom14`) |
|0x7f |Custom Features 15 (`custom15`) |
|===

==== Debug Module Status ([[status]]`dmstatus`, at 0x11)

This register reports status for the overall Debug
Module as well as the currently selected harts, as defined in <<hasel>>. Its
address will not change in the future, because it contains <<version>>.

This entire register is read-only.

*FIXME: register diagram goes here*

[[statusVersion]]
[align="center",float="center",cols="<2,<3,^1,<1",options="header"]
|===
|Field |Description |Access |Reset
|[[statusNdmresetpending]] `ndmresetpending`
|0 (false): Unimplemented, or <<ndmreset>> is zero and no ndmreset is currently in progress. +
1 (true): <<ndmreset>> is currently nonzero, or there is an ndmreset in progress.
|R |-
|[[statusStickyunavail]] `stickyunavail`
|0 (current): The per-hart `unavail` bits reflect the current state of
the hart. +
1 (sticky): The per-hart `unavail` bits are sticky. Once they are set,
they will not clear until the debugger acknowledges them using <<ackunavail>>.
|R |Preset
|[[statusImpebreak]] `impebreak`
|If 1, then there is an implicit `ebreak` instruction at the non-existent
word immediately after the Program Buffer. This saves the debugger from
having to write the `ebreak` itself, and allows the Program Buffer to be
one word smaller. +
This must be 1 when <<progbufsize>> is 1.
|R |Preset
|[[statusAllhavereset]] `allhavereset`
|This field is 1 when all currently selected harts have been reset and reset has not been acknowledged for any of them.
|R |-
|[[statusAnyhavereset]] `anyhavereset`
|This field is 1 when at least one currently selected hart has been reset and reset has not been acknowledged for that hart.
|R |-
|[[statusAllresumeack]] `allresumeack`
|This field is 1 when all currently selected harts have their resume ack bit set.
|R |-
|[[statusAnyresumeack]] `anyresumeack`
|This field is 1 when any currently selected hart has its resume ack bit set.
|R |-
|[[statusAllnonexistent]] `allnonexistent`
|This field is 1 when all currently selected harts do not exist in this hardware platform.
|R|-
|[[statusAnynonexistent]] `anynonexistent`
|This field is 1 when any currently selected hart does not exist in this hardware platform.
|R|-
|[[statusAllunavail]] `allunavail`
|This field is 1 when all currently selected harts are unavailable, or (if <<stickyunavail>> is 1) were unavailable without that being acknowledged.
|R |-
|[[statusAnyunavail]] `anyunavail`
|This field is 1 when any currently selected hart is unavailable, or (if <<stickyunavail>> is 1) was unavailable without that being acknowledged.
|R |-
|[[statusAllrunning]] `allrunning`
|This field is 1 when all currently selected harts are running.
|R |-
|[[statusAnyrunning]] `anyrunning`
|This field is 1 when any currently selected hart is running.
|R |-
|[[statusAllhalted]] `allhalted`
|This field is 1 when all currently selected harts are halted.
|R |-
|[[statusAnyhalted]] `anyhalted`
|This field is 1 when any currently selected hart is halted.
|R |-
|[[statusAuthenticated]] `authenticated`
|0 (false): Authentication is required before using the DM. +
1 (true): The authentication check has passed. +
On components that don't implement authentication, this bit must be
preset as 1.
|R |Preset
|[[statusAuthbusy]] `authbusy`
|0 (ready): The authentication module is ready to process the next
read/write to <<authdata>>. +
1 (busy): The authentication module is busy. Accessing <<authdata>> results in
unspecified behavior. +
<<authbusy>> only becomes set in immediate response to an access to <<authdata>>.
|R |0
|[[statusHasresethaltreq]] `hasresethaltreq`
|1 if this Debug Module supports halt-on-reset functionality controllable by the <<setresethaltreq>> and <<clrresethaltreq>> bits. 0 otherwise.
|R |Preset
|[[statusConfstrptrvalid]] `confstrptrvalid`
|0 (invalid): <<confstrptr0>>-<<confstrptr3>> hold information which is not relevant to the configuration structure. +
1 (valid): <<confstrptr0>>-<<confstrptr3>> hold the address of the configuration structure.
|R |Preset
|`version`
|0 (none): There is no Debug Module present. +
1 (0.11): There is a Debug Module and it conforms to version 0.11 of
this specification. +
2 (0.13): There is a Debug Module and it conforms to version 0.13 of
this specification. +
3 (1.0): There is a Debug Module and it conforms to version 1.0 of this
specification. +
15 (custom): There is a Debug Module but it does not conform to any
available version of this spec.
|R |3
|===

==== Debug Module Control (`dmcontrol`, at 0x10)

[[control]]
This register controls the overall Debug Module as well as the currently selected harts, as defined in <<hasel>>.

[[hartsel]]
Throughout this document we refer to <<hartsel>>, which is <<hartselhi>> combined with <<hartsello>>. While the spec allows for 20 <<hartsel>> bits, an implementation may choose
to implement fewer than that. The actual width of <<hartsel>> is called
`HARTSELLEN`. It must be at least 0 and at most 20. A debugger should
discover `HARTSELLEN` by writing all ones to <<hartsel>> (assuming the maximum size)
and reading back the value to see which bits were actually set.
Debuggers must not change <<hartsel>> while an abstract command is executing.

[NOTE]
====
There are separate <<setresethaltreq>> and <<clrresethaltreq>> bits so that it is possible to write <<dmcontroll>> without
changing the halt-on-reset request bit for each selected hart, when not
all selected harts have the same configuration.
====

On any given write, a debugger may only write 1 to at most one of the
following bits: <<resumereq>>, <<hartreset>>, <<ackhavereset>>, <<setresethaltreq>>, and <<clrresethaltreq>>. The others must be written 0.

[[resethaltreq]]
<<resethaltreq>> is an optional internal bit of per-hart state that
cannot be read, but can be written with <<setresethaltreq>> and <<clrresethaltreq>>.

[[keepalive]]
<<heepalive>> is an optional internal bit of per-hart state. When it is
set, it suggests that the hardware should attempt to keep the hart
available for the debugger, e.g. by keeping it from entering a low-power
state once powered on. Even if the bit is implemented, hardware might
not be able to keep a hart available. The bit is written through <<setkeepalive>> and <<clrkeepalive>>.

For forward compatibility, <<version>> will always be readable when bit 1 (<<ndmreset>>) is 0 and bit 0 (<<dmactive>>) is 1.

*FIXME: Register diagram goes here.*

[[controlDmactive]]
[align="center",float="center",cols="<2,<3,^1,<1",options="header",]
|===
|Field |Description |Access |Reset
|[[controlHaltreq]] `haltreq`
|Writing 0 clears the halt request bit for all currently selected harts.
This may cancel outstanding halt requests for those harts. +
Writing 1 sets the halt request bit for all currently selected harts.
Running harts will halt whenever their halt request bit is set. +
Writes apply to the new value of <<hartsell>> and <<hasel>>.
|WARZ |-
|[[controlResumereq]] `resumereq`
|Writing 1 causes the currently selected harts to resume once, if they
are halted when the write occurs. It also clears the resume ack bit for
those harts. +
<<resumereq>> is ignored if <<haltreq>> is set. +
Writes apply to the new value of <<hartsel>> and >>hasel>>.
|W1 |-
|[[controlHartreset]] `hartreset`
|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. +
While this bit is 1, the debugger must not change which harts are
selected. +
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 <<hartsel>> and <<hasel>>.
|WARL |0
|[[controlAckhavereset]] `ackhavereset`
|0 (nop): No effect. +
1 (ack): Clears `havereset` for any selected harts. +
Writes apply to the new value of <<hartsel>> and <<hasel>>.
|W1 |-
|[[controlAckunavail]] `ackunavail`
|0 (nop): No effect. +
1 (ack): Clears `unavail` for any selected harts that are currently
available. +
Writes apply to the new value of <<hartsel>> and <<hasel>>.
|W1 |-
|[[controlHasel]] `hasel`
|Selects the definition of currently selected harts. +
0 (single): There is a single currently selected hart, that is selected
by <<hartsel>>. +
1 (multiple): There may be multiple currently selected harts - the hart
selected by <<hartsel>>, 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.
|WARL |0
|[[controlHartsello]] `hartsello`
|The low 10 bits of <<hartsel>>: the DM-specific index of the hart to select. This hart is always part of the currently selected harts. 
|WARL |0
|[[controlHartselhi]] `hartselhi`
|The high 10 bits of <<hartsel>>: the DM-specific index of the hart to  select. This hart is always part of the currently selected harts.
|WARL |0
|[[controlSetkeepalive]] `setkeepalive`
|This optional field sets <<heepalive>> for all currently selected harts, unless <<clrkeepalive>> is simultaneously set to 1. +
Writes apply to the new value of <<hartsel>> and <<hasel>>.
|W1 |-
|[[controlClrkeepalive]] `clrkeepalive`
|This optional field clears <<keepalive>> for all currently selected harts. +
Writes apply to the new value of <<hartsel>> and <<hasel>>.
|W1 |-
|[[controlSetresethaltreq]] `setresethaltreq`
|This optional field writes the halt-on-reset request bit for all
currently selected harts, unless <<clrresethaltreq>> is simultaneously set to 1. 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 <<clrresethaltreq>> to clear it. +
Writes apply to the new value of <<hartsel>> and <<hasel>>. +
If <<hasresethaltreq>> is 0, this field is not implemented.
|W1 |-
|[[controlClrresethaltreq]] `clrresethaltreq`
|This optional field clears the halt-on-reset request bit for all
currently selected harts. +
Writes apply to the new value of <<hartsel>> and <<hasel>>.
|W1 |-
|[[controlNdmreset]] `ndmreset`
|This bit controls the reset signal from the DM to the rest of the hardware platform. The signal should reset every part of the hardware platform, including every hart,
except for the DM and any logic required to access the DM. To perform a
hardware platform reset the debugger writes 1, and then writes 0 to
deassert the reset. 
|R/W |0
|`dmactive`
|This bit serves as a reset signal for the Debug Module itself. After
changing the value of this bit, the debugger must poll <<dmcontrol>> until <<dmactive>> has taken
the requested value before performing any action that assumes the
requested <<dmactive>> state change has completed. Hardware may take an arbitrarily
long time to complete activation or deactivation and will indicate
completion by setting <<dmactive>> to the requested value. +
0 (inactive): The module's state, including authentication mechanism,
takes its reset values (the <<dmactive>> bit is the only bit which can be written to
something other than its reset value). Any accesses to the module may
fail. Specifically, <<version>> might not return correct data. +
1 (active): The module functions normally. +
No other mechanism should exist that may result in resetting the Debug
Module after power up.  To place the Debug Module into a known state, a debugger may write 0 to <<dmactive>>, poll until <<dmactive>> is observed 0, write 1 to <<dmactive>>, and poll <<dmactive>> until is observed 1. +
Implementations may pay attention to this bit to further aid debugging,
for example by preventing the Debug Module from being power gated while
debugging is active.
|R/W |0
|===

==== Hart Info (`hartinfo`, at 0x12)

[[Hartinfo]]
This register gives information about the hart currently
selected by <<hartsel>>.

This register is optional. If it is not present it should read all-zero.

If this register is included, the debugger can do more with the Program
Buffer by writing programs which explicitly access the `data` and/or
`dscratch` registers.

This entire register is read-only.

*FIXME: Register diagram goes here*

[[HartinfoDataaddr]]
[float="center",align="center",cols="<2,<3,^1,<1",options="header"]
|===
|Field |Description |Access |Reset
|[[HartinfoNscratch]] `nscratch`
|Number of `dscratch` registers available for the debugger to use during program buffer execution, starting from <<dscratch0>>. The debugger can make no assumptions about the contents of these registers between commands.
|R |Preset
|[[HartinfoDataaccess]] `dataaccess`
|0 (csr): The `data` registers are shadowed in the hart by CSRs. Each CSR
is DXLEN bits in size, and corresponds to a single argument, per
<<datareg>>. +
1 (memory): The `data` registers are shadowed in the hart's memory map.
Each register takes up 4 bytes in the memory map.
|R |Preset
|[[HartinfoDatasize]] `datasize`
|If <<dataaccess>> is 0: Number of CSRs dedicated to shadowing the `data` registers. +
If <<dataaccess>> is 1: Number of 32-bit words in the memory map dedicated to shadowing the `data` registers. +
If this value is non-zero, then the tt data registers must be
traditional registers and not MRs.
Since there are at most 12 `data` registers, the value in this register
must be 12 or smaller.
|R |Preset
|`dataaddr`
|If <<dataaccess>> is 0: The number of the first CSR dedicated to shadowing the `data` registers. +
If <<dataaccess>> is 1: Address of RAM where the data registers are shadowed. This address is sign extended giving a range of -2048 to 2047, easily
addressed with a load or store using as the address register.
|R |Preset
|===

==== Hart Array Window Select (`hawindowsel`, at 0x14)

[[hawindowsel, hawindowsel]]
This register selects which of the 32-bit portion of the hart array mask register (see <<hartarraymask>>) is accessible in <<hawindow>>.

*FIXME: Register diagram goes here*

[float="center",align="center",cols="<2,<3,^1,<1",options="header"]
|===
|Field |Description |Access |Reset
|`hawindowsel`
|The high bits of this field may be tied to 0, depending on how large the array mask register is. E.g. on a hardware platform with 48 harts only bit 0 of this field may actually be writable. 
|WARL |0
|===

==== Hart Array Window (`hawindow`, at 0x15)

[[hawindow, hawindow]]
This register provides R/W access to a 32-bit portion of
the hart array mask register (see <<hartarraymask>>).
The position of the window is determined by <<hawindowsel>>. I.e. bit 0 refers to hart latexmath:[$\hawindowsel * 32$], while bit 31 refers to hart
latexmath:[$\hawindowsel * 32 + 31$].

Since some bits in the hart array mask register may be constant 0, some
bits in this register may be constant 0, depending on the current value
of <<hawindowsel>>.

*FIXME: Register diagram goes here.*

==== Abstract Control and Status (`abstractcs`, at 0x16)

[[abstractcs, abstractcs]]
Writing this register while an abstract command is executing causes <<cmderr>> to become 1 (busy) once the command completes (busy
becomes 0).

[NOTE]
====
<<datacount>> must be at least 1 to support RV32 harts, 2 to support RV64 harts, or 4 to support RV128 harts.
====
*FIXME: Register diagram goes here.*

[[abstractcsdatacount, abstractdatacount]]
[align="center",float="center",cols="<2,<3,^1,^1",options="header"]
|===
|Field |Description |Access |Reset
|[[abstractcsprogbufsize]] `progbufsize`
|Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16.
|R |Preset
|[[abstractcsbusy]] `busy` 
|0 (ready): There is no abstract command currently being executed. +
1 (busy): An abstract command is currently being executed. +
This bit is set as soon as <<command>> is written, and is not cleared until that command has completed.
|R |0
|[[abstractcsrelaxedpriv]] `relaxedpriv` 
|This optional bit controls whether program buffer and abstract memory
accesses are performed with the exact and full set of permission checks
that apply based on the current architectural state of the hart
performing the access, or with a relaxed set of permission checks (e.g.
PMP restrictions are ignored). The details of the latter are
implementation-specific. +
0 (full checks): Full permission checks apply. +
1 (relaxed checks): Relaxed permission checks apply.
|WARL |Preset
|[[abstractcscmderr]] `cmderr` 
|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. +
This field only contains a valid value if <<busy>> is 0. +
0 (none): No error. +
1 (busy): An abstract command was executing while <<command>>, <<abstractcs>>, or <<abstractauto>> was written, or
when one of the `data` or `progbuf` registers was read or written. This
status is only written if <<cmderr>> contains 0. +
2 (not supported): The command in <<command>> is not supported. It may be supported
with different options set, but it will not be supported at a later time
when the hart or system state are different. +
3 (exception): An exception occurred while executing the command
(e.g. 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), or unavailable. +
5 (bus): The abstract command failed due to a bus error (e.g. alignment,
access size, or timeout). +
6 (reserved): Reserved for future use. +
7 (other): The command failed for another reason.
|R/W1C |0
|`datacount` |Number of `data` registers that are implemented as part
of the abstract command interface. Valid sizes are 1 - 12.
|R |Preset
|===

==== Abstract Command (`command`, at 0x17)

[[command,command]]
Writes to this register cause the corresponding abstract
command to be executed.

Writing this register while an abstract command is executing causes <<cmderr>> to become 1 (busy) once the command completes (busy becomes 0).

If <<cmderr>> is non-zero, writes to this register are ignored.

[NOTE]
====
<<cmderr>> inhibits starting a new command to accommodate debuggers that, for
performance reasons, send several commands to be executed in a row
without checking <<cmderr>> in between. They can safely do so and check <<cmderr>> at the end without worrying that one command failed but then a later command (which might have depended on the previous one succeeding) passed.
====
*FIXME: Register diagram goes here.*

[[commandcontrol, commandcontrol]]
[cols="<,<,^,<",options="header",]
|===
|Field |Description |Access ^|Reset
|[[commandcmdtype,commandcmdtype]] `cmdtype`
|The type determines the overall functionality of this abstract command.
|WARZ |0
|`control` |This field is interpreted in a command-specific manner,
described for each abstract command. 
|WARZ |0
|===

==== Abstract Command Autoexec (`abstractauto`, at 0x18)

[[abstractauto,abstractauto]]
This register is optional. Including it allows more efficient burst accesses. A debugger can detect whether it is supported by setting bits and reading them back.

If this register is implemented then bits corresponding to implemented
progbuf and data registers must be writable. Other bits must be
hard-wired to 0.

If this register is written while an abstract command is executing then
the write is ignored and becomes 1 (busy) once the command completes
(busy becomes 0).

*FIXME: Register diagram goes here.*

[[abstractautoautoexecdata,abstractautoautoexecdata]]
[align="center",float="center",cols="<2,<3,^1,<1",options="header",]
|===
|Field |Description |Access ^|Reset
|[[abstractautoautoexecprogbuf,abstractautoautoexecprogbuf]] `autoexecprogbuf` 
|When a bit in this field is 1, read or write accesses to the corresponding `progbuf` word cause the DM to act as if the current value in <<command>> was written there again after the access to `progbuf` completes. 
|WARL |0
|`autoexecdata`
|When a bit in this field is 1, read or write accesses
to the corresponding `data` word cause the DM to act as if the current
value in <<command>> was written there again after the access to `data` completes.
|WARL |0
|===

==== Configuration Structure Pointer 0 (`confstrptr0`, at 0x19)

[[confstrptrzero,confstrptrzero]]
When <<confstrptrvalid>> is set, reading this register returns bits
31:0 of the configuration structure pointer. Reading the other
`confstrptr` registers returns the upper bits of the address.

When system bus access is implemented, this must be an address that can
be used with the System Bus Access module. Otherwise, this must be an
address that can be used to access the configuration structure from the
hart with ID 0.

If <<confstrptrvalid>> is 0, then the `confstrptr` registers hold identifier information which is not further specified in this document.

The configuration structure itself is a data structure of the same
format as the data structure pointed to by mconfigptr as described in
the Privileged Spec.

This entire register is read-only.

*FIXME: Register diagram goes here.*

==== Configuration Structure Pointer 1 (`confstrptr1`, at 0x1a)

[[confstrptrone,confstrptrone]]
When <<confstrptrvalid>> is set, reading this register returns bits
63:32 of the configuration structure pointer. See <<confstrptr0>> for more details.

This entire register is read-only.

*FIXME:Register diagram goes here.*

==== Configuration Structure Pointer 2 (`confstrptr2`, at 0x1b)

[[confstrptrtwo,confstrptrtwo]]
When <<confstrptrvalid>> is set, reading this register returns bits
95:64 of the configuration structure pointer. See <<confstrptr0>> for more details.

This entire register is read-only.

*FIXME: Register diagram goes here.*

==== Configuration Structure Pointer 3 (`confstrptr3`, at 0x1c)

[[confstrptrthree,confstrptrthree]]
When <<confstrptrvalid>> is set, reading this register returns bits
127:96 of the configuration structure pointer. See <<confstrptr0>> for more details.

This entire register is read-only.

*FIXME:Register diagram goes here.*

==== Next Debug Module (`nextdm`, at 0x1d)

[[nextdm,nextdm]]
If there is more than one DM accessible on this DMI, this
register contains the base address of the next one in the chain, or 0 if
this is the last one in the chain.

This entire register is read-only.

*FIXME:Register diagram goes here.*

==== Abstract Data 0 (`data0`, at 0x04)

[[datazero,datazero]]
<<datazero>> through `data11` are registers that may be read or
changed by abstract commands. <<datacount>> indicates how many of them are
implemented, starting at <<datazero>>, counting up.
<<datareg>> shows how abstract commands use these registers.

Accessing these registers while an abstract command is executing causes <<cmderr>> to be set to 1 (busy) if it is 0.

Attempts to write them while <<busy>> is set does not change their value.

The values in these registers might not be preserved after an abstract
command is executed. The only guarantees on their contents are the ones
offered by the command in question. If the command fails, no assumptions
can be made about the contents of these registers.

*FIXME:Register diagram goes here.*

==== Program Buffer 0 (`progbuf0`, at 0x20)

[[progbufzero,progbufzero]] through 'progbuf15' must provide write access to the optional program buffer. It may also be possible for the debugger to read from the program buffer through these registers. If reading is not supported,
then all reads return 0.

<<progbufsize>> indicates how many `progbuf` registers are implemented starting at <<progbuf0>>, counting up.

Accessing these registers while an abstract command is executing causes
<<cmderr>> to be set to 1 (busy) if it is 0.

Attempts to write them while <<busy>> is set does not change their value.

*FIXME:Register diagram goes here.*

==== Authentication Data (`authdata`, at 0x30)

[[authdata,authdata]]
This register serves as a 32-bit serial port to/from the authentication module.

When <<authbusy>> is clear, the debugger can communicate with the authentication module by reading or writing this register. There is no separate mechanism to signal overflow/underflow.

*FIXME:Register diagram goes here.*

==== Debug Module Control and Status 2 (`dmcs2`, at 0x32)

[[dmcstwo,dmcstwo]]
This register contains DM control and status bits that
didn’t easily fit in <<dmcontrol>> and <<dmstatus>>. All are optional.

If halt groups are not implemented, then <<group>> will always be 0 when <<grouptype>> is 0.

If resume groups are not implemented, then <<grouptype>> will remain 0 even after 1 is written there.

The DM external triggers available to add to halt groups may be the same
as or distinct from the DM external triggers available to add to resume
groups.

*FIXME:Register diagram goes here.*

[[cstwohgselect,cstwohgselect]]
[float="center",align="center",cols="<2,<3,^1,<1",options="header"]
|===
|Field |Description |Access |Reset
|[[dmcstwogrouptype]] `grouptype` 
|0 (halt): The remaining fields in this register configure halt groups. +
1 (resume): The remaining fields in this register configure resume groups.
|WARL |0
|[[dmcstwodmexttrigger]] `dmexttrigger` 
|This field contains the currently selected DM external trigger. +
If a non-existent trigger value is written here, the hardware will
change it to a valid one or 0 if no DM external triggers exist.
|WARL |0
|[[dmcstwogroup]] `group` 
|When <<hgselect>> is 0, contains the group of the hart specified by <<hartsel>>. +
When <<hgselect>> is 1, contains the group of the DM external trigger selected by <<dmexttrigger>>. +
The value written to this field is ignored unless <<hgwrite>> is also written 1. +
Group numbers are contiguous starting at 0, with the highest number
being implementation-dependent, and possibly different between different
group types. Debuggers should read back this field after writing to
confirm they are using a hart group that is supported. +
If groups aren't implemented, then this entire field is 0.
|WARL |preset
|[[dmcstwohgwrite,dmcstwohgwrite]] `hgwrite` 
|When 1 is written and <<hgselect>> is 0, for every selected hart the DM will change its group to the value written to <<group>>, if the hardware supports that group for that hart. Implementations may also change the group of a minimal set of unselected harts in the same way, if that is necessary due to a
hardware limitation. +
When 1 is written and <<hgselect>> is 1, the DM will change the group of the DM external trigger selected by <<dmexttrigger>> to the value written to <<group>>, if the hardware supports that group for that trigger. +
Writing 0 has no effect.
|W1 |-
|`hgselect` 
|0 (harts): Operate on harts. +
1 (triggers): Operate on DM external triggers. +
If there are no DM external triggers, this field must be tied to 0.
|WARL |0
|===

==== Halt Summary 0 (`haltsum0`, at 0x40)

[[haltsumzero,haltsumzero]]
Each bit in this read-only register indicates whether one specific hart is halted or not. Unavailable/nonexistent harts are not considered to be halted.

This register might not be present if fewer than 2 harts are connected
to this DM.

The LSB reflects the halt status of hart {hartsel[19:5],5’h0}, and the
MSB reflects halt status of hart {hartsel[19:5],5’h1f}.

This entire register is read-only.

*FIXME:Register diagram goes here.*

==== Halt Summary 1 (`haltsum1`, at 0x13)

[[haltsumone,haltsumone]]
Each bit in this read-only register indicates whether any of a group of harts is halted or not. Unavailable/nonexistent harts are not considered to be halted.

This register might not be present if fewer than 33 harts are connected
to this DM.

The LSB reflects the halt status of harts {hartsel[19:10],10’h0}
through {hartsel[19:10],10’h1f}. The MSB reflects the halt status of
harts {hartsel[19:10],10’h3e0} through {hartsel[19:10],10’h3ff}.

This entire register is read-only.

*FIXME:Register diagram goes here.*

==== Halt Summary 2 (`haltsum2`, at 0x34)

[[haltsumtwo,haltsumtwo]] 
Each bit in this read-only register indicates whether
any of a group of harts is halted or not. Unavailable/nonexistent harts
are not considered to be halted.

This register might not be present if fewer than 1025 harts are
connected to this DM.

The LSB reflects the halt status of harts {hartsel[19:15],15’h0}
through {hartsel[19:15],15’h3ff}. The MSB reflects the halt status of
harts {hartsel[19:15],15’h7c00} through {hartsel[19:15],15’h7fff}.

This entire register is read-only.

*FIXME:Register diagram goes here.*

==== Halt Summary 3 (`haltsum3`, at 0x35)

[[haltsumthree,haltsumthree]] 
Each bit in this read-only register indicates
whether any of a group of harts is halted or not.
Unavailable/nonexistent harts are not considered to be halted.

This register might not be present if fewer than 32769 harts are
connected to this DM.

The LSB reflects the halt status of harts 20’h0 through 20’h7fff. The
MSB reflects the halt status of harts 20’hf8000 through 20’hfffff.

This entire register is read-only.

*FIXME:Register diagram goes here.*

==== System Bus Access Control and Status (`sbcs`, at 0x38)

[[sbcs,sbcs]]

*FIXME:Register diagram goes here.*

[[sbcssbaccesseight,sbcssbaccesseight]]
[float="center",align="center",cols="<2,<3,^1,<1",options="header"]
|===
|Field |Description |Access |Reset
|[[sbcssbversion,sbcssbversion]] `sbversion` 
|0 (legacy): The System Bus interface conforms to mainline drafts of this
spec older than 1 January, 2018. +
1 (1.0): The System Bus interface conforms to this version of the spec. +
Other values are reserved for future versions.
|R |1
|[[sbcssbbusyerror,sbcssbbusyerror]] `sbbusyerror` 
|Set when the debugger attempts to read data while a read is in progress,
or when the debugger initiates a new access while one is already in
progress (while <<sbbusy>> is set). It remains set until it's explicitly cleared by the debugger. +
While this field is set, no more system bus accesses can be initiated by
the Debug Module.
|R/W1C |0
|[[sbcssbbusy,sbcssbbusy]] `sbbusy` 
|When 1, indicates the system bus manager is busy. (Whether the system
bus itself is busy is related, but not the same thing.) This bit goes
high immediately when a read or write is requested for any reason, and
does not go low until the access is fully completed. +
Writes to <<sbcs>> while <<sbbusy>> is high resulting in undefined behavior. A debugger must not write to <<sbcs>> until it reads <<sbbusy>> as 0.
|R |0
|[[sbcssbreadonaddr,sbcssbreadonaddr]] `sbreadonaddr` 
|When 1, every write to <<sbaddress0>> automatically triggers a system bus read at the new address. 
|R/W |0
|[[sbcssbaccess,sbcssbaccess]] `sbaccess` 
|Select the access size to use for system bus accesses. +
0 (8bit): 8-bit +
1 (16bit): 16-bit +
2 (32bit): 32-bit +
3 (64bit): 64-bit +
4 (128bit): 128-bit +
If <<sbaccess>> has an unsupported value when the DM starts a bus access, the access is not performed and <<sberror>> is set to 4.
|R/W |2
|[[sbcssbautoincrement,sbcssbautoincrement]] `sbautoincrement` 
|When 1, `sbaddress` is incremented by the access size (in bytes) selected in after every system bus access.
 |R/W |0
|[[sbcssbreadondata,sbcssbreadondata]] `sbreadondata` 
|When 1, every read from ,,sbdata0>> automatically triggers a system bus read at the (possibly auto-incremented) address.
|R/W |0
|[[sbcssberror,sbcssberror]] `sberror` 
|When the Debug Module's system bus manager encounters an error, this
field gets set. The bits in this field remain set until they are cleared
by writing 1 to them. While this field is non-zero, no more system bus
accesses can be initiated by the Debug Module. +
An implementation may report "Other" (7) for any error condition. +
0 (none): There was no bus error. +
1 (timeout): There was a timeout. +
2 (address): A bad address was accessed. +
3 (alignment): There was an alignment error. +
4 (size): An access of unsupported size was requested. +
7 (other): Other. 
|R/W1C |0
|[[sbcssbasize,sbcssbasize]] `sbasize` 
|Width of system bus addresses in bits. (0 indicates there is no bus access support.) 
|R |Preset
|[[sbcssbaccessonetwentyeight,sbcssbaccessonetwentyeight]] `sbaccess128` 
|1 when 128-bit system bus accesses are supported.
|R |Preset
|[[sbcssbaccesssixtyfour,sbcssbaccessonetwentyeight]] `sbaccess64`
|1 when 64-bit system bus accesses are supported.
|R |Preset
|[[sbcssbaccessthirtytwo,sbcssbaccessthirtytwo]] `sbaccess32`
|1 when 32-bit system bus accesses are supported.
|R |Preset
|[[sbcssbaccesssixteen,sbcssbaccesssixteen]] `sbaccess16`
|1 when 16-bit system bus accesses are supported.
|R |Preset
|`sbaccess8`
|1 when 8-bit system bus accesses are supported.
|R |Preset
|===

==== System Bus Address 31:0 (`sbaddress0`, at 0x39)

[[sbaddresszero,sbaddresszero]]
If <<sbasize>> is 0, then this register is not present.
When the system bus manager is busy, writes to this register will set <<sbbusyerror>> and don't do anything else.
If <<sberror>> is 0, <<sbbusyerror>> is 0, and <<sbreadonaddr>> is set then writes to this register start the following:

. Set <<sbbusy>>.
. Perform a bus read from the new value of `sbaddress`.
. If the read succeeded and <<sbautoincrement>> is set, increment `sbaddress`.
. Clear <<sbbusy>>.

*FIXME: Register diagram goes here.*

[[sbaddresszeroaddress,sbaddresszeroaddress]]
[%autowidth,float="center",align="center",cols="<,<,^,<",options="header"]
|===
|Field |Description |Access |Reset
|`address` |Accesses bits 31:0 of the physical address in `sbaddress`.
|R/W |0
|===

==== System Bus Address 63:32 (`sbaddress1`, at 0x3a)

[[sbaddressone,sbaddressone]]
If <<sbasize>> is less than 33, then this register is not present.

When the system bus manager is busy, writes to this register will set <<sbbusyerror>> and don't do anything else.

*FIXME:Register diagram goes here.*

[[sbaddressoneaddress,sbaddressoneaddress]]
[%autowidth,float="center,align="center",cols="<,<,^,<",options="header"]
|===
|Field |Description |Access |Reset
|`address` |Accesses bits 63:32 of the physical address in `sbaddress`
(if the system address bus is that wide).
|R/W |0
|===

==== System Bus Address 95:64 (`sbaddress2`, at 0x3b)

[[sbaddresstwo,sbaddresstwo]] If <<sbasize>> is less than 65, then this register is not present.

When the system bus manager is busy, writes to this register will set <<sbbusyerror>> and don't do anything else.

*FIXME:Register diagram goes here.*

[[sbaddresstwoaddress,sbaddresstwoaddress]]
[%autowidth,float="center",align="center",cols="<,<,^,<",options="header"]
|===
|Field |Description |Access |Reset
|`address`
|Accesses bits 95:64 of the physical address in `sbaddress` (if the system address bus is that wide). 
|R/W |0
|===

==== System Bus Address 127:96 (`sbaddress3`, at 0x37)

[[sbaddressthree,sbaddressthree]]
If <<sbasize>> is less than 97, then this register is not present.

When the system bus manager is busy, writes to this register will set <<sbbusyerror>> and don't do anything else.

*FIXME:Register diagram goes here.*

[[sbaddressthreeaddress,sbaddressthreeaddress]]
[%autowidth,float="center",align="center",cols="<,<,^,<",options="header"]
|===
|Field |Description |Access |Reset
|`address` 
|Accesses bits 127:96 of the physical address in `sbaddress` (if the system address bus is that wide). 
|R/W |0
|===

==== System Bus Data 31:0 (`sbdata0`, at 0x3c)

[[sbdatazero,sbdatazero]] 
If all of the `sbaccess` bits in <<sbcs>> are 0, then this register is not present.

Any successful system bus read updates `sbdata`. If the width of the read access is less than the width of `sbdata`, the contents of the remaining high bits may take on any value.

If either <<sberror>> or <<sbbusyerror>> isn't 0 then accesses do nothing.

If the bus manager is busy then accesses set <<sbbusyerror>>, and don't do anything else.

Writes to this register start the following:

. Set <<sbbusy>>.
. Perform a bus write of the new value of `sbdata` to `sbaddress`.
. If the write succeeded and <<sbautoincrement>> is set, increment `sbaddress`.
. Clear <<sbbusy>>.

Reads from this register start the following:

. "Return" the data.
. Set <<sbbusy>>.
. If <<sbreadondata>> is set:
..Perform a system bus read from the address contained in `sbaddress`,
placing the result in `sbdata`.
.. If <<sbautoincrement>> is set and the read was successful, increment `sbaddress`.
. Clear <<sbbusy>>.

Only <<sbdata0>> has this behavior. The other `sbdata` registers have no side
effects. On systems that have buses wider than 32 bits, a debugger
should access <<sbdata0>> after accessing the other `sbdata` registers.

*FIXME: Register diagram goes here.*

[[sbdatazerodata,sbdatazerodata]]
[%autowidth,align="center",float="center",cols="<,<,^,<",options="header"]
|===
|Field |Description |Access |Reset
|`data` |Accesses bits 31:0 of `sbdata`. 
|R/W |0
|===

==== System Bus Data 63:32 (`sbdata1`, at 0x3d)

[[sbdataone,sbdataone]]
If <<sbaccess64>> and <<sbaccess128>> are 0, then this register is not present.

If the bus manager is busy then accesses set <<sbbusyerror>>, and don't do anything else.

*FIXME: Register diagram goes here.*

[[sbdataonedata,sbdataonedata]]
[%autowidth,align="center",float="center",cols="<,<,^,<",options="header"]
|===
|Field |Description |Access |Reset
|`data` |Accesses bits 63:32 of `sbdata` (if the system bus is that wide).
|R/W |0
|===

==== System Bus Data 95:64 (`sbdata2`, at 0x3e)

[[sbdatatwo,sbdatatwo]]
This register only exists if <<sbaccess128>> is 1.

If the bus manager is busy then accesses set <<sbbusyerror>>, and don't do anything else.

*FIXME:Register diagram goes here.*

[[sbdatatwodata,sbdatatwodata]]
[%autowidth,float="center",align="center",cols="<,<,^,<",options="header"]
|===
|Field |Description |Access |Reset
|`data` |Accesses bits 95:64 of `sbdata` (if the system bus is that wide). 
|R/W |0
|===

==== System Bus Data 127:96 (`sbdata3`, at 0x3f)

[[sbdatathree,sbdatathree]]
This register only exists if <<sbaccess128>> is 1.

If the bus manager is busy then accesses set <<sbbusyerror>>, and don't do anything else.

*FIXME:Register diagram goes here.*

[[sbdatathreedata,sbdatathreedata]]
[%autowidth,float="center",align="center",cols="<,<,^,<",options="header"]
|===
|Field |Description |Access |Reset
|`data` |Accesses bits 127:96 of `sbdata` (if the system bus is that wide).
|R/W |0
|===

==== Custom Features (`custom`, at 0x1f)

[[custom,custom,]]
This optional register may be used for non-standard features. Future version of the debug spec will not use this address.

==== Custom Features 0 (`custom0`, at 0x70)

[[customzero,customzero]]
The optional through registers may be used for non-standard features. Future versions of the debug spec will not use these addresses.
