From c80ee06472fc923f4dc3dcedee5ca3078fdb3278 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 22 Nov 2016 14:58:03 -0800 Subject: [PATCH 01/12] rocketchip: configString is a lazy property of outer --- src/main/scala/rocketchip/Utils.scala | 8 +-- src/main/scala/uncore/devices/Plic.scala | 74 +++++++++++++----------- src/main/scala/uncore/devices/Prci.scala | 19 +++--- 3 files changed, 53 insertions(+), 48 deletions(-) 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 + } +} From a140b070095c164685e0b1d04584699862390346 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 22 Nov 2016 15:01:45 -0800 Subject: [PATCH 02/12] rocketchip: cut coreplex from rocketchip --- src/main/scala/groundtest/TestHarness.scala | 2 +- src/main/scala/groundtest/Top.scala | 13 +++++--- src/main/scala/rocketchip/BaseTop.scala | 25 ++++---------- src/main/scala/rocketchip/ExampleTop.scala | 33 +++++++------------ src/main/scala/rocketchip/Periphery.scala | 21 ++++++------ .../scala/rocketchip/RocketPlexMaster.scala | 31 +++++++++++++++++ src/main/scala/rocketchip/TestHarness.scala | 2 +- 7 files changed, 69 insertions(+), 58 deletions(-) create mode 100644 src/main/scala/rocketchip/RocketPlexMaster.scala diff --git a/src/main/scala/groundtest/TestHarness.scala b/src/main/scala/groundtest/TestHarness.scala index fd265858..97bc39b6 100644 --- a/src/main/scala/groundtest/TestHarness.scala +++ b/src/main/scala/groundtest/TestHarness.scala @@ -12,7 +12,7 @@ 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) { 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..5f2810c7 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,13 @@ 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 -} diff --git a/src/main/scala/rocketchip/ExampleTop.scala b/src/main/scala/rocketchip/ExampleTop.scala index 00cafe31..c0ec3d3c 100644 --- a/src/main/scala/rocketchip/ExampleTop.scala +++ b/src/main/scala/rocketchip/ExampleTop.scala @@ -5,56 +5,45 @@ 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 { 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 -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 -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..40b202cc 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 } } diff --git a/src/main/scala/rocketchip/RocketPlexMaster.scala b/src/main/scala/rocketchip/RocketPlexMaster.scala new file mode 100644 index 00000000..9cbe64ef --- /dev/null +++ b/src/main/scala/rocketchip/RocketPlexMaster.scala @@ -0,0 +1,31 @@ +// 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 TopNetwork { + val module: RocketPlexMasterModule + val mem: Seq[TLInwardNode] + + val coreplex = LazyModule(new DefaultCoreplex) + + socBus.node := coreplex.mmio + coreplex.mmioInt := intBus.intnode + (mem zip coreplex.mem) foreach { case (m, c) => m := c } +} + +trait RocketPlexMasterBundle extends TopNetworkBundle { + val outer: RocketPlexMaster +} + +trait RocketPlexMasterModule extends TopNetworkModule { + val outer: RocketPlexMaster + val io: RocketPlexMasterBundle +} diff --git a/src/main/scala/rocketchip/TestHarness.scala b/src/main/scala/rocketchip/TestHarness.scala index 092a290b..465183f9 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) From bbabcf67fffa84100332d839e8d365abf2884bb5 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 22 Nov 2016 15:12:45 -0800 Subject: [PATCH 03/12] coreplex: width adapter should happen as part of coherence manager In the future we will want the L2 to be wider on the backside so that we can take advantage of fat DDR controllers (256bits/beat). --- src/main/scala/coreplex/BaseCoreplex.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 } From c230580157edeff5fa3e9f1e087c22c193d3e144 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 22 Nov 2016 15:49:06 -0800 Subject: [PATCH 04/12] coreplex: rename RocketPlex => RocketTiles --- src/main/scala/coreplex/Coreplex.scala | 12 ++++---- .../{RocketPlex.scala => RocketTiles.scala} | 28 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) rename src/main/scala/coreplex/{RocketPlex.scala => RocketTiles.scala} (83%) diff --git a/src/main/scala/coreplex/Coreplex.scala b/src/main/scala/coreplex/Coreplex.scala index fd6fde18..f577338a 100644 --- a/src/main/scala/coreplex/Coreplex.scala +++ b/src/main/scala/coreplex/Coreplex.scala @@ -14,30 +14,30 @@ import rocket._ class DefaultCoreplex(implicit p: Parameters) extends BaseCoreplex with CoreplexRISCVPlatform - with RocketPlex { + 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 RocketTilesBundle class DefaultCoreplexModule[+L <: DefaultCoreplex, +B <: DefaultCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io) with CoreplexRISCVPlatformModule - with RocketPlexModule + with RocketTilesModule ///// class MultiClockCoreplex(implicit p: Parameters) extends BaseCoreplex with CoreplexRISCVPlatform - with AsyncRocketPlex { + 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 AsyncRocketTilesBundle class MultiClockCoreplexModule[+L <: MultiClockCoreplex, +B <: MultiClockCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io) with CoreplexRISCVPlatformModule - with AsyncRocketPlexModule + 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 From 13190a5de0a48739291a265e8f2b15dbaf94151f Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 22 Nov 2016 16:58:24 -0800 Subject: [PATCH 05/12] rocketchip: re-add AXI4 interface --- src/main/scala/coreplex/Coreplex.scala | 27 +++++++++++++++++++ src/main/scala/groundtest/TestHarness.scala | 4 +-- src/main/scala/rocketchip/BaseTop.scala | 10 +++++++ src/main/scala/rocketchip/ExampleTop.scala | 5 +++- src/main/scala/rocketchip/Periphery.scala | 25 ++++++++++++++++- .../scala/rocketchip/RocketPlexMaster.scala | 7 ++--- src/main/scala/rocketchip/TestHarness.scala | 15 ++++++++--- 7 files changed, 82 insertions(+), 11 deletions(-) diff --git a/src/main/scala/coreplex/Coreplex.scala b/src/main/scala/coreplex/Coreplex.scala index f577338a..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 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 L2MasterPortBundle with RocketTilesBundle class DefaultCoreplexModule[+L <: DefaultCoreplex, +B <: DefaultCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io) with CoreplexRISCVPlatformModule + with L2MasterPortModule with RocketTilesModule ///// class MultiClockCoreplex(implicit p: Parameters) extends BaseCoreplex with CoreplexRISCVPlatform + 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 L2MasterPortBundle with AsyncRocketTilesBundle class MultiClockCoreplexModule[+L <: MultiClockCoreplex, +B <: MultiClockCoreplexBundle[L]](_outer: L, _io: () => B) extends BaseCoreplexModule(_outer, _io) with CoreplexRISCVPlatformModule + with L2MasterPortModule with AsyncRocketTilesModule diff --git a/src/main/scala/groundtest/TestHarness.scala b/src/main/scala/groundtest/TestHarness.scala index 97bc39b6..6cf8cb22 100644 --- a/src/main/scala/groundtest/TestHarness.scala +++ b/src/main/scala/groundtest/TestHarness.scala @@ -18,8 +18,8 @@ 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 } } } diff --git a/src/main/scala/rocketchip/BaseTop.scala b/src/main/scala/rocketchip/BaseTop.scala index 5f2810c7..5879d58e 100644 --- a/src/main/scala/rocketchip/BaseTop.scala +++ b/src/main/scala/rocketchip/BaseTop.scala @@ -67,3 +67,13 @@ class BaseTopBundle[+L <: BaseTop](_outer: L) extends BareTopBundle(_outer) class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle[L]](_outer: L, _io: () => B) extends BareTopModule(_outer, _io) with TopNetworkModule + +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 c0ec3d3c..6a064104 100644 --- a/src/main/scala/rocketchip/ExampleTop.scala +++ b/src/main/scala/rocketchip/ExampleTop.scala @@ -11,7 +11,8 @@ import rocketchip._ 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)) } @@ -19,11 +20,13 @@ class ExampleTopBundle[+L <: ExampleTop](_outer: L) extends BaseTopBundle(_outer with PeripheryExtInterruptsBundle with PeripheryMasterAXI4MemBundle with PeripheryMasterAXI4MMIOBundle + with PeripherySlaveAXI4Bundle 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(implicit p: Parameters) extends ExampleTop with PeripheryBootROM diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index 40b202cc..9458e328 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -140,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 { @@ -153,6 +153,29 @@ trait PeripheryMasterAXI4MMIOModule { ///// +// PeripherySlaveAXI4 is an example, make your own cake pattern like this one. +trait PeripherySlaveAXI4 extends L2Crossbar { + private val idBits = 8 + val l2_axi4 = AXI4BlindInputNode(AXI4MasterPortParameters( + masters = Seq(AXI4MasterParameters( + id = IdRange(0, 1 << idBits))))) + + l2.node := 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 index 9cbe64ef..a00c39cb 100644 --- a/src/main/scala/rocketchip/RocketPlexMaster.scala +++ b/src/main/scala/rocketchip/RocketPlexMaster.scala @@ -10,22 +10,23 @@ import uncore.devices._ import util._ import coreplex._ -trait RocketPlexMaster extends TopNetwork { +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 TopNetworkBundle { +trait RocketPlexMasterBundle extends L2CrossbarBundle { val outer: RocketPlexMaster } -trait RocketPlexMasterModule extends TopNetworkModule { +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 465183f9..727315e9 100644 --- a/src/main/scala/rocketchip/TestHarness.scala +++ b/src/main/scala/rocketchip/TestHarness.scala @@ -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 } } } From d9a203b0f0064f542677a4dda2792c8c11104502 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 22 Nov 2016 18:38:55 -0800 Subject: [PATCH 06/12] PositionalMultiQueue: convert 'next' to a single write port --- src/main/scala/util/PositionalMultiQueue.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/scala/util/PositionalMultiQueue.scala b/src/main/scala/util/PositionalMultiQueue.scala index cd87ebdc..eadb1f88 100644 --- a/src/main/scala/util/PositionalMultiQueue.scala +++ b/src/main/scala/util/PositionalMultiQueue.scala @@ -45,6 +45,10 @@ class PositionalMultiQueue[T <: Data](params: PositionalMultiQueueParameters[T], // 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 deq = Wire(io.deq) @@ -59,8 +63,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 } } From f9de7173cce9b75843ec83390d37c5aacbfe2e1f Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 22 Nov 2016 18:46:11 -0800 Subject: [PATCH 07/12] PositionalMultiQueue: use 1-write n-read Mem instead of Reg(Vec(...)) --- src/main/scala/util/PositionalMultiQueue.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scala/util/PositionalMultiQueue.scala b/src/main/scala/util/PositionalMultiQueue.scala index eadb1f88..b9c00b9b 100644 --- a/src/main/scala/util/PositionalMultiQueue.scala +++ b/src/main/scala/util/PositionalMultiQueue.scala @@ -35,8 +35,8 @@ 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) }) From 437be0f36a6b708d973d910d41fcd0499fea06fa Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 22 Nov 2016 20:39:38 -0800 Subject: [PATCH 08/12] PositionalMultiQueue: use a UInt instead of Reg(Vec(Bool)) This results in much less Verilog to simulate --- src/main/scala/util/PositionalMultiQueue.scala | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/scala/util/PositionalMultiQueue.scala b/src/main/scala/util/PositionalMultiQueue.scala index b9c00b9b..e3879d64 100644 --- a/src/main/scala/util/PositionalMultiQueue.scala +++ b/src/main/scala/util/PositionalMultiQueue.scala @@ -38,23 +38,24 @@ class PositionalMultiQueue[T <: Data](params: PositionalMultiQueueParameters[T], 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) @@ -78,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 From 0097274ea34c8b67161725922e71cf6319e772e8 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 22 Nov 2016 20:45:40 -0800 Subject: [PATCH 09/12] Broadcast: single-cycle response is possible --- src/main/scala/uncore/tilelink2/Broadcast.scala | 1 - 1 file changed, 1 deletion(-) 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) From c0b27999ea3553527bc81740b206a185a51a5940 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 22 Nov 2016 21:20:26 -0800 Subject: [PATCH 10/12] tilelink2 SourceShrinker: a concurrency reducing adapter --- src/main/scala/uncore/tilelink2/SRAM.scala | 1 - .../uncore/tilelink2/SourceShrinker.scala | 79 +++++++++++++++++++ src/main/scala/uncore/tilelink2/package.scala | 1 + 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 src/main/scala/uncore/tilelink2/SourceShrinker.scala 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..a1a270e4 --- /dev/null +++ b/src/main/scala/uncore/tilelink2/SourceShrinker.scala @@ -0,0 +1,79 @@ +// 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 +{ + 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) + + // 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) = { From 1e7d597fd37063710a66a79a4c9f0e05d73c5c4f Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 22 Nov 2016 21:48:41 -0800 Subject: [PATCH 11/12] rocketchip: don't waste too many sources on the AXI master port --- src/main/scala/rocketchip/Periphery.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index 9458e328..35d5306f 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -155,12 +155,14 @@ trait PeripheryMasterAXI4MMIOModule { // PeripherySlaveAXI4 is an example, make your own cake pattern like this one. trait PeripherySlaveAXI4 extends L2Crossbar { - private val idBits = 8 + 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 << idBits))))) + id = IdRange(0, 1 << axiIdBits))))) - l2.node := AXI4ToTL()(AXI4Fragmenter()(l2_axi4)) + l2.node := TLSourceShrinker(1 << tlIdBits)(AXI4ToTL()(AXI4Fragmenter()(l2_axi4))) } trait PeripherySlaveAXI4Bundle extends L2CrossbarBundle { From 1d3cad36713dfe69717a6707c001122ae444e1ef Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Tue, 22 Nov 2016 22:01:43 -0800 Subject: [PATCH 12/12] tilelink2 SourceShrinker: handle degenerate cases for free --- .../uncore/tilelink2/SourceShrinker.scala | 53 +++++++++++-------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/src/main/scala/uncore/tilelink2/SourceShrinker.scala b/src/main/scala/uncore/tilelink2/SourceShrinker.scala index a1a270e4..4870820a 100644 --- a/src/main/scala/uncore/tilelink2/SourceShrinker.scala +++ b/src/main/scala/uncore/tilelink2/SourceShrinker.scala @@ -9,6 +9,8 @@ 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 @@ -37,34 +39,39 @@ class TLSourceShrinker(maxInFlight: Int) extends LazyModule in.c.ready := Bool(true) in.e.ready := Bool(true) - // 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() + 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 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) + 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) + 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 + 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 } - - 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 } }