Revised generic config
This commit is contained in:
@@ -59,14 +59,7 @@ 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 Config((site, here, up) => {
|
class WithL2TLBs(entries: Int) extends GenericCoreConfig(Map("core" -> Map("nL2TLBEntries" -> entries)))
|
||||||
case RocketTilesKey => up(RocketTilesKey) map (tile => tile.copy(
|
|
||||||
core = tile.core.copy(nL2TLBEntries = entries)
|
|
||||||
))
|
|
||||||
case BoomTilesKey => up(BoomTilesKey) map (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))
|
||||||
@@ -148,7 +141,7 @@ class WithControlCore extends Config((site, here, up) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithTraceIO extends GenericCoreConfig(
|
class WithTraceIO extends GenericCoreConfig(
|
||||||
properties = Map("trace" -> true),
|
newValues = Map("trace" -> true),
|
||||||
specialCase = (site, here, up) => {
|
specialCase = (site, here, up) => {
|
||||||
case TracePortKey => Some(TracePortParams())
|
case TracePortKey => Some(TracePortParams())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ 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}
|
||||||
import chipsalliance.rocketchip.config.Parameters
|
|
||||||
|
|
||||||
// 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
|
||||||
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 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)
|
||||||
@@ -26,36 +26,22 @@ sealed trait CoreEntryBase {
|
|||||||
|
|
||||||
// Implementation of third-party core entries
|
// Implementation of third-party core entries
|
||||||
class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTile : TypeTag](
|
class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTile : TypeTag](
|
||||||
|
val name: String,
|
||||||
tilesKey: Field[Seq[TileParamsT]],
|
tilesKey: Field[Seq[TileParamsT]],
|
||||||
crossingKey: Field[Seq[RocketCrossingParams]]
|
crossingKey: Field[Seq[RocketCrossingParams]]
|
||||||
) extends CoreEntryBase {
|
) extends CoreEntryBase {
|
||||||
// Use reflection to get the parameter's constructor
|
|
||||||
private val mirror = runtimeMirror(getClass.getClassLoader)
|
|
||||||
private val paramClass = mirror.runtimeClass(typeOf[TileParamsT].typeSymbol.asClass)
|
|
||||||
private val paramNames = (paramClass.getDeclaredFields map (f => f.getName)).zipWithIndex.toMap
|
|
||||||
private val paramCtor = paramClass.getConstructors.head
|
|
||||||
|
|
||||||
// Use reflection to get the tile's constructor
|
// Use reflection to get the tile's constructor
|
||||||
|
private val mirror = runtimeMirror(getClass.getClassLoader)
|
||||||
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
|
||||||
|
|
||||||
// Version of case class' copy() using reflection, where fields to be updated are passed by a map
|
|
||||||
def copyTileParam(tileParam: TileParamsT, properties: Map[String, Any]) = {
|
|
||||||
val values = tileParam.productIterator.toList
|
|
||||||
//val filteredProperties = properties filter { case (key, value) => paramNames contains key }
|
|
||||||
val indexedProperties = /*filteredProperties*/ properties map { case (key, value) => (paramNames(key), value) }
|
|
||||||
val newValues = (0 until values.size) map
|
|
||||||
(i => (if (indexedProperties contains i) indexedProperties(i) else values(i)).asInstanceOf[AnyRef])
|
|
||||||
paramCtor.newInstance(newValues:_*)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
// 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] = {
|
def updateWithFilter(view: View, p: Any => Boolean): PartialFunction[Any, Map[String, Any] => Any] = {
|
||||||
case key if (key == tilesKey && p(tilesKey)) => properties => view(tilesKey) map
|
case key if (key == tilesKey && p(tilesKey)) => newValues => view(tilesKey) map
|
||||||
(tile => copyTileParam(tile, properties))
|
(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
|
||||||
@@ -73,27 +59,12 @@ class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic Core Config - change properties in the given map
|
|
||||||
class GenericCoreConfig(
|
|
||||||
// Parameter properties to be changed and their new values. Any field not in a core's parameters will be ignored.
|
|
||||||
properties: 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 map (tile => tile(properties)))
|
|
||||||
}).orElse(specialCase(site, here, up))
|
|
||||||
)
|
|
||||||
|
|
||||||
// A list of all cores.
|
// A list of all cores.
|
||||||
object CoreManager {
|
object CoreManager {
|
||||||
val cores: List[CoreEntryBase] = List(
|
val cores: List[CoreEntryBase] = List(
|
||||||
// TODO ADD YOUR CORE DEFINITION HERE
|
// TODO ADD YOUR CORE DEFINITION HERE; note that the
|
||||||
new CoreEntry[RocketTileParams, RocketTile](RocketTilesKey, RocketCrossingKey),
|
new CoreEntry[RocketTileParams, RocketTile]("Rocket", RocketTilesKey, RocketCrossingKey),
|
||||||
new CoreEntry[BoomTileParams, BoomTile](BoomTilesKey, BoomCrossingKey),
|
new CoreEntry[BoomTileParams, BoomTile]("Boom", BoomTilesKey, BoomCrossingKey),
|
||||||
new CoreEntry[ArianeTileParams, ArianeTile](ArianeTilesKey, ArianeCrossingKey)
|
new CoreEntry[ArianeTileParams, ArianeTile]("Ariane", ArianeTilesKey, ArianeCrossingKey)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
133
generators/chipyard/src/main/scala/GenericCoreConfig.scala
Normal file
133
generators/chipyard/src/main/scala/GenericCoreConfig.scala
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
package chipyard
|
||||||
|
|
||||||
|
import scala.reflect.ClassTag
|
||||||
|
import scala.reflect.runtime.universe._
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
|
||||||
|
import freechips.rocketchip.config.{Parameters, Config, Field, View}
|
||||||
|
import freechips.rocketchip.subsystem.{SystemBusKey, RocketTilesKey, RocketCrossingParams, RocketCrossingKey}
|
||||||
|
import freechips.rocketchip.diplomacy.{LazyModule, ClockCrossingType, ValName}
|
||||||
|
import freechips.rocketchip.diplomaticobjectmodel.logicaltree.LogicalTreeNode
|
||||||
|
import freechips.rocketchip.rocket._
|
||||||
|
import freechips.rocketchip.tile._
|
||||||
|
|
||||||
|
import boom.common.{BoomTile, BoomTilesKey, BoomCrossingKey, BoomTileParams}
|
||||||
|
import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams}
|
||||||
|
|
||||||
|
// Extractor object accompanied class
|
||||||
|
// This is used to check the convertibility for those wrapped in Option, since Option's type is erased at runtime.
|
||||||
|
trait SubParameterBase {
|
||||||
|
def toProduct: Product
|
||||||
|
def cast(p: Any): Any
|
||||||
|
}
|
||||||
|
final class SubParameter[T <: Product](param: T) extends SubParameterBase {
|
||||||
|
def toProduct: Product = param
|
||||||
|
def cast(p: Any) = p.asInstanceOf[T]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extractor object that help identify the parameter case classes.
|
||||||
|
// Add your customized nested parameter classes (or their commom base classes) here.
|
||||||
|
object CustomizedSubParameter {
|
||||||
|
def unapply(param: Product): Option[Product] = param match {
|
||||||
|
// ADD YOUR NESTED PARAMETER CLASS HERE, in the format shown below in SubParameter
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard nested
|
||||||
|
object SubParameter {
|
||||||
|
def unapply(param: Product): Option[SubParameterBase] = param match {
|
||||||
|
case p: TileParams => Some(new SubParameter(p))
|
||||||
|
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 CopyParam(paramExtracted: SubParameterBase) {
|
||||||
|
// Constructor for corresponding TileParams
|
||||||
|
private val param: Product = paramExtracted.toProduct
|
||||||
|
private val paramClass = param.getClass
|
||||||
|
private val paramNames = (paramClass.getDeclaredFields map (f => f.getName))
|
||||||
|
private val paramCtor = paramClass.getConstructors.head
|
||||||
|
|
||||||
|
// Function to build value entry
|
||||||
|
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:_*)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For debug purpose - print what's in the object
|
||||||
|
override def toString(): String = paramClass.getSimpleName + "(" + entries.toString + ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
object CopyParam {
|
||||||
|
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))
|
||||||
|
)
|
||||||
@@ -33,8 +33,15 @@ class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipS
|
|||||||
val suiteHelper = new TestSuiteHelper
|
val suiteHelper = new TestSuiteHelper
|
||||||
// Use Xlen as a proxy for detecting if we are a processor-like target
|
// Use Xlen as a proxy for detecting if we are a processor-like target
|
||||||
// The underlying test suites expect this field to be defined
|
// The underlying test suites expect this field to be defined
|
||||||
if (p.lift(XLen).nonEmpty)
|
if (p.lift(XLen).nonEmpty) {
|
||||||
CoreManager.cores map (core => suiteHelper.addGenericTestSuites(core.tileParamsLookup))
|
val customizedSuite: Map[String, TestSuiteHelper => Unit] = Map(
|
||||||
|
// DEFINE CUSTOMIZED TEST HERE, using format ({Core name} -> _.{Test suite builder in TestSuiteHelper})
|
||||||
|
)
|
||||||
|
CoreManager.cores map (core => customizedSuite.get(core.name) match {
|
||||||
|
case Some(builder) => builder(suiteHelper)
|
||||||
|
case None => suiteHelper.addGenericTestSuites(core.tileParamsLookup)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// if hwacha parameter exists then generate its tests
|
// if hwacha parameter exists then generate its tests
|
||||||
// TODO: find a more elegant way to do this. either through
|
// TODO: find a more elegant way to do this. either through
|
||||||
|
|||||||
Reference in New Issue
Block a user