\chapter{Sdtrig ISA Extension}
\label{sec:trigger}

This chapter describes the Sdtrig ISA extension, which can be implemented
independently of functionality described in the other chapters. It consists
exclusively of the Trigger Module (TM).

Triggers can cause a breakpoint exception, entry into Debug Mode, or a trace action
without having to execute a special instruction. This makes them invaluable
when debugging code from ROM. They can trigger on execution of instructions at
a given memory address, or on the address/data in loads/stores.

A hart can be compatible with this specification without implementing any
trigger functionality at all, but if it is implemented then it must conform to
this section.
Accessing trigger CSRs that are not used by any of the implemented triggers must
result in an illegal instruction exception. M-Mode and Debug Mode accesses to
trigger CSRs that are used by any of the implemented triggers must succeed,
regardless of the current type of the currently selected trigger.

A trigger matches when the conditions that it specifies (e.g. a load from a
specific address) are met. A trigger fires when a trigger that matches performs
the action configured for that trigger.

Triggers do not fire while in Debug Mode.

\section{Enumeration}

\begin{steps}{Each trigger may support a variety of features. A debugger can
    build a list of all triggers and their features as follows:}
\item Write 0 to \RcsrTselect. If this results in an illegal instruction
    exception, then there are no triggers implemented.
\item Read back \RcsrTselect and check that it contains the written value. If not,
    exit the loop.
\item Read \RcsrTinfo.
\item If that caused an exception, the debugger must read \RcsrTdataOne to
    discover the type. (If \FcsrTdataOneType is 0, this trigger doesn't exist. Exit the
    loop.)
\item If \FcsrTinfoInfo is 1, this trigger doesn't exist. Exit the loop.
\item Otherwise, the selected trigger supports the types discovered in \FcsrTinfoInfo.
\item Repeat, incrementing the value in \RcsrTselect.
\end{steps}

\begin{commentary}
    The above algorithm reads back \RcsrTselect so that implementations which have
    $2^n$ triggers only need to implement $n$ bits of \RcsrTselect.

    The algorithm checks \RcsrTinfo and \FcsrTdataOneType in case the implementation has $m$
    bits of \RcsrTselect but fewer than $2^m$ triggers.
\end{commentary}

\section{Actions}

Triggers can be configured to take one of several actions when they fire.
Table~\ref{tab:action} lists all options.

\begin{table}[H]
\centering
\caption{\FcsrMcontrolAction encoding}
\label{tab:action}
\begin{tabular}{|r|L|}
\hline
Value & Description \\
\hline
0 & Raise a breakpoint exception. (Used when software wants to use the
    trigger module without an external debugger attached.)  \Rxepc
    must contain the virtual address of the next instruction that must
    be executed to preserve the program flow. \\
\hline
1 & Enter Debug Mode.
    \RcsrDpc must contain the virtual address of the next instruction that must
    be executed to preserve the program flow.

    This action is only legal when the trigger's \FcsrTdataOneDmode is 1.
    Since the {\tt tdata} registers are WARL, hardware should clear the action
    field whenever the action field is 1, the new value of \FcsrTdataOneDmode would be 0, and the
    new value of the action field would be 1.

    This action can only be supported if Sdext is implemented on the hart.\\
\hline
2 & Trace on, described in the trace specification. \\
\hline
3 & Trace off, described in the trace specification. \\
\hline
4 & Trace notify, described in the trace specification. \\
\hline
5 & Reserved for use by the trace specification. \\
\hline
8 -- 9 & Send a signal to TM external trigger output 0 or 1 (respectively). \\
\hline
other & Reserved for future use. \\
\hline
\end{tabular}
\end{table}

\begin{commentary}
    Actions 8 and 9 are intended to increment custom event counters, but these
    signals could also be brought to outputs for use by external logic.
\end{commentary}

\section{Priority}

