diff --git a/src/main/scala/devices/debug/Debug.scala b/src/main/scala/devices/debug/Debug.scala index d2a4846a32e..ef93c3fad11 100755 --- a/src/main/scala/devices/debug/Debug.scala +++ b/src/main/scala/devices/debug/Debug.scala @@ -86,17 +86,22 @@ object DebugAbstractCommandType extends scala.Enumeration { * full specification. The implementation which receives this * object can perform more checks on what that implementation * actually supports. - * nComponents : The number of components to support debugging. - * nDMIAddrSize : Size of the Debug Bus Address - * nAbstractDataWords: Number of 32-bit words for Abstract Commands - * nProgamBufferWords: Number of 32-bit words for Program Buffer - * hasBusMaster: Whether or not a bus master should be included - * maxSupportedSBAccess: Maximum transaction size supported by System Bus Access logic. - * supportQuickAccess : Whether or not to support the quick access command. - * supportHartArray : Whether or not to implement the hart array register (if >1 hart). - * hasImplicitEbreak: There is an additional RO program buffer word containing an ebreak - * crossingHasSafeReset: Include "safe" logic in Async Crossings so that only one side needs to be reset. - **/ + * @param nComponents Number of components to support debugging. + * @param baseAddress Base offest for debugEntry and debugException + * @param nDMIAddrSize Size of the Debug Bus Address + * @param nAbstractDataWords Number of 32-bit words for Abstract Commands + * @param nProgamBufferWords Number of 32-bit words for Program Buffer + * @param hasBusMaster Whether or not a bus master should be included + * @param clockGate Whether or not to use dmactive as the clockgate for debug module + * @param maxSupportedSBAccess Maximum transaction size supported by System Bus Access logic. + * @param supportQuickAccess Whether or not to support the quick access command. + * @param supportHartArray Whether or not to implement the hart array register (if >1 hart). + * @param nHaltGroups Number of halt groups + * @param nExtTriggers Number of external triggers + * @param hasHartResets Feature to reset all the currently selected harts + * @param hasImplicitEbreak There is an additional RO program buffer word containing an ebreak + * @param crossingHasSafeReset Include "safe" logic in Async Crossings so that only one side needs to be reset. + */ case class DebugModuleParams ( baseAddress : BigInt = BigInt(0), @@ -130,7 +135,14 @@ case class DebugModuleParams ( } def address = AddressSet(baseAddress, 0xFFF) + /** the base address of DM */ def atzero = (baseAddress == 0) + /** The number of generated instructions + * + * When the base address is not zero, we need more instruction also, + * more dscratch registers) to load/store memory mapped data register + * because they may no longer be directly addressible with x0 + 12-bit imm + */ def nAbstractInstructions = if (atzero) 2 else 5 def debugEntry: BigInt = baseAddress + 0x800 def debugException: BigInt = baseAddress + 0x808 @@ -153,7 +165,7 @@ case object DebugModuleKey extends Field[Option[DebugModuleParams]](Some(DebugMo * * hartIdToHartSel: For systems where hart ids are not 1:1 with hartsel, provide the mapping. * hartSelToHartId: Provide inverse mapping of the above - **/ + */ case class DebugModuleHartSelFuncs ( hartIdToHartSel : (UInt) => UInt = (x:UInt) => x, hartSelToHartId : (UInt) => UInt = (x:UInt) => x @@ -191,25 +203,41 @@ class DebugAuthenticationIO () (implicit val p: Parameters) extends Parameterize // // ***************************************** -/* structure for passing hartsel between the "Outer" and "Inner" - */ - +/** Control signals for Inner, generated in Outer + * {{{ + * run control: resumreq, ackhavereset, halt-on-reset mask + * hart select: hasel, hartsel and the hart array mask + * }}} + */ class DebugInternalBundle (val nComponents: Int)(implicit val p: Parameters) extends ParameterizedBundle()(p) { + /** resume request */ val resumereq = Bool() + /** hart select */ val hartsel = UInt(10.W) + /** reset acknowledge */ val ackhavereset = Bool() + /** hart array enable */ val hasel = Bool() + /** hart array mask */ val hamask = Vec(nComponents, Bool()) + /** halt-on-reset mask */ val hrmask = Vec(nComponents, 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. */ class DebugCtrlBundle (nComponents: Int)(implicit val p: Parameters) extends ParameterizedBundle()(p) { + /** debug availability status for all harts */ val debugUnavail = Input(Vec(nComponents, Bool())) + /** reset signal + * + * for every part of the hardware platform, + * including every hart, except for the DM and any + * logic required to access the DM + */ val ndreset = Output(Bool()) + /** reset signal for the DM itself */ val dmactive = Output(Bool()) + /** dmactive acknowlege */ val dmactiveAck = Input(Bool()) } @@ -233,7 +261,7 @@ class DebugCtrlBundle (nComponents: Int)(implicit val p: Parameters) extends Par * DebugModule is responsible for control registers and RAM, and * Debug ROM. It runs partially off of the dmiClk (e.g. TCK) and * the TL clock. Therefore, it is divided into "Outer" portion (running - * of off dmiClock and dmiReset) and "Inner" (running off tl_clock and tl_reset). + * off dmiClock and dmiReset) and "Inner" (running off tl_clock and tl_reset). * This allows DMCONTROL.haltreq, hartsel, hasel, hawindowsel, hawindow, dmactive, * and ndreset to be modified even while the Core is in reset or not being clocked. * Not all reads from the Debugger to the Debug Module will actually complete @@ -269,7 +297,7 @@ object RWNotify { } // Local reg mapper function : Notify with value when written, take read input as presented. -// This allows checking or correcting the write value before storing it in the register field. +// This allows checking or correcting the write value before storing it in the register field. object WNotifyVal { def apply(n: Int, rVal: UInt, wVal: UInt, wNotify: Bool, desc: RegFieldDesc): RegField = { RegField(n, rVal, RegWriteFn((valid, data) => { @@ -312,10 +340,20 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod val supportHartArray = cfg.supportHartArray && (nComponents > 1) // no hart array if only one hart val io = IO(new Bundle { + /** structure for top-level Debug Module signals which aren't the bus interfaces. */ val ctrl = (new DebugCtrlBundle(nComponents)) + /** control signals for Inner, generated in Outer */ val innerCtrl = new DecoupledIO(new DebugInternalBundle(nComponents)) + /** debug interruption from Inner to Outer + * + * contains 2 type of debug interruption causes: + * - halt group + * - halt-on-reset + */ val hgDebugInt = Input(Vec(nComponents, Bool())) + /** hart reset request to core */ val hartResetReq = cfg.hasHartResets.option(Output(Vec(nComponents, Bool()))) + /** authentication support */ val dmAuthenticated = cfg.hasAuthentication.option(Input(Bool())) }) @@ -336,6 +374,7 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod val hartsel_mask = if (nComponents > 1) ((1 << p(MaxHartIdBits)) - 1).U else 0.U val DMCONTROLWrData = WireInit(0.U.asTypeOf(new DMCONTROLFields())) + val dmactiveWrEn = WireInit(false.B) val ndmresetWrEn = WireInit(false.B) val clrresethaltreqWrEn = WireInit(false.B) @@ -380,14 +419,15 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod //-------------------------------------------------------------- // Hart array mask and window - // HAMASK is 1 bit per component + // hamask is hart array mask(1 bit per component), which doesn't include the hart selected by dmcontrol.hartsello // HAWINDOWSEL selects a 32-bit slice of HAMASK to be visible for read/write in HAWINDOW //-------------------------------------------------------------- + val hamask = WireInit(VecInit(Seq.fill(nComponents) {false.B} )) def haWindowSize = 32 - // The following need to be declared even if supportHartArray is false due to reference - // at compile time by dmiNode.regmap + // The following need to be declared even if supportHartArray is false due to reference + // at compile time by dmiNode.regmap val HAWINDOWSELWrData = WireInit(0.U.asTypeOf(new HAWINDOWSELFields())) val HAWINDOWSELWrEn = WireInit(false.B) @@ -395,6 +435,7 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod val HAWINDOWWrData = WireInit(0.U.asTypeOf(new HAWINDOWFields())) val HAWINDOWWrEn = WireInit(false.B) + /** whether the hart is selected */ def hartSelected(hart: Int): Bool = { ((io.innerCtrl.bits.hartsel === hart.U) || (if (supportHartArray) io.innerCtrl.bits.hasel && io.innerCtrl.bits.hamask(hart) else false.B)) @@ -419,9 +460,9 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod } } } - val numHAMASKSlices = ((nComponents - 1)/haWindowSize)+1 HAWINDOWRdData.maskdata := 0.U // default, overridden below + // for each slice,use a hamaskReg to store the selection info for (ii <- 0 until numHAMASKSlices) { val sliceMask = if (nComponents > ((ii*haWindowSize) + haWindowSize-1)) (BigInt(1) << haWindowSize) - 1 // All harts in this slice exist else (BigInt(1)<<(nComponents - (ii*haWindowSize))) - 1 // Partial last slice @@ -441,8 +482,8 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod HAMASKNxt.maskdata := HAWINDOWWrData.maskdata } } - - // drive each slice of hamask with stored HAMASKReg or with new value being written + + // drive each slice of hamask with stored HAMASKReg or with new value being written for (jj <- 0 until haWindowSize) { if (((ii*haWindowSize) + jj) < nComponents) { val tempWrData = HAWINDOWWrData.maskdata.asBools @@ -464,7 +505,9 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod // Bits are set by writing 1 to DMCONTROL.setresethaltreq // Bits are cleared by writing 1 to DMCONTROL.clrresethaltreq // Spec says if both are 1, then clrresethaltreq is executed + // hrmask is the halt-on-reset mask which will be sent to inner //-------------------------------------------------------------- + val hrmask = Wire(Vec(nComponents, Bool())) val hrmaskNxt = Wire(Vec(nComponents, Bool())) val hrmaskReg = RegNext(next=hrmaskNxt, init=0.U.asTypeOf(hrmaskNxt)).suggestName("hrmaskReg") @@ -481,7 +524,6 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod } hrmask := hrmaskNxt - val dmControlRegFields = RegFieldGroup("dmcontrol", Some("debug module control register"), Seq( WNotifyVal(1, DMCONTROLReg.dmactive & io.ctrl.dmactiveAck, DMCONTROLWrData.dmactive, dmactiveWrEn, RegFieldDesc("dmactive", "debug module active", reset=Some(0))), @@ -526,7 +568,8 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod //-------------------------------------------------------------- // DMI register decoder for Outer //-------------------------------------------------------------- - // regmap addresses are byte offsets from lowest address + + // regmap addresses are byte offsets from lowest address def DMI_DMCONTROL_OFFSET = 0 def DMI_HARTINFO_OFFSET = ((DMI_HARTINFO - DMI_DMCONTROL) << 2) def DMI_HAWINDOWSEL_OFFSET = ((DMI_HAWINDOWSEL - DMI_DMCONTROL) << 2) @@ -551,18 +594,12 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod val debugIntRegs = RegNext(next=debugIntNxt, init=0.U.asTypeOf(debugIntNxt)).suggestName("debugIntRegs") debugIntNxt := debugIntRegs - val (intnode_out, _) = intnode.out.unzip for (component <- 0 until nComponents) { intnode_out(component)(0) := debugIntRegs(component) | io.hgDebugInt(component) } - // Halt request registers are set & cleared by writes to DMCONTROL.haltreq - // resumereq also causes the core to execute a 'dret', - // so resumereq is passed through to Inner. - // hartsel/hasel/hamask must also be used by the DebugModule state machine, - // so it is passed to Inner. - + // sends debug interruption to Core when dmcs.haltreq is set, for (component <- 0 until nComponents) { when (~dmactive || ~dmAuthenticated) { debugIntNxt(component) := false.B @@ -573,6 +610,11 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod } } } + // Halt request registers are set & cleared by writes to DMCONTROL.haltreq + // resumereq also causes the core to execute a 'dret', + // so resumereq is passed through to Inner. + // hartsel/hasel/hamask must also be used by the DebugModule state machine, + // so it is passed to Inner. // These registers ensure that requests to dmInner are not lost if inner clock isn't running or requests occur too close together. // If the innerCtrl async queue is not ready, the notification will be posted and held until ready is received. @@ -603,6 +645,7 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod io.ctrl.ndreset := DMCONTROLReg.ndmreset io.ctrl.dmactive := DMCONTROLReg.dmactive + // hart reset mechanism implementation if (cfg.hasHartResets) { val hartResetNxt = Wire(Vec(nComponents, Bool())) val hartResetReg = RegNext(next=hartResetNxt, init=0.U.asTypeOf(hartResetNxt)) @@ -615,7 +658,7 @@ class TLDebugModuleOuter(device: Device)(implicit p: Parameters) extends LazyMod omRegMap // FIXME: Remove this when withReset is removed }} } - +// wrap a Outer with a DMIToTL, derived by dmi clock & reset class TLDebugModuleOuterAsync(device: Device)(implicit p: Parameters) extends LazyModule { val cfg = p(DebugModuleKey).get @@ -659,12 +702,20 @@ class TLDebugModuleOuterAsync(device: Device)(implicit p: Parameters) extends La val io = IO(new Bundle { val dmi_clock = Input(Clock()) val dmi_reset = Input(Reset()) + /** Debug Module Interface bewteen DM and DTM + * + * The DTM provides access to one or more Debug Modules (DMs) using DMI + */ val dmi = (!p(ExportDebug).apb).option(Flipped(new DMIIO()(p))) // Optional APB Interface is fully diplomatic so is not listed here. val ctrl = new DebugCtrlBundle(nComponents) + /** conrol signals for Inner, generated in Outer */ val innerCtrl = new AsyncBundle(new DebugInternalBundle(nComponents), AsyncQueueParams.singleton(safe=cfg.crossingHasSafeReset)) + /** debug interruption generated in Inner */ val hgDebugInt = Input(Vec(nComponents, Bool())) + /** hart reset request to core */ val hartResetReq = p(DebugModuleKey).get.hasHartResets.option(Output(Vec(nComponents, Bool()))) + /** Authentication signal from core */ val dmAuthenticated = p(DebugModuleKey).get.hasAuthentication.option(Input(Bool())) }) val rf_reset = IO(Input(Reset())) // RF transform @@ -696,9 +747,8 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I val cfg = p(DebugModuleKey).get def getCfg = () => cfg - val dmTopAddr = (1 << cfg.nDMIAddrSize) << 2 - + /** dmiNode address set */ val dmiNode = TLRegisterNode( // Address is range 0 to 0x1FF except DMCONTROL, HARTINFO, HAWINDOWSEL, HAWINDOW which are handled by Outer address = AddressSet.misaligned(0, DMI_DMCONTROL << 2) ++ @@ -738,14 +788,32 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I ) val io = IO(new Bundle { + /** dm reset signal passed in from Outer */ val dmactive = Input(Bool()) + /** conrol signals for Inner + * + * it's generated by Outer and comes in + */ val innerCtrl = Flipped(new DecoupledIO(new DebugInternalBundle(nComponents))) + /** debug unavail signal passed in from Outer*/ val debugUnavail = Input(Vec(nComponents, Bool())) + /** debug interruption from Inner to Outer + * + * contain 2 type of debug interruption causes: + * - halt group + * - halt-on-reset + */ val hgDebugInt = Output(Vec(nComponents, Bool())) + /** interface for trigger */ val extTrigger = (nExtTriggers > 0).option(new DebugExtTriggerIO()) + /** vector to indicate which hart is in reset + * + * dm receives it from core and sends it to Inner + */ val hartIsInReset = Input(Vec(nComponents, Bool())) val tl_clock = Input(Clock()) val tl_reset = Input(Reset()) + /** Debug Authentication signals from core */ val auth = cfg.hasAuthentication.option(new DebugAuthenticationIO()) }) @@ -774,14 +842,23 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I // Register & Wire Declarations (which need to be pre-declared) //-------------------------------------------------------------- + // run control regs: tracking all the harts + // implements: see implementation-specific bits part + /** all harts halted status */ val haltedBitRegs = Reg(UInt(nComponents.W)) + /** all harts resume request status */ val resumeReqRegs = Reg(UInt(nComponents.W)) + /** all harts have reset status */ val haveResetBitRegs = Reg(UInt(nComponents.W)) + // default is 1,after resume, resumeAcks get 0 + /** all harts resume ack status */ val resumeAcks = Wire(UInt(nComponents.W)) // --- regmapper outputs + // hart state Id and En + // in Hart Bus Access ROM val hartHaltedWrEn = Wire(Bool()) val hartHaltedId = Wire(UInt(sbIdWidth.W)) val hartGoingWrEn = Wire(Bool()) @@ -791,6 +868,9 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I val hartExceptionWrEn = Wire(Bool()) val hartExceptionId = Wire(UInt(sbIdWidth.W)) + // progbuf and abstract data: byte-addressable control logic + // AccessLegal is set only when state = waiting + // RdEn and WrEnMaybe : contrl signal drived by DMI bus val dmiProgramBufferRdEn = WireInit(VecInit(Seq.fill(cfg.nProgramBufferWords * 4) {false.B} )) val dmiProgramBufferAccessLegal = WireInit(false.B) val dmiProgramBufferWrEnMaybe = WireInit(VecInit(Seq.fill(cfg.nProgramBufferWords * 4) {false.B} )) @@ -827,15 +907,16 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I } hamaskFull := hamaskReg } - + // Outer.hamask doesn't consider the hart selected by dmcontrol.hartsello, + // so append it here when (selectedHartReg < nComponents.U) { hamaskFull(selectedHartReg) := true.B } io.innerCtrl.ready := true.B - // Construct a Vec from io.innerCtrl fields indicating whether each hart is being selected in this write - // A hart may be selected by hartsel field or by hart array + // Construct a Vec from io.innerCtrl fields indicating whether each hart is being selected in this write + // A hart may be selected by hartsel field or by hart array val hamaskWrSel = WireInit(VecInit(Seq.fill(nComponents) {false.B} )) for (component <- 0 until nComponents ) { hamaskWrSel(component) := ((io.innerCtrl.bits.hartsel === component.U) || @@ -892,7 +973,8 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I DMSTATUSRdData.hasresethaltreq := true.B DMSTATUSRdData.anynonexistent := (selectedHartReg >= nComponents.U) // only hartsel can be nonexistent - // all harts nonexistent if hartsel is out of range and there are no harts selected in the hart array + + // all harts nonexistent if hartsel is out of range and there are no harts selected in the hart array DMSTATUSRdData.allnonexistent := (selectedHartReg >= nComponents.U) & (~hamaskFull.reduce(_ | _)) when (~DMSTATUSRdData.allnonexistent) { // if no existent harts selected, all other status is false @@ -914,7 +996,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I DMSTATUSRdData.confstrptrvalid := false.B DMSTATUSRdData.impebreak := (cfg.hasImplicitEbreak).B } - + when(~io.dmactive || ~dmAuthenticated) { haveResetBitRegs := 0.U }.otherwise { @@ -941,6 +1023,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I val hgParticipateHart = RegInit(VecInit(Seq.fill(nComponents)(0.U(hgBits.W)))) val hgParticipateTrig = if (nExtTriggers > 0) RegInit(VecInit(Seq.fill(nExtTriggers)(0.U(hgBits.W)))) else Nil + // assign group index to current seledcted harts for (component <- 0 until nComponents) { when (~io.dmactive || ~dmAuthenticated) { hgParticipateHart(component) := 0.U @@ -964,6 +1047,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I } } + // assign group index to trigger for (trigger <- 0 until nExtTriggers) { when (~io.dmactive || ~dmAuthenticated) { hgParticipateTrig(trigger) := 0.U @@ -1092,7 +1176,9 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I val ABSTRACTCSWrEnLegal = WireInit(false.B) val ABSTRACTCSWrEn = ABSTRACTCSWrEnMaybe && ABSTRACTCSWrEnLegal - + + // multiple error types + // find implement in the state machine part val errorBusy = WireInit(false.B) val errorException = WireInit(false.B) val errorUnsupported = WireInit(false.B) @@ -1110,6 +1196,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I }.elsewhen (errorHaltResume) { ABSTRACTCSReg.cmderr := DebugAbstractCommandError.ErrHaltResume.id.U }.otherwise { + //W1C when (ABSTRACTCSWrEn){ ABSTRACTCSReg.cmderr := ABSTRACTCSReg.cmderr & ~(ABSTRACTCSWrData.cmderr); } @@ -1125,6 +1212,11 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I } //---- ABSTRACTAUTO + // It is a mask indicating whether datai/probufi have the autoexcution permisson + // this part aims to produce 3 wires : autoexecData,autoexecProg,autoexec + // first two specify which reg supports autoexec + // autoexec is a control signal, meaning there is at least one enabled autoexec reg + // when autoexec is set, generate instructions using COMMAND register val ABSTRACTAUTOReset = WireInit(0.U.asTypeOf(new ABSTRACTAUTOFields())) val ABSTRACTAUTOReg = Reg(new ABSTRACTAUTOFields()) @@ -1148,12 +1240,13 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I } } + // Abstract Data access vector(byte-addressable) val dmiAbstractDataAccessVec = WireInit(VecInit(Seq.fill(cfg.nAbstractDataWords * 4) {false.B} )) dmiAbstractDataAccessVec := (dmiAbstractDataWrEnMaybe zip dmiAbstractDataRdEn).map{ case (r,w) => r | w} - + // Program Buffer access vector(byte-addressable) val dmiProgramBufferAccessVec = WireInit(VecInit(Seq.fill(cfg.nProgramBufferWords * 4) {false.B} )) dmiProgramBufferAccessVec := (dmiProgramBufferWrEnMaybe zip dmiProgramBufferRdEn).map{ case (r,w) => r | w} - + // at least one word access val dmiAbstractDataAccess = dmiAbstractDataAccessVec.reduce(_ || _ ) val dmiProgramBufferAccess = dmiProgramBufferAccessVec.reduce(_ || _) @@ -1195,6 +1288,8 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I val abstractDataNxt = WireInit(abstractDataMem) // --- Program Buffer + + // byte-addressible mem val programBufferMem = Reg(Vec(cfg.nProgramBufferWords*4, UInt(8.W))) val programBufferNxt = WireInit(programBufferMem) @@ -1203,34 +1298,41 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I // by harts executing code. //-------------------------------------------------------------- + // Run control logic when (~io.dmactive || ~dmAuthenticated) { haltedBitRegs := 0.U resumeReqRegs := 0.U }.otherwise { - + //remove those harts in reset resumeReqRegs := resumeReqRegs & ~(hartIsInResetSync.asUInt) val hartHaltedIdIndex = UIntToOH(hartSelFuncs.hartIdToHartSel(hartHaltedId)) val hartResumingIdIndex = UIntToOH(hartSelFuncs.hartIdToHartSel(hartResumingId)) val hartselIndex = UIntToOH(io.innerCtrl.bits.hartsel) when (hartHaltedWrEn) { + // add those harts halting and remove those in reset haltedBitRegs := (haltedBitRegs | hartHaltedIdIndex) & ~(hartIsInResetSync.asUInt) }.elsewhen (hartResumingWrEn) { + // remove those harts in reset and those in resume haltedBitRegs := (haltedBitRegs & ~(hartResumingIdIndex)) & ~(hartIsInResetSync.asUInt) }.otherwise { + // remove those harts in reset haltedBitRegs := haltedBitRegs & ~(hartIsInResetSync.asUInt) } when (hartResumingWrEn) { + // remove those harts in resume and those in reset resumeReqRegs := (resumeReqRegs & ~(hartResumingIdIndex)) & ~(hartIsInResetSync.asUInt) } when (resumereq) { + // set all sleceted harts to resumeReq, remove those in reset resumeReqRegs := (resumeReqRegs | hamaskWrSel.asUInt) & ~(hartIsInResetSync.asUInt) } } when (resumereq) { + // next cycle resumeAcls will be the negation of next cycle resumeReqRegs resumeAcks := (~resumeReqRegs & ~(hamaskWrSel.asUInt)) }.otherwise { resumeAcks := ~resumeReqRegs @@ -1300,6 +1402,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I //-------------------------------------------------------------- // Program Buffer Access (DMI ... System Bus can override) //-------------------------------------------------------------- + val omRegMap = dmiNode.regmap( (DMI_DMSTATUS << 2) -> dmstatusRegFields, //TODO (DMI_CFGSTRADDR0 << 2) -> cfgStrAddrFields, @@ -1413,6 +1516,7 @@ class TLDebugModuleInner(device: Device, getNComponents: () => Int, beatBytes: I //---------------------------- val accessRegisterCommandWr = WireInit(COMMANDWrData.asUInt().asTypeOf(new ACCESS_REGISTERFields())) + /** real COMMAND*/ val accessRegisterCommandReg = WireInit(COMMANDReg.asUInt().asTypeOf(new ACCESS_REGISTERFields())) // TODO: Quick Access @@ -1762,13 +1866,25 @@ class TLDebugModuleInnerAsync(device: Device, getNComponents: () => Int, beatByt val tl_clock = Input(Clock()) val tl_reset = Input(Reset()) // These are all asynchronous and come from Outer + /** reset signal for DM */ val dmactive = Input(Bool()) + /** conrol signals for Inner + * + * generated in Outer + */ val innerCtrl = Flipped(new AsyncBundle(new DebugInternalBundle(getNComponents()), AsyncQueueParams.singleton(safe=cfg.crossingHasSafeReset))) // This comes from tlClk domain. + /** debug available status */ val debugUnavail = Input(Vec(getNComponents(), Bool())) + /** debug interruption*/ val hgDebugInt = Output(Vec(getNComponents(), Bool())) val extTrigger = (p(DebugModuleKey).get.nExtTriggers > 0).option(new DebugExtTriggerIO()) + /** vector to indicate which hart is in reset + * + * dm receives it from core and sends it to Inner + */ val hartIsInReset = Input(Vec(getNComponents(), Bool())) + /** Debug Authentication signals from core */ val auth = p(DebugModuleKey).get.hasAuthentication.option(new DebugAuthenticationIO()) }) val rf_reset = IO(Input(Reset())) // RF transform @@ -1796,7 +1912,7 @@ class TLDebugModuleInnerAsync(device: Device, getNComponents: () => Int, beatByt /** Create a version of the TLDebugModule which includes a synchronization interface * internally for the DMI. This is no longer optional outside of this module - * because the Clock must run when tl_clock isn't running or tl_reset is asserted. + * because the Clock must run when tl_clock isn't running or tl_reset is asserted. */ class TLDebugModule(beatBytes: Int)(implicit p: Parameters) extends LazyModule { @@ -1839,13 +1955,24 @@ class TLDebugModule(beatBytes: Int)(implicit p: Parameters) extends LazyModule { val tl_clock = Input(Clock()) val tl_reset = Input(Reset()) + /** Debug control signals generated in Outer */ val ctrl = new DebugCtrlBundle(nComponents) + /** Debug Module Interface bewteen DM and DTM + * + * The DTM provides access to one or more Debug Modules (DMs) using DMI + */ val dmi = (!p(ExportDebug).apb).option(Flipped(new ClockedDMIIO())) val apb_clock = p(ExportDebug).apb.option(Input(Clock())) val apb_reset = p(ExportDebug).apb.option(Input(Reset())) val extTrigger = (p(DebugModuleKey).get.nExtTriggers > 0).option(new DebugExtTriggerIO()) + /** vector to indicate which hart is in reset + * + * dm receives it from core and sends it to Inner + */ val hartIsInReset = Input(Vec(nComponents, Bool())) + /** hart reset request generated by hartreset-logic in Outer */ val hartResetReq = p(DebugModuleKey).get.hasHartResets.option(Output(Vec(nComponents, Bool()))) + /** Debug Authentication signals from core */ val auth = p(DebugModuleKey).get.hasAuthentication.option(new DebugAuthenticationIO()) }) diff --git a/src/main/scala/devices/debug/Periphery.scala b/src/main/scala/devices/debug/Periphery.scala index f3fbba9a6d5..c78b5fc3e07 100644 --- a/src/main/scala/devices/debug/Periphery.scala +++ b/src/main/scala/devices/debug/Periphery.scala @@ -42,6 +42,7 @@ class ClockedAPBBundle(params: APBBundleParameters) extends APBBundle(params) { val reset = Reset() } + class DebugIO(implicit val p: Parameters) extends Bundle { val clock = Input(Clock()) val reset = Input(Reset()) @@ -175,7 +176,7 @@ trait HasPeripheryDebugModuleImp extends LazyModuleImp { dtm } } - +/** BlackBox to export DMI interface */ class SimDTM(implicit p: Parameters) extends BlackBox with HasBlackBoxResource { val io = IO(new Bundle { val clk = Input(Clock()) @@ -201,7 +202,7 @@ class SimDTM(implicit p: Parameters) extends BlackBox with HasBlackBoxResource { addResource("/vsrc/SimDTM.v") addResource("/csrc/SimDTM.cc") } - +/** BlackBox to export JTAG interface */ class SimJTAG(tickDelay: Int = 50) extends BlackBox(Map("TICK_DELAY" -> IntParam(tickDelay))) with HasBlackBoxResource { val io = IO(new Bundle { diff --git a/src/main/scala/devices/debug/dm_registers.scala b/src/main/scala/devices/debug/dm_registers.scala index dc367d4feb2..ed46fed9611 100644 --- a/src/main/scala/devices/debug/dm_registers.scala +++ b/src/main/scala/devices/debug/dm_registers.scala @@ -455,6 +455,7 @@ class DMSTATUSFields extends Bundle { } +/** @todo replace reserved0 with setkeepalive and clrkeepalive to confrom with Debug Spec v1.0 */ class DMCONTROLFields extends Bundle { /* Writing 0 clears the halt request bit for all currently selected