forked from riscv/riscv-debug-spec
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimplementations.tex
73 lines (58 loc) · 3.47 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
\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}
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.
When taking this exception, \Rpc is saved to \RcsrDpc and \FcsrDcsrCause is updated
in \RcsrDcsr.
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 \FcsrMcontrolExecute 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 a debug exception address within
the Debug Module. The code at that address causes the hart to
write to an address in the Debug Module which indicates exception.
This address is considered I/O for {\tt fence} instructions (see \#\ref{fence}
on page \pageref{fence}).
Then the hart jumps back to the park loop.
The DM infers from the write that there was an exception, and sets \FdmAbstractcsCmderr appropriately.
To resume execution, the debug module sets a flag which causes the hart to execute a {\tt dret}.
When {\tt dret} is executed, \Rpc is restored from \RcsrDpc and normal execution resumes at the
privilege set by \FcsrDcsrPrv.
\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.