forked from riscv/riscv-debug-spec
-
Notifications
You must be signed in to change notification settings - Fork 1
/
implementations.tex
129 lines (108 loc) · 6.24 KB
/
implementations.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
\chapter{Hardware Implementations}
\label{sec:implementations}
Below are two possible implementations. A designer could choose one, mix and
match, or come up with their own design.
\section{Abstract Command Based}
Halting happens by stalling the hart execution pipeline.
Muxes on the register file(s) allow for accessing GPRs and CSRs
using the Access Register abstract command.
Memory is accessed using the Abstract Access Memory command or through System
Bus Access.
This implementation could allow a debugger to collect information from the hart
even when that hart is unable to execute instructions.
\section{Execution Based} \label{execution_based}
This implementation only implements the Access Register abstract command
for GPRs on a halted hart, and relies on the Program Buffer for all other
operations.
It uses the hart's existing pipeline
and ability to execute from arbitrary memory locations to avoid
modifications to a hart's datapath.
When the halt request bit is set, the Debug Module raises a special interrupt
to the selected harts. This interrupt causes each
hart to enter Debug Mode and jump to a defined
memory region that is serviced by the DM and is only accessible to the harts in Debug Mode.
When taking this jump, \Rpc is saved to \RcsrDpc and \FcsrDcsrCause is updated
in \RcsrDcsr. This jump is similar to a trap but it is not architecturally
considered a trap, so for instance doesn't count as a trap for trigger behavior.
The code in the Debug Module causes the hart to execute a ``park loop.''
In the park loop the hart writes its \Rmhartid to a
memory location within the Debug Module to indicate that it is halted.
To allow the DM to individually control one out of several
halted harts, each hart polls for flags in a DM-controlled memory location
to determine whether the debugger wants it to
execute the Program Buffer or perform a resume.
To execute an abstract command, the DM first populates some internal words of
program buffer according to \RdmCommand. When \FacAccessregisterTransfer is set, the DM
populates these words with {\tt lw <gpr>, 0x400(zero)} or {\tt sw 0x400(zero), <gpr>}.
64- and 128-bit accesses use {\tt ld}/{\tt sd} and {\tt lq}/{\tt sq}
respectively. If \FacAccessregisterTransfer is not set, the DM populates these instructions as {\tt nop}s.
If \FacAccessregisterPostexec is set, execution continues to the debugger-controlled Program Buffer,
otherwise the DM causes a {\tt ebreak} to execute immediately.
When {\tt ebreak} is executed (indicating the end of the
Program Buffer code) the hart returns to its park loop. If an exception is
encountered, the hart jumps to an address within
the Debug Module. The code there causes the hart to
write to the Debug Module indicating an exception.
Then the hart jumps back to the park loop.
The DM infers from the write that there was an exception, and sets \FdmAbstractcsCmderr appropriately.
Typically the hart will execute a {\tt fence} instruction before entering the
park loop, to ensure that any effects from the abstract command, such as a
write to \RdmDataZero, take effect before the DM returns \FdmAbstractcsBusy
to 0.
To resume execution, the debug module sets a flag which causes the hart to execute a {\tt dret}.
{\tt dret} is an instruction that only has meaning while in Debug Mode and
not executing from the Program Buffer.
Its recommended encoding is 0x7b200073.
When {\tt dret} is executed, \Rpc is restored from \RcsrDpc and normal execution resumes at the
privilege set by \FcsrDcsrPrv and \FcsrDcsrV.
\RdmDataZero etc. are mapped into regular memory at an address relative to \Rzero
with only a 12-bit {\tt imm}. The exact address is an implementation
detail that a debugger must not rely on. For example, the {\tt data}
registers might be mapped to {\tt 0x400}.
For additional flexibility, \RdmProgbufZero, etc. are mapped into regular memory
immediately preceding \RdmDataZero, in order to form a contiguous region of memory which
can be used for either program execution or data transfer.
The PMP must not disallow fetches,
loads, or stores in the address range associated with the Debug Module when the
hart is in Debug Mode, regardless of how the PMP is configured. The same is
true of PMA. Without this guarantee, the park loop would enter an infinite
loop of traps and debug would not be possible.
\section{Debug Module Interface Signals} \label{dmi_signals}
As stated in section \ref{dmi} the details of the DMI are left to the system designer.
It is quite often the case that only one DTM and one DM is implemented.
In this case it might be useful to comply with the signals suggested in table \ref{tab:dmi_signals},
which is the implementation used in the open-source \href{https://github.com/chipsalliance/rocket-chip/blob/375045a7db1bdc7b4f7851f1a59b3f10a2b922ff/src/main/scala/devices/debug/Debug.scala#L170}{rocket-chip} RISC-V core.
The DTM can start a request when the DM sets REQ\_READY to 1.
When this is the case REQ\_OP can be set to 1 for a read or 2 for a write request.
The desired address is driven with the REQ\_ADDRESS signal.
Finally REQ\_VALID is set high, indicating to the DM that a valid request is pending.
The DM must respond to a request from the DTM when RSP\_READY is high.
The status of the response is indicated by the RSP\_OP signal (see \FdtmDmiOp).
The data of the response is driven to RSP\_DATA.
A pending response is signalled by setting RSP\_VALID.
\begin{table}[ht]\centering
\begin{tabular}[h]{l l l l}
\hline
Signal & Width & Source & Description \\
\hline
REQ\_VALID & 1 & DTM & Indicates that a valid request is pending \\
\hline
REQ\_READY & 1 & DM & Indicates that the DM is able to process a request \\
\hline
REQ\_ADDRESS & \FdtmDtmcsAbits & DTM & Requested address \\
\hline
REQ\_DATA & 32 & DTM & Requested data \\
\hline
REQ\_OP & 2 & DTM & Same meaning as the \FdtmDmiOp field\\
\hline
RSP\_VALID & 1 & DM & Indicates that a valid respond is pending \\
\hline
RSP\_READY & 1 & DTM & Indicates that the DTM is able to process a respond \\
\hline
RSP\_DATA & 32 & DM & Response data \\
\hline
RSP\_OP & 2 & DM & Same meaning as the \FdtmDmiOp field\\
\hline
\end{tabular}
\caption{Signals for the suggested DMI between one DTM and one DM \label{tab:dmi_signals}}
\end{table}