move rocketchip package sources into its own subdirectory
This commit is contained in:
280
src/main/scala/rocketchip/Configs.scala
Normal file
280
src/main/scala/rocketchip/Configs.scala
Normal file
@ -0,0 +1,280 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
package rocketchip
|
||||
|
||||
import Chisel._
|
||||
import junctions._
|
||||
import rocket._
|
||||
import uncore.agents._
|
||||
import uncore.tilelink._
|
||||
import uncore.devices._
|
||||
import uncore.converters._
|
||||
import coreplex._
|
||||
import scala.math.max
|
||||
import scala.collection.mutable.{LinkedHashSet, ListBuffer}
|
||||
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)))
|
||||
new AddrMap(entries)
|
||||
}
|
||||
lazy val externalAddrMap = new AddrMap(
|
||||
site(ExtIOAddrMapEntries),
|
||||
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 ioMap = if (site(ExportMMIOPort)) AddrMap(intern, extern) else AddrMap(intern)
|
||||
|
||||
val addrMap = AddrMap(
|
||||
AddrMapEntry("io", ioMap),
|
||||
AddrMapEntry("mem", MemRange(memBase, memSize, MemAttr(AddrMapProt.RWX, true))))
|
||||
|
||||
Dump("MEM_BASE", addrMap("mem").start)
|
||||
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"
|
||||
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)) {
|
||||
val isa = s"rv${site(XLen)}im${if (site(UseAtomics)) "a" else ""}${if (site(FPUKey).nonEmpty) "fd" else ""}"
|
||||
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 s" };\n"
|
||||
res append " };\n"
|
||||
res append " };\n"
|
||||
}
|
||||
res append "};\n"
|
||||
for (device <- site(ExtraDevices)) {
|
||||
if (device.hasMMIOPort) {
|
||||
val deviceName = device.addrMapEntry.name
|
||||
val deviceRegion = addrMap("io:ext:" + deviceName)
|
||||
res.append(device.makeConfigString(deviceRegion))
|
||||
}
|
||||
}
|
||||
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 NExtInterrupts => 2
|
||||
case AsyncDebugBus => false
|
||||
case AsyncMMIOChannels => false
|
||||
case ExtraDevices => Nil
|
||||
case ExtraTopPorts => (p: Parameters) => new Bundle
|
||||
case ExtMMIOPorts => Nil
|
||||
case ExtIOAddrMapEntries =>
|
||||
site(ExtraDevices)
|
||||
.filter(_.hasMMIOPort)
|
||||
.map(_.addrMapEntry) ++
|
||||
site(ExtMMIOPorts)
|
||||
case NExtMMIOAXIChannels => 0
|
||||
case NExtMMIOAHBChannels => 0
|
||||
case NExtMMIOTLChannels => 0
|
||||
case ExportMMIOPort => (site(ExtraDevices).filter(_.hasMMIOPort).size + site(ExtMMIOPorts).size) > 0
|
||||
case AsyncBusChannels => false
|
||||
case NExtBusAXIChannels => 0
|
||||
case NExternalClients => (if (site(NExtBusAXIChannels) > 1) 1 else 0) +
|
||||
site(ExtraDevices).filter(_.hasClientPort).size
|
||||
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 _ => throw new CDEMatchError
|
||||
}})
|
||||
|
||||
class BaseConfig extends Config(new BaseCoreplexConfig ++ new BasePlatformConfig)
|
||||
class DefaultConfig extends Config(new WithBlockingL1 ++ new BaseConfig)
|
||||
|
||||
class DefaultL2Config extends Config(new WithL2Cache ++ new BaseConfig)
|
||||
class DefaultBufferlessConfig extends Config(
|
||||
new WithBufferlessBroadcastHub ++ new BaseConfig)
|
||||
|
||||
class FPGAConfig extends Config (
|
||||
(pname,site,here) => pname match {
|
||||
case NAcquireTransactors => 4
|
||||
case ExportGroundTestStatus => true
|
||||
case _ => throw new CDEMatchError
|
||||
}
|
||||
)
|
||||
|
||||
class DefaultFPGAConfig extends Config(new FPGAConfig ++ new BaseConfig)
|
||||
class DefaultL2FPGAConfig extends Config(
|
||||
new WithL2Capacity(64) ++ new WithL2Cache ++ new DefaultFPGAConfig)
|
||||
|
||||
class PLRUL2Config extends Config(new WithPLRU ++ new DefaultL2Config)
|
||||
|
||||
class WithNMemoryChannels(n: Int) extends Config(
|
||||
(pname,site,here) => pname match {
|
||||
case NMemoryChannels => Dump("N_MEM_CHANNELS", n)
|
||||
case _ => throw new CDEMatchError
|
||||
}
|
||||
)
|
||||
|
||||
class WithExtMemSize(n: Long) extends Config(
|
||||
(pname,site,here) => pname match {
|
||||
case ExtMemSize => Dump("MEM_SIZE", n)
|
||||
case _ => throw new CDEMatchError
|
||||
}
|
||||
)
|
||||
class WithAHB extends Config(
|
||||
(pname, site, here) => pname match {
|
||||
case TMemoryChannels => BusType.AHB
|
||||
case NExtMMIOAHBChannels => 1
|
||||
})
|
||||
|
||||
class WithTL extends Config(
|
||||
(pname, site, here) => pname match {
|
||||
case TMemoryChannels => BusType.TL
|
||||
case NExtMMIOTLChannels => 1
|
||||
})
|
||||
|
||||
class DefaultFPGASmallConfig extends Config(new WithSmallCores ++ new DefaultFPGAConfig)
|
||||
class DefaultSmallConfig extends Config(new WithSmallCores ++ new BaseConfig)
|
||||
class DefaultRV32Config extends Config(new WithRV32 ++ new DefaultSmallConfig)
|
||||
|
||||
class DualBankConfig extends Config(
|
||||
new WithNBanksPerMemChannel(2) ++ new BaseConfig)
|
||||
class DualBankL2Config extends Config(
|
||||
new WithNBanksPerMemChannel(2) ++ new WithL2Cache ++ new BaseConfig)
|
||||
|
||||
class DualChannelConfig extends Config(new WithNMemoryChannels(2) ++ new BaseConfig)
|
||||
class DualChannelL2Config extends Config(
|
||||
new WithNMemoryChannels(2) ++ new WithL2Cache ++ new BaseConfig)
|
||||
|
||||
class DualChannelDualBankConfig extends Config(
|
||||
new WithNMemoryChannels(2) ++
|
||||
new WithNBanksPerMemChannel(2) ++ new BaseConfig)
|
||||
class DualChannelDualBankL2Config extends Config(
|
||||
new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(2) ++
|
||||
new WithL2Cache ++ new BaseConfig)
|
||||
|
||||
class RoccExampleConfig extends Config(new WithRoccExample ++ new BaseConfig)
|
||||
|
||||
class WithMIFDataBits(n: Int) extends Config(
|
||||
(pname, site, here) => pname match {
|
||||
case MIFDataBits => Dump("MIF_DATA_BITS", n)
|
||||
})
|
||||
|
||||
class MIF128BitConfig extends Config(
|
||||
new WithMIFDataBits(128) ++ new BaseConfig)
|
||||
class MIF32BitConfig extends Config(
|
||||
new WithMIFDataBits(32) ++ new BaseConfig)
|
||||
|
||||
class SmallL2Config extends Config(
|
||||
new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(4) ++
|
||||
new WithL2Capacity(256) ++ new DefaultL2Config)
|
||||
|
||||
class SingleChannelBenchmarkConfig extends Config(new WithL2Capacity(256) ++ new DefaultL2Config)
|
||||
class DualChannelBenchmarkConfig extends Config(new WithNMemoryChannels(2) ++ new SingleChannelBenchmarkConfig)
|
||||
class QuadChannelBenchmarkConfig extends Config(new WithNMemoryChannels(4) ++ new SingleChannelBenchmarkConfig)
|
||||
class OctoChannelBenchmarkConfig extends Config(new WithNMemoryChannels(8) ++ new SingleChannelBenchmarkConfig)
|
||||
|
||||
class EightChannelConfig extends Config(new WithNMemoryChannels(8) ++ new BaseConfig)
|
||||
|
||||
class SplitL2MetadataTestConfig extends Config(new WithSplitL2Metadata ++ new DefaultL2Config)
|
||||
|
||||
class DualCoreConfig extends Config(
|
||||
new WithNCores(2) ++ new WithL2Cache ++ new BaseConfig)
|
||||
|
||||
class TinyConfig extends Config(
|
||||
new WithRV32 ++ new WithSmallCores ++
|
||||
new WithStatelessBridge ++ new BaseConfig)
|
||||
|
||||
class WithTestRAM extends Config(
|
||||
(pname, site, here) => pname match {
|
||||
case ExtraDevices => {
|
||||
class TestRAMDevice extends Device {
|
||||
val ramSize = 0x1000
|
||||
def hasClientPort = false
|
||||
def hasMMIOPort = true
|
||||
def builder(
|
||||
mmioPort: Option[ClientUncachedTileLinkIO],
|
||||
clientPort: Option[ClientUncachedTileLinkIO],
|
||||
extra: Bundle, p: Parameters) {
|
||||
val testram = Module(new TileLinkTestRAM(ramSize)(p))
|
||||
testram.io <> mmioPort.get
|
||||
}
|
||||
override def addrMapEntry =
|
||||
AddrMapEntry("testram", MemSize(ramSize, MemAttr(AddrMapProt.RW)))
|
||||
}
|
||||
Seq(new TestRAMDevice)
|
||||
}
|
||||
})
|
47
src/main/scala/rocketchip/Devices.scala
Normal file
47
src/main/scala/rocketchip/Devices.scala
Normal file
@ -0,0 +1,47 @@
|
||||
package rocketchip
|
||||
|
||||
import Chisel._
|
||||
import junctions._
|
||||
import uncore.tilelink._
|
||||
import cde.{Parameters, Field}
|
||||
|
||||
case object ExtraTopPorts extends Field[Parameters => Bundle]
|
||||
case object ExtraDevices extends Field[Seq[Device]]
|
||||
|
||||
abstract class Device {
|
||||
/** Does this device have an MMIO port? */
|
||||
def hasMMIOPort: Boolean
|
||||
/** Does this device have a client port? */
|
||||
def hasClientPort: Boolean
|
||||
/**
|
||||
* This function elaborates the hardware for the device and connects
|
||||
* it to the mmio port, client port, and extra top-level ports.
|
||||
*
|
||||
* @param mmioPort The port from the MMIO network that goes to this device.
|
||||
* If hasMMIOPort is false, this will be None
|
||||
*
|
||||
* @param clientPort The client port provided for this device to make
|
||||
* requests to the memory system. If hasClientPort is false, this will be None
|
||||
*/
|
||||
def builder(
|
||||
mmioPort: Option[ClientUncachedTileLinkIO],
|
||||
clientPort: Option[ClientUncachedTileLinkIO],
|
||||
extra: Bundle, p: Parameters): Unit
|
||||
/**
|
||||
* The entry that will be placed into the address map for this device.
|
||||
* If hasMMIOPort is false, you do not need to override this
|
||||
*/
|
||||
def addrMapEntry: AddrMapEntry =
|
||||
throw new UnsupportedOperationException("no addrMapEntry defined")
|
||||
|
||||
/**
|
||||
* Create the config string entry for this device that goes into the
|
||||
* Boot ROM. You generally won't need to override this
|
||||
*/
|
||||
def makeConfigString(region: MemRegion): String = {
|
||||
s"${addrMapEntry.name} {\n" +
|
||||
s" addr 0x${region.start.toString(16)};\n" +
|
||||
s" size 0x${region.size.toString(16)}; \n" +
|
||||
"}\n"
|
||||
}
|
||||
}
|
84
src/main/scala/rocketchip/Generator.scala
Normal file
84
src/main/scala/rocketchip/Generator.scala
Normal file
@ -0,0 +1,84 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
package rocketchip
|
||||
|
||||
import Chisel._
|
||||
import scala.collection.mutable.{LinkedHashSet,LinkedHashMap}
|
||||
import cde.{Parameters, ParameterDump, Config, Field, CDEMatchError, World}
|
||||
import coreplex._
|
||||
|
||||
object GeneratorUtils {
|
||||
def getConfig(projectName: String, configClassName: String): Config = {
|
||||
val aggregateConfigs = configClassName.split('_')
|
||||
|
||||
aggregateConfigs.foldRight(new Config()) { case (currentConfigName, finalConfig) =>
|
||||
val currentConfig = try {
|
||||
Class.forName(s"$projectName.$currentConfigName").newInstance.asInstanceOf[Config]
|
||||
} catch {
|
||||
case e: java.lang.ClassNotFoundException =>
|
||||
throwException("Unable to find part \"" + currentConfigName +
|
||||
"\" of configClassName \"" + configClassName +
|
||||
"\", did you misspell it?", e)
|
||||
}
|
||||
currentConfig ++ finalConfig
|
||||
}
|
||||
}
|
||||
|
||||
def getParameters(config: Config): Parameters =
|
||||
Parameters.root(config.toInstance)
|
||||
|
||||
def getParameters(projectName: String, configClassName: String): Parameters =
|
||||
getParameters(getConfig(projectName, configClassName))
|
||||
|
||||
def elaborate(fullName: String, args: Array[String], params: Parameters) {
|
||||
val gen = () =>
|
||||
Class.forName(fullName)
|
||||
.getConstructor(classOf[cde.Parameters])
|
||||
.newInstance(params)
|
||||
.asInstanceOf[Module]
|
||||
|
||||
chiselMain.run(args, gen)
|
||||
}
|
||||
|
||||
def dumpParameters(fname: String) {
|
||||
val pdFile = TestGeneration.createOutputFile(fname)
|
||||
pdFile.write(ParameterDump.getDump)
|
||||
pdFile.close
|
||||
}
|
||||
|
||||
def dumpKnobs(configClassName: String, world: World) {
|
||||
val knbFile = TestGeneration.createOutputFile(configClassName + ".knb")
|
||||
knbFile.write(world.getKnobs)
|
||||
knbFile.close
|
||||
|
||||
val cstFile = TestGeneration.createOutputFile(configClassName + ".cst")
|
||||
cstFile.write(world.getConstraints)
|
||||
cstFile.close
|
||||
}
|
||||
|
||||
def dumpConfigString(fname: String, params: Parameters) {
|
||||
val cfgFile = new java.io.FileOutputStream(Driver.targetDir + "/" + fname)
|
||||
cfgFile.write(params(ConfigString))
|
||||
cfgFile.close
|
||||
}
|
||||
}
|
||||
import GeneratorUtils._
|
||||
|
||||
object RocketChipGenerator extends App {
|
||||
val projectName = args(0)
|
||||
val topModuleName = args(1)
|
||||
val configClassName = args(2)
|
||||
|
||||
val config = getConfig(projectName, configClassName)
|
||||
val world = config.toInstance
|
||||
val paramsFromConfig = Parameters.root(world)
|
||||
|
||||
elaborate(s"$projectName.$topModuleName", args.drop(3), paramsFromConfig)
|
||||
|
||||
TestGeneration.addSuite(new RegressionTestSuite(paramsFromConfig(RegressionTestNames)))
|
||||
TestGeneration.generateMakefrag(topModuleName, configClassName)
|
||||
|
||||
dumpParameters(s"$topModuleName.$configClassName.prm")
|
||||
dumpKnobs(configClassName, world)
|
||||
dumpConfigString(s"$configClassName.cfg", paramsFromConfig)
|
||||
}
|
281
src/main/scala/rocketchip/RocketChip.scala
Normal file
281
src/main/scala/rocketchip/RocketChip.scala
Normal file
@ -0,0 +1,281 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
package rocketchip
|
||||
|
||||
import Chisel._
|
||||
import cde.{Parameters, Field}
|
||||
import junctions._
|
||||
import uncore.tilelink._
|
||||
import uncore.devices._
|
||||
import uncore.util._
|
||||
import uncore.converters._
|
||||
import uncore.coherence.{InnerTLId, OuterTLId}
|
||||
import rocket._
|
||||
import coreplex._
|
||||
|
||||
/** Top-level parameters of RocketChip, values set in e.g. PublicConfigs.scala */
|
||||
|
||||
/** Options for memory bus interface */
|
||||
object BusType {
|
||||
sealed trait EnumVal
|
||||
case object AXI extends EnumVal
|
||||
case object AHB extends EnumVal
|
||||
case object TL extends EnumVal
|
||||
val busTypes = Seq(AXI, AHB, TL)
|
||||
}
|
||||
|
||||
/** Memory channel controls */
|
||||
case object TMemoryChannels extends Field[BusType.EnumVal]
|
||||
/** External MMIO controls */
|
||||
case object NExtMMIOAXIChannels extends Field[Int]
|
||||
case object NExtMMIOAHBChannels extends Field[Int]
|
||||
case object NExtMMIOTLChannels extends Field[Int]
|
||||
/** External Bus controls */
|
||||
case object NExtBusAXIChannels extends Field[Int]
|
||||
/** Async configurations */
|
||||
case object AsyncBusChannels extends Field[Boolean]
|
||||
case object AsyncDebugBus extends Field[Boolean]
|
||||
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 ExtIOAddrMapEntries 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]
|
||||
|
||||
/** Utility trait for quick access to some relevant parameters */
|
||||
trait HasTopLevelParameters {
|
||||
implicit val p: Parameters
|
||||
lazy val tMemChannels = p(TMemoryChannels)
|
||||
lazy val nMemChannels = p(NMemoryChannels)
|
||||
lazy val nMemAXIChannels = if (tMemChannels == BusType.AXI) nMemChannels else 0
|
||||
lazy val nMemAHBChannels = if (tMemChannels == BusType.AHB) nMemChannels else 0
|
||||
lazy val nMemTLChannels = if (tMemChannels == BusType.TL) nMemChannels else 0
|
||||
lazy val innerParams = p.alterPartial({ case TLId => "L1toL2" })
|
||||
lazy val outermostParams = p.alterPartial({ case TLId => "Outermost" })
|
||||
lazy val outermostMMIOParams = p.alterPartial({ case TLId => "MMIO_Outermost" })
|
||||
lazy val exportMMIO = p(ExportMMIOPort)
|
||||
}
|
||||
|
||||
class MemBackupCtrlIO extends Bundle {
|
||||
val en = Bool(INPUT)
|
||||
val in_valid = Bool(INPUT)
|
||||
val out_ready = Bool(INPUT)
|
||||
val out_valid = Bool(OUTPUT)
|
||||
}
|
||||
|
||||
/** Top-level io for the chip */
|
||||
class BasicTopIO(implicit val p: Parameters) extends ParameterizedBundle()(p)
|
||||
with HasTopLevelParameters
|
||||
|
||||
class TopIO(implicit p: Parameters) extends BasicTopIO()(p) {
|
||||
val mem_clk = if (p(AsyncMemChannels)) Some(Vec(nMemChannels, Clock(INPUT))) else None
|
||||
val mem_rst = if (p(AsyncMemChannels)) Some(Vec(nMemChannels, Bool (INPUT))) else None
|
||||
val mem_axi = Vec(nMemAXIChannels, new NastiIO)
|
||||
val mem_ahb = Vec(nMemAHBChannels, new HastiMasterIO)
|
||||
val mem_tl = Vec(nMemTLChannels, new ClientUncachedTileLinkIO()(outermostParams))
|
||||
val interrupts = Vec(p(NExtInterrupts), Bool()).asInput
|
||||
val bus_clk = if (p(AsyncBusChannels)) Some(Vec(p(NExtBusAXIChannels), Clock(INPUT))) else None
|
||||
val bus_rst = if (p(AsyncBusChannels)) Some(Vec(p(NExtBusAXIChannels), Bool (INPUT))) else None
|
||||
val bus_axi = Vec(p(NExtBusAXIChannels), new NastiIO).flip
|
||||
val mmio_clk = if (p(AsyncMMIOChannels)) Some(Vec(p(NExtMMIOAXIChannels), Clock(INPUT))) else None
|
||||
val mmio_rst = if (p(AsyncMMIOChannels)) Some(Vec(p(NExtMMIOAXIChannels), Bool (INPUT))) else None
|
||||
val mmio_axi = Vec(p(NExtMMIOAXIChannels), new NastiIO)
|
||||
val mmio_ahb = Vec(p(NExtMMIOAHBChannels), new HastiMasterIO)
|
||||
val mmio_tl = Vec(p(NExtMMIOTLChannels), new ClientUncachedTileLinkIO()(outermostMMIOParams))
|
||||
val debug_clk = if (p(AsyncDebugBus)) Some(Clock(INPUT)) else None
|
||||
val debug_rst = if (p(AsyncDebugBus)) Some(Bool(INPUT)) else None
|
||||
val debug = new DebugBusIO()(p).flip
|
||||
val extra = p(ExtraTopPorts)(p)
|
||||
}
|
||||
|
||||
object TopUtils {
|
||||
// Connect two Nasti interfaces with queues in-between
|
||||
def connectNasti(outer: NastiIO, inner: NastiIO)(implicit p: Parameters) {
|
||||
val mifDataBeats = p(MIFDataBeats)
|
||||
outer.ar <> Queue(inner.ar, 1)
|
||||
outer.aw <> Queue(inner.aw, 1)
|
||||
outer.w <> Queue(inner.w)
|
||||
inner.r <> Queue(outer.r)
|
||||
inner.b <> Queue(outer.b, 1)
|
||||
}
|
||||
def connectTilelinkNasti(nasti: NastiIO, tl: ClientUncachedTileLinkIO)(implicit p: Parameters) = {
|
||||
val conv = Module(new NastiIOTileLinkIOConverter())
|
||||
conv.io.tl <> tl
|
||||
TopUtils.connectNasti(nasti, conv.io.nasti)
|
||||
}
|
||||
def connectTilelinkAhb(ahb: HastiMasterIO, tl: ClientUncachedTileLinkIO)(implicit p: Parameters) = {
|
||||
val bridge = Module(new AHBBridge(true))
|
||||
bridge.io.tl <> tl
|
||||
bridge.io.ahb
|
||||
}
|
||||
def connectTilelink(
|
||||
outer: ClientUncachedTileLinkIO, inner: ClientUncachedTileLinkIO)(implicit p: Parameters) = {
|
||||
outer.acquire <> Queue(inner.acquire)
|
||||
inner.grant <> Queue(outer.grant)
|
||||
}
|
||||
}
|
||||
|
||||
/** Top-level module for the chip */
|
||||
//TODO: Remove this wrapper once multichannel DRAM controller is provided
|
||||
class Top(topParams: Parameters) extends Module with HasTopLevelParameters {
|
||||
implicit val p = topParams
|
||||
|
||||
val coreplex = p(BuildCoreplex)(p)
|
||||
val periphery = Module(new Periphery()(innerParams))
|
||||
|
||||
val io = new TopIO {
|
||||
val success = if (coreplex.hasSuccessFlag) Some(Bool(OUTPUT)) else None
|
||||
}
|
||||
io.success zip coreplex.io.success map { case (x, y) => x := y }
|
||||
|
||||
if (exportMMIO) { periphery.io.mmio_in.get <> coreplex.io.mmio.get }
|
||||
periphery.io.mem_in <> coreplex.io.mem
|
||||
coreplex.io.ext_clients <> periphery.io.clients_out
|
||||
|
||||
coreplex.io.debug <>
|
||||
(if (p(AsyncDebugBus))
|
||||
AsyncDebugBusFrom(io.debug_clk.get, io.debug_rst.get, io.debug)
|
||||
else io.debug)
|
||||
|
||||
def asyncAxiTo(clocks: Seq[Clock], resets: Seq[Bool], inner_axis: Seq[NastiIO]): Seq[NastiIO] =
|
||||
(clocks, resets, inner_axis).zipped.map {
|
||||
case (clk, rst, in_axi) => AsyncNastiTo(clk, rst, in_axi)
|
||||
}
|
||||
|
||||
def asyncAxiFrom(clocks: Seq[Clock], resets: Seq[Bool], outer_axis: Seq[NastiIO]): Seq[NastiIO] =
|
||||
(clocks, resets, outer_axis).zipped.map {
|
||||
case (clk, rst, out_axi) => AsyncNastiFrom(clk, rst, out_axi)
|
||||
}
|
||||
|
||||
io.mmio_axi <>
|
||||
(if (p(AsyncMMIOChannels))
|
||||
asyncAxiTo(io.mmio_clk.get, io.mmio_rst.get, periphery.io.mmio_axi)
|
||||
else periphery.io.mmio_axi)
|
||||
io.mmio_ahb <> periphery.io.mmio_ahb
|
||||
io.mmio_tl <> periphery.io.mmio_tl
|
||||
|
||||
io.mem_axi <>
|
||||
(if (p(AsyncMemChannels))
|
||||
asyncAxiTo(io.mem_clk.get, io.mem_rst.get, periphery.io.mem_axi)
|
||||
else periphery.io.mem_axi)
|
||||
io.mem_ahb <> periphery.io.mem_ahb
|
||||
io.mem_tl <> periphery.io.mem_tl
|
||||
|
||||
periphery.io.bus_axi <>
|
||||
(if (p(AsyncBusChannels))
|
||||
asyncAxiFrom(io.bus_clk.get, io.bus_rst.get, io.bus_axi)
|
||||
else io.bus_axi)
|
||||
|
||||
coreplex.io.interrupts <> io.interrupts
|
||||
|
||||
io.extra <> periphery.io.extra
|
||||
p(ConnectExtraPorts)(io.extra, coreplex.io.extra, p)
|
||||
}
|
||||
|
||||
class Periphery(implicit val p: Parameters) extends Module
|
||||
with HasTopLevelParameters {
|
||||
val io = new Bundle {
|
||||
val mem_in = Vec(nMemChannels, new ClientUncachedTileLinkIO()(outermostParams)).flip
|
||||
val clients_out = Vec(p(NExternalClients), new ClientUncachedTileLinkIO()(innerParams))
|
||||
val mmio_in = if (exportMMIO) Some(new ClientUncachedTileLinkIO()(outermostMMIOParams).flip) else None
|
||||
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_axi = Vec(p(NExtMMIOAXIChannels), new NastiIO)
|
||||
val mmio_ahb = Vec(p(NExtMMIOAHBChannels), new HastiMasterIO)
|
||||
val mmio_tl = Vec(p(NExtMMIOTLChannels), new ClientUncachedTileLinkIO()(outermostMMIOParams))
|
||||
val extra = p(ExtraTopPorts)(p)
|
||||
}
|
||||
|
||||
var client_ind = 0
|
||||
|
||||
if (io.bus_axi.size > 0) {
|
||||
val conv = Module(new TileLinkIONastiIOConverter)
|
||||
val arb = Module(new NastiArbiter(io.bus_axi.size))
|
||||
arb.io.master <> io.bus_axi
|
||||
conv.io.nasti <> conv.io.tl
|
||||
io.clients_out.head <> conv.io.tl
|
||||
client_ind += 1
|
||||
}
|
||||
|
||||
def connectExternalMMIO(ports: Seq[ClientUncachedTileLinkIO])(implicit p: Parameters) {
|
||||
val mmio_axi_start = 0
|
||||
val mmio_axi_end = mmio_axi_start + p(NExtMMIOAXIChannels)
|
||||
val mmio_ahb_start = mmio_axi_end
|
||||
val mmio_ahb_end = mmio_ahb_start + p(NExtMMIOAHBChannels)
|
||||
val mmio_tl_start = mmio_ahb_end
|
||||
val mmio_tl_end = mmio_tl_start + p(NExtMMIOTLChannels)
|
||||
require (mmio_tl_end == ports.size)
|
||||
|
||||
for (i <- 0 until ports.size) {
|
||||
if (mmio_axi_start <= i && i < mmio_axi_end) {
|
||||
TopUtils.connectTilelinkNasti(io.mmio_axi(i-mmio_axi_start), ports(i))
|
||||
} else if (mmio_ahb_start <= i && i < mmio_ahb_end) {
|
||||
val ahbBridge = Module(new AHBBridge(true))
|
||||
io.mmio_ahb(i-mmio_ahb_start) <> ahbBridge.io.ahb
|
||||
ahbBridge.io.tl <> ports(i)
|
||||
} else if (mmio_tl_start <= i && i < mmio_tl_end) {
|
||||
TopUtils.connectTilelink(io.mmio_tl(i-mmio_tl_start), ports(i))
|
||||
} else {
|
||||
require(false, "Unconnected external MMIO port")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def buildMMIONetwork(implicit p: Parameters) = {
|
||||
val extAddrMap = p(GlobalAddrMap).subMap("io:ext")
|
||||
|
||||
val mmioNetwork = Module(new TileLinkRecursiveInterconnect(1, extAddrMap))
|
||||
mmioNetwork.io.in.head <> io.mmio_in.get
|
||||
|
||||
for (device <- p(ExtraDevices)) {
|
||||
val mmioPort = if (device.hasMMIOPort)
|
||||
Some(mmioNetwork.port(device.addrMapEntry.name)) else None
|
||||
|
||||
val clientPort = if (device.hasClientPort) {
|
||||
client_ind += 1
|
||||
Some(io.clients_out(client_ind - 1))
|
||||
} else None
|
||||
|
||||
val buildParams = p.alterPartial({
|
||||
case InnerTLId => "L2toMMIO" // Device MMIO port
|
||||
case OuterTLId => "L1toL2" // Device client port
|
||||
})
|
||||
|
||||
device.builder(mmioPort, clientPort, io.extra, buildParams)
|
||||
}
|
||||
|
||||
val ext = p(ExtMMIOPorts).map(
|
||||
port => TileLinkWidthAdapter(mmioNetwork.port(port.name), "MMIO_Outermost"))
|
||||
connectExternalMMIO(ext)(outermostMMIOParams)
|
||||
}
|
||||
|
||||
if (exportMMIO) {
|
||||
buildMMIONetwork(p.alterPartial({case TLId => "L2toMMIO"}))
|
||||
}
|
||||
|
||||
for ((nasti, tl) <- io.mem_axi zip io.mem_in) {
|
||||
TopUtils.connectTilelinkNasti(nasti, tl)(outermostParams)
|
||||
// Memory cache type should be normal non-cacheable bufferable
|
||||
// TODO why is this happening here? Would 0000 (device) be OK instead?
|
||||
nasti.ar.bits.cache := UInt("b0011")
|
||||
nasti.aw.bits.cache := UInt("b0011")
|
||||
}
|
||||
|
||||
// Abuse the fact that zip takes the shorter of the two lists
|
||||
for ((ahb, tl) <- io.mem_ahb zip io.mem_in) {
|
||||
val bridge = Module(new AHBBridge(false)) // no atomics
|
||||
ahb <> bridge.io.ahb
|
||||
bridge.io.tl <> tl
|
||||
}
|
||||
|
||||
for ((mem_tl, tl) <- io.mem_tl zip io.mem_in) {
|
||||
TopUtils.connectTilelink(mem_tl, tl)
|
||||
}
|
||||
}
|
205
src/main/scala/rocketchip/TestConfigs.scala
Normal file
205
src/main/scala/rocketchip/TestConfigs.scala
Normal file
@ -0,0 +1,205 @@
|
||||
package rocketchip
|
||||
|
||||
import Chisel._
|
||||
import groundtest._
|
||||
import rocket._
|
||||
import uncore.tilelink._
|
||||
import uncore.coherence._
|
||||
import uncore.agents._
|
||||
import uncore.devices.NTiles
|
||||
import uncore.unittests._
|
||||
import junctions._
|
||||
import junctions.unittests._
|
||||
import scala.collection.mutable.LinkedHashSet
|
||||
import cde.{Parameters, Config, Dump, Knob, CDEMatchError}
|
||||
import scala.math.max
|
||||
import coreplex._
|
||||
import ConfigUtils._
|
||||
|
||||
class WithUnitTest extends Config(
|
||||
(pname, site, here) => pname match {
|
||||
case BuildCoreplex => {
|
||||
val groundtest = if (site(XLen) == 64)
|
||||
DefaultTestSuites.groundtest64
|
||||
else
|
||||
DefaultTestSuites.groundtest32
|
||||
TestGeneration.addSuite(groundtest("p"))
|
||||
TestGeneration.addSuite(DefaultTestSuites.emptyBmarks)
|
||||
(p: Parameters) => Module(new UnitTestCoreplex(p))
|
||||
}
|
||||
case UnitTests => (testParams: Parameters) =>
|
||||
JunctionsUnitTests(testParams) ++ UncoreUnitTests(testParams)
|
||||
case NMemoryChannels => Dump("N_MEM_CHANNELS", 0)
|
||||
case FPUKey => None
|
||||
case UseAtomics => false
|
||||
case UseCompressed => false
|
||||
case RegressionTestNames => LinkedHashSet("rv64ui-p-simple")
|
||||
case _ => throw new CDEMatchError
|
||||
})
|
||||
|
||||
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 TLKey("L1toL2") => {
|
||||
val useMEI = site(NTiles) <= 1 && site(NCachedTileLinkPorts) <= 1
|
||||
TileLinkParameters(
|
||||
coherencePolicy = (
|
||||
if (useMEI) new MEICoherence(site(L2DirectoryRepresentation))
|
||||
else new MESICoherence(site(L2DirectoryRepresentation))),
|
||||
nManagers = site(NBanksPerMemoryChannel)*site(NMemoryChannels) + 1,
|
||||
nCachingClients = site(NCachedTileLinkPorts),
|
||||
nCachelessClients = site(NExternalClients) + site(NUncachedTileLinkPorts),
|
||||
maxClientXacts = ((site(DCacheKey).nMSHRs + 1) +:
|
||||
site(GroundTestKey).map(_.maxXacts))
|
||||
.reduce(max(_, _)),
|
||||
maxClientsPerPort = 1,
|
||||
maxManagerXacts = site(NAcquireTransactors) + 2,
|
||||
dataBeats = 8,
|
||||
dataBits = site(CacheBlockBytes)*8)
|
||||
}
|
||||
case BuildTiles => {
|
||||
val groundtest = if (site(XLen) == 64)
|
||||
DefaultTestSuites.groundtest64
|
||||
else
|
||||
DefaultTestSuites.groundtest32
|
||||
TestGeneration.addSuite(groundtest("p"))
|
||||
TestGeneration.addSuite(DefaultTestSuites.emptyBmarks)
|
||||
(0 until site(NTiles)).map { i =>
|
||||
val tileSettings = site(GroundTestKey)(i)
|
||||
(r: Bool, p: Parameters) => {
|
||||
Module(new GroundTestTile(resetSignal = r)(p.alterPartial({
|
||||
case TLId => "L1toL2"
|
||||
case GroundTestId => i
|
||||
case NCachedTileLinkPorts => if(tileSettings.cached > 0) 1 else 0
|
||||
case NUncachedTileLinkPorts => tileSettings.uncached
|
||||
})))
|
||||
}
|
||||
}
|
||||
}
|
||||
case FPUKey => None
|
||||
case UseAtomics => false
|
||||
case UseCompressed => false
|
||||
case RegressionTestNames => LinkedHashSet("rv64ui-p-simple")
|
||||
case _ => throw new CDEMatchError
|
||||
})
|
||||
|
||||
class GroundTestConfig extends Config(new WithGroundTest ++ new BaseConfig)
|
||||
|
||||
class ComparatorConfig extends Config(
|
||||
new WithTestRAM ++ new WithComparator ++ new GroundTestConfig)
|
||||
class ComparatorL2Config extends Config(
|
||||
new WithAtomics ++ new WithPrefetches ++
|
||||
new WithL2Cache ++ new ComparatorConfig)
|
||||
class ComparatorBufferlessConfig extends Config(
|
||||
new WithBufferlessBroadcastHub ++ new ComparatorConfig)
|
||||
class ComparatorStatelessConfig extends Config(
|
||||
new WithStatelessBridge ++ new ComparatorConfig)
|
||||
|
||||
class MemtestConfig extends Config(new WithMemtest ++ new GroundTestConfig)
|
||||
class MemtestL2Config extends Config(
|
||||
new WithL2Cache ++ new MemtestConfig)
|
||||
class MemtestBufferlessConfig extends Config(
|
||||
new WithBufferlessBroadcastHub ++ new MemtestConfig)
|
||||
class MemtestStatelessConfig extends Config(
|
||||
new WithNGenerators(0, 1) ++ new WithStatelessBridge ++ new MemtestConfig)
|
||||
// Test ALL the things
|
||||
class FancyMemtestConfig extends Config(
|
||||
new WithNGenerators(1, 2) ++ new WithNCores(2) ++ new WithMemtest ++
|
||||
new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(4) ++
|
||||
new WithSplitL2Metadata ++ new WithL2Cache ++ new GroundTestConfig)
|
||||
|
||||
class CacheFillTestConfig extends Config(
|
||||
new WithCacheFillTest ++ new WithPLRU ++ new WithL2Cache ++ new GroundTestConfig)
|
||||
|
||||
class BroadcastRegressionTestConfig extends Config(
|
||||
new WithBroadcastRegressionTest ++ new GroundTestConfig)
|
||||
class BufferlessRegressionTestConfig extends Config(
|
||||
new WithBufferlessBroadcastHub ++ new BroadcastRegressionTestConfig)
|
||||
class CacheRegressionTestConfig extends Config(
|
||||
new WithCacheRegressionTest ++ new WithL2Cache ++ new GroundTestConfig)
|
||||
|
||||
class NastiConverterTestConfig extends Config(new WithNastiConverterTest ++ new GroundTestConfig)
|
||||
class FancyNastiConverterTestConfig extends Config(
|
||||
new WithNCores(2) ++ new WithNastiConverterTest ++
|
||||
new WithNMemoryChannels(2) ++ new WithNBanksPerMemChannel(4) ++
|
||||
new WithL2Cache ++ new GroundTestConfig)
|
||||
|
||||
class TraceGenConfig extends Config(
|
||||
new WithNCores(2) ++ new WithTraceGen ++ new GroundTestConfig)
|
||||
class TraceGenBufferlessConfig extends Config(
|
||||
new WithBufferlessBroadcastHub ++ new TraceGenConfig)
|
||||
class TraceGenL2Config extends Config(
|
||||
new WithNL2Ways(1) ++ new WithL2Capacity(32 * 64 / 1024) ++
|
||||
new WithL2Cache ++ new TraceGenConfig)
|
||||
|
||||
class MIF128BitComparatorConfig extends Config(
|
||||
new WithMIFDataBits(128) ++ new ComparatorConfig)
|
||||
class MIF128BitMemtestConfig extends Config(
|
||||
new WithMIFDataBits(128) ++ new MemtestConfig)
|
||||
|
||||
class MIF32BitComparatorConfig extends Config(
|
||||
new WithMIFDataBits(32) ++ new ComparatorConfig)
|
||||
class MIF32BitMemtestConfig extends Config(
|
||||
new WithMIFDataBits(32) ++ new MemtestConfig)
|
||||
|
||||
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 Device {
|
||||
def hasClientPort = true
|
||||
def hasMMIOPort = true
|
||||
def builder(
|
||||
mmioPort: Option[ClientUncachedTileLinkIO],
|
||||
clientPort: Option[ClientUncachedTileLinkIO],
|
||||
extra: Bundle, p: Parameters) {
|
||||
val busmaster = Module(new ExampleBusMaster()(p))
|
||||
busmaster.io.mmio <> mmioPort.get
|
||||
clientPort.get <> busmaster.io.mem
|
||||
}
|
||||
override def addrMapEntry =
|
||||
AddrMapEntry("busmaster", MemSize(4096, MemAttr(AddrMapProt.RW)))
|
||||
}
|
||||
Seq(new BusMasterDevice)
|
||||
}
|
||||
case _ => throw new CDEMatchError
|
||||
})
|
||||
|
||||
class BusMasterTestConfig extends Config(new WithBusMasterTest ++ new GroundTestConfig)
|
116
src/main/scala/rocketchip/TestHarness.scala
Normal file
116
src/main/scala/rocketchip/TestHarness.scala
Normal file
@ -0,0 +1,116 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
package rocketchip
|
||||
|
||||
import Chisel._
|
||||
import cde.{Parameters, Field}
|
||||
import rocket.Util._
|
||||
import junctions._
|
||||
|
||||
class TestHarness(implicit p: Parameters) extends Module {
|
||||
val io = new Bundle {
|
||||
val success = Bool(OUTPUT)
|
||||
}
|
||||
val dut = Module(new Top(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)
|
||||
require(dut.io.bus_axi.isEmpty)
|
||||
require(dut.io.mmio_clk.isEmpty)
|
||||
require(dut.io.mmio_rst.isEmpty)
|
||||
require(dut.io.mmio_axi.isEmpty)
|
||||
require(dut.io.mmio_ahb.isEmpty)
|
||||
require(dut.io.mmio_tl.isEmpty)
|
||||
require(dut.io.debug_clk.isEmpty)
|
||||
require(dut.io.debug_rst.isEmpty)
|
||||
require(dut.io.debug_rst.isEmpty)
|
||||
require(dut.io.extra.elements.isEmpty)
|
||||
|
||||
for (int <- dut.io.interrupts)
|
||||
int := false
|
||||
|
||||
if (dut.io.mem_axi.nonEmpty) {
|
||||
val memSize = p(GlobalAddrMap)("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
|
||||
}
|
||||
|
||||
val dtm = Module(new SimDTM)
|
||||
dut.io.debug <> dtm.io.debug
|
||||
dtm.io.clk := clock
|
||||
dtm.io.reset := reset
|
||||
io.success := dut.io.success.getOrElse(dtm.io.exit === 1)
|
||||
when (dtm.io.exit >= 2) {
|
||||
printf("*** FAILED *** (exit code = %d)\n", dtm.io.exit >> 1)
|
||||
stop(1)
|
||||
}
|
||||
}
|
||||
|
||||
class SimAXIMem(size: BigInt)(implicit p: Parameters) extends Module {
|
||||
val io = new Bundle {
|
||||
val axi = new NastiIO().flip
|
||||
}
|
||||
|
||||
val rValid = Reg(init = Bool(false))
|
||||
val ar = RegEnable(io.axi.ar.bits, io.axi.ar.fire())
|
||||
io.axi.ar.ready := !rValid
|
||||
when (io.axi.ar.fire()) { rValid := true }
|
||||
when (io.axi.r.fire()) {
|
||||
assert(ar.burst === NastiConstants.BURST_INCR)
|
||||
ar.addr := ar.addr + (UInt(1) << ar.size)
|
||||
ar.len := ar.len - 1
|
||||
when (ar.len === UInt(0)) { rValid := false }
|
||||
}
|
||||
|
||||
val w = io.axi.w.bits
|
||||
require((size * 8) % w.data.getWidth == 0)
|
||||
val depth = (size * 8) / w.data.getWidth
|
||||
val mem = Mem(depth.toInt, w.data)
|
||||
|
||||
val wValid = Reg(init = Bool(false))
|
||||
val bValid = Reg(init = Bool(false))
|
||||
val aw = RegEnable(io.axi.aw.bits, io.axi.aw.fire())
|
||||
io.axi.aw.ready := !wValid && !bValid
|
||||
io.axi.w.ready := wValid
|
||||
when (io.axi.b.fire()) { bValid := false }
|
||||
when (io.axi.aw.fire()) { wValid := true }
|
||||
when (io.axi.w.fire()) {
|
||||
assert(aw.burst === NastiConstants.BURST_INCR)
|
||||
aw.addr := aw.addr + (UInt(1) << aw.size)
|
||||
aw.len := aw.len - 1
|
||||
when (aw.len === UInt(0)) {
|
||||
wValid := false
|
||||
bValid := true
|
||||
}
|
||||
|
||||
def row = mem((aw.addr >> log2Ceil(w.data.getWidth/8))(log2Ceil(depth)-1, 0))
|
||||
val mask = FillInterleaved(8, w.strb)
|
||||
val newData = mask & w.data | ~mask & row
|
||||
row := newData
|
||||
}
|
||||
|
||||
io.axi.b.valid := bValid
|
||||
io.axi.b.bits.id := aw.id
|
||||
io.axi.b.bits.resp := UInt(0)
|
||||
|
||||
io.axi.r.valid := rValid
|
||||
io.axi.r.bits.id := ar.id
|
||||
io.axi.r.bits.data := mem((ar.addr >> log2Ceil(w.data.getWidth/8))(log2Ceil(depth)-1, 0))
|
||||
io.axi.r.bits.resp := UInt(0)
|
||||
io.axi.r.bits.last := ar.len === UInt(0)
|
||||
}
|
||||
|
||||
class SimDTM(implicit p: Parameters) extends BlackBox {
|
||||
val io = new Bundle {
|
||||
val clk = Clock(INPUT)
|
||||
val reset = Bool(INPUT)
|
||||
val debug = new uncore.devices.DebugBusIO
|
||||
val exit = UInt(OUTPUT, 32)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user