1
0

now able to add periphery devices through traits

Unfortunately, I had to touch a lot of code, which weren't quite possible to split up into multiple commits.
This commit gets rid of the "extra" infrastructure to add periphery devices into Top.
This commit is contained in:
Yunsup Lee
2016-09-10 23:39:29 -07:00
parent 2c000a99da
commit bb3f514e8d
15 changed files with 414 additions and 472 deletions

View File

@ -8,6 +8,7 @@ import rocket._
import rocket.Util._
import uncore.agents._
import uncore.tilelink._
import uncore.tilelink2.{LazyModule}
import uncore.devices._
import uncore.converters._
import coreplex._
@ -17,156 +18,66 @@ import scala.collection.immutable.HashMap
import DefaultTestSuites._
import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
class BasePlatformConfig extends Config (
topDefinitions = { (pname,site,here) =>
type PF = PartialFunction[Any,Any]
def findBy(sname:Any):Any = here[PF](site[Any](sname))(pname)
lazy val internalIOAddrMap: AddrMap = {
val entries = collection.mutable.ArrayBuffer[AddrMapEntry]()
entries += AddrMapEntry("debug", MemSize(4096, MemAttr(AddrMapProt.RWX)))
entries += AddrMapEntry("bootrom", MemSize(4096, MemAttr(AddrMapProt.RX)))
entries += AddrMapEntry("plic", MemRange(0x40000000, 0x4000000, MemAttr(AddrMapProt.RW)))
entries += AddrMapEntry("prci", MemSize(0x4000000, MemAttr(AddrMapProt.RW)))
if (site(DataScratchpadSize) > 0) { // TODO heterogeneous tiles
require(site(NTiles) == 1) // TODO relax this
require(site(NMemoryChannels) == 0) // TODO allow both scratchpad & DRAM
entries += AddrMapEntry("dmem0", MemRange(0x80000000L, site[Int](DataScratchpadSize), MemAttr(AddrMapProt.RWX)))
}
new AddrMap(entries)
}
lazy val externalAddrMap = new AddrMap(
site(ExtraDevices).addrMapEntries ++ site(ExtMMIOPorts),
start = BigInt("50000000", 16),
collapse = true)
lazy val globalAddrMap = {
val memBase = 0x80000000L
val memSize = site(ExtMemSize)
val intern = AddrMapEntry("int", internalIOAddrMap)
val extern = AddrMapEntry("ext", externalAddrMap)
val io = AddrMapEntry("io", AddrMap((intern +: site(ExportMMIOPort).option(extern).toSeq):_*))
val mem = AddrMapEntry("mem", MemRange(memBase, memSize, MemAttr(AddrMapProt.RWX, true)))
val addrMap = AddrMap((io +: (site(NMemoryChannels) > 0).option(mem).toSeq):_*)
Dump("MEM_BASE", memBase)
addrMap
}
def makeConfigString() = {
val addrMap = globalAddrMap
val plicAddr = addrMap("io:int:plic").start
val prciAddr = addrMap("io:int:prci").start
val plicInfo = site(PLICKey)
val xLen = site(XLen)
val res = new StringBuilder
res append "plic {\n"
res append s" priority 0x${plicAddr.toString(16)};\n"
res append s" pending 0x${(plicAddr + plicInfo.pendingBase).toString(16)};\n"
res append s" ndevs ${plicInfo.nDevices};\n"
res append "};\n"
res append "rtc {\n"
res append s" addr 0x${(prciAddr + PRCI.time).toString(16)};\n"
res append "};\n"
if (addrMap contains "mem") {
res append "ram {\n"
res append " 0 {\n"
res append s" addr 0x${addrMap("mem").start.toString(16)};\n"
res append s" size 0x${addrMap("mem").size.toString(16)};\n"
res append " };\n"
res append "};\n"
}
res append "core {\n"
for (i <- 0 until site(NTiles)) { // TODO heterogeneous tiles
val isa = {
val m = if (site(MulDivKey).nonEmpty) "m" else ""
val a = if (site(UseAtomics)) "a" else ""
val f = if (site(FPUKey).nonEmpty) "f" else ""
val d = if (site(FPUKey).nonEmpty && site(XLen) > 32) "d" else ""
val s = if (site(UseVM)) "s" else ""
s"rv${site(XLen)}i$m$a$f$d$s"
class BasePlatformConfig extends Config(
topDefinitions = {
val configString = new GlobalVariable[String]
val globalAddrMap = new GlobalVariable[AddrMap]
val nCoreplexExtClients = new GlobalVariable[Int]
(pname,site,here) => {
type PF = PartialFunction[Any,Any]
def findBy(sname:Any):Any = here[PF](site[Any](sname))(pname)
lazy val innerDataBits = 64
lazy val innerDataBeats = (8 * site(CacheBlockBytes)) / innerDataBits
pname match {
//Memory Parameters
case MIFTagBits => Dump("MIF_TAG_BITS", 5)
case MIFDataBits => Dump("MIF_DATA_BITS", 64)
case MIFAddrBits => Dump("MIF_ADDR_BITS",
site(PAddrBits) - site(CacheBlockOffsetBits))
case MIFDataBeats => site(CacheBlockBytes) * 8 / site(MIFDataBits)
case NastiKey => {
Dump("MEM_STRB_BITS", site(MIFDataBits) / 8)
NastiParameters(
dataBits = Dump("MEM_DATA_BITS", site(MIFDataBits)),
addrBits = Dump("MEM_ADDR_BITS", site(PAddrBits)),
idBits = Dump("MEM_ID_BITS", site(MIFTagBits)))
}
res append s" $i {\n"
res append " 0 {\n"
res append s" isa $isa;\n"
res append s" timecmp 0x${(prciAddr + PRCI.timecmp(i)).toString(16)};\n"
res append s" ipi 0x${(prciAddr + PRCI.msip(i)).toString(16)};\n"
res append s" plic {\n"
res append s" m {\n"
res append s" ie 0x${(plicAddr + plicInfo.enableAddr(i, 'M')).toString(16)};\n"
res append s" thresh 0x${(plicAddr + plicInfo.threshAddr(i, 'M')).toString(16)};\n"
res append s" claim 0x${(plicAddr + plicInfo.claimAddr(i, 'M')).toString(16)};\n"
res append s" };\n"
if (site(UseVM)) {
res append s" s {\n"
res append s" ie 0x${(plicAddr + plicInfo.enableAddr(i, 'S')).toString(16)};\n"
res append s" thresh 0x${(plicAddr + plicInfo.threshAddr(i, 'S')).toString(16)};\n"
res append s" claim 0x${(plicAddr + plicInfo.claimAddr(i, 'S')).toString(16)};\n"
res append s" };\n"
}
res append " };\n"
res append " };\n"
res append " };\n"
case BuildCoreplex =>
(p: Parameters, c: CoreplexConfig) => Module(new DefaultCoreplex(p, c))
case NExtTopInterrupts => 2
// Note that PLIC asserts that this is > 0.
case AsyncDebugBus => false
case IncludeJtagDTM => false
case AsyncMMIOChannels => false
case ExtMMIOPorts => Nil
case NExtMMIOAXIChannels => 0
case NExtMMIOAHBChannels => 0
case NExtMMIOTLChannels => 0
case AsyncBusChannels => false
case NExtBusAXIChannels => 0
case NCoreplexExtClients => nCoreplexExtClients
case HastiId => "Ext"
case HastiKey("TL") =>
HastiParameters(
addrBits = site(PAddrBits),
dataBits = site(TLKey(site(TLId))).dataBits / site(TLKey(site(TLId))).dataBeats)
case HastiKey("Ext") =>
HastiParameters(
addrBits = site(PAddrBits),
dataBits = site(XLen))
case AsyncMemChannels => false
case NMemoryChannels => Dump("N_MEM_CHANNELS", 1)
case TMemoryChannels => BusType.AXI
case ExtMemSize => Dump("MEM_SIZE", 0x10000000L)
case ConfigString => configString
case GlobalAddrMap => globalAddrMap
case RTCPeriod => 100 // gives 10 MHz RTC assuming 1 GHz uncore clock
case BuildExampleTop =>
(p: Parameters) => uncore.tilelink2.LazyModule(new ExampleTop(p))
case _ => throw new CDEMatchError
}
res append "};\n"
res append (site(ExtraDevices).makeConfigString(addrMap))
res append '\u0000'
res.toString.getBytes
}
lazy val innerDataBits = 64
lazy val innerDataBeats = (8 * site(CacheBlockBytes)) / innerDataBits
pname match {
//Memory Parameters
case MIFTagBits => Dump("MIF_TAG_BITS", 5)
case MIFDataBits => Dump("MIF_DATA_BITS", 64)
case MIFAddrBits => Dump("MIF_ADDR_BITS",
site(PAddrBits) - site(CacheBlockOffsetBits))
case MIFDataBeats => site(CacheBlockBytes) * 8 / site(MIFDataBits)
case NastiKey => {
Dump("MEM_STRB_BITS", site(MIFDataBits) / 8)
NastiParameters(
dataBits = Dump("MEM_DATA_BITS", site(MIFDataBits)),
addrBits = Dump("MEM_ADDR_BITS", site(PAddrBits)),
idBits = Dump("MEM_ID_BITS", site(MIFTagBits)))
}
case BuildCoreplex => (p: Parameters) => Module(new DefaultCoreplex(p))
case NExtTopInterrupts => 2
case NExtPeripheryInterrupts => site(ExtraDevices).nInterrupts
// Note that PLIC asserts that this is > 0.
case NExtInterrupts => site(NExtTopInterrupts) + site(NExtPeripheryInterrupts)
case AsyncDebugBus => false
case IncludeJtagDTM => false
case AsyncMMIOChannels => false
case ExtraDevices => new EmptyDeviceBlock
case ExtraTopPorts => (p: Parameters) => new Bundle
case ExtMMIOPorts => Nil
case NExtMMIOAXIChannels => 0
case NExtMMIOAHBChannels => 0
case NExtMMIOTLChannels => 0
case ExportMMIOPort => !externalAddrMap.isEmpty
case AsyncBusChannels => false
case NExtBusAXIChannels => 0
case NExternalClients => (if (site(NExtBusAXIChannels) > 0) 1 else 0) +
site(ExtraDevices).nClientPorts
case ConnectExtraPorts =>
(out: Bundle, in: Bundle, p: Parameters) => out <> in
case HastiId => "Ext"
case HastiKey("TL") =>
HastiParameters(
addrBits = site(PAddrBits),
dataBits = site(TLKey(site(TLId))).dataBits / site(TLKey(site(TLId))).dataBeats)
case HastiKey("Ext") =>
HastiParameters(
addrBits = site(PAddrBits),
dataBits = site(XLen))
case AsyncMemChannels => false
case NMemoryChannels => Dump("N_MEM_CHANNELS", 1)
case TMemoryChannels => BusType.AXI
case ExtMemSize => Dump("MEM_SIZE", 0x10000000L)
case ConfigString => makeConfigString()
case GlobalAddrMap => globalAddrMap
case RTCPeriod => 100 // gives 10 MHz RTC assuming 1 GHz uncore clock
case _ => throw new CDEMatchError
}})
})
class BaseConfig extends Config(new BaseCoreplexConfig ++ new BasePlatformConfig)
class DefaultConfig extends Config(new WithBlockingL1 ++ new BaseConfig)
@ -178,7 +89,6 @@ class DefaultBufferlessConfig extends Config(
class FPGAConfig extends Config (
(pname,site,here) => pname match {
case NAcquireTransactors => 4
case ExportGroundTestStatus => true
case _ => throw new CDEMatchError
}
)
@ -269,35 +179,12 @@ class TinyConfig extends Config(
new WithSmallCores ++ new WithRV32 ++
new WithStatelessBridge ++ new BaseConfig)
class WithTestRAM extends Config(
(pname, site, here) => pname match {
case ExtraDevices => {
class TestRAMDevice extends DeviceBlock {
val ramSize = 0x1000
def nClientPorts = 0
def addrMapEntries = Seq(
AddrMapEntry("testram", MemSize(ramSize, MemAttr(AddrMapProt.RW))))
def builder(
mmioPorts: HashMap[String, ClientUncachedTileLinkIO],
clientPorts: Seq[ClientUncachedTileLinkIO],
interrupts: Seq[Bool],
extra: Bundle, p: Parameters) {
val testram = Module(new TileLinkTestRAM(ramSize)(p))
testram.io <> mmioPorts("testram")
}
}
new TestRAMDevice
}
}
)
class WithAsyncDebug extends Config (
(pname, site, here) => pname match {
case AsyncDebugBus => true
}
)
class WithJtagDTM extends Config (
(pname, site, here) => pname match {
case IncludeJtagDTM => true

View File

@ -1,68 +0,0 @@
package rocketchip
import Chisel._
import junctions._
import uncore.tilelink._
import scala.collection.immutable.HashMap
import cde.{Parameters, Field}
case object ExtraTopPorts extends Field[Parameters => Bundle]
case object ExtraDevices extends Field[DeviceBlock]
abstract class DeviceBlock {
/** How many client ports will the devices use */
def nClientPorts: Int
/** Address map entries for all of the devices */
def addrMapEntries: Seq[AddrMapEntry]
/**
* The total number of interrupt signals coming
* from all the devices */
def nInterrupts : Int = 0
/**
* The function that elaborates all the extra devices and connects them
* to the TileLink ports and extra top-level ports.
*
* @param mmioPorts A hashmap for the mmio ports.
* Use the names specified in addrMapEntries to get
* the mmio port for each device.
* @param clientPorts All the client ports available for the devices
* @param interrupts External interrupts from Periphery to Coreplex
* @param extra The extra top-level IO bundle
* @param p The CDE parameters for the devices
*/
def builder(
mmioPorts: HashMap[String, ClientUncachedTileLinkIO],
clientPorts: Seq[ClientUncachedTileLinkIO],
interrupts : Seq[Bool],
extra: Bundle, p: Parameters): Unit
/**
* Create the config string entry for this device that goes into the
* Boot ROM. You generally won't need to override this
*
* @param fullAddrMap The full global address map
*/
def makeConfigString(fullAddrMap: AddrMap): String = {
addrMapEntries.map { entry =>
val region = fullAddrMap("io:ext:" + entry.name)
s"${entry.name} {\n" +
s" addr 0x${region.start.toString(16)};\n" +
s" size 0x${region.size.toString(16)}; \n" +
"}\n"
}.mkString
}
}
class EmptyDeviceBlock extends DeviceBlock {
def nClientPorts = 0
def addrMapEntries = Seq.empty
def builder(
mmioPorts: HashMap[String, ClientUncachedTileLinkIO],
clientPorts: Seq[ClientUncachedTileLinkIO],
interrupts : Seq[Bool],
extra: Bundle, p: Parameters) {}
}

View File

@ -82,5 +82,5 @@ object RocketChipGenerator extends Generator {
writeOutputFile(td, s"$longName.prm", ParameterDump.getDump) // Parameters flagged with Dump()
writeOutputFile(td, s"${names.configs}.knb", world.getKnobs) // Knobs for DSE
writeOutputFile(td, s"${names.configs}.cst", world.getConstraints) // Constraints for DSE
writeOutputFile(td, s"${names.configs}.cfg", params(ConfigString).toString) // String for software
writeOutputFile(td, s"${names.configs}.cfg", params(ConfigString).get) // String for software
}

View File

@ -37,17 +37,10 @@ case object AsyncMemChannels extends Field[Boolean]
case object AsyncMMIOChannels extends Field[Boolean]
/** External address map settings */
case object ExtMMIOPorts extends Field[Seq[AddrMapEntry]]
/** Function for building Coreplex */
case object BuildCoreplex extends Field[Parameters => Coreplex]
/** Function for connecting coreplex extra ports to top-level extra ports */
case object ConnectExtraPorts extends Field[(Bundle, Bundle, Parameters) => Unit]
/** Specifies the size of external memory */
case object ExtMemSize extends Field[Long]
/** Specifies the actual sorce of External Interrupts as Top and Periphery.
* NExtInterrupts = NExtTopInterrupts + NExtPeripheryInterrupts
**/
/** Specifies the number of external interrupts */
case object NExtTopInterrupts extends Field[Int]
case object NExtPeripheryInterrupts extends Field[Int]
/** Source of RTC. First bundle is TopIO.extra, Second bundle is periphery.io.extra **/
case object RTCPeriod extends Field[Int]
@ -122,29 +115,30 @@ trait PeripheryDebugModule {
/////
trait PeripheryInterrupt extends LazyModule {
trait PeripheryExtInterrupts extends LazyModule {
implicit val p: Parameters
val pInterrupts: RangeManager
pInterrupts.add("ext", p(NExtTopInterrupts))
}
trait PeripheryInterruptBundle {
trait PeripheryExtInterruptsBundle {
implicit val p: Parameters
val interrupts = Vec(p(NExtTopInterrupts), Bool()).asInput
}
trait PeripheryInterruptModule {
trait PeripheryExtInterruptsModule {
implicit val p: Parameters
val outer: PeripheryInterrupt
val io: PeripheryInterruptBundle
val outer: PeripheryExtInterrupts
val io: PeripheryExtInterruptsBundle
val coreplex: Coreplex
val interrupts_periphery = Vec(p(NExtPeripheryInterrupts), Bool())
var interrupts_cnt = 0
// This places the Periphery Interrupts at Bits [0...]
// External interrupts are at the higher Bits.
// This may have some implications for prioritization of the interrupts,
// but PLIC could do some internal swizzling in the future.
coreplex.io.interrupts <> (interrupts_periphery ++ io.interrupts)
{
val r = outer.pInterrupts.range("ext")
((r._1 until r._2) zipWithIndex) foreach { case (c, i) =>
coreplex.io.interrupts(c) := io.interrupts(i)
}
}
}
/////
@ -169,7 +163,7 @@ trait PeripheryMasterMemModule extends HasPeripheryParameters {
val coreplex: Coreplex
// Abuse the fact that zip takes the shorter of the two lists
((io.mem_axi zip coreplex.io.mem) zipWithIndex) foreach { case ((axi, mem), idx) =>
((io.mem_axi zip coreplex.io.master.mem) zipWithIndex) foreach { case ((axi, mem), idx) =>
val axi_sync = PeripheryUtils.convertTLtoAXI(mem)(outermostParams)
axi_sync.ar.bits.cache := UInt("b0011")
axi_sync.aw.bits.cache := UInt("b0011")
@ -179,11 +173,11 @@ trait PeripheryMasterMemModule extends HasPeripheryParameters {
)
}
(io.mem_ahb zip coreplex.io.mem) foreach { case (ahb, mem) =>
(io.mem_ahb zip coreplex.io.master.mem) foreach { case (ahb, mem) =>
ahb <> PeripheryUtils.convertTLtoAHB(mem, atomics = false)(outermostParams)
}
(io.mem_tl zip coreplex.io.mem) foreach { case (tl, mem) =>
(io.mem_tl zip coreplex.io.master.mem) foreach { case (tl, mem) =>
tl <> ClientUncachedTileLinkEnqueuer(mem, 2)(outermostParams)
}
}
@ -245,6 +239,9 @@ trait PeripheryMasterMMIOModule extends HasPeripheryParameters {
trait PeripherySlave extends LazyModule {
implicit val p: Parameters
val pBusMasters: RangeManager
if (p(NExtBusAXIChannels) > 0) pBusMasters.add("ext", 1) // NExtBusAXIChannels are arbitrated into one TL port
}
trait PeripherySlaveBundle extends HasPeripheryParameters {
@ -270,7 +267,65 @@ trait PeripherySlaveModule extends HasPeripheryParameters {
}
val conv = Module(new TileLinkIONastiIOConverter()(innerParams))
conv.io.nasti <> arb.io.slave
coreplex.io.ext_clients.head <> conv.io.tl
require(p(NExternalClients) == 1, "external devices can't slave ports. wait for tilelink2!")
val r = outer.pBusMasters.range("ext")
require(r._2 - r._1 == 1, "RangeManager should return 1 slot")
coreplex.io.slave(r._1) <> conv.io.tl
}
}
/////
trait PeripheryTestRAM extends LazyModule {
implicit val p: Parameters
val pDevices: ResourceManager[AddrMapEntry]
val ramSize = 0x1000
pDevices.add(AddrMapEntry("testram", MemSize(ramSize, MemAttr(AddrMapProt.RW))))
}
trait PeripheryTestRAMBundle {
implicit val p: Parameters
}
trait PeripheryTestRAMModule extends HasPeripheryParameters {
implicit val p: Parameters
val outer: PeripheryTestRAM
val io: PeripheryTestRAMBundle
val mmioNetwork: Option[TileLinkRecursiveInterconnect]
val testram = Module(new TileLinkTestRAM(outer.ramSize)(innerMMIOParams))
testram.io <> mmioNetwork.get.port("testram")
}
/////
trait PeripheryTestBusMaster extends LazyModule {
implicit val p: Parameters
val pBusMasters: RangeManager
val pDevices: ResourceManager[AddrMapEntry]
pBusMasters.add("busmaster", 1)
pDevices.add(AddrMapEntry("busmaster", MemSize(4096, MemAttr(AddrMapProt.RW))))
}
trait PeripheryTestBusMasterBundle {
implicit val p: Parameters
}
trait PeripheryTestBusMasterModule {
implicit val p: Parameters
val outer: PeripheryTestBusMaster
val io: PeripheryTestBusMasterBundle
val mmioNetwork: Option[TileLinkRecursiveInterconnect]
val coreplex: Coreplex
val busmaster = Module(new groundtest.ExampleBusMaster()(p))
busmaster.io.mmio <> mmioNetwork.get.port("busmaster")
{
val r = outer.pBusMasters.range("busmaster")
require(r._2 - r._1 == 1, "RangeManager should return 1 slot")
coreplex.io.slave(r._1) <> busmaster.io.mem
}
}

View File

@ -26,7 +26,7 @@ class WithUnitTest extends Config(
DefaultTestSuites.groundtest32
TestGeneration.addSuite(groundtest("p"))
TestGeneration.addSuite(DefaultTestSuites.emptyBmarks)
(p: Parameters) => Module(new UnitTestCoreplex(p))
(p: Parameters, c: CoreplexConfig) => Module(new UnitTestCoreplex(p, c))
}
case UnitTests => (testParams: Parameters) =>
JunctionsUnitTests(testParams) ++ UncoreUnitTests(testParams)
@ -42,7 +42,8 @@ class UnitTestConfig extends Config(new WithUnitTest ++ new BaseConfig)
class WithGroundTest extends Config(
(pname, site, here) => pname match {
case BuildCoreplex => (p: Parameters) => Module(new GroundTestCoreplex(p))
case BuildCoreplex =>
(p: Parameters, c: CoreplexConfig) => Module(new GroundTestCoreplex(p, c))
case TLKey("L1toL2") => {
val useMEI = site(NTiles) <= 1 && site(NCachedTileLinkPorts) <= 1
TileLinkParameters(
@ -51,7 +52,7 @@ class WithGroundTest extends Config(
else new MESICoherence(site(L2DirectoryRepresentation))),
nManagers = site(NBanksPerMemoryChannel)*site(NMemoryChannels) + 1,
nCachingClients = site(NCachedTileLinkPorts),
nCachelessClients = site(NExternalClients) + site(NUncachedTileLinkPorts),
nCachelessClients = site(NCoreplexExtClients).get + site(NUncachedTileLinkPorts),
maxClientXacts = ((site(DCacheKey).nMSHRs + 1) +:
site(GroundTestKey).map(_.maxXacts))
.reduce(max(_, _)),
@ -79,6 +80,8 @@ class WithGroundTest extends Config(
}
}
}
case BuildExampleTop =>
(p: Parameters) => uncore.tilelink2.LazyModule(new ExampleTopWithTestRAM(p))
case FPUKey => None
case UseAtomics => false
case UseCompressed => false
@ -89,7 +92,7 @@ class WithGroundTest extends Config(
class GroundTestConfig extends Config(new WithGroundTest ++ new BaseConfig)
class ComparatorConfig extends Config(
new WithTestRAM ++ new WithComparator ++ new GroundTestConfig)
new WithComparator ++ new GroundTestConfig)
class ComparatorL2Config extends Config(
new WithAtomics ++ new WithPrefetches ++
new WithL2Cache ++ new ComparatorConfig)
@ -147,60 +150,3 @@ class MIF32BitMemtestConfig extends Config(
class PCIeMockupTestConfig extends Config(
new WithPCIeMockupTest ++ new GroundTestConfig)
class WithDirectGroundTest extends Config(
(pname, site, here) => pname match {
case ExportGroundTestStatus => true
case BuildCoreplex => (p: Parameters) => Module(new DirectGroundTestCoreplex(p))
case ExtraCoreplexPorts => (p: Parameters) =>
if (p(ExportGroundTestStatus)) new GroundTestStatus else new Bundle
case ExtraTopPorts => (p: Parameters) =>
if (p(ExportGroundTestStatus)) new GroundTestStatus else new Bundle
case TLKey("Outermost") => site(TLKey("L2toMC")).copy(
maxClientXacts = site(GroundTestKey)(0).maxXacts,
maxClientsPerPort = site(NBanksPerMemoryChannel),
dataBeats = site(MIFDataBeats))
case NBanksPerMemoryChannel => site(GroundTestKey)(0).uncached
case _ => throw new CDEMatchError
})
class DirectGroundTestConfig extends Config(
new WithDirectGroundTest ++ new GroundTestConfig)
class DirectMemtestConfig extends Config(
new WithDirectMemtest ++ new DirectGroundTestConfig)
class DirectComparatorConfig extends Config(
new WithDirectComparator ++ new DirectGroundTestConfig)
class DirectMemtestFPGAConfig extends Config(
new FPGAConfig ++ new DirectMemtestConfig)
class DirectComparatorFPGAConfig extends Config(
new FPGAConfig ++ new DirectComparatorConfig)
class WithBusMasterTest extends Config(
(pname, site, here) => pname match {
case GroundTestKey => Seq.fill(site(NTiles)) {
GroundTestTileSettings(uncached = 1)
}
case BuildGroundTest =>
(p: Parameters) => Module(new BusMasterTest()(p))
case ExtraDevices => {
class BusMasterDevice extends DeviceBlock {
def nClientPorts = 1
def addrMapEntries = Seq(
AddrMapEntry("busmaster", MemSize(4096, MemAttr(AddrMapProt.RW))))
def builder(
mmioPorts: HashMap[String, ClientUncachedTileLinkIO],
clientPorts: Seq[ClientUncachedTileLinkIO],
interrupts : Seq[Bool],
extra: Bundle, p: Parameters) {
val busmaster = Module(new ExampleBusMaster()(p))
busmaster.io.mmio <> mmioPorts("busmaster")
clientPorts.head <> busmaster.io.mem
}
}
new BusMasterDevice
}
case _ => throw new CDEMatchError
})
class BusMasterTestConfig extends Config(new WithBusMasterTest ++ new GroundTestConfig)

View File

@ -7,11 +7,13 @@ import cde.{Parameters, Field}
import rocket.Util._
import junctions._
class TestHarness(implicit p: Parameters) extends Module {
case object BuildExampleTop extends Field[Parameters => ExampleTop]
class TestHarness(implicit val p: Parameters) extends Module with HasAddrMapParameters {
val io = new Bundle {
val success = Bool(OUTPUT)
}
val dut = uncore.tilelink2.LazyModule(new ExampleTop(p)).module
val dut = p(BuildExampleTop)(p).module
// This test harness isn't especially flexible yet
require(dut.io.mem_clk.isEmpty)
@ -29,7 +31,7 @@ class TestHarness(implicit p: Parameters) extends Module {
int := false
if (dut.io.mem_axi.nonEmpty) {
val memSize = p(GlobalAddrMap)("mem").size
val memSize = addrMap("mem").size
require(memSize % dut.io.mem_axi.size == 0)
for (axi <- dut.io.mem_axi)
Module(new SimAXIMem(memSize / dut.io.mem_axi.size)).io.axi <> axi

View File

@ -3,49 +3,93 @@
package rocketchip
import Chisel._
import cde.{Parameters}
import cde.{Parameters, Field}
import junctions._
import uncore.tilelink._
import uncore.tilelink2.{LazyModule, LazyModuleImp}
import uncore.devices._
import rocket._
import rocket.Util._
import coreplex._
// the following parameters will be refactored properly with TL2
case object GlobalAddrMap extends Field[GlobalVariable[AddrMap]]
case object ConfigString extends Field[GlobalVariable[String]]
case object NCoreplexExtClients extends Field[GlobalVariable[Int]]
/** Base Top with no Periphery */
abstract class BaseTop(val p: Parameters) extends LazyModule
abstract class BaseTop(val p: Parameters) extends LazyModule {
// the following variables will be refactored properly with TL2
val pInterrupts = new RangeManager
val pBusMasters = new RangeManager
val pDevices = new ResourceManager[AddrMapEntry]
}
class BaseTopBundle(val p: Parameters, val c: Coreplex) extends ParameterizedBundle()(p) {
val success = c.hasSuccessFlag.option(Bool(OUTPUT))
}
class BaseTopModule[L <: BaseTop, B <: BaseTopBundle](val p: Parameters, l: L, b: Coreplex => B) extends LazyModuleImp(l) {
val coreplex = p(BuildCoreplex)(p)
class BaseTopModule[+L <: BaseTop, +B <: BaseTopBundle](val p: Parameters, l: L, b: Coreplex => B) extends LazyModuleImp(l) {
val outer: L = l
val c = CoreplexConfig(
nTiles = p(NTiles),
nExtInterrupts = outer.pInterrupts.sum,
nSlaves = outer.pBusMasters.sum,
hasSupervisor = p(UseVM),
hasExtMMIOPort = !(outer.pDevices.get.isEmpty && p(ExtMMIOPorts).isEmpty)
)
p(NCoreplexExtClients).assign(outer.pBusMasters.sum)
p(GlobalAddrMap).assign(GenerateGlobalAddrMap(p, outer.pDevices.get))
p(ConfigString).assign(GenerateConfigString(p, c, outer.pDevices.get))
println("Generated Address Map")
for (entry <- p(GlobalAddrMap).get.flatten) {
val name = entry.name
val start = entry.region.start
val end = entry.region.start + entry.region.size - 1
println(f"\t$name%s $start%x - $end%x")
}
println("Generated Configuration String")
println(p(ConfigString).get)
val coreplex = p(BuildCoreplex)(p, c)
val io: B = b(coreplex)
io.success zip coreplex.io.success map { case (x, y) => x := y }
coreplex.io.rtcTick := Counter(p(RTCPeriod)).inc()
val mmioNetwork = p(ExportMMIOPort).option(
Module(new TileLinkRecursiveInterconnect(1, p(GlobalAddrMap).subMap("io:ext"))(
val mmioNetwork = c.hasExtMMIOPort.option(
Module(new TileLinkRecursiveInterconnect(1, p(GlobalAddrMap).get.subMap("io:ext"))(
p.alterPartial({ case TLId => "L2toMMIO" }))))
mmioNetwork.foreach { _.io.in.head <> coreplex.io.mmio.get }
mmioNetwork.foreach { _.io.in.head <> coreplex.io.master.mmio.get }
}
/** Example Top with Periphery */
class ExampleTop(p: Parameters) extends BaseTop(p)
with PeripheryDebug with PeripheryInterrupt
with PeripheryDebug with PeripheryExtInterrupts
with PeripheryMasterMem with PeripheryMasterMMIO with PeripherySlave {
lazy val module = Module(new ExampleTopModule(p, this, new ExampleTopBundle(p, _)))
override lazy val module = Module(new ExampleTopModule(p, this, new ExampleTopBundle(p, _)))
}
class ExampleTopBundle(p: Parameters, c: Coreplex) extends BaseTopBundle(p, c)
with PeripheryDebugBundle with PeripheryInterruptBundle
with PeripheryDebugBundle with PeripheryExtInterruptsBundle
with PeripheryMasterMemBundle with PeripheryMasterMMIOBundle with PeripherySlaveBundle
class ExampleTopModule[L <: ExampleTop, B <: ExampleTopBundle](p: Parameters, l: L, b: Coreplex => B) extends BaseTopModule(p, l, b)
with PeripheryDebugModule with PeripheryInterruptModule
class ExampleTopModule[+L <: ExampleTop, +B <: ExampleTopBundle](p: Parameters, l: L, b: Coreplex => B) extends BaseTopModule(p, l, b)
with PeripheryDebugModule with PeripheryExtInterruptsModule
with PeripheryMasterMemModule with PeripheryMasterMMIOModule with PeripherySlaveModule
/** Example Top with TestRAM */
class ExampleTopWithTestRAM(p: Parameters) extends ExampleTop(p)
with PeripheryTestRAM {
override lazy val module = Module(new ExampleTopWithTestRAMModule(p, this, new ExampleTopWithTestRAMBundle(p, _)))
}
class ExampleTopWithTestRAMBundle(p: Parameters, c: Coreplex) extends ExampleTopBundle(p, c)
with PeripheryTestRAMBundle
class ExampleTopWithTestRAMModule[+L <: ExampleTopWithTestRAM, +B <: ExampleTopWithTestRAMBundle](p: Parameters, l: L, b: Coreplex => B) extends ExampleTopModule(p, l, b)
with PeripheryTestRAMModule

View File

@ -0,0 +1,149 @@
// See LICENSE for license details.
package rocketchip
import cde.{Parameters, Dump}
import junctions._
import uncore.devices._
import rocket._
import rocket.Util._
import coreplex._
class RangeManager {
private var finalized = false
private val l = collection.mutable.HashMap[String, Int]()
def add(name: String, element: Int) = { require(!finalized); l += (name -> element) }
def rangeMap = {
finalized = true
l map {
var sum = 0
x => { sum += x._2; (x._1 -> (sum-x._2, sum)) }
}
}
def range(name: String) = rangeMap(name)
def print = {
rangeMap map { case (name, (start, end)) =>
println(s"${name} on port ${start}-${end-1}")
}
}
def sum = {
finalized = true
l.map(_._2).sum
}
}
class ResourceManager[T] {
private var finalized = false
private val l = collection.mutable.ArrayBuffer[T]()
def add(element: T) = { require(!finalized); l += element }
def add(list: Seq[T]) = { require(!finalized); l ++= list }
def get: Seq[T] = { finalized = true; l }
}
class GlobalVariable[T] {
private var assigned = false
private var variable: T = _
def assign(value: T) = { require(!assigned); assigned = true; variable = value }
def get: T = { require(assigned); variable }
}
object GenerateGlobalAddrMap {
def apply(p: Parameters, pDevicesEntries: Seq[AddrMapEntry]) = {
lazy val intIOAddrMap: AddrMap = {
val entries = collection.mutable.ArrayBuffer[AddrMapEntry]()
entries += AddrMapEntry("debug", MemSize(4096, MemAttr(AddrMapProt.RWX)))
entries += AddrMapEntry("bootrom", MemSize(4096, MemAttr(AddrMapProt.RX)))
entries += AddrMapEntry("plic", MemRange(0x40000000, 0x4000000, MemAttr(AddrMapProt.RW)))
entries += AddrMapEntry("prci", MemSize(0x4000000, MemAttr(AddrMapProt.RW)))
if (p(DataScratchpadSize) > 0) { // TODO heterogeneous tiles
require(p(NTiles) == 1) // TODO relax this
require(p(NMemoryChannels) == 0) // TODO allow both scratchpad & DRAM
entries += AddrMapEntry("dmem0", MemRange(0x80000000L, BigInt(p(DataScratchpadSize)), MemAttr(AddrMapProt.RWX)))
}
new AddrMap(entries)
}
lazy val extIOAddrMap = new AddrMap(
pDevicesEntries ++ p(ExtMMIOPorts),
start = BigInt("50000000", 16),
collapse = true)
val memBase = 0x80000000L
val memSize = p(ExtMemSize)
Dump("MEM_BASE", memBase)
val intern = AddrMapEntry("int", intIOAddrMap)
val extern = AddrMapEntry("ext", extIOAddrMap)
val io = AddrMapEntry("io", AddrMap((intern +: (!extIOAddrMap.isEmpty).option(extern).toSeq):_*))
val mem = AddrMapEntry("mem", MemRange(memBase, memSize, MemAttr(AddrMapProt.RWX, true)))
AddrMap((io +: (p(NMemoryChannels) > 0).option(mem).toSeq):_*)
}
}
object GenerateConfigString {
def apply(p: Parameters, c: CoreplexConfig, pDevicesEntries: Seq[AddrMapEntry]) = {
val addrMap = p(GlobalAddrMap).get
val plicAddr = addrMap("io:int:plic").start
val prciAddr = addrMap("io:int:prci").start
val xLen = p(XLen)
val res = new StringBuilder
res append "plic {\n"
res append s" priority 0x${plicAddr.toString(16)};\n"
res append s" pending 0x${(plicAddr + c.plicKey.pendingBase).toString(16)};\n"
res append s" ndevs ${c.plicKey.nDevices};\n"
res append "};\n"
res append "rtc {\n"
res append s" addr 0x${(prciAddr + PRCI.time).toString(16)};\n"
res append "};\n"
if (addrMap contains "mem") {
res append "ram {\n"
res append " 0 {\n"
res append s" addr 0x${addrMap("mem").start.toString(16)};\n"
res append s" size 0x${addrMap("mem").size.toString(16)};\n"
res append " };\n"
res append "};\n"
}
res append "core {\n"
for (i <- 0 until c.nTiles) { // TODO heterogeneous tiles
val isa = {
val m = if (p(MulDivKey).nonEmpty) "m" else ""
val a = if (p(UseAtomics)) "a" else ""
val f = if (p(FPUKey).nonEmpty) "f" else ""
val d = if (p(FPUKey).nonEmpty && p(XLen) > 32) "d" else ""
val s = if (c.hasSupervisor) "s" else ""
s"rv${p(XLen)}i$m$a$f$d$s"
}
res append s" $i {\n"
res append " 0 {\n"
res append s" isa $isa;\n"
res append s" timecmp 0x${(prciAddr + PRCI.timecmp(i)).toString(16)};\n"
res append s" ipi 0x${(prciAddr + PRCI.msip(i)).toString(16)};\n"
res append s" plic {\n"
res append s" m {\n"
res append s" ie 0x${(plicAddr + c.plicKey.enableAddr(i, 'M')).toString(16)};\n"
res append s" thresh 0x${(plicAddr + c.plicKey.threshAddr(i, 'M')).toString(16)};\n"
res append s" claim 0x${(plicAddr + c.plicKey.claimAddr(i, 'M')).toString(16)};\n"
res append s" };\n"
if (c.hasSupervisor) {
res append s" s {\n"
res append s" ie 0x${(plicAddr + c.plicKey.enableAddr(i, 'S')).toString(16)};\n"
res append s" thresh 0x${(plicAddr + c.plicKey.threshAddr(i, 'S')).toString(16)};\n"
res append s" claim 0x${(plicAddr + c.plicKey.claimAddr(i, 'S')).toString(16)};\n"
res append s" };\n"
}
res append " };\n"
res append " };\n"
res append " };\n"
}
res append "};\n"
pDevicesEntries foreach { entry =>
val region = addrMap("io:ext:" + entry.name)
res append s"${entry.name} {\n"
res append s" addr 0x${region.start.toString(16)};\n"
res append s" size 0x${region.size.toString(16)}; \n"
res append "}\n"
}
res append '\u0000'
res.toString
}
}