1
0

Add some add'l debug features (#1112)

* debug: Update macros from spec

* debug: some corrections in the auto-generated files

* debug: update renamed fields

* Debug: implement the implicit ebreak option for small program buffers

* debug: clean up some unused code and add more require() explanations

* debug: make implicit ebreak false

* debug: Add the havereset/haveresetack functionality

* debug: program buffer can still be 16 even if there is an implicit ebreak
This commit is contained in:
Megan Wachs 2017-11-16 17:14:41 -08:00 committed by GitHub
parent acc8c2bbb3
commit e7704f46c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 232 additions and 251 deletions

View File

@ -44,8 +44,6 @@ object DsbBusConsts {
object DsbRegAddrs{ object DsbRegAddrs{
// These may need to move around to be used by the serial interface.
// These are used by the ROM. // These are used by the ROM.
def HALTED = 0x100 def HALTED = 0x100
def GOING = 0x104 def GOING = 0x104
@ -61,8 +59,14 @@ object DsbRegAddrs{
def DATA = 0x380 def DATA = 0x380
// We want DATA to immediately follow PROGBUF so that we can // We want DATA to immediately follow PROGBUF so that we can
// use them interchangeably. // use them interchangeably. Leave another slot if there is an
def PROGBUF(cfg:DebugModuleParams) = {DATA - (cfg.nProgramBufferWords * 4)} // implicit ebreak.
def PROGBUF(cfg:DebugModuleParams) = {
val tmp = DATA - (cfg.nProgramBufferWords * 4)
if (cfg.hasImplicitEbreak) (tmp - 4) else tmp
}
// This is unused if hasImpEbreak is false, and just points to the end of the PROGBUF.
def IMPEBREAK(cfg: DebugModuleParams) = { DATA - 4 }
// We want abstract to be immediately before PROGBUF // We want abstract to be immediately before PROGBUF
// because we auto-generate 2 instructions. // because we auto-generate 2 instructions.
@ -108,9 +112,11 @@ import DebugAbstractCommandType._
* nProgamBufferWords: Number of 32-bit words for Program Buffer * nProgamBufferWords: Number of 32-bit words for Program Buffer
* hasBusMaster: Whethr or not a bus master should be included * hasBusMaster: Whethr or not a bus master should be included
* The size of the accesses supported by the Bus Master. * The size of the accesses supported by the Bus Master.
* nSerialPorts : Number of serial ports to instantiate
* supportQuickAccess : Whether or not to support the quick access command. * supportQuickAccess : Whether or not to support the quick access command.
* supportHartArray : Whether or not to implement the hart array register. * supportHartArray : Whether or not to implement the hart array register.
* hartIdToHartSel: For systems where hart ids are not 1:1 with hartsel, provide the mapping.
* hartSelToHartId: Provide inverse mapping of the above
* hasImplicitEbreak: There is an additional RO program buffer word containing an ebreak
**/ **/
case class DebugModuleParams ( case class DebugModuleParams (
@ -125,27 +131,25 @@ case class DebugModuleParams (
hasAccess32 : Boolean = false, hasAccess32 : Boolean = false,
hasAccess16 : Boolean = false, hasAccess16 : Boolean = false,
hasAccess8 : Boolean = false, hasAccess8 : Boolean = false,
nSerialPorts : Int = 0,
supportQuickAccess : Boolean = false, supportQuickAccess : Boolean = false,
supportHartArray : Boolean = false, supportHartArray : Boolean = false,
hartIdToHartSel : (UInt) => UInt = (x:UInt) => x, hartIdToHartSel : (UInt) => UInt = (x:UInt) => x,
hartSelToHartId : (UInt) => UInt = (x:UInt) => x hartSelToHartId : (UInt) => UInt = (x:UInt) => x,
hasImplicitEbreak : Boolean = false
) { ) {
if (hasBusMaster == false){ if (hasBusMaster == false){
require (hasAccess128 == false) require (hasAccess128 == false, "No Bus mastering support in Debug Module yet")
require (hasAccess64 == false) require (hasAccess64 == false, "No Bus mastering support in Debug Module yet")
require (hasAccess32 == false) require (hasAccess32 == false, "No Bus mastering support in Debug Module yet")
require (hasAccess16 == false) require (hasAccess16 == false, "No Bus mastering support in Debug Module yet")
require (hasAccess8 == false) require (hasAccess8 == false, "No Bus mastering support in Debug Module yet")
} }
require (nSerialPorts <= 8) require ((nDMIAddrSize >= 7) && (nDMIAddrSize <= 32), s"Legal DMIAddrSize is 7-32, not ${nDMIAddrSize}")
require ((nDMIAddrSize >= 7) && (nDMIAddrSize <= 32)) require ((nAbstractDataWords > 0) && (nAbstractDataWords <= 16), s"Legal nAbstractDataWords is 0-16, not ${nAbstractDataWords}")
require ((nProgramBufferWords >= 0) && (nProgramBufferWords <= 16), s"Legal nProgramBufferWords is 0-16, not ${nProgramBufferWords}")
require ((nAbstractDataWords > 0) && (nAbstractDataWords <= 16))
require ((nProgramBufferWords >= 0) && (nProgramBufferWords <= 16))
if (supportQuickAccess) { if (supportQuickAccess) {
// TODO: Check that quick access requirements are met. // TODO: Check that quick access requirements are met.
@ -201,8 +205,9 @@ class DMIIO(implicit val p: Parameters) extends ParameterizedBundle()(p) {
*/ */
class DebugInternalBundle ()(implicit val p: Parameters) extends ParameterizedBundle()(p) { class DebugInternalBundle ()(implicit val p: Parameters) extends ParameterizedBundle()(p) {
val resumereq = Bool() val resumereq = Bool()
val hartsel = UInt(10.W) val hartsel = UInt(10.W)
val ackhavereset = Bool()
} }
/* structure for top-level Debug Module signals which aren't the bus interfaces. /* structure for top-level Debug Module signals which aren't the bus interfaces.
@ -324,10 +329,11 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod
DMCONTROLNxt := DMCONTROLReset DMCONTROLNxt := DMCONTROLReset
} .otherwise { } .otherwise {
when (DMCONTROLWrEn) { when (DMCONTROLWrEn) {
DMCONTROLNxt.ndmreset := DMCONTROLWrData.ndmreset DMCONTROLNxt.ndmreset := DMCONTROLWrData.ndmreset
DMCONTROLNxt.hartsel := DMCONTROLWrData.hartsel DMCONTROLNxt.hartsel := DMCONTROLWrData.hartsel
DMCONTROLNxt.haltreq := DMCONTROLWrData.haltreq DMCONTROLNxt.haltreq := DMCONTROLWrData.haltreq
DMCONTROLNxt.resumereq := DMCONTROLWrData.resumereq DMCONTROLNxt.resumereq := DMCONTROLWrData.resumereq
DMCONTROLNxt.ackhavereset := DMCONTROLWrData.ackhavereset
} }
} }
@ -378,8 +384,9 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod
} }
io.innerCtrl.valid := DMCONTROLWrEn io.innerCtrl.valid := DMCONTROLWrEn
io.innerCtrl.bits.hartsel := DMCONTROLWrData.hartsel io.innerCtrl.bits.hartsel := DMCONTROLWrData.hartsel
io.innerCtrl.bits.resumereq := DMCONTROLWrData.resumereq io.innerCtrl.bits.resumereq := DMCONTROLWrData.resumereq
io.innerCtrl.bits.ackhavereset := DMCONTROLWrData.ackhavereset
io.ctrl.ndreset := DMCONTROLReg.ndmreset io.ctrl.ndreset := DMCONTROLReg.ndmreset
io.ctrl.dmactive := DMCONTROLReg.dmactive io.ctrl.dmactive := DMCONTROLReg.dmactive
@ -461,17 +468,17 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
// Sanity Check Configuration For this implementation. // Sanity Check Configuration For this implementation.
//-------------------------------------------------------------- //--------------------------------------------------------------
require (cfg.nSerialPorts == 0) require (cfg.hasBusMaster == false, "No Bus Mastering support yet")
require (cfg.hasBusMaster == false) require (cfg.supportQuickAccess == false, "No Quick Access support yet")
require (cfg.supportQuickAccess == false) require (cfg.supportHartArray == false, "No Hart Array support yet")
require (cfg.supportHartArray == false)
//-------------------------------------------------------------- //--------------------------------------------------------------
// Register & Wire Declarations (which need to be pre-declared) // Register & Wire Declarations (which need to be pre-declared)
//-------------------------------------------------------------- //--------------------------------------------------------------
val haltedBitRegs = RegInit(Vec.fill(nComponents){false.B}) val haltedBitRegs = RegInit(Vec.fill(nComponents){false.B})
val resumeReqRegs = RegInit(Vec.fill(nComponents){false.B}) val resumeReqRegs = RegInit(Vec.fill(nComponents){false.B})
val haveResetBitRegs = RegInit(Vec.fill(nComponents){true.B})
// --- regmapper outputs // --- regmapper outputs
@ -512,7 +519,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
val DMSTATUSRdData = Wire(init = (new DMSTATUSFields()).fromBits(0.U)) val DMSTATUSRdData = Wire(init = (new DMSTATUSFields()).fromBits(0.U))
DMSTATUSRdData.authenticated := true.B // Not implemented DMSTATUSRdData.authenticated := true.B // Not implemented
DMSTATUSRdData.versionlo := "b10".U DMSTATUSRdData.version := 2.U // Version 0.13
// Chisel3 Issue #527 , have to do intermediate assignment. // Chisel3 Issue #527 , have to do intermediate assignment.
val unavailVec = Wire(init = Vec.fill(nComponents){false.B}) val unavailVec = Wire(init = Vec.fill(nComponents){false.B})
@ -531,14 +538,24 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
DMSTATUSRdData.allrunning := true.B DMSTATUSRdData.allrunning := true.B
DMSTATUSRdData.anyrunning := true.B DMSTATUSRdData.anyrunning := true.B
} }
DMSTATUSRdData.allhavereset := haveResetBitRegs(selectedHartReg)
DMSTATUSRdData.anyhavereset := haveResetBitRegs(selectedHartReg)
val resumereq = io.innerCtrl.fire() && io.innerCtrl.bits.resumereq val resumereq = io.innerCtrl.fire() && io.innerCtrl.bits.resumereq
when (io.innerCtrl.fire()){
when (io.innerCtrl.bits.ackhavereset) {
haveResetBitRegs(io.innerCtrl.bits.hartsel) := false.B
}
}
DMSTATUSRdData.allresumeack := ~resumeReqRegs(selectedHartReg) && ~resumereq DMSTATUSRdData.allresumeack := ~resumeReqRegs(selectedHartReg) && ~resumereq
DMSTATUSRdData.anyresumeack := ~resumeReqRegs(selectedHartReg) && ~resumereq DMSTATUSRdData.anyresumeack := ~resumeReqRegs(selectedHartReg) && ~resumereq
//TODO //TODO
DMSTATUSRdData.cfgstrvalid := false.B DMSTATUSRdData.devtreevalid := false.B
DMSTATUSRdData.impebreak := (cfg.hasImplicitEbreak).B
//----HARTINFO //----HARTINFO
@ -562,8 +579,8 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
//----ABSTRACTCS //----ABSTRACTCS
val ABSTRACTCSReset = Wire(init = (new ABSTRACTCSFields()).fromBits(0.U)) val ABSTRACTCSReset = Wire(init = (new ABSTRACTCSFields()).fromBits(0.U))
ABSTRACTCSReset.datacount := cfg.nAbstractDataWords.U ABSTRACTCSReset.datacount := cfg.nAbstractDataWords.U
ABSTRACTCSReset.progsize := cfg.nProgramBufferWords.U ABSTRACTCSReset.progbufsize := cfg.nProgramBufferWords.U
val ABSTRACTCSReg = Reg(new ABSTRACTCSFields()) val ABSTRACTCSReg = Reg(new ABSTRACTCSFields())
val ABSTRACTCSWrDataVal = Wire(init = 0.U(32.W)) val ABSTRACTCSWrDataVal = Wire(init = 0.U(32.W))
@ -876,10 +893,11 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int)(implicit p:
PROGBUF(cfg)-> programBufferMem.map(x => RegField(8, x)), PROGBUF(cfg)-> programBufferMem.map(x => RegField(8, x)),
// These sections are read-only. // These sections are read-only.
WHERETO -> Seq(RegField.r(32, jalAbstract.asUInt)), IMPEBREAK(cfg)-> {if (cfg.hasImplicitEbreak) Seq(RegField.r(32, Instructions.EBREAK.value.U)) else Nil},
ABSTRACT(cfg)-> abstractGeneratedMem.map{x => RegField.r(32, x)}, WHERETO -> Seq(RegField.r(32, jalAbstract.asUInt)),
FLAGS -> flags.map{x => RegField.r(8, x.asUInt())}, ABSTRACT(cfg) -> abstractGeneratedMem.map{x => RegField.r(32, x)},
ROMBASE -> DebugRomContents().map(x => RegField.r(8, (x & 0xFF).U(8.W))) FLAGS -> flags.map{x => RegField.r(8, x.asUInt())},
ROMBASE -> DebugRomContents().map(x => RegField.r(8, (x & 0xFF).U(8.W)))
) )

View File

@ -2,7 +2,7 @@ package freechips.rocketchip.devices.debug
import Chisel._ import Chisel._
// This file was auto-generated from the repository at https://github.com/sifive/riscv-debug-spec.git, // This file was auto-generated from the repository at https://github.com/riscv/riscv-debug-spec.git,
// 'make chisel' // 'make chisel'
object AC_RegAddrs { object AC_RegAddrs {
@ -29,7 +29,7 @@ class ACCESS_REGISTERFields extends Bundle {
val size = UInt(3.W) val size = UInt(3.W)
val reserved1 = UInt(1.W) val reserved1 = UInt(1.W)
/* When 1, execute the program in the Program Buffer exactly once /* When 1, execute the program in the Program Buffer exactly once
after performing the transfer, if any. after performing the transfer, if any.
*/ */
@ -38,6 +38,9 @@ class ACCESS_REGISTERFields extends Bundle {
/* 0: Don't do the operation specified by \Fwrite. /* 0: Don't do the operation specified by \Fwrite.
1: Do the operation specified by \Fwrite. 1: Do the operation specified by \Fwrite.
This bit can be used to just execute the Program Buffer without
having to worry about placing valid values into \Fsize or \Fregno.
*/ */
val transfer = Bool() val transfer = Bool()
@ -50,7 +53,10 @@ class ACCESS_REGISTERFields extends Bundle {
*/ */
val write = Bool() val write = Bool()
/* Number of the register to access, as described in Table~\ref{tab:regno}. /* Number of the register to access, as described in
Table~\ref{tab:regno}.
\Rdpc may be used as an alias for PC if this command is
supported on a non-halted hart.
*/ */
val regno = UInt(16.W) val regno = UInt(16.W)

View File

@ -2,7 +2,7 @@ package freechips.rocketchip.devices.debug
import Chisel._ import Chisel._
// This file was auto-generated from the repository at https://github.com/sifive/riscv-debug-spec.git, // This file was auto-generated from the repository at https://github.com/riscv/riscv-debug-spec.git,
// 'make chisel' // 'make chisel'
object DMI_RegAddrs { object DMI_RegAddrs {
@ -11,6 +11,14 @@ object DMI_RegAddrs {
This register reports status for the overall debug module This register reports status for the overall debug module
as well as the currently selected harts, as defined in \Fhasel. as well as the currently selected harts, as defined in \Fhasel.
Harts are nonexistent if they will never be part of this system, no
matter how long a user waits. Eg. in a simple single-hart system only
one hart exists, and all others are nonexistent.
Harts are unavailable if they might exist/become available at a later
time. Eg. in a multi-hart system some might temporarily be powered
down, or a system might support hot-swapping harts.
*/ */
def DMI_DMSTATUS = 0x11 def DMI_DMSTATUS = 0x11
@ -52,8 +60,10 @@ object DMI_RegAddrs {
def DMI_HAWINDOWSEL = 0x14 def DMI_HAWINDOWSEL = 0x14
/* This register provides R/W access to a 32-bit portion of the /* This register provides R/W access to a 32-bit portion of the
hart array mask register. The position of the window is determined by hart array mask register.
\Rhawindowsel. The position of the window is determined by \Rhawindowsel. I.e. bit 0
refers to hart $\Rhawindowsel * 32$, while bit 31 refers to hart
$\Rhawindowsel * 32 + 31$.
*/ */
def DMI_HAWINDOW = 0x15 def DMI_HAWINDOW = 0x15
@ -82,27 +92,29 @@ object DMI_RegAddrs {
*/ */
def DMI_ABSTRACTAUTO = 0x18 def DMI_ABSTRACTAUTO = 0x18
/* The Configuration String is described in the RISC-V Priviledged Specification. /* When {\tt devtreevalid} is set, reading this register returns bits 31:0
When {\tt cfgstrvalid} is set, reading this register returns bits 31:0 of the configuration of the Device Tree address. Reading the other {\tt devtreeaddr}
string address. Reading the other {\tt cfgstraddr} registers returns the upper bits of the registers returns the upper bits of the address.
address.
When system bus mastering is implemented, this should be the When system bus mastering is implemented, this must be an
address that should be used with the System Bus Access module. Otherwise, address that can be used with the System Bus Access module. Otherwise,
this should be the address that should be used to access the this must be an address that can be used to access the
config string when \Fhartsel=0. Device Tree from the hart with ID 0.
If {\tt cfgstrvalid} is 0, then the {\tt cfgstraddr} registers If {\tt devtreevalid} is 0, then the {\tt devtreeaddr} registers
hold identifier information which is not hold identifier information which is not
further specified in this document. further specified in this document.
The Device Tree itself is described in the RISC-V Privileged
Specification.
*/ */
def DMI_CFGSTRADDR0 = 0x19 def DMI_DEVTREEADDR0 = 0x19
def DMI_CFGSTRADDR1 = 0x1a def DMI_DEVTREEADDR1 = 0x1a
def DMI_CFGSTRADDR2 = 0x1b def DMI_DEVTREEADDR2 = 0x1b
def DMI_CFGSTRADDR3 = 0x1c def DMI_DEVTREEADDR3 = 0x1c
/* Basic read/write registers that may be read or changed by abstract /* Basic read/write registers that may be read or changed by abstract
commands. commands.
@ -110,6 +122,8 @@ object DMI_RegAddrs {
Accessing them while an abstract command is executing causes \Fcmderr Accessing them while an abstract command is executing causes \Fcmderr
to be set. to be set.
Attempts to write them while \Fbusy is set does not change their value.
The values in these registers may not be preserved after an abstract The values in these registers may not be preserved after an abstract
command is executed. The only guarantees on their contents are the ones command is executed. The only guarantees on their contents are the ones
offered by the command in question. If the command fails, no offered by the command in question. If the command fails, no
@ -121,6 +135,11 @@ object DMI_RegAddrs {
/* The {\tt progbuf} registers provide read/write access to the optional /* The {\tt progbuf} registers provide read/write access to the optional
program buffer. program buffer.
Accessing them while an abstract command is executing causes \Fcmderr
to be set.
Attempts to write them while \Fbusy is set does not change their value.
*/ */
def DMI_PROGBUF0 = 0x20 def DMI_PROGBUF0 = 0x20
@ -135,41 +154,12 @@ object DMI_RegAddrs {
*/ */
def DMI_AUTHDATA = 0x30 def DMI_AUTHDATA = 0x30
/* If \Fserialcount is 0, this register is not present.
*/
def DMI_SERCS = 0x34
/* If \Fserialcount is 0, this register is not present.
This register provides access to the write data queue of the serial port
selected by \Fserial in \Rsercs.
If the {\tt error} bit is not set and the queue is not full, a write to this register
adds the written data to the core-to-debugger queue.
Otherwise the {\tt error} bit is set and the write returns error.
A read to this register returns the last data written.
*/
def DMI_SERTX = 0x35
/* If \Fserialcount is 0, this register is not present.
This register provides access to the read data queues of the serial port
selected by \Fserial in \Rsercs.
If the {\tt error} bit is not set and the queue is not empty, a read from this register reads the
oldest entry in the debugger-to-core queue, and removes that entry from the queue.
Otherwise the {\tt error} bit is set and the read returns error.
*/
def DMI_SERRX = 0x36
def DMI_SBCS = 0x38 def DMI_SBCS = 0x38
/* If \Fsbasize is 0, then this register is not present. /* If \Fsbasize is 0, then this register is not present.
When the system bus master is busy, When the system bus master is busy,
writes to this register will return error writes to this register will set \Fsberror.
and \Fsberror is set.
If \Fsberror is 0 and \Fsbautoread is set then the system bus If \Fsberror is 0 and \Fsbautoread is set then the system bus
master will start master will start
@ -189,31 +179,31 @@ object DMI_RegAddrs {
/* If all of the {\tt sbaccess} bits in \Rsbcs are 0, then this register /* If all of the {\tt sbaccess} bits in \Rsbcs are 0, then this register
is not present. is not present.
If \Fsberror isn't 0 then accesses return error, and don't do anything Any successful system bus read updates the data in this register, and
else. marks it no longer stale.
Writes to this register: If \Fsberror isn't 0 then accesses do nothing.
\begin{steps}{Writes to this register:}
\item If the bus master is busy then accesses set \Fsberror, and
don't do anything else.
\item Start a bus write of {\tt sbdata} to {\tt sbaddress}.
\item If \Fsbautoincrement is set, increment {\tt sbaddress}.
\end{steps}
1. If the bus master is busy then accesses set \Fsberror, return error, \begin{steps}{Reads from this register:}
and don't do anything else. \item If the register is marked stale, then set \Fsberror and don't
do anything else.
\item ``Return'' the data.
\item Mark the register stale.
\item If \Fsbautoincrement is set, increment {\tt sbaddress}.
\item If \Fsbautoread is set, start another system bus read.
\end{steps}
2. Update internal data. Only \Rsbdatazero has this behavior. The other {\tt sbdata} registers
have no side effects. On systems that have buses wider than 32 bits, a
3. Start a bus write of the internal data to the internal address. debugger should access \Rsbdatazero after accessing the other {\tt
sbdata} registers.
4. If \Fsbautoincrement is set, increment the internal address.
Reads to this register:
1. If bits 31:0 of the internal data register haven't been updated
since the last time this register was read, then set \Fsberror, return
error, and don't do anything else.
2. ``Return'' the data.
3. If \Fsbautoincrement is set, increment the internal address.
4. If \Fsbautoread is set, start another system bus read.
*/ */
def DMI_SBDATA0 = 0x3c def DMI_SBDATA0 = 0x3c
@ -234,13 +224,47 @@ object DMI_RegAddrs {
class DMSTATUSFields extends Bundle { class DMSTATUSFields extends Bundle {
val reserved0 = UInt(14.W) val reserved0 = UInt(5.W)
/* This field is 1 when all currently selected harts have acknowledged the previous \Fresumereq. /* Gets set if the Debug Module was accessed incorrectly.
0 (none): No error.
1 (badaddr): There was an access to an unimplemented Debug Module
address.
7 (other): An access failed for another reason.
*/
val dmerr = UInt(3.W)
val reserved1 = UInt(1.W)
/* If 1, then there is an implicit {\tt ebreak} instruction at the
non-existent word immediately after the Program Buffer. This saves
the debugger from having to write the {\tt ebreak} itself, and
allows the Program Buffer to be one word smaller.
This must be 1 when \Fprogbufsize is 1.
*/
val impebreak = Bool()
val reserved2 = UInt(2.W)
/* This field is 1 when all currently selected harts have been reset but the reset has not been acknowledged.
*/
val allhavereset = Bool()
/* This field is 1 when any currently selected hart has been reset but the reset has not been acknowledged.
*/
val anyhavereset = Bool()
/* This field is 1 when all currently selected harts have acknowledged
the previous resume request.
*/ */
val allresumeack = Bool() val allresumeack = Bool()
/* This field is 1 when any currently selected hart has acknowledged the previous \Fresumereq. /* This field is 1 when any currently selected hart has acknowledged
the previous resume request.
*/ */
val anyresumeack = Bool() val anyresumeack = Bool()
@ -293,49 +317,58 @@ class DMSTATUSFields extends Bundle {
*/ */
val authbusy = Bool() val authbusy = Bool()
val reserved1 = UInt(1.W) val reserved3 = UInt(1.W)
val cfgstrvalid = Bool() /* 0: \Rdevtreeaddrzero--\Rdevtreeaddrthree hold information which
is not relevant to the Device Tree.
/* Reserved for future use. Reads as 0. 1: \Rdevtreeaddrzero--\Rdevtreeaddrthree registers hold the address of the
Device Tree.
*/ */
val versionhi = UInt(2.W) val devtreevalid = Bool()
/* 00: There is no Debug Module present. /* 0: There is no Debug Module present.
01: There is a Debug Module and it conforms to version 0.11 of this 1: There is a Debug Module and it conforms to version 0.11 of this
specification. specification.
10: There is a Debug Module and it conforms to version 0.13 of this 2: There is a Debug Module and it conforms to version 0.13 of this
specification. specification.
11: Reserved for future use. 15: There is a Debug Module but it does not conform to any
available version of this spec.
*/ */
val versionlo = UInt(2.W) val version = UInt(4.W)
} }
class DMCONTROLFields extends Bundle { class DMCONTROLFields extends Bundle {
/* Halt request signal for all currently selected harts. When set to 1, the /* Writes the halt request bit for all currently selected harts.
hart will halt if it is not currently halted. When set to 1, each selected hart will halt if it is not currently
Setting both \Fhaltreq and \Fresumereq leads to undefined behavior. halted.
Writing 1 or 0 has no effect on a hart which is already halted, but
the bit must be cleared to 0 before the hart is resumed.
Writes apply to the new value of \Fhartsel and \Fhasel. Writes apply to the new value of \Fhartsel and \Fhasel.
*/ */
val haltreq = Bool() val haltreq = Bool()
/* Resume request signal for all currently selected harts. When set to 1, /* Writes the resume request bit for all currently selected harts.
the hart will resume if it is currently halted. When set to 1, each selected hart will resume if it is currently
Setting both \Fhaltreq and \Fresumereq leads to undefined behavior. halted.
The resume request bit is ignored while the halt request bit is
set.
Writes apply to the new value of \Fhartsel and \Fhasel. Writes apply to the new value of \Fhartsel and \Fhasel.
*/ */
val resumereq = Bool() val resumereq = Bool()
/* This optional bit controls reset to all the currently selected harts. /* This optional field writes the reset bit for all the currently
To perform a reset the debugger writes 1, and then writes 0 to selected harts. To perform a reset the debugger writes 1, and then
deassert the reset signal. writes 0 to deassert the reset signal.
If this feature is not implemented, the bit always stays 0, so If this feature is not implemented, the bit always stays 0, so
after writing 1 the debugger can read the register back to see if after writing 1 the debugger can read the register back to see if
@ -345,7 +378,14 @@ class DMCONTROLFields extends Bundle {
*/ */
val hartreset = Bool() val hartreset = Bool()
val reserved0 = UInt(2.W) /* Writing 1 to this bit clears the {\tt havereset} bits for
any selected harts.
Writes apply to the new value of \Fhartsel and \Fhasel.
*/
val ackhavereset = Bool()
val reserved0 = UInt(1.W)
/* Selects the definition of currently selected harts. /* Selects the definition of currently selected harts.
@ -369,7 +409,11 @@ class DMCONTROLFields extends Bundle {
val reserved1 = UInt(14.W) val reserved1 = UInt(14.W)
/* This bit controls the reset signal from the DM to the rest of the /* This bit controls the reset signal from the DM to the rest of the
system. To perform a reset the debugger writes 1, and then writes 0 system. The signal should reset every part of the system, including
every hart, except for the DM and any logic required to access the
DM.
To perform a system reset the debugger writes 1,
and then writes 0
to deassert the reset. to deassert the reset.
*/ */
val ndmreset = Bool() val ndmreset = Bool()
@ -386,8 +430,8 @@ class DMCONTROLFields extends Bundle {
Debug Module after power up, including the platform's system reset Debug Module after power up, including the platform's system reset
or Debug Transport reset signals. or Debug Transport reset signals.
A debugger should pulse this bit low to ensure that the Debug A debugger may pulse this bit low to get the debug module into a
Module is fully reset and ready to use. known state.
Implementations may use this bit to aid debugging, for example by Implementations may use this bit to aid debugging, for example by
preventing the Debug Module from being power gated while debugging preventing the Debug Module from being power gated while debugging
@ -431,7 +475,7 @@ class HARTINFOFields extends Bundle {
shadowing the {\tt data} registers. shadowing the {\tt data} registers.
If \Fdataaccess is 1: Signed address of RAM where the {\tt data} If \Fdataaccess is 1: Signed address of RAM where the {\tt data}
registers are shadowed. registers are shadowed, to be used to access relative to \Rzero.
*/ */
val dataaddr = UInt(12.W) val dataaddr = UInt(12.W)
@ -524,11 +568,8 @@ class ABSTRACTCSFields extends Bundle {
val reserved0 = UInt(3.W) val reserved0 = UInt(3.W)
/* Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16. /* Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16.
TODO: Explain what can be done with each size of the buffer, to suggest
why you would want more or less words.
*/ */
val progsize = UInt(5.W) val progbufsize = UInt(5.W)
val reserved1 = UInt(11.W) val reserved1 = UInt(11.W)
@ -547,8 +588,9 @@ class ABSTRACTCSFields extends Bundle {
0 (none): No error. 0 (none): No error.
1 (busy): An abstract command was executing while \Rcommand or one 1 (busy): An abstract command was executing while \Rcommand,
of the {\tt data} registers was accessed. \Rabstractcs, \Rabstractauto was written, or when one
of the {\tt data} or {\tt progbuf} registers was read or written.
2 (not supported): The requested command is not supported. A 2 (not supported): The requested command is not supported. A
command that is not supported while the hart is running may be command that is not supported while the hart is running may be
@ -567,7 +609,7 @@ class ABSTRACTCSFields extends Bundle {
val reserved3 = UInt(3.W) val reserved3 = UInt(3.W)
/* Number of {\tt data} registers that are implemented as part of the /* Number of {\tt data} registers that are implemented as part of the
abstract command interface. Valid sizes are 0 - 8. abstract command interface. Valid sizes are 0 - 12.
*/ */
val datacount = UInt(5.W) val datacount = UInt(5.W)
@ -590,20 +632,20 @@ class COMMANDFields extends Bundle {
class ABSTRACTAUTOFields extends Bundle { class ABSTRACTAUTOFields extends Bundle {
/* When a bit in this field is 1, read or write accesses the corresponding {\tt progbuf} word /* When a bit in this field is 1, read or write accesses the corresponding {\tt progbuf} word
cause the command in \Rcommand to be executed again. cause the command in \Rcommand to be executed again.
*/ */
val autoexecprogbuf = UInt(16.W) val autoexecprogbuf = UInt(16.W)
val reserved0 = UInt(4.W) val reserved0 = UInt(4.W)
/* When a bit in this field is 1, read or write accesses the corresponding {\tt data} word /* When a bit in this field is 1, read or write accesses the corresponding {\tt data} word
cause the command in \Rcommand to be executed again. cause the command in \Rcommand to be executed again.
*/ */
val autoexecdata = UInt(12.W) val autoexecdata = UInt(12.W)
} }
class CFGSTRADDR0Fields extends Bundle { class DEVTREEADDR0Fields extends Bundle {
val addr = UInt(32.W) val addr = UInt(32.W)
@ -627,88 +669,6 @@ class AUTHDATAFields extends Bundle {
} }
class SERCSFields extends Bundle {
/* Number of supported serial ports.
*/
val serialcount = UInt(4.W)
val reserved0 = UInt(1.W)
/* Select which serial port is accessed by \Rserrx and \Rsertx.
*/
val serial = UInt(3.W)
val error7 = Bool()
val valid7 = Bool()
val full7 = Bool()
val error6 = Bool()
val valid6 = Bool()
val full6 = Bool()
val error5 = Bool()
val valid5 = Bool()
val full5 = Bool()
val error4 = Bool()
val valid4 = Bool()
val full4 = Bool()
val error3 = Bool()
val valid3 = Bool()
val full3 = Bool()
val error2 = Bool()
val valid2 = Bool()
val full2 = Bool()
val error1 = Bool()
val valid1 = Bool()
val full1 = Bool()
/* 1 when the debugger-to-core queue for serial port 0 has
over or underflowed. This bit will remain set until it is reset by
writing 1 to this bit.
*/
val error0 = Bool()
/* 1 when the core-to-debugger queue for serial port 0 is not empty.
*/
val valid0 = Bool()
/* 1 when the debugger-to-core queue for serial port 0 is full.
*/
val full0 = Bool()
}
class SERTXFields extends Bundle {
val data = UInt(32.W)
}
class SERRXFields extends Bundle {
val data = UInt(32.W)
}
class SBCSFields extends Bundle { class SBCSFields extends Bundle {
val reserved0 = UInt(11.W) val reserved0 = UInt(11.W)
@ -731,20 +691,18 @@ class SBCSFields extends Bundle {
4: 128-bit 4: 128-bit
If an unsupported system bus access size is written here, If an unsupported system bus access size is written here, the DM
the DM may not perform the access, or may perform the access does not perform the access and sberror is set to 3.
with any access size.
*/ */
val sbaccess = UInt(3.W) val sbaccess = UInt(3.W)
/* When 1, the internal address value (used by the system bus master) /* When 1, {\tt sbaddress} is incremented by the access size (in
is incremented by the access size (in bytes) selected in \Fsbaccess bytes) selected in \Fsbaccess after every system bus access.
after every system bus access.
*/ */
val sbautoincrement = Bool() val sbautoincrement = Bool()
/* When 1, every read from \Rsbdatazero automatically triggers a system /* When 1, every read from \Rsbdatazero automatically triggers a
bus read at the new address. system bus read at the (possibly auto-incremented) address.
*/ */
val sbautoread = Bool() val sbautoread = Bool()
@ -762,10 +720,9 @@ class SBCSFields extends Bundle {
3: There was some other error (eg. alignment). 3: There was some other error (eg. alignment).
4: The system bus master was busy when a one of the 4: The system bus master was busy when one of the
{\tt sbaddress} or {\tt sbdata} registers was written, {\tt sbaddress} or {\tt sbdata} registers was written,
or the {\tt sbdata} register was read when it had or \Rsbdatazero was read when it had stale data.
stale data.
*/ */
val sberror = UInt(3.W) val sberror = UInt(3.W)
@ -798,7 +755,7 @@ class SBCSFields extends Bundle {
class SBADDRESS0Fields extends Bundle { class SBADDRESS0Fields extends Bundle {
/* Accesses bits 31:0 of the internal address. /* Accesses bits 31:0 of the physical address in {\tt sbaddress}.
*/ */
val address = UInt(32.W) val address = UInt(32.W)
@ -806,8 +763,8 @@ class SBADDRESS0Fields extends Bundle {
class SBADDRESS1Fields extends Bundle { class SBADDRESS1Fields extends Bundle {
/* Accesses bits 63:32 of the internal address (if the system address /* Accesses bits 63:32 of the physical address in {\tt sbaddress} (if
bus is that wide). the system address bus is that wide).
*/ */
val address = UInt(32.W) val address = UInt(32.W)
@ -815,8 +772,8 @@ class SBADDRESS1Fields extends Bundle {
class SBADDRESS2Fields extends Bundle { class SBADDRESS2Fields extends Bundle {
/* Accesses bits 95:64 of the internal address (if the system address /* Accesses bits 95:64 of the physical address in {\tt sbaddress} (if
bus is that wide). the system address bus is that wide).
*/ */
val address = UInt(32.W) val address = UInt(32.W)
@ -824,7 +781,7 @@ class SBADDRESS2Fields extends Bundle {
class SBDATA0Fields extends Bundle { class SBDATA0Fields extends Bundle {
/* Accesses bits 31:0 of the internal data. /* Accesses bits 31:0 of {\tt sbdata}.
*/ */
val data = UInt(32.W) val data = UInt(32.W)
@ -832,8 +789,8 @@ class SBDATA0Fields extends Bundle {
class SBDATA1Fields extends Bundle { class SBDATA1Fields extends Bundle {
/* Accesses bits 63:32 of the internal data (if the system bus is /* Accesses bits 63:32 of {\tt sbdata} (if the system bus is that
that wide). wide).
*/ */
val data = UInt(32.W) val data = UInt(32.W)
@ -841,8 +798,8 @@ class SBDATA1Fields extends Bundle {
class SBDATA2Fields extends Bundle { class SBDATA2Fields extends Bundle {
/* Accesses bits 95:64 of the internal data (if the system bus is /* Accesses bits 95:64 of {\tt sbdata} (if the system bus is that
that wide). wide).
*/ */
val data = UInt(32.W) val data = UInt(32.W)
@ -850,8 +807,8 @@ class SBDATA2Fields extends Bundle {
class SBDATA3Fields extends Bundle { class SBDATA3Fields extends Bundle {
/* Accesses bits 127:96 of the internal data (if the system bus is /* Accesses bits 127:96 of {\tt sbdata} (if the system bus is that
that wide). wide).
*/ */
val data = UInt(32.W) val data = UInt(32.W)