refactor top-level into coreplex and platform
This commit is contained in:
parent
993da60f2c
commit
3ea2f4a6c4
@ -34,15 +34,18 @@ class BaseConfig extends Config (
|
|||||||
entries += AddrMapEntry("bootrom", MemSize(4096, MemAttr(AddrMapProt.RX)))
|
entries += AddrMapEntry("bootrom", MemSize(4096, MemAttr(AddrMapProt.RX)))
|
||||||
entries += AddrMapEntry("plic", MemRange(0x40000000, 0x4000000, MemAttr(AddrMapProt.RW)))
|
entries += AddrMapEntry("plic", MemRange(0x40000000, 0x4000000, MemAttr(AddrMapProt.RW)))
|
||||||
entries += AddrMapEntry("prci", MemSize(0x4000000, MemAttr(AddrMapProt.RW)))
|
entries += AddrMapEntry("prci", MemSize(0x4000000, MemAttr(AddrMapProt.RW)))
|
||||||
entries ++= site(ExtraDevices).map(_.addrMapEntry)
|
|
||||||
new AddrMap(entries)
|
new AddrMap(entries)
|
||||||
}
|
}
|
||||||
lazy val globalAddrMap = {
|
lazy val globalAddrMap = {
|
||||||
val memBase = 0x80000000L
|
val memBase = 0x80000000L
|
||||||
val memSize = 0x10000000L
|
val memSize = 0x10000000L
|
||||||
val io = new AddrMap(AddrMapEntry("int", internalIOAddrMap) +: site(ExtMMIOPorts).entries)
|
|
||||||
|
val intern = AddrMapEntry("int", internalIOAddrMap)
|
||||||
|
val extern = AddrMapEntry("ext", MemRange(0x50000000L, 0x30000000L, MemAttr(AddrMapProt.RWX)))
|
||||||
|
val ioMap = if (site(ExportMMIOPort)) AddrMap(intern, extern) else AddrMap(intern)
|
||||||
|
|
||||||
val addrMap = AddrMap(
|
val addrMap = AddrMap(
|
||||||
AddrMapEntry("io", io),
|
AddrMapEntry("io", ioMap),
|
||||||
AddrMapEntry("mem", MemRange(memBase, memSize, MemAttr(AddrMapProt.RWX, true))))
|
AddrMapEntry("mem", MemRange(memBase, memSize, MemAttr(AddrMapProt.RWX, true))))
|
||||||
|
|
||||||
Dump("MEM_BASE", addrMap("mem").start)
|
Dump("MEM_BASE", addrMap("mem").start)
|
||||||
@ -51,6 +54,7 @@ class BaseConfig extends Config (
|
|||||||
}
|
}
|
||||||
def makeConfigString() = {
|
def makeConfigString() = {
|
||||||
val addrMap = globalAddrMap
|
val addrMap = globalAddrMap
|
||||||
|
val extAddrMap = site(ExtAddrMap)
|
||||||
val plicAddr = addrMap("io:int:plic").start
|
val plicAddr = addrMap("io:int:plic").start
|
||||||
val prciAddr = addrMap("io:int:prci").start
|
val prciAddr = addrMap("io:int:prci").start
|
||||||
val plicInfo = site(PLICKey)
|
val plicInfo = site(PLICKey)
|
||||||
@ -97,7 +101,7 @@ class BaseConfig extends Config (
|
|||||||
}
|
}
|
||||||
for (device <- site(ExtraDevices)) {
|
for (device <- site(ExtraDevices)) {
|
||||||
val deviceName = device.addrMapEntry.name
|
val deviceName = device.addrMapEntry.name
|
||||||
val deviceRegion = addrMap("io:int:" + deviceName)
|
val deviceRegion = extAddrMap(deviceName)
|
||||||
res.append(device.makeConfigString(deviceRegion))
|
res.append(device.makeConfigString(deviceRegion))
|
||||||
}
|
}
|
||||||
res append "};\n"
|
res append "};\n"
|
||||||
@ -188,6 +192,7 @@ class BaseConfig extends Config (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case BuildRoCC => Nil
|
case BuildRoCC => Nil
|
||||||
|
case BuildCoreplex => (p: Parameters) => Module(new DefaultCoreplex(p))
|
||||||
case RoccNMemChannels => site(BuildRoCC).map(_.nMemChannels).foldLeft(0)(_ + _)
|
case RoccNMemChannels => site(BuildRoCC).map(_.nMemChannels).foldLeft(0)(_ + _)
|
||||||
case RoccNPTWPorts => site(BuildRoCC).map(_.nPTWPorts).foldLeft(0)(_ + _)
|
case RoccNPTWPorts => site(BuildRoCC).map(_.nPTWPorts).foldLeft(0)(_ + _)
|
||||||
case RoccNCSRs => site(BuildRoCC).map(_.csrs.size).foldLeft(0)(_ + _)
|
case RoccNCSRs => site(BuildRoCC).map(_.csrs.size).foldLeft(0)(_ + _)
|
||||||
@ -231,17 +236,18 @@ class BaseConfig extends Config (
|
|||||||
case AsyncMMIOChannels => false
|
case AsyncMMIOChannels => false
|
||||||
case ExtraDevices => Nil
|
case ExtraDevices => Nil
|
||||||
case ExtraTopPorts => (p: Parameters) => new Bundle
|
case ExtraTopPorts => (p: Parameters) => new Bundle
|
||||||
case ExtMMIOPorts => AddrMap()
|
case ExtMMIOPorts => Nil
|
||||||
/*
|
case ExtAddrMap => new AddrMap(
|
||||||
AddrMap(
|
site(ExtraDevices).map(_.addrMapEntry) ++
|
||||||
AddrMapEntry("cfg", MemRange(0x50000000L, 0x04000000L, MemAttr(AddrMapProt.RW))),
|
site(ExtMMIOPorts),
|
||||||
AddrMapEntry("ext", MemRange(0x60000000L, 0x20000000L, MemAttr(AddrMapProt.RWX))))
|
start = BigInt("50000000", 16))
|
||||||
*/
|
|
||||||
case NExtMMIOAXIChannels => 0
|
case NExtMMIOAXIChannels => 0
|
||||||
case NExtMMIOAHBChannels => 0
|
case NExtMMIOAHBChannels => 0
|
||||||
case NExtMMIOTLChannels => 0
|
case NExtMMIOTLChannels => 0
|
||||||
|
case ExportMMIOPort => (site(ExtraDevices).size + site(ExtMMIOPorts).size) > 0
|
||||||
case AsyncBusChannels => false
|
case AsyncBusChannels => false
|
||||||
case NExtBusAXIChannels => 0
|
case NExtBusAXIChannels => 0
|
||||||
|
case ExportBusPort => site(NExtBusAXIChannels) > 0
|
||||||
case PLICKey => PLICConfig(site(NTiles), site(UseVM), site(NExtInterrupts), 0)
|
case PLICKey => PLICConfig(site(NTiles), site(UseVM), site(NExtInterrupts), 0)
|
||||||
case DMKey => new DefaultDebugModuleConfig(site(NTiles), site(XLen))
|
case DMKey => new DefaultDebugModuleConfig(site(NTiles), site(XLen))
|
||||||
case FDivSqrt => true
|
case FDivSqrt => true
|
||||||
|
255
src/main/scala/Coreplex.scala
Normal file
255
src/main/scala/Coreplex.scala
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
package rocketchip
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import cde.{Parameters, Field}
|
||||||
|
import junctions._
|
||||||
|
import uncore.tilelink._
|
||||||
|
import uncore.coherence._
|
||||||
|
import uncore.agents._
|
||||||
|
import uncore.devices._
|
||||||
|
import uncore.util._
|
||||||
|
import uncore.converters._
|
||||||
|
import rocket._
|
||||||
|
import rocket.Util._
|
||||||
|
import java.nio.{ByteBuffer,ByteOrder}
|
||||||
|
import java.nio.file.{Files, Paths}
|
||||||
|
|
||||||
|
/** Number of memory channels */
|
||||||
|
case object NMemoryChannels extends Field[Int]
|
||||||
|
/** Number of banks per memory channel */
|
||||||
|
case object NBanksPerMemoryChannel extends Field[Int]
|
||||||
|
/** Least significant bit of address used for bank partitioning */
|
||||||
|
case object BankIdLSB extends Field[Int]
|
||||||
|
/** Function for building some kind of coherence manager agent */
|
||||||
|
case object BuildL2CoherenceManager extends Field[(Int, Parameters) => CoherenceAgent]
|
||||||
|
/** Function for building some kind of tile connected to a reset signal */
|
||||||
|
case object BuildTiles extends Field[Seq[(Bool, Parameters) => Tile]]
|
||||||
|
/** A string describing on-chip devices, readable by target software */
|
||||||
|
case object ConfigString extends Field[Array[Byte]]
|
||||||
|
/** Number of external interrupt sources */
|
||||||
|
case object NExtInterrupts extends Field[Int]
|
||||||
|
/** Interrupt controller configuration */
|
||||||
|
case object PLICKey extends Field[PLICConfig]
|
||||||
|
/** Number of clock cycles per RTC tick */
|
||||||
|
case object RTCPeriod extends Field[Int]
|
||||||
|
/** The file to read the BootROM contents from */
|
||||||
|
case object BootROMFile extends Field[String]
|
||||||
|
/** Export an external MMIO slave port */
|
||||||
|
case object ExportMMIOPort extends Field[Boolean]
|
||||||
|
/** Expose an additional bus master port */
|
||||||
|
case object ExportBusPort extends Field[Boolean]
|
||||||
|
/** Function for building Coreplex */
|
||||||
|
case object BuildCoreplex extends Field[Parameters => Coreplex]
|
||||||
|
|
||||||
|
/** Wrapper around everything that isn't a Tile.
|
||||||
|
*
|
||||||
|
* Usually this is clocked and/or place-and-routed separately from the Tiles.
|
||||||
|
*/
|
||||||
|
class Uncore(implicit val p: Parameters) extends Module
|
||||||
|
with HasTopLevelParameters {
|
||||||
|
|
||||||
|
val io = new Bundle {
|
||||||
|
val mem = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outermostParams))
|
||||||
|
val tiles_cached = Vec(nCachedTilePorts, new ClientTileLinkIO).flip
|
||||||
|
val tiles_uncached = Vec(nUncachedTilePorts, new ClientUncachedTileLinkIO).flip
|
||||||
|
val prci = Vec(nTiles, new PRCITileIO).asOutput
|
||||||
|
val bus = if (exportBus) Some(new ClientUncachedTileLinkIO().flip) else None
|
||||||
|
val mmio = if (exportMMIO) Some(new ClientUncachedTileLinkIO()(outermostMMIOParams)) else None
|
||||||
|
val interrupts = Vec(p(NExtInterrupts), Bool()).asInput
|
||||||
|
val debug = new DebugBusIO()(p).flip
|
||||||
|
}
|
||||||
|
|
||||||
|
val outmemsys = if (nCachedTilePorts + nUncachedTilePorts > 0)
|
||||||
|
Module(new OuterMemorySystem) // NoC, LLC and SerDes
|
||||||
|
else Module(new DummyOuterMemorySystem)
|
||||||
|
outmemsys.io.incoherent foreach (_ := false)
|
||||||
|
outmemsys.io.tiles_uncached <> io.tiles_uncached
|
||||||
|
outmemsys.io.tiles_cached <> io.tiles_cached
|
||||||
|
if (exportBus) { outmemsys.io.bus.get <> io.bus.get }
|
||||||
|
io.mem <> outmemsys.io.mem
|
||||||
|
|
||||||
|
buildMMIONetwork(p.alterPartial({case TLId => "L2toMMIO"}))
|
||||||
|
|
||||||
|
def makeBootROM()(implicit p: Parameters) = {
|
||||||
|
val romdata = Files.readAllBytes(Paths.get(p(BootROMFile)))
|
||||||
|
val rom = ByteBuffer.wrap(romdata)
|
||||||
|
|
||||||
|
rom.order(ByteOrder.LITTLE_ENDIAN)
|
||||||
|
|
||||||
|
// for now, have the reset vector jump straight to memory
|
||||||
|
val resetToMemDist = p(GlobalAddrMap)("mem").start - p(ResetVector)
|
||||||
|
require(resetToMemDist == (resetToMemDist.toInt >> 12 << 12))
|
||||||
|
val configStringAddr = p(ResetVector).toInt + rom.capacity
|
||||||
|
|
||||||
|
require(rom.getInt(12) == 0,
|
||||||
|
"Config string address position should not be occupied by code")
|
||||||
|
rom.putInt(12, configStringAddr)
|
||||||
|
rom.array() ++ p(ConfigString).toSeq
|
||||||
|
}
|
||||||
|
|
||||||
|
def buildMMIONetwork(implicit p: Parameters) = {
|
||||||
|
val ioAddrMap = p(GlobalAddrMap).subMap("io")
|
||||||
|
|
||||||
|
val mmioNetwork = Module(new TileLinkRecursiveInterconnect(1, ioAddrMap))
|
||||||
|
mmioNetwork.io.in.head <> outmemsys.io.mmio
|
||||||
|
|
||||||
|
val plic = Module(new PLIC(p(PLICKey)))
|
||||||
|
plic.io.tl <> mmioNetwork.port("int:plic")
|
||||||
|
for (i <- 0 until io.interrupts.size) {
|
||||||
|
val gateway = Module(new LevelGateway)
|
||||||
|
gateway.io.interrupt := io.interrupts(i)
|
||||||
|
plic.io.devices(i) <> gateway.io.plic
|
||||||
|
}
|
||||||
|
|
||||||
|
val debugModule = Module(new DebugModule)
|
||||||
|
debugModule.io.tl <> mmioNetwork.port("int:debug")
|
||||||
|
debugModule.io.db <> io.debug
|
||||||
|
|
||||||
|
val prci = Module(new PRCI)
|
||||||
|
prci.io.tl <> mmioNetwork.port("int:prci")
|
||||||
|
io.prci := prci.io.tiles
|
||||||
|
prci.io.rtcTick := Counter(p(RTCPeriod)).inc() // placeholder for real RTC
|
||||||
|
|
||||||
|
for (i <- 0 until nTiles) {
|
||||||
|
prci.io.interrupts(i).meip := plic.io.harts(plic.cfg.context(i, 'M'))
|
||||||
|
if (p(UseVM))
|
||||||
|
prci.io.interrupts(i).seip := plic.io.harts(plic.cfg.context(i, 'S'))
|
||||||
|
prci.io.interrupts(i).debug := debugModule.io.debugInterrupts(i)
|
||||||
|
|
||||||
|
io.prci(i).reset := reset
|
||||||
|
}
|
||||||
|
|
||||||
|
val bootROM = Module(new ROMSlave(makeBootROM()))
|
||||||
|
bootROM.io <> mmioNetwork.port("int:bootrom")
|
||||||
|
|
||||||
|
io.mmio.map { ext => ext <> mmioNetwork.port("ext") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractOuterMemorySystem(implicit val p: Parameters)
|
||||||
|
extends Module with HasTopLevelParameters {
|
||||||
|
val io = new Bundle {
|
||||||
|
val tiles_cached = Vec(nCachedTilePorts, new ClientTileLinkIO).flip
|
||||||
|
val tiles_uncached = Vec(nUncachedTilePorts, new ClientUncachedTileLinkIO).flip
|
||||||
|
val bus = if (exportBus) Some(new ClientUncachedTileLinkIO().flip) else None
|
||||||
|
val incoherent = Vec(nCachedTilePorts, Bool()).asInput
|
||||||
|
val mem = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outermostParams))
|
||||||
|
val mmio = new ClientUncachedTileLinkIO()(p.alterPartial({case TLId => "L2toMMIO"}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Use in place of OuterMemorySystem if there are no clients to connect. */
|
||||||
|
class DummyOuterMemorySystem(implicit p: Parameters) extends AbstractOuterMemorySystem()(p) {
|
||||||
|
require(nCachedTilePorts + nUncachedTilePorts == 0)
|
||||||
|
require(io.bus.isEmpty)
|
||||||
|
|
||||||
|
io.mem.foreach { tl =>
|
||||||
|
tl.acquire.valid := Bool(false)
|
||||||
|
tl.grant.ready := Bool(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
io.mmio.acquire.valid := Bool(false)
|
||||||
|
io.mmio.grant.ready := Bool(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The whole outer memory hierarchy, including a NoC, some kind of coherence
|
||||||
|
* manager agent, and a converter from TileLink to MemIO.
|
||||||
|
*/
|
||||||
|
class OuterMemorySystem(implicit p: Parameters) extends AbstractOuterMemorySystem()(p) {
|
||||||
|
// Create a simple L1toL2 NoC between the tiles and the banks of outer memory
|
||||||
|
// 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 = {
|
||||||
|
val isMemory = p(GlobalAddrMap).isInRegion("mem", addr << log2Up(p(CacheBlockBytes)))
|
||||||
|
Mux(isMemory,
|
||||||
|
if (nBanks > 1) addr(lsb + log2Up(nBanks) - 1, lsb) else UInt(0),
|
||||||
|
UInt(nBanks))
|
||||||
|
}
|
||||||
|
val preBuffering = TileLinkDepths(1,1,2,2,0)
|
||||||
|
val l1tol2net = Module(new PortedTileLinkCrossbar(addrToBank, sharerToClientId, preBuffering))
|
||||||
|
|
||||||
|
// Create point(s) of coherence serialization
|
||||||
|
val managerEndpoints = List.tabulate(nBanks){id => p(BuildL2CoherenceManager)(id, p)}
|
||||||
|
managerEndpoints.foreach { _.incoherent := io.incoherent }
|
||||||
|
|
||||||
|
val mmioManager = Module(new MMIOTileLinkManager()(p.alterPartial({
|
||||||
|
case TLId => "L1toL2"
|
||||||
|
case InnerTLId => "L1toL2"
|
||||||
|
case OuterTLId => "L2toMMIO"
|
||||||
|
})))
|
||||||
|
io.mmio <> mmioManager.io.outer
|
||||||
|
|
||||||
|
// Wire the tiles to the TileLink client ports of the L1toL2 network,
|
||||||
|
// and coherence manager(s) to the other side
|
||||||
|
l1tol2net.io.clients_cached <> io.tiles_cached
|
||||||
|
l1tol2net.io.clients_uncached <> io.tiles_uncached ++ io.bus
|
||||||
|
l1tol2net.io.managers <> managerEndpoints.map(_.innerTL) :+ mmioManager.io.inner
|
||||||
|
|
||||||
|
// Create a converter between TileLinkIO and MemIO for each channel
|
||||||
|
val outerTLParams = p.alterPartial({ case TLId => "L2toMC" })
|
||||||
|
val backendBuffering = TileLinkDepths(0,0,0,0,0)
|
||||||
|
|
||||||
|
// TODO: the code to print this stuff should live somewhere else
|
||||||
|
println("Generated Address Map")
|
||||||
|
for ((name, region) <- p(GlobalAddrMap).flatten) {
|
||||||
|
println(f"\t$name%s ${region.start}%x - ${region.start + region.size - 1}%x")
|
||||||
|
}
|
||||||
|
println("Generated Configuration String")
|
||||||
|
println(new String(p(ConfigString)))
|
||||||
|
|
||||||
|
val mem_ic = Module(new TileLinkMemoryInterconnect(nBanksPerMemChannel, nMemChannels)(outermostParams))
|
||||||
|
|
||||||
|
for ((bank, icPort) <- managerEndpoints zip mem_ic.io.in) {
|
||||||
|
val unwrap = Module(new ClientTileLinkIOUnwrapper()(outerTLParams))
|
||||||
|
unwrap.io.in <> ClientTileLinkEnqueuer(bank.outerTL, backendBuffering)(outerTLParams)
|
||||||
|
TileLinkWidthAdapter(icPort, unwrap.io.out)
|
||||||
|
}
|
||||||
|
|
||||||
|
io.mem <> mem_ic.io.out
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class Coreplex(implicit val p: Parameters) extends Module
|
||||||
|
with HasTopLevelParameters {
|
||||||
|
val io = new Bundle {
|
||||||
|
val mem = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outermostParams))
|
||||||
|
val bus = if (p(ExportBusPort)) Some(new ClientUncachedTileLinkIO().flip) else None
|
||||||
|
val mmio = if(p(ExportMMIOPort)) Some(new ClientUncachedTileLinkIO()(outermostMMIOParams)) else None
|
||||||
|
val interrupts = Vec(p(NExtInterrupts), Bool()).asInput
|
||||||
|
val debug = new DebugBusIO()(p).flip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultCoreplex(topParams: Parameters) extends Coreplex()(topParams) {
|
||||||
|
// Build an Uncore and a set of Tiles
|
||||||
|
val tileResets = Wire(Vec(nTiles, Bool()))
|
||||||
|
val tileList = p(BuildTiles).zip(tileResets).map {
|
||||||
|
case (tile, rst) => tile(rst, p)
|
||||||
|
}
|
||||||
|
val nCachedPorts = tileList.map(tile => tile.io.cached.size).reduce(_ + _)
|
||||||
|
val nUncachedPorts = tileList.map(tile => tile.io.uncached.size).reduce(_ + _)
|
||||||
|
|
||||||
|
val innerTLParams = p.alterPartial({
|
||||||
|
case HastiId => "TL"
|
||||||
|
case TLId => "L1toL2"
|
||||||
|
case NCachedTileLinkPorts => nCachedPorts
|
||||||
|
case NUncachedTileLinkPorts => nUncachedPorts
|
||||||
|
})
|
||||||
|
|
||||||
|
val uncore = Module(new Uncore()(innerTLParams))
|
||||||
|
|
||||||
|
(uncore.io.prci, tileResets, tileList).zipped.foreach {
|
||||||
|
case (prci, rst, tile) =>
|
||||||
|
rst := prci.reset
|
||||||
|
tile.io.prci <> prci
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect the uncore to the tile memory ports, HostIO and MemIO
|
||||||
|
uncore.io.tiles_cached <> tileList.map(_.io.cached).flatten
|
||||||
|
uncore.io.tiles_uncached <> tileList.map(_.io.uncached).flatten
|
||||||
|
uncore.io.interrupts <> io.interrupts
|
||||||
|
uncore.io.debug <> io.debug
|
||||||
|
if (exportBus) { uncore.io.bus.get <> io.bus.get }
|
||||||
|
if (exportMMIO) { io.mmio.get <> uncore.io.mmio.get }
|
||||||
|
io.mem <> uncore.io.mem
|
||||||
|
}
|
@ -6,15 +6,10 @@ import Chisel._
|
|||||||
import cde.{Parameters, Field}
|
import cde.{Parameters, Field}
|
||||||
import junctions._
|
import junctions._
|
||||||
import uncore.tilelink._
|
import uncore.tilelink._
|
||||||
import uncore.coherence._
|
|
||||||
import uncore.agents._
|
|
||||||
import uncore.devices._
|
import uncore.devices._
|
||||||
import uncore.util._
|
import uncore.util._
|
||||||
import uncore.converters._
|
import uncore.converters._
|
||||||
import rocket._
|
import rocket._
|
||||||
import rocket.Util._
|
|
||||||
import java.nio.{ByteBuffer,ByteOrder}
|
|
||||||
import java.nio.file.{Files, Paths}
|
|
||||||
|
|
||||||
/** Top-level parameters of RocketChip, values set in e.g. PublicConfigs.scala */
|
/** Top-level parameters of RocketChip, values set in e.g. PublicConfigs.scala */
|
||||||
|
|
||||||
@ -27,38 +22,25 @@ object BusType {
|
|||||||
val busTypes = Seq(AXI, AHB, TL)
|
val busTypes = Seq(AXI, AHB, TL)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Number of memory channels */
|
/** Memory channel controls */
|
||||||
case object AsyncMemChannels extends Field[Boolean]
|
|
||||||
case object NMemoryChannels extends Field[Int]
|
|
||||||
case object TMemoryChannels extends Field[BusType.EnumVal]
|
case object TMemoryChannels extends Field[BusType.EnumVal]
|
||||||
/** Number of banks per memory channel */
|
|
||||||
case object NBanksPerMemoryChannel extends Field[Int]
|
|
||||||
/** Least significant bit of address used for bank partitioning */
|
|
||||||
case object BankIdLSB extends Field[Int]
|
|
||||||
/** Number of outstanding memory requests */
|
/** Number of outstanding memory requests */
|
||||||
case object NOutstandingMemReqsPerChannel extends Field[Int]
|
case object NOutstandingMemReqsPerChannel extends Field[Int]
|
||||||
/** Number of exteral MMIO ports */
|
/** External MMIO controls */
|
||||||
case object AsyncMMIOChannels extends Field[Boolean]
|
|
||||||
case object ExtMMIOPorts extends Field[AddrMap]
|
|
||||||
case object NExtMMIOAXIChannels extends Field[Int]
|
case object NExtMMIOAXIChannels extends Field[Int]
|
||||||
case object NExtMMIOAHBChannels extends Field[Int]
|
case object NExtMMIOAHBChannels extends Field[Int]
|
||||||
case object NExtMMIOTLChannels extends Field[Int]
|
case object NExtMMIOTLChannels extends Field[Int]
|
||||||
case object AsyncBusChannels extends Field[Boolean]
|
/** External Bus controls */
|
||||||
case object NExtBusAXIChannels extends Field[Int]
|
case object NExtBusAXIChannels extends Field[Int]
|
||||||
/** Function for building some kind of coherence manager agent */
|
/** Async configurations */
|
||||||
case object BuildL2CoherenceManager extends Field[(Int, Parameters) => CoherenceAgent]
|
case object AsyncBusChannels extends Field[Boolean]
|
||||||
/** Function for building some kind of tile connected to a reset signal */
|
|
||||||
case object BuildTiles extends Field[Seq[(Bool, Parameters) => Tile]]
|
|
||||||
/** A string describing on-chip devices, readable by target software */
|
|
||||||
case object ConfigString extends Field[Array[Byte]]
|
|
||||||
/** Number of external interrupt sources */
|
|
||||||
case object NExtInterrupts extends Field[Int]
|
|
||||||
/** Interrupt controller configuration */
|
|
||||||
case object PLICKey extends Field[PLICConfig]
|
|
||||||
/** Number of clock cycles per RTC tick */
|
|
||||||
case object RTCPeriod extends Field[Int]
|
|
||||||
case object AsyncDebugBus extends Field[Boolean]
|
case object AsyncDebugBus extends Field[Boolean]
|
||||||
case object BootROMFile extends Field[String]
|
case object AsyncMemChannels extends Field[Boolean]
|
||||||
|
case object AsyncMMIOChannels extends Field[Boolean]
|
||||||
|
|
||||||
|
/** External address map settings */
|
||||||
|
case object ExtMMIOPorts extends Field[Seq[AddrMapEntry]]
|
||||||
|
case object ExtAddrMap extends Field[AddrMap]
|
||||||
|
|
||||||
/** Utility trait for quick access to some relevant parameters */
|
/** Utility trait for quick access to some relevant parameters */
|
||||||
trait HasTopLevelParameters {
|
trait HasTopLevelParameters {
|
||||||
@ -81,6 +63,8 @@ trait HasTopLevelParameters {
|
|||||||
lazy val xLen = p(XLen)
|
lazy val xLen = p(XLen)
|
||||||
lazy val outermostParams = p.alterPartial({ case TLId => "Outermost" })
|
lazy val outermostParams = p.alterPartial({ case TLId => "Outermost" })
|
||||||
lazy val outermostMMIOParams = p.alterPartial({ case TLId => "MMIO_Outermost" })
|
lazy val outermostMMIOParams = p.alterPartial({ case TLId => "MMIO_Outermost" })
|
||||||
|
lazy val exportBus = p(ExportBusPort)
|
||||||
|
lazy val exportMMIO = p(ExportMMIOPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MemBackupCtrlIO extends Bundle {
|
class MemBackupCtrlIO extends Bundle {
|
||||||
@ -148,34 +132,14 @@ class Top(topParams: Parameters) extends Module with HasTopLevelParameters {
|
|||||||
implicit val p = topParams
|
implicit val p = topParams
|
||||||
val io = new TopIO
|
val io = new TopIO
|
||||||
|
|
||||||
// Build an Uncore and a set of Tiles
|
val coreplex = p(BuildCoreplex)(p)
|
||||||
val tileResets = Wire(Vec(nTiles, Bool()))
|
val periphery = Module(new Periphery)
|
||||||
val tileList = p(BuildTiles).zip(tileResets).map {
|
|
||||||
case (tile, rst) => tile(rst, p)
|
|
||||||
}
|
|
||||||
val nCachedPorts = tileList.map(tile => tile.io.cached.size).reduce(_ + _)
|
|
||||||
val nUncachedPorts = tileList.map(tile => tile.io.uncached.size).reduce(_ + _)
|
|
||||||
|
|
||||||
val innerTLParams = p.alterPartial({
|
if (exportMMIO) { periphery.io.mmio_in.get <> coreplex.io.mmio.get }
|
||||||
case HastiId => "TL"
|
periphery.io.mem_in <> coreplex.io.mem
|
||||||
case TLId => "L1toL2"
|
if (exportBus) { coreplex.io.bus.get <> periphery.io.bus_out.get }
|
||||||
case NCachedTileLinkPorts => nCachedPorts
|
|
||||||
case NUncachedTileLinkPorts => nUncachedPorts
|
|
||||||
})
|
|
||||||
|
|
||||||
val uncore = Module(new Uncore()(innerTLParams))
|
coreplex.io.debug <>
|
||||||
|
|
||||||
(uncore.io.prci, tileResets, tileList).zipped.foreach {
|
|
||||||
case (prci, rst, tile) =>
|
|
||||||
rst := prci.reset
|
|
||||||
tile.io.prci <> prci
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect the uncore to the tile memory ports, HostIO and MemIO
|
|
||||||
uncore.io.tiles_cached <> tileList.map(_.io.cached).flatten
|
|
||||||
uncore.io.tiles_uncached <> tileList.map(_.io.uncached).flatten
|
|
||||||
uncore.io.interrupts <> io.interrupts
|
|
||||||
uncore.io.debugBus <>
|
|
||||||
(if (p(AsyncDebugBus))
|
(if (p(AsyncDebugBus))
|
||||||
AsyncDebugBusFrom(io.debug_clk.get, io.debug_rst.get, io.debug)
|
AsyncDebugBusFrom(io.debug_clk.get, io.debug_rst.get, io.debug)
|
||||||
else io.debug)
|
else io.debug)
|
||||||
@ -192,62 +156,49 @@ class Top(topParams: Parameters) extends Module with HasTopLevelParameters {
|
|||||||
|
|
||||||
io.mmio_axi <>
|
io.mmio_axi <>
|
||||||
(if (p(AsyncMMIOChannels))
|
(if (p(AsyncMMIOChannels))
|
||||||
asyncAxiTo(io.mmio_clk.get, io.mmio_rst.get, uncore.io.mmio_axi)
|
asyncAxiTo(io.mmio_clk.get, io.mmio_rst.get, periphery.io.mmio_axi)
|
||||||
else uncore.io.mmio_axi)
|
else periphery.io.mmio_axi)
|
||||||
io.mmio_ahb <> uncore.io.mmio_ahb
|
io.mmio_ahb <> periphery.io.mmio_ahb
|
||||||
io.mmio_tl <> uncore.io.mmio_tl
|
io.mmio_tl <> periphery.io.mmio_tl
|
||||||
|
|
||||||
io.mem_axi <>
|
io.mem_axi <>
|
||||||
(if (p(AsyncMemChannels))
|
(if (p(AsyncMemChannels))
|
||||||
asyncAxiTo(io.mem_clk.get, io.mem_rst.get, uncore.io.mem_axi)
|
asyncAxiTo(io.mem_clk.get, io.mem_rst.get, periphery.io.mem_axi)
|
||||||
else uncore.io.mem_axi)
|
else periphery.io.mem_axi)
|
||||||
io.mem_ahb <> uncore.io.mem_ahb
|
io.mem_ahb <> periphery.io.mem_ahb
|
||||||
io.mem_tl <> uncore.io.mem_tl
|
io.mem_tl <> periphery.io.mem_tl
|
||||||
|
|
||||||
uncore.io.bus_axi <>
|
periphery.io.bus_axi <>
|
||||||
(if (p(AsyncBusChannels))
|
(if (p(AsyncBusChannels))
|
||||||
asyncAxiFrom(io.bus_clk.get, io.bus_rst.get, io.bus_axi)
|
asyncAxiFrom(io.bus_clk.get, io.bus_rst.get, io.bus_axi)
|
||||||
else io.bus_axi)
|
else io.bus_axi)
|
||||||
|
|
||||||
io.extra <> uncore.io.extra
|
io.extra <> periphery.io.extra
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Wrapper around everything that isn't a Tile.
|
class Periphery(implicit val p: Parameters) extends Module
|
||||||
*
|
|
||||||
* Usually this is clocked and/or place-and-routed separately from the Tiles.
|
|
||||||
*/
|
|
||||||
class Uncore(implicit val p: Parameters) extends Module
|
|
||||||
with HasTopLevelParameters {
|
with HasTopLevelParameters {
|
||||||
|
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
|
val mem_in = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outermostParams)).flip
|
||||||
|
val bus_out = if (exportBus) Some(new ClientUncachedTileLinkIO) else None
|
||||||
|
val mmio_in = if (exportMMIO) Some(new ClientUncachedTileLinkIO()(outermostMMIOParams).flip) else None
|
||||||
val mem_axi = Vec(nMemAXIChannels, new NastiIO)
|
val mem_axi = Vec(nMemAXIChannels, new NastiIO)
|
||||||
val mem_ahb = Vec(nMemAHBChannels, new HastiMasterIO)
|
val mem_ahb = Vec(nMemAHBChannels, new HastiMasterIO)
|
||||||
val mem_tl = Vec(nMemTLChannels, new ClientUncachedTileLinkIO()(outermostParams))
|
val mem_tl = Vec(nMemTLChannels, new ClientUncachedTileLinkIO()(outermostParams))
|
||||||
val tiles_cached = Vec(nCachedTilePorts, new ClientTileLinkIO).flip
|
|
||||||
val tiles_uncached = Vec(nUncachedTilePorts, new ClientUncachedTileLinkIO).flip
|
|
||||||
val prci = Vec(nTiles, new PRCITileIO).asOutput
|
|
||||||
val bus_axi = Vec(p(NExtBusAXIChannels), new NastiIO).flip
|
val bus_axi = Vec(p(NExtBusAXIChannels), new NastiIO).flip
|
||||||
val mmio_axi = Vec(p(NExtMMIOAXIChannels), new NastiIO)
|
val mmio_axi = Vec(p(NExtMMIOAXIChannels), new NastiIO)
|
||||||
val mmio_ahb = Vec(p(NExtMMIOAHBChannels), new HastiMasterIO)
|
val mmio_ahb = Vec(p(NExtMMIOAHBChannels), new HastiMasterIO)
|
||||||
val mmio_tl = Vec(p(NExtMMIOTLChannels), new ClientUncachedTileLinkIO()(outermostMMIOParams))
|
val mmio_tl = Vec(p(NExtMMIOTLChannels), new ClientUncachedTileLinkIO()(outermostMMIOParams))
|
||||||
val interrupts = Vec(p(NExtInterrupts), Bool()).asInput
|
|
||||||
val debugBus = new DebugBusIO()(p).flip
|
|
||||||
val extra = p(ExtraTopPorts)(p)
|
val extra = p(ExtraTopPorts)(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
val outmemsys = if (nCachedTilePorts + nUncachedTilePorts > 0)
|
io.bus_out.map { tl_out =>
|
||||||
Module(new OuterMemorySystem) // NoC, LLC and SerDes
|
val conv = Module(new TileLinkIONastiIOConverter)
|
||||||
else Module(new DummyOuterMemorySystem)
|
val arb = Module(new NastiArbiter(p(NExtBusAXIChannels)))
|
||||||
outmemsys.io.incoherent foreach (_ := false)
|
arb.io.master <> io.bus_axi
|
||||||
outmemsys.io.tiles_uncached <> io.tiles_uncached
|
conv.io.nasti <> conv.io.tl
|
||||||
outmemsys.io.tiles_cached <> io.tiles_cached
|
tl_out <> conv.io.tl
|
||||||
|
}
|
||||||
buildMMIONetwork(p.alterPartial({case TLId => "L2toMMIO"}))
|
|
||||||
|
|
||||||
io.mem_axi <> outmemsys.io.mem_axi
|
|
||||||
io.mem_ahb <> outmemsys.io.mem_ahb
|
|
||||||
io.mem_tl <> outmemsys.io.mem_tl
|
|
||||||
outmemsys.io.bus_axi <> io.bus_axi
|
|
||||||
|
|
||||||
def connectExternalMMIO(ports: Seq[ClientUncachedTileLinkIO])(implicit p: Parameters) {
|
def connectExternalMMIO(ports: Seq[ClientUncachedTileLinkIO])(implicit p: Parameters) {
|
||||||
val mmio_axi_start = 0
|
val mmio_axi_start = 0
|
||||||
@ -273,175 +224,27 @@ class Uncore(implicit val p: Parameters) extends Module
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def makeBootROM()(implicit p: Parameters) = {
|
|
||||||
val romdata = Files.readAllBytes(Paths.get(p(BootROMFile)))
|
|
||||||
val rom = ByteBuffer.wrap(romdata)
|
|
||||||
|
|
||||||
rom.order(ByteOrder.LITTLE_ENDIAN)
|
|
||||||
|
|
||||||
// for now, have the reset vector jump straight to memory
|
|
||||||
val resetToMemDist = p(GlobalAddrMap)("mem").start - p(ResetVector)
|
|
||||||
require(resetToMemDist == (resetToMemDist.toInt >> 12 << 12))
|
|
||||||
val configStringAddr = p(ResetVector).toInt + rom.capacity
|
|
||||||
|
|
||||||
require(rom.getInt(12) == 0,
|
|
||||||
"Config string address position should not be occupied by code")
|
|
||||||
rom.putInt(12, configStringAddr)
|
|
||||||
rom.array() ++ p(ConfigString).toSeq
|
|
||||||
}
|
|
||||||
|
|
||||||
def buildMMIONetwork(implicit p: Parameters) = {
|
def buildMMIONetwork(implicit p: Parameters) = {
|
||||||
val ioAddrMap = p(GlobalAddrMap).subMap("io")
|
val extAddrMap = p(ExtAddrMap)
|
||||||
|
|
||||||
val mmioNetwork = Module(new TileLinkRecursiveInterconnect(1, ioAddrMap))
|
val mmioNetwork = Module(new TileLinkRecursiveInterconnect(1, extAddrMap))
|
||||||
mmioNetwork.io.in.head <> outmemsys.io.mmio
|
mmioNetwork.io.in.head <> io.mmio_in.get
|
||||||
|
|
||||||
val plic = Module(new PLIC(p(PLICKey)))
|
|
||||||
plic.io.tl <> mmioNetwork.port("int:plic")
|
|
||||||
for (i <- 0 until io.interrupts.size) {
|
|
||||||
val gateway = Module(new LevelGateway)
|
|
||||||
gateway.io.interrupt := io.interrupts(i)
|
|
||||||
plic.io.devices(i) <> gateway.io.plic
|
|
||||||
}
|
|
||||||
|
|
||||||
val debugModule = Module(new DebugModule)
|
|
||||||
debugModule.io.tl <> mmioNetwork.port("int:debug")
|
|
||||||
debugModule.io.db <> io.debugBus
|
|
||||||
|
|
||||||
val prci = Module(new PRCI)
|
|
||||||
prci.io.tl <> mmioNetwork.port("int:prci")
|
|
||||||
io.prci := prci.io.tiles
|
|
||||||
prci.io.rtcTick := Counter(p(RTCPeriod)).inc() // placeholder for real RTC
|
|
||||||
|
|
||||||
for (i <- 0 until nTiles) {
|
|
||||||
prci.io.interrupts(i).meip := plic.io.harts(plic.cfg.context(i, 'M'))
|
|
||||||
if (p(UseVM))
|
|
||||||
prci.io.interrupts(i).seip := plic.io.harts(plic.cfg.context(i, 'S'))
|
|
||||||
prci.io.interrupts(i).debug := debugModule.io.debugInterrupts(i)
|
|
||||||
|
|
||||||
io.prci(i).reset := reset
|
|
||||||
}
|
|
||||||
|
|
||||||
val bootROM = Module(new ROMSlave(makeBootROM()))
|
|
||||||
bootROM.io <> mmioNetwork.port("int:bootrom")
|
|
||||||
|
|
||||||
for (device <- p(ExtraDevices)) {
|
for (device <- p(ExtraDevices)) {
|
||||||
device.builder(mmioNetwork.port("int:" + device.addrMapEntry.name), io.extra, p)
|
device.builder(mmioNetwork.port(device.addrMapEntry.name), io.extra, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
val ext = p(ExtMMIOPorts).entries.map(port => TileLinkWidthAdapter(mmioNetwork.port(port.name), "MMIO_Outermost"))
|
val ext = p(ExtMMIOPorts).map(
|
||||||
|
port => TileLinkWidthAdapter(mmioNetwork.port(port.name), "MMIO_Outermost"))
|
||||||
connectExternalMMIO(ext)(outermostMMIOParams)
|
connectExternalMMIO(ext)(outermostMMIOParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (exportMMIO) {
|
||||||
|
buildMMIONetwork(p.alterPartial({case TLId => "L2toMMIO"}))
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class AbstractOuterMemorySystem(implicit val p: Parameters)
|
for ((nasti, tl) <- io.mem_axi zip io.mem_in) {
|
||||||
extends Module with HasTopLevelParameters {
|
TopUtils.connectTilelinkNasti(nasti, tl)(outermostParams)
|
||||||
val io = new Bundle {
|
|
||||||
val tiles_cached = Vec(nCachedTilePorts, new ClientTileLinkIO).flip
|
|
||||||
val tiles_uncached = Vec(nUncachedTilePorts, new ClientUncachedTileLinkIO).flip
|
|
||||||
val incoherent = Vec(nCachedTilePorts, Bool()).asInput
|
|
||||||
val mem_axi = Vec(nMemAXIChannels, new NastiIO)
|
|
||||||
val mem_ahb = Vec(nMemAHBChannels, new HastiMasterIO)
|
|
||||||
val mem_tl = Vec(nMemTLChannels, new ClientUncachedTileLinkIO()(outermostParams))
|
|
||||||
val bus_axi = Vec(p(NExtBusAXIChannels), new NastiIO).flip
|
|
||||||
val mmio = new ClientUncachedTileLinkIO()(p.alterPartial({case TLId => "L2toMMIO"}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Use in place of OuterMemorySystem if there are no clients to connect. */
|
|
||||||
class DummyOuterMemorySystem(implicit p: Parameters) extends AbstractOuterMemorySystem()(p) {
|
|
||||||
require(nCachedTilePorts + nUncachedTilePorts == 0)
|
|
||||||
|
|
||||||
io.mem_axi.foreach { axi =>
|
|
||||||
axi.ar.valid := Bool(false)
|
|
||||||
axi.aw.valid := Bool(false)
|
|
||||||
axi.w.valid := Bool(false)
|
|
||||||
axi.r.ready := Bool(false)
|
|
||||||
axi.b.ready := Bool(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
io.mem_ahb.foreach { ahb =>
|
|
||||||
ahb.htrans := UInt(0)
|
|
||||||
ahb.hmastlock := Bool(false)
|
|
||||||
ahb.hwrite := Bool(false)
|
|
||||||
ahb.haddr := UInt(0)
|
|
||||||
ahb.hburst := UInt(0)
|
|
||||||
ahb.hsize := UInt(0)
|
|
||||||
ahb.hprot := UInt(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
io.mem_tl.foreach { tl =>
|
|
||||||
tl.acquire.valid := Bool(false)
|
|
||||||
tl.grant.ready := Bool(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
io.mmio.acquire.valid := Bool(false)
|
|
||||||
io.mmio.grant.ready := Bool(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The whole outer memory hierarchy, including a NoC, some kind of coherence
|
|
||||||
* manager agent, and a converter from TileLink to MemIO.
|
|
||||||
*/
|
|
||||||
class OuterMemorySystem(implicit p: Parameters) extends AbstractOuterMemorySystem()(p) {
|
|
||||||
// Create a simple L1toL2 NoC between the tiles and the banks of outer memory
|
|
||||||
// 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 = {
|
|
||||||
val isMemory = p(GlobalAddrMap).isInRegion("mem", addr << log2Up(p(CacheBlockBytes)))
|
|
||||||
Mux(isMemory,
|
|
||||||
if (nBanks > 1) addr(lsb + log2Up(nBanks) - 1, lsb) else UInt(0),
|
|
||||||
UInt(nBanks))
|
|
||||||
}
|
|
||||||
val preBuffering = TileLinkDepths(1,1,2,2,0)
|
|
||||||
val l1tol2net = Module(new PortedTileLinkCrossbar(addrToBank, sharerToClientId, preBuffering))
|
|
||||||
|
|
||||||
// Create point(s) of coherence serialization
|
|
||||||
val managerEndpoints = List.tabulate(nBanks){id => p(BuildL2CoherenceManager)(id, p)}
|
|
||||||
managerEndpoints.foreach { _.incoherent := io.incoherent }
|
|
||||||
|
|
||||||
val mmioManager = Module(new MMIOTileLinkManager()(p.alterPartial({
|
|
||||||
case TLId => "L1toL2"
|
|
||||||
case InnerTLId => "L1toL2"
|
|
||||||
case OuterTLId => "L2toMMIO"
|
|
||||||
})))
|
|
||||||
io.mmio <> mmioManager.io.outer
|
|
||||||
|
|
||||||
val bus_in = io.bus_axi.map { ext_nasti =>
|
|
||||||
val converter = Module(new TileLinkIONastiIOConverter)
|
|
||||||
converter.io.nasti <> ext_nasti
|
|
||||||
converter.io.tl
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wire the tiles to the TileLink client ports of the L1toL2 network,
|
|
||||||
// and coherence manager(s) to the other side
|
|
||||||
l1tol2net.io.clients_cached <> io.tiles_cached
|
|
||||||
l1tol2net.io.clients_uncached <> io.tiles_uncached ++ bus_in
|
|
||||||
l1tol2net.io.managers <> managerEndpoints.map(_.innerTL) :+ mmioManager.io.inner
|
|
||||||
|
|
||||||
// Create a converter between TileLinkIO and MemIO for each channel
|
|
||||||
val outerTLParams = p.alterPartial({ case TLId => "L2toMC" })
|
|
||||||
val outermostTLParams = p.alterPartial({case TLId => "Outermost"})
|
|
||||||
val backendBuffering = TileLinkDepths(0,0,0,0,0)
|
|
||||||
|
|
||||||
// TODO: the code to print this stuff should live somewhere else
|
|
||||||
println("Generated Address Map")
|
|
||||||
for ((name, region) <- p(GlobalAddrMap).flatten) {
|
|
||||||
println(f"\t$name%s ${region.start}%x - ${region.start + region.size - 1}%x")
|
|
||||||
}
|
|
||||||
println("Generated Configuration String")
|
|
||||||
println(new String(p(ConfigString)))
|
|
||||||
|
|
||||||
val mem_ic = Module(new TileLinkMemoryInterconnect(nBanksPerMemChannel, nMemChannels)(outermostTLParams))
|
|
||||||
|
|
||||||
for ((bank, icPort) <- managerEndpoints zip mem_ic.io.in) {
|
|
||||||
val unwrap = Module(new ClientTileLinkIOUnwrapper()(outerTLParams))
|
|
||||||
unwrap.io.in <> ClientTileLinkEnqueuer(bank.outerTL, backendBuffering)(outerTLParams)
|
|
||||||
TileLinkWidthAdapter(icPort, unwrap.io.out)
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((nasti, tl) <- io.mem_axi zip mem_ic.io.out) {
|
|
||||||
TopUtils.connectTilelinkNasti(nasti, tl)(outermostTLParams)
|
|
||||||
// Memory cache type should be normal non-cacheable bufferable
|
// Memory cache type should be normal non-cacheable bufferable
|
||||||
// TODO why is this happening here? Would 0000 (device) be OK instead?
|
// TODO why is this happening here? Would 0000 (device) be OK instead?
|
||||||
nasti.ar.bits.cache := UInt("b0011")
|
nasti.ar.bits.cache := UInt("b0011")
|
||||||
@ -449,13 +252,13 @@ class OuterMemorySystem(implicit p: Parameters) extends AbstractOuterMemorySyste
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Abuse the fact that zip takes the shorter of the two lists
|
// Abuse the fact that zip takes the shorter of the two lists
|
||||||
for ((ahb, tl) <- io.mem_ahb zip mem_ic.io.out) {
|
for ((ahb, tl) <- io.mem_ahb zip io.mem_in) {
|
||||||
val bridge = Module(new AHBBridge(false)) // no atomics
|
val bridge = Module(new AHBBridge(false)) // no atomics
|
||||||
ahb <> bridge.io.ahb
|
ahb <> bridge.io.ahb
|
||||||
bridge.io.tl <> tl
|
bridge.io.tl <> tl
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((mem_tl, tl) <- io.mem_tl zip mem_ic.io.out) {
|
for ((mem_tl, tl) <- io.mem_tl zip io.mem_in) {
|
||||||
TopUtils.connectTilelink(mem_tl, tl)
|
TopUtils.connectTilelink(mem_tl, tl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,10 @@ class WithComparator extends Config(
|
|||||||
case BuildGroundTest =>
|
case BuildGroundTest =>
|
||||||
(p: Parameters) => Module(new ComparatorCore()(p))
|
(p: Parameters) => Module(new ComparatorCore()(p))
|
||||||
case ComparatorKey => ComparatorParameters(
|
case ComparatorKey => ComparatorParameters(
|
||||||
targets = Seq("mem", "io:int:testram").map(name => site(GlobalAddrMap)(name).start.longValue),
|
targets = Seq(
|
||||||
|
site(GlobalAddrMap)("mem"),
|
||||||
|
site(ExtAddrMap)("testram"))
|
||||||
|
.map(entry => entry.start.longValue),
|
||||||
width = 8,
|
width = 8,
|
||||||
operations = 1000,
|
operations = 1000,
|
||||||
atomics = site(UseAtomics),
|
atomics = site(UseAtomics),
|
||||||
|
Loading…
Reference in New Issue
Block a user