rocketchip: use TL2 and AXI4 for memory subsytem
This commit is contained in:
parent
9d77e34bee
commit
32fd11935c
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
/////
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user