Table~\ref{tab:priority} lists the synchronous exceptions from the Privileged
Spec, and where the various types of triggers fit in. The first 3 columns come
from the Privileged Spec, and the final column shows where triggers fit in.
Priorities in the table are separated by horizontal lines, so e.g. etrigger and
itrigger have the same priority.
If this table contradicts the table in the Privileged Spec, then the latter
takes precedence.

This table only applies if triggers are precise. Otherwise triggers
will fire some indeterminate time after the event, and the priority is
irrelevant.
When triggers are chained, the priority is the lowest priority of the triggers
in the chain.

\begin{table}[H]
\centering
\begin{tabular}{|l|r|l|l|}
  \hline
  Priority      & Exception & Description & Trigger \\
                &      Code &             & \\
  \hline
  {\em Highest} &          3 & & etrigger \\
                &          3 & & icount \\
                &          3 & & itrigger \\
                &          3 & & mcontrol/mcontrol6 after \\
                &            & & \hspace{2em}(on previous instruction) \\
                \hline
                &          3 & Instruction address breakpoint & mcontrol/mcontrol6 execute address before \\ \hline
                &         12 & Instruction page fault & \\ \hline
                &          1 & Instruction access fault & \\ \hline
                &          3 & & mcontrol/mcontrol6 execute data before \\ \hline
                &          2 & Illegal instruction & \\
                &          0 & Instruction address misaligned & \\
                &   8, 9, 11 & Environment call & \\
                &          3 & Environment break & \\
                &          3 & Load/Store/AMO address breakpoint & mcontrol/mcontrol6 load/store address before \\
                &          3 & & mcontrol/mcontrol6 store data before \\ \hline
                &          6 & Store/AMO address misaligned & \\
                &          4 & Load address misaligned & \\ \hline
                &         15 & Store/AMO page fault & \\
                &         13 & Load page fault & \\ \hline
                &          7 & Store/AMO access fault & \\
                &          5 & Load access fault & \\
  {\em Lowest}  &          3 & & mcontrol/mcontrol6 load data before \\
  \hline
\end{tabular}
\caption{Synchronous exception priority in decreasing priority order.}
\label{tab:priority}
\end{table}

When multiple triggers in the same priority fire at once, \FcsrMcontrolHit (if
implemented) is set for all of them.  If more than one of these triggers has
\FcsrMcontrolSixAction=0 then {\tt tval} is updated in accordance with one of
them, but which one is \unspecified.  If one of these triggers has
the ``enter Debug Mode'' action (1) and another
trigger has the ``raise a breakpoint exception'' action (0),
the preferred behavior is to have both actions take place.  It is
implementation-dependent which of the two happens first.  This ensures both
that the presence of an external debugger doesn't affect execution and that a
trigger set by user code doesn't affect the external debugger. If this is not
implemented, then the hart must enter Debug Mode and ignore the breakpoint
exception. In the latter case, \FcsrMcontrolHit of the trigger whose action is 0 must still
be set, giving a debugger an opportunity to handle this case. What happens with
trace actions when triggers with different actions are also firing is left to
the trace specification.

\section{Native Triggers}
\label{sec:nativetrigger}

Triggers can be used for native debugging when \FcsrMcontrolSixAction=0.
If supported by the hart and desired by the debugger, triggers will often be
programmed to have \FcsrMcontrolSixM=0 so that when they fire they cause a
breakpoint exception to trap to a more privileged mode. That breakpoint
exception can either be taken in M-mode or it can be delegated to a less
privileged mode. However, it is possible for triggers to fire in the same
mode that the resulting exception will be handled in.

In these cases such a trigger may cause a breakpoint exception while already
in a trap handler. This might leave the hart unable to resume normal execution
because state such as \Rmcause and \Rmepc would be overwritten.

