rocketchip: use TileLink2 interrupts
This commit is contained in:
parent
6505431eac
commit
ba529c3716
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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"
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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:_*)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user