rocket: use diplomatic interrupts
This makes it possible for the PLIC to work with heterogenous cores.
This commit is contained in:
parent
d3c5318714
commit
4535de2669
@ -49,7 +49,6 @@ trait HasCoreplexParameters {
|
||||
lazy val cbusConfig = p(CBusConfig)
|
||||
lazy val l1tol2Config = p(L1toL2Config)
|
||||
lazy val nTiles = tilesParams.size
|
||||
lazy val hasSupervisor = tilesParams.exists(_.core.useVM) // TODO ask andrew about this
|
||||
lazy val l2Config = p(BankedL2Config)
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ trait CoreplexRISCVPlatform extends CoreplexNetwork {
|
||||
val module: CoreplexRISCVPlatformModule
|
||||
|
||||
val debug = LazyModule(new TLDebugModule())
|
||||
val plic = LazyModule(new TLPLIC(hasSupervisor, maxPriorities = 7))
|
||||
val plic = LazyModule(new TLPLIC(maxPriorities = 7))
|
||||
val clint = LazyModule(new CoreplexLocalInterrupter)
|
||||
|
||||
debug.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node)
|
||||
|
@ -23,20 +23,6 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
||||
private val crossing = p(RocketCrossing)
|
||||
private val configs = p(RocketTilesKey)
|
||||
|
||||
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.debug := debug.module.io.debugInterrupts(i)
|
||||
x.meip := rocketTileIntNodes(i).bundleOut(0)(0)
|
||||
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) =>
|
||||
val pWithExtra = p.alterPartial {
|
||||
case TileKey => c
|
||||
@ -45,6 +31,15 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
||||
case PAddrBits => l1tol2.node.edgesIn(0).bundle.addressBits
|
||||
}
|
||||
|
||||
// Hack debug interrupt into a node (future debug module should use diplomacy)
|
||||
val debugNode = IntInternalInputNode(IntSourcePortSimple())
|
||||
|
||||
val intBar = LazyModule(new IntXbar)
|
||||
intBar.intnode := debugNode
|
||||
intBar.intnode := clint.intnode // msip+mtip
|
||||
intBar.intnode := plic.intnode // meip
|
||||
if (c.core.useVM) intBar.intnode := plic.intnode // seip
|
||||
|
||||
crossing match {
|
||||
case Synchronous => {
|
||||
val tile = LazyModule(new RocketTile(c, i)(pWithExtra))
|
||||
@ -52,21 +47,12 @@ 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
|
||||
}
|
||||
}
|
||||
tile.intNode := intBar.intnode
|
||||
(io: HasRocketTilesBundle) => {
|
||||
// leave clock as default (simpler for hierarchical PnR)
|
||||
tile.module.io.hartid := UInt(i)
|
||||
tile.module.io.resetVector := io.resetVector
|
||||
wireInterrupts(tile.module.io.interrupts, i)
|
||||
debugNode.bundleOut(0)(0) := debug.module.io.debugInterrupts(i)
|
||||
}
|
||||
}
|
||||
case Asynchronous(depth, sync) => {
|
||||
@ -76,23 +62,14 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
||||
sink.node :=* wrapper.masterNode
|
||||
l1tol2.node :=* sink.node
|
||||
wrapper.slaveNode :*= source.node
|
||||
wrapper.intNode := intBar.intnode
|
||||
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
|
||||
wrapper.module.io.hartid := UInt(i)
|
||||
wrapper.module.io.resetVector := io.resetVector
|
||||
wireInterrupts(wrapper.module.io.interrupts, i)
|
||||
debugNode.bundleOut(0)(0) := debug.module.io.debugInterrupts(i)
|
||||
}
|
||||
}
|
||||
case Rational => {
|
||||
@ -102,23 +79,14 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
||||
sink.node :=* wrapper.masterNode
|
||||
l1tol2.node :=* sink.node
|
||||
wrapper.slaveNode :*= source.node
|
||||
wrapper.intNode := intBar.intnode
|
||||
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
|
||||
wrapper.module.io.hartid := UInt(i)
|
||||
wrapper.module.io.resetVector := io.resetVector
|
||||
wireInterrupts(wrapper.module.io.interrupts, i)
|
||||
debugNode.bundleOut(0)(0) := debug.module.io.debugInterrupts(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,6 +87,19 @@ class RocketTile(val rocketParams: RocketTileParams, val hartid: Int)(implicit p
|
||||
|
||||
ResourceBinding {
|
||||
Resource(device, "reg").bind(ResourceInt(BigInt(hartid)))
|
||||
|
||||
// debug, msip, mtip, meip, seip offsets in CSRs
|
||||
val intMap = Seq(65535, 3, 7, 11, 9)
|
||||
|
||||
intNode.edgesIn.flatMap(_.source.sources).map { case s =>
|
||||
for (i <- s.range.start until s.range.end) {
|
||||
intMap.lift(i).foreach { j =>
|
||||
s.resources.foreach { r =>
|
||||
r.bind(device, ResourceInt(j))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override lazy val module = new RocketTileModule(this)
|
||||
@ -100,7 +113,6 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne
|
||||
with CanHaveScratchpadModule {
|
||||
|
||||
val core = Module(p(BuildCore)(outer.p))
|
||||
core.io.interrupts := io.interrupts
|
||||
core.io.hartid := io.hartid
|
||||
outer.frontend.module.io.cpu <> core.io.imem
|
||||
outer.frontend.module.io.resetVector := io.resetVector
|
||||
@ -115,6 +127,13 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne
|
||||
core.io.rocc.interrupt := lr.module.io.core.interrupt
|
||||
}
|
||||
|
||||
// Decode the interrupt vector
|
||||
core.io.interrupts.debug := io.interrupts(0)(0)
|
||||
core.io.interrupts.msip := io.interrupts(0)(1)
|
||||
core.io.interrupts.mtip := io.interrupts(0)(2)
|
||||
core.io.interrupts.meip := io.interrupts(0)(3)
|
||||
core.io.interrupts.seip.foreach { _ := io.interrupts(0)(4) }
|
||||
|
||||
// TODO eliminate this redundancy
|
||||
val h = dcachePorts.size
|
||||
val c = core.dcacheArbPorts
|
||||
@ -139,15 +158,19 @@ class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters
|
||||
rocket.slaveNode :*= sink.node
|
||||
sink.node :*= slaveNode
|
||||
|
||||
val intNode = IntInputNode()
|
||||
val xing = LazyModule(new IntXing(3))
|
||||
rocket.intNode := xing.intnode
|
||||
xing.intnode := intNode
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
val master = masterNode.bundleOut
|
||||
val slave = slaveNode.bundleIn
|
||||
val interrupts = intNode.bundleIn
|
||||
val hartid = UInt(INPUT, p(XLen))
|
||||
val interrupts = new TileInterrupts()(p).asInput
|
||||
val resetVector = UInt(INPUT, p(XLen))
|
||||
}
|
||||
rocket.module.io.interrupts := ShiftRegister(io.interrupts, 3)
|
||||
// signals that do not change:
|
||||
rocket.module.io.hartid := io.hartid
|
||||
rocket.module.io.resetVector := io.resetVector
|
||||
@ -167,15 +190,19 @@ class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Paramet
|
||||
rocket.slaveNode :*= sink.node
|
||||
sink.node :*= slaveNode
|
||||
|
||||
val intNode = IntInputNode()
|
||||
val xing = LazyModule(new IntXing(1))
|
||||
rocket.intNode := xing.intnode
|
||||
xing.intnode := intNode
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
val io = new Bundle {
|
||||
val master = masterNode.bundleOut
|
||||
val slave = slaveNode.bundleIn
|
||||
val interrupts = intNode.bundleIn
|
||||
val hartid = UInt(INPUT, p(XLen))
|
||||
val interrupts = new TileInterrupts()(p).asInput
|
||||
val resetVector = UInt(INPUT, p(XLen))
|
||||
}
|
||||
rocket.module.io.interrupts := ShiftRegister(io.interrupts, 1)
|
||||
// signals that do not change:
|
||||
rocket.module.io.hartid := io.hartid
|
||||
rocket.module.io.resetVector := io.resetVector
|
||||
|
@ -53,11 +53,13 @@ trait HasTileLinkMasterPort extends HasTileParameters {
|
||||
implicit val p: Parameters
|
||||
val module: HasTileLinkMasterPortModule
|
||||
val masterNode = TLOutputNode()
|
||||
val intNode = IntSinkNode(IntSinkPortSimple())
|
||||
}
|
||||
|
||||
trait HasTileLinkMasterPortBundle {
|
||||
val outer: HasTileLinkMasterPort
|
||||
val master = outer.masterNode.bundleOut
|
||||
val interrupts = outer.intNode.bundleIn
|
||||
}
|
||||
|
||||
trait HasTileLinkMasterPortModule {
|
||||
@ -73,7 +75,6 @@ abstract class BaseTile(tileParams: TileParams)(implicit p: Parameters) extends
|
||||
class BaseTileBundle[+L <: BaseTile](_outer: L) extends BareTileBundle(_outer)
|
||||
with HasTileLinkMasterPortBundle {
|
||||
val hartid = UInt(INPUT, p(XLen))
|
||||
val interrupts = new TileInterrupts()(p).asInput
|
||||
val resetVector = UInt(INPUT, p(XLen))
|
||||
}
|
||||
|
||||
|
@ -53,9 +53,8 @@ object PLICConsts
|
||||
}
|
||||
|
||||
/** Platform-Level Interrupt Controller */
|
||||
class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC000000)(implicit p: Parameters) extends LazyModule
|
||||
class TLPLIC(maxPriorities: Int, address: BigInt = 0xC000000)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val contextsPerHart = if (supervisor) 2 else 1
|
||||
require (maxPriorities >= 0)
|
||||
|
||||
// plic0 => max devices 1023
|
||||
@ -81,7 +80,7 @@ class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC00000
|
||||
val intnode = IntNexusNode(
|
||||
numSourcePorts = 0 to 1024,
|
||||
numSinkPorts = 0 to 1024,
|
||||
sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(contextsPerHart, Seq(Resource(device, "int"))))) },
|
||||
sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(1, Seq(Resource(device, "int"))))) },
|
||||
sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) })
|
||||
|
||||
/* Negotiated sizes */
|
||||
|
Loading…
Reference in New Issue
Block a user