diff --git a/regression/Makefile b/regression/Makefile index 1c6df80b..f9a59e7a 100644 --- a/regression/Makefile +++ b/regression/Makefile @@ -59,6 +59,7 @@ endif ifeq ($(SUITE),GroundtestSuiteA) PROJECT=groundtest CONFIGS=MemtestConfig MemtestBufferlessConfig MemtestStatelessConfig +# FancyMemtestConfig takes too long to compile endif ifeq ($(SUITE),GroundtestSuiteB) diff --git a/src/main/scala/coreplex/Configs.scala b/src/main/scala/coreplex/Configs.scala index 267ce219..bd09cf20 100644 --- a/src/main/scala/coreplex/Configs.scala +++ b/src/main/scala/coreplex/Configs.scala @@ -143,12 +143,11 @@ class WithBufferlessBroadcastHub extends Config((site, here, up) => { * DO NOT use this configuration. */ class WithStatelessBridge extends Config((site, here, up) => { -/* !!! FIXME - case BankedL2Config => up(BankedL2Config, site).copy(coherenceManager = { case (_, _) => - val pass = LazyModule(new TLBuffer(0)(site)) - (pass.node, pass.node) - }) -*/ + case BankedL2Config => up(BankedL2Config, site).copy(coherenceManager = { case q => + implicit val p = q + val cork = LazyModule(new TLCacheCork(unsafe = true)) + (cork.node, TLWidthWidget(p(L1toL2Config).beatBytes)(cork.node)) + }) case DCacheKey => up(DCacheKey, site).copy(nMSHRs = 0) }) diff --git a/src/main/scala/coreplex/CoreplexNetwork.scala b/src/main/scala/coreplex/CoreplexNetwork.scala index f14a8229..bce3a12e 100644 --- a/src/main/scala/coreplex/CoreplexNetwork.scala +++ b/src/main/scala/coreplex/CoreplexNetwork.scala @@ -55,7 +55,7 @@ trait CoreplexNetworkModule extends HasCoreplexParameters { val prot = (if (manager.supportsGet) "R" else "") + (if (manager.supportsPutFull) "W" else "") + (if (manager.executable) "X" else "") + - (if (manager.supportsAcquire) " [C]" else "") + (if (manager.supportsAcquireB) " [C]" else "") manager.address.foreach { a => println(f"\t${manager.name}%s ${a.base}%x - ${a.base+a.mask+1}%x, $prot") } @@ -70,27 +70,23 @@ trait BankedL2CoherenceManagers extends CoreplexNetwork { require (isPow2(l2Config.nBanksPerChannel)) require (isPow2(l1tol2_lineBytes)) - val mem = Seq.fill(l2Config.nMemoryChannels) { + val mem = TLOutputNode() + for (i <- 0 until l2Config.nMemoryChannels) { val bankBar = LazyModule(new TLXbar) - val output = TLOutputNode() - output := bankBar.node + mem := bankBar.node val mask = ~BigInt((l2Config.nBanksPerChannel-1) * l1tol2_lineBytes) for (i <- 0 until l2Config.nBanksPerChannel) { val (in, out) = l2Config.coherenceManager(p) in := TLFilter(AddressSet(i * l1tol2_lineBytes, mask))(l1tol2.node) bankBar.node := out } - - output } } trait BankedL2CoherenceManagersBundle extends CoreplexNetworkBundle { val outer: BankedL2CoherenceManagers - - require (l2Config.nMemoryChannels <= 1, "Seq in Chisel Bundle needed to support > 1") // !!! - val mem = outer.mem.map(_.bundleOut).toList.headOption // .headOption should be removed !!! + val mem = outer.mem.bundleOut } trait BankedL2CoherenceManagersModule extends CoreplexNetworkModule { diff --git a/src/main/scala/diplomacy/Nodes.scala b/src/main/scala/diplomacy/Nodes.scala index c01febf7..5cd75811 100644 --- a/src/main/scala/diplomacy/Nodes.scala +++ b/src/main/scala/diplomacy/Nodes.scala @@ -224,29 +224,29 @@ class SinkNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(pi: P override lazy val bundleOut = { require(false, s"${name} has no bundleOut; try bundleIn?"); bundleIn } } -class BlindOutputNode[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) +class BlindOutputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(pi: Seq[PI]) + extends SimpleNode(imp)({case (0, _) => Seq()}, {case (_, Seq()) => pi}, 0 to 0, pi.size to pi.size) { override val flip = true override lazy val bundleOut = bundleIn } -class BlindInputNode[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) +class BlindInputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(po: Seq[PO]) + extends SimpleNode(imp)({case (_, Seq()) => po}, {case (0, _) => Seq()}, po.size to po.size, 0 to 0) { override val flip = true 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) +class InternalOutputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(pi: Seq[PI]) + extends SimpleNode(imp)({case (0, _) => Seq()}, {case (_, Seq()) => pi}, 0 to 0, pi.size to pi.size) { 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) +class InternalInputNode[PO, PI, EO, EI, B <: Data](imp: NodeImp[PO, PI, EO, EI, B])(po: Seq[PO]) + extends SimpleNode(imp)({case (_, Seq()) => po}, {case (0, _) => Seq()}, po.size to po.size, 0 to 0) { override val wire = true override lazy val bundleIn = bundleOut diff --git a/src/main/scala/groundtest/Configs.scala b/src/main/scala/groundtest/Configs.scala index 49191416..c539e6b4 100644 --- a/src/main/scala/groundtest/Configs.scala +++ b/src/main/scala/groundtest/Configs.scala @@ -40,7 +40,7 @@ class MemtestStatelessConfig extends Config( // Test ALL the things class FancyMemtestConfig extends Config( new WithNGenerators(1, 2) ++ new WithNCores(2) ++ new WithMemtest ++ - new WithNMemoryChannels(1) ++ new WithNBanksPerMemChannel(4) ++ // !!! waiting on Chisel3 support for 2 channels + new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(4) ++ new WithL2Cache ++ new GroundTestConfig) class CacheFillTestConfig extends Config( diff --git a/src/main/scala/groundtest/TestHarness.scala b/src/main/scala/groundtest/TestHarness.scala index a7f523fe..615a13dc 100644 --- a/src/main/scala/groundtest/TestHarness.scala +++ b/src/main/scala/groundtest/TestHarness.scala @@ -16,11 +16,6 @@ class TestHarness(implicit p: Parameters) extends 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 (axi4 <- dut.io.mem_axi4) { - Module(LazyModule(new SimAXIMem(memSize / dut.io.mem_axi4.size)).module).io.axi4 <> axi4 - } - } + val channels = p(coreplex.BankedL2Config).nMemoryChannels + if (channels > 0) Module(LazyModule(new SimAXIMem(channels)).module).io.axi4 <> dut.io.mem_axi4 } diff --git a/src/main/scala/groundtest/Top.scala b/src/main/scala/groundtest/Top.scala index bbd6cd19..5e328089 100644 --- a/src/main/scala/groundtest/Top.scala +++ b/src/main/scala/groundtest/Top.scala @@ -17,7 +17,7 @@ class GroundTestTop(implicit p: Parameters) extends BaseTop socBus.node := coreplex.mmio coreplex.mmioInt := intBus.intnode - (mem zip coreplex.mem) foreach { case (m, c) => m := c } + mem.foreach { _ := coreplex.mem } } class GroundTestTopBundle[+L <: GroundTestTop](_outer: L) extends BaseTopBundle(_outer) diff --git a/src/main/scala/rocket/DCache.scala b/src/main/scala/rocket/DCache.scala index f4e5adc2..3a71311b 100644 --- a/src/main/scala/rocket/DCache.scala +++ b/src/main/scala/rocket/DCache.scala @@ -253,7 +253,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { val access_address = s2_req.addr val a_size = s2_req.typ(MT_SZ-2, 0) val a_data = Fill(beatWords, pstore1_storegen.data) - val acquire = if (edge.manager.anySupportAcquire) { + val acquire = if (edge.manager.anySupportAcquireB) { edge.Acquire(a_source, acquire_address, lgCacheBlockBytes, s2_grow_param)._2 // Cacheability checked by tlb } else { Wire(new TLBundleA(edge.bundle)) @@ -373,7 +373,7 @@ class DCacheModule(outer: DCache) extends HellaCacheModule(outer) { b = probe_bits, reportPermissions = TLPermissions.NtoN) - val voluntaryReleaseMessage = if (edge.manager.anySupportAcquire) { + val voluntaryReleaseMessage = if (edge.manager.anySupportAcquireB) { edge.Release( fromSource = UInt(maxUncachedInFlight - 1), toAddress = probe_bits.address, diff --git a/src/main/scala/rocket/NBDcache.scala b/src/main/scala/rocket/NBDcache.scala index 11f67509..e99ae262 100644 --- a/src/main/scala/rocket/NBDcache.scala +++ b/src/main/scala/rocket/NBDcache.scala @@ -332,7 +332,7 @@ class MSHRFile(implicit edge: TLEdgeOut, cfg: DCacheConfig, p: Parameters) exten } // determine if the request is cacheable or not - val cacheable = edge.manager.supportsAcquireFast(io.req.bits.addr, lgCacheBlockBytes) + val cacheable = edge.manager.supportsAcquireBFast(io.req.bits.addr, lgCacheBlockBytes) val sdq_val = Reg(init=Bits(0, cfg.nSDQ)) val sdq_alloc_id = PriorityEncoder(~sdq_val(cfg.nSDQ-1,0)) diff --git a/src/main/scala/rocket/TLB.scala b/src/main/scala/rocket/TLB.scala index b31a805f..0e99a933 100644 --- a/src/main/scala/rocket/TLB.scala +++ b/src/main/scala/rocket/TLB.scala @@ -73,16 +73,19 @@ class TLB(implicit edge: TLEdgeOut, val p: Parameters) extends Module with HasTL val prot_r = fastCheck(_.supportsGet) val prot_w = fastCheck(_.supportsPutFull) val prot_x = fastCheck(_.executable) - val cacheable = fastCheck(_.supportsAcquire) + val cacheable = fastCheck(_.supportsAcquireB) + val xferSizes = TransferSizes(cacheBlockBytes, cacheBlockBytes) val allSizes = TransferSizes(1, cacheBlockBytes) val amoSizes = TransferSizes(1, xLen/8) edge.manager.managers.foreach { m => require (m.minAlignment >= 4096, s"MemoryMap region ${m.name} must be page-aligned (is ${m.minAlignment})") - require (!m.supportsGet || m.supportsGet .contains(allSizes), s"MemoryMap region ${m.name} only supports ${m.supportsGet} Get, but must support ${allSizes}") - require (!m.supportsPutFull || m.supportsPutFull.contains(allSizes), s"MemoryMap region ${m.name} only supports ${m.supportsPutFull} PutFull, but must support ${allSizes}") - require (!m.supportsAcquire || m.supportsAcquire.contains(allSizes), s"MemoryMap region ${m.name} only supports ${m.supportsAcquire} Acquire, but must support ${allSizes}") - require (!m.supportsLogical || m.supportsLogical.contains(amoSizes), s"MemoryMap region ${m.name} only supports ${m.supportsLogical} Logical, but must support ${amoSizes}") - require (!m.supportsArithmetic || m.supportsArithmetic.contains(amoSizes), s"MemoryMap region ${m.name} only supports ${m.supportsArithmetic} Arithmetic, but must support ${amoSizes}") + require (!m.supportsGet || m.supportsGet .contains(allSizes), s"MemoryMap region ${m.name} only supports ${m.supportsGet} Get, but must support ${allSizes}") + require (!m.supportsPutFull || m.supportsPutFull .contains(allSizes), s"MemoryMap region ${m.name} only supports ${m.supportsPutFull} PutFull, but must support ${allSizes}") + require (!m.supportsAcquireB || m.supportsAcquireB .contains(xferSizes), s"MemoryMap region ${m.name} only supports ${m.supportsAcquireB} AcquireB, but must support ${xferSizes}") + require (!m.supportsAcquireT || m.supportsAcquireT .contains(xferSizes), s"MemoryMap region ${m.name} only supports ${m.supportsAcquireT} AcquireT, but must support ${xferSizes}") + require (!m.supportsLogical || m.supportsLogical .contains(amoSizes), s"MemoryMap region ${m.name} only supports ${m.supportsLogical} Logical, but must support ${amoSizes}") + require (!m.supportsArithmetic || m.supportsArithmetic.contains(amoSizes), s"MemoryMap region ${m.name} only supports ${m.supportsArithmetic} Arithmetic, but must support ${amoSizes}") + require (m.supportsAcquireT || !m.supportsPutFull || !m.supportsAcquireB, s"MemoryMap region ${m.name} supports PutFull and AcquireB but not AcquireT") } val lookup_tag = Cat(io.ptw.ptbr.asid, io.req.bits.vpn(vpnBits-1,0)) diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index 64e95e6b..7402345b 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -87,11 +87,11 @@ trait PeripheryMasterAXI4Mem { private val config = p(ExtMem) private val channels = p(BankedL2Config).nMemoryChannels - val mem_axi4 = Seq.tabulate(channels) { i => + val mem_axi4 = AXI4BlindOutputNode(Seq.tabulate(channels) { i => val c_size = config.size/channels val c_base = config.base + c_size*i - AXI4BlindOutputNode(AXI4SlavePortParameters( + AXI4SlavePortParameters( slaves = Seq(AXI4SlaveParameters( address = List(AddressSet(c_base, c_size-1)), regionType = RegionType.UNCACHED, // cacheable @@ -99,12 +99,12 @@ trait PeripheryMasterAXI4Mem { supportsWrite = TransferSizes(1, 256), // The slave supports 1-256 byte transfers supportsRead = TransferSizes(1, 256), interleavedId = Some(0))), // slave does not interleave read responses - beatBytes = config.beatBytes)) - } + beatBytes = config.beatBytes) + }) - val mem = mem_axi4.map { node => + val mem = Seq.fill(channels) { val converter = LazyModule(new TLToAXI4(config.idBits)) - node := AXI4Buffer()(converter.node) + mem_axi4 := AXI4Buffer()(converter.node) converter.node } } @@ -113,7 +113,7 @@ trait PeripheryMasterAXI4MemBundle { this: TopNetworkBundle { val outer: PeripheryMasterAXI4Mem } => - val mem_axi4 = outer.mem_axi4.map(_.bundleOut).toList.headOption // !!! remove headOption when Seq supported + val mem_axi4 = outer.mem_axi4.bundleOut } trait PeripheryMasterAXI4MemModule { @@ -130,14 +130,14 @@ trait PeripheryMasterAXI4MMIO { this: TopNetwork => private val config = p(ExtBus) - val mmio_axi4 = AXI4BlindOutputNode(AXI4SlavePortParameters( + val mmio_axi4 = AXI4BlindOutputNode(Seq(AXI4SlavePortParameters( slaves = Seq(AXI4SlaveParameters( address = List(AddressSet(BigInt(config.base), config.size-1)), executable = true, // Can we run programs on this memory? supportsWrite = TransferSizes(1, 256), // The slave supports 1-256 byte transfers supportsRead = TransferSizes(1, 256), interleavedId = Some(0))), // slave does not interleave read responses - beatBytes = config.beatBytes)) + beatBytes = config.beatBytes))) mmio_axi4 := AXI4Buffer()( @@ -167,9 +167,9 @@ trait PeripheryMasterAXI4MMIOModule { // PeripherySlaveAXI4 is an example, make your own cake pattern like this one. trait PeripherySlaveAXI4 extends L2Crossbar { private val config = p(ExtIn) - val l2_axi4 = AXI4BlindInputNode(AXI4MasterPortParameters( + val l2_axi4 = AXI4BlindInputNode(Seq(AXI4MasterPortParameters( masters = Seq(AXI4MasterParameters( - id = IdRange(0, 1 << config.idBits))))) + id = IdRange(0, 1 << config.idBits)))))) l2.node := TLSourceShrinker(1 << config.sourceBits)( @@ -197,14 +197,14 @@ trait PeripheryMasterTLMMIO { this: TopNetwork => private val config = p(ExtBus) - val mmio_tl = TLBlindOutputNode(TLManagerPortParameters( + val mmio_tl = TLBlindOutputNode(Seq(TLManagerPortParameters( managers = Seq(TLManagerParameters( address = List(AddressSet(BigInt(config.base), config.size-1)), executable = true, supportsGet = TransferSizes(1, cacheBlockBytes), supportsPutFull = TransferSizes(1, cacheBlockBytes), supportsPutPartial = TransferSizes(1, cacheBlockBytes))), - beatBytes = config.beatBytes)) + beatBytes = config.beatBytes))) mmio_tl := TLBuffer()( @@ -233,9 +233,9 @@ trait PeripheryMasterTLMMIOModule { // NOTE: this port is NOT allowed to issue Acquires trait PeripherySlaveTL extends L2Crossbar { private val config = p(ExtIn) - val l2_tl = TLBlindInputNode(TLClientPortParameters( + val l2_tl = TLBlindInputNode(Seq(TLClientPortParameters( clients = Seq(TLClientParameters( - sourceId = IdRange(0, 1 << config.idBits))))) + sourceId = IdRange(0, 1 << config.idBits)))))) l2.node := TLSourceShrinker(1 << config.sourceBits)( diff --git a/src/main/scala/rocketchip/RocketPlexMaster.scala b/src/main/scala/rocketchip/RocketPlexMaster.scala index 05a4c331..ff6f7652 100644 --- a/src/main/scala/rocketchip/RocketPlexMaster.scala +++ b/src/main/scala/rocketchip/RocketPlexMaster.scala @@ -19,7 +19,7 @@ trait RocketPlexMaster extends L2Crossbar { coreplex.l2in := l2.node socBus.node := coreplex.mmio coreplex.mmioInt := intBus.intnode - (mem zip coreplex.mem) foreach { case (m, c) => m := c } + mem.foreach { _ := coreplex.mem } } trait RocketPlexMasterBundle extends L2CrossbarBundle { diff --git a/src/main/scala/rocketchip/TestHarness.scala b/src/main/scala/rocketchip/TestHarness.scala index 20aaaece..f9569534 100644 --- a/src/main/scala/rocketchip/TestHarness.scala +++ b/src/main/scala/rocketchip/TestHarness.scala @@ -18,13 +18,8 @@ class TestHarness()(implicit p: Parameters) extends Module { for (int <- dut.io.interrupts(0)) int := Bool(false) - if (dut.io.mem_axi4.nonEmpty) { - val memSize = p(ExtMem).size - require(memSize % dut.io.mem_axi4.size == 0) - for (axi4 <- dut.io.mem_axi4) { - Module(LazyModule(new SimAXIMem(memSize / dut.io.mem_axi4.size)).module).io.axi4 <> axi4 - } - } + val channels = p(coreplex.BankedL2Config).nMemoryChannels + if (channels > 0) Module(LazyModule(new SimAXIMem(channels)).module).io.axi4 <> dut.io.mem_axi4 if (!p(IncludeJtagDTM)) { val dtm = Module(new SimDTM).connect(clock, reset, dut.io.debug.get, io.success) @@ -32,7 +27,7 @@ class TestHarness()(implicit p: Parameters) extends Module { val jtag = Module(new JTAGVPI).connect(dut.io.jtag.get, reset, io.success) } - val mmio_sim = Module(LazyModule(new SimAXIMem(4096)).module) + val mmio_sim = Module(LazyModule(new SimAXIMem(1, 4096)).module) mmio_sim.io.axi4 <> dut.io.mmio_axi4 val l2_axi4 = dut.io.l2_axi4(0) @@ -43,12 +38,19 @@ class TestHarness()(implicit p: Parameters) extends Module { l2_axi4.b .ready := Bool(true) } -class SimAXIMem(size: BigInt)(implicit p: Parameters) extends LazyModule { +class SimAXIMem(channels: Int, forceSize: BigInt = 0)(implicit p: Parameters) extends LazyModule { val config = p(ExtMem) + val totalSize = if (forceSize > 0) forceSize else BigInt(config.size) + val size = totalSize / channels + require(totalSize % channels == 0) - val node = AXI4BlindInputNode(AXI4MasterPortParameters(Seq(AXI4MasterParameters(IdRange(0, 1 << config.idBits))))) - val sram = LazyModule(new AXI4RAM(AddressSet(0, size-1), beatBytes = config.beatBytes)) - sram.node := AXI4Buffer()(AXI4Fragmenter(maxInFlight = 4)(node)) + val node = AXI4BlindInputNode(Seq.fill(channels) { + AXI4MasterPortParameters(Seq(AXI4MasterParameters(IdRange(0, 1 << config.idBits))))}) + + for (i <- 0 until channels) { + val sram = LazyModule(new AXI4RAM(AddressSet(0, size-1), beatBytes = config.beatBytes)) + sram.node := AXI4Buffer()(AXI4Fragmenter(maxInFlight = 4)(node)) + } lazy val module = new LazyModuleImp(this) { val io = new Bundle { diff --git a/src/main/scala/uncore/ahb/Nodes.scala b/src/main/scala/uncore/ahb/Nodes.scala index 79776111..7ed88dd8 100644 --- a/src/main/scala/uncore/ahb/Nodes.scala +++ b/src/main/scala/uncore/ahb/Nodes.scala @@ -11,14 +11,9 @@ object AHBImp extends NodeImp[AHBMasterPortParameters, AHBSlavePortParameters, A { def edgeO(pd: AHBMasterPortParameters, pu: AHBSlavePortParameters): AHBEdgeParameters = AHBEdgeParameters(pd, pu) def edgeI(pd: AHBMasterPortParameters, pu: AHBSlavePortParameters): AHBEdgeParameters = AHBEdgeParameters(pd, pu) - def bundleO(eo: Seq[AHBEdgeParameters]): Vec[AHBBundle] = { - require (!eo.isEmpty) - Vec(eo.size, AHBBundle(eo.map(_.bundle).reduce(_.union(_)))) - } - def bundleI(ei: Seq[AHBEdgeParameters]): Vec[AHBBundle] = { - require (!ei.isEmpty) - Vec(ei.size, AHBBundle(ei.map(_.bundle).reduce(_.union(_)))) - } + + def bundleO(eo: Seq[AHBEdgeParameters]): Vec[AHBBundle] = Vec(eo.size, AHBBundle(AHBBundleParameters.union(eo.map(_.bundle)))) + def bundleI(ei: Seq[AHBEdgeParameters]): Vec[AHBBundle] = Vec(ei.size, AHBBundle(AHBBundleParameters.union(ei.map(_.bundle)))) def colour = "#00ccff" // bluish override def labelI(ei: AHBEdgeParameters) = (ei.slave.beatBytes * 8).toString @@ -52,8 +47,8 @@ case class AHBOutputNode() extends OutputNode(AHBImp) case class AHBInputNode() extends InputNode(AHBImp) // Nodes used for external ports -case class AHBBlindOutputNode(portParams: AHBSlavePortParameters) extends BlindOutputNode(AHBImp)(portParams) -case class AHBBlindInputNode(portParams: AHBMasterPortParameters) extends BlindInputNode(AHBImp)(portParams) +case class AHBBlindOutputNode(portParams: Seq[AHBSlavePortParameters]) extends BlindOutputNode(AHBImp)(portParams) +case class AHBBlindInputNode(portParams: Seq[AHBMasterPortParameters]) extends BlindInputNode(AHBImp)(portParams) -case class AHBInternalOutputNode(portParams: AHBSlavePortParameters) extends InternalOutputNode(AHBImp)(portParams) -case class AHBInternalInputNode(portParams: AHBMasterPortParameters) extends InternalInputNode(AHBImp)(portParams) +case class AHBInternalOutputNode(portParams: Seq[AHBSlavePortParameters]) extends InternalOutputNode(AHBImp)(portParams) +case class AHBInternalInputNode(portParams: Seq[AHBMasterPortParameters]) extends InternalInputNode(AHBImp)(portParams) diff --git a/src/main/scala/uncore/ahb/Parameters.scala b/src/main/scala/uncore/ahb/Parameters.scala index 1af5773c..ce85c0cd 100644 --- a/src/main/scala/uncore/ahb/Parameters.scala +++ b/src/main/scala/uncore/ahb/Parameters.scala @@ -85,6 +85,9 @@ case class AHBBundleParameters( object AHBBundleParameters { + val emptyBundleParams = AHBBundleParameters(addrBits = 1, dataBits = 8) + def union(x: Seq[AHBBundleParameters]) = x.foldLeft(emptyBundleParams)((x,y) => x.union(y)) + def apply(master: AHBMasterPortParameters, slave: AHBSlavePortParameters) = new AHBBundleParameters( addrBits = log2Up(slave.maxAddress+1), diff --git a/src/main/scala/uncore/apb/Nodes.scala b/src/main/scala/uncore/apb/Nodes.scala index 0663875b..7d22743b 100644 --- a/src/main/scala/uncore/apb/Nodes.scala +++ b/src/main/scala/uncore/apb/Nodes.scala @@ -11,14 +11,9 @@ object APBImp extends NodeImp[APBMasterPortParameters, APBSlavePortParameters, A { def edgeO(pd: APBMasterPortParameters, pu: APBSlavePortParameters): APBEdgeParameters = APBEdgeParameters(pd, pu) def edgeI(pd: APBMasterPortParameters, pu: APBSlavePortParameters): APBEdgeParameters = APBEdgeParameters(pd, pu) - def bundleO(eo: Seq[APBEdgeParameters]): Vec[APBBundle] = { - require (!eo.isEmpty) - Vec(eo.size, APBBundle(eo.map(_.bundle).reduce(_.union(_)))) - } - def bundleI(ei: Seq[APBEdgeParameters]): Vec[APBBundle] = { - require (!ei.isEmpty) - Vec(ei.size, APBBundle(ei.map(_.bundle).reduce(_.union(_)))) - } + + def bundleO(eo: Seq[APBEdgeParameters]): Vec[APBBundle] = Vec(eo.size, APBBundle(APBBundleParameters.union(eo.map(_.bundle)))) + def bundleI(ei: Seq[APBEdgeParameters]): Vec[APBBundle] = Vec(ei.size, APBBundle(APBBundleParameters.union(ei.map(_.bundle)))) def colour = "#00ccff" // bluish override def labelI(ei: APBEdgeParameters) = (ei.slave.beatBytes * 8).toString @@ -52,8 +47,8 @@ case class APBOutputNode() extends OutputNode(APBImp) case class APBInputNode() extends InputNode(APBImp) // Nodes used for external ports -case class APBBlindOutputNode(portParams: APBSlavePortParameters) extends BlindOutputNode(APBImp)(portParams) -case class APBBlindInputNode(portParams: APBMasterPortParameters) extends BlindInputNode(APBImp)(portParams) +case class APBBlindOutputNode(portParams: Seq[APBSlavePortParameters]) extends BlindOutputNode(APBImp)(portParams) +case class APBBlindInputNode(portParams: Seq[APBMasterPortParameters]) extends BlindInputNode(APBImp)(portParams) -case class APBInternalOutputNode(portParams: APBSlavePortParameters) extends InternalOutputNode(APBImp)(portParams) -case class APBInternalInputNode(portParams: APBMasterPortParameters) extends InternalInputNode(APBImp)(portParams) +case class APBInternalOutputNode(portParams: Seq[APBSlavePortParameters]) extends InternalOutputNode(APBImp)(portParams) +case class APBInternalInputNode(portParams: Seq[APBMasterPortParameters]) extends InternalInputNode(APBImp)(portParams) diff --git a/src/main/scala/uncore/apb/Parameters.scala b/src/main/scala/uncore/apb/Parameters.scala index dd75c7e2..3f47c96e 100644 --- a/src/main/scala/uncore/apb/Parameters.scala +++ b/src/main/scala/uncore/apb/Parameters.scala @@ -72,6 +72,9 @@ case class APBBundleParameters( object APBBundleParameters { + val emptyBundleParams = APBBundleParameters(addrBits = 1, dataBits = 8) + def union(x: Seq[APBBundleParameters]) = x.foldLeft(emptyBundleParams)((x,y) => x.union(y)) + def apply(master: APBMasterPortParameters, slave: APBSlavePortParameters) = new APBBundleParameters( addrBits = log2Up(slave.maxAddress+1), diff --git a/src/main/scala/uncore/axi4/Nodes.scala b/src/main/scala/uncore/axi4/Nodes.scala index 7d22b666..03c9e840 100644 --- a/src/main/scala/uncore/axi4/Nodes.scala +++ b/src/main/scala/uncore/axi4/Nodes.scala @@ -11,14 +11,9 @@ object AXI4Imp extends NodeImp[AXI4MasterPortParameters, AXI4SlavePortParameters { def edgeO(pd: AXI4MasterPortParameters, pu: AXI4SlavePortParameters): AXI4EdgeParameters = AXI4EdgeParameters(pd, pu) def edgeI(pd: AXI4MasterPortParameters, pu: AXI4SlavePortParameters): AXI4EdgeParameters = AXI4EdgeParameters(pd, pu) - def bundleO(eo: Seq[AXI4EdgeParameters]): Vec[AXI4Bundle] = { - require (!eo.isEmpty) - Vec(eo.size, AXI4Bundle(eo.map(_.bundle).reduce(_.union(_)))) - } - def bundleI(ei: Seq[AXI4EdgeParameters]): Vec[AXI4Bundle] = { - require (!ei.isEmpty) - Vec(ei.size, AXI4Bundle(ei.map(_.bundle).reduce(_.union(_)))) - } + + def bundleO(eo: Seq[AXI4EdgeParameters]): Vec[AXI4Bundle] = Vec(eo.size, AXI4Bundle(AXI4BundleParameters.union(eo.map(_.bundle)))) + def bundleI(ei: Seq[AXI4EdgeParameters]): Vec[AXI4Bundle] = Vec(ei.size, AXI4Bundle(AXI4BundleParameters.union(ei.map(_.bundle)))) def colour = "#00ccff" // bluish override def labelI(ei: AXI4EdgeParameters) = (ei.slave.beatBytes * 8).toString @@ -52,8 +47,8 @@ case class AXI4OutputNode() extends OutputNode(AXI4Imp) case class AXI4InputNode() extends InputNode(AXI4Imp) // Nodes used for external ports -case class AXI4BlindOutputNode(portParams: AXI4SlavePortParameters) extends BlindOutputNode(AXI4Imp)(portParams) -case class AXI4BlindInputNode(portParams: AXI4MasterPortParameters) extends BlindInputNode(AXI4Imp)(portParams) +case class AXI4BlindOutputNode(portParams: Seq[AXI4SlavePortParameters]) extends BlindOutputNode(AXI4Imp)(portParams) +case class AXI4BlindInputNode(portParams: Seq[AXI4MasterPortParameters]) extends BlindInputNode(AXI4Imp)(portParams) -case class AXI4InternalOutputNode(portParams: AXI4SlavePortParameters) extends InternalOutputNode(AXI4Imp)(portParams) -case class AXI4InternalInputNode(portParams: AXI4MasterPortParameters) extends InternalInputNode(AXI4Imp)(portParams) +case class AXI4InternalOutputNode(portParams: Seq[AXI4SlavePortParameters]) extends InternalOutputNode(AXI4Imp)(portParams) +case class AXI4InternalInputNode(portParams: Seq[AXI4MasterPortParameters]) extends InternalInputNode(AXI4Imp)(portParams) diff --git a/src/main/scala/uncore/axi4/Parameters.scala b/src/main/scala/uncore/axi4/Parameters.scala index 12e7b277..3e6b267f 100644 --- a/src/main/scala/uncore/axi4/Parameters.scala +++ b/src/main/scala/uncore/axi4/Parameters.scala @@ -101,6 +101,9 @@ case class AXI4BundleParameters( object AXI4BundleParameters { + val emptyBundleParams = AXI4BundleParameters(addrBits=1, dataBits=8, idBits=1) + def union(x: Seq[AXI4BundleParameters]) = x.foldLeft(emptyBundleParams)((x,y) => x.union(y)) + def apply(master: AXI4MasterPortParameters, slave: AXI4SlavePortParameters) = new AXI4BundleParameters( addrBits = log2Up(slave.maxAddress+1), diff --git a/src/main/scala/uncore/tilelink2/AtomicAutomata.scala b/src/main/scala/uncore/tilelink2/AtomicAutomata.scala index 667188b5..1674f45d 100644 --- a/src/main/scala/uncore/tilelink2/AtomicAutomata.scala +++ b/src/main/scala/uncore/tilelink2/AtomicAutomata.scala @@ -253,7 +253,7 @@ class TLAtomicAutomata(logical: Boolean = true, arithmetic: Boolean = true, conc in.d.bits := out.d.bits } - if (edgeOut.manager.anySupportAcquire && edgeIn.client.anySupportProbe) { + if (edgeOut.manager.anySupportAcquireB && edgeIn.client.anySupportProbe) { in.b.valid := out.b.valid out.b.ready := in.b.ready in.b.bits := out.b.bits diff --git a/src/main/scala/uncore/tilelink2/Broadcast.scala b/src/main/scala/uncore/tilelink2/Broadcast.scala index 50cc55dc..8e7f9629 100644 --- a/src/main/scala/uncore/tilelink2/Broadcast.scala +++ b/src/main/scala/uncore/tilelink2/Broadcast.scala @@ -22,22 +22,24 @@ class TLBroadcast(lineBytes: Int, numTrackers: Int = 4, bufferless: Boolean = fa endSinkId = numTrackers, managers = mp.managers.map { m => // We are the last level manager - require (m.regionType != RegionType.CACHED) - require (m.regionType != RegionType.TRACKED) - require (!m.supportsAcquire) + require (!m.supportsAcquireB) // We only manage addresses which are uncached - if (m.regionType == RegionType.UNCACHED && m.supportsGet) { + if (m.regionType == RegionType.UNCACHED) { // The device had better support line transfers val lowerBound = max(m.supportsPutFull.min, m.supportsGet.min) require (!m.supportsPutFull || m.supportsPutFull.contains(lineBytes)) require (!m.supportsGet || m.supportsGet .contains(lineBytes)) m.copy( regionType = RegionType.TRACKED, - supportsAcquire = TransferSizes(lowerBound, lineBytes), + supportsAcquireB = TransferSizes(lowerBound, lineBytes), + supportsAcquireT = if (m.supportsPutFull) TransferSizes(lowerBound, lineBytes) else TransferSizes.none, // truncate supported accesses to lineBytes (we only ever probe for one line) supportsPutFull = TransferSizes(m.supportsPutFull .min, min(m.supportsPutFull .max, lineBytes)), supportsPutPartial = TransferSizes(m.supportsPutPartial.min, min(m.supportsPutPartial.max, lineBytes)), supportsGet = TransferSizes(m.supportsGet .min, min(m.supportsGet .max, lineBytes)), + supportsHint = TransferSizes(m.supportsHint .min, min(m.supportsHint .max, lineBytes)), + supportsArithmetic = TransferSizes(m.supportsArithmetic.min, min(m.supportsArithmetic.max, lineBytes)), + supportsLogical = TransferSizes(m.supportsLogical .min, min(m.supportsLogical .max, lineBytes)), fifoId = None // trackers do not respond in FIFO order! ) } else { diff --git a/src/main/scala/uncore/tilelink2/Buffer.scala b/src/main/scala/uncore/tilelink2/Buffer.scala index 56a4070a..b481e0d5 100644 --- a/src/main/scala/uncore/tilelink2/Buffer.scala +++ b/src/main/scala/uncore/tilelink2/Buffer.scala @@ -31,7 +31,7 @@ class TLBuffer(a: Int = 2, b: Int = 2, c: Int = 2, d: Int = 2, e: Int = 2, pipe: if (a>0) { out.a <> Queue(in .a, a, pipe && a<2) } else { out.a <> in.a } if (d>0) { in .d <> Queue(out.d, d, pipe && d<2) } else { in.d <> out.d } - if (edgeOut.manager.anySupportAcquire && edgeOut.client.anySupportProbe) { + if (edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe) { if (b>0) { in .b <> Queue(out.b, b, pipe && b<2) } else { in.b <> out.b } if (c>0) { out.c <> Queue(in .c, c, pipe && c<2) } else { out.c <> in.c } if (e>0) { out.e <> Queue(in .e, e, pipe && e<2) } else { out.e <> in.e } diff --git a/src/main/scala/uncore/tilelink2/CacheCork.scala b/src/main/scala/uncore/tilelink2/CacheCork.scala new file mode 100644 index 00000000..60e7305d --- /dev/null +++ b/src/main/scala/uncore/tilelink2/CacheCork.scala @@ -0,0 +1,128 @@ +// See LICENSE.SiFive for license details. + +package uncore.tilelink2 + +import Chisel._ +import chisel3.internal.sourceinfo.SourceInfo +import config._ +import diplomacy._ +import scala.math.{min,max} +import TLMessages._ + +class TLCacheCork(unsafe: Boolean = false)(implicit p: Parameters) extends LazyModule +{ + val node = TLAdapterNode( + clientFn = { case Seq(cp) => + cp.copy(clients = cp.clients.map { c => c.copy( + sourceId = IdRange(c.sourceId.start*2, c.sourceId.end*2))})}, + managerFn = { case Seq(mp) => + mp.copy(managers = mp.managers.map { m => m.copy( + regionType = if (m.regionType == RegionType.UNCACHED) RegionType.TRACKED else m.regionType, + supportsAcquireB = m.supportsGet, + supportsAcquireT = m.supportsPutFull)})}) + + 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) + + require (edgeIn.client.clients.size == 1 || unsafe, "Only one client can safely use a TLCacheCork") + require (edgeIn.client.clients.filter(_.supportsProbe).size == 1, "Only one caching client allowed") + edgeOut.manager.managers.foreach { case m => + require (!m.supportsAcquireB, "Cannot support caches beyond the Cork") + } + + val out = io.out(0) + val in = io.in(0) + + // The Cork turns [Acquire=>Get] => [AccessAckData=>GrantData] + // and [ReleaseData=>PutFullData] => [AccessAck=>ReleaseAck] + // We need to encode information sufficient to reverse the transformation in output. + // A caveat is that we get Acquire+Release with the same source and must keep the + // source unique after transformation onto the A channel. + // The coding scheme is: + // Put: 1, Release: 0 => AccessAck + // *: 0, Acquire: 1 => AccessAckData + + // Take requests from A to A + val isPut = in.a.bits.opcode === PutFullData || in.a.bits.opcode === PutPartialData + val a_a = Wire(out.a) + a_a <> in.a + a_a.bits.source := in.a.bits.source << 1 | Mux(isPut, UInt(1), UInt(0)) + + // Transform Acquire into Get + when (in.a.bits.opcode === Acquire) { + a_a.bits.opcode := Get + a_a.bits.param := UInt(0) + a_a.bits.source := in.a.bits.source << 1 | UInt(1) + } + + // Take ReleaseData from C to A; Release from C to D + val c_a = Wire(out.a) + c_a.valid := in.c.valid && in.c.bits.opcode === ReleaseData + c_a.bits.opcode := PutFullData + c_a.bits.param := UInt(0) + c_a.bits.size := in.c.bits.size + c_a.bits.source := in.c.bits.source << 1 + c_a.bits.address := in.c.bits.address + c_a.bits.mask := edgeOut.mask(in.c.bits.address, in.c.bits.size) + c_a.bits.data := in.c.bits.data + + val c_d = Wire(in.d) + c_d.valid := in.c.valid && in.c.bits.opcode === Release + c_d.bits.opcode := ReleaseAck + c_d.bits.param := UInt(0) + c_d.bits.size := in.c.bits.size + c_d.bits.source := in.c.bits.source + c_d.bits.sink := UInt(0) + c_d.bits.addr_lo := in.c.bits.address + c_d.bits.data := UInt(0) + c_d.bits.error := Bool(false) + + assert (!in.c.valid || in.c.bits.opcode === Release || in.c.bits.opcode === ReleaseData) + in.c.ready := Mux(in.c.bits.opcode === Release, c_d.ready, c_a.ready) + + // Discard E + in.e.ready := Bool(true) + + // Block B; should never happen + out.b.ready := Bool(false) + assert (!out.b.valid) + + // Take responses from D and transform them + val d_d = Wire(in.d) + d_d <> out.d + d_d.bits.source := out.d.bits.source >> 1 + + when (out.d.bits.opcode === AccessAckData && out.d.bits.source(0)) { + d_d.bits.opcode := GrantData + d_d.bits.param := TLPermissions.toT + } + when (out.d.bits.opcode === AccessAck && !out.d.bits.source(0)) { + d_d.bits.opcode := ReleaseAck + } + + // Combine the sources of messages into the channels + TLArbiter(TLArbiter.lowestIndexFirst)(out.a, (edgeOut.numBeats1(c_a.bits), c_a), (edgeOut.numBeats1(a_a.bits), a_a)) + TLArbiter(TLArbiter.lowestIndexFirst)(in.d, (edgeIn .numBeats1(d_d.bits), d_d), (UInt(0), Queue(c_d, 2))) + + // Tie off unused ports + in.b.valid := Bool(false) + out.c.valid := Bool(false) + out.e.valid := Bool(false) + } +} + +object TLCacheCork +{ + // applied to the TL source node; y.node := TLCacheCork()(x.node) + def apply(unsafe: Boolean = false)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { + val cork = LazyModule(new TLCacheCork(unsafe)) + cork.node := x + cork.node + } +} diff --git a/src/main/scala/uncore/tilelink2/Crossing.scala b/src/main/scala/uncore/tilelink2/Crossing.scala index f0eb8caf..dae7440d 100644 --- a/src/main/scala/uncore/tilelink2/Crossing.scala +++ b/src/main/scala/uncore/tilelink2/Crossing.scala @@ -20,7 +20,7 @@ class TLAsyncCrossingSource(sync: Int = 3)(implicit p: Parameters) extends LazyM ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => val sink_reset_n = out.a.sink_reset_n - val bce = edgeIn.manager.anySupportAcquire && edgeIn.client.anySupportProbe + val bce = edgeIn.manager.anySupportAcquireB && edgeIn.client.anySupportProbe val depth = edgeOut.manager.depth out.a <> ToAsyncBundle(in.a, depth, sync) @@ -54,7 +54,7 @@ class TLAsyncCrossingSink(depth: Int = 8, sync: Int = 3)(implicit p: Parameters) ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => val source_reset_n = in.a.source_reset_n - val bce = edgeOut.manager.anySupportAcquire && edgeOut.client.anySupportProbe + val bce = edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe out.a <> FromAsyncBundle(in.a, sync) in.d <> ToAsyncBundle(out.d, depth, sync) diff --git a/src/main/scala/uncore/tilelink2/Edges.scala b/src/main/scala/uncore/tilelink2/Edges.scala index e794d846..886902d7 100644 --- a/src/main/scala/uncore/tilelink2/Edges.scala +++ b/src/main/scala/uncore/tilelink2/Edges.scala @@ -27,7 +27,7 @@ class TLEdge( // Do there exist A messages with Data? val aDataYes = manager.anySupportArithmetic || manager.anySupportLogical || manager.anySupportPutFull || manager.anySupportPutPartial // Do there exist A messages without Data? - val aDataNo = manager.anySupportAcquire || manager.anySupportGet || manager.anySupportHint + val aDataNo = manager.anySupportAcquireB || manager.anySupportGet || manager.anySupportHint // Statically optimize the case where hasData is a constant if (!aDataYes) Some(false) else if (!aDataNo) Some(true) else None } @@ -48,9 +48,9 @@ class TLEdge( } case _:TLBundleD => { // Do there eixst D messages with Data? - val dDataYes = manager.anySupportGet || manager.anySupportArithmetic || manager.anySupportLogical || manager.anySupportAcquire + val dDataYes = manager.anySupportGet || manager.anySupportArithmetic || manager.anySupportLogical || manager.anySupportAcquireB // Do there exist D messages without Data? - val dDataNo = manager.anySupportPutFull || manager.anySupportPutPartial || manager.anySupportHint || manager.anySupportAcquire + val dDataNo = manager.anySupportPutFull || manager.anySupportPutPartial || manager.anySupportHint || manager.anySupportAcquireT if (!dDataYes) Some(false) else if (!dDataNo) Some(true) else None } case _:TLBundleE => Some(false) @@ -244,8 +244,8 @@ class TLEdgeOut( { // Transfers def Acquire(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = { - require (manager.anySupportAcquire) - val legal = manager.supportsAcquireFast(toAddress, lgSize) + require (manager.anySupportAcquireB) + val legal = manager.supportsAcquireBFast(toAddress, lgSize) val a = Wire(new TLBundleA(bundle)) a.opcode := TLMessages.Acquire a.param := growPermissions @@ -258,8 +258,8 @@ class TLEdgeOut( } def Release(fromSource: UInt, toAddress: UInt, lgSize: UInt, shrinkPermissions: UInt) = { - require (manager.anySupportAcquire) - val legal = manager.supportsAcquireFast(toAddress, lgSize) + require (manager.anySupportAcquireB) + val legal = manager.supportsAcquireBFast(toAddress, lgSize) val c = Wire(new TLBundleC(bundle)) c.opcode := TLMessages.Release c.param := shrinkPermissions @@ -272,8 +272,8 @@ class TLEdgeOut( } def Release(fromSource: UInt, toAddress: UInt, lgSize: UInt, shrinkPermissions: UInt, data: UInt) = { - require (manager.anySupportAcquire) - val legal = manager.supportsAcquireFast(toAddress, lgSize) + require (manager.anySupportAcquireB) + val legal = manager.supportsAcquireBFast(toAddress, lgSize) val c = Wire(new TLBundleC(bundle)) c.opcode := TLMessages.ReleaseData c.param := shrinkPermissions diff --git a/src/main/scala/uncore/tilelink2/Filter.scala b/src/main/scala/uncore/tilelink2/Filter.scala index b6ddb9ea..3c0a04b7 100644 --- a/src/main/scala/uncore/tilelink2/Filter.scala +++ b/src/main/scala/uncore/tilelink2/Filter.scala @@ -22,7 +22,8 @@ class TLFilter(select: AddressSet)(implicit p: Parameters) extends LazyModule if (filtered.isEmpty) { None } else { Some(m.copy( address = filtered, - supportsAcquire = m.supportsAcquire .intersect(cap), + supportsAcquireT = m.supportsAcquireT .intersect(cap), + supportsAcquireB = m.supportsAcquireB .intersect(cap), supportsArithmetic = m.supportsArithmetic.intersect(cap), supportsLogical = m.supportsLogical .intersect(cap), supportsGet = m.supportsGet .intersect(cap), diff --git a/src/main/scala/uncore/tilelink2/Fragmenter.scala b/src/main/scala/uncore/tilelink2/Fragmenter.scala index 63197e63..934fb9b1 100644 --- a/src/main/scala/uncore/tilelink2/Fragmenter.scala +++ b/src/main/scala/uncore/tilelink2/Fragmenter.scala @@ -62,7 +62,7 @@ class TLFragmenter(val minSize: Int, val maxSize: Int, val alwaysMin: Boolean = // We don't support fragmenting to sub-beat accesses require (minSize >= beatBytes) // We can't support devices which are cached on both sides of us - require (!edgeOut.manager.anySupportAcquire || !edgeIn.client.anySupportProbe) + require (!edgeOut.manager.anySupportAcquireB || !edgeIn.client.anySupportProbe) /* The Fragmenter is a bit tricky, because there are 5 sizes in play: * max size -- the maximum transfer size possible diff --git a/src/main/scala/uncore/tilelink2/HintHandler.scala b/src/main/scala/uncore/tilelink2/HintHandler.scala index d9540b52..623d4887 100644 --- a/src/main/scala/uncore/tilelink2/HintHandler.scala +++ b/src/main/scala/uncore/tilelink2/HintHandler.scala @@ -27,7 +27,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f val edgeOut = node.edgesOut(0) // Don't add support for clients if there is no BCE channel - val bce = edgeOut.manager.anySupportAcquire && edgeIn.client.anySupportProbe + val bce = edgeOut.manager.anySupportAcquireB && edgeIn.client.anySupportProbe require (!supportClients || bce) // Does it even make sense to add the HintHandler? diff --git a/src/main/scala/uncore/tilelink2/IntNodes.scala b/src/main/scala/uncore/tilelink2/IntNodes.scala index eac638ba..18d0553e 100644 --- a/src/main/scala/uncore/tilelink2/IntNodes.scala +++ b/src/main/scala/uncore/tilelink2/IntNodes.scala @@ -95,11 +95,11 @@ case class IntAdapterNode( 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 IntBlindOutputNode() extends BlindOutputNode(IntImp)(Seq(IntSinkPortParameters(Seq(IntSinkParameters())))) +case class IntBlindInputNode(num: Int) extends BlindInputNode(IntImp)(Seq(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)))) +case class IntInternalOutputNode() extends InternalOutputNode(IntImp)(Seq(IntSinkPortParameters(Seq(IntSinkParameters())))) +case class IntInternalInputNode(num: Int) extends InternalInputNode(IntImp)(Seq(IntSourcePortParameters(Seq(IntSourceParameters(num))))) class IntXbar()(implicit p: Parameters) extends LazyModule { diff --git a/src/main/scala/uncore/tilelink2/Isolation.scala b/src/main/scala/uncore/tilelink2/Isolation.scala index bc3fcd44..74eba192 100644 --- a/src/main/scala/uncore/tilelink2/Isolation.scala +++ b/src/main/scala/uncore/tilelink2/Isolation.scala @@ -57,7 +57,7 @@ class TLIsolation(fOut: (Bool, UInt) => UInt, fIn: (Bool, UInt) => UInt)(implici ABo(out.a, in .a) ABi(in .d, out.d) - if (edgeOut.manager.base.anySupportAcquire && edgeOut.client.base.anySupportProbe) { + if (edgeOut.manager.base.anySupportAcquireB && edgeOut.client.base.anySupportProbe) { ABi(in .b, out.b) ABo(out.c, in .c) ABo(out.e, in .e) diff --git a/src/main/scala/uncore/tilelink2/Monitor.scala b/src/main/scala/uncore/tilelink2/Monitor.scala index 184fe9a0..c0ce44e1 100644 --- a/src/main/scala/uncore/tilelink2/Monitor.scala +++ b/src/main/scala/uncore/tilelink2/Monitor.scala @@ -42,7 +42,7 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args) val mask = edge.full_mask(bundle) when (bundle.opcode === TLMessages.Acquire) { - assert (edge.manager.supportsAcquireSafe(edge.address(bundle), bundle.size), "'A' channel carries Acquire type unsupported by manager" + extra) + assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'A' channel carries Acquire type unsupported by manager" + extra) assert (source_ok, "'A' channel Acquire carries invalid source ID" + extra) assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel Acquire smaller than a beat" + extra) assert (is_aligned, "'A' channel Acquire address not aligned to size" + extra) @@ -189,7 +189,7 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args) } when (bundle.opcode === TLMessages.Release) { - assert (edge.manager.supportsAcquireSafe(edge.address(bundle), bundle.size), "'C' channel carries Release type unsupported by manager" + extra) + assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'C' channel carries Release type unsupported by manager" + extra) assert (source_ok, "'C' channel Release carries invalid source ID" + extra) assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel Release smaller than a beat" + extra) assert (is_aligned, "'C' channel Release address not aligned to size" + extra) @@ -198,7 +198,7 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args) } when (bundle.opcode === TLMessages.ReleaseData) { - assert (edge.manager.supportsAcquireSafe(edge.address(bundle), bundle.size), "'C' channel carries ReleaseData type unsupported by manager" + extra) + assert (edge.manager.supportsAcquireBSafe(edge.address(bundle), bundle.size), "'C' channel carries ReleaseData type unsupported by manager" + extra) assert (source_ok, "'C' channel ReleaseData carries invalid source ID" + extra) assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel ReleaseData smaller than a beat" + extra) assert (is_aligned, "'C' channel ReleaseData address not aligned to size" + extra) @@ -409,7 +409,7 @@ class TLMonitor(args: TLMonitorArgs) extends TLMonitorBase(args) val d_last = edge.last(bundle.d.bits, bundle.d.fire()) if (edge.manager.minLatency > 0) { - assert(bundle.a.bits.source =/= bundle.d.bits.source || !bundle.a.valid || !bundle.d.valid, s"'A' and 'D' concurrent, despite minlatency ${edge.manager.minLatency}" + extra) + assert(bundle.d.bits.opcode === TLMessages.ReleaseAck || bundle.a.bits.source =/= bundle.d.bits.source || !bundle.a.valid || !bundle.d.valid, s"'A' and 'D' concurrent, despite minlatency ${edge.manager.minLatency}" + extra) } val a_set = Wire(init = UInt(0, width = edge.client.endSourceId)) diff --git a/src/main/scala/uncore/tilelink2/Nodes.scala b/src/main/scala/uncore/tilelink2/Nodes.scala index da879180..9fb1c000 100644 --- a/src/main/scala/uncore/tilelink2/Nodes.scala +++ b/src/main/scala/uncore/tilelink2/Nodes.scala @@ -16,14 +16,9 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL { def edgeO(pd: TLClientPortParameters, pu: TLManagerPortParameters): TLEdgeOut = new TLEdgeOut(pd, pu) def edgeI(pd: TLClientPortParameters, pu: TLManagerPortParameters): TLEdgeIn = new TLEdgeIn(pd, pu) - def bundleO(eo: Seq[TLEdgeOut]): Vec[TLBundle] = { - require (!eo.isEmpty) - Vec(eo.size, TLBundle(eo.map(_.bundle).reduce(_.union(_)))) - } - def bundleI(ei: Seq[TLEdgeIn]): Vec[TLBundle] = { - require (!ei.isEmpty) - Vec(ei.size, TLBundle(ei.map(_.bundle).reduce(_.union(_)))) - } + + def bundleO(eo: Seq[TLEdgeOut]): Vec[TLBundle] = Vec(eo.size, TLBundle(TLBundleParameters.union(eo.map(_.bundle)))) + def bundleI(ei: Seq[TLEdgeIn]): Vec[TLBundle] = Vec(ei.size, TLBundle(TLBundleParameters.union(ei.map(_.bundle)))) def colour = "#000000" // black override def labelI(ei: TLEdgeIn) = (ei.manager.beatBytes * 8).toString @@ -120,11 +115,11 @@ case class TLOutputNode() extends OutputNode(TLImp) case class TLInputNode() extends InputNode(TLImp) // Nodes used for external ports -case class TLBlindOutputNode(portParams: TLManagerPortParameters) extends BlindOutputNode(TLImp)(portParams) -case class TLBlindInputNode(portParams: TLClientPortParameters) extends BlindInputNode(TLImp)(portParams) +case class TLBlindOutputNode(portParams: Seq[TLManagerPortParameters]) extends BlindOutputNode(TLImp)(portParams) +case class TLBlindInputNode(portParams: Seq[TLClientPortParameters]) extends BlindInputNode(TLImp)(portParams) -case class TLInternalOutputNode(portParams: TLManagerPortParameters) extends InternalOutputNode(TLImp)(portParams) -case class TLInternalInputNode(portParams: TLClientPortParameters) extends InternalInputNode(TLImp)(portParams) +case class TLInternalOutputNode(portParams: Seq[TLManagerPortParameters]) extends InternalOutputNode(TLImp)(portParams) +case class TLInternalInputNode(portParams: Seq[TLClientPortParameters]) extends InternalInputNode(TLImp)(portParams) /** Synthesizeable unit tests */ import unittest._ @@ -152,14 +147,9 @@ object TLAsyncImp extends NodeImp[TLAsyncClientPortParameters, TLAsyncManagerPor { def edgeO(pd: TLAsyncClientPortParameters, pu: TLAsyncManagerPortParameters): TLAsyncEdgeParameters = TLAsyncEdgeParameters(pd, pu) def edgeI(pd: TLAsyncClientPortParameters, pu: TLAsyncManagerPortParameters): TLAsyncEdgeParameters = TLAsyncEdgeParameters(pd, pu) - def bundleO(eo: Seq[TLAsyncEdgeParameters]): Vec[TLAsyncBundle] = { - require (eo.size == 1) - Vec(eo.size, new TLAsyncBundle(eo(0).bundle)) - } - def bundleI(ei: Seq[TLAsyncEdgeParameters]): Vec[TLAsyncBundle] = { - require (ei.size == 1) - Vec(ei.size, new TLAsyncBundle(ei(0).bundle)) - } + + def bundleO(eo: Seq[TLAsyncEdgeParameters]): Vec[TLAsyncBundle] = Vec(eo.size, new TLAsyncBundle(TLAsyncBundleParameters.union(eo.map(_.bundle)))) + def bundleI(ei: Seq[TLAsyncEdgeParameters]): Vec[TLAsyncBundle] = Vec(ei.size, new TLAsyncBundle(TLAsyncBundleParameters.union(ei.map(_.bundle)))) def colour = "#ff0000" // red override def labelI(ei: TLAsyncEdgeParameters) = ei.manager.depth.toString diff --git a/src/main/scala/uncore/tilelink2/Parameters.scala b/src/main/scala/uncore/tilelink2/Parameters.scala index 7418d575..2fac6bee 100644 --- a/src/main/scala/uncore/tilelink2/Parameters.scala +++ b/src/main/scala/uncore/tilelink2/Parameters.scala @@ -12,7 +12,8 @@ case class TLManagerParameters( executable: Boolean = false, // processor can execute from this memory nodePath: Seq[BaseNode] = Seq(), // Supports both Acquire+Release+Finish of these sizes - supportsAcquire: TransferSizes = TransferSizes.none, + supportsAcquireT: TransferSizes = TransferSizes.none, + supportsAcquireB: TransferSizes = TransferSizes.none, supportsArithmetic: TransferSizes = TransferSizes.none, supportsLogical: TransferSizes = TransferSizes.none, supportsGet: TransferSizes = TransferSizes.none, @@ -28,10 +29,20 @@ case class TLManagerParameters( address.combinations(2).foreach { case Seq(x,y) => require (!x.overlaps(y)) } require (supportsPutFull.contains(supportsPutPartial)) + require (supportsPutFull.contains(supportsArithmetic)) + require (supportsPutFull.contains(supportsLogical)) + require (supportsGet.contains(supportsArithmetic)) + require (supportsGet.contains(supportsLogical)) + require (supportsAcquireB.contains(supportsAcquireT)) + + // Make sure that the regionType agrees with the capabilities + require ((regionType == RegionType.CACHED || regionType == RegionType.TRACKED) != supportsAcquireB.none) + require (regionType != RegionType.UNCACHED || supportsGet) // Largest support transfer of all types val maxTransfer = List( - supportsAcquire.max, + supportsAcquireT.max, + supportsAcquireB.max, supportsArithmetic.max, supportsLogical.max, supportsGet.max, @@ -73,7 +84,8 @@ case class TLManagerPortParameters( def maxTransfer = managers.map(_.maxTransfer).max // Operation sizes supported by all outward Managers - val allSupportAcquire = managers.map(_.supportsAcquire) .reduce(_ intersect _) + val allSupportAcquireT = managers.map(_.supportsAcquireT) .reduce(_ intersect _) + val allSupportAcquireB = managers.map(_.supportsAcquireB) .reduce(_ intersect _) val allSupportArithmetic = managers.map(_.supportsArithmetic).reduce(_ intersect _) val allSupportLogical = managers.map(_.supportsLogical) .reduce(_ intersect _) val allSupportGet = managers.map(_.supportsGet) .reduce(_ intersect _) @@ -82,7 +94,8 @@ case class TLManagerPortParameters( val allSupportHint = managers.map(_.supportsHint) .reduce(_ intersect _) // Operation supported by at least one outward Managers - val anySupportAcquire = managers.map(!_.supportsAcquire.none) .reduce(_ || _) + val anySupportAcquireT = managers.map(!_.supportsAcquireT.none) .reduce(_ || _) + val anySupportAcquireB = managers.map(!_.supportsAcquireB.none) .reduce(_ || _) val anySupportArithmetic = managers.map(!_.supportsArithmetic.none).reduce(_ || _) val anySupportLogical = managers.map(!_.supportsLogical.none) .reduce(_ || _) val anySupportGet = managers.map(!_.supportsGet.none) .reduce(_ || _) @@ -122,7 +135,8 @@ case class TLManagerPortParameters( } // Check for support of a given operation at a specific address - val supportsAcquireSafe = safe_helper(_.supportsAcquire) _ + val supportsAcquireTSafe = safe_helper(_.supportsAcquireT) _ + val supportsAcquireBSafe = safe_helper(_.supportsAcquireB) _ val supportsArithmeticSafe = safe_helper(_.supportsArithmetic) _ val supportsLogicalSafe = safe_helper(_.supportsLogical) _ val supportsGetSafe = safe_helper(_.supportsGet) _ @@ -130,7 +144,8 @@ case class TLManagerPortParameters( val supportsPutPartialSafe = safe_helper(_.supportsPutPartial) _ val supportsHintSafe = safe_helper(_.supportsHint) _ - val supportsAcquireFast = fast_helper(_.supportsAcquire) _ + val supportsAcquireTFast = fast_helper(_.supportsAcquireT) _ + val supportsAcquireBFast = fast_helper(_.supportsAcquireB) _ val supportsArithmeticFast = fast_helper(_.supportsArithmetic) _ val supportsLogicalFast = fast_helper(_.supportsLogical) _ val supportsGetFast = fast_helper(_.supportsGet) _ @@ -258,6 +273,15 @@ case class TLBundleParameters( object TLBundleParameters { + val emptyBundleParams = TLBundleParameters( + addressBits = 1, + dataBits = 8, + sourceBits = 1, + sinkBits = 1, + sizeBits = 1) + + def union(x: Seq[TLBundleParameters]) = x.foldLeft(emptyBundleParams)((x,y) => x.union(y)) + def apply(client: TLClientPortParameters, manager: TLManagerPortParameters) = new TLBundleParameters( addressBits = log2Up(manager.maxAddress + 1), @@ -282,7 +306,21 @@ case class TLEdgeParameters( case class TLAsyncManagerPortParameters(depth: Int, base: TLManagerPortParameters) { require (isPow2(depth)) } case class TLAsyncClientPortParameters(base: TLClientPortParameters) -case class TLAsyncBundleParameters(depth: Int, base: TLBundleParameters) { require (isPow2(depth)) } + +case class TLAsyncBundleParameters(depth: Int, base: TLBundleParameters) +{ + require (isPow2(depth)) + def union(x: TLAsyncBundleParameters) = TLAsyncBundleParameters( + depth = max(depth, x.depth), + base = base.union(x.base)) +} + +object TLAsyncBundleParameters +{ + val emptyBundleParams = TLAsyncBundleParameters(depth = 1, base = TLBundleParameters.emptyBundleParams) + def union(x: Seq[TLAsyncBundleParameters]) = x.foldLeft(emptyBundleParams)((x,y) => x.union(y)) +} + case class TLAsyncEdgeParameters(client: TLAsyncClientPortParameters, manager: TLAsyncManagerPortParameters) { val bundle = TLAsyncBundleParameters(manager.depth, TLBundleParameters(client.base, manager.base)) @@ -296,7 +334,8 @@ object ManagerUnification regionType: RegionType.T, executable: Boolean, lastNode: BaseNode, - supportsAcquire: TransferSizes, + supportsAcquireT: TransferSizes, + supportsAcquireB: TransferSizes, supportsArithmetic: TransferSizes, supportsLogical: TransferSizes, supportsGet: TransferSizes, @@ -307,7 +346,8 @@ object ManagerUnification regionType = x.regionType, executable = x.executable, lastNode = x.nodePath.last, - supportsAcquire = x.supportsAcquire, + supportsAcquireT = x.supportsAcquireT, + supportsAcquireB = x.supportsAcquireB, supportsArithmetic = x.supportsArithmetic, supportsLogical = x.supportsLogical, supportsGet = x.supportsGet, diff --git a/src/main/scala/uncore/tilelink2/SourceShrinker.scala b/src/main/scala/uncore/tilelink2/SourceShrinker.scala index d4948bc4..5e4788cf 100644 --- a/src/main/scala/uncore/tilelink2/SourceShrinker.scala +++ b/src/main/scala/uncore/tilelink2/SourceShrinker.scala @@ -31,7 +31,7 @@ class TLSourceShrinker(maxInFlight: Int)(implicit p: Parameters) extends LazyMod // Acquires cannot pass this adapter; it makes Probes impossible require (!edgeIn.client.anySupportProbe || - !edgeOut.manager.anySupportAcquire) + !edgeOut.manager.anySupportAcquireB) out.b.ready := Bool(true) out.c.valid := Bool(false) diff --git a/src/main/scala/uncore/tilelink2/ToAXI4.scala b/src/main/scala/uncore/tilelink2/ToAXI4.scala index 53fec766..cd068e97 100644 --- a/src/main/scala/uncore/tilelink2/ToAXI4.scala +++ b/src/main/scala/uncore/tilelink2/ToAXI4.scala @@ -84,9 +84,9 @@ class TLToAXI4(idBits: Int, combinational: Boolean = true)(implicit p: Parameter val a_last = edgeIn.last(in.a) // Make sure the fields are within the bounds we assumed - assert (a_source < UInt(1 << sourceBits)) - assert (a_size < UInt(1 << sizeBits)) - assert (a_addr_lo < UInt(1 << addrBits)) + assert (a_source < UInt(BigInt(1) << sourceBits)) + assert (a_size < UInt(BigInt(1) << sizeBits)) + assert (a_addr_lo < UInt(BigInt(1) << addrBits)) // Carefully pack/unpack fields into the state we send val baseEnd = 0 diff --git a/src/main/scala/uncore/tilelink2/WidthWidget.scala b/src/main/scala/uncore/tilelink2/WidthWidget.scala index 7a8aa01f..7c24d082 100644 --- a/src/main/scala/uncore/tilelink2/WidthWidget.scala +++ b/src/main/scala/uncore/tilelink2/WidthWidget.scala @@ -147,7 +147,7 @@ class TLWidthWidget(innerBeatBytes: Int)(implicit p: Parameters) extends LazyMod splice(edgeIn, in.a, edgeOut, out.a) splice(edgeOut, out.d, edgeIn, in.d) - if (edgeOut.manager.anySupportAcquire && edgeIn.client.anySupportProbe) { + if (edgeOut.manager.anySupportAcquireB && edgeIn.client.anySupportProbe) { splice(edgeOut, out.b, edgeIn, in.b) splice(edgeIn, in.c, edgeOut, out.c) in.e.ready := out.e.ready diff --git a/src/main/scala/uncore/tilelink2/Xbar.scala b/src/main/scala/uncore/tilelink2/Xbar.scala index 6e6b8fb8..cd18c9c6 100644 --- a/src/main/scala/uncore/tilelink2/Xbar.scala +++ b/src/main/scala/uncore/tilelink2/Xbar.scala @@ -164,7 +164,7 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.lowestIndexFirst)(implicit p: for (o <- 0 until out.size) { val allowI = Seq.tabulate(in.size) { i => node.edgesIn(i).client.anySupportProbe && - node.edgesOut(o).manager.anySupportAcquire + node.edgesOut(o).manager.anySupportAcquireB } TLArbiter(policy)(out(o).a, (beatsAI zip portsAOI(o) ):_*) TLArbiter(policy)(out(o).c, filter(beatsCI zip portsCOI(o), allowI):_*) @@ -174,7 +174,7 @@ class TLXbar(policy: TLArbiter.Policy = TLArbiter.lowestIndexFirst)(implicit p: for (i <- 0 until in.size) { val allowO = Seq.tabulate(out.size) { o => node.edgesIn(i).client.anySupportProbe && - node.edgesOut(o).manager.anySupportAcquire + node.edgesOut(o).manager.anySupportAcquireB } TLArbiter(policy)(in(i).b, filter(beatsBO zip portsBIO(i), allowO):_*) TLArbiter(policy)(in(i).d, (beatsDO zip portsDIO(i) ):_*)