跳转至

Debug Module

  • Version: V2R2
  • Status: OK
  • Date: 2025/01/20
  • Commit: xxx

Terminology Description

Terminology Description
Abbreviation Full Name Description
DM Debug Module Debug Module
DTM Debug Transport Module Debug Transport Module
DMI Debug Module Interface Debug Module Interface

Parameter Design

Parameter Design
Parameter Default Value Description
baseAddress 0x38020800 Debug Module MMIO Base Address
nDMIAddrSize 7 DMI Address Width
nProgramBufferWords 16 Number of Program Buffers
nAbstractDataWords 4 Number of Abstract Commands
hasBusMaster true System Bus Master
maxSupportedSBAccess 64 Max System Bus Access Width
supportQuickAccess false QuickAccess Support
supportHartArray true Hart Array Support
nHaltGroups 1 Number of Halt Groups
nExtTriggers 0 Number of External Triggers
hasHartResets true Resets selected harts
hasImplicitEbreak false Implicit Ebreak Support

Overall Design

Overall Block Diagram

As shown in 此图:

DebugModule Overview

Multi-clock Domain

As shown in 此图:

DebugModule Multi-clock Domain

Debug MMIO

As shown in 此表:

Debug MMIO Address Space
Address (Base Address 0x3802_0000) Name Description Content stored at this address
0x800 debugEntry Debug entry address / Base address of debug rom
0x808 debugException Exception entry address when executing in dmode
0x100 HALTED hartid of the hart that entered dmode, Debug Module will get it
0x104 GOING whereto, eventually jumps to ABSTRACT for execution
0x108 RESUMING Executes dret
0x10c EXCEPTION
0x300 WHERETO Instruction stored at this address Jump instruction generated by DM to jump to ABSTRACT
0x380 DATA Base address of DATA (for ld/st) Data exchange
DATA-4*nProgBuf PROGBUF Address of progbuf0 Instructions generated by DM (prepared before go)
DATA-4 IMPEBREAK Implicit ebreak instruction
PROGBUF - 4* nAbstractInst ABSTRACT AbstractInstructions Instructions generated by DM (prepared before go)
0x400 FLAGS Base address for hartid corresponding flags. Each flag is 8bits. 0x400 represents the flag address for hartid=0 Only the lowest two bits of this 8bits are valid. The second lowest bit indicates resume, the lowest bit indicates go. The address space is 1k, i.e., 0x400 -> (0x500-0x1)

Module Design

Debug Module

The current implementation of Debug in Kunming Lake is as follows:

  • Supports debugging from the first instruction, entering debug mode after CPU reset.
  • Supports run control for single core and multi-core (selected cores) debugging, including halt, resume, and reset.
  • Supports single-step debugging.
  • Supports stopcount and stoptime.
  • Supports software breakpoints (ebreak instruction), hardware breakpoints (trigger), and memory breakpoints (trigger).
  • Supports GPR, CSR, and memory access, using both progbuf and sysbus access methods.
  • Supports entering debug mode via debug interrupt (haltreq, haltgroup, halt-on-reset), trigger fire, ebreak, singlestep, critical error, etc.

Trigger Module

The current implementation of the Trigger Module in Kunming Lake is as follows:

  • The debug-related CSRs currently implemented by the Kunming Lake Trigger Module are shown in the table below.
  • The default number of triggers configured is 4 (user-configurable).
  • Supports triggers for mcontrol6 type instructions and memory accesses.
  • Supports match types equal to, greater than or equal to, and less than (vector access currently only supports equal type matching).
  • Only supports address matching, not data matching.
  • Only supports timing = before.
  • Only supports chaining of one pair of triggers.
  • To prevent secondary breakpoint exceptions from triggers, control via xSTATUS.xIE is supported.
  • Supports software and hardware breakpoints and watchpoint debugging methods for the H extension.
  • Supports memory access triggers for atomic instructions.

The following table describes the access granularity in the microarchitecture and the trigger matching granularity for memory access instructions currently supported by Kunming Lake: For scalar instructions and vector instructions that access elements by element granularity, the match types >=, =, < are supported; for other vector instructions, only match type = is supported. In addition, for vector memory access instructions, triggers fired by instructions with smaller element indices are handled (regardless of whether their trigger action is breakpoint or debug).

Access Granularity and Trigger Matching Granularity
Instruction Type Access Granularity Trigger Matching Granularity
Scalar Memory Access Instructions Instruction (element) Checks element little-endian address, supports >=, =, <
Atomic Memory Access (lr/sc) Instruction (element) Checks element little-endian address, supports >=, =, <; lr is treated as load, sc as store (regardless of success)
Atomic Memory Access (amo) Instruction (element) Checks element little-endian address, supports >=, =, <; Checks both load and store when vaddr is available
Vector Memory Access (unit-stride) Vector Register Width (128bit) Supports checking any address within the access range of the instruction (at 8-bit granularity), but only supports = match
Vector Memory Access (whole) Vector Register Width (128bit) Supports checking any address within the access range of the instruction (at 8-bit granularity), but only supports = match
Vector Memory Access (fof unit-stride) Vector Register Width (128bit) Supports checking any address within the access range of the instruction (at 8-bit granularity), but only supports element 0 = match
Vector Memory Access (segment) Element Checks each element's little-endian address, but only supports = match
Other Vector Memory Access Element Checks each element's little-endian address, supports >=, =, <
Kunming Lake Debug Related CSRs
Name Address Read/Write Description Reset Value
Tselect 0x7A0 RW Trigger Select Register 0X0
Tdata1(Mcontrol6) 0x7A1 RW Trigger Data1 0xF0000000000000000
Tdata2 0x7A2 RW Trigger Data2 0x0
Tinfo 0x7A4 RO Trigger Info 0x40
Dcsr 0x7B0 RW Debug Control and Status 0x40000003
Dpc 0x7B1 RW Debug PC 0x0
Dscratch0 0x7B2 RW Debug Scratch Register 0 -
Dscratch1 0x7B3 RW Debug Scratch Register 1
mcontext 0x7A8 RW Machine Context -
hcontext 0x6A8 RW Hypervisor Context -
scontext 0x5A8 RW Supervisor Context -

Debug Flow Examples

CSR Access:

Debug Module CSR access is accomplished through the cooperation of abstract commands and progbuff. According to the abstract command, corresponding instructions will be generated at the ABSTRACT and PROGBUFF addresses respectively (these two address spaces are contiguous) for the CPU to execute, achieving the purpose of accessing CSRs. The instructions generated at ABSTRACT are lw/st instructions, which perform data exchange between the MMIO address and GPR s0/s1. The instructions generated at PROGBUFF are CSR read/write instructions. Below is an example illustrating how the Debug Module accesses the mstatus register:

  1. Assume the software issues a command to write the mstatus CSR. This command will sequentially pass through JtagProbe, JtagDTM, DMI, and be converted into DMI operations.
  2. The DMI operations, via dmi2tl, modify the internal control signals of the Debug Module, changing DMI_COMMAND to the command for writing the mstatus register.
  3. OpenOCD first reads the value of s0/fp and saves it, then writes the CSR write instruction to the progbuffer.
  4. Execute ABSTRACT (ld instruction), writing DATA to s0.
  5. Execute progbuffer (CSR write instruction). Progbuff ends with an ebreak instruction, re-entering the parking loop.

    If it's a read CSR operation: 6. Execute progbuffer (CSR read instruction), reading the CSR value into s0. 7. Execute ABSTRACT (st instruction), writing s0 to DATA.

Hardware Breakpoint:

The following content takes setting a breakpoint as an example to illustrate the collaborative workflow between software and hardware during debugging:

  1. First, the software issues a halt command. This command sequentially passes through JtagProbe, JtagDTM, DMI, and is converted into DMI operations.
  2. The DMI operations, via dmi2tl, modify the internal control signals of the Debug Module, sending an external debug interrupt to the hart. This interrupt is eventually transmitted to the CSR module inside the hart.
  3. The CSR handles the external debug interrupt: the hart will Trap to the Debug Module's entry address (see Debug Module MMIO) and enter DMode.
  4. After the Hart enters DMode, it executes instructions in the debug ROM. It will write its hartid to HALTED (see Section 8 Debug ROM), notifying the Debug Module that it (the hart) has entered dmode and can now be debugged by the Debugger in Dmode.
  5. When the software issues a command to set a hardware breakpoint, the hart will jump to whereto. Abstract and progbuff cooperate to control the hart to execute CSR instructions (progbuffer) to configure the trigger CSR register, writing the breakpoint information into the trigger CSR. Progbuff ends with an ebreak instruction. Executing this ebreak will cause it to jump back to the Debug Module's entry address.
  6. The software issues a resume command. The hart will jump to _resume to execute the dret instruction, exiting dMode and returning to resume execution where it was before halting at step 1. (There is preparatory work before resuming: it needs to execute a step first, committing only one instruction, and then trap to debugMode via a single-step exception. You can look at the OpenOCD source code for this.)
  7. When the hart executes the program and reaches the breakpoint location, the instruction's pc matches the breakpoint address configured in the trigger CSR. The trigger fires, and the hart will enter dmode again (Trap to the Debug Module's entry address) to execute instructions in the debug ROM, waiting for the debugger to debug.