\begin{commentary}
\begin{steps}{In particular, when \FcsrMcontrolSixAction=0:}
\item mcontrol and mcontrol6 triggers with \FcsrMcontrolSixM=1 can cause a
breakpoint exception that is taken from M-mode to M-mode (regardless of
delegation).
\item mcontrol and mcontrol6 triggers with \FcsrMcontrolSixS=1 can cause a
breakpoint exception that is taken from S-mode to S-mode if \Rmedeleg[3]=1.
\item mcontrol6 triggers with \FcsrMcontrolSixVs=1 can cause a
breakpoint exception that is taken from VS-mode to VS-mode if \Rmedeleg[3]=1
and \Rhedeleg[3]=1.
\item icount triggers with \FcsrIcountM=1 can cause a
breakpoint exception that is taken from M-mode to M-mode (regardless of
delegation).
\item icount triggers with \FcsrIcountS=1 can cause a
breakpoint exception that is taken from S-mode to S-mode if \Rmedeleg[3]=1.
\item icount triggers with \FcsrIcountVs=1 can cause a
breakpoint exception that is taken from VS-mode to VS-mode if \Rmedeleg[3]=1
and \Rhedeleg[3]=1.
\item etrigger and itrigger triggers will always be taken from a trap handler
before the first instruction of the handler.  If etrigger/itrigger is set to
trigger on exception/interrupt X and if X is delegated to mode Y then the
trigger will cause a breakpoint exception that is taken from mode Y to mode
Y unless breakpoint exceptions are delegated to a more privileged mode than Y.
\item tmexttrigger triggers are asynchronous and may occur in any mode and
at any time.
\end{steps}
\end{commentary}

\begin{steps}{Harts that support triggers with \FcsrMcontrolSixAction=0
should implement one of the following two solutions to solve the problem of
reentrancy:}
\item The hardware prevents triggers with \FcsrMcontrolSixAction=0 from
matching or firing while in M-mode and while \FcsrMstatusMie in \Rmstatus is 0.  If
\Rmedeleg[3]=1 then it prevents triggers with \FcsrMcontrolSixAction=0
from matching or firing while in S-mode and while \FcsrSstatusSie in \Rsstatus is 0.
If \Rmedeleg[3]=1 and \Rhedeleg[3]=1 then it prevents triggers with
\FcsrMcontrolSixAction=0 from matching or firing while in VS-mode and while
\FcsrSstatusSie in \Rvsstatus is 0.
\item \FcsrTcontrolMte and \FcsrTcontrolMpte in \RcsrTcontrol is
implemented.  \Rmedeleg[3] is hard-wired to 0.
\end{steps}

\begin{commentary}
The first option has the limitation that interrupts might be disabled at
times when a user still might want triggers to fire.  It has the benefit
that breakpoints are not required to be handled in M-mode.

The second option has the benefit that it only disables triggers during
the trap handler, though it requires specific software support for this debug
feature in the M-mode trap handlers.  It can only work if breakpoints are not
delegated to less privileged modes and therefore targets primarily
implementations without S-mode.

Because \RcsrTcontrol is not accessible to S-mode, the second option can
not be extended to accommodate delegation without adding additional S-mode
and VS-mode CSRs.

Both options prevent etrigger and itrigger from having any effect on
exceptions and interrupts that are handled in M-mode.  They also prevent
triggering during some initial portion of each handler.  Debuggers should
use other mechanisms to debug these cases, such as patching the handler
or setting a breakpoint on the instruction after \FcsrMstatusMie is cleared.
\end{commentary}

\section{Memory Access Triggers}

\RcsrMcontrol and \RcsrMcontrolSix both enable triggers on memory accesses. This
section describes for both of them how certain corner cases are treated.

\subsection{A Extension}

\begin{steps}{If the A extension is supported, then triggers on loads/stores
treat them as follows:}
\item {\tt lr} instructions are loads.
\item Successful {\tt sc} instructions are stores.
\item It is \unspecified\ whether failing {\tt sc} instructions are stores or not.
\item Each AMO instruction is a load for the read portion of the
operation. The address is always available to trigger on, although
the value loaded might not be, depending on the hardware
implementation.
\item Each AMO instruction is a store for the write portion of the
operation. The address is always available to trigger on, although
the value stored might not be, depending on the hardware
implementation.
\end{steps}

If the destination register of any load or AMO is \Rzero then it is
\unspecified\ whether a data load trigger will match.  Whether data store
triggers match on AMOs is \unspecified.

\subsection{Combined Accesses}

Some instructions lead a hart to perform multiple memory accesses. This includes
vector loads and stores, as well as {\tt cm.push} and {\tt cm.pop} instructions.
The Trigger Module should match such accesses as if they all happened
individually. E.g. a vector load should be treated as if it performed multiple
loads of size SEW (selected element width), and {\tt cm.push} should be treated
as if it performed multiple stores of size XLEN.

\subsection{Cache Operations}

\begin{steps}{
Cache operations are infrequently performed, and code that uses them can have
hard-to-find bugs. For the purposes of debug triggers, two classes of cache
operations must match as stores:}
\item Cache operations that enable software to maintain coherence between
otherwise non-coherent implicit and explicit memory accesses.
\item Cache operations that perform block writes of constant data.
\end{steps}

\begin{steps}{Only triggers with \FcsrMcontrolSixSize=0 and
\FcsrMcontrolSixSelect=0 will match. Since cache operations affect multiple
addresses, there are multiple possible values to compare against.
Implementations must implement one of the following options.  From most
desirable to least desirable, they are:}
\item Every address from the effective address rounded down to the
    nearest cache block boundary (inclusive) to the effective address rounded up to
    the nearest cache block boundary (exclusive) is a compare value.
\item The effective address rounded down to the nearest cache block boundary is a
    compare value.
\item The effective address of the instruction is a compare value.
\end{steps}

Cache operations encoded as HINTs do not match debug triggers.

\begin{commentary}
    The above language intends to capture the trigger behavior with respect to
    the cache operations to be introduced in a forthcoming I/D consistency
    extension.

    \begin{steps}{For RISC-V Base Cache Management Operation ISA Extensions
            1.0.1, this means the following:}
        \item \inst{cbo.clean}, \inst{cbo.flush}, and \inst{cbo.inval} match as
            if they are stores because they affect consistency.
        \item \inst{cbo.zero} matches as if it is a store because it performs a
            block write of constant data.
        \item The prefetch instructions don't match at all.
    \end{steps}
\end{commentary}

\section{Trigger Registers}

These registers are CSRs, accessible using the RISC-V {\tt csr} opcodes and
optionally also using abstract debug commands.

Almost all trigger functionality is optional. All {\tt tdata} registers follow
write-any-read-legal semantics. If a debugger writes an unsupported
configuration, the register will read back a value that is supported (which may
simply be a disabled trigger).  This means that a debugger must always read
back values it writes to {\tt tdata} registers, unless it already knows already
what is
supported.  Writes to one {\tt tdata} register must not modify the contents of
other {\tt tdata} registers, nor the configuration of any trigger besides the
one that is currently selected.

The combination of these rules means that a debugger cannot simply set a
trigger by writing \RcsrTdataOne, then \RcsrTdataTwo, etc. The current value
of \RcsrTdataTwo might not be legal with the new value of \RcsrTdataOne. To
help with this situation, it is guaranteed that writing 0 to \RcsrTdataOne
disables the trigger, and leaves it in a state where \RcsrTdataTwo and
\RcsrTdataThree can be written with any value that makes sense for any
trigger type supported by this trigger.

\begin{steps}{As a result, a debugger can write any supported trigger as
follows:}
\item Write 0 to \RcsrTdataOne. (This will result in \RcsrTdataOne containing a
    non-zero value, since the register is \warl.)
\item Write desired values to \RcsrTdataTwo and \RcsrTdataThree.
\item Write desired value to \RcsrTdataOne.
\end{steps}

Code that restores CSR context of triggers that might be configured to fire in
the current privilege mode must use this same sequence to restore the triggers.
This avoids the problem of a partially written trigger firing at a different
time than is expected.

Attempts to access a non-existent Trigger Register raise an illegal instruction
exception.

\input{hwbp_registers.tex}
