diff --git a/src/main/scala/rocket/CSR.scala b/src/main/scala/rocket/CSR.scala index 2d8dd0e1743..2407dd9c4c1 100644 --- a/src/main/scala/rocket/CSR.scala +++ b/src/main/scala/rocket/CSR.scala @@ -205,6 +205,11 @@ class PerfCounterIO(implicit p: Parameters) extends CoreBundle val inc = UInt(INPUT, log2Ceil(1+retireWidth)) } +class TraceDoctor(val traceWidth: Int) extends Bundle { + val valid = Bool() + val bits = Vec(traceWidth, Bool()) +} + class TracedInstruction(implicit p: Parameters) extends CoreBundle { val valid = Bool() val iaddr = UInt(width = coreMaxAddrBits) diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index 90b8d57588f..2789b0adb52 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -49,7 +49,8 @@ case class RocketCoreParams( mvendorid: Int = 0, // 0 means non-commercial implementation mimpid: Int = 0x20181004, // release date in BCD mulDiv: Option[MulDivParams] = Some(MulDivParams()), - fpu: Option[FPUParams] = Some(FPUParams()) + fpu: Option[FPUParams] = Some(FPUParams()), + setTraceDoctorWidth: Int = 0 ) extends CoreParams { val lgPauseCycles = 5 val haveFSDirty = false @@ -62,6 +63,8 @@ case class RocketCoreParams( val lrscCycles: Int = 80 // worst case is 14 mispredicted branches + slop override def minFLen: Int = fpu.map(_.minFLen).getOrElse(32) override def customCSRs(implicit p: Parameters) = new RocketCustomCSRs + + override def traceDoctorWidth: Int = setTraceDoctorWidth } trait HasRocketCoreParameters extends HasCoreParameters { @@ -949,6 +952,24 @@ class Rocket(tile: RocketTile)(implicit p: Parameters) extends CoreModule()(p) coreMonitorBundle.excpt := csr.io.trace(0).exception coreMonitorBundle.priv_mode := csr.io.trace(0).priv + if (io.traceDoctor.traceWidth >= (64 + 64 + (retireWidth * 64))) { + val traceValids = for (i <- 0 until retireWidth) yield { + csr.io.trace(i).valid + } + val traceTimestamp = csr.io.time + val traceAddresses = for (i <- 0 until retireWidth) yield { + csr.io.trace(0).iaddr(vaddrBitsExtended-1, 0).sextTo(xLen) + } + val coreStalled = csr.io.csr_stall + + io.traceDoctor.valid := traceValids.reduce(_||_) && !coreStalled + io.traceDoctor.bits := Cat(Seq( + traceTimestamp(63, 0).pad(64), + traceValids.reverse.asUInt()(retireWidth - 1, 0).pad(64), + traceAddresses.map(a => a(63, 0).pad(64)).reverse.asUInt() + ).reverse).pad(io.traceDoctor.traceWidth).asBools + } + if (enableCommitLog) { val t = csr.io.trace(0) val rd = wb_waddr diff --git a/src/main/scala/tile/BaseTile.scala b/src/main/scala/tile/BaseTile.scala index a333912f097..e2144f8c333 100644 --- a/src/main/scala/tile/BaseTile.scala +++ b/src/main/scala/tile/BaseTile.scala @@ -92,7 +92,7 @@ trait HasNonDiplomaticTileParameters { def masterPortBeatBytes = p(SystemBusKey).beatBytes // TODO make HellaCacheIO diplomatic and remove this brittle collection of hacks - // Core PTW DTIM coprocessors + // Core PTW DTIM coprocessors def dcacheArbPorts = 1 + usingVM.toInt + usingDataScratchpad.toInt + p(BuildRoCC).size + tileParams.core.useVector.toInt // TODO merge with isaString in CSR.scala @@ -265,6 +265,10 @@ abstract class BaseTile private (val crossing: ClockCrossingType, q: Parameters) // assuming the core itself is diplomatic. // Then these nodes should just become IdentityNodes of their respective type + val traceDoctorSourceNode = BundleBridgeSource(() => new TraceDoctor(tileParams.core.traceDoctorWidth)) + private val traceDoctorNexus = BundleBroadcast[TraceDoctor]() // backwards compatiblity; not blocked during stretched reset + val traceDoctorNode: BundleBridgeOutwardNode[TraceDoctor] = traceDoctorNexus := traceDoctorSourceNode + protected def traceRetireWidth = tileParams.core.retireWidth /** Node for the core to drive legacy "raw" instruction trace. */ val traceSourceNode = BundleBridgeSource(() => Vec(traceRetireWidth, new TracedInstruction())) diff --git a/src/main/scala/tile/Core.scala b/src/main/scala/tile/Core.scala index 09fa4ad029c..5f307d09821 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -50,6 +50,9 @@ trait CoreParams { val nPTECacheEntries: Int val mtvecInit: Option[BigInt] val mtvecWritable: Boolean + + def traceDoctorWidth: Int = 0 + def customCSRs(implicit p: Parameters): CustomCSRs = new CustomCSRs def hasSupervisorMode: Boolean = useSupervisor || useVM @@ -149,6 +152,7 @@ trait HasCoreIO extends HasTileParameters { val fpu = new FPUCoreIO().flip val rocc = new RoCCCoreIO().flip val trace = Vec(coreParams.retireWidth, new TracedInstruction).asOutput + val traceDoctor = new TraceDoctor(coreParams.traceDoctorWidth).asOutput val bpwatch = Vec(coreParams.nBreakpoints, new BPWatch(coreParams.retireWidth)).asOutput val cease = Bool().asOutput val wfi = Bool().asOutput diff --git a/src/main/scala/tile/RocketTile.scala b/src/main/scala/tile/RocketTile.scala index 619c9debdab..4754f7d94ab 100644 --- a/src/main/scala/tile/RocketTile.scala +++ b/src/main/scala/tile/RocketTile.scala @@ -151,6 +151,8 @@ class RocketTileModuleImp(outer: RocketTile) extends BaseTileModuleImp(outer) // Pass through various external constants and reports that were bundle-bridged into the tile outer.traceSourceNode.bundle <> core.io.trace + outer.traceDoctorSourceNode.bundle <> core.io.traceDoctor + core.io.traceStall := outer.traceAuxSinkNode.bundle.stall outer.bpwatchSourceNode.bundle <> core.io.bpwatch core.io.hartid := outer.hartIdSinkNode.bundle