From 7ff9f88ad7972ba81c492ce992aced116ff82b9b Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Wed, 1 Mar 2017 21:57:00 -0800 Subject: [PATCH] rocket: connect interrupt map for Plic+Clint --- src/main/scala/coreplex/RocketTiles.scala | 42 ++++++- src/main/scala/diplomacy/Nodes.scala | 4 +- src/main/scala/uncore/devices/Prci.scala | 130 +++++++++++----------- 3 files changed, 106 insertions(+), 70 deletions(-) diff --git a/src/main/scala/coreplex/RocketTiles.scala b/src/main/scala/coreplex/RocketTiles.scala index 3202f128..206098f0 100644 --- a/src/main/scala/coreplex/RocketTiles.scala +++ b/src/main/scala/coreplex/RocketTiles.scala @@ -23,14 +23,18 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { private val crossing = p(RocketCrossing) private val configs = p(RocketTilesKey) - private val rocketTileIntNodes = configs.map { _ => IntInternalOutputNode(IntSinkPortSimple()) } - rocketTileIntNodes.foreach { _ := plic.intnode } + private val rocketTileIntNodes = configs.map { _ => IntInternalOutputNode(IntSinkPortSimple(ports = 2)) } + rocketTileIntNodes.foreach { n => + n := plic.intnode + n := clint.intnode + } private def wireInterrupts(x: TileInterrupts, i: Int) { - x := clint.module.io.tiles(i) x.debug := debug.module.io.debugInterrupts(i) x.meip := rocketTileIntNodes(i).bundleOut(0)(0) - x.seip.foreach { _ := rocketTileIntNodes(i).bundleOut(0)(1) } + x.seip.foreach { _ := rocketTileIntNodes(i).bundleOut(0)(1) } // optional + x.msip := rocketTileIntNodes(i).bundleOut(1)(0) + x.mtip := rocketTileIntNodes(i).bundleOut(1)(1) } val rocketWires: Seq[HasRocketTilesBundle => Unit] = configs.zipWithIndex.map { case (c, i) => @@ -48,6 +52,16 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { buffer.node :=* tile.masterNode l1tol2.node :=* buffer.node tile.slaveNode :*= cbus.node + ResourceBinding { + rocketTileIntNodes(i).edgesIn(0).source.sources.flatMap(_.resources).foreach { r => + r.bind(tile.device, ResourceInt(11)) // meip + if (c.core.useVM) r.bind(tile.device, ResourceInt(9)) // seip + } + rocketTileIntNodes(i).edgesIn(1).source.sources.flatMap(_.resources).foreach { r => + r.bind(tile.device, ResourceInt(3)) // msip + r.bind(tile.device, ResourceInt(7)) // mtip + } + } (io: HasRocketTilesBundle) => { // leave clock as default (simpler for hierarchical PnR) tile.module.io.hartid := UInt(i) @@ -63,6 +77,16 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { l1tol2.node :=* sink.node wrapper.slaveNode :*= source.node source.node :*= cbus.node + ResourceBinding { + rocketTileIntNodes(i).edgesIn(0).source.sources.flatMap(_.resources).foreach { r => + r.bind(wrapper.rocket.device, ResourceInt(11)) // meip + if (c.core.useVM) r.bind(wrapper.rocket.device, ResourceInt(9)) // seip + } + rocketTileIntNodes(i).edgesIn(1).source.sources.flatMap(_.resources).foreach { r => + r.bind(wrapper.rocket.device, ResourceInt(3)) // msip + r.bind(wrapper.rocket.device, ResourceInt(7)) // mtip + } + } (io: HasRocketTilesBundle) => { wrapper.module.clock := io.tcrs(i).clock wrapper.module.reset := io.tcrs(i).reset @@ -79,6 +103,16 @@ trait HasRocketTiles extends CoreplexRISCVPlatform { l1tol2.node :=* sink.node wrapper.slaveNode :*= source.node source.node :*= cbus.node + ResourceBinding { + rocketTileIntNodes(i).edgesIn(0).source.sources.flatMap(_.resources).foreach { r => + r.bind(wrapper.rocket.device, ResourceInt(11)) // meip + if (c.core.useVM) r.bind(wrapper.rocket.device, ResourceInt(9)) // seip + } + rocketTileIntNodes(i).edgesIn(1).source.sources.flatMap(_.resources).foreach { r => + r.bind(wrapper.rocket.device, ResourceInt(3)) // msip + r.bind(wrapper.rocket.device, ResourceInt(7)) // mtip + } + } (io: HasRocketTilesBundle) => { wrapper.module.clock := io.tcrs(i).clock wrapper.module.reset := io.tcrs(i).reset diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index 312e9997..2080e8c0 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -302,8 +302,8 @@ class MixedNexusNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data]( numPI: Range.Inclusive = 1 to 999) extends MixedNode(inner, outer)(numPO, numPI) { - require (numPO.end >= 1, s"${name} does not accept outputs${lazyModule.line}") - require (numPI.end >= 1, s"${name} does not accept inputs${lazyModule.line}") +// require (numPO.end >= 1, s"${name} does not accept outputs${lazyModule.line}") +// require (numPI.end >= 1, s"${name} does not accept inputs${lazyModule.line}") val externalIn: Boolean = true val externalOut: Boolean = true diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index f61b773c..fa05b29e 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -17,11 +17,6 @@ import tile.XLen /** Number of tiles */ case object NTiles extends Field[Int] -class CoreplexLocalInterrupts extends Bundle { - val mtip = Bool() - val msip = Bool() -} - object ClintConsts { def msipOffset(hart: Int) = hart * msipBytes @@ -30,71 +25,78 @@ object ClintConsts def msipBytes = 4 def timecmpBytes = 8 def size = 0x10000 + def timeWidth = 64 + def regWidth = 32 + def ints = 2 } -trait MixCoreplexLocalInterrupterParameters { - implicit val p: Parameters -} - -trait CoreplexLocalInterrupterBundle extends Bundle with MixCoreplexLocalInterrupterParameters { - val tiles = Vec(p(NTiles), new CoreplexLocalInterrupts).asOutput - val rtcTick = Bool(INPUT) -} - -trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCoreplexLocalInterrupterParameters { - val io: CoreplexLocalInterrupterBundle - val address: AddressSet - - val timeWidth = 64 - val regWidth = 32 - - val time = Seq.fill(timeWidth/regWidth)(Reg(init=UInt(0, width = regWidth))) - when (io.rtcTick) { - val newTime = time.asUInt + UInt(1) - for ((reg, i) <- time zip (0 until timeWidth by regWidth)) - reg := newTime >> i - } - - val timecmp = Seq.fill(p(NTiles)) { Seq.fill(timeWidth/regWidth)(Reg(UInt(width = regWidth))) } - val ipi = Seq.fill(p(NTiles)) { RegInit(UInt(0, width = 1)) } - - for ((tile, i) <- io.tiles zipWithIndex) { - tile.msip := ipi(i)(0) - tile.mtip := time.asUInt >= timecmp(i).asUInt - } - - /* 0000 msip hart 0 - * 0004 msip hart 1 - * 4000 mtimecmp hart 0 lo - * 4004 mtimecmp hart 0 hi - * 4008 mtimecmp hart 1 lo - * 400c mtimecmp hart 1 hi - * bff8 mtime lo - * bffc mtime hi - */ - - regmap( - 0 -> makeRegFields(ipi), - ClintConsts.timecmpOffset(0) -> makeRegFields(timecmp.flatten), - ClintConsts.timeOffset -> makeRegFields(time)) - - def makeRegFields(s: Seq[UInt]) = s.map(r => RegField(regWidth, r)) -} - -/** Power, Reset, Clock, Interrupt */ -// Magic TL2 Incantation to create a TL2 Slave -// prci0 => at most 4095 devices -class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Parameters) - extends TLRegisterRouter(address, "clint", Seq("riscv,clint0"), size = ClintConsts.size, beatBytes = p(XLen)/8, undefZero = true)( - new TLRegBundle((), _) with CoreplexLocalInterrupterBundle)( - new TLRegModule((), _, _) with CoreplexLocalInterrupterModule) +class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Parameters) extends LazyModule { + import ClintConsts._ + + // clint0 => at most 4095 devices + val device = new SimpleDevice("clint", Seq("riscv,clint0")) { + override val alwaysExtended = true + } + + val node = TLRegisterNode( + address = AddressSet(address, size-1), + device = device, + beatBytes = p(XLen)/8) + + val intnode = IntNexusNode( + numSourcePorts = 0 to 1024, + numSinkPorts = 0 to 0, + sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(ints, Seq(Resource(device, "int"))))) }, + sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }) + + // Legacy stuff: val globalConfigString = Seq( s"rtc {\n", - s" addr 0x${(address + ClintConsts.timeOffset).toString(16)};\n", + s" addr 0x${(address + timeOffset).toString(16)};\n", s"};\n").mkString val hartConfigStrings = (0 until p(NTiles)).map { i => Seq( - s" timecmp 0x${(address + ClintConsts.timecmpOffset(i)).toString(16)};\n", - s" ipi 0x${(address + ClintConsts.msipOffset(i)).toString(16)};\n").mkString + s" timecmp 0x${(address + timecmpOffset(i)).toString(16)};\n", + s" ipi 0x${(address + msipOffset(i)).toString(16)};\n").mkString + } + + lazy val module = new LazyModuleImp(this) { + val io = new Bundle { + val rtcTick = Bool(INPUT) + val int = intnode.bundleOut + val in = node.bundleIn + } + + val time = Seq.fill(timeWidth/regWidth)(Reg(init=UInt(0, width = regWidth))) + when (io.rtcTick) { + val newTime = time.asUInt + UInt(1) + for ((reg, i) <- time zip (0 until timeWidth by regWidth)) + reg := newTime >> i + } + + val timecmp = Seq.fill(p(NTiles)) { Seq.fill(timeWidth/regWidth)(Reg(UInt(width = regWidth))) } + val ipi = Seq.fill(p(NTiles)) { RegInit(UInt(0, width = 1)) } + + io.int.zipWithIndex.foreach { case (int, i) => + int(0) := ipi(i)(0) // msip + int(1) := time.asUInt >= timecmp(i).asUInt // mtip + } + + /* 0000 msip hart 0 + * 0004 msip hart 1 + * 4000 mtimecmp hart 0 lo + * 4004 mtimecmp hart 0 hi + * 4008 mtimecmp hart 1 lo + * 400c mtimecmp hart 1 hi + * bff8 mtime lo + * bffc mtime hi + */ + + def makeRegFields(s: Seq[UInt]) = s.map(r => RegField(regWidth, r)) + + node.regmap( + 0 -> makeRegFields(ipi), + timecmpOffset(0) -> makeRegFields(timecmp.flatten), + timeOffset -> makeRegFields(time)) } }