1
0

rocketchip: use TileLink2 interrupts

This commit is contained in:
Wesley W. Terpstra 2016-10-28 21:20:49 -07:00
parent 6505431eac
commit ba529c3716
10 changed files with 270 additions and 214 deletions

View File

@ -36,14 +36,9 @@ trait HasCoreplexParameters {
lazy val outerMMIOParams = p.alterPartial({ case TLId => "L2toMMIO" }) lazy val outerMMIOParams = p.alterPartial({ case TLId => "L2toMMIO" })
lazy val globalAddrMap = p(rocketchip.GlobalAddrMap) lazy val globalAddrMap = p(rocketchip.GlobalAddrMap)
lazy val nTiles = p(uncore.devices.NTiles) lazy val nTiles = p(uncore.devices.NTiles)
lazy val nExtInterrupts = p(rocketchip.NExtInterrupts)
lazy val nSlaves = p(rocketchip.NCoreplexExtClients) lazy val nSlaves = p(rocketchip.NCoreplexExtClients)
lazy val nMemChannels = p(NMemoryChannels) lazy val nMemChannels = p(NMemoryChannels)
lazy val hasSupervisor = p(rocket.UseVM) lazy val hasSupervisor = p(rocket.UseVM)
lazy val nInterruptPriorities = if (nExtInterrupts <= 1) 0 else (nExtInterrupts min 7)
lazy val plicKey = PLICConfig(nTiles, hasSupervisor, nExtInterrupts, nInterruptPriorities)
lazy val clintKey = CoreplexLocalInterrupterConfig()
} }
case class CoreplexParameters(implicit val p: Parameters) extends HasCoreplexParameters case class CoreplexParameters(implicit val p: Parameters) extends HasCoreplexParameters
@ -55,7 +50,7 @@ abstract class BareCoreplexModule[+B <: BareCoreplexBundle[BareCoreplex]](val io
} }
trait CoreplexNetwork extends HasCoreplexParameters { trait CoreplexNetwork extends HasCoreplexParameters {
this: BareCoreplex => this: BareCoreplex =>
val l1tol2 = LazyModule(new TLXbar) val l1tol2 = LazyModule(new TLXbar)
val l1tol2_beatBytes = p(rocketchip.EdgeDataBits)/8 val l1tol2_beatBytes = p(rocketchip.EdgeDataBits)/8
@ -65,16 +60,29 @@ trait CoreplexNetwork extends HasCoreplexParameters {
val cbus_beatBytes = p(XLen)/8 val cbus_beatBytes = p(XLen)/8
val cbus_lineBytes = l1tol2_lineBytes val cbus_lineBytes = l1tol2_lineBytes
val mmio = TLOutputNode()
val mmioInt = IntInputNode()
cbus.node := cbus.node :=
TLAtomicAutomata(arithmetic = true)( // disable once TLB uses TL2 metadata TLAtomicAutomata(arithmetic = true)( // disable once TLB uses TL2 metadata
TLWidthWidget(l1tol2_beatBytes)( TLWidthWidget(l1tol2_beatBytes)(
TLBuffer()( TLBuffer()(
l1tol2.node))) l1tol2.node)))
mmio :=
TLBuffer()(
TLWidthWidget(l1tol2_beatBytes)(
l1tol2.node))
} }
trait CoreplexNetworkBundle extends HasCoreplexParameters { trait CoreplexNetworkBundle extends HasCoreplexParameters {
this: BareCoreplexBundle[BareCoreplex] => this: {
val outer: CoreplexNetwork
} =>
implicit val p = outer.p implicit val p = outer.p
val mmio = outer.mmio.bundleOut
val interrupts = outer.mmioInt.bundleIn
} }
trait CoreplexNetworkModule extends HasCoreplexParameters { trait CoreplexNetworkModule extends HasCoreplexParameters {
@ -88,11 +96,11 @@ trait CoreplexRISCV {
// Build a set of Tiles // Build a set of Tiles
val lazyTiles = p(BuildTiles) map { _(p) } val lazyTiles = p(BuildTiles) map { _(p) }
val legacy = LazyModule(new TLLegacy()(outerMMIOParams)) val legacy = LazyModule(new TLLegacy()(outerMMIOParams))
val tileIntNode = IntInternalOutputNode() // this should be moved into the Tile...
val debug = LazyModule(new TLDebugModule()) val debug = LazyModule(new TLDebugModule())
val plic = LazyModule(new TLPLIC(() => plicKey)) val plic = LazyModule(new TLPLIC(hasSupervisor, maxPriorities = 7))
val clint = LazyModule(new CoreplexLocalInterrupter(clintKey)) val clint = LazyModule(new CoreplexLocalInterrupter)
val mmio = TLOutputNode()
// Kill this once we move TL2 into rocket // Kill this once we move TL2 into rocket
l1tol2.node := l1tol2.node :=
@ -103,10 +111,8 @@ trait CoreplexRISCV {
plic.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node) plic.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node)
clint.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node) clint.node := TLFragmenter(cbus_beatBytes, cbus_lineBytes)(cbus.node)
mmio := plic.intnode := mmioInt
TLBuffer()( lazyTiles.foreach { _ => tileIntNode := plic.intnode }
TLWidthWidget(l1tol2_beatBytes)(
l1tol2.node))
} }
trait CoreplexRISCVBundle { trait CoreplexRISCVBundle {
@ -114,13 +120,11 @@ trait CoreplexRISCVBundle {
val outer: CoreplexRISCV val outer: CoreplexRISCV
} => } =>
val mmio = outer.mmio.bundleOut
val mem = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outerMemParams)) val mem = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outerMemParams))
val slave = Vec(nSlaves, new ClientUncachedTileLinkIO()(innerParams)).flip val slave = Vec(nSlaves, new ClientUncachedTileLinkIO()(innerParams)).flip
val resetVector = UInt(INPUT, p(XLen)) val resetVector = UInt(INPUT, p(XLen))
val success = Bool(OUTPUT) // used for testing val success = Bool(OUTPUT) // used for testing
val debug = new DebugBusIO().flip val debug = new DebugBusIO().flip
val interrupts = Vec(nExtInterrupts, Bool()).asInput
} }
trait CoreplexRISCVModule { trait CoreplexRISCVModule {
@ -134,7 +138,7 @@ trait CoreplexRISCVModule {
// Create and export the ConfigString // Create and export the ConfigString
val managers = outer.l1tol2.node.edgesIn(0).manager.managers val managers = outer.l1tol2.node.edgesIn(0).manager.managers
val configString = rocketchip.GenerateConfigString(p, managers) val configString = rocketchip.GenerateConfigString(p, outer.clint, outer.plic, managers)
println(s"\nGenerated Configuration String\n${configString}") println(s"\nGenerated Configuration String\n${configString}")
ConfigStringOutput.contents = Some(configString) ConfigStringOutput.contents = Some(configString)
@ -192,22 +196,16 @@ trait CoreplexRISCVModule {
for ((tile, i) <- (uncoreTileIOs zipWithIndex)) { for ((tile, i) <- (uncoreTileIOs zipWithIndex)) {
tile.hartid := UInt(i) tile.hartid := UInt(i)
tile.resetVector := io.resetVector tile.resetVector := io.resetVector
tile.interrupts <> outer.clint.module.io.tiles(i)
tile.interrupts.meip := outer.plic.module.io.harts(plicKey.context(i, 'M'))
tile.interrupts.seip.foreach(_ := outer.plic.module.io.harts(plicKey.context(i, 'S')))
tile.interrupts.debug := outer.debug.module.io.debugInterrupts(i) tile.interrupts.debug := outer.debug.module.io.debugInterrupts(i)
} tile.interrupts.meip := outer.tileIntNode.bundleOut(i)(0)
tile.interrupts.seip.foreach(_ := outer.tileIntNode.bundleOut(i)(1))
// Coreplex doesn't know when to stop running
io.success := Bool(false)
for (i <- 0 until io.interrupts.size) {
val gateway = Module(new LevelGateway)
gateway.io.interrupt := io.interrupts(i)
outer.plic.module.io.devices(i) <> gateway.io.plic
} }
outer.debug.module.io.db <> io.debug outer.debug.module.io.db <> io.debug
outer.clint.module.io.rtcTick := Counter(p(rocketchip.RTCPeriod)).inc() outer.clint.module.io.rtcTick := Counter(p(rocketchip.RTCPeriod)).inc()
// Coreplex doesn't know when to stop running
io.success := Bool(false)
} }
class BaseCoreplex(implicit p: Parameters) extends BareCoreplex class BaseCoreplex(implicit p: Parameters) extends BareCoreplex

View File

@ -166,9 +166,12 @@ class MixedNode[DI, UI, EI, BI <: Data, DO, UO, EO, BO <: Data](
val flip = false // needed for blind nodes val flip = false // needed for blind nodes
private def flipO(b: Vec[BO]) = if (flip) b.flip else b private def flipO(b: Vec[BO]) = if (flip) b.flip else b
private def flipI(b: Vec[BI]) = if (flip) b else b.flip private def flipI(b: Vec[BI]) = if (flip) b else b.flip
val wire = false // needed if you want to grab access to from inside a module
private def wireO(b: Vec[BO]) = if (wire) Wire(b) else b
private def wireI(b: Vec[BI]) = if (wire) Wire(b) else b
lazy val bundleOut = flipO(outer.bundleO(edgesOut)) lazy val bundleOut = wireO(flipO(outer.bundleO(edgesOut)))
lazy val bundleIn = flipI(inner.bundleI(edgesIn)) lazy val bundleIn = wireI(flipI(inner.bundleI(edgesIn)))
// connects the outward part of a node with the inward part of this node // connects the outward part of a node with the inward part of this node
override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit sourceInfo: SourceInfo): Option[LazyModule] = { override def := (h: OutwardNodeHandle[DI, UI, BI])(implicit sourceInfo: SourceInfo): Option[LazyModule] = {
@ -234,6 +237,20 @@ class BlindInputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])
override lazy val bundleIn = bundleOut override lazy val bundleIn = bundleOut
} }
class InternalOutputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(pi: PI)
extends SimpleNode(imp)({case (0, _) => Seq()}, {case (n, Seq()) => Seq.fill(n)(pi)}, 0 to 0, 1 to 1)
{
override val wire = true
override lazy val bundleOut = bundleIn
}
class InternalInputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(po: PO)
extends SimpleNode(imp)({case (n, Seq()) => Seq.fill(n)(po)}, {case (0, _) => Seq()}, 1 to 1, 0 to 0)
{
override val wire = true
override lazy val bundleIn = bundleOut
}
class InteriorNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B]) class InteriorNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])
(oFn: Seq[PO] => PO, iFn: Seq[PI] => PI, numPO: Range.Inclusive, numPI: Range.Inclusive) (oFn: Seq[PO] => PO, iFn: Seq[PI] => PI, numPO: Range.Inclusive, numPI: Range.Inclusive)
extends SimpleNode(imp)({case (n,s) => Seq.fill(n)(oFn(s))}, {case (n,s) => Seq.fill(n)(iFn(s))}, numPO, numPI) extends SimpleNode(imp)({case (n,s) => Seq.fill(n)(oFn(s))}, {case (n,s) => Seq.fill(n)(iFn(s))}, numPO, numPI)

View File

@ -16,14 +16,12 @@ import coreplex._
// the following parameters will be refactored properly with TL2 // the following parameters will be refactored properly with TL2
case object GlobalAddrMap extends Field[AddrMap] case object GlobalAddrMap extends Field[AddrMap]
case object NCoreplexExtClients extends Field[Int] case object NCoreplexExtClients extends Field[Int]
case object NExtInterrupts extends Field[Int]
/** Enable or disable monitoring of Diplomatic buses */ /** Enable or disable monitoring of Diplomatic buses */
case object TLEmitMonitors extends Field[Bool] case object TLEmitMonitors extends Field[Bool]
/** Base Top with no Periphery */ /** Base Top with no Periphery */
abstract class BaseTop[+C <: BaseCoreplex](buildCoreplex: Parameters => C)(implicit q: Parameters) extends LazyModule { abstract class BaseTop[+C <: BaseCoreplex](buildCoreplex: Parameters => C)(implicit q: Parameters) extends LazyModule {
// the following variables will be refactored properly with TL2 // the following variables will be refactored properly with TL2
val pInterrupts = new RangeManager
val pBusMasters = new RangeManager val pBusMasters = new RangeManager
TLImp.emitMonitors = q(TLEmitMonitors) TLImp.emitMonitors = q(TLEmitMonitors)
@ -31,11 +29,11 @@ abstract class BaseTop[+C <: BaseCoreplex](buildCoreplex: Parameters => C)(impli
// Add a SoC and peripheral bus // Add a SoC and peripheral bus
val socBus = LazyModule(new TLXbar) val socBus = LazyModule(new TLXbar)
val peripheryBus = LazyModule(new TLXbar) val peripheryBus = LazyModule(new TLXbar)
val intBus = LazyModule(new IntXbar)
// Fill in the TL1 legacy parameters // Fill in the TL1 legacy parameters
implicit val p = q.alterPartial { implicit val p = q.alterPartial {
case NCoreplexExtClients => pBusMasters.sum case NCoreplexExtClients => pBusMasters.sum
case NExtInterrupts => pInterrupts.sum
case GlobalAddrMap => legacyAddrMap case GlobalAddrMap => legacyAddrMap
} }
@ -64,7 +62,6 @@ abstract class BaseTopModule[+B <: BaseTopBundle[BaseTop[BaseCoreplex]]](val io:
val coreplexMem : Vec[ClientUncachedTileLinkIO] = Wire(outer.coreplex.module.io.mem) val coreplexMem : Vec[ClientUncachedTileLinkIO] = Wire(outer.coreplex.module.io.mem)
val coreplexSlave : Vec[ClientUncachedTileLinkIO] = Wire(outer.coreplex.module.io.slave) val coreplexSlave : Vec[ClientUncachedTileLinkIO] = Wire(outer.coreplex.module.io.slave)
val coreplexDebug : DebugBusIO = Wire(outer.coreplex.module.io.debug) val coreplexDebug : DebugBusIO = Wire(outer.coreplex.module.io.debug)
val coreplexInterrupts : Vec[Bool] = Wire(outer.coreplex.module.io.interrupts)
println("Generated Address Map") println("Generated Address Map")
for (entry <- p(GlobalAddrMap).flatten) { for (entry <- p(GlobalAddrMap).flatten) {
@ -79,17 +76,16 @@ abstract class BaseTopModule[+B <: BaseTopBundle[BaseTop[BaseCoreplex]]](val io:
println(f"\t$name%s $start%x - $end%x, $protStr$cacheable") println(f"\t$name%s $start%x - $end%x, $protStr$cacheable")
} }
println("\nGenerated Interrupt Vector")
outer.pInterrupts.print
io.success := outer.coreplex.module.io.success io.success := outer.coreplex.module.io.success
} }
trait DirectConnection { trait DirectConnection {
val coreplex: BaseCoreplex val coreplex: BaseCoreplex
val socBus: TLXbar val socBus: TLXbar
val intBus: IntXbar
socBus.node := coreplex.mmio socBus.node := coreplex.mmio
coreplex.mmioInt := intBus.intnode
} }
trait DirectConnectionModule { trait DirectConnectionModule {
@ -98,10 +94,8 @@ trait DirectConnectionModule {
val coreplexMem : Vec[ClientUncachedTileLinkIO] val coreplexMem : Vec[ClientUncachedTileLinkIO]
val coreplexSlave : Vec[ClientUncachedTileLinkIO] val coreplexSlave : Vec[ClientUncachedTileLinkIO]
val coreplexDebug : DebugBusIO val coreplexDebug : DebugBusIO
val coreplexInterrupts : Vec[Bool]
coreplexMem <> outer.coreplex.module.io.mem coreplexMem <> outer.coreplex.module.io.mem
coreplexInterrupts <> outer.coreplex.module.io.interrupts
outer.coreplex.module.io.slave <> coreplexSlave outer.coreplex.module.io.slave <> coreplexSlave
outer.coreplex.module.io.debug <> coreplexDebug outer.coreplex.module.io.debug <> coreplexDebug
} }

View File

@ -129,28 +129,21 @@ trait PeripheryDebugModule {
trait PeripheryExtInterrupts extends LazyModule { trait PeripheryExtInterrupts extends LazyModule {
implicit val p: Parameters implicit val p: Parameters
val pInterrupts: RangeManager val intBus: IntXbar
pInterrupts.add("ext", p(NExtTopInterrupts)) val extInterrupts = IntBlindInputNode(p(NExtTopInterrupts))
val extInterruptXing = LazyModule(new IntXing)
intBus.intnode := extInterruptXing.intnode
extInterruptXing.intnode := extInterrupts
} }
trait PeripheryExtInterruptsBundle { trait PeripheryExtInterruptsBundle {
implicit val p: Parameters val outer: PeripheryExtInterrupts
val interrupts = Vec(p(NExtTopInterrupts), Bool()).asInput val interrupts = outer.extInterrupts.bundleIn
} }
trait PeripheryExtInterruptsModule { trait PeripheryExtInterruptsModule {
implicit val p: Parameters
val outer: PeripheryExtInterrupts
val io: PeripheryExtInterruptsBundle
val coreplexInterrupts: Vec[Bool]
{
val r = outer.pInterrupts.range("ext")
((r._1 until r._2) zipWithIndex) foreach { case (c, i) =>
coreplexInterrupts(c) := io.interrupts(i)
}
}
} }
///// /////
@ -220,9 +213,7 @@ trait PeripheryMasterAXI4MMIO extends HasPeripheryParameters {
} }
trait PeripheryMasterAXI4MMIOBundle extends HasPeripheryParameters { trait PeripheryMasterAXI4MMIOBundle extends HasPeripheryParameters {
implicit val p: Parameters
val outer: PeripheryMasterAXI4MMIO val outer: PeripheryMasterAXI4MMIO
val mmio_axi = outer.mmio_axi4.bundleOut val mmio_axi = outer.mmio_axi4.bundleOut
} }

View File

@ -26,7 +26,7 @@ class TestHarness(q: Parameters) extends Module {
require(dut.io.bus_clk.isEmpty) require(dut.io.bus_clk.isEmpty)
require(dut.io.bus_rst.isEmpty) require(dut.io.bus_rst.isEmpty)
for (int <- dut.io.interrupts) for (int <- dut.io.interrupts(0))
int := Bool(false) int := Bool(false)
if (dut.io.mem_axi.nonEmpty) { if (dut.io.mem_axi.nonEmpty) {

View File

@ -88,21 +88,12 @@ object GenerateGlobalAddrMap {
} }
object GenerateConfigString { object GenerateConfigString {
def apply(p: Parameters, peripheryManagers: Seq[TLManagerParameters]) = { def apply(p: Parameters, clint: CoreplexLocalInterrupter, plic: TLPLIC, peripheryManagers: Seq[TLManagerParameters]) = {
val c = CoreplexParameters()(p) val c = CoreplexParameters()(p)
val addrMap = p(GlobalAddrMap) val addrMap = p(GlobalAddrMap)
val plicAddr = addrMap("TL2:plic").start
val clint = CoreplexLocalInterrupterConfig()
val xLen = p(XLen)
val res = new StringBuilder val res = new StringBuilder
res append "plic {\n" res append plic.module.globalConfigString
res append s" priority 0x${plicAddr.toString(16)};\n" res append clint.module.globalConfigString
res append s" pending 0x${(plicAddr + PLICConsts.pendingBase).toString(16)};\n"
res append s" ndevs ${c.plicKey.nDevices};\n"
res append "};\n"
res append "rtc {\n"
res append s" addr 0x${clint.timeAddress.toString(16)};\n"
res append "};\n"
if (addrMap contains "mem") { if (addrMap contains "mem") {
res append "ram {\n" res append "ram {\n"
res append " 0 {\n" res append " 0 {\n"
@ -124,22 +115,8 @@ object GenerateConfigString {
res append s" $i {\n" res append s" $i {\n"
res append " 0 {\n" res append " 0 {\n"
res append s" isa $isa;\n" res append s" isa $isa;\n"
res append s" timecmp 0x${clint.timecmpAddress(i).toString(16)};\n" res append clint.module.hartConfigStrings(i)
res append s" ipi 0x${clint.msipAddress(i).toString(16)};\n" res append plic.module.hartConfigStrings(i)
res append s" plic {\n"
res append s" m {\n"
res append s" ie 0x${(plicAddr + c.plicKey.enableAddr(i, 'M')).toString(16)};\n"
res append s" thresh 0x${(plicAddr + c.plicKey.threshAddr(i, 'M')).toString(16)};\n"
res append s" claim 0x${(plicAddr + c.plicKey.claimAddr(i, 'M')).toString(16)};\n"
res append s" };\n"
if (c.hasSupervisor) {
res append s" s {\n"
res append s" ie 0x${(plicAddr + c.plicKey.enableAddr(i, 'S')).toString(16)};\n"
res append s" thresh 0x${(plicAddr + c.plicKey.threshAddr(i, 'S')).toString(16)};\n"
res append s" claim 0x${(plicAddr + c.plicKey.claimAddr(i, 'S')).toString(16)};\n"
res append s" };\n"
}
res append " };\n"
res append " };\n" res append " };\n"
res append " };\n" res append " };\n"
} }

View File

@ -6,9 +6,11 @@ import Chisel._
import Chisel.ImplicitConversions._ import Chisel.ImplicitConversions._
import junctions._ import junctions._
import diplomacy._
import regmapper._ import regmapper._
import uncore.tilelink2._ import uncore.tilelink2._
import cde.Parameters import cde.Parameters
import scala.math.min
class GatewayPLICIO extends Bundle { class GatewayPLICIO extends Bundle {
val valid = Bool(OUTPUT) val valid = Bool(OUTPUT)
@ -49,113 +51,161 @@ object PLICConsts
require(hartBase >= enableBase(maxHarts)) require(hartBase >= enableBase(maxHarts))
} }
case class PLICConfig(nHartsIn: Int, supervisor: Boolean, nDevices: Int, nPriorities: Int) {
import PLICConsts._
def contextsPerHart = if (supervisor) 2 else 1
def nHarts = contextsPerHart * nHartsIn
def context(i: Int, mode: Char) = mode match {
case 'M' => i * contextsPerHart
case 'S' => require(supervisor); i * contextsPerHart + 1
}
def claimAddr(i: Int, mode: Char) = hartBase(context(i, mode)) + claimOffset
def threshAddr(i: Int, mode: Char) = hartBase(context(i, mode))
def enableAddr(i: Int, mode: Char) = enableBase(context(i, mode))
require(nDevices <= maxDevices)
require(nHarts > 0 && nHarts <= maxHarts)
require(nPriorities >= 0 && nPriorities <= nDevices)
}
trait HasPLICParameters {
val params: (() => PLICConfig, Parameters)
val cfg = params._1 ()
implicit val p = params._2
}
trait PLICBundle extends Bundle with HasPLICParameters {
val devices = Vec(cfg.nDevices, new GatewayPLICIO).flip
val harts = Vec(cfg.nHarts, Bool()).asOutput
}
trait PLICModule extends Module with HasRegMap with HasPLICParameters {
val io: PLICBundle
val priority =
if (cfg.nPriorities > 0) Reg(Vec(cfg.nDevices+1, UInt(width=log2Up(cfg.nPriorities+1))))
else Wire(init=Vec.fill(cfg.nDevices+1)(UInt(1)))
val threshold =
if (cfg.nPriorities > 0) Reg(Vec(cfg.nHarts, UInt(width = log2Up(cfg.nPriorities+1))))
else Wire(init=Vec.fill(cfg.nHarts)(UInt(0)))
val pending = Reg(init=Vec.fill(cfg.nDevices+1){Bool(false)})
val enables = Reg(Vec(cfg.nHarts, Vec(cfg.nDevices+1, Bool())))
for ((p, g) <- pending.tail zip io.devices) {
g.ready := !p
g.complete := false
when (g.valid) { p := true }
}
def findMax(x: Seq[UInt]): (UInt, UInt) = {
if (x.length > 1) {
val half = 1 << (log2Ceil(x.length) - 1)
val lMax = findMax(x take half)
val rMax = findMax(x drop half)
val useLeft = lMax._1 >= rMax._1
(Mux(useLeft, lMax._1, rMax._1), Mux(useLeft, lMax._2, UInt(half) | rMax._2))
} else (x.head, UInt(0))
}
val maxDevs = Reg(Vec(cfg.nHarts, UInt(width = log2Up(pending.size))))
for (hart <- 0 until cfg.nHarts) {
val effectivePriority =
for (((p, en), pri) <- (pending zip enables(hart) zip priority).tail)
yield Cat(p && en, pri)
val (maxPri, maxDev) = findMax((UInt(1) << priority(0).getWidth) +: effectivePriority)
maxDevs(hart) := maxDev
io.harts(hart) := Reg(next = maxPri) > Cat(UInt(1), threshold(hart))
}
def priorityRegField(x: UInt) = if (cfg.nPriorities > 0) RegField(32, x) else RegField.r(32, x)
val priorityRegFields = Seq(PLICConsts.priorityBase -> priority.map(p => priorityRegField(p)))
val pendingRegFields = Seq(PLICConsts.pendingBase -> pending .map(b => RegField.r(1, b)))
val enableRegFields = enables.zipWithIndex.map { case (e, i) =>
PLICConsts.enableBase(i) -> e.map(b => RegField(1, b))
}
val hartRegFields = Seq.tabulate(cfg.nHarts) { i =>
PLICConsts.hartBase(i) -> Seq(
priorityRegField(threshold(i)),
RegField(32,
RegReadFn { valid =>
when (valid) {
pending(maxDevs(i)) := Bool(false)
maxDevs(i) := UInt(0) // flush pipeline
}
(Bool(true), maxDevs(i))
},
RegWriteFn { (valid, data) =>
when (valid && enables(i)(data)) {
io.devices(data - UInt(1)).complete := Bool(true)
}
Bool(true)
}
)
)
}
regmap((priorityRegFields ++ pendingRegFields ++ enableRegFields ++ hartRegFields):_*)
priority(0) := 0
pending(0) := false
for (e <- enables)
e(0) := false
}
/** Platform-Level Interrupt Controller */ /** Platform-Level Interrupt Controller */
class TLPLIC(c: () => PLICConfig, address: BigInt = 0xC000000)(implicit val p: Parameters) class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC000000)(implicit val p: Parameters) extends LazyModule
extends TLRegisterRouter(address, size = PLICConsts.size, beatBytes = p(rocket.XLen)/8, undefZero = false)( {
new TLRegBundle((c, p), _) with PLICBundle)( val contextsPerHart = if (supervisor) 2 else 1
new TLRegModule((c, p), _, _) with PLICModule) require (maxPriorities >= 0)
val node = TLRegisterNode(
address = AddressSet(address, PLICConsts.size-1),
beatBytes = p(rocket.XLen)/8,
undefZero = false)
val intnode = IntAdapterNode(
numSourcePorts = 0 to 1024,
numSinkPorts = 0 to 1024,
sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(contextsPerHart))) },
sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) })
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val tl_in = node.bundleIn
val devices = intnode.bundleIn
val harts = intnode.bundleOut
}
// Assign all the devices unique ranges
val sources = intnode.edgesIn.map(_.source)
val flatSources = (sources zip sources.map(_.num).scanLeft(0)(_+_).init).map {
case (s, o) => s.sources.map(z => z.copy(range = z.range.offset(o)))
}.flatten
// Compact the interrupt vector the same way
val interrupts = (intnode.edgesIn zip io.devices).map { case (e, i) => i.take(e.source.num) }.flatten
// This flattens the harts into an MSMSMSMSMS... or MMMMM.... sequence
val harts = io.harts.flatten
println("\nInterrupt map:")
flatSources.foreach { s =>
println(s" [${s.range.start}, ${s.range.end}) => ${s.name}")
}
val nDevices = interrupts.size
val nPriorities = min(maxPriorities, nDevices)
val nHarts = harts.size
require(nDevices <= PLICConsts.maxDevices)
require(nHarts > 0 && nHarts <= PLICConsts.maxHarts)
def context(i: Int, mode: Char) = mode match {
case 'M' => i * contextsPerHart
case 'S' => require(supervisor); i * contextsPerHart + 1
}
def claimAddr(i: Int, mode: Char) = address + PLICConsts.hartBase(context(i, mode)) + PLICConsts.claimOffset
def threshAddr(i: Int, mode: Char) = address + PLICConsts.hartBase(context(i, mode))
def enableAddr(i: Int, mode: Char) = address + PLICConsts.enableBase(context(i, mode))
// Create the global PLIC config string
val globalConfigString = Seq(
s"plic {\n",
s" priority 0x${address.toString(16)};\n",
s" pending 0x${(address + PLICConsts.pendingBase).toString(16)};\n",
s" ndevs ${nDevices};\n",
s"};\n").mkString
// Create the per-Hart config string
val hartConfigStrings = io.harts.zipWithIndex.map { case (_, i) => (Seq(
s" plic {\n",
s" m {\n",
s" ie 0x${enableAddr(i, 'M').toString(16)};\n",
s" thresh 0x${threshAddr(i, 'M').toString(16)};\n",
s" claim 0x${claimAddr(i, 'M').toString(16)};\n",
s" };\n") ++ (if (!supervisor) Seq() else Seq(
s" s {\n",
s" ie 0x${enableAddr(i, 'S').toString(16)};\n",
s" thresh 0x${threshAddr(i, 'S').toString(16)};\n",
s" claim 0x${claimAddr(i, 'S').toString(16)};\n",
s" };\n")) ++ Seq(
s" };\n")).mkString
}
// For now, use LevelGateways for all TL2 interrupts
val gateways = Vec(interrupts.map { case i =>
val gateway = Module(new LevelGateway)
gateway.io.interrupt := i
gateway.io.plic
})
val priority =
if (nPriorities > 0) Reg(Vec(nDevices+1, UInt(width=log2Up(nPriorities+1))))
else Wire(init=Vec.fill(nDevices+1)(UInt(1)))
val threshold =
if (nPriorities > 0) Reg(Vec(nHarts, UInt(width = log2Up(nPriorities+1))))
else Wire(init=Vec.fill(nHarts)(UInt(0)))
val pending = Reg(init=Vec.fill(nDevices+1){Bool(false)})
val enables = Reg(Vec(nHarts, Vec(nDevices+1, Bool())))
for ((p, g) <- pending.tail zip gateways) {
g.ready := !p
g.complete := false
when (g.valid) { p := true }
}
def findMax(x: Seq[UInt]): (UInt, UInt) = {
if (x.length > 1) {
val half = 1 << (log2Ceil(x.length) - 1)
val lMax = findMax(x take half)
val rMax = findMax(x drop half)
val useLeft = lMax._1 >= rMax._1
(Mux(useLeft, lMax._1, rMax._1), Mux(useLeft, lMax._2, UInt(half) | rMax._2))
} else (x.head, UInt(0))
}
val maxDevs = Reg(Vec(nHarts, UInt(width = log2Up(pending.size))))
for (hart <- 0 until nHarts) {
val effectivePriority =
for (((p, en), pri) <- (pending zip enables(hart) zip priority).tail)
yield Cat(p && en, pri)
val (maxPri, maxDev) = findMax((UInt(1) << priority(0).getWidth) +: effectivePriority)
maxDevs(hart) := maxDev
harts(hart) := Reg(next = maxPri) > Cat(UInt(1), threshold(hart))
}
def priorityRegField(x: UInt) = if (nPriorities > 0) RegField(32, x) else RegField.r(32, x)
val priorityRegFields = Seq(PLICConsts.priorityBase -> priority.map(p => priorityRegField(p)))
val pendingRegFields = Seq(PLICConsts.pendingBase -> pending .map(b => RegField.r(1, b)))
val enableRegFields = enables.zipWithIndex.map { case (e, i) =>
PLICConsts.enableBase(i) -> e.map(b => RegField(1, b))
}
val hartRegFields = Seq.tabulate(nHarts) { i =>
PLICConsts.hartBase(i) -> Seq(
priorityRegField(threshold(i)),
RegField(32,
RegReadFn { valid =>
when (valid) {
pending(maxDevs(i)) := Bool(false)
maxDevs(i) := UInt(0) // flush pipeline
}
(Bool(true), maxDevs(i))
},
RegWriteFn { (valid, data) =>
when (valid && enables(i)(data)) {
gateways(data - UInt(1)).complete := Bool(true)
}
Bool(true)
}
)
)
}
node.regmap((priorityRegFields ++ pendingRegFields ++ enableRegFields ++ hartRegFields):_*)
priority(0) := 0
pending(0) := false
for (e <- enables)
e(0) := false
}
}

View File

@ -6,6 +6,7 @@ import Chisel._
import junctions._ import junctions._
import junctions.NastiConstants._ import junctions.NastiConstants._
import regmapper._ import regmapper._
import diplomacy._
import uncore.tilelink2._ import uncore.tilelink2._
import uncore.util._ import uncore.util._
import util._ import util._
@ -20,22 +21,19 @@ class CoreplexLocalInterrupts extends Bundle {
val msip = Bool() val msip = Bool()
} }
case class CoreplexLocalInterrupterConfig(address: BigInt = 0x02000000) { object ClintConsts
{
def msipOffset(hart: Int) = hart * msipBytes def msipOffset(hart: Int) = hart * msipBytes
def msipAddress(hart: Int) = address + msipOffset(hart)
def timecmpOffset(hart: Int) = 0x4000 + hart * timecmpBytes def timecmpOffset(hart: Int) = 0x4000 + hart * timecmpBytes
def timecmpAddress(hart: Int) = address + timecmpOffset(hart)
def timeOffset = 0xbff8 def timeOffset = 0xbff8
def timeAddress = address + timeOffset
def msipBytes = 4 def msipBytes = 4
def timecmpBytes = 8 def timecmpBytes = 8
def size = 0x10000 def size = 0x10000
} }
trait MixCoreplexLocalInterrupterParameters { trait MixCoreplexLocalInterrupterParameters {
val params: (CoreplexLocalInterrupterConfig, Parameters) val params: Parameters
val c = params._1 implicit val p = params
implicit val p = params._2
} }
trait CoreplexLocalInterrupterBundle extends Bundle with MixCoreplexLocalInterrupterParameters { trait CoreplexLocalInterrupterBundle extends Bundle with MixCoreplexLocalInterrupterParameters {
@ -45,6 +43,7 @@ trait CoreplexLocalInterrupterBundle extends Bundle with MixCoreplexLocalInterru
trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCoreplexLocalInterrupterParameters { trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCoreplexLocalInterrupterParameters {
val io: CoreplexLocalInterrupterBundle val io: CoreplexLocalInterrupterBundle
val address: AddressSet
val timeWidth = 64 val timeWidth = 64
val regWidth = 32 val regWidth = 32
@ -64,6 +63,15 @@ trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCorep
tile.mtip := time.asUInt >= timecmp(i).asUInt tile.mtip := time.asUInt >= timecmp(i).asUInt
} }
val globalConfigString = Seq(
s"rtc {\n",
s" addr 0x${(address.base + ClintConsts.timeOffset).toString(16)};\n",
s"};\n").mkString
val hartConfigStrings = (0 until p(NTiles)).map { i => Seq(
s" timecmp 0x${(address.base + ClintConsts.timecmpOffset(i)).toString(16)};\n",
s" ipi 0x${(address.base + ClintConsts.msipOffset(i)).toString(16)};\n").mkString
}
/* 0000 msip hart 0 /* 0000 msip hart 0
* 0004 msip hart 1 * 0004 msip hart 1
* 4000 mtimecmp hart 0 lo * 4000 mtimecmp hart 0 lo
@ -75,16 +83,16 @@ trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCorep
*/ */
regmap( regmap(
0 -> makeRegFields(ipi), 0 -> makeRegFields(ipi),
c.timecmpOffset(0) -> makeRegFields(timecmp.flatten), ClintConsts.timecmpOffset(0) -> makeRegFields(timecmp.flatten),
c.timeOffset -> makeRegFields(time)) 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 */ /** Power, Reset, Clock, Interrupt */
// Magic TL2 Incantation to create a TL2 Slave // Magic TL2 Incantation to create a TL2 Slave
class CoreplexLocalInterrupter(c: CoreplexLocalInterrupterConfig)(implicit val p: Parameters) class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit val p: Parameters)
extends TLRegisterRouter(c.address, size = c.size, beatBytes = p(rocket.XLen)/8, undefZero = false)( extends TLRegisterRouter(address, size = ClintConsts.size, beatBytes = p(rocket.XLen)/8, undefZero = false)(
new TLRegBundle((c, p), _) with CoreplexLocalInterrupterBundle)( new TLRegBundle(p, _) with CoreplexLocalInterrupterBundle)(
new TLRegModule((c, p), _, _) with CoreplexLocalInterrupterModule) new TLRegModule(p, _, _) with CoreplexLocalInterrupterModule)

View File

@ -79,9 +79,6 @@ object IntImp extends NodeImp[IntSourcePortParameters, IntSinkPortParameters, In
} }
case class IntIdentityNode() extends IdentityNode(IntImp) case class IntIdentityNode() extends IdentityNode(IntImp)
case class IntOutputNode() extends OutputNode(IntImp)
case class IntInputNode() extends InputNode(IntImp)
case class IntSourceNode(num: Int) extends SourceNode(IntImp)( case class IntSourceNode(num: Int) extends SourceNode(IntImp)(
IntSourcePortParameters(Seq(IntSourceParameters(num))), (if (num == 0) 0 else 1) to 1) IntSourcePortParameters(Seq(IntSourceParameters(num))), (if (num == 0) 0 else 1) to 1)
case class IntSinkNode() extends SinkNode(IntImp)( case class IntSinkNode() extends SinkNode(IntImp)(
@ -94,11 +91,20 @@ case class IntAdapterNode(
numSinkPorts: Range.Inclusive = 1 to 1) numSinkPorts: Range.Inclusive = 1 to 1)
extends InteriorNode(IntImp)(sourceFn, sinkFn, numSourcePorts, numSinkPorts) extends InteriorNode(IntImp)(sourceFn, sinkFn, numSourcePorts, numSinkPorts)
case class IntOutputNode() extends OutputNode(IntImp)
case class IntInputNode() extends InputNode(IntImp)
case class IntBlindOutputNode() extends BlindOutputNode(IntImp)(IntSinkPortParameters(Seq(IntSinkParameters())))
case class IntBlindInputNode(num: Int) extends BlindInputNode(IntImp)(IntSourcePortParameters(Seq(IntSourceParameters(num))))
case class IntInternalOutputNode() extends InternalOutputNode(IntImp)(IntSinkPortParameters(Seq(IntSinkParameters())))
case class IntInternalInputNode(num: Int) extends InternalInputNode(IntImp)(IntSourcePortParameters(Seq(IntSourceParameters(num))))
class IntXbar extends LazyModule class IntXbar extends LazyModule
{ {
val intnode = IntAdapterNode( val intnode = IntAdapterNode(
numSourcePorts = 1 to 1, // does it make sense to have more than one interrupt sink? numSourcePorts = 1 to 1, // does it make sense to have more than one interrupt sink?
numSinkPorts = 1 to 128, numSinkPorts = 0 to 128,
sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }, sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) },
sourceFn = { seq => sourceFn = { seq =>
IntSourcePortParameters((seq zip seq.map(_.num).scanLeft(0)(_+_).init).map { IntSourcePortParameters((seq zip seq.map(_.num).scanLeft(0)(_+_).init).map {
@ -116,3 +122,17 @@ class IntXbar extends LazyModule
io.out.foreach { _ := cat } io.out.foreach { _ := cat }
} }
} }
class IntXing extends LazyModule
{
val intnode = IntIdentityNode()
lazy val module = new LazyModuleImp(this) {
val io = new Bundle {
val in = intnode.bundleIn
val out = intnode.bundleOut
}
io.out := RegNext(RegNext(RegNext(io.in)))
}
}

View File

@ -79,7 +79,7 @@ object TLRegisterNode
// register mapped device from a totally abstract register mapped device. // register mapped device from a totally abstract register mapped device.
// See GPIO.scala in this directory for an example // See GPIO.scala in this directory for an example
abstract class TLRegisterRouterBase(address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean) extends LazyModule abstract class TLRegisterRouterBase(val address: AddressSet, interrupts: Int, concurrency: Int, beatBytes: Int, undefZero: Boolean, executable: Boolean) extends LazyModule
{ {
val node = TLRegisterNode(address, concurrency, beatBytes, undefZero, executable) val node = TLRegisterNode(address, concurrency, beatBytes, undefZero, executable)
val intnode = IntSourceNode(interrupts) val intnode = IntSourceNode(interrupts)
@ -100,6 +100,7 @@ class TLRegModule[P, B <: TLRegBundleBase](val params: P, bundleBuilder: => B, r
{ {
val io = bundleBuilder val io = bundleBuilder
val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0) val interrupts = if (io.interrupts.isEmpty) Vec(0, Bool()) else io.interrupts(0)
val address = router.address
def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*) def regmap(mapping: RegField.Map*) = router.node.regmap(mapping:_*)
} }