Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relax dependencies on HasPeripheryDebug #3279

Merged
merged 2 commits into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 37 additions & 33 deletions src/main/scala/devices/debug/Periphery.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) := _ }
Expand All @@ -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 = {

Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/main/scala/groundtest/GroundTestSubsystem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}

Expand Down
8 changes: 7 additions & 1 deletion src/main/scala/interrupts/NullIntSource.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
4 changes: 4 additions & 0 deletions src/main/scala/interrupts/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
13 changes: 5 additions & 8 deletions src/main/scala/subsystem/HasTiles.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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._
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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") }
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/subsystem/RocketSubsystem.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -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)
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/scala/system/TestHarness.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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)
}