Only punch realistic subset of DebugIO through chiptop

This commit is contained in:
Jerry Zhao
2020-08-27 23:48:01 -07:00
parent 98c4e6c711
commit 27b78f4de2

View File

@@ -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)))
} }
}) })