rocket: connect interrupt map for Plic+Clint
This commit is contained in:
parent
38489ad9b0
commit
7ff9f88ad7
@ -23,14 +23,18 @@ 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()) }
|
private val rocketTileIntNodes = configs.map { _ => IntInternalOutputNode(IntSinkPortSimple(ports = 2)) }
|
||||||
rocketTileIntNodes.foreach { _ := plic.intnode }
|
rocketTileIntNodes.foreach { n =>
|
||||||
|
n := plic.intnode
|
||||||
|
n := clint.intnode
|
||||||
|
}
|
||||||
|
|
||||||
private def wireInterrupts(x: TileInterrupts, i: Int) {
|
private def wireInterrupts(x: TileInterrupts, i: Int) {
|
||||||
x := clint.module.io.tiles(i)
|
|
||||||
x.debug := debug.module.io.debugInterrupts(i)
|
x.debug := debug.module.io.debugInterrupts(i)
|
||||||
x.meip := rocketTileIntNodes(i).bundleOut(0)(0)
|
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) =>
|
val rocketWires: Seq[HasRocketTilesBundle => Unit] = configs.zipWithIndex.map { case (c, i) =>
|
||||||
@ -48,6 +52,16 @@ 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 {
|
||||||
|
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)
|
||||||
@ -63,6 +77,16 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
|||||||
l1tol2.node :=* sink.node
|
l1tol2.node :=* sink.node
|
||||||
wrapper.slaveNode :*= source.node
|
wrapper.slaveNode :*= source.node
|
||||||
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
|
||||||
@ -79,6 +103,16 @@ trait HasRocketTiles extends CoreplexRISCVPlatform {
|
|||||||
l1tol2.node :=* sink.node
|
l1tol2.node :=* sink.node
|
||||||
wrapper.slaveNode :*= source.node
|
wrapper.slaveNode :*= source.node
|
||||||
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
|
||||||
|
@ -302,8 +302,8 @@ class MixedNexusNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
|
|||||||
numPI: Range.Inclusive = 1 to 999)
|
numPI: Range.Inclusive = 1 to 999)
|
||||||
extends MixedNode(inner, outer)(numPO, numPI)
|
extends MixedNode(inner, outer)(numPO, numPI)
|
||||||
{
|
{
|
||||||
require (numPO.end >= 1, s"${name} does not accept outputs${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}")
|
// require (numPI.end >= 1, s"${name} does not accept inputs${lazyModule.line}")
|
||||||
|
|
||||||
val externalIn: Boolean = true
|
val externalIn: Boolean = true
|
||||||
val externalOut: Boolean = true
|
val externalOut: Boolean = true
|
||||||
|
@ -17,11 +17,6 @@ import tile.XLen
|
|||||||
/** Number of tiles */
|
/** Number of tiles */
|
||||||
case object NTiles extends Field[Int]
|
case object NTiles extends Field[Int]
|
||||||
|
|
||||||
class CoreplexLocalInterrupts extends Bundle {
|
|
||||||
val mtip = Bool()
|
|
||||||
val msip = Bool()
|
|
||||||
}
|
|
||||||
|
|
||||||
object ClintConsts
|
object ClintConsts
|
||||||
{
|
{
|
||||||
def msipOffset(hart: Int) = hart * msipBytes
|
def msipOffset(hart: Int) = hart * msipBytes
|
||||||
@ -30,23 +25,47 @@ object ClintConsts
|
|||||||
def msipBytes = 4
|
def msipBytes = 4
|
||||||
def timecmpBytes = 8
|
def timecmpBytes = 8
|
||||||
def size = 0x10000
|
def size = 0x10000
|
||||||
|
def timeWidth = 64
|
||||||
|
def regWidth = 32
|
||||||
|
def ints = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
trait MixCoreplexLocalInterrupterParameters {
|
class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Parameters) extends LazyModule
|
||||||
implicit val p: Parameters
|
{
|
||||||
}
|
import ClintConsts._
|
||||||
|
|
||||||
trait CoreplexLocalInterrupterBundle extends Bundle with MixCoreplexLocalInterrupterParameters {
|
// clint0 => at most 4095 devices
|
||||||
val tiles = Vec(p(NTiles), new CoreplexLocalInterrupts).asOutput
|
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 + timeOffset).toString(16)};\n",
|
||||||
|
s"};\n").mkString
|
||||||
|
val hartConfigStrings = (0 until p(NTiles)).map { i => Seq(
|
||||||
|
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 rtcTick = Bool(INPUT)
|
||||||
}
|
val int = intnode.bundleOut
|
||||||
|
val in = node.bundleIn
|
||||||
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)))
|
val time = Seq.fill(timeWidth/regWidth)(Reg(init=UInt(0, width = regWidth)))
|
||||||
when (io.rtcTick) {
|
when (io.rtcTick) {
|
||||||
@ -58,9 +77,9 @@ trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCorep
|
|||||||
val timecmp = Seq.fill(p(NTiles)) { Seq.fill(timeWidth/regWidth)(Reg(UInt(width = regWidth))) }
|
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)) }
|
val ipi = Seq.fill(p(NTiles)) { RegInit(UInt(0, width = 1)) }
|
||||||
|
|
||||||
for ((tile, i) <- io.tiles zipWithIndex) {
|
io.int.zipWithIndex.foreach { case (int, i) =>
|
||||||
tile.msip := ipi(i)(0)
|
int(0) := ipi(i)(0) // msip
|
||||||
tile.mtip := time.asUInt >= timecmp(i).asUInt
|
int(1) := time.asUInt >= timecmp(i).asUInt // mtip
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 0000 msip hart 0
|
/* 0000 msip hart 0
|
||||||
@ -73,28 +92,11 @@ trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCorep
|
|||||||
* bffc mtime hi
|
* 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))
|
def makeRegFields(s: Seq[UInt]) = s.map(r => RegField(regWidth, r))
|
||||||
}
|
|
||||||
|
|
||||||
/** Power, Reset, Clock, Interrupt */
|
node.regmap(
|
||||||
// Magic TL2 Incantation to create a TL2 Slave
|
0 -> makeRegFields(ipi),
|
||||||
// prci0 => at most 4095 devices
|
timecmpOffset(0) -> makeRegFields(timecmp.flatten),
|
||||||
class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit p: Parameters)
|
timeOffset -> makeRegFields(time))
|
||||||
extends TLRegisterRouter(address, "clint", Seq("riscv,clint0"), size = ClintConsts.size, beatBytes = p(XLen)/8, undefZero = true)(
|
|
||||||
new TLRegBundle((), _) with CoreplexLocalInterrupterBundle)(
|
|
||||||
new TLRegModule((), _, _) with CoreplexLocalInterrupterModule)
|
|
||||||
{
|
|
||||||
val globalConfigString = Seq(
|
|
||||||
s"rtc {\n",
|
|
||||||
s" addr 0x${(address + ClintConsts.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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user