From 32fd11935c9a0e01c89f08b095e99127b78a07f2 Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Thu, 3 Nov 2016 21:31:26 -0700 Subject: [PATCH] rocketchip: use TL2 and AXI4 for memory subsytem --- src/main/scala/coreplex/BaseCoreplex.scala | 13 ++-- src/main/scala/coreplex/Coreplex.scala | 2 + src/main/scala/groundtest/Coreplex.scala | 1 + src/main/scala/rocketchip/BaseTop.scala | 6 +- src/main/scala/rocketchip/ExampleTop.scala | 12 ++-- src/main/scala/rocketchip/Periphery.scala | 70 +++++++++++---------- src/main/scala/rocketchip/TestHarness.scala | 12 ++-- src/main/scala/rocketchip/Utils.scala | 7 +-- 8 files changed, 59 insertions(+), 64 deletions(-) diff --git a/src/main/scala/coreplex/BaseCoreplex.scala b/src/main/scala/coreplex/BaseCoreplex.scala index 15c2cc4b..387019d0 100644 --- a/src/main/scala/coreplex/BaseCoreplex.scala +++ b/src/main/scala/coreplex/BaseCoreplex.scala @@ -165,7 +165,6 @@ trait CoreplexRISCVPlatformBundle { val outer: CoreplexRISCVPlatform } => - val mem = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outerMemParams)) val slave = Vec(nSlaves, new ClientUncachedTileLinkIO()(innerParams)).flip val debug = new DebugBusIO().flip val rtcTick = Bool(INPUT) @@ -220,10 +219,7 @@ trait CoreplexRISCVPlatformModule { // Cached ports are first in client list, making sharerToClientId just an indentity function // addrToBank is sed to hash physical addresses (of cache blocks) to banks (and thereby memory channels) def sharerToClientId(sharerId: UInt) = sharerId - def addrToBank(addr: UInt): UInt = if (nBanks == 0) UInt(0) else { - val isMemory = globalAddrMap.isInRegion("mem", addr << log2Up(p(CacheBlockBytes))) - Mux(isMemory, addr.extract(lsb + log2Ceil(nBanks) - 1, lsb), UInt(nBanks)) - } + def addrToBank(addr: UInt): UInt = UInt(nBanks) val l1tol2net = Module(new PortedTileLinkCrossbar(addrToBank, sharerToClientId)) // Create point(s) of coherence serialization @@ -250,8 +246,6 @@ trait CoreplexRISCVPlatformModule { val enqueued = TileLinkEnqueuer(bank.outerTL, backendBuffering) icPort <> TileLinkIOUnwrapper(enqueued) } - - io.mem <> mem_ic.io.out } // connect coreplex-internal interrupts to tiles @@ -271,16 +265,19 @@ trait CoreplexRISCVPlatformModule { io.success := Bool(false) } -class BaseCoreplex(implicit p: Parameters) extends BareCoreplex +abstract class BaseCoreplex(implicit p: Parameters) extends BareCoreplex with CoreplexNetwork + with BankedL2CoherenceManagers with CoreplexRISCVPlatform { override lazy val module = new BaseCoreplexModule(this, () => new BaseCoreplexBundle(this)) } class BaseCoreplexBundle[+L <: BaseCoreplex](_outer: L) extends BareCoreplexBundle(_outer) with CoreplexNetworkBundle + with BankedL2CoherenceManagersBundle with CoreplexRISCVPlatformBundle class BaseCoreplexModule[+L <: BaseCoreplex, +B <: BaseCoreplexBundle[L]](_outer: L, _io: () => B) extends BareCoreplexModule(_outer, _io) with CoreplexNetworkModule + with BankedL2CoherenceManagersModule with CoreplexRISCVPlatformModule diff --git a/src/main/scala/coreplex/Coreplex.scala b/src/main/scala/coreplex/Coreplex.scala index c9fa0429..82a2b54c 100644 --- a/src/main/scala/coreplex/Coreplex.scala +++ b/src/main/scala/coreplex/Coreplex.scala @@ -43,6 +43,7 @@ trait DirectConnectionModule { } class DefaultCoreplex(implicit p: Parameters) extends BaseCoreplex + with BroadcastL2 with DirectConnection { override lazy val module = new DefaultCoreplexModule(this, () => new DefaultCoreplexBundle(this)) } @@ -112,6 +113,7 @@ trait AsyncConnectionModule { } class MultiClockCoreplex(implicit p: Parameters) extends BaseCoreplex + with BroadcastL2 with AsyncConnection { override lazy val module = new MultiClockCoreplexModule(this, () => new MultiClockCoreplexBundle(this)) } diff --git a/src/main/scala/groundtest/Coreplex.scala b/src/main/scala/groundtest/Coreplex.scala index 738b02f8..3687af5c 100644 --- a/src/main/scala/groundtest/Coreplex.scala +++ b/src/main/scala/groundtest/Coreplex.scala @@ -5,6 +5,7 @@ import cde.{Parameters} import coreplex._ class GroundTestCoreplex(implicit p: Parameters) extends BaseCoreplex + with BroadcastL2 with DirectConnection { override lazy val module = new GroundTestCoreplexModule(this, () => new GroundTestCoreplexBundle(this)) } diff --git a/src/main/scala/rocketchip/BaseTop.scala b/src/main/scala/rocketchip/BaseTop.scala index 99a5521e..1219d26a 100644 --- a/src/main/scala/rocketchip/BaseTop.scala +++ b/src/main/scala/rocketchip/BaseTop.scala @@ -55,6 +55,8 @@ trait TopNetwork extends HasPeripheryParameters { TLWidthWidget(p(SOCBusKey).beatBytes)( TLAtomicAutomata(arithmetic = p(PeripheryBusKey).arithAMO)( socBus.node)) + + var coreplexMem = Seq[TLOutwardNode]() } trait TopNetworkBundle extends HasPeripheryParameters { @@ -70,7 +72,6 @@ trait TopNetworkModule extends HasPeripheryParameters { } => implicit val p = outer.p - val coreplexMem : Vec[ClientUncachedTileLinkIO] = Wire(outer.coreplex.module.io.mem) val coreplexSlave: Vec[ClientUncachedTileLinkIO] = Wire(outer.coreplex.module.io.slave) val coreplexDebug: DebugBusIO = Wire(outer.coreplex.module.io.debug) val coreplexRtc : Bool = Wire(outer.coreplex.module.io.rtcTick) @@ -98,6 +99,8 @@ trait DirectConnection { socBus.node := coreplex.mmio coreplex.mmioInt := intBus.intnode + + coreplexMem = coreplex.mem } trait DirectConnectionModule { @@ -105,7 +108,6 @@ trait DirectConnectionModule { val outer: BaseTop[BaseCoreplex] } => - coreplexMem <> outer.coreplex.module.io.mem outer.coreplex.module.io.slave <> coreplexSlave outer.coreplex.module.io.debug <> coreplexDebug } diff --git a/src/main/scala/rocketchip/ExampleTop.scala b/src/main/scala/rocketchip/ExampleTop.scala index 5b17b242..45e67a03 100644 --- a/src/main/scala/rocketchip/ExampleTop.scala +++ b/src/main/scala/rocketchip/ExampleTop.scala @@ -10,13 +10,13 @@ import rocketchip._ /** Example Top with Periphery */ class ExampleTop[+C <: BaseCoreplex](_coreplex: Parameters => C)(implicit p: Parameters) extends BaseTop(_coreplex) + with DirectConnection with PeripheryBootROM with PeripheryDebug with PeripheryExtInterrupts - with PeripheryMasterMem + with PeripheryMasterAXI4Mem with PeripheryMasterAXI4MMIO - with PeripherySlave - with DirectConnection { + with PeripherySlave { override lazy val module = new ExampleTopModule(this, () => new ExampleTopBundle(this)) } @@ -24,19 +24,19 @@ class ExampleTopBundle[+L <: ExampleTop[BaseCoreplex]](_outer: L) extends BaseTo with PeripheryBootROMBundle with PeripheryDebugBundle with PeripheryExtInterruptsBundle - with PeripheryMasterMemBundle + with PeripheryMasterAXI4MemBundle with PeripheryMasterAXI4MMIOBundle with PeripherySlaveBundle class ExampleTopModule[+L <: ExampleTop[BaseCoreplex], +B <: ExampleTopBundle[L]](_outer: L, _io: () => B) extends BaseTopModule(_outer, _io) + with DirectConnectionModule with PeripheryBootROMModule with PeripheryDebugModule with PeripheryExtInterruptsModule - with PeripheryMasterMemModule + with PeripheryMasterAXI4MemModule with PeripheryMasterAXI4MMIOModule with PeripherySlaveModule with HardwiredResetVector - with DirectConnectionModule /** Example Top with TestRAM */ class ExampleTopWithTestRAM[+C <: BaseCoreplex](_coreplex: Parameters => C)(implicit p: Parameters) extends ExampleTop(_coreplex) diff --git a/src/main/scala/rocketchip/Periphery.scala b/src/main/scala/rocketchip/Periphery.scala index 0b6783d8..60021afa 100644 --- a/src/main/scala/rocketchip/Periphery.scala +++ b/src/main/scala/rocketchip/Periphery.scala @@ -3,7 +3,7 @@ package rocketchip import Chisel._ -import cde.{Parameters, Field} +import cde.{Parameters, Field, Dump} import junctions._ import junctions.NastiConstants._ import diplomacy._ @@ -153,47 +153,49 @@ trait PeripheryExtInterruptsModule { ///// -trait PeripheryMasterMem { - this: TopNetwork => +trait PeripheryMasterAXI4Mem { + this: BaseTop[BaseCoreplex] with TopNetwork => + + val base = 0x80000000L + val size = p(ExtMemSize) + val channels = coreplexMem.size + Dump("MEM_BASE", base) + + val mem_axi4 = coreplexMem.zipWithIndex.map { case (node, i) => + val c_size = size/channels + val c_base = base + c_size*i + + val axi4 = AXI4BlindOutputNode(AXI4SlavePortParameters( + slaves = Seq(AXI4SlaveParameters( + address = List(AddressSet(c_base, c_size-1)), + executable = true, + 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 = 8)) // 64-bit AXI interface + + axi4 := + // AXI4Fragmenter(lite=false, maxInFlight = 20)( // beef device up to support awlen = 0xff + TLToAXI4(idBits = 4)( // use idBits = 0 for AXI4-Lite + TLWidthWidget(coreplex.l1tol2_beatBytes)( // convert width before attaching to the l1tol2 + node)) + + axi4 + } } -trait PeripheryMasterMemBundle { +trait PeripheryMasterAXI4MemBundle { this: TopNetworkBundle { - val outer: PeripheryMasterMem + val outer: PeripheryMasterAXI4Mem } => - val mem_clk = p(AsyncMemChannels).option(Vec(nMemChannels, Clock(INPUT))) - val mem_rst = p(AsyncMemChannels).option(Vec(nMemChannels, Bool (INPUT))) - val mem_axi = Vec(nMemAXIChannels, new NastiIO) - val mem_ahb = Vec(nMemAHBChannels, new HastiMasterIO) - val mem_tl = Vec(nMemTLChannels, new ClientUncachedTileLinkIO()(edgeMemParams)) + val mem_axi4 = outer.mem_axi4.map(_.bundleOut).toList.headOption // !!! remove headOption when Seq supported } -trait PeripheryMasterMemModule { +trait PeripheryMasterAXI4MemModule { this: TopNetworkModule { - val outer: PeripheryMasterMem - val io: PeripheryMasterMemBundle + val outer: PeripheryMasterAXI4Mem + val io: PeripheryMasterAXI4MemBundle } => - - val edgeMem = coreplexMem.map(TileLinkWidthAdapter(_, edgeMemParams)) - - // Abuse the fact that zip takes the shorter of the two lists - ((io.mem_axi zip edgeMem) zipWithIndex) foreach { case ((axi, mem), idx) => - val axi_sync = PeripheryUtils.convertTLtoAXI(mem) - axi_sync.ar.bits.cache := CACHE_NORMAL_NOCACHE_BUF - axi_sync.aw.bits.cache := CACHE_NORMAL_NOCACHE_BUF - axi <> ( - if (!p(AsyncMemChannels)) axi_sync - else AsyncNastiTo(io.mem_clk.get(idx), io.mem_rst.get(idx), axi_sync) - ) - } - - (io.mem_ahb zip edgeMem) foreach { case (ahb, mem) => - ahb <> PeripheryUtils.convertTLtoAHB(mem, atomics = false) - } - - (io.mem_tl zip edgeMem) foreach { case (tl, mem) => - tl <> TileLinkEnqueuer(mem, 2) - } } ///// diff --git a/src/main/scala/rocketchip/TestHarness.scala b/src/main/scala/rocketchip/TestHarness.scala index 5d07d1cd..f760b260 100644 --- a/src/main/scala/rocketchip/TestHarness.scala +++ b/src/main/scala/rocketchip/TestHarness.scala @@ -19,21 +19,17 @@ class TestHarness(q: Parameters) extends Module { implicit val p = dut.p // This test harness isn't especially flexible yet - require(dut.io.mem_clk.isEmpty) - require(dut.io.mem_rst.isEmpty) - require(dut.io.mem_ahb.isEmpty) - require(dut.io.mem_tl.isEmpty) require(dut.io.bus_clk.isEmpty) require(dut.io.bus_rst.isEmpty) for (int <- dut.io.interrupts(0)) int := Bool(false) - if (dut.io.mem_axi.nonEmpty) { + if (dut.io.mem_axi4.nonEmpty) { val memSize = p(ExtMemSize) - require(memSize % dut.io.mem_axi.size == 0) - for (axi <- dut.io.mem_axi) { - val mem = Module(new SimAXIMem(memSize / dut.io.mem_axi.size)) + require(memSize % dut.io.mem_axi4.size == 0) + for (axi <- dut.io.mem_axi4.map(_(0))) { + val mem = Module(new SimAXIMem(memSize / dut.io.mem_axi4.size)) mem.io.axi.ar <> axi.ar mem.io.axi.aw <> axi.aw mem.io.axi.w <> axi.w diff --git a/src/main/scala/rocketchip/Utils.scala b/src/main/scala/rocketchip/Utils.scala index d4839120..cfff19dc 100644 --- a/src/main/scala/rocketchip/Utils.scala +++ b/src/main/scala/rocketchip/Utils.scala @@ -77,13 +77,8 @@ object GenerateGlobalAddrMap { case (e, i) => if (i == 0) e else e.copy(name = e.name + "_" + i) }).flatten.toList - val memBase = 0x80000000L - val memSize = p(ExtMemSize) - Dump("MEM_BASE", memBase) - val tl2 = AddrMapEntry("TL2", new AddrMap(uniquelyNamedTL2Devices, collapse = true)) - val mem = AddrMapEntry("mem", MemRange(memBase, memSize, MemAttr(AddrMapProt.RWX, true))) - AddrMap((tl2 +: (p(NMemoryChannels) > 0).option(mem).toSeq):_*) + AddrMap(tl2) } }