diff --git a/src/main/scala/devices/debug/Periphery.scala b/src/main/scala/devices/debug/Periphery.scala index e94660f5703..1d0a89000df 100644 --- a/src/main/scala/devices/debug/Periphery.scala +++ b/src/main/scala/devices/debug/Periphery.scala @@ -14,6 +14,7 @@ import freechips.rocketchip.jtag._ import freechips.rocketchip.util._ import freechips.rocketchip.prci.{ClockSinkParameters, ClockSinkNode} import freechips.rocketchip.tilelink._ +import freechips.rocketchip.interrupts.{NullIntSyncSource} /** Protocols used for communicating with external debugging tools */ sealed trait DebugExportProtocol @@ -71,16 +72,16 @@ class ResetCtrlIO(val nComponents: Int)(implicit val p: Parameters) extends Bund */ trait HasPeripheryDebug { this: BaseSubsystem => - private val tlbus = locateTLBusWrapper(p(ExportDebug).slaveWhere) + private lazy val tlbus = locateTLBusWrapper(p(ExportDebug).slaveWhere) - val debugCustomXbarOpt = p(DebugModuleKey).map(params => LazyModule( new DebugCustomXbar(outputRequiresInput = false))) - val apbDebugNodeOpt = p(ExportDebug).apb.option(APBMasterNode(Seq(APBMasterPortParameters(Seq(APBMasterParameters("debugAPB")))))) + lazy val debugCustomXbarOpt = p(DebugModuleKey).map(params => LazyModule( new DebugCustomXbar(outputRequiresInput = false))) + lazy val apbDebugNodeOpt = p(ExportDebug).apb.option(APBMasterNode(Seq(APBMasterPortParameters(Seq(APBMasterParameters("debugAPB")))))) val debugTLDomainOpt = p(DebugModuleKey).map { _ => val domain = ClockSinkNode(Seq(ClockSinkParameters())) domain := tlbus.fixedClockNode domain } - val debugOpt = p(DebugModuleKey).map { params => + lazy val debugOpt = p(DebugModuleKey).map { params => val tlDM = LazyModule(new TLDebugModule(tlbus.beatBytes)) tlDM.node := tlbus.coupleTo("debug"){ TLFragmenter(tlbus) := _ } @@ -97,62 +98,65 @@ trait HasPeripheryDebug { this: BaseSubsystem => } tlDM } -} -trait HasPeripheryDebugModuleImp extends LazyModuleImp { - val outer: HasPeripheryDebug + lazy val debugNode = debugOpt.map(_.intnode).getOrElse(NullIntSyncSource()) - val psd = IO(new PSDIO) + val psd = InModuleBody { + val psd = IO(new PSDIO) + psd + } - val resetctrl = outer.debugOpt.map { outerdebug => - outerdebug.module.io.tl_reset := outer.debugTLDomainOpt.get.in.head._1.reset - outerdebug.module.io.tl_clock := outer.debugTLDomainOpt.get.in.head._1.clock - val resetctrl = IO(new ResetCtrlIO(outerdebug.dmOuter.dmOuter.intnode.edges.out.size)) - outerdebug.module.io.hartIsInReset := resetctrl.hartIsInReset - resetctrl.hartResetReq.foreach { rcio => outerdebug.module.io.hartResetReq.foreach { rcdm => rcio := rcdm }} - resetctrl + val resetctrl = InModuleBody { + debugOpt.map { debug => + debug.module.io.tl_reset := debugTLDomainOpt.get.in.head._1.reset + debug.module.io.tl_clock := debugTLDomainOpt.get.in.head._1.clock + val resetctrl = IO(new ResetCtrlIO(debug.dmOuter.dmOuter.intnode.edges.out.size)) + debug.module.io.hartIsInReset := resetctrl.hartIsInReset + resetctrl.hartResetReq.foreach { rcio => debug.module.io.hartResetReq.foreach { rcdm => rcio := rcdm }} + resetctrl + } } // noPrefix is workaround https://github.com/freechipsproject/chisel3/issues/1603 - val debug = noPrefix(outer.debugOpt.map { outerdebug => + val debug = InModuleBody { noPrefix(debugOpt.map { debugmod => val debug = IO(new DebugIO) require(!(debug.clockeddmi.isDefined && debug.systemjtag.isDefined), - "You cannot have both DMI and JTAG interface in HasPeripheryDebugModuleImp") + "You cannot have both DMI and JTAG interface in HasPeripheryDebug") require(!(debug.clockeddmi.isDefined && debug.apb.isDefined), - "You cannot have both DMI and APB interface in HasPeripheryDebugModuleImp") + "You cannot have both DMI and APB interface in HasPeripheryDebug") require(!(debug.systemjtag.isDefined && debug.apb.isDefined), - "You cannot have both APB and JTAG interface in HasPeripheryDebugModuleImp") + "You cannot have both APB and JTAG interface in HasPeripheryDebug") - debug.clockeddmi.foreach { dbg => outerdebug.module.io.dmi.get <> dbg } + debug.clockeddmi.foreach { dbg => debugmod.module.io.dmi.get <> dbg } (debug.apb - zip outer.apbDebugNodeOpt - zip outerdebug.module.io.apb_clock - zip outerdebug.module.io.apb_reset).foreach { + zip apbDebugNodeOpt + zip debugmod.module.io.apb_clock + zip debugmod.module.io.apb_reset).foreach { case (((io, apb), c ), r) => apb.out(0)._1 <> io c:= io.clock r:= io.reset } - outerdebug.module.io.debug_reset := debug.reset - outerdebug.module.io.debug_clock := debug.clock + debugmod.module.io.debug_reset := debug.reset + debugmod.module.io.debug_clock := debug.clock - debug.ndreset := outerdebug.module.io.ctrl.ndreset - debug.dmactive := outerdebug.module.io.ctrl.dmactive - outerdebug.module.io.ctrl.dmactiveAck := debug.dmactiveAck - debug.extTrigger.foreach { x => outerdebug.module.io.extTrigger.foreach {y => x <> y}} + debug.ndreset := debugmod.module.io.ctrl.ndreset + debug.dmactive := debugmod.module.io.ctrl.dmactive + debugmod.module.io.ctrl.dmactiveAck := debug.dmactiveAck + debug.extTrigger.foreach { x => debugmod.module.io.extTrigger.foreach {y => x <> y}} // TODO in inheriting traits: Set this to something meaningful, e.g. "component is in reset or powered down" - outerdebug.module.io.ctrl.debugUnavail.foreach { _ := false.B } + debugmod.module.io.ctrl.debugUnavail.foreach { _ := false.B } debug - }) + })} - val dtm = debug.flatMap(_.systemjtag.map(instantiateJtagDTM(_))) + val dtm = InModuleBody { debug.flatMap(_.systemjtag.map(instantiateJtagDTM(_))) } def instantiateJtagDTM(sj: SystemJTAGIO): DebugTransportModuleJTAG = { @@ -168,7 +172,7 @@ trait HasPeripheryDebugModuleImp extends LazyModuleImp { dtm.io.jtag_version := sj.version dtm.rf_reset := sj.reset - outer.debugOpt.map { outerdebug => + debugOpt.map { outerdebug => outerdebug.module.io.dmi.get.dmi <> dtm.io.dmi outerdebug.module.io.dmi.get.dmiClock := sj.jtag.TCK outerdebug.module.io.dmi.get.dmiReset := sj.reset diff --git a/src/main/scala/groundtest/GroundTestSubsystem.scala b/src/main/scala/groundtest/GroundTestSubsystem.scala index 621f4a244ae..ba3215f7f53 100644 --- a/src/main/scala/groundtest/GroundTestSubsystem.scala +++ b/src/main/scala/groundtest/GroundTestSubsystem.scala @@ -8,6 +8,7 @@ import freechips.rocketchip.diplomacy.{AddressSet, LazyModule} import freechips.rocketchip.interrupts.{IntSinkNode, IntSinkPortSimple} import freechips.rocketchip.subsystem.{BaseSubsystem, BaseSubsystemModuleImp, HasTiles, CanHaveMasterAXI4MemPort} import freechips.rocketchip.tilelink.{TLRAM, TLFragmenter} +import freechips.rocketchip.interrupts.{NullIntSyncSource} class GroundTestSubsystem(implicit p: Parameters) extends BaseSubsystem @@ -25,6 +26,9 @@ class GroundTestSubsystem(implicit p: Parameters) val tileStatusNodes = tiles.collect { case t: GroundTestTile => t.statusNode.makeSink() } + // no debug module + val debugNode = NullIntSyncSource() + override lazy val module = new GroundTestSubsystemModuleImp(this) } diff --git a/src/main/scala/interrupts/NullIntSource.scala b/src/main/scala/interrupts/NullIntSource.scala index 815bdfdeaa6..d906ac36fd9 100644 --- a/src/main/scala/interrupts/NullIntSource.scala +++ b/src/main/scala/interrupts/NullIntSource.scala @@ -18,8 +18,14 @@ class NullIntSource(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: } object NullIntSource { - def apply(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: Parameters): IntNode = { + def apply(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: Parameters): IntOutwardNode = { val null_int_source = LazyModule(new NullIntSource(num, ports, sources)) null_int_source.intnode } } + +object NullIntSyncSource { + def apply(num: Int = 1, ports: Int = 1, sources: Int = 1)(implicit p: Parameters): IntSyncOutwardNode = { + IntSyncCrossingSource() := NullIntSource(num, ports, sources) + } +} diff --git a/src/main/scala/interrupts/package.scala b/src/main/scala/interrupts/package.scala index 9d70f9b4668..a29898210ba 100644 --- a/src/main/scala/interrupts/package.scala +++ b/src/main/scala/interrupts/package.scala @@ -12,6 +12,10 @@ package object interrupts type IntOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] type IntNode = SimpleNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]] + type IntSyncInwardNode = InwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, SyncInterrupts] + type IntSyncOutwardNode = OutwardNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, SyncInterrupts] + type IntSyncNode = SimpleNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, SyncInterrupts] + implicit class IntClockDomainCrossing(private val x: HasClockDomainCrossing) extends AnyVal { def crossIn (n: IntInwardNode) (implicit valName: ValName) = IntInwardClockCrossingHelper(valName.name, x, n) def crossOut(n: IntOutwardNode)(implicit valName: ValName) = IntOutwardClockCrossingHelper(valName.name, x, n) diff --git a/src/main/scala/subsystem/HasTiles.scala b/src/main/scala/subsystem/HasTiles.scala index 5ec7e6d2553..d56c284503c 100644 --- a/src/main/scala/subsystem/HasTiles.scala +++ b/src/main/scala/subsystem/HasTiles.scala @@ -5,7 +5,6 @@ package freechips.rocketchip.subsystem import chisel3._ import chisel3.dontTouch import org.chipsalliance.cde.config.{Field, Parameters} -import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp} import freechips.rocketchip.devices.tilelink.{BasicBusBlocker, BasicBusBlockerParams, CLINTConsts, PLICKey, CanHavePeripheryPLIC, CanHavePeripheryCLINT} import freechips.rocketchip.diplomacy._ import freechips.rocketchip.interrupts._ @@ -102,7 +101,6 @@ case class TileSlavePortParams( trait HasTileInterruptSources extends CanHavePeripheryPLIC with CanHavePeripheryCLINT - with HasPeripheryDebug with InstantiatesTiles { this: BaseSubsystem => // TODO ideally this bound would be softened to LazyModule /** meipNode is used to create a single bit subsystem input in Configs without a PLIC */ @@ -230,7 +228,9 @@ trait DefaultTileContextType with HasTileInterruptSources with HasTileNotificationSinks with HasTileInputConstants -{ this: BaseSubsystem => } // TODO: ideally this bound would be softened to LazyModule +{ this: BaseSubsystem => + val debugNode: IntSyncOutwardNode +} // TODO: ideally this bound would be softened to LazyModule /** Standardized interface by which parameterized tiles can be attached to contexts containing interconnect resources. * @@ -291,10 +291,7 @@ trait CanAttachTile { // we stub out missing interrupts with constant sources here. // 1. Debug interrupt is definitely asynchronous in all cases. - domain.tile.intInwardNode := - context.debugOpt - .map { domain { IntSyncAsyncCrossingSink(3) } := _.intnode } - .getOrElse { NullIntSource() } + domain.tile.intInwardNode := domain { IntSyncAsyncCrossingSink(3) } := context.debugNode // 2. The CLINT and PLIC output interrupts are synchronous to the TileLink bus clock, // so might need to be synchronized depending on the Tile's crossing type. @@ -440,7 +437,7 @@ trait HasTiles extends InstantiatesTiles with HasCoreMonitorBundles with Default } /** Provides some Chisel connectivity to certain tile IOs */ -trait HasTilesModuleImp extends LazyModuleImp with HasPeripheryDebugModuleImp { +trait HasTilesModuleImp extends LazyModuleImp { val outer: HasTiles with HasTileInterruptSources with HasTileInputConstants val reset_vector = outer.tileResetVectorIONodes.zipWithIndex.map { case (n, i) => n.makeIO(s"reset_vector_$i") } diff --git a/src/main/scala/subsystem/RocketSubsystem.scala b/src/main/scala/subsystem/RocketSubsystem.scala index c3d52a8139e..e9e1f555515 100644 --- a/src/main/scala/subsystem/RocketSubsystem.scala +++ b/src/main/scala/subsystem/RocketSubsystem.scala @@ -6,6 +6,7 @@ import org.chipsalliance.cde.config.Parameters import freechips.rocketchip.diplomacy._ import freechips.rocketchip.prci.{ResetCrossingType, NoResetCrossing} import freechips.rocketchip.tile._ +import freechips.rocketchip.devices.debug.{HasPeripheryDebug} case class RocketCrossingParams( crossingType: ClockCrossingType = SynchronousCrossing(), @@ -29,7 +30,7 @@ trait HasRocketTiles extends HasTiles { this: BaseSubsystem => }).toList } -class RocketSubsystem(implicit p: Parameters) extends BaseSubsystem with HasRocketTiles { +class RocketSubsystem(implicit p: Parameters) extends BaseSubsystem with HasRocketTiles with HasPeripheryDebug { override lazy val module = new RocketSubsystemModuleImp(this) } diff --git a/src/main/scala/system/TestHarness.scala b/src/main/scala/system/TestHarness.scala index 19907224bbc..a1e37dea169 100644 --- a/src/main/scala/system/TestHarness.scala +++ b/src/main/scala/system/TestHarness.scala @@ -17,7 +17,7 @@ class TestHarness()(implicit p: Parameters) extends Module { val dut = Module(ldut.module) // Allow the debug ndreset to reset the dut, but not until the initial reset has completed - dut.reset := (reset.asBool | dut.debug.map { debug => AsyncResetReg(debug.ndreset) }.getOrElse(false.B)).asBool + dut.reset := (reset.asBool | ldut.debug.map { debug => AsyncResetReg(debug.ndreset) }.getOrElse(false.B)).asBool dut.dontTouchPorts() dut.tieOffInterrupts() @@ -34,5 +34,5 @@ class TestHarness()(implicit p: Parameters) extends Module { a.b.ready := false.B }) //ldut.l2_frontend_bus_axi4.foreach(_.tieoff) - Debug.connectDebug(dut.debug, dut.resetctrl, dut.psd, clock, reset.asBool, io.success) + Debug.connectDebug(ldut.debug, ldut.resetctrl, ldut.psd, clock, reset.asBool, io.success) }