Below are milestones planned for Standard Debug specification implementation in Vexriscv:
| Spec Feature (Chapter) | Vexriscv Debug Implementation | Implementation Details |
| Ch 6: Debug Transport Module (DTM) | | |
| JTAG TAP with IDCODE/dtmcs/dmi | ✅ Implemented | DebugTransportModuleJtag.scala — standard IR codes, dtmcs with version/abits/idle/dmistat, dmi with op/address/data |
| DMI bus protocol | ✅ Implemented | DebugInterfaces.scala — DebugBus with DebugCmd/DebugRsp, DebugBusSlaveFactory |
| DMI busy/error handling | ✅ Implemented | dmihardreset, dmireset, pending/overrun detection |
| Cross-clock-domain DMI | ✅ Implemented | ccToggle for JTAG↔debug clock domains |
| JTAG tunnel support | ✅ Implemented | JtagTunnel.scala — tunneling through outer TAP |
| Spec Feature (Chapter) | Vexriscv Debug Implementation | Implementation Details |
| Ch 3: Debug Module (DM) | | |
dmcontrol (0x10) | ✅ Implemented | dmactive, ndmreset, haltreq, resumereq, ackhavereset, hartsello/hi. Missing: hasel, setresethaltreq, hartreset, keepalive |
dmstatus (0x11) | ✅ Implemented | version, authenticated=1, all halted/running/unavail/nonexistent/resumeack/havereset flags, impebreak=1 |
hartinfo (0x12) | ✅ Implemented | dataaddr=0, datasize=0, dataaccess=0, nscratch=0 |
abstractcs (0x16) | ✅ Implemented | datacount, progbufsize, busy, cmderr (all 7 error codes) |
command (0x17) — Access Register | ✅ Implemented | cmdtype=0 with full FSM: transfer, write, postexec, aarsize validation, GPR+FPU register access |
command (0x17) — Access Memory | ❌ Not implemented | Returns NOT_SUPPORTED |
command (0x17) — Quick Access | ❌ Not implemented | Returns NOT_SUPPORTED |
abstractauto (0x18) | ✅ Implemented | autoexecdata and autoexecProgbuf for burst access |
progbuf0-N (0x20+) | ✅ Implemented | Parameterized progbuf memory, multi-word execution with counter, redo support |
data0-N (0x04+) | ✅ Implemented | Memory-backed, hart writes via fromHarts, host reads async |
sbcs (0x38) — System Bus Access | ✅ Implemented (optional) | sbversion=1, sbaccess, sbbusyerror, sbbusy, sbreadonaddr, sbautoincrement, sbreadondata, sberror, 32-bit only |
sbaddress0 (0x39) | ✅ Implemented | Read/write with auto-increment |
sbdata0 (0x3c) | ✅ Implemented | Read/write with bus triggers |
sbaddress1-3 / sbdata1-3 | ❌ Not implemented | 32-bit address/data only |
sbcs 8/16/64/128-bit access | ❌ Not implemented | Only sbaccess32 supported |
haltsum0 (0x40) | ✅ Implemented | Per-hart halted bits, up to 32 harts |
haltsum1-3 | ❌ Not implemented | Only haltsum0 exists |
authdata (0x30) | ❌ Not implemented | Always authenticated |
confstrptr0-3 | ❌ Not implemented | — |
nextdm (0x1d) | ❌ Not implemented | — |
dmcs2 (0x32) | ❌ Not implemented | — |
Hart arrays (hawindowsel/hawindow) | ❌ Not implemented | — |
custom0-15 | ❌ Not implemented | — |
| Multi-hart support | ✅ Implemented | Parameterized p.harts, per-hart buses, hartSel selection |
| Spec Feature (Chapter) | Vexriscv Debug Implementation | Implementation Details |
| Ch 4: Core Debug (hart-side CSRs) | | |
| Halt/Resume | ✅ DebugHartBus + CsrPlugin | CsrPlugin.scala (line 702+): running flag, DebugHartBus wiring, halt/resume handshake |
| Single-step | ✅ Implemented | CsrPlugin.scala (lines 807-845): dcsr.step with full FSM (IDLE→SINGLE→WAIT), timeout/redo handling |
dcsr (0x7B0) | ✅ Implemented | CsrPlugin.scala (lines 792-851): prv, step, nmip, mprven, cause, stoptime, stopcount, stepie, ebreakm/s/u, xdebugver=4 |
dpc (0x7B1) | ✅ Implemented | CsrPlugin.scala (line 791): Reg(UInt(32 bits)), read/write via rw(CSR.DPC, dpc) |
dscratch0 (0x7B2) | ❌ Not implemented | — |
dscratch1 (0x7B3) | ❌ Not implemented | — |
| Debug mode entry | ✅ Implemented | CsrPlugin.scala (lines 1426-1443): saves PC→dpc, sets dcsr.cause (1=ebreak, 3=haltreq, 4=step), saves privilege→dcsr.prv, enters M-mode |
| Debug mode exit (resume) | ✅ Implemented | CsrPlugin.scala (lines 1488-1498): jumps to dpc, restores privilege from dcsr.prv, via DebugHartBus.resume |
| Halt cause reporting | ✅ Implemented | dcsr.cause: 1 (ebreak), 2 (trigger), 3 (haltreq), 4 (step) |
dcsr.ebreakm/s/u | ✅ Implemented | CsrPlugin.scala (lines 1372-1377): per-privilege ebreak→debug detection |
dcsr.stoptime | ✅ Implemented | CsrPlugin.scala (line 866): stoptime output gated by debugMode |
dcsr.stopcount | ✅ Implemented | CsrPlugin.scala (line 1176): mcycle increment gated by !debugMode || !stopcount |
dcsr.stepie | ✅ Implemented | CsrPlugin.scala (line 1315): interrupts cleared when step && !stepie |
| Interrupt inhibition in debug | ✅ Implemented | CsrPlugin.scala (line 721): inhibateInterrupts() when debugMode |
| CSR access protection (0x7Bx) | ✅ Implemented | CsrPlugin.scala (line 1718): blocks non-debug access to 0x7B0-0x7BF |
DebugHartBus wiring | ✅ Implemented | CsrPlugin.scala (lines 704-789): instruction injection, data CSR, all hartToDm/dmToHart signals |
| Reset control | ✅ dmcontrol.ndmreset → io.ndmreset | Both implementations provide ndmreset |
| Spec Feature (Chapter) | Vexriscv Debug Implementation | Implementation Details |
| Ch 5: Trigger Module (hart-side CSRs) | | |
tselect (0x7A0) | ✅ Implemented | CsrPlugin.scala (lines 870-875): WARL index, parameterized debugTriggers (default 2) |
tinfo (0x7A4) | ✅ Implemented | CsrPlugin.scala (line 878): reports type 2 (mcontrol) support |
tdata1 (0x7A1) | ⚠️ Partial | CsrPlugin.scala (lines 922-942): type=2, dmode, execute, m/s/u, action. Missing: timing, select, sizelo/hi, maskmax, chain, match, load, store, hit |
tdata2 (0x7A2) | ✅ Implemented | CsrPlugin.scala (lines 944-953): 32-bit compare value, PC equality match |
tdata3 (0x7A3) | ❌ Not implemented | — |
tcontrol (0x7A5) | ❌ Not implemented | No mte/mpte |
| Trigger type | ⚠️ mcontrol (type 2) only | Legacy type 2, not type 6 (mcontrol6). Spec recommends type 6 for new implementations |
| Match modes | ⚠️ Equal only | Only match=0 (equality). No napot, >=, <, mask modes |
| Match targets | ⚠️ Execute address only | Only execute bit implemented. No load/store data/address match |
| Privilege filtering | ✅ Implemented | m, s, u bits with privilegeHit logic (lines 930-934) |
dmode security | ✅ Implemented | dmode bit controls debug-only write access (line 925) |
action field | ⚠️ Partial | Register exists but only action=1 (enter debug) used in match logic |
| Trigger chaining | ❌ Not implemented | No chain bit |
dcsr.cause=2 on trigger | ✅ Implemented | CsrPlugin.scala (line 892): sets dcsr.cause := 2 on trigger hit |
| Trigger hit → debug entry | ✅ Implemented | CsrPlugin.scala (lines 881-897): decodeBreak halts pipeline, enters debug mode |
mcontrol6 (type 6) | ❌ Not implemented | Only legacy type 2 exists |
icount (type 3) | ❌ Not implemented | — |
itrigger/etrigger/tmexttrigger | ❌ Not implemented | — |
| Hardware breakpoints | ⚠️ Spec-compliant but limited | Type 2 mcontrol with execute address match=0 only, privilege filtering, dmode security |
mcontext/scontext | ❌ Not implemented | — |
| SoC Integration | | |
| DTM→DM→Hart wiring | ✅ Implemented | DebugModuleFiber.scala — multi-hart binding, clock-domain-safe pipelining |
| Tilelink SBA bridge | ✅ Implemented | makeSysbusTilelink() in DebugModuleFiber |