1
0

rocket: connect interrupt map for Plic+Clint

This commit is contained in:
Wesley W. Terpstra 2017-03-01 21:57:00 -08:00
parent 38489ad9b0
commit 7ff9f88ad7
3 changed files with 106 additions and 70 deletions

View File

@ -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

View File

@ -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

View File

@ -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,71 +25,78 @@ 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
}
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)
{ {
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( val globalConfigString = Seq(
s"rtc {\n", s"rtc {\n",
s" addr 0x${(address + ClintConsts.timeOffset).toString(16)};\n", s" addr 0x${(address + timeOffset).toString(16)};\n",
s"};\n").mkString s"};\n").mkString
val hartConfigStrings = (0 until p(NTiles)).map { i => Seq( val hartConfigStrings = (0 until p(NTiles)).map { i => Seq(
s" timecmp 0x${(address + ClintConsts.timecmpOffset(i)).toString(16)};\n", s" timecmp 0x${(address + timecmpOffset(i)).toString(16)};\n",
s" ipi 0x${(address + ClintConsts.msipOffset(i)).toString(16)};\n").mkString 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))
} }
} }