coreplex: support multiple memory channels via diplomatic trickery
This commit is contained in:
		| @@ -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 { | ||||
|   | ||||
| @@ -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( | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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(Seq(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 { | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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(Seq(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 { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user