Only punch realistic subset of DebugIO through chiptop
This commit is contained in:
@@ -7,6 +7,7 @@ import chisel3.experimental.{Analog, IO}
|
|||||||
import freechips.rocketchip.config.{Field, Config, Parameters}
|
import freechips.rocketchip.config.{Field, Config, Parameters}
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
|
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
|
||||||
import freechips.rocketchip.devices.debug._
|
import freechips.rocketchip.devices.debug._
|
||||||
|
import freechips.rocketchip.jtag.{JTAGIO}
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.system.{SimAXIMem}
|
import freechips.rocketchip.system.{SimAXIMem}
|
||||||
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
|
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
|
||||||
@@ -163,30 +164,65 @@ object AddIOCells {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add IO cells to a debug module and name the IO ports.
|
* Add IO cells to a debug module and name the IO ports, for debug IO which must go off-chip
|
||||||
* @param psd A PSDIO bundle
|
* For on-chip debug IO, drive them appropriately
|
||||||
|
* @param system A BaseSubsystem that might have a debug module
|
||||||
* @param resetctrlOpt An optional ResetCtrlIO bundle
|
* @param resetctrlOpt An optional ResetCtrlIO bundle
|
||||||
* @param debugOpt An optional DebugIO bundle
|
* @param debugOpt An optional DebugIO bundle
|
||||||
* @return Returns a tuple3 of (Top-level PSDIO IO; Optional top-level DebugIO IO; a list of IOCell module references)
|
* @return Returns a tuple2 of (Generated debug io ports, Generated IOCells)
|
||||||
*/
|
*/
|
||||||
def debug(psd: PSDIO, resetctrlOpt: Option[ResetCtrlIO], debugOpt: Option[DebugIO])(implicit p: Parameters):
|
def debug(system: HasPeripheryDebugModuleImp)(implicit p: Parameters): (Seq[Bundle], Seq[IOCell]) = {
|
||||||
(PSDIO, Option[ResetCtrlIO], Option[DebugIO], Seq[IOCell]) = {
|
system.debug.map { debug =>
|
||||||
val (psdPort, psdIOs) = IOCell.generateIOFromSignal(
|
|
||||||
psd, Some("iocell_psd"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
|
||||||
val debugTuple = debugOpt.map(d =>
|
|
||||||
IOCell.generateIOFromSignal(d, Some("iocell_debug"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync))
|
|
||||||
val debugPortOpt: Option[DebugIO] = debugTuple.map(_._1)
|
|
||||||
val debugIOs: Seq[IOCell] = debugTuple.map(_._2).toSeq.flatten
|
|
||||||
debugPortOpt.foreach(_.suggestName("debug"))
|
|
||||||
|
|
||||||
val resetctrlTuple = resetctrlOpt.map(d =>
|
// We never use the PSDIO, so tie it off on-chip
|
||||||
IOCell.generateIOFromSignal(d, Some("iocell_resetctrl"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync))
|
system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) }
|
||||||
val resetctrlPortOpt: Option[ResetCtrlIO] = resetctrlTuple.map(_._1)
|
|
||||||
val resetctrlIOs: Seq[IOCell] = resetctrlTuple.map(_._2).toSeq.flatten
|
|
||||||
resetctrlPortOpt.foreach(_.suggestName("resetctrl"))
|
|
||||||
|
|
||||||
psdPort.suggestName("psd")
|
// Set resetCtrlOpt with the system reset
|
||||||
(psdPort, resetctrlPortOpt, debugPortOpt, psdIOs ++ debugIOs ++ resetctrlIOs)
|
system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := system.reset.asBool } }
|
||||||
|
|
||||||
|
system.debug.map { d =>
|
||||||
|
// Tie off extTrigger
|
||||||
|
d.extTrigger.foreach { t =>
|
||||||
|
t.in.req := false.B
|
||||||
|
t.out.ack := t.out.req
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tie off disableDebug
|
||||||
|
d.disableDebug.foreach { d => d := false.B }
|
||||||
|
|
||||||
|
// Drive JTAG on-chip IOs
|
||||||
|
d.systemjtag.map { j =>
|
||||||
|
j.reset := system.reset
|
||||||
|
j.mfr_id := system.p(JtagDTMKey).idcodeManufId.U(11.W)
|
||||||
|
j.part_number := system.p(JtagDTMKey).idcodePartNum.U(16.W)
|
||||||
|
j.version := system.p(JtagDTMKey).idcodeVersion.U(4.W)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Connect DebugClockAndReset to system implicit clock. TODO this should use the clock of the bus the debug module is attached to
|
||||||
|
Debug.connectDebugClockAndReset(Some(debug), system.clock)(system.p)
|
||||||
|
|
||||||
|
// Add IOCells for the DMI/JTAG/APB ports
|
||||||
|
|
||||||
|
val dmiTuple = debug.clockeddmi.map { d =>
|
||||||
|
IOCell.generateIOFromSignal(d, Some("iocell_dmi"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
||||||
|
}
|
||||||
|
dmiTuple.map(_._1).foreach(_.suggestName("dmi"))
|
||||||
|
|
||||||
|
val jtagTuple = debug.systemjtag.map { j =>
|
||||||
|
IOCell.generateIOFromSignal(j.jtag, Some("iocell_jtag"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
||||||
|
}
|
||||||
|
jtagTuple.map(_._1).foreach(_.suggestName("jtag"))
|
||||||
|
|
||||||
|
val apbTuple = debug.apb.map { a =>
|
||||||
|
IOCell.generateIOFromSignal(a, Some("iocell_apb"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
||||||
|
}
|
||||||
|
apbTuple.map(_._1).foreach(_.suggestName("apb"))
|
||||||
|
|
||||||
|
val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq
|
||||||
|
(allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq)
|
||||||
|
}.getOrElse((Nil, Nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -364,40 +400,53 @@ class WithTieOffL2FBusAXI extends OverrideIOBinder({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO we need to rethink what "Tie-off-debug" means. The current system punches out
|
class WithSimDebug extends OverrideIOBinder({
|
||||||
// excessive IOs.
|
|
||||||
class WithTiedOffDebug extends OverrideIOBinder({
|
|
||||||
(system: HasPeripheryDebugModuleImp) => {
|
(system: HasPeripheryDebugModuleImp) => {
|
||||||
val (psdPort, resetctrlOpt, debugPortOpt, ioCells) =
|
val (ports, iocells) = AddIOCells.debug(system)(system.p)
|
||||||
AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p)
|
|
||||||
val harnessFn = (th: HasHarnessSignalReferences) => {
|
val harnessFn = (th: HasHarnessSignalReferences) => {
|
||||||
Debug.tieoffDebug(debugPortOpt, resetctrlOpt, Some(psdPort))(system.p)
|
val dtm_success = Wire(Bool())
|
||||||
// tieoffDebug doesn't actually tie everything off :/
|
when (dtm_success) { th.success := true.B }
|
||||||
debugPortOpt.foreach { d =>
|
ports.map {
|
||||||
d.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare; cdmi.dmiClock := th.harnessClock })
|
case d: ClockedDMIIO =>
|
||||||
d.dmactiveAck := DontCare
|
val dtm = Module(new SimDTM()(system.p)).connect(th.harnessClock, th.harnessReset.asBool, d, dtm_success)
|
||||||
d.clock := th.harnessClock // TODO fix: This should be driven from within the chip
|
case j: JTAGIO =>
|
||||||
|
val jtag = Module(new SimJTAG(tickDelay=3)).connect(j, th.harnessClock, th.harnessReset.asBool, ~(th.harnessReset.asBool), dtm_success)
|
||||||
|
case _ =>
|
||||||
|
require(false, "We only support DMI or JTAG simulated debug connections")
|
||||||
}
|
}
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
Seq((Seq(psdPort) ++ resetctrlOpt ++ debugPortOpt.toSeq, Nil, Some(harnessFn)))
|
Seq((ports, iocells, Some(harnessFn)))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO we need to rethink what this does. The current system punches out excessive IOs.
|
class WithTiedOffDebug extends OverrideIOBinder({
|
||||||
// Some of the debug clock/reset should be driven from on-chip
|
|
||||||
class WithSimDebug extends OverrideIOBinder({
|
|
||||||
(system: HasPeripheryDebugModuleImp) => {
|
(system: HasPeripheryDebugModuleImp) => {
|
||||||
val (psdPort, resetctrlPortOpt, debugPortOpt, ioCells) =
|
val (ports, iocells) = AddIOCells.debug(system)(system.p)
|
||||||
AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p)
|
|
||||||
val harnessFn = (th: HasHarnessSignalReferences) => {
|
val harnessFn = (th: HasHarnessSignalReferences) => {
|
||||||
val dtm_success = Wire(Bool())
|
ports.map {
|
||||||
Debug.connectDebug(debugPortOpt, resetctrlPortOpt, psdPort, th.harnessClock, th.harnessReset.asBool, dtm_success)(system.p)
|
case d: ClockedDMIIO =>
|
||||||
when (dtm_success) { th.success := true.B }
|
d.dmi.req.valid := false.B
|
||||||
th.dutReset := th.harnessReset.asBool | debugPortOpt.map { debug => AsyncResetReg(debug.ndreset).asBool }.getOrElse(false.B)
|
d.dmi.req.bits := DontCare
|
||||||
|
d.dmi.resp.ready := true.B
|
||||||
|
d.dmiClock := th.harnessClock
|
||||||
|
d.dmiReset := th.harnessReset
|
||||||
|
case j: JTAGIO =>
|
||||||
|
j.TCK := true.B.asClock
|
||||||
|
j.TMS := true.B
|
||||||
|
j.TDI := true.B
|
||||||
|
j.TRSTn.foreach { r => r := true.B }
|
||||||
|
case a: ClockedAPBBundle =>
|
||||||
|
a.tieoff()
|
||||||
|
a.clock := false.B.asClock
|
||||||
|
a.reset := true.B.asAsyncReset
|
||||||
|
a.psel := false.B
|
||||||
|
a.penable := false.B
|
||||||
|
case _ => require(false)
|
||||||
|
}
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
Seq((Seq(psdPort) ++ debugPortOpt.toSeq, ioCells, Some(harnessFn)))
|
Seq((ports, iocells, Some(harnessFn)))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user