diff --git a/src/main/scala/coreplex/BaseCoreplex.scala b/src/main/scala/coreplex/BaseCoreplex.scala index 75325802..6b43acec 100644 --- a/src/main/scala/coreplex/BaseCoreplex.scala +++ b/src/main/scala/coreplex/BaseCoreplex.scala @@ -29,10 +29,10 @@ case object BroadcastConfig extends Field[BroadcastConfig] case class BankedL2Config( nMemoryChannels: Int = 1, nBanksPerChannel: Int = 1, - coherenceManager: (Int, Parameters) => (TLInwardNode, TLOutwardNode) = { case (lineBytes, p) => + coherenceManager: Parameters => (TLInwardNode, TLOutwardNode) = { case p => val BroadcastConfig(nTrackers, bufferless) = p(BroadcastConfig) - val bh = LazyModule(new TLBroadcast(lineBytes, nTrackers, bufferless)) - (bh.node, bh.node) + val bh = LazyModule(new TLBroadcast(p(CacheBlockBytes), nTrackers, bufferless)) + (bh.node, TLWidthWidget(p(L1toL2Config).beatBytes)(bh.node)) }) { val nBanks = nMemoryChannels*nBanksPerChannel } @@ -130,7 +130,7 @@ trait BankedL2CoherenceManagers extends CoreplexNetwork { output := bankBar.node val mask = ~BigInt((l2Config.nBanksPerChannel-1) * l1tol2_lineBytes) for (i <- 0 until l2Config.nBanksPerChannel) { - val (in, out) = l2Config.coherenceManager(l1tol2_lineBytes, p) + val (in, out) = l2Config.coherenceManager(p) in := TLFilter(AddressSet(i * l1tol2_lineBytes, mask))(l1tol2.node) bankBar.node := out } diff --git a/src/main/scala/coreplex/Coreplex.scala b/src/main/scala/coreplex/Coreplex.scala index fd6fde18..ec2e4673 100644 --- a/src/main/scala/coreplex/Coreplex.scala +++ b/src/main/scala/coreplex/Coreplex.scala @@ -12,32 +12,59 @@ import rocket._ ///// +trait L2MasterPort extends CoreplexNetwork +{ + val module: L2MasterPortModule + val l2in = TLInputNode() + l1tol2.node := l2in +} + +trait L2MasterPortBundle extends CoreplexNetworkBundle +{ + val outer: L2MasterPort + val l2in = outer.l2in.bundleIn +} + +trait L2MasterPortModule extends CoreplexNetworkModule +{ + val outer: L2MasterPort + val io: L2MasterPortBundle +} + +///// + class DefaultCoreplex(implicit p: Parameters) extends BaseCoreplex with CoreplexRISCVPlatform - with RocketPlex { + with L2MasterPort + with RocketTiles { override lazy val module = new DefaultCoreplexModule(this, () => new DefaultCoreplexBundle(this)) } class DefaultCoreplexBundle[+L <: DefaultCoreplex](_outer: L) extends BaseCoreplexBundle(_outer) with CoreplexRISCVPlatformBundle - with RocketPlexBundle + with L2MasterPortBundle + with RocketTilesBundle class DefaultCoreplexModule[+L <: DefaultCoreplex, +B <: DefaultCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io) with CoreplexRISCVPlatformModule - with RocketPlexModule + with L2MasterPortModule + with RocketTilesModule ///// class MultiClockCoreplex(implicit p: Parameters) extends BaseCoreplex with CoreplexRISCVPlatform - with AsyncRocketPlex { + with L2MasterPort + with AsyncRocketTiles { override lazy val module = new MultiClockCoreplexModule(this, () => new MultiClockCoreplexBundle(this)) } class MultiClockCoreplexBundle[+L <: MultiClockCoreplex](_outer: L) extends BaseCoreplexBundle(_outer) with CoreplexRISCVPlatformBundle - with AsyncRocketPlexBundle + with L2MasterPortBundle + with AsyncRocketTilesBundle class MultiClockCoreplexModule[+L <: MultiClockCoreplex, +B <: MultiClockCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io) with CoreplexRISCVPlatformModule - with AsyncRocketPlexModule + with L2MasterPortModule + with AsyncRocketTilesModule diff --git a/src/main/scala/coreplex/RocketPlex.scala b/src/main/scala/coreplex/RocketTiles.scala similarity index 83% rename from src/main/scala/coreplex/RocketPlex.scala rename to src/main/scala/coreplex/RocketTiles.scala index 5c85112e..78a1097a 100644 --- a/src/main/scala/coreplex/RocketPlex.scala +++ b/src/main/scala/coreplex/RocketTiles.scala @@ -8,8 +8,8 @@ import uncore.coherence._ import rocket._ import uncore.devices.NTiles -trait RocketPlex extends CoreplexRISCVPlatform { - val module: RocketPlexModule +trait RocketTiles extends CoreplexRISCVPlatform { + val module: RocketTilesModule val rocketTiles = List.tabulate(p(NTiles)) { i => LazyModule(new RocketTile(i)) } val tileIntNodes = rocketTiles.map { _ => IntInternalOutputNode() } @@ -22,13 +22,13 @@ trait RocketPlex extends CoreplexRISCVPlatform { } } -trait RocketPlexBundle extends CoreplexRISCVPlatformBundle { - val outer: CoreplexRISCVPlatform +trait RocketTilesBundle extends CoreplexRISCVPlatformBundle { + val outer: RocketTiles } -trait RocketPlexModule extends CoreplexRISCVPlatformModule { - val outer: RocketPlex - val io: RocketPlexBundle +trait RocketTilesModule extends CoreplexRISCVPlatformModule { + val outer: RocketTiles + val io: RocketTilesBundle outer.rocketTiles.map(_.module).zipWithIndex.foreach { case (tile, i) => tile.io.hartid := UInt(i) @@ -67,8 +67,8 @@ class AsyncRocketTile(tileId: Int)(implicit p: Parameters) extends LazyModule { } } -trait AsyncRocketPlex extends CoreplexRISCVPlatform { - val module: AsyncRocketPlexModule +trait AsyncRocketTiles extends CoreplexRISCVPlatform { + val module: AsyncRocketTilesModule val rocketTiles = List.tabulate(p(NTiles)) { i => LazyModule(new AsyncRocketTile(i)) } val tileIntNodes = rocketTiles.map { _ => IntInternalOutputNode() } @@ -81,8 +81,8 @@ trait AsyncRocketPlex extends CoreplexRISCVPlatform { } } -trait AsyncRocketPlexBundle extends CoreplexRISCVPlatformBundle { - val outer: CoreplexRISCVPlatform +trait AsyncRocketTilesBundle extends CoreplexRISCVPlatformBundle { + val outer: AsyncRocketTiles val tcrs = Vec(nTiles, new Bundle { val clock = Clock(INPUT) @@ -90,9 +90,9 @@ trait AsyncRocketPlexBundle extends CoreplexRISCVPlatformBundle { }) } -trait AsyncRocketPlexModule extends CoreplexRISCVPlatformModule { - val outer: AsyncRocketPlex - val io: AsyncRocketPlexBundle +trait AsyncRocketTilesModule extends CoreplexRISCVPlatformModule { + val outer: AsyncRocketTiles + val io: AsyncRocketTilesBundle outer.rocketTiles.map(_.module).zipWithIndex.foreach { case (tile, i) => tile.clock := io.tcrs(i).clock diff --git a/src/main/scala/groundtest/TestHarness.scala b/src/main/scala/groundtest/TestHarness.scala index fd265858..6cf8cb22 100644 --- a/src/main/scala/groundtest/TestHarness.scala +++ b/src/main/scala/groundtest/TestHarness.scala @@ -12,14 +12,14 @@ class TestHarness(q: Parameters) extends Module { } implicit val p = q - val dut = Module(LazyModule(new GroundTestTop(new GroundTestCoreplex()(_))).module) + val dut = Module(LazyModule(new GroundTestTop).module) io.success := dut.io.success if (dut.io.mem_axi4.nonEmpty) { val memSize = p(ExtMem).size require(memSize % dut.io.mem_axi4.size == 0) - for (axi <- dut.io.mem_axi4) { - Module(LazyModule(new SimAXIMem(memSize / dut.io.mem_axi4.size)).module).io.axi <> axi + for (axi4 <- dut.io.mem_axi4) { + Module(LazyModule(new SimAXIMem(memSize / dut.io.mem_axi4.size)).module).io.axi4 <> axi4 } } } diff --git a/src/main/scala/groundtest/Top.scala b/src/main/scala/groundtest/Top.scala index 613bb39a..088d16f1 100644 --- a/src/main/scala/groundtest/Top.scala +++ b/src/main/scala/groundtest/Top.scala @@ -6,20 +6,25 @@ import diplomacy._ import coreplex._ import rocketchip._ -class GroundTestTop[+C <: GroundTestCoreplex](_coreplex: Parameters => C)(implicit p: Parameters) extends BaseTop(_coreplex) - with DirectConnection +class GroundTestTop(implicit p: Parameters) extends BaseTop with PeripheryMasterAXI4Mem with PeripheryTestRAM { override lazy val module = new GroundTestTopModule(this, () => new GroundTestTopBundle(this)) + + val coreplex = LazyModule(new GroundTestCoreplex) + + socBus.node := coreplex.mmio + coreplex.mmioInt := intBus.intnode + (mem zip coreplex.mem) foreach { case (m, c) => m := c } } -class GroundTestTopBundle[+L <: GroundTestTop[GroundTestCoreplex]](_outer: L) extends BaseTopBundle(_outer) +class GroundTestTopBundle[+L <: GroundTestTop](_outer: L) extends BaseTopBundle(_outer) with PeripheryMasterAXI4MemBundle with PeripheryTestRAMBundle { val success = Bool(OUTPUT) } -class GroundTestTopModule[+L <: GroundTestTop[GroundTestCoreplex], +B <: GroundTestTopBundle[L]](_outer: L, _io: () => B) extends BaseTopModule(_outer, _io) +class GroundTestTopModule[+L <: GroundTestTop, +B <: GroundTestTopBundle[L]](_outer: L, _io: () => B) extends BaseTopModule(_outer, _io) with PeripheryMasterAXI4MemModule with PeripheryTestRAMModule { io.success := outer.coreplex.module.io.success diff --git a/src/main/scala/rocketchip/BaseTop.scala b/src/main/scala/rocketchip/BaseTop.scala index 76055561..5879d58e 100644 --- a/src/main/scala/rocketchip/BaseTop.scala +++ b/src/main/scala/rocketchip/BaseTop.scala @@ -11,21 +11,19 @@ import uncore.tilelink2._ import uncore.devices._ import util._ import rocket._ -import coreplex._ /** Enable or disable monitoring of Diplomatic buses */ case object TLEmitMonitors extends Field[Boolean] -abstract class BareTop[+C <: BaseCoreplex](_coreplex: Parameters => C)(implicit val p: Parameters) extends LazyModule { - val coreplex = LazyModule(_coreplex(p)) +abstract class BareTop(implicit val p: Parameters) extends LazyModule { TopModule.contents = Some(this) } -abstract class BareTopBundle[+L <: BareTop[BaseCoreplex]](_outer: L) extends Bundle { +abstract class BareTopBundle[+L <: BareTop](_outer: L) extends Bundle { val outer = _outer } -abstract class BareTopModule[+L <: BareTop[BaseCoreplex], +B <: BareTopBundle[L]](_outer: L, _io: () => B) extends LazyModuleImp(_outer) { +abstract class BareTopModule[+L <: BareTop, +B <: BareTopBundle[L]](_outer: L, _io: () => B) extends LazyModuleImp(_outer) { val outer = _outer val io = _io () } @@ -45,8 +43,6 @@ trait TopNetwork extends HasPeripheryParameters { TLWidthWidget(socBusConfig.beatBytes)( TLAtomicAutomata(arithmetic = peripheryBusArithmetic)( socBus.node)) - - var coreplexMem = Seq[TLOutwardNode]() } trait TopNetworkBundle extends HasPeripheryParameters { @@ -61,22 +57,23 @@ trait TopNetworkModule extends HasPeripheryParameters { } /** Base Top with no Periphery */ -class BaseTop[+C <: BaseCoreplex](_coreplex: Parameters => C)(implicit p: Parameters) extends BareTop(_coreplex) +class BaseTop(implicit p: Parameters) extends BareTop with TopNetwork { override lazy val module = new BaseTopModule(this, () => new BaseTopBundle(this)) } -class BaseTopBundle[+L <: BaseTop[BaseCoreplex]](_outer: L) extends BareTopBundle(_outer) +class BaseTopBundle[+L <: BaseTop](_outer: L) extends BareTopBundle(_outer) with TopNetworkBundle -class BaseTopModule[+L <: BaseTop[BaseCoreplex], +B <: BaseTopBundle[L]](_outer: L, _io: () => B) extends BareTopModule(_outer, _io) +class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle[L]](_outer: L, _io: () => B) extends BareTopModule(_outer, _io) with TopNetworkModule -trait DirectConnection extends TopNetwork { - val coreplex: BaseCoreplex - - socBus.node := coreplex.mmio - coreplex.mmioInt := intBus.intnode - - coreplexMem = coreplex.mem +trait L2Crossbar extends TopNetwork { + val l2 = LazyModule(new TLXbar) +} + +trait L2CrossbarBundle extends TopNetworkBundle { +} + +trait L2CrossbarModule extends TopNetworkModule { } diff --git a/src/main/scala/rocketchip/ExampleTop.scala b/src/main/scala/rocketchip/ExampleTop.scala index 00cafe31..6a064104 100644 --- a/src/main/scala/rocketchip/ExampleTop.scala +++ b/src/main/scala/rocketchip/ExampleTop.scala @@ -5,56 +5,48 @@ package rocketchip import Chisel._ import config._ import junctions._ -import coreplex._ import rocketchip._ -/** Example Top with Periphery */ -class ExampleTop[+C <: BaseCoreplex](_coreplex: Parameters => C)(implicit p: Parameters) extends BaseTop(_coreplex) - with DirectConnection +/** Example Top with Periphery (w/o coreplex) */ +abstract class ExampleTop(implicit p: Parameters) extends BaseTop with PeripheryExtInterrupts with PeripheryMasterAXI4Mem - with PeripheryMasterAXI4MMIO { + with PeripheryMasterAXI4MMIO + with PeripherySlaveAXI4 { override lazy val module = new ExampleTopModule(this, () => new ExampleTopBundle(this)) } -class ExampleTopBundle[+L <: ExampleTop[BaseCoreplex]](_outer: L) extends BaseTopBundle(_outer) +class ExampleTopBundle[+L <: ExampleTop](_outer: L) extends BaseTopBundle(_outer) with PeripheryExtInterruptsBundle with PeripheryMasterAXI4MemBundle with PeripheryMasterAXI4MMIOBundle + with PeripherySlaveAXI4Bundle -class ExampleTopModule[+L <: ExampleTop[BaseCoreplex], +B <: ExampleTopBundle[L]](_outer: L, _io: () => B) extends BaseTopModule(_outer, _io) +class ExampleTopModule[+L <: ExampleTop, +B <: ExampleTopBundle[L]](_outer: L, _io: () => B) extends BaseTopModule(_outer, _io) with PeripheryExtInterruptsModule with PeripheryMasterAXI4MemModule with PeripheryMasterAXI4MMIOModule + with PeripherySlaveAXI4Module -class ExampleRocketTop[+C <: DefaultCoreplex](_coreplex: Parameters => C)(implicit p: Parameters) extends ExampleTop(_coreplex) +class ExampleRocketTop(implicit p: Parameters) extends ExampleTop with PeripheryBootROM with PeripheryDTM with PeripheryCounter - with HardwiredResetVector { + with HardwiredResetVector + with RocketPlexMaster { override lazy val module = new ExampleRocketTopModule(this, () => new ExampleRocketTopBundle(this)) } -class ExampleRocketTopBundle[+L <: ExampleRocketTop[DefaultCoreplex]](_outer: L) extends ExampleTopBundle(_outer) +class ExampleRocketTopBundle[+L <: ExampleRocketTop](_outer: L) extends ExampleTopBundle(_outer) with PeripheryBootROMBundle with PeripheryDTMBundle with PeripheryCounterBundle with HardwiredResetVectorBundle + with RocketPlexMasterBundle -class ExampleRocketTopModule[+L <: ExampleRocketTop[DefaultCoreplex], +B <: ExampleRocketTopBundle[L]](_outer: L, _io: () => B) extends ExampleTopModule(_outer, _io) +class ExampleRocketTopModule[+L <: ExampleRocketTop, +B <: ExampleRocketTopBundle[L]](_outer: L, _io: () => B) extends ExampleTopModule(_outer, _io) with PeripheryBootROMModule with PeripheryDTMModule with PeripheryCounterModule with HardwiredResetVectorModule - -/** Example Top with TestRAM */ -class ExampleTopWithTestRAM[+C <: BaseCoreplex](_coreplex: Parameters => C)(implicit p: Parameters) extends ExampleTop(_coreplex) - with PeripheryTestRAM { - override lazy val module = new ExampleTopWithTestRAMModule(this, () => new ExampleTopWithTestRAMBundle(this)) -} - -class ExampleTopWithTestRAMBundle[+L <: ExampleTopWithTestRAM[BaseCoreplex]](_outer: L) extends ExampleTopBundle(_outer) - with PeripheryTestRAMBundle - -class ExampleTopWithTestRAMModule[+L <: ExampleTopWithTestRAM[BaseCoreplex], +B <: ExampleTopWithTestRAMBundle[L]](_outer: L, _io: () => B) extends ExampleTopModule(_outer, _io) - with PeripheryTestRAMModule + with RocketPlexMasterModule diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index 3cc38035..35d5306f 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -71,16 +71,17 @@ trait PeripheryExtInterruptsModule { ///// trait PeripheryMasterAXI4Mem { - this: BaseTop[BaseCoreplex] with TopNetwork => + this: TopNetwork => + val module: PeripheryMasterAXI4MemModule private val config = p(ExtMem) - private val channels = coreplexMem.size + private val channels = p(BankedL2Config).nMemoryChannels - val mem_axi4 = coreplexMem.zipWithIndex.map { case (node, i) => + val mem_axi4 = Seq.tabulate(channels) { i => val c_size = config.size/channels val c_base = config.base + c_size*i - val axi4 = AXI4BlindOutputNode(AXI4SlavePortParameters( + AXI4BlindOutputNode(AXI4SlavePortParameters( slaves = Seq(AXI4SlaveParameters( address = List(AddressSet(c_base, c_size-1)), regionType = RegionType.UNCACHED, // cacheable @@ -89,14 +90,12 @@ trait PeripheryMasterAXI4Mem { supportsRead = TransferSizes(1, 256), interleavedId = Some(0))), // slave does not interleave read responses beatBytes = config.beatBytes)) + } - axi4 := - // AXI4Fragmenter(lite=false, maxInFlight = 20)( // beef device up to support awlen = 0xff - TLToAXI4(idBits = config.idBits)( // use idBits = 0 for AXI4-Lite - TLWidthWidget(coreplex.l1tol2_beatBytes)( // convert width before attaching to the l1tol2 - node)) - - axi4 + val mem = mem_axi4.map { node => + val foo = LazyModule(new TLToAXI4(config.idBits)) + node := foo.node + foo.node } } @@ -141,7 +140,7 @@ trait PeripheryMasterAXI4MMIOBundle { this: TopNetworkBundle { val outer: PeripheryMasterAXI4MMIO } => - val mmio_axi = outer.mmio_axi4.bundleOut + val mmio_axi4 = outer.mmio_axi4.bundleOut } trait PeripheryMasterAXI4MMIOModule { @@ -154,6 +153,31 @@ trait PeripheryMasterAXI4MMIOModule { ///// +// PeripherySlaveAXI4 is an example, make your own cake pattern like this one. +trait PeripherySlaveAXI4 extends L2Crossbar { + private val axiIdBits = 8 + private val tlIdBits = 2 // at most 4 AXI requets inflight at a time + + val l2_axi4 = AXI4BlindInputNode(AXI4MasterPortParameters( + masters = Seq(AXI4MasterParameters( + id = IdRange(0, 1 << axiIdBits))))) + + l2.node := TLSourceShrinker(1 << tlIdBits)(AXI4ToTL()(AXI4Fragmenter()(l2_axi4))) +} + +trait PeripherySlaveAXI4Bundle extends L2CrossbarBundle { + val outer: PeripherySlaveAXI4 + val l2_axi4 = outer.l2_axi4.bundleIn +} + +trait PeripherySlaveAXI4Module extends L2CrossbarModule { + val outer: PeripherySlaveAXI4 + val io: PeripherySlaveAXI4Bundle + // nothing to do +} + +///// + trait PeripheryBootROM { this: TopNetwork => val coreplex: CoreplexRISCVPlatform diff --git a/src/main/scala/rocketchip/RocketPlexMaster.scala b/src/main/scala/rocketchip/RocketPlexMaster.scala new file mode 100644 index 00000000..a00c39cb --- /dev/null +++ b/src/main/scala/rocketchip/RocketPlexMaster.scala @@ -0,0 +1,32 @@ +// See LICENSE for license details. + +package rocketchip + +import Chisel._ +import config._ +import diplomacy._ +import uncore.tilelink2._ +import uncore.devices._ +import util._ +import coreplex._ + +trait RocketPlexMaster extends L2Crossbar { + val module: RocketPlexMasterModule + val mem: Seq[TLInwardNode] + + val coreplex = LazyModule(new DefaultCoreplex) + + coreplex.l2in := l2.node + socBus.node := coreplex.mmio + coreplex.mmioInt := intBus.intnode + (mem zip coreplex.mem) foreach { case (m, c) => m := c } +} + +trait RocketPlexMasterBundle extends L2CrossbarBundle { + val outer: RocketPlexMaster +} + +trait RocketPlexMasterModule extends L2CrossbarModule { + val outer: RocketPlexMaster + val io: RocketPlexMasterBundle +} diff --git a/src/main/scala/rocketchip/TestHarness.scala b/src/main/scala/rocketchip/TestHarness.scala index 092a290b..727315e9 100644 --- a/src/main/scala/rocketchip/TestHarness.scala +++ b/src/main/scala/rocketchip/TestHarness.scala @@ -14,7 +14,7 @@ class TestHarness(q: Parameters) extends Module { val success = Bool(OUTPUT) } implicit val p = q - val dut = Module(LazyModule(new ExampleRocketTop(new DefaultCoreplex()(_))).module) + val dut = Module(LazyModule(new ExampleRocketTop).module) for (int <- dut.io.interrupts(0)) int := Bool(false) @@ -22,15 +22,22 @@ class TestHarness(q: Parameters) extends Module { if (dut.io.mem_axi4.nonEmpty) { val memSize = p(ExtMem).size require(memSize % dut.io.mem_axi4.size == 0) - for (axi <- dut.io.mem_axi4) { - Module(LazyModule(new SimAXIMem(memSize / dut.io.mem_axi4.size)).module).io.axi <> axi + for (axi4 <- dut.io.mem_axi4) { + Module(LazyModule(new SimAXIMem(memSize / dut.io.mem_axi4.size)).module).io.axi4 <> axi4 } } val dtm = Module(new SimDTM).connect(clock, reset, dut.io.debug, io.success) val mmio_sim = Module(LazyModule(new SimAXIMem(4096)).module) - mmio_sim.io.axi <> dut.io.mmio_axi + mmio_sim.io.axi4 <> dut.io.mmio_axi4 + + val l2_axi4 = dut.io.l2_axi4(0) + l2_axi4.ar.valid := Bool(false) + l2_axi4.aw.valid := Bool(false) + l2_axi4.w .valid := Bool(false) + l2_axi4.r .ready := Bool(true) + l2_axi4.b .ready := Bool(true) } class SimAXIMem(size: BigInt)(implicit p: Parameters) extends LazyModule { @@ -42,7 +49,7 @@ class SimAXIMem(size: BigInt)(implicit p: Parameters) extends LazyModule { lazy val module = new LazyModuleImp(this) { val io = new Bundle { - val axi = node.bundleIn + val axi4 = node.bundleIn } } } diff --git a/src/main/scala/rocketchip/Utils.scala b/src/main/scala/rocketchip/Utils.scala index bcf54049..d2287e38 100644 --- a/src/main/scala/rocketchip/Utils.scala +++ b/src/main/scala/rocketchip/Utils.scala @@ -56,8 +56,8 @@ object GenerateConfigString { def apply(p: Parameters, clint: CoreplexLocalInterrupter, plic: TLPLIC, peripheryManagers: Seq[TLManagerParameters]) = { val c = CoreplexParameters()(p) val res = new StringBuilder - res append plic.module.globalConfigString - res append clint.module.globalConfigString + res append plic.globalConfigString + res append clint.globalConfigString res append "core {\n" for (i <- 0 until c.nTiles) { // TODO heterogeneous tiles val isa = { @@ -71,8 +71,8 @@ object GenerateConfigString { res append s" $i {\n" res append " 0 {\n" res append s" isa $isa;\n" - res append clint.module.hartConfigStrings(i) - res append plic.module.hartConfigStrings(i) + res append clint.hartConfigStrings(i) + res append plic.hartConfigStrings(i) res append " };\n" res append " };\n" } diff --git a/src/main/scala/uncore/devices/Plic.scala b/src/main/scala/uncore/devices/Plic.scala index 4673b8cf..b28c05d1 100644 --- a/src/main/scala/uncore/devices/Plic.scala +++ b/src/main/scala/uncore/devices/Plic.scala @@ -68,6 +68,43 @@ class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC00000 sourceFn = { _ => IntSourcePortParameters(Seq(IntSourceParameters(contextsPerHart))) }, sinkFn = { _ => IntSinkPortParameters(Seq(IntSinkParameters())) }) + /* Negotiated sizes */ + def nDevices = intnode.edgesIn.map(_.source.num).sum + def nPriorities = min(maxPriorities, nDevices) + def nHarts = intnode.edgesOut.map(_.source.num).sum + + 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 + lazy 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 + lazy val hartConfigStrings = Seq.tabulate(intnode.edgesOut.size) { 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 + } + lazy val module = new LazyModuleImp(this) { val io = new Bundle { val tl_in = node.bundleIn @@ -91,45 +128,12 @@ class TLPLIC(supervisor: Boolean, maxPriorities: Int, address: BigInt = 0xC00000 println(s" [${s.range.start+1}, ${s.range.end}] => ${s.name}") } - val nDevices = interrupts.size - val nPriorities = min(maxPriorities, nDevices) - val nHarts = harts.size + require (nDevices == interrupts.size) + require (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) diff --git a/src/main/scala/uncore/devices/Prci.scala b/src/main/scala/uncore/devices/Prci.scala index ef73294c..9bd4748f 100644 --- a/src/main/scala/uncore/devices/Prci.scala +++ b/src/main/scala/uncore/devices/Prci.scala @@ -63,15 +63,6 @@ trait CoreplexLocalInterrupterModule extends Module with HasRegMap with MixCorep 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 * 0004 msip hart 1 * 4000 mtimecmp hart 0 lo @@ -96,3 +87,13 @@ class CoreplexLocalInterrupter(address: BigInt = 0x02000000)(implicit val p: Par extends TLRegisterRouter(address, size = ClintConsts.size, beatBytes = p(rocket.XLen)/8, undefZero = false)( new TLRegBundle(p, _) with CoreplexLocalInterrupterBundle)( new TLRegModule(p, _, _) 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 + } +} diff --git a/src/main/scala/uncore/tilelink2/Broadcast.scala b/src/main/scala/uncore/tilelink2/Broadcast.scala index 8bc40111..66cb95b8 100644 --- a/src/main/scala/uncore/tilelink2/Broadcast.scala +++ b/src/main/scala/uncore/tilelink2/Broadcast.scala @@ -19,7 +19,6 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa managerFn = { case Seq(mp) => mp.copy( endSinkId = numTrackers, - minLatency = 1, managers = mp.managers.map { m => // We are the last level manager require (m.regionType != RegionType.CACHED) diff --git a/src/main/scala/uncore/tilelink2/SRAM.scala b/src/main/scala/uncore/tilelink2/SRAM.scala index bbfbf0f6..83e7f882 100644 --- a/src/main/scala/uncore/tilelink2/SRAM.scala +++ b/src/main/scala/uncore/tilelink2/SRAM.scala @@ -72,7 +72,6 @@ class TLRAM(address: AddressSet, executable: Boolean = true, beatBytes: Int = 4) mem.write(memAddress, wdata, in.a.bits.mask.toBools) } val ren = in.a.fire() && read - def holdUnless[T <: Data](in : T, enable: Bool): T = Mux(!enable, RegEnable(in, enable), in) rdata := holdUnless(mem.read(memAddress, ren), RegNext(ren)) // Tie off unused channels diff --git a/src/main/scala/uncore/tilelink2/SourceShrinker.scala b/src/main/scala/uncore/tilelink2/SourceShrinker.scala new file mode 100644 index 00000000..4870820a --- /dev/null +++ b/src/main/scala/uncore/tilelink2/SourceShrinker.scala @@ -0,0 +1,86 @@ +// See LICENSE for license details. + +package uncore.tilelink2 + +import Chisel._ +import chisel3.internal.sourceinfo.SourceInfo +import diplomacy._ +import scala.math.{min,max} + +class TLSourceShrinker(maxInFlight: Int) extends LazyModule +{ + require (maxInFlight > 0) + + private val client = TLClientParameters(sourceId = IdRange(0, maxInFlight)) + val node = TLAdapterNode( + // We erase all client information since we crush the source Ids + clientFn = { case _ => TLClientPortParameters(clients = Seq(client)) }, + managerFn = { case Seq(mp) => mp }) + + lazy val module = new LazyModuleImp(this) { + val io = new Bundle { + val in = node.bundleIn + val out = node.bundleOut + } + + val edgeIn = node.edgesIn(0) + val edgeOut = node.edgesOut(0) + val in = io.in(0) + val out = io.out(0) + + // Acquires cannot pass this adapter; it makes Probes impossible + require (!edgeIn.client.anySupportProbe || + !edgeOut.manager.anySupportAcquire) + + out.b.ready := Bool(true) + out.c.valid := Bool(false) + out.e.valid := Bool(false) + in.b.valid := Bool(false) + in.c.ready := Bool(true) + in.e.ready := Bool(true) + + if (maxInFlight >= edgeIn.client.endSourceId) { + out.a <> in.a + in.d <> out.d + } else { + // State tracking + val sourceIdMap = Mem(maxInFlight, in.a.bits.source) + val allocated = RegInit(UInt(0, width = maxInFlight)) + val nextFreeOH = ~(leftOR(~allocated) << 1) & ~allocated + val nextFree = OHToUInt(nextFreeOH) + val full = allocated.andR() + + val a_first = edgeIn.first(in.a) + val d_last = edgeIn.last(in.d) + + val block = a_first && full + in.a.ready := out.a.ready && !block + out.a.valid := in.a.valid && !block + out.a.bits := in.a.bits + out.a.bits.source := holdUnless(nextFree, a_first) + + in.d <> out.d + in.d.bits.source := sourceIdMap(out.d.bits.source) + + when (a_first && in.a.fire()) { + sourceIdMap(nextFree) := in.a.bits.source + } + + val alloc = a_first && in.a.fire() + val free = d_last && in.d.fire() + val alloc_id = Mux(alloc, nextFreeOH, UInt(0)) + val free_id = Mux(free, UIntToOH(out.d.bits.source), UInt(0)) + allocated := (allocated | alloc_id) & ~free_id + } + } +} + +object TLSourceShrinker +{ + // applied to the TL source node; y.node := TLSourceShrinker(n)(x.node) + def apply(maxInFlight: Int)(x: TLOutwardNode)(implicit sourceInfo: SourceInfo): TLOutwardNode = { + val shrinker = LazyModule(new TLSourceShrinker(maxInFlight)) + shrinker.node := x + shrinker.node + } +} diff --git a/src/main/scala/uncore/tilelink2/package.scala b/src/main/scala/uncore/tilelink2/package.scala index 3fcd3fc5..bd6ad401 100644 --- a/src/main/scala/uncore/tilelink2/package.scala +++ b/src/main/scala/uncore/tilelink2/package.scala @@ -13,6 +13,7 @@ package object tilelink2 def OH1ToOH(x: UInt) = (x << 1 | UInt(1)) & ~Cat(UInt(0, width=1), x) def OH1ToUInt(x: UInt) = OHToUInt(OH1ToOH(x)) def UIntToOH1(x: UInt, width: Int) = ~(SInt(-1, width=width).asUInt << x)(width-1, 0) + def holdUnless[T <: Data](in : T, enable: Bool): T = Mux(!enable, RegEnable(in, enable), in) def trailingZeros(x: Int) = if (x > 0) Some(log2Ceil(x & -x)) else None // Fill 1s from low bits to high bits def leftOR(x: UInt) = { diff --git a/src/main/scala/util/PositionalMultiQueue.scala b/src/main/scala/util/PositionalMultiQueue.scala index cd87ebdc..e3879d64 100644 --- a/src/main/scala/util/PositionalMultiQueue.scala +++ b/src/main/scala/util/PositionalMultiQueue.scala @@ -35,22 +35,27 @@ class PositionalMultiQueue[T <: Data](params: PositionalMultiQueueParameters[T], val empty = RegInit(Vec.fill(params.ways) { Bool(true) }) val head = Reg(Vec(params.ways, UInt(width = log2Up(params.positions)))) val tail = Reg(Vec(params.ways, UInt(width = log2Up(params.positions)))) - val next = Reg(Vec(params.positions, UInt(width = log2Up(params.positions)))) - val data = Reg(Vec(params.positions, params.gen)) + val next = Mem(params.positions, UInt(width = log2Up(params.positions))) + val data = Mem(params.positions, params.gen) // optimized away for synthesis; used to confirm invariant - val guard = RegInit(Vec.fill(params.positions) { Bool(false) }) + val guard = RegInit(UInt(0, width = params.positions)) when (io.enq.fire()) { data(io.enq.bits.pos) := io.enq.bits.data // ensure the user never stores to the same position twice assert (!guard(io.enq.bits.pos)) - guard(io.enq.bits.pos) := Bool(true) + + when (!empty(io.enq.bits.way)) { + next(tail(io.enq.bits.way)) := io.enq.bits.pos + } } + val setGuard = io.enq.fire() << io.enq.bits.pos val deq = Wire(io.deq) io.deq <> deq val waySelect = UIntToOH(io.enq.bits.way, params.ways) + var clrGuard = UInt(0) for (i <- 0 until params.ways) { val enq = io.enq.fire() && waySelect(i) val last = head(i) === tail(i) @@ -59,8 +64,6 @@ class PositionalMultiQueue[T <: Data](params: PositionalMultiQueueParameters[T], tail(i) := io.enq.bits.pos when (empty(i)) { head(i) := io.enq.bits.pos - } .otherwise { - next(tail(i)) := io.enq.bits.pos } } @@ -76,13 +79,15 @@ class PositionalMultiQueue[T <: Data](params: PositionalMultiQueueParameters[T], when (deq(i).fire()) { head(i) := Mux(last, io.enq.bits.pos, next(head(i))) - guard(deq(i).bits.pos) := Bool(false) } + clrGuard = clrGuard | (deq(i).fire() << deq(i).bits.pos) when (enq =/= deq(i).fire()) { empty(i) := deq(i).fire() && last } } + + guard := (guard | setGuard) & ~clrGuard } object PositionalMultiQueue