Change Generic Config
This commit is contained in:
@@ -13,6 +13,7 @@ import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams
|
|||||||
import freechips.rocketchip.util.{AsyncResetReg}
|
import freechips.rocketchip.util.{AsyncResetReg}
|
||||||
|
|
||||||
import boom.common.{BoomTilesKey}
|
import boom.common.{BoomTilesKey}
|
||||||
|
import ariane.ArianeTilesKey
|
||||||
import testchipip._
|
import testchipip._
|
||||||
|
|
||||||
import hwacha.{Hwacha}
|
import hwacha.{Hwacha}
|
||||||
@@ -22,7 +23,8 @@ import sifive.blocks.devices.uart._
|
|||||||
import sifive.blocks.devices.spi._
|
import sifive.blocks.devices.spi._
|
||||||
|
|
||||||
import chipyard.{BuildTop, BuildSystem}
|
import chipyard.{BuildTop, BuildSystem}
|
||||||
import chipyard.GenericCoreConfig
|
import chipyard.TilesKey
|
||||||
|
import chipyard.TileSeq._
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO: Why do we need this?
|
* TODO: Why do we need this?
|
||||||
@@ -59,7 +61,11 @@ class WithSPIFlash(size: BigInt = 0x10000000) extends Config((site, here, up) =>
|
|||||||
SPIFlashParams(rAddress = 0x10040000, fAddress = 0x20000000, fSize = size))
|
SPIFlashParams(rAddress = 0x10040000, fAddress = 0x20000000, fSize = size))
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithL2TLBs(entries: Int) extends GenericCoreConfig(Map("core" -> Map("nL2TLBEntries" -> entries)))
|
class WithL2TLBs(entries: Int) extends Config((site, here, up) => {
|
||||||
|
case TilesKey(tilesKey) => up(tilesKey) tileMap (tile => tile.copy(
|
||||||
|
core = tile.core.copy(nL2TLBEntries = entries)
|
||||||
|
))
|
||||||
|
})
|
||||||
|
|
||||||
class WithTracegenSystem extends Config((site, here, up) => {
|
class WithTracegenSystem extends Config((site, here, up) => {
|
||||||
case BuildSystem => (p: Parameters) => LazyModule(new tracegen.TraceGenSystem()(p))
|
case BuildSystem => (p: Parameters) => LazyModule(new tracegen.TraceGenSystem()(p))
|
||||||
@@ -140,9 +146,8 @@ class WithControlCore extends Config((site, here, up) => {
|
|||||||
case MaxHartIdBits => log2Up(up(RocketTilesKey, site).size + up(BoomTilesKey, site).size + 1)
|
case MaxHartIdBits => log2Up(up(RocketTilesKey, site).size + up(BoomTilesKey, site).size + 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithTraceIO extends GenericCoreConfig(
|
class WithTraceIO extends Config((site, here, up) => {
|
||||||
newValues = Map("trace" -> true),
|
case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy(trace = true))
|
||||||
specialCase = (site, here, up) => {
|
case ArianeTilesKey => up(ArianeTilesKey) map (tile => tile.copy(trace = true))
|
||||||
case TracePortKey => Some(TracePortParams())
|
case TracePortKey => Some(TracePortParams())
|
||||||
}
|
})
|
||||||
)
|
|
||||||
@@ -18,8 +18,10 @@ import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams}
|
|||||||
// Base trait for all third-party core entries
|
// Base trait for all third-party core entries
|
||||||
sealed trait CoreEntryBase {
|
sealed trait CoreEntryBase {
|
||||||
val name: String
|
val name: String
|
||||||
|
|
||||||
|
def keyEqual(key: Any): Boolean
|
||||||
def tileParamsLookup(implicit p: Parameters): Seq[TileParams]
|
def tileParamsLookup(implicit p: Parameters): Seq[TileParams]
|
||||||
def updateWithFilter(view: View, p: Any => Boolean): PartialFunction[Any, Map[String, Any] => Any]
|
|
||||||
def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => Seq[RocketCrossingParams], logicalTreeNode: LogicalTreeNode)
|
def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => Seq[RocketCrossingParams], logicalTreeNode: LogicalTreeNode)
|
||||||
(implicit p: Parameters, valName: ValName): Seq[(TileParams, RocketCrossingParams, () => BaseTile)]
|
(implicit p: Parameters, valName: ValName): Seq[(TileParams, RocketCrossingParams, () => BaseTile)]
|
||||||
}
|
}
|
||||||
@@ -35,15 +37,11 @@ class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTi
|
|||||||
private val tileClass = mirror.runtimeClass(typeOf[TileT].typeSymbol.asClass)
|
private val tileClass = mirror.runtimeClass(typeOf[TileT].typeSymbol.asClass)
|
||||||
private val tileCtor = tileClass.getConstructors.filter(ctor => ctor.getParameterTypes()(4) == classOf[Parameters]).head
|
private val tileCtor = tileClass.getConstructors.filter(ctor => ctor.getParameterTypes()(4) == classOf[Parameters]).head
|
||||||
|
|
||||||
|
def keyEqual(key: Any) = key == tilesKey
|
||||||
|
|
||||||
// Tile parameter lookup using correct type
|
// Tile parameter lookup using correct type
|
||||||
def tileParamsLookup(implicit p: Parameters) = p(tilesKey)
|
def tileParamsLookup(implicit p: Parameters) = p(tilesKey)
|
||||||
|
|
||||||
// If this core meet the requirement given by p, update parameter fields in the map
|
|
||||||
def updateWithFilter(view: View, p: Any => Boolean): PartialFunction[Any, Map[String, Any] => Any] = {
|
|
||||||
case key if (key == tilesKey && p(tilesKey)) => newValues => view(tilesKey) map
|
|
||||||
(tile => CopyParam(tile, newValues))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instantiate a tile and zip it with its parameter info, used by subsystem
|
// Instantiate a tile and zip it with its parameter info, used by subsystem
|
||||||
def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => Seq[RocketCrossingParams], logicalTreeNode: LogicalTreeNode)
|
def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => Seq[RocketCrossingParams], logicalTreeNode: LogicalTreeNode)
|
||||||
(implicit p: Parameters, valName: ValName) = {
|
(implicit p: Parameters, valName: ValName) = {
|
||||||
|
|||||||
@@ -15,116 +15,165 @@ import freechips.rocketchip.tile._
|
|||||||
import boom.common.{BoomTile, BoomTilesKey, BoomCrossingKey, BoomTileParams}
|
import boom.common.{BoomTile, BoomTilesKey, BoomCrossingKey, BoomTileParams}
|
||||||
import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams}
|
import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams}
|
||||||
|
|
||||||
// Extractor object accompanied class
|
// Case class to change common parameters visible in the base traits. Some fields in the base traits may not be configurable as a
|
||||||
// This is used to check the convertibility for those wrapped in Option, since Option's type is erased at runtime.
|
// case class constructor parameter for some cores, and those field will be ignored when applied.
|
||||||
trait SubParameterBase {
|
case class GenericCoreParams(
|
||||||
def toProduct: Product
|
val bootFreqHz: BigInt,
|
||||||
def cast(p: Any): Any
|
val useVM: Boolean,
|
||||||
}
|
val useUser: Boolean,
|
||||||
final class SubParameter[T <: Product](param: T) extends SubParameterBase {
|
val useSupervisor: Boolean,
|
||||||
def toProduct: Product = param
|
val useDebug: Boolean,
|
||||||
def cast(p: Any) = p.asInstanceOf[T]
|
val useAtomics: Boolean,
|
||||||
|
val useAtomicsOnlyForIO: Boolean,
|
||||||
|
val useCompressed: Boolean,
|
||||||
|
override val useVector: Boolean,
|
||||||
|
val useSCIE: Boolean,
|
||||||
|
val useRVE: Boolean,
|
||||||
|
val mulDiv: Option[MulDivParams],
|
||||||
|
val fpu: Option[FPUParams],
|
||||||
|
val fetchWidth: Int,
|
||||||
|
val decodeWidth: Int,
|
||||||
|
val retireWidth: Int,
|
||||||
|
val instBits: Int,
|
||||||
|
val nLocalInterrupts: Int,
|
||||||
|
val nPMPs: Int,
|
||||||
|
val pmpGranularity: Int,
|
||||||
|
val nBreakpoints: Int,
|
||||||
|
val useBPWatch: Boolean,
|
||||||
|
val nPerfCounters: Int,
|
||||||
|
val haveBasicCounters: Boolean,
|
||||||
|
val haveFSDirty: Boolean,
|
||||||
|
val misaWritable: Boolean,
|
||||||
|
val haveCFlush: Boolean,
|
||||||
|
val nL2TLBEntries: Int,
|
||||||
|
val mtvecInit: Option[BigInt],
|
||||||
|
val mtvecWritable: Boolean,
|
||||||
|
// The original object
|
||||||
|
val _origin: CoreParams
|
||||||
|
) extends CoreParams {
|
||||||
|
def this(coreParams: CoreParams) = this(
|
||||||
|
bootFreqHz = coreParams.bootFreqHz,
|
||||||
|
useVM = coreParams.useVM,
|
||||||
|
useUser = coreParams.useUser,
|
||||||
|
useSupervisor = coreParams.useSupervisor,
|
||||||
|
useDebug = coreParams.useDebug,
|
||||||
|
useAtomics = coreParams.useAtomics,
|
||||||
|
useAtomicsOnlyForIO = coreParams.useAtomicsOnlyForIO,
|
||||||
|
useCompressed = coreParams.useCompressed,
|
||||||
|
useVector = coreParams.useVector,
|
||||||
|
useSCIE = coreParams.useSCIE,
|
||||||
|
useRVE = coreParams.useRVE,
|
||||||
|
mulDiv = coreParams.mulDiv,
|
||||||
|
fpu = coreParams.fpu,
|
||||||
|
fetchWidth = coreParams.fetchWidth,
|
||||||
|
decodeWidth = coreParams.decodeWidth,
|
||||||
|
retireWidth = coreParams.retireWidth,
|
||||||
|
instBits = coreParams.instBits,
|
||||||
|
nLocalInterrupts = coreParams.nLocalInterrupts,
|
||||||
|
nPMPs = coreParams.nPMPs,
|
||||||
|
pmpGranularity = coreParams.pmpGranularity,
|
||||||
|
nBreakpoints = coreParams.nBreakpoints,
|
||||||
|
useBPWatch = coreParams.useBPWatch,
|
||||||
|
nPerfCounters = coreParams.nPerfCounters,
|
||||||
|
haveBasicCounters = coreParams.haveBasicCounters,
|
||||||
|
haveFSDirty = coreParams.haveFSDirty,
|
||||||
|
misaWritable = coreParams.misaWritable,
|
||||||
|
haveCFlush = coreParams.haveCFlush,
|
||||||
|
nL2TLBEntries = coreParams.nL2TLBEntries,
|
||||||
|
mtvecInit = coreParams.mtvecInit,
|
||||||
|
mtvecWritable = coreParams.mtvecWritable,
|
||||||
|
|
||||||
|
_origin = coreParams
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reflection Info of this class
|
||||||
|
val fieldNames = (this.getClass.getDeclaredFields map (f => f.getName)).init
|
||||||
|
|
||||||
|
// Convert back to core-specific tile
|
||||||
|
def convert: CoreParams = {
|
||||||
|
// Reflection of target class
|
||||||
|
val paramClass = _origin.getClass
|
||||||
|
val paramNames = (paramClass.getDeclaredFields map (f => f.getName))
|
||||||
|
val paramCtor = paramClass.getConstructors.head
|
||||||
|
|
||||||
|
// Build a list of parameter in the original parameter class
|
||||||
|
val nameDict = paramNames.zipWithIndex.toMap
|
||||||
|
val indexList = fieldNames map (n => nameDict.get(n))
|
||||||
|
val fieldList = this.productIterator.toList.init
|
||||||
|
val fieldDict = ((indexList zip fieldList) collect { case (Some(i), v) => (i, v) }).toMap
|
||||||
|
val newValues = _origin.asInstanceOf[Product].productIterator.toList.zipWithIndex map
|
||||||
|
{ case (v, i) => (if (fieldDict contains i) fieldDict(i) else v).asInstanceOf[AnyRef] }
|
||||||
|
|
||||||
|
paramCtor.newInstance(newValues:_*).asInstanceOf[CoreParams]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement abstract function as placeholder
|
||||||
|
def lrscCycles: Int = _origin.lrscCycles
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extractor object that help identify the parameter case classes.
|
case class GenericTileParams(
|
||||||
// Add your customized nested parameter classes (or their commom base classes) here.
|
val core: GenericCoreParams,
|
||||||
object CustomizedSubParameter {
|
val icache: Option[ICacheParams],
|
||||||
def unapply(param: Product): Option[Product] = param match {
|
val dcache: Option[DCacheParams],
|
||||||
// ADD YOUR NESTED PARAMETER CLASS HERE, in the format shown below in SubParameter
|
val btb: Option[BTBParams],
|
||||||
case _ => None
|
val hartId: Int,
|
||||||
|
val beuAddr: Option[BigInt],
|
||||||
|
val blockerCtrlAddr: Option[BigInt],
|
||||||
|
val name: Option[String],
|
||||||
|
// The original object
|
||||||
|
val _origin: TileParams
|
||||||
|
) extends TileParams {
|
||||||
|
// Copy constructor to build the params
|
||||||
|
def this(tileParams: TileParams) = this(
|
||||||
|
core = new GenericCoreParams(tileParams.core),
|
||||||
|
icache = tileParams.icache,
|
||||||
|
dcache = tileParams.dcache,
|
||||||
|
btb = tileParams.btb,
|
||||||
|
hartId = tileParams.hartId,
|
||||||
|
beuAddr = tileParams.beuAddr,
|
||||||
|
blockerCtrlAddr = tileParams.blockerCtrlAddr,
|
||||||
|
name = tileParams.name,
|
||||||
|
|
||||||
|
_origin = tileParams
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reflection Info of this class
|
||||||
|
val fieldNames = (this.getClass.getDeclaredFields map (f => f.getName)).init
|
||||||
|
|
||||||
|
// Convert back to core-specific tile
|
||||||
|
def convert: TileParams = {
|
||||||
|
// Reflection of target class
|
||||||
|
val paramClass = _origin.getClass
|
||||||
|
val paramNames = (paramClass.getDeclaredFields map (f => f.getName))
|
||||||
|
val paramCtor = paramClass.getConstructors.head
|
||||||
|
|
||||||
|
// Build a list of parameter in the original parameter class
|
||||||
|
val nameDict = paramNames.zipWithIndex.toMap
|
||||||
|
val indexList = fieldNames map (n => nameDict.get(n))
|
||||||
|
val fieldList = this.productIterator.toList.updated(0, core.convert).init
|
||||||
|
val fieldDict = ((indexList zip fieldList) collect { case (Some(i), v) => (i, v) }).toMap
|
||||||
|
val newValues = _origin.asInstanceOf[Product].productIterator.toList.zipWithIndex map
|
||||||
|
{ case (v, i) => (if (fieldDict contains i) fieldDict(i) else v).asInstanceOf[AnyRef] }
|
||||||
|
|
||||||
|
paramCtor.newInstance(newValues:_*).asInstanceOf[TileParams]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standard nested
|
// Extractor to capture TilesKey
|
||||||
object SubParameter {
|
object TilesKey {
|
||||||
def unapply(param: Product): Option[SubParameterBase] = param match {
|
def unapply(key: Any): Option[Field[Seq[_]]] =
|
||||||
case p: TileParams => Some(new SubParameter(p))
|
if ((CoreManager.cores filter (core => core.keyEqual(key))).size != 0) Some(key.asInstanceOf[Field[Seq[_]]]) else None
|
||||||
case p: CoreParams => Some(new SubParameter(p))
|
|
||||||
case p: ICacheParams => Some(new SubParameter(p))
|
|
||||||
case p: DCacheParams => Some(new SubParameter(p))
|
|
||||||
case p: MulDivParams => Some(new SubParameter(p))
|
|
||||||
case p: FPUParams => Some(new SubParameter(p))
|
|
||||||
case p: BTBParams => Some(new SubParameter(p))
|
|
||||||
case p: BHTParams => Some(new SubParameter(p))
|
|
||||||
case CustomizedSubParameter(p) => Some(new SubParameter(p))
|
|
||||||
case _ => None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic update helper for Parameter class.
|
class TileSeq(list: Seq[Any]) {
|
||||||
class CopyParam(paramExtracted: SubParameterBase) {
|
def tileMap(f: GenericTileParams => GenericTileParams): Seq[TileParams] = {
|
||||||
// Constructor for corresponding TileParams
|
// If this is not an unpacked tile key, simply throw a type exception
|
||||||
private val param: Product = paramExtracted.toProduct
|
// Static type checking is not possible when this class is used with TilesKey extractor
|
||||||
private val paramClass = param.getClass
|
val tileList = list.asInstanceOf[Seq[TileParams]]
|
||||||
private val paramNames = (paramClass.getDeclaredFields map (f => f.getName))
|
|
||||||
private val paramCtor = paramClass.getConstructors.head
|
|
||||||
|
|
||||||
// Function to build value entry
|
tileList map (tileParams => f(new GenericTileParams(tileParams)).convert)
|
||||||
private def buildEntry(value: Any): Any = value match {
|
|
||||||
case Some(v) => Some(buildEntry(v))
|
|
||||||
case SubParameter(p) => new CopyParam(p)
|
|
||||||
case v => v
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value of the case class
|
|
||||||
private val entries = param.productIterator.toList map (v => buildEntry(v))
|
|
||||||
|
|
||||||
// Update one value entry
|
|
||||||
private def updateEntry(entry: Any, newValue: Any): Any = entry match {
|
|
||||||
case Some(e) => newValue match {
|
|
||||||
case Some(v) => Some(updateEntry(e, v))
|
|
||||||
case None => None
|
|
||||||
}
|
|
||||||
case e: CopyParam => newValue match {
|
|
||||||
case newValues: Map[String, Any] => e.update(newValues)
|
|
||||||
case v => paramExtracted.cast(v)
|
|
||||||
}
|
|
||||||
// Use cast() to check the type of the new value. Here I assume that all entries in the parameters class are simple values
|
|
||||||
// (like Int, BigInt and String), which are all final. This may breaks if a polymorphic type is added (unless it's a case
|
|
||||||
// class and registered above).
|
|
||||||
case e => e.getClass.cast(newValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the entire parameter object.
|
|
||||||
def update(newValues: Map[String, Any]): Any = {
|
|
||||||
val filteredValues = newValues.filter({ case (key, value) => paramNames contains key })
|
|
||||||
val newValueList = entries.zipWithIndex map {
|
|
||||||
case (value, i) if newValues contains paramNames(i) => updateEntry(value, filteredValues(paramNames(i))).asInstanceOf[AnyRef]
|
|
||||||
case (value, i) => (value match {
|
|
||||||
case Some(v) => v match {
|
|
||||||
case copyParam: CopyParam => Some(copyParam.param)
|
|
||||||
case _ => Some(v)
|
|
||||||
}
|
|
||||||
case copyParam: CopyParam => copyParam.param
|
|
||||||
case _ => value
|
|
||||||
}).asInstanceOf[AnyRef]
|
|
||||||
}
|
|
||||||
paramCtor.newInstance(newValueList:_*)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
object TileSeq {
|
||||||
object CopyParam {
|
implicit def convertSeq(s: Seq[Any]) = new TileSeq(s)
|
||||||
def apply(param: Product, newValues: Map[String, Any]): Any = param match {
|
|
||||||
case SubParameter(p) => new CopyParam(p).update(newValues)
|
|
||||||
case _ => throw new Exception("param is not a known Parameter type: add your custom parameter class to GenericCoreConfig.scala to fix it")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change parameters for all registered cores in CoreManager.
|
|
||||||
class GenericCoreConfig (
|
|
||||||
// Key-value pairs to be updated (keys are the name of fields). Any field not in a core's parameters will be ignored.
|
|
||||||
// If a field is a case class containing parameters (or an Option of that), you can use another Map containing the key-value pairs to
|
|
||||||
// update that case class. Using a new case class instance as the value is also acceptable.
|
|
||||||
// If a field is an Option, you should wrap your new values with Some() or set it to None. This also applies when a new case
|
|
||||||
// class instance is used for an Option field.
|
|
||||||
newValues: Map[String, Any],
|
|
||||||
// Function for filtering the list of TilesKey.
|
|
||||||
filterFunc: Any => Boolean = (_ => true),
|
|
||||||
// Handling special cases where partial function input is not a TilesKey.
|
|
||||||
specialCase: (View, View, View) => PartialFunction[Any, Any] = ((_, _, _) => Map.empty)
|
|
||||||
) extends Config((site, here, up) =>
|
|
||||||
scala.Function.unlift((key: Any) => {
|
|
||||||
val tiles = CoreManager.cores flatMap (core => core.updateWithFilter(up, filterFunc).lift(key))
|
|
||||||
if (tiles.size == 0) None else Some(tiles(0)(newValues))
|
|
||||||
}).orElse(specialCase(site, here, up))
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user