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 cbusConfig = p(CBusConfig)
|
||||||
lazy val l1tol2Config = p(L1toL2Config)
|
lazy val l1tol2Config = p(L1toL2Config)
|
||||||
lazy val nTiles = tilesParams.size
|
lazy val nTiles = tilesParams.size
|
||||||
lazy val hasSupervisor = tilesParams.exists(_.core.useVM) // TODO ask andrew about this
|
|
||||||
lazy val l2Config = p(BankedL2Config)
|
lazy val l2Config = p(BankedL2Config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ trait CoreplexRISCVPlatform extends CoreplexNetwork {
|
|||||||
val module: CoreplexRISCVPlatformModule
|
val module: CoreplexRISCVPlatformModule
|
||||||
|
|
||||||
val debug = LazyModule(new TLDebugModule())
|
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)
|
val clint = LazyModule(new CoreplexLocalInterrupter)
|
||||||
|
|
||||||
debug.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node)
|
debug.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node)
|
||||||
|
@ -23,20 +23,6 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
|||||||
private val crossing = p(RocketCrossing)
|
private val crossing = p(RocketCrossing)
|
||||||
private val configs = p(RocketTilesKey)
|
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 rocketWires: Seq[HasRocketTilesBundle => Unit] = configs.zipWithIndex.map { case (c, i) =>
|
||||||
val pWithExtra = p.alterPartial {
|
val pWithExtra = p.alterPartial {
|
||||||
case TileKey => c
|
case TileKey => c
|
||||||
@ -45,6 +31,15 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
|||||||
case PAddrBits => l1tol2.node.edgesIn(0).bundle.addressBits
|
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 {
|
crossing match {
|
||||||
case Synchronous => {
|
case Synchronous => {
|
||||||
val tile = LazyModule(new RocketTile(c, i)(pWithExtra))
|
val tile = LazyModule(new RocketTile(c, i)(pWithExtra))
|
||||||
@ -52,21 +47,12 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
|||||||
buffer.node :=* tile.masterNode
|
buffer.node :=* tile.masterNode
|
||||||
l1tol2.node :=* buffer.node
|
l1tol2.node :=* buffer.node
|
||||||
tile.slaveNode :*= cbus.node
|
tile.slaveNode :*= cbus.node
|
||||||
ResourceBinding {
|
tile.intNode := intBar.intnode
|
||||||
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) => {
|
(io: HasRocketTilesBundle) => {
|
||||||
// leave clock as default (simpler for hierarchical PnR)
|
// leave clock as default (simpler for hierarchical PnR)
|
||||||
tile.module.io.hartid := UInt(i)
|
tile.module.io.hartid := UInt(i)
|
||||||
tile.module.io.resetVector := io.resetVector
|
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) => {
|
case Asynchronous(depth, sync) => {
|
||||||
@ -76,23 +62,14 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
|||||||
sink.node :=* wrapper.masterNode
|
sink.node :=* wrapper.masterNode
|
||||||
l1tol2.node :=* sink.node
|
l1tol2.node :=* sink.node
|
||||||
wrapper.slaveNode :*= source.node
|
wrapper.slaveNode :*= source.node
|
||||||
|
wrapper.intNode := intBar.intnode
|
||||||
source.node :*= cbus.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) => {
|
(io: HasRocketTilesBundle) => {
|
||||||
wrapper.module.clock := io.tcrs(i).clock
|
wrapper.module.clock := io.tcrs(i).clock
|
||||||
wrapper.module.reset := io.tcrs(i).reset
|
wrapper.module.reset := io.tcrs(i).reset
|
||||||
wrapper.module.io.hartid := UInt(i)
|
wrapper.module.io.hartid := UInt(i)
|
||||||
wrapper.module.io.resetVector := io.resetVector
|
wrapper.module.io.resetVector := io.resetVector
|
||||||
wireInterrupts(wrapper.module.io.interrupts, i)
|
debugNode.bundleOut(0)(0) := debug.module.io.debugInterrupts(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case Rational => {
|
case Rational => {
|
||||||
@ -102,23 +79,14 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
|||||||
sink.node :=* wrapper.masterNode
|
sink.node :=* wrapper.masterNode
|
||||||
l1tol2.node :=* sink.node
|
l1tol2.node :=* sink.node
|
||||||
wrapper.slaveNode :*= source.node
|
wrapper.slaveNode :*= source.node
|
||||||
|
wrapper.intNode := intBar.intnode
|
||||||
source.node :*= cbus.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) => {
|
(io: HasRocketTilesBundle) => {
|
||||||
wrapper.module.clock := io.tcrs(i).clock
|
wrapper.module.clock := io.tcrs(i).clock
|
||||||
wrapper.module.reset := io.tcrs(i).reset
|
wrapper.module.reset := io.tcrs(i).reset
|
||||||
wrapper.module.io.hartid := UInt(i)
|
wrapper.module.io.hartid := UInt(i)
|
||||||
wrapper.module.io.resetVector := io.resetVector
|
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 {
|
ResourceBinding {
|
||||||
Resource(device, "reg").bind(ResourceInt(BigInt(hartid)))
|
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)
|
override lazy val module = new RocketTileModule(this)
|
||||||
@ -100,7 +113,6 @@ class RocketTileModule(outer: RocketTile) extends BaseTileModule(outer, () => ne
|
|||||||
with CanHaveScratchpadModule {
|
with CanHaveScratchpadModule {
|
||||||
|
|
||||||
val core = Module(p(BuildCore)(outer.p))
|
val core = Module(p(BuildCore)(outer.p))
|
||||||
core.io.interrupts := io.interrupts
|
|
||||||
core.io.hartid := io.hartid
|
core.io.hartid := io.hartid
|
||||||
outer.frontend.module.io.cpu <> core.io.imem
|
outer.frontend.module.io.cpu <> core.io.imem
|
||||||
outer.frontend.module.io.resetVector := io.resetVector
|
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
|
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
|
// TODO eliminate this redundancy
|
||||||
val h = dcachePorts.size
|
val h = dcachePorts.size
|
||||||
val c = core.dcacheArbPorts
|
val c = core.dcacheArbPorts
|
||||||
@ -139,15 +158,19 @@ class AsyncRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Parameters
|
|||||||
rocket.slaveNode :*= sink.node
|
rocket.slaveNode :*= sink.node
|
||||||
sink.node :*= slaveNode
|
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) {
|
lazy val module = new LazyModuleImp(this) {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val master = masterNode.bundleOut
|
val master = masterNode.bundleOut
|
||||||
val slave = slaveNode.bundleIn
|
val slave = slaveNode.bundleIn
|
||||||
|
val interrupts = intNode.bundleIn
|
||||||
val hartid = UInt(INPUT, p(XLen))
|
val hartid = UInt(INPUT, p(XLen))
|
||||||
val interrupts = new TileInterrupts()(p).asInput
|
|
||||||
val resetVector = UInt(INPUT, p(XLen))
|
val resetVector = UInt(INPUT, p(XLen))
|
||||||
}
|
}
|
||||||
rocket.module.io.interrupts := ShiftRegister(io.interrupts, 3)
|
|
||||||
// signals that do not change:
|
// signals that do not change:
|
||||||
rocket.module.io.hartid := io.hartid
|
rocket.module.io.hartid := io.hartid
|
||||||
rocket.module.io.resetVector := io.resetVector
|
rocket.module.io.resetVector := io.resetVector
|
||||||
@ -167,15 +190,19 @@ class RationalRocketTile(rtp: RocketTileParams, hartid: Int)(implicit p: Paramet
|
|||||||
rocket.slaveNode :*= sink.node
|
rocket.slaveNode :*= sink.node
|
||||||
sink.node :*= slaveNode
|
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) {
|
lazy val module = new LazyModuleImp(this) {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
val master = masterNode.bundleOut
|
val master = masterNode.bundleOut
|
||||||
val slave = slaveNode.bundleIn
|
val slave = slaveNode.bundleIn
|
||||||
|
val interrupts = intNode.bundleIn
|
||||||
val hartid = UInt(INPUT, p(XLen))
|
val hartid = UInt(INPUT, p(XLen))
|
||||||
val interrupts = new TileInterrupts()(p).asInput
|
|
||||||
val resetVector = UInt(INPUT, p(XLen))
|
val resetVector = UInt(INPUT, p(XLen))
|
||||||
}
|
}
|
||||||
rocket.module.io.interrupts := ShiftRegister(io.interrupts, 1)
|
|
||||||
// signals that do not change:
|
// signals that do not change:
|
||||||
rocket.module.io.hartid := io.hartid
|
rocket.module.io.hartid := io.hartid
|
||||||
rocket.module.io.resetVector := io.resetVector
|
rocket.module.io.resetVector := io.resetVector
|
||||||
|
@ -53,11 +53,13 @@ trait HasTileLinkMasterPort extends HasTileParameters {
|
|||||||
implicit val p: Parameters
|
implicit val p: Parameters
|
||||||
val module: HasTileLinkMasterPortModule
|
val module: HasTileLinkMasterPortModule
|
||||||
val masterNode = TLOutputNode()
|
val masterNode = TLOutputNode()
|
||||||
|
val intNode = IntSinkNode(IntSinkPortSimple())
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasTileLinkMasterPortBundle {
|
trait HasTileLinkMasterPortBundle {
|
||||||
val outer: HasTileLinkMasterPort
|
val outer: HasTileLinkMasterPort
|
||||||
val master = outer.masterNode.bundleOut
|
val master = outer.masterNode.bundleOut
|
||||||
|
val interrupts = outer.intNode.bundleIn
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasTileLinkMasterPortModule {
|
trait HasTileLinkMasterPortModule {
|
||||||
@ -73,7 +75,6 @@ abstract class BaseTile(tileParams: TileParams)(implicit p: Parameters) extends
|
|||||||
class BaseTileBundle[+L <: BaseTile](_outer: L) extends BareTileBundle(_outer)
|
class BaseTileBundle[+L <: BaseTile](_outer: L) extends BareTileBundle(_outer)
|
||||||
with HasTileLinkMasterPortBundle {
|
with HasTileLinkMasterPortBundle {
|
||||||
val hartid = UInt(INPUT, p(XLen))
|
val hartid = UInt(INPUT, p(XLen))
|
||||||
val interrupts = new TileInterrupts()(p).asInput
|
|
||||||
val resetVector = UInt(INPUT, p(XLen))
|
val resetVector = UInt(INPUT, p(XLen))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,9 +53,8 @@ object PLICConsts
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Platform-Level Interrupt Controller */
|
/** 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)
|
require (maxPriorities >= 0)
|
||||||
|
|
||||||
// plic0 => max devices 1023
|
// plic0 => max devices 1023
|
||||||
@ -81,7 +80,7 @@ class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC00000
|
|||||||
val intnode = IntNexusNode(
|
val intnode = IntNexusNode(
|
||||||
numSourcePorts = 0 to 1024,
|
numSourcePorts = 0 to 1024,
|
||||||
numSinkPorts = 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())) })
|
sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) })
|
||||||
|
|
||||||
/* Negotiated sizes */
|
/* Negotiated sizes */
|
||||||
|
Loading…
Reference in New Issue
Block a user