diff --git a/src/main/scala/coreplex/RocketCoreplex.scala b/src/main/scala/coreplex/RocketCoreplex.scala index f39f5db0..6bac3fd4 100644 --- a/src/main/scala/coreplex/RocketCoreplex.scala +++ b/src/main/scala/coreplex/RocketCoreplex.scala @@ -84,6 +84,8 @@ trait HasRocketTiles extends HasSystemBus lip.foreach { coreIntXbar.intnode := _ } // lip wrapper.coreIntNode := coreIntXbar.intnode + wrapper.intOutputNode.foreach { plic.intnode := _ } + wrapper } } diff --git a/src/main/scala/rocket/BusErrorUnit.scala b/src/main/scala/rocket/BusErrorUnit.scala index 76e40b61..45a75eeb 100644 --- a/src/main/scala/rocket/BusErrorUnit.scala +++ b/src/main/scala/rocket/BusErrorUnit.scala @@ -25,13 +25,14 @@ class L1BusErrors(implicit p: Parameters) extends CoreBundle()(p) with BusErrors None, None, dcache.correctable, dcache.uncorrectable) } -class BusErrorUnit[T <: BusErrors](t: => T, addr: BigInt)(implicit p: Parameters) extends LazyModule { +case class BusErrorUnitParams(addr: BigInt, size: Int = 4096) + +class BusErrorUnit[T <: BusErrors](t: => T, params: BusErrorUnitParams)(implicit p: Parameters) extends LazyModule { val regWidth = 64 - val size = 64 val device = new SimpleDevice("bus-error-unit", Seq("sifive,buserror0")) val intNode = IntSourceNode(IntSourcePortSimple(resources = device.int)) val node = TLRegisterNode( - address = Seq(AddressSet(addr, size-1)), + address = Seq(AddressSet(params.addr, params.size-1)), device = device, beatBytes = p(XLen)/8) @@ -45,7 +46,7 @@ class BusErrorUnit[T <: BusErrors](t: => T, addr: BigInt)(implicit p: Parameters val sources = io.errors.toErrorList val mask = sources.map(_.nonEmpty.B).asUInt val cause = Reg(init = UInt(0, log2Ceil(sources.lastIndexWhere(_.nonEmpty) + 1))) - val value = Reg(UInt(width = sources.flatten.map(_.getWidth).max)) + val value = Reg(UInt(width = sources.flatten.map(_.bits.getWidth).max)) require(value.getWidth <= regWidth) val enable = Reg(init = mask) val interrupt = Reg(init = UInt(0, sources.size)) diff --git a/src/main/scala/rocket/RocketCore.scala b/src/main/scala/rocket/RocketCore.scala index 15d2ac6e..898fa9b1 100644 --- a/src/main/scala/rocket/RocketCore.scala +++ b/src/main/scala/rocket/RocketCore.scala @@ -30,6 +30,7 @@ case class RocketCoreParams( fastLoadWord: Boolean = true, fastLoadByte: Boolean = false, jumpInFrontend: Boolean = true, + tileControlAddr: Option[BigInt] = None, mulDiv: Option[MulDivParams] = Some(MulDivParams()), fpu: Option[FPUParams] = Some(FPUParams()) ) extends CoreParams { diff --git a/src/main/scala/rocket/ScratchpadSlavePort.scala b/src/main/scala/rocket/ScratchpadSlavePort.scala index 2d27642c..201fb7d0 100644 --- a/src/main/scala/rocket/ScratchpadSlavePort.scala +++ b/src/main/scala/rocket/ScratchpadSlavePort.scala @@ -100,21 +100,29 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend { val module: CanHaveScratchpadModule val cacheBlockBytes = p(CacheBlockBytes) - val slaveNode = TLInputNode() // Up to two uses for this input node: + val intOutputNode = tileParams.core.tileControlAddr.map(dummy => IntOutputNode()) + val slaveNode = TLInputNode() // Up to three uses for this input node: // 1) Frontend always exists, but may or may not have a scratchpad node // 2) ScratchpadSlavePort always has a node, but only exists when the HellaCache has a scratchpad + // 3) BusErrorUnit sometimes has a node val fg = LazyModule(new TLFragmenter(tileParams.core.fetchBytes, cacheBlockBytes, earlyAck=true)) val ww = LazyModule(new TLWidthWidget(xBytes)) val scratch = tileParams.dcache.flatMap { d => d.scratch.map(s => LazyModule(new ScratchpadSlavePort(AddressSet(s, d.dataScratchpadBytes-1), xBytes, tileParams.core.useAtomics))) } + val busErrorUnit = tileParams.core.tileControlAddr map { a => + val beu = LazyModule(new BusErrorUnit(new L1BusErrors, BusErrorUnitParams(a))) + intOutputNode.get := beu.intNode + beu + } DisableMonitors { implicit p => frontend.slaveNode :*= fg.node fg.node :*= ww.node ww.node :*= slaveNode scratch foreach { lm => lm.node := TLFragmenter(xBytes, cacheBlockBytes, earlyAck=true)(slaveNode) } + busErrorUnit foreach { lm => lm.node := TLFragmenter(xBytes, cacheBlockBytes, earlyAck=true)(slaveNode) } } def findScratchpadFromICache: Option[AddressSet] = scratch.map { s => @@ -130,6 +138,7 @@ trait CanHaveScratchpad extends HasHellaCache with HasICacheFrontend { trait CanHaveScratchpadBundle extends HasHellaCacheBundle with HasICacheFrontendBundle { val outer: CanHaveScratchpad val slave = outer.slaveNode.bundleIn + val intOutput = outer.intOutputNode.map(_.bundleOut) } trait CanHaveScratchpadModule extends HasHellaCacheModule with HasICacheFrontendModule { @@ -137,4 +146,8 @@ trait CanHaveScratchpadModule extends HasHellaCacheModule with HasICacheFrontend val io: CanHaveScratchpadBundle outer.scratch.foreach { lm => dcachePorts += lm.module.io.dmem } + outer.busErrorUnit.foreach { lm => + lm.module.io.errors.dcache := outer.dcache.module.io.errors + lm.module.io.errors.icache := outer.frontend.module.io.errors + } } diff --git a/src/main/scala/tile/Core.scala b/src/main/scala/tile/Core.scala index a4133c8f..0662b678 100644 --- a/src/main/scala/tile/Core.scala +++ b/src/main/scala/tile/Core.scala @@ -27,6 +27,7 @@ trait CoreParams { val nLocalInterrupts: Int val nL2TLBEntries: Int val jumpInFrontend: Boolean + val tileControlAddr: Option[BigInt] def instBytes: Int = instBits / 8 def fetchBytes: Int = fetchWidth * instBytes diff --git a/src/main/scala/tile/RocketTile.scala b/src/main/scala/tile/RocketTile.scala index 72467826..1e2db5f6 100644 --- a/src/main/scala/tile/RocketTile.scala +++ b/src/main/scala/tile/RocketTile.scala @@ -168,6 +168,7 @@ abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p: val rocket = LazyModule(new RocketTile(rtp, hartid)) val masterNode: OutputNode[_,_,_,_,_] val slaveNode: InputNode[_,_,_,_,_] + val intOutputNode = rocket.intOutputNode.map(dummy => IntOutputNode()) val asyncIntNode = IntInputNode() val periphIntNode = IntInputNode() val coreIntNode = IntInputNode() @@ -195,10 +196,19 @@ abstract class RocketTileWrapper(rtp: RocketTileParams, hartid: Int)(implicit p: } } + def outputInterruptXingLatency: Int + + rocket.intOutputNode.foreach { rocketIntOutputNode => + val outXing = LazyModule(new IntXing(outputInterruptXingLatency)) + intOutputNode.get := outXing.intnode + outXing.intnode := rocketIntOutputNode + } + lazy val module = new LazyModuleImp(this) { val io = new CoreBundle with HasExternallyDrivenTileConstants { val master = masterNode.bundleOut val slave = slaveNode.bundleIn + val outputInterrupts = intOutputNode.map(_.bundleOut) val asyncInterrupts = asyncIntNode.bundleIn val periphInterrupts = periphIntNode.bundleIn val coreInterrupts = coreIntNode.bundleIn @@ -224,6 +234,8 @@ class SyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) intXbar.intnode := xing.intnode intXbar.intnode := periphIntNode intXbar.intnode := coreIntNode + + def outputInterruptXingLatency = 0 } class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) { @@ -251,6 +263,8 @@ class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters intXbar.intnode := asyncXing.intnode intXbar.intnode := periphXing.intnode intXbar.intnode := coreIntNode + + def outputInterruptXingLatency = 3 } class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters) extends RocketTileWrapper(rtp, hartid) { @@ -279,4 +293,6 @@ class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Paramet intXbar.intnode := asyncXing.intnode intXbar.intnode := periphXing.intnode intXbar.intnode := coreIntNode + + def outputInterruptXingLatency = 1 }