From ff583e9e1f5c136d65f510c35584fe2ffff46815 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Wed, 20 May 2020 15:44:07 -0700 Subject: [PATCH 01/20] first attempt decoupling --- .../src/main/scala/ConfigFragments.scala | 23 +++++++++--- .../src/main/scala/CoreRegistrar.scala | 37 +++++++++++++++++++ .../chipyard/src/main/scala/Subsystem.scala | 33 ++++++++++------- .../chipyard/src/main/scala/TestSuites.scala | 11 +++--- .../scala/stage/phases/AddDefaultTests.scala | 4 +- 5 files changed, 82 insertions(+), 26 deletions(-) create mode 100644 generators/chipyard/src/main/scala/CoreRegistrar.scala diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index 72eaa414..3db4f326 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -3,7 +3,7 @@ package chipyard.config import chisel3._ import chisel3.util.{log2Up} -import freechips.rocketchip.config.{Field, Parameters, Config} +import freechips.rocketchip.config.{Field, Parameters, Config, View} import freechips.rocketchip.subsystem.{SystemBusKey, RocketTilesKey, WithRoccExample, WithNMemoryChannels, WithNBigCores, WithRV32, CacheBlockBytes} import freechips.rocketchip.diplomacy.{LazyModule, ValName} import freechips.rocketchip.devices.tilelink.BootROMParams @@ -13,7 +13,6 @@ import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams import freechips.rocketchip.util.{AsyncResetReg} import boom.common.{BoomTilesKey} -import ariane.{ArianeTilesKey} import testchipip._ import hwacha.{Hwacha} @@ -23,6 +22,7 @@ import sifive.blocks.devices.uart._ import sifive.blocks.devices.spi._ import chipyard.{BuildTop, BuildSystem} +import chipyard.{CoreRegistrar, CoreRegisterEntryBase} /** * TODO: Why do we need this? @@ -147,8 +147,21 @@ class WithControlCore extends Config((site, here, up) => { case MaxHartIdBits => log2Up(up(RocketTilesKey, site).size + up(BoomTilesKey, site).size + 1) }) +trait TraceIOMatch { + this: CoreRegisterEntryBase => + val matchTile: (View, View, View) => PartialFunction[Field[Seq[TileParams]],Any] = ((site, here, up) => { + // TODO: XXX What's the "tile" here? + case tilesKey => up(tilesKey) map (tile => tile.copy(trace = true)) + }) +} + class WithTraceIO extends Config((site, here, up) => { - case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy(trace = true)) - case ArianeTilesKey => up(ArianeTilesKey) map (tile => tile.copy(trace = true)) - case TracePortKey => Some(TracePortParams()) + val coreMatch = (coreList: List[CoreRegisterEntryBase]) => coreList match { + case coreEntry :: tail => coreEntry.matchTile(site, here, up) orElse coreMatch(tail) + case Nil => { + case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy(trace = true)) + case TracePortKey => Some(TracePortParams()) + } + } + coreMatch(CoreRegistrar.cores) }) diff --git a/generators/chipyard/src/main/scala/CoreRegistrar.scala b/generators/chipyard/src/main/scala/CoreRegistrar.scala new file mode 100644 index 00000000..a0b1625c --- /dev/null +++ b/generators/chipyard/src/main/scala/CoreRegistrar.scala @@ -0,0 +1,37 @@ +package chipyard + +import chisel3._ + +import freechips.rocketchip.config.{Parameters, Config, Field} +import freechips.rocketchip.subsystem.{SystemBusKey, RocketTilesKey, RocketCrossingParams} +import freechips.rocketchip.devices.tilelink.{BootROMParams} +import freechips.rocketchip.diplomacy.{SynchronousCrossing, AsynchronousCrossing, RationalCrossing} +import freechips.rocketchip.rocket._ +import freechips.rocketchip.tile._ + +import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams} + +import chipyard.config.TraceIOMatch + +// Third-party core entries +sealed trait CoreRegisterEntryBase { + type Tile + type TitleParams + def tilesKey: Field[Seq[TitleParams]] + def crossingKey: Field[Seq[RocketCrossingParams]] +} + +class CoreRegisterEntry[TileT <: BaseTile, TileParamsT <: CoreParams](tk: Field[Seq[TileParamsT]], ck: Field[Seq[RocketCrossingParams]]) + extends CoreRegisterEntryBase with TraceIOMatch { + type Tile = TileT + type TileParams = TileParamsT + def tilesKey = tk + def crossingKey = ck +} + +object CoreRegistrar { + val cores: List[CoreRegisterEntryBase] = List( + // ADD YOUR CORE DEFINITION HERE + new CoreRegisterEntry[ArianeTile, ArianeTileParams](ArianeTilesKey, ArianeCrossingKey) + ) +} \ No newline at end of file diff --git a/generators/chipyard/src/main/scala/Subsystem.scala b/generators/chipyard/src/main/scala/Subsystem.scala index 99c31472..fcb58fc4 100644 --- a/generators/chipyard/src/main/scala/Subsystem.scala +++ b/generators/chipyard/src/main/scala/Subsystem.scala @@ -22,7 +22,6 @@ import freechips.rocketchip.subsystem._ import freechips.rocketchip.amba.axi4._ import boom.common.{BoomTile, BoomTilesKey, BoomCrossingKey, BoomTileParams} -import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams} import testchipip.{DromajoHelper} @@ -36,14 +35,17 @@ trait HasChipyardTiles extends HasTiles protected val rocketTileParams = p(RocketTilesKey) protected val boomTileParams = p(BoomTilesKey) - protected val arianeTileParams = p(ArianeTilesKey) + protected val coreTileParams = CoreRegistrar.cores map (coreType => p(coreType.tilesKey)) // crossing can either be per tile or global (aka only 1 crossing specified) private val rocketCrossings = perTileOrGlobalSetting(p(RocketCrossingKey), rocketTileParams.size) private val boomCrossings = perTileOrGlobalSetting(p(BoomCrossingKey), boomTileParams.size) - private val arianeCrossings = perTileOrGlobalSetting(p(ArianeCrossingKey), arianeTileParams.size) + private val coreCrossings = (CoreRegistrar.cores zip coreTileParams) map ((coreType, tileParams) => + perTileOrGlobalSetting(p(coreType.crossingKey), tileParams.size)) - val allTilesInfo = (rocketTileParams ++ boomTileParams ++ arianeTileParams) zip (rocketCrossings ++ boomCrossings ++ arianeCrossings) + // TODO: XXX The "tiles" below scan for hartId but it is not in CoreParams. Should that be added in later + // revision, or I have to use reflection to get that parameter? + val allTilesInfo = (rocketTileParams ++ boomTileParams ++ coreTileParams) zip (rocketCrossings ++ boomCrossings ++ coreCrossings) // Make a tile and wire its nodes into the system, // according to the specified type of clock crossing. @@ -55,17 +57,22 @@ trait HasChipyardTiles extends HasTiles val tiles = allTilesInfo.sortWith(_._1.hartId < _._1.hartId).map { case (param, crossing) => { - val tile = param match { - case r: RocketTileParams => { - LazyModule(new RocketTile(r, crossing, PriorityMuxHartIdFromSeq(rocketTileParams), logicalTreeNode)) - } - case b: BoomTileParams => { - LazyModule(new BoomTile(b, crossing, PriorityMuxHartIdFromSeq(boomTileParams), logicalTreeNode)) - } - case a: ArianeTileParams => { - LazyModule(new ArianeTile(a, crossing, PriorityMuxHartIdFromSeq(arianeTileParams), logicalTreeNode)) + val tileMatch = coreAndtileParamsList => { + case (coreType, tileParams) :: tail => (param => { + case a: coreType.TileParams => { + LazyModule(new coreType.Tile(a, crossing, PriorityMuxHartIdFromSeq(tileParams), logicalTreeNode)) + } + }) orElse tileMatch(tail) + case Nil => param => { + case r: RocketTileParams => { + LazyModule(new RocketTile(r, crossing, PriorityMuxHartIdFromSeq(rocketTileParams), logicalTreeNode)) + } + case b: BoomTileParams => { + LazyModule(new BoomTile(b, crossing, PriorityMuxHartIdFromSeq(boomTileParams), logicalTreeNode)) + } } } + val tile = tileMatch(CoreRegistrar.cores zip coreTileParams) connectMasterPortsToSBus(tile, crossing) connectSlavePortsToCBus(tile, crossing) connectInterrupts(tile, debugOpt, clintOpt, plicOpt) diff --git a/generators/chipyard/src/main/scala/TestSuites.scala b/generators/chipyard/src/main/scala/TestSuites.scala index 9fdef05a..f90e3d23 100644 --- a/generators/chipyard/src/main/scala/TestSuites.scala +++ b/generators/chipyard/src/main/scala/TestSuites.scala @@ -3,12 +3,11 @@ package chipyard import scala.collection.mutable.{LinkedHashSet} import freechips.rocketchip.subsystem.{RocketTilesKey} -import freechips.rocketchip.tile.{XLen} -import freechips.rocketchip.config.{Parameters} +import freechips.rocketchip.tile.{XLen, CoreParams} +import freechips.rocketchip.config.{Parameters, Field} import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite, RocketTestSuite} import boom.common.{BoomTilesKey} -import ariane.{ArianeTilesKey} /** * A set of pre-chosen regression tests @@ -144,11 +143,11 @@ class TestSuiteHelper } /** - * Add Ariane tests (asm, bmark, regression) + * Add third-party core (including Ariane) tests (asm, bmark, regression) */ - def addArianeTestSuites(implicit p: Parameters) = { + def addThirdPartyTestSuites[TileParams <: CoreParams](tilesKey: Field[Seq[TileParams]])(implicit p: Parameters) = { val xlen = p(XLen) - p(ArianeTilesKey).find(_.hartId == 0).map { tileParams => + p(tilesKey).find(_.hartId == 0).map { tileParams => val coreParams = tileParams.core val vm = coreParams.useVM val env = if (vm) List("p","v") else List("p") diff --git a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala index fce5d432..3d367ffa 100644 --- a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala +++ b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala @@ -17,7 +17,7 @@ import freechips.rocketchip.stage.phases.{RocketTestSuiteAnnotation} import freechips.rocketchip.system.{RocketTestSuite, TestGeneration} import freechips.rocketchip.util.HasRocketChipStageUtils -import chipyard.TestSuiteHelper +import chipyard.{TestSuiteHelper, CoreRegistrar} class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { // Make sure we run both after RocketChip's version of this phase, and Rocket Chip's annotation emission phase @@ -32,7 +32,7 @@ class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipS val suiteHelper = new TestSuiteHelper suiteHelper.addRocketTestSuites suiteHelper.addBoomTestSuites - suiteHelper.addArianeTestSuites + CoreRegistrar.cores map suiteHelper.addThirdPartyTestSuites(_.tilesKey) // if hwacha parameter exists then generate its tests // TODO: find a more elegant way to do this. either through From adb85c98caed9190abae7a927ee68fb61e5b4a33 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Thu, 21 May 2020 12:35:26 -0700 Subject: [PATCH 02/20] Some Revisions --- .../src/main/scala/ConfigFragments.scala | 21 +++++-------- .../src/main/scala/CoreRegistrar.scala | 31 ++++++++++++------- .../chipyard/src/main/scala/Subsystem.scala | 30 ++++++++---------- 3 files changed, 39 insertions(+), 43 deletions(-) diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index 3db4f326..6eca517f 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -147,21 +147,14 @@ class WithControlCore extends Config((site, here, up) => { case MaxHartIdBits => log2Up(up(RocketTilesKey, site).size + up(BoomTilesKey, site).size + 1) }) -trait TraceIOMatch { - this: CoreRegisterEntryBase => - val matchTile: (View, View, View) => PartialFunction[Field[Seq[TileParams]],Any] = ((site, here, up) => { - // TODO: XXX What's the "tile" here? - case tilesKey => up(tilesKey) map (tile => tile.copy(trace = true)) - }) -} - class WithTraceIO extends Config((site, here, up) => { - val coreMatch = (coreList: List[CoreRegisterEntryBase]) => coreList match { - case coreEntry :: tail => coreEntry.matchTile(site, here, up) orElse coreMatch(tail) - case Nil => { - case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy(trace = true)) - case TracePortKey => Some(TracePortParams()) + val coreMatch: List[CoreRegisterEntryBase] => PartialFunction[Any,Any] = + coreList => coreList match { + case coreEntry :: tail => coreEntry.enableTileTrace(site, here, up) orElse coreMatch(tail) + case Nil => { + case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy(trace = true)) + case TracePortKey => Some(TracePortParams()) + } } - } coreMatch(CoreRegistrar.cores) }) diff --git a/generators/chipyard/src/main/scala/CoreRegistrar.scala b/generators/chipyard/src/main/scala/CoreRegistrar.scala index a0b1625c..b1503361 100644 --- a/generators/chipyard/src/main/scala/CoreRegistrar.scala +++ b/generators/chipyard/src/main/scala/CoreRegistrar.scala @@ -2,36 +2,43 @@ package chipyard import chisel3._ -import freechips.rocketchip.config.{Parameters, Config, Field} +import freechips.rocketchip.config.{Parameters, Config, Field, View} import freechips.rocketchip.subsystem.{SystemBusKey, RocketTilesKey, RocketCrossingParams} -import freechips.rocketchip.devices.tilelink.{BootROMParams} -import freechips.rocketchip.diplomacy.{SynchronousCrossing, AsynchronousCrossing, RationalCrossing} +import freechips.rocketchip.diplomacy.LazyModule +import freechips.rocketchip.diplomaticobjectmodel.logicaltree.LogicalTreeNode import freechips.rocketchip.rocket._ import freechips.rocketchip.tile._ import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams} -import chipyard.config.TraceIOMatch - // Third-party core entries sealed trait CoreRegisterEntryBase { - type Tile - type TitleParams - def tilesKey: Field[Seq[TitleParams]] + type TileParams <: CoreParams + def tilesKey: Field[Seq[TileParams]] def crossingKey: Field[Seq[RocketCrossingParams]] + def enableTileTrace(site: View, here: View, up: View): PartialFunction[Any, Any] + def instantiateTile(param: TileParams, crossing: RocketCrossingParams, + logicalTreeNode: LogicalTreeNode, p: Parameters): Option[BaseTile] } -class CoreRegisterEntry[TileT <: BaseTile, TileParamsT <: CoreParams](tk: Field[Seq[TileParamsT]], ck: Field[Seq[RocketCrossingParams]]) - extends CoreRegisterEntryBase with TraceIOMatch { - type Tile = TileT +class CoreRegisterEntry[TileParamsT <: CoreParams, TileT <: BaseTile](tk: Field[Seq[TileParamsT]], ck: Field[Seq[RocketCrossingParams]], + tileInstantiator: (TileParamsT, RocketCrossingParams, LookupByHartIdImpl, LogicalTreeNode, Parameters) => TileT) extends CoreRegisterEntryBase { type TileParams = TileParamsT def tilesKey = tk def crossingKey = ck + def enableTileTrace(site: View, here: View, up: View): PartialFunction[Any, Any] = { + case in if in == tilesKey => up(this.tilesKey) map (tile => tile.copy(trace = true)) + } + def instantiateTile(param: TileParams, crossing: RocketCrossingParams, + logicalTreeNode: LogicalTreeNode, p: Parameters): Option[BaseTile] = param match { + case a: TileParams => Some(tileInstantiator(a, crossing, PriorityMuxHartIdFromSeq(p(tilesKey)), logicalTreeNode, p)) + case _ => None + } } object CoreRegistrar { val cores: List[CoreRegisterEntryBase] = List( // ADD YOUR CORE DEFINITION HERE - new CoreRegisterEntry[ArianeTile, ArianeTileParams](ArianeTilesKey, ArianeCrossingKey) + new CoreRegisterEntry[ArianeTileParams, ArianeTile](ArianeTilesKey, ArianeCrossingKey, ((a, b, c, d, p) => {new ArianeTile(a, b, c, d)})) ) } \ No newline at end of file diff --git a/generators/chipyard/src/main/scala/Subsystem.scala b/generators/chipyard/src/main/scala/Subsystem.scala index fcb58fc4..7b554d2a 100644 --- a/generators/chipyard/src/main/scala/Subsystem.scala +++ b/generators/chipyard/src/main/scala/Subsystem.scala @@ -40,12 +40,13 @@ trait HasChipyardTiles extends HasTiles // crossing can either be per tile or global (aka only 1 crossing specified) private val rocketCrossings = perTileOrGlobalSetting(p(RocketCrossingKey), rocketTileParams.size) private val boomCrossings = perTileOrGlobalSetting(p(BoomCrossingKey), boomTileParams.size) - private val coreCrossings = (CoreRegistrar.cores zip coreTileParams) map ((coreType, tileParams) => - perTileOrGlobalSetting(p(coreType.crossingKey), tileParams.size)) + private val coreCrossings = (CoreRegistrar.cores zip coreTileParams) map (_ match { + case (coreType, tileParams) => perTileOrGlobalSetting(p(coreType.crossingKey), tileParams.size) + }) // TODO: XXX The "tiles" below scan for hartId but it is not in CoreParams. Should that be added in later // revision, or I have to use reflection to get that parameter? - val allTilesInfo = (rocketTileParams ++ boomTileParams ++ coreTileParams) zip (rocketCrossings ++ boomCrossings ++ coreCrossings) + val allTilesInfo = (rocketTileParams ++ boomTileParams ++ coreTileParams.flatten) zip (rocketCrossings ++ boomCrossings ++ coreCrossings.flatten) // Make a tile and wire its nodes into the system, // according to the specified type of clock crossing. @@ -57,22 +58,17 @@ trait HasChipyardTiles extends HasTiles val tiles = allTilesInfo.sortWith(_._1.hartId < _._1.hartId).map { case (param, crossing) => { - val tileMatch = coreAndtileParamsList => { - case (coreType, tileParams) :: tail => (param => { - case a: coreType.TileParams => { - LazyModule(new coreType.Tile(a, crossing, PriorityMuxHartIdFromSeq(tileParams), logicalTreeNode)) - } - }) orElse tileMatch(tail) - case Nil => param => { - case r: RocketTileParams => { - LazyModule(new RocketTile(r, crossing, PriorityMuxHartIdFromSeq(rocketTileParams), logicalTreeNode)) - } - case b: BoomTileParams => { - LazyModule(new BoomTile(b, crossing, PriorityMuxHartIdFromSeq(boomTileParams), logicalTreeNode)) - } + val tile = param match { + case r: RocketTileParams => { + LazyModule(new RocketTile(r, crossing, PriorityMuxHartIdFromSeq(rocketTileParams), logicalTreeNode)) } + case b: BoomTileParams => { + LazyModule(new BoomTile(b, crossing, PriorityMuxHartIdFromSeq(boomTileParams), logicalTreeNode)) + } + case _ => LazyModule( + (CoreRegistrar.cores collect (core => core.instantiateTile(param, crossing, paramList, logicalTreeNode, p)).unlift()) (0) + ) } - val tile = tileMatch(CoreRegistrar.cores zip coreTileParams) connectMasterPortsToSBus(tile, crossing) connectSlavePortsToCBus(tile, crossing) connectInterrupts(tile, debugOpt, clintOpt, plicOpt) From 15c1f5adba5d6c56748573beaa32432a437338d4 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Mon, 25 May 2020 10:47:58 -0700 Subject: [PATCH 03/20] Sync works to my laptop --- .../src/main/scala/ConfigFragments.scala | 7 +++++ .../src/main/scala/CoreRegistrar.scala | 30 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index 6eca517f..cdf84327 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -23,6 +23,7 @@ import sifive.blocks.devices.spi._ import chipyard.{BuildTop, BuildSystem} import chipyard.{CoreRegistrar, CoreRegisterEntryBase} +import chipyard.hlist /** * TODO: Why do we need this? @@ -147,6 +148,12 @@ class WithControlCore extends Config((site, here, up) => { case MaxHartIdBits => log2Up(up(RocketTilesKey, site).size + up(BoomTilesKey, site).size + 1) }) +class WithTraceIOHMap extends ConfigHMap { + override def apply[I](v: I) = (site, here, up) => { + + } +} + class WithTraceIO extends Config((site, here, up) => { val coreMatch: List[CoreRegisterEntryBase] => PartialFunction[Any,Any] = coreList => coreList match { diff --git a/generators/chipyard/src/main/scala/CoreRegistrar.scala b/generators/chipyard/src/main/scala/CoreRegistrar.scala index b1503361..766172d1 100644 --- a/generators/chipyard/src/main/scala/CoreRegistrar.scala +++ b/generators/chipyard/src/main/scala/CoreRegistrar.scala @@ -1,5 +1,8 @@ package chipyard +import scala.reflect.ClassTag +import scala.reflect.runtime.universe._ + import chisel3._ import freechips.rocketchip.config.{Parameters, Config, Field, View} @@ -16,16 +19,27 @@ sealed trait CoreRegisterEntryBase { type TileParams <: CoreParams def tilesKey: Field[Seq[TileParams]] def crossingKey: Field[Seq[RocketCrossingParams]] + + def findTilesWithFilter(view: View, p: Any => View): PartialFunction[Any, Seq[AnyRef]] + def enableTileTrace(site: View, here: View, up: View): PartialFunction[Any, Any] def instantiateTile(param: TileParams, crossing: RocketCrossingParams, logicalTreeNode: LogicalTreeNode, p: Parameters): Option[BaseTile] } -class CoreRegisterEntry[TileParamsT <: CoreParams, TileT <: BaseTile](tk: Field[Seq[TileParamsT]], ck: Field[Seq[RocketCrossingParams]], - tileInstantiator: (TileParamsT, RocketCrossingParams, LookupByHartIdImpl, LogicalTreeNode, Parameters) => TileT) extends CoreRegisterEntryBase { +class CoreRegisterEntry[TileParamsT <: CoreParams, TileT <: BaseTile]( + tk: Field[Seq[TileParamsT]], + ck: Field[Seq[RocketCrossingParams]], + tileInstantiator: (TileParamsT, RocketCrossingParams, LookupByHartIdImpl, LogicalTreeNode, Parameters) => TileT +) extends CoreRegisterEntryBase { type TileParams = TileParamsT def tilesKey = tk def crossingKey = ck + + def findTilesWithFilter(view: View, p: Any => View) = { + case key if (key == tk && p(tk)) => view(tk) + } + def enableTileTrace(site: View, here: View, up: View): PartialFunction[Any, Any] = { case in if in == tilesKey => up(this.tilesKey) map (tile => tile.copy(trace = true)) } @@ -41,4 +55,14 @@ object CoreRegistrar { // ADD YOUR CORE DEFINITION HERE new CoreRegisterEntry[ArianeTileParams, ArianeTile](ArianeTilesKey, ArianeCrossingKey, ((a, b, c, d, p) => {new ArianeTile(a, b, c, d)})) ) -} \ No newline at end of file +} + +// Core Generic Config - change properties in the given map +class GenericConfig(properties: Map[String, Any], filterFunc: Any => Bool = (_ => true)) { + val configFunc: (View, View, View) => PartialFunction[Any, Any] = ((site, here, up) => key => { + val tiles = CoreRegistrar.cores flatMap _.findTilesWithFilter(up, filterFunc).lift(key) + if (tiles.size == 0) None else Some(tiles map (tile => { + val method = ClassTag(tile.getClass).member(TermName(methodName)).asMethod + })).unlift + }).unlift +} From c0bafa306c694764d3593bab8d4717023c434821 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Mon, 25 May 2020 13:22:28 -0700 Subject: [PATCH 04/20] Config Done --- .../src/main/scala/ConfigFragments.scala | 22 ++---- .../chipyard/src/main/scala/CoreManager.scala | 76 +++++++++++++++++++ .../src/main/scala/CoreRegistrar.scala | 68 ----------------- .../chipyard/src/main/scala/TestSuites.scala | 2 +- 4 files changed, 82 insertions(+), 86 deletions(-) create mode 100644 generators/chipyard/src/main/scala/CoreManager.scala delete mode 100644 generators/chipyard/src/main/scala/CoreRegistrar.scala diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index cdf84327..e87b833a 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -148,20 +148,8 @@ class WithControlCore extends Config((site, here, up) => { case MaxHartIdBits => log2Up(up(RocketTilesKey, site).size + up(BoomTilesKey, site).size + 1) }) -class WithTraceIOHMap extends ConfigHMap { - override def apply[I](v: I) = (site, here, up) => { - - } -} - -class WithTraceIO extends Config((site, here, up) => { - val coreMatch: List[CoreRegisterEntryBase] => PartialFunction[Any,Any] = - coreList => coreList match { - case coreEntry :: tail => coreEntry.enableTileTrace(site, here, up) orElse coreMatch(tail) - case Nil => { - case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy(trace = true)) - case TracePortKey => Some(TracePortParams()) - } - } - coreMatch(CoreRegistrar.cores) -}) +class WithTraceIO extends Config((site, here, up) => + GenericConfig(Map("trace" -> true)) (site, here, up) orElse { + case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy(trace = true)) + case TracePortKey => Some(TracePortParams()) + }) diff --git a/generators/chipyard/src/main/scala/CoreManager.scala b/generators/chipyard/src/main/scala/CoreManager.scala new file mode 100644 index 00000000..72c5dc85 --- /dev/null +++ b/generators/chipyard/src/main/scala/CoreManager.scala @@ -0,0 +1,76 @@ +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} +import freechips.rocketchip.diplomacy.LazyModule +import freechips.rocketchip.diplomaticobjectmodel.logicaltree.LogicalTreeNode +import freechips.rocketchip.rocket._ +import freechips.rocketchip.tile._ + +import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams} + +// Third-party core entries +sealed trait CoreEntryBase { + def updateWithFilter(view: View, p: Any => View): (Map[String, Any] => PartialFunction[Any, Seq[AnyRef]]) + + def instantiateTile(param: TileParams, crossing: RocketCrossingParams, + logicalTreeNode: LogicalTreeNode, p: Parameters): Option[BaseTile] +} + +class CoreEntry[TileParamsT <: CoreParams, TileT <: BaseTile]( + tk: Field[Seq[TileParamsT]], + ck: Field[Seq[RocketCrossingParams]] +) extends CoreEntryBase { + private val mirror = runtimeMirror(getClass.getClassLoader) + private val paramClass = mirror.runtimeClass(typeOf[TileParamsT].typeSymbol.asClass) + private val paramNames = Map((paramClass.getDeclaredFields map _.getName).zipWithIndex) + private val paramCtr = paramClass.getConstructors.head + + private val tileClass = mirror.runtimeClass(typeOf[TileT].typeSymbol.asClass) + private val tileCtr = paramClass.getConstructors.head + + // copy() function in + def copyTileParam(tileParam: AnyRef, properties: Map[String, Any]) = { + val values = foo.productIterator.toList + val indexedProperties = properties map (key => (paramNames(key), properties(key))) + val newValues = (0 until values.size) map + (i => if (indexedProperties contains i) indexedProperties(i) else values(i)) + paramCtr.newInstance(newValues:_*) + } + + def updateWithFilter(view: View, p: Any => View) = { + case key if (key == tk && p(tk)) => view(tk) map + (tile => properties => copyTileParam(tile, properties)) + } + + def instantiateTile(param: TileParams, crossing: RocketCrossingParams, + logicalTreeNode: LogicalTreeNode, p: Parameters): Option[BaseTile] = param match { + case a: TileParams => Some(tileCtr.newInstance(a, crossing, PriorityMuxHartIdFromSeq(p(tilesKey)), logicalTreeNode, p)) + case _ => None + } +} + +object CoreManager { + val cores: List[CoreEntryBase] = List( + // ADD YOUR CORE DEFINITION HERE + new CoreEntry[ArianeTileParams, ArianeTile](ArianeTilesKey, ArianeCrossingKey) + ) +} + +// Core Generic Config - change properties in the given map +class GenericConfig(properties: Map[String, Any], filterFunc: Any => Bool) { + val configFunc: (View, View, View) => PartialFunction[Any, Any] = ((site, here, up) => key => { + val tiles = CoreManager.cores flatMap _.updateWithFilter(up, filterFunc).lift(key) + if (tiles.size == 0) None else Some(tiles map _(properties)) + }).unlift +} + +object GenericConfig { + def apply(properties: Map[String, Any], filterFunc: Any => Bool = (_ => true)) = + new GenericConfig(properties, filterFunc).configFunc +} diff --git a/generators/chipyard/src/main/scala/CoreRegistrar.scala b/generators/chipyard/src/main/scala/CoreRegistrar.scala deleted file mode 100644 index 766172d1..00000000 --- a/generators/chipyard/src/main/scala/CoreRegistrar.scala +++ /dev/null @@ -1,68 +0,0 @@ -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} -import freechips.rocketchip.diplomacy.LazyModule -import freechips.rocketchip.diplomaticobjectmodel.logicaltree.LogicalTreeNode -import freechips.rocketchip.rocket._ -import freechips.rocketchip.tile._ - -import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams} - -// Third-party core entries -sealed trait CoreRegisterEntryBase { - type TileParams <: CoreParams - def tilesKey: Field[Seq[TileParams]] - def crossingKey: Field[Seq[RocketCrossingParams]] - - def findTilesWithFilter(view: View, p: Any => View): PartialFunction[Any, Seq[AnyRef]] - - def enableTileTrace(site: View, here: View, up: View): PartialFunction[Any, Any] - def instantiateTile(param: TileParams, crossing: RocketCrossingParams, - logicalTreeNode: LogicalTreeNode, p: Parameters): Option[BaseTile] -} - -class CoreRegisterEntry[TileParamsT <: CoreParams, TileT <: BaseTile]( - tk: Field[Seq[TileParamsT]], - ck: Field[Seq[RocketCrossingParams]], - tileInstantiator: (TileParamsT, RocketCrossingParams, LookupByHartIdImpl, LogicalTreeNode, Parameters) => TileT -) extends CoreRegisterEntryBase { - type TileParams = TileParamsT - def tilesKey = tk - def crossingKey = ck - - def findTilesWithFilter(view: View, p: Any => View) = { - case key if (key == tk && p(tk)) => view(tk) - } - - def enableTileTrace(site: View, here: View, up: View): PartialFunction[Any, Any] = { - case in if in == tilesKey => up(this.tilesKey) map (tile => tile.copy(trace = true)) - } - def instantiateTile(param: TileParams, crossing: RocketCrossingParams, - logicalTreeNode: LogicalTreeNode, p: Parameters): Option[BaseTile] = param match { - case a: TileParams => Some(tileInstantiator(a, crossing, PriorityMuxHartIdFromSeq(p(tilesKey)), logicalTreeNode, p)) - case _ => None - } -} - -object CoreRegistrar { - val cores: List[CoreRegisterEntryBase] = List( - // ADD YOUR CORE DEFINITION HERE - new CoreRegisterEntry[ArianeTileParams, ArianeTile](ArianeTilesKey, ArianeCrossingKey, ((a, b, c, d, p) => {new ArianeTile(a, b, c, d)})) - ) -} - -// Core Generic Config - change properties in the given map -class GenericConfig(properties: Map[String, Any], filterFunc: Any => Bool = (_ => true)) { - val configFunc: (View, View, View) => PartialFunction[Any, Any] = ((site, here, up) => key => { - val tiles = CoreRegistrar.cores flatMap _.findTilesWithFilter(up, filterFunc).lift(key) - if (tiles.size == 0) None else Some(tiles map (tile => { - val method = ClassTag(tile.getClass).member(TermName(methodName)).asMethod - })).unlift - }).unlift -} diff --git a/generators/chipyard/src/main/scala/TestSuites.scala b/generators/chipyard/src/main/scala/TestSuites.scala index f90e3d23..a4944355 100644 --- a/generators/chipyard/src/main/scala/TestSuites.scala +++ b/generators/chipyard/src/main/scala/TestSuites.scala @@ -147,7 +147,7 @@ class TestSuiteHelper */ def addThirdPartyTestSuites[TileParams <: CoreParams](tilesKey: Field[Seq[TileParams]])(implicit p: Parameters) = { val xlen = p(XLen) - p(tilesKey).find(_.hartId == 0).map { tileParams => + p(tilesKey).asInstanceOf[Seq[CoreParams]].find(_.hartId == 0).map { tileParams => val coreParams = tileParams.core val vm = coreParams.useVM val env = if (vm) List("p","v") else List("p") From 2edfcb9022f9904e99820477423c9ba57ec4463c Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Mon, 25 May 2020 13:58:04 -0700 Subject: [PATCH 05/20] Subsystem done --- .../chipyard/src/main/scala/CoreManager.scala | 32 +++++++++-------- .../chipyard/src/main/scala/Subsystem.scala | 34 ++++++++----------- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/generators/chipyard/src/main/scala/CoreManager.scala b/generators/chipyard/src/main/scala/CoreManager.scala index 72c5dc85..39c3a678 100644 --- a/generators/chipyard/src/main/scala/CoreManager.scala +++ b/generators/chipyard/src/main/scala/CoreManager.scala @@ -17,9 +17,8 @@ import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams} // Third-party core entries sealed trait CoreEntryBase { def updateWithFilter(view: View, p: Any => View): (Map[String, Any] => PartialFunction[Any, Seq[AnyRef]]) - - def instantiateTile(param: TileParams, crossing: RocketCrossingParams, - logicalTreeNode: LogicalTreeNode, p: Parameters): Option[BaseTile] + def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => ClockCrossingType) + (implicit logicalTreeNode: LogicalTreeNode, p: Parameters): (CoreParams, ClockCrossingType, BaseTile) } class CoreEntry[TileParamsT <: CoreParams, TileT <: BaseTile]( @@ -48,20 +47,18 @@ class CoreEntry[TileParamsT <: CoreParams, TileT <: BaseTile]( (tile => properties => copyTileParam(tile, properties)) } - def instantiateTile(param: TileParams, crossing: RocketCrossingParams, - logicalTreeNode: LogicalTreeNode, p: Parameters): Option[BaseTile] = param match { - case a: TileParams => Some(tileCtr.newInstance(a, crossing, PriorityMuxHartIdFromSeq(p(tilesKey)), logicalTreeNode, p)) - case _ => None + def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => ClockCrossingType) + (implicit logicalTreeNode: LogicalTreeNode, p: Parameters) = { + val tileParams = p(tk) + val crossings = crossingLookup(p(ck), tileParams.size) + (tileParams zip crossings) map ((param, crossing) => ( + param, + crossing, + LazyModule(tileCtr(param, crossing, PriorityMuxHartIdFromSeq(tileParams), logicalTreeNode)) + )) } } -object CoreManager { - val cores: List[CoreEntryBase] = List( - // ADD YOUR CORE DEFINITION HERE - new CoreEntry[ArianeTileParams, ArianeTile](ArianeTilesKey, ArianeCrossingKey) - ) -} - // Core Generic Config - change properties in the given map class GenericConfig(properties: Map[String, Any], filterFunc: Any => Bool) { val configFunc: (View, View, View) => PartialFunction[Any, Any] = ((site, here, up) => key => { @@ -74,3 +71,10 @@ object GenericConfig { def apply(properties: Map[String, Any], filterFunc: Any => Bool = (_ => true)) = new GenericConfig(properties, filterFunc).configFunc } + +object CoreManager { + val cores: List[CoreEntryBase] = List( + // ADD YOUR CORE DEFINITION HERE + new CoreEntry[ArianeTileParams, ArianeTile](ArianeTilesKey, ArianeCrossingKey) + ) +} diff --git a/generators/chipyard/src/main/scala/Subsystem.scala b/generators/chipyard/src/main/scala/Subsystem.scala index 7b554d2a..c7924c9a 100644 --- a/generators/chipyard/src/main/scala/Subsystem.scala +++ b/generators/chipyard/src/main/scala/Subsystem.scala @@ -35,18 +35,25 @@ trait HasChipyardTiles extends HasTiles protected val rocketTileParams = p(RocketTilesKey) protected val boomTileParams = p(BoomTilesKey) - protected val coreTileParams = CoreRegistrar.cores map (coreType => p(coreType.tilesKey)) // crossing can either be per tile or global (aka only 1 crossing specified) private val rocketCrossings = perTileOrGlobalSetting(p(RocketCrossingKey), rocketTileParams.size) private val boomCrossings = perTileOrGlobalSetting(p(BoomCrossingKey), boomTileParams.size) - private val coreCrossings = (CoreRegistrar.cores zip coreTileParams) map (_ match { - case (coreType, tileParams) => perTileOrGlobalSetting(p(coreType.crossingKey), tileParams.size) - }) - // TODO: XXX The "tiles" below scan for hartId but it is not in CoreParams. Should that be added in later + private val rocketTilesInfo = (rocketTileParams zip rocketCrossings) map ((param, crossing) => ( + param, + crossing, + LazyModule(new RocketTile(param, crossing, PriorityMuxHartIdFromSeq(rocketTileParams), logicalTreeNode)) + )) + private val boomTilesInfo = (boomTileParams zip boomCrossings) map ((param, crossing) => ( + param, + crossing, + LazyModule(new RocketTile(param, crossing, PriorityMuxHartIdFromSeq(boomCrossings), logicalTreeNode)) + )) + + // TODO: XXX The "tiles" below scan for hartId but it is not in CoreParams. Should that be added in later // revision, or I have to use reflection to get that parameter? - val allTilesInfo = (rocketTileParams ++ boomTileParams ++ coreTileParams.flatten) zip (rocketCrossings ++ boomCrossings ++ coreCrossings.flatten) + val allTilesInfo = rocketTilesInfo ++ boomTilesInfo ++ (CoreManager.cores map _.instantiateTile(perTileOrGlobalSetting _)) // Make a tile and wire its nodes into the system, // according to the specified type of clock crossing. @@ -56,19 +63,7 @@ trait HasChipyardTiles extends HasTiles // There is something weird with registering tile-local interrupt controllers to the CLINT. // TODO: investigate why val tiles = allTilesInfo.sortWith(_._1.hartId < _._1.hartId).map { - case (param, crossing) => { - - val tile = param match { - case r: RocketTileParams => { - LazyModule(new RocketTile(r, crossing, PriorityMuxHartIdFromSeq(rocketTileParams), logicalTreeNode)) - } - case b: BoomTileParams => { - LazyModule(new BoomTile(b, crossing, PriorityMuxHartIdFromSeq(boomTileParams), logicalTreeNode)) - } - case _ => LazyModule( - (CoreRegistrar.cores collect (core => core.instantiateTile(param, crossing, paramList, logicalTreeNode, p)).unlift()) (0) - ) - } + case (param, crossing, tile) => { connectMasterPortsToSBus(tile, crossing) connectSlavePortsToCBus(tile, crossing) connectInterrupts(tile, debugOpt, clintOpt, plicOpt) @@ -77,7 +72,6 @@ trait HasChipyardTiles extends HasTiles } } - def coreMonitorBundles = tiles.map { case r: RocketTile => r.module.core.rocketImpl.coreMonitorBundle case b: BoomTile => b.module.core.coreMonitorBundle From a120edd36431edf382a7a5f22728420357e9c8f9 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Mon, 25 May 2020 21:50:44 -0700 Subject: [PATCH 06/20] Pass Scala Compilation --- .../src/main/scala/ConfigFragments.scala | 3 +- .../chipyard/src/main/scala/CoreManager.scala | 57 ++++++++++--------- .../chipyard/src/main/scala/Subsystem.scala | 29 +++++----- .../chipyard/src/main/scala/TestSuites.scala | 6 +- .../scala/stage/phases/AddDefaultTests.scala | 4 +- 5 files changed, 53 insertions(+), 46 deletions(-) diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index e87b833a..697dc4ec 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -22,8 +22,7 @@ import sifive.blocks.devices.uart._ import sifive.blocks.devices.spi._ import chipyard.{BuildTop, BuildSystem} -import chipyard.{CoreRegistrar, CoreRegisterEntryBase} -import chipyard.hlist +import chipyard.GenericConfig /** * TODO: Why do we need this? diff --git a/generators/chipyard/src/main/scala/CoreManager.scala b/generators/chipyard/src/main/scala/CoreManager.scala index 39c3a678..d92f839c 100644 --- a/generators/chipyard/src/main/scala/CoreManager.scala +++ b/generators/chipyard/src/main/scala/CoreManager.scala @@ -7,7 +7,7 @@ import chisel3._ import freechips.rocketchip.config.{Parameters, Config, Field, View} import freechips.rocketchip.subsystem.{SystemBusKey, RocketTilesKey, RocketCrossingParams} -import freechips.rocketchip.diplomacy.LazyModule +import freechips.rocketchip.diplomacy.{LazyModule, ClockCrossingType, ValName} import freechips.rocketchip.diplomaticobjectmodel.logicaltree.LogicalTreeNode import freechips.rocketchip.rocket._ import freechips.rocketchip.tile._ @@ -16,59 +16,64 @@ import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams} // Third-party core entries sealed trait CoreEntryBase { - def updateWithFilter(view: View, p: Any => View): (Map[String, Any] => PartialFunction[Any, Seq[AnyRef]]) - def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => ClockCrossingType) - (implicit logicalTreeNode: LogicalTreeNode, p: Parameters): (CoreParams, ClockCrossingType, BaseTile) + 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) + (implicit p: Parameters, valName: ValName): Seq[(TileParams, RocketCrossingParams, BaseTile)] } -class CoreEntry[TileParamsT <: CoreParams, TileT <: BaseTile]( +class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTile : TypeTag]( tk: Field[Seq[TileParamsT]], ck: Field[Seq[RocketCrossingParams]] ) extends CoreEntryBase { private val mirror = runtimeMirror(getClass.getClassLoader) private val paramClass = mirror.runtimeClass(typeOf[TileParamsT].typeSymbol.asClass) - private val paramNames = Map((paramClass.getDeclaredFields map _.getName).zipWithIndex) + private val paramNames = (paramClass.getDeclaredFields map (f => f.getName)).zipWithIndex.toMap private val paramCtr = paramClass.getConstructors.head private val tileClass = mirror.runtimeClass(typeOf[TileT].typeSymbol.asClass) private val tileCtr = paramClass.getConstructors.head // copy() function in - def copyTileParam(tileParam: AnyRef, properties: Map[String, Any]) = { - val values = foo.productIterator.toList - val indexedProperties = properties map (key => (paramNames(key), properties(key))) + def copyTileParam(tileParam: TileParamsT, properties: Map[String, Any]) = { + val values = tileParam.productIterator.toList + val indexedProperties = 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)) + (i => (if (indexedProperties contains i) indexedProperties(i) else values(i)).asInstanceOf[AnyRef]) paramCtr.newInstance(newValues:_*) } - def updateWithFilter(view: View, p: Any => View) = { - case key if (key == tk && p(tk)) => view(tk) map - (tile => properties => copyTileParam(tile, properties)) + def tileParamsLookup(implicit p: Parameters) = p(tk) + + def updateWithFilter(view: View, p: Any => Boolean): PartialFunction[Any, Map[String, Any] => Any] = { + case key if (key == tk && p(tk)) => properties => view(tk) map + (tile => copyTileParam(tile, properties)) } - def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => ClockCrossingType) - (implicit logicalTreeNode: LogicalTreeNode, p: Parameters) = { + def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => Seq[RocketCrossingParams], logicalTreeNode: LogicalTreeNode) + (implicit p: Parameters, valName: ValName) = { val tileParams = p(tk) val crossings = crossingLookup(p(ck), tileParams.size) - (tileParams zip crossings) map ((param, crossing) => ( - param, - crossing, - LazyModule(tileCtr(param, crossing, PriorityMuxHartIdFromSeq(tileParams), logicalTreeNode)) - )) + (tileParams zip crossings) map { + case (param, crossing) => ( + param, + crossing, + LazyModule(tileCtr.newInstance(param, crossing, PriorityMuxHartIdFromSeq(tileParams), logicalTreeNode).asInstanceOf[TileT]) + ) + } } } // Core Generic Config - change properties in the given map -class GenericConfig(properties: Map[String, Any], filterFunc: Any => Bool) { - val configFunc: (View, View, View) => PartialFunction[Any, Any] = ((site, here, up) => key => { - val tiles = CoreManager.cores flatMap _.updateWithFilter(up, filterFunc).lift(key) - if (tiles.size == 0) None else Some(tiles map _(properties)) - }).unlift +class GenericConfig(properties: Map[String, Any], filterFunc: Any => Boolean) { + val configFunc: (View, View, View) => PartialFunction[Any, Any] = (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))) + }) } object GenericConfig { - def apply(properties: Map[String, Any], filterFunc: Any => Bool = (_ => true)) = + def apply(properties: Map[String, Any], filterFunc: Any => Boolean = (_ => true)) = new GenericConfig(properties, filterFunc).configFunc } diff --git a/generators/chipyard/src/main/scala/Subsystem.scala b/generators/chipyard/src/main/scala/Subsystem.scala index c7924c9a..1b766099 100644 --- a/generators/chipyard/src/main/scala/Subsystem.scala +++ b/generators/chipyard/src/main/scala/Subsystem.scala @@ -40,20 +40,23 @@ trait HasChipyardTiles extends HasTiles private val rocketCrossings = perTileOrGlobalSetting(p(RocketCrossingKey), rocketTileParams.size) private val boomCrossings = perTileOrGlobalSetting(p(BoomCrossingKey), boomTileParams.size) - private val rocketTilesInfo = (rocketTileParams zip rocketCrossings) map ((param, crossing) => ( - param, - crossing, - LazyModule(new RocketTile(param, crossing, PriorityMuxHartIdFromSeq(rocketTileParams), logicalTreeNode)) - )) - private val boomTilesInfo = (boomTileParams zip boomCrossings) map ((param, crossing) => ( - param, - crossing, - LazyModule(new RocketTile(param, crossing, PriorityMuxHartIdFromSeq(boomCrossings), logicalTreeNode)) - )) + private val rocketTilesInfo = (rocketTileParams zip rocketCrossings) map { + case (param, crossing) => ( + param, + crossing, + LazyModule(new RocketTile(param, crossing, PriorityMuxHartIdFromSeq(rocketTileParams), logicalTreeNode)) + ) + } + private val boomTilesInfo = (boomTileParams zip boomCrossings) map { + case (param, crossing) => ( + param, + crossing, + LazyModule(new BoomTile(param, crossing, PriorityMuxHartIdFromSeq(boomTileParams), logicalTreeNode)) + ) + } - // TODO: XXX The "tiles" below scan for hartId but it is not in CoreParams. Should that be added in later - // revision, or I have to use reflection to get that parameter? - val allTilesInfo = rocketTilesInfo ++ boomTilesInfo ++ (CoreManager.cores map _.instantiateTile(perTileOrGlobalSetting _)) + val allTilesInfo = rocketTilesInfo ++ boomTilesInfo ++ + (CoreManager.cores flatMap (core => core.instantiateTile(perTileOrGlobalSetting _, logicalTreeNode))) // Make a tile and wire its nodes into the system, // according to the specified type of clock crossing. diff --git a/generators/chipyard/src/main/scala/TestSuites.scala b/generators/chipyard/src/main/scala/TestSuites.scala index a4944355..9041be61 100644 --- a/generators/chipyard/src/main/scala/TestSuites.scala +++ b/generators/chipyard/src/main/scala/TestSuites.scala @@ -3,7 +3,7 @@ package chipyard import scala.collection.mutable.{LinkedHashSet} import freechips.rocketchip.subsystem.{RocketTilesKey} -import freechips.rocketchip.tile.{XLen, CoreParams} +import freechips.rocketchip.tile.{XLen, TileParams} import freechips.rocketchip.config.{Parameters, Field} import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite, RocketTestSuite} @@ -145,9 +145,9 @@ class TestSuiteHelper /** * Add third-party core (including Ariane) tests (asm, bmark, regression) */ - def addThirdPartyTestSuites[TileParams <: CoreParams](tilesKey: Field[Seq[TileParams]])(implicit p: Parameters) = { + def addThirdPartyTestSuites(tiles: Seq[TileParams])(implicit p: Parameters) = { val xlen = p(XLen) - p(tilesKey).asInstanceOf[Seq[CoreParams]].find(_.hartId == 0).map { tileParams => + tiles.find(_.hartId == 0).map { tileParams => val coreParams = tileParams.core val vm = coreParams.useVM val env = if (vm) List("p","v") else List("p") diff --git a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala index 3d367ffa..cbd2e1a7 100644 --- a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala +++ b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala @@ -17,7 +17,7 @@ import freechips.rocketchip.stage.phases.{RocketTestSuiteAnnotation} import freechips.rocketchip.system.{RocketTestSuite, TestGeneration} import freechips.rocketchip.util.HasRocketChipStageUtils -import chipyard.{TestSuiteHelper, CoreRegistrar} +import chipyard.{TestSuiteHelper, CoreManager} class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { // Make sure we run both after RocketChip's version of this phase, and Rocket Chip's annotation emission phase @@ -32,7 +32,7 @@ class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipS val suiteHelper = new TestSuiteHelper suiteHelper.addRocketTestSuites suiteHelper.addBoomTestSuites - CoreRegistrar.cores map suiteHelper.addThirdPartyTestSuites(_.tilesKey) + CoreManager.cores map (core => suiteHelper.addThirdPartyTestSuites(core.tileParamsLookup)) // if hwacha parameter exists then generate its tests // TODO: find a more elegant way to do this. either through From 8f39791d940e748d0a25c06a957b0b9fd40e275c Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Thu, 28 May 2020 22:46:13 -0700 Subject: [PATCH 07/20] Git ignores vscode and scala plugins --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 47cb4d87..eaddd6e1 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,10 @@ target *# *~ .idea +.bloop +.metals +project/metals.sbt +.vscode .DS_Store env.sh riscv-tools-install From 71bac7b7c9f28a47662c2334914faaf8606744a9 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Fri, 29 May 2020 20:23:53 -0700 Subject: [PATCH 08/20] Fixed runtime error --- generators/chipyard/src/main/scala/CoreManager.scala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/generators/chipyard/src/main/scala/CoreManager.scala b/generators/chipyard/src/main/scala/CoreManager.scala index d92f839c..22212795 100644 --- a/generators/chipyard/src/main/scala/CoreManager.scala +++ b/generators/chipyard/src/main/scala/CoreManager.scala @@ -13,8 +13,9 @@ import freechips.rocketchip.rocket._ import freechips.rocketchip.tile._ import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams} +import chipsalliance.rocketchip.config.Parameters -// Third-party core entries +// Base trait for all third-party core entries sealed trait CoreEntryBase { def tileParamsLookup(implicit p: Parameters): Seq[TileParams] def updateWithFilter(view: View, p: Any => Boolean): PartialFunction[Any, Map[String, Any] => Any] @@ -22,6 +23,7 @@ sealed trait CoreEntryBase { (implicit p: Parameters, valName: ValName): Seq[(TileParams, RocketCrossingParams, BaseTile)] } +// Implementation of third-party core entries class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTile : TypeTag]( tk: Field[Seq[TileParamsT]], ck: Field[Seq[RocketCrossingParams]] @@ -32,9 +34,9 @@ class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTi private val paramCtr = paramClass.getConstructors.head private val tileClass = mirror.runtimeClass(typeOf[TileT].typeSymbol.asClass) - private val tileCtr = paramClass.getConstructors.head + private val tileCtr = tileClass.getConstructors.head - // copy() function in + // Reflective version of copy() def copyTileParam(tileParam: TileParamsT, properties: Map[String, Any]) = { val values = tileParam.productIterator.toList val indexedProperties = properties map { case (key, value) => (paramNames(key), value) } @@ -58,7 +60,7 @@ class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTi case (param, crossing) => ( param, crossing, - LazyModule(tileCtr.newInstance(param, crossing, PriorityMuxHartIdFromSeq(tileParams), logicalTreeNode).asInstanceOf[TileT]) + LazyModule(tileCtr.newInstance(param, crossing, PriorityMuxHartIdFromSeq(tileParams), logicalTreeNode, p.asInstanceOf[Parameters]).asInstanceOf[TileT]) ) } } From 3fcfc133b1a4e1840ca7f6cd08fd5eb43938aaab Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sun, 31 May 2020 10:51:11 -0700 Subject: [PATCH 09/20] Add Rocket and Boom to CoreManager --- .../src/main/scala/ConfigFragments.scala | 6 +- .../chipyard/src/main/scala/CoreManager.scala | 7 +- .../chipyard/src/main/scala/Subsystem.scala | 24 +----- .../chipyard/src/main/scala/TestSuites.scala | 81 +------------------ .../scala/stage/phases/AddDefaultTests.scala | 5 +- 5 files changed, 12 insertions(+), 111 deletions(-) diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index 697dc4ec..dfe225e4 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -148,7 +148,9 @@ class WithControlCore extends Config((site, here, up) => { }) class WithTraceIO extends Config((site, here, up) => - GenericConfig(Map("trace" -> true)) (site, here, up) orElse { - case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy(trace = true)) + GenericConfig(Map("trace" -> true), { + case RocketTilesKey => false + case _ => true + }) (site, here, up) orElse { case TracePortKey => Some(TracePortParams()) }) diff --git a/generators/chipyard/src/main/scala/CoreManager.scala b/generators/chipyard/src/main/scala/CoreManager.scala index 22212795..ec467d8f 100644 --- a/generators/chipyard/src/main/scala/CoreManager.scala +++ b/generators/chipyard/src/main/scala/CoreManager.scala @@ -6,12 +6,13 @@ import scala.reflect.runtime.universe._ import chisel3._ import freechips.rocketchip.config.{Parameters, Config, Field, View} -import freechips.rocketchip.subsystem.{SystemBusKey, RocketTilesKey, RocketCrossingParams} +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} import chipsalliance.rocketchip.config.Parameters @@ -34,7 +35,7 @@ class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTi private val paramCtr = paramClass.getConstructors.head private val tileClass = mirror.runtimeClass(typeOf[TileT].typeSymbol.asClass) - private val tileCtr = tileClass.getConstructors.head + private val tileCtr = tileClass.getConstructors.filter(ctr => ctr.getParameterTypes()(4) == classOf[Parameters]).head // Reflective version of copy() def copyTileParam(tileParam: TileParamsT, properties: Map[String, Any]) = { @@ -82,6 +83,8 @@ object GenericConfig { object CoreManager { val cores: List[CoreEntryBase] = List( // ADD YOUR CORE DEFINITION HERE + new CoreEntry[RocketTileParams, RocketTile](RocketTilesKey, RocketCrossingKey), + new CoreEntry[BoomTileParams, BoomTile](BoomTilesKey, BoomCrossingKey), new CoreEntry[ArianeTileParams, ArianeTile](ArianeTilesKey, ArianeCrossingKey) ) } diff --git a/generators/chipyard/src/main/scala/Subsystem.scala b/generators/chipyard/src/main/scala/Subsystem.scala index 1b766099..889e5f6f 100644 --- a/generators/chipyard/src/main/scala/Subsystem.scala +++ b/generators/chipyard/src/main/scala/Subsystem.scala @@ -33,29 +33,7 @@ trait HasChipyardTiles extends HasTiles val module: HasChipyardTilesModuleImp - protected val rocketTileParams = p(RocketTilesKey) - protected val boomTileParams = p(BoomTilesKey) - - // crossing can either be per tile or global (aka only 1 crossing specified) - private val rocketCrossings = perTileOrGlobalSetting(p(RocketCrossingKey), rocketTileParams.size) - private val boomCrossings = perTileOrGlobalSetting(p(BoomCrossingKey), boomTileParams.size) - - private val rocketTilesInfo = (rocketTileParams zip rocketCrossings) map { - case (param, crossing) => ( - param, - crossing, - LazyModule(new RocketTile(param, crossing, PriorityMuxHartIdFromSeq(rocketTileParams), logicalTreeNode)) - ) - } - private val boomTilesInfo = (boomTileParams zip boomCrossings) map { - case (param, crossing) => ( - param, - crossing, - LazyModule(new BoomTile(param, crossing, PriorityMuxHartIdFromSeq(boomTileParams), logicalTreeNode)) - ) - } - - val allTilesInfo = rocketTilesInfo ++ boomTilesInfo ++ + val allTilesInfo: Seq[(TileParams, RocketCrossingParams, BaseTile)] = (CoreManager.cores flatMap (core => core.instantiateTile(perTileOrGlobalSetting _, logicalTreeNode))) // Make a tile and wire its nodes into the system, diff --git a/generators/chipyard/src/main/scala/TestSuites.scala b/generators/chipyard/src/main/scala/TestSuites.scala index 9041be61..6fba4b2a 100644 --- a/generators/chipyard/src/main/scala/TestSuites.scala +++ b/generators/chipyard/src/main/scala/TestSuites.scala @@ -62,86 +62,6 @@ class TestSuiteHelper def addSuite(s: RocketTestSuite) { suites += (s.makeTargetName -> s) } def addSuites(s: Seq[RocketTestSuite]) { s.foreach(addSuite) } - /** - * Add BOOM tests (asm, bmark, regression) - */ - def addBoomTestSuites(implicit p: Parameters) = { - val xlen = p(XLen) - p(BoomTilesKey).find(_.hartId == 0).map { tileParams => - val coreParams = tileParams.core - val vm = coreParams.useVM - val env = if (vm) List("p","v") else List("p") - coreParams.fpu foreach { case cfg => - if (xlen == 32) { - addSuites(env.map(rv32uf)) - if (cfg.fLen >= 64) { - addSuites(env.map(rv32ud)) - } - } else if (cfg.fLen >= 64) { - addSuites(env.map(rv64ud)) - addSuites(env.map(rv64uf)) - addSuite(rv32udBenchmarks) - } - } - if (coreParams.useAtomics) { - if (tileParams.dcache.flatMap(_.scratch).isEmpty) { - addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) - } else { - addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC)) - } - } - if (coreParams.useCompressed) addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) - val (rvi, rvu) = - if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u) - else ((if (vm) rv32i else rv32pi), rv32u) - - addSuites(rvi.map(_("p"))) - addSuites(rvu.map(_("p"))) - addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env)))) - addSuite(benchmarks) - addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames)) - } - } - - /** - * Add Rocket tests (asm, bmark, regression) - */ - def addRocketTestSuites(implicit p: Parameters) = { - val xlen = p(XLen) - p(RocketTilesKey).find(_.hartId == 0).map { tileParams => - val coreParams = tileParams.core - val vm = coreParams.useVM - val env = if (vm) List("p","v") else List("p") - coreParams.fpu foreach { case cfg => - if (xlen == 32) { - addSuites(env.map(rv32uf)) - if (cfg.fLen >= 64) - addSuites(env.map(rv32ud)) - } else { - addSuite(rv32udBenchmarks) - addSuites(env.map(rv64uf)) - if (cfg.fLen >= 64) - addSuites(env.map(rv64ud)) - } - } - if (coreParams.useAtomics) { - if (tileParams.dcache.flatMap(_.scratch).isEmpty) - addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) - else - addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC)) - } - if (coreParams.useCompressed) addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) - val (rvi, rvu) = - if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u) - else ((if (vm) rv32i else rv32pi), rv32u) - - addSuites(rvi.map(_("p"))) - addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env)))) - addSuite(benchmarks) - addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames)) - } - } - /** * Add third-party core (including Ariane) tests (asm, bmark, regression) */ @@ -175,6 +95,7 @@ class TestSuiteHelper else ((if (vm) rv32i else rv32pi), rv32u) addSuites(rvi.map(_("p"))) + addSuites(rvu.map(_("p"))) addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env)))) addSuite(benchmarks) addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames)) diff --git a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala index 464c8ff5..f8ae3177 100644 --- a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala +++ b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala @@ -33,11 +33,8 @@ class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipS val suiteHelper = new TestSuiteHelper // Use Xlen as a proxy for detecting if we are a processor-like target // The underlying test suites expect this field to be defined - if (p.lift(XLen).nonEmpty) { - suiteHelper.addRocketTestSuites - suiteHelper.addBoomTestSuites + if (p.lift(XLen).nonEmpty) CoreManager.cores map (core => suiteHelper.addThirdPartyTestSuites(core.tileParamsLookup)) - } // if hwacha parameter exists then generate its tests // TODO: find a more elegant way to do this. either through From 0743abd9db6446f5194c6dc5f4425a2d93794c80 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sun, 31 May 2020 15:09:22 -0700 Subject: [PATCH 10/20] Add comments --- generators/chipyard/src/main/scala/CoreManager.scala | 11 +++++++++-- generators/chipyard/src/main/scala/Subsystem.scala | 3 ++- generators/chipyard/src/main/scala/TestSuites.scala | 4 ++-- .../src/main/scala/stage/phases/AddDefaultTests.scala | 4 ++-- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/generators/chipyard/src/main/scala/CoreManager.scala b/generators/chipyard/src/main/scala/CoreManager.scala index ec467d8f..ecee820f 100644 --- a/generators/chipyard/src/main/scala/CoreManager.scala +++ b/generators/chipyard/src/main/scala/CoreManager.scala @@ -29,15 +29,17 @@ class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTi tk: Field[Seq[TileParamsT]], ck: Field[Seq[RocketCrossingParams]] ) 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 paramCtr = paramClass.getConstructors.head + // Use reflection to get the tile's constructor private val tileClass = mirror.runtimeClass(typeOf[TileT].typeSymbol.asClass) private val tileCtr = tileClass.getConstructors.filter(ctr => ctr.getParameterTypes()(4) == classOf[Parameters]).head - // Reflective version of copy() + // 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 indexedProperties = properties map { case (key, value) => (paramNames(key), value) } @@ -46,13 +48,16 @@ class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTi paramCtr.newInstance(newValues:_*) } + // Tile parameter lookup using correct type def tileParamsLookup(implicit p: Parameters) = p(tk) + // 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 == tk && p(tk)) => properties => view(tk) map (tile => copyTileParam(tile, properties)) } + // Instantiate a tile and zip it with its parameter info, used by subsystem def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => Seq[RocketCrossingParams], logicalTreeNode: LogicalTreeNode) (implicit p: Parameters, valName: ValName) = { val tileParams = p(tk) @@ -75,14 +80,16 @@ class GenericConfig(properties: Map[String, Any], filterFunc: Any => Boolean) { }) } +// Wrapper object of the class above object GenericConfig { def apply(properties: Map[String, Any], filterFunc: Any => Boolean = (_ => true)) = new GenericConfig(properties, filterFunc).configFunc } +// A list of all cores. object CoreManager { val cores: List[CoreEntryBase] = List( - // ADD YOUR CORE DEFINITION HERE + // TODO ADD YOUR CORE DEFINITION HERE new CoreEntry[RocketTileParams, RocketTile](RocketTilesKey, RocketCrossingKey), new CoreEntry[BoomTileParams, BoomTile](BoomTilesKey, BoomCrossingKey), new CoreEntry[ArianeTileParams, ArianeTile](ArianeTilesKey, ArianeCrossingKey) diff --git a/generators/chipyard/src/main/scala/Subsystem.scala b/generators/chipyard/src/main/scala/Subsystem.scala index 889e5f6f..6410ac4e 100644 --- a/generators/chipyard/src/main/scala/Subsystem.scala +++ b/generators/chipyard/src/main/scala/Subsystem.scala @@ -33,7 +33,8 @@ trait HasChipyardTiles extends HasTiles val module: HasChipyardTilesModuleImp - val allTilesInfo: Seq[(TileParams, RocketCrossingParams, BaseTile)] = + // Generate tiles info from the list of cores in CoreManager + val allTilesInfo: Seq[(TileParams, RocketCrossingParams, BaseTile)] = (CoreManager.cores flatMap (core => core.instantiateTile(perTileOrGlobalSetting _, logicalTreeNode))) // Make a tile and wire its nodes into the system, diff --git a/generators/chipyard/src/main/scala/TestSuites.scala b/generators/chipyard/src/main/scala/TestSuites.scala index 6fba4b2a..2261000f 100644 --- a/generators/chipyard/src/main/scala/TestSuites.scala +++ b/generators/chipyard/src/main/scala/TestSuites.scala @@ -63,9 +63,9 @@ class TestSuiteHelper def addSuites(s: Seq[RocketTestSuite]) { s.foreach(addSuite) } /** - * Add third-party core (including Ariane) tests (asm, bmark, regression) + * Add generic tests (asm, bmark, regression) for all cores. */ - def addThirdPartyTestSuites(tiles: Seq[TileParams])(implicit p: Parameters) = { + def addGenericTestSuites(tiles: Seq[TileParams])(implicit p: Parameters) = { val xlen = p(XLen) tiles.find(_.hartId == 0).map { tileParams => val coreParams = tileParams.core diff --git a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala index f8ae3177..a36131b1 100644 --- a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala +++ b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala @@ -22,7 +22,7 @@ import chipyard.{TestSuiteHelper, CoreManager} class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { // Make sure we run both after RocketChip's version of this phase, and Rocket Chip's annotation emission phase - // because the RocketTestSuiteAnnotation is not serializable (but is not marked as such). + // because the RocketTestSuiteAnnotation is not serializable (but is not marked as such). override val prerequisites = Seq( Dependency[freechips.rocketchip.stage.phases.GenerateFirrtlAnnos], Dependency[freechips.rocketchip.stage.phases.AddDefaultTests]) @@ -34,7 +34,7 @@ class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipS // Use Xlen as a proxy for detecting if we are a processor-like target // The underlying test suites expect this field to be defined if (p.lift(XLen).nonEmpty) - CoreManager.cores map (core => suiteHelper.addThirdPartyTestSuites(core.tileParamsLookup)) + CoreManager.cores map (core => suiteHelper.addGenericTestSuites(core.tileParamsLookup)) // if hwacha parameter exists then generate its tests // TODO: find a more elegant way to do this. either through From aa606e580a60515fdc375c30b9ace5b074efd8fc Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Mon, 1 Jun 2020 18:41:21 -0700 Subject: [PATCH 11/20] Change names --- .../src/main/scala/ConfigFragments.scala | 13 +++--- .../chipyard/src/main/scala/CoreManager.scala | 46 ++++++++++--------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index dfe225e4..cad47f72 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -22,7 +22,7 @@ import sifive.blocks.devices.uart._ import sifive.blocks.devices.spi._ import chipyard.{BuildTop, BuildSystem} -import chipyard.GenericConfig +import chipyard.GenericCoreConfig /** * TODO: Why do we need this? @@ -147,10 +147,9 @@ class WithControlCore extends Config((site, here, up) => { case MaxHartIdBits => log2Up(up(RocketTilesKey, site).size + up(BoomTilesKey, site).size + 1) }) -class WithTraceIO extends Config((site, here, up) => - GenericConfig(Map("trace" -> true), { - case RocketTilesKey => false - case _ => true - }) (site, here, up) orElse { +class WithTraceIO extends GenericCoreConfig( + properties = Map("trace" -> true), + specialCase = (site, here, up) => { case TracePortKey => Some(TracePortParams()) - }) + } +) \ No newline at end of file diff --git a/generators/chipyard/src/main/scala/CoreManager.scala b/generators/chipyard/src/main/scala/CoreManager.scala index ecee820f..2756a42b 100644 --- a/generators/chipyard/src/main/scala/CoreManager.scala +++ b/generators/chipyard/src/main/scala/CoreManager.scala @@ -26,65 +26,67 @@ sealed trait CoreEntryBase { // Implementation of third-party core entries class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTile : TypeTag]( - tk: Field[Seq[TileParamsT]], - ck: Field[Seq[RocketCrossingParams]] + tilesKey: Field[Seq[TileParamsT]], + crossingKey: Field[Seq[RocketCrossingParams]] ) 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 paramCtr = paramClass.getConstructors.head + private val paramCtor = paramClass.getConstructors.head // Use reflection to get the tile's constructor private val tileClass = mirror.runtimeClass(typeOf[TileT].typeSymbol.asClass) - private val tileCtr = tileClass.getConstructors.filter(ctr => ctr.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 indexedProperties = properties map { case (key, value) => (paramNames(key), value) } + //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]) - paramCtr.newInstance(newValues:_*) + paramCtor.newInstance(newValues:_*) } // Tile parameter lookup using correct type - def tileParamsLookup(implicit p: Parameters) = p(tk) + 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 == tk && p(tk)) => properties => view(tk) map + case key if (key == tilesKey && p(tilesKey)) => properties => view(tilesKey) map (tile => copyTileParam(tile, properties)) } // Instantiate a tile and zip it with its parameter info, used by subsystem def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => Seq[RocketCrossingParams], logicalTreeNode: LogicalTreeNode) (implicit p: Parameters, valName: ValName) = { - val tileParams = p(tk) - val crossings = crossingLookup(p(ck), tileParams.size) + val tileParams = p(tilesKey) + val crossings = crossingLookup(p(crossingKey), tileParams.size) (tileParams zip crossings) map { case (param, crossing) => ( param, crossing, - LazyModule(tileCtr.newInstance(param, crossing, PriorityMuxHartIdFromSeq(tileParams), logicalTreeNode, p.asInstanceOf[Parameters]).asInstanceOf[TileT]) + LazyModule(tileCtor.newInstance(param, crossing, PriorityMuxHartIdFromSeq(tileParams), logicalTreeNode, p.asInstanceOf[Parameters]).asInstanceOf[TileT]) ) } } } -// Core Generic Config - change properties in the given map -class GenericConfig(properties: Map[String, Any], filterFunc: Any => Boolean) { - val configFunc: (View, View, View) => PartialFunction[Any, Any] = (site, here, up) => scala.Function.unlift((key: Any) => { +// 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))) - }) -} - -// Wrapper object of the class above -object GenericConfig { - def apply(properties: Map[String, Any], filterFunc: Any => Boolean = (_ => true)) = - new GenericConfig(properties, filterFunc).configFunc -} + }).orElse(specialCase(site, here, up)) +) // A list of all cores. object CoreManager { From 02c8aac346df1f889fa7d4810a76b3db2daedd67 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Wed, 3 Jun 2020 20:22:41 -0700 Subject: [PATCH 12/20] Revised generic config --- .../src/main/scala/ConfigFragments.scala | 11 +- .../chipyard/src/main/scala/CoreManager.scala | 47 ++----- .../src/main/scala/GenericCoreConfig.scala | 133 ++++++++++++++++++ .../scala/stage/phases/AddDefaultTests.scala | 11 +- 4 files changed, 153 insertions(+), 49 deletions(-) create mode 100644 generators/chipyard/src/main/scala/GenericCoreConfig.scala diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index cad47f72..4d0e0725 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -59,14 +59,7 @@ class WithSPIFlash(size: BigInt = 0x10000000) extends Config((site, here, up) => SPIFlashParams(rAddress = 0x10040000, fAddress = 0x20000000, fSize = size)) }) -class WithL2TLBs(entries: Int) extends Config((site, here, up) => { - 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 WithL2TLBs(entries: Int) extends GenericCoreConfig(Map("core" -> Map("nL2TLBEntries" -> entries))) class WithTracegenSystem extends Config((site, here, up) => { case BuildSystem => (p: Parameters) => LazyModule(new tracegen.TraceGenSystem()(p)) @@ -148,7 +141,7 @@ class WithControlCore extends Config((site, here, up) => { }) class WithTraceIO extends GenericCoreConfig( - properties = Map("trace" -> true), + newValues = Map("trace" -> true), specialCase = (site, here, up) => { case TracePortKey => Some(TracePortParams()) } diff --git a/generators/chipyard/src/main/scala/CoreManager.scala b/generators/chipyard/src/main/scala/CoreManager.scala index 2756a42b..57b63743 100644 --- a/generators/chipyard/src/main/scala/CoreManager.scala +++ b/generators/chipyard/src/main/scala/CoreManager.scala @@ -14,10 +14,10 @@ import freechips.rocketchip.tile._ import boom.common.{BoomTile, BoomTilesKey, BoomCrossingKey, BoomTileParams} import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams} -import chipsalliance.rocketchip.config.Parameters // Base trait for all third-party core entries sealed trait CoreEntryBase { + val name: String 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) @@ -26,36 +26,22 @@ sealed trait CoreEntryBase { // Implementation of third-party core entries class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTile : TypeTag]( + val name: String, tilesKey: Field[Seq[TileParamsT]], crossingKey: Field[Seq[RocketCrossingParams]] ) 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 + private val mirror = runtimeMirror(getClass.getClassLoader) private val tileClass = mirror.runtimeClass(typeOf[TileT].typeSymbol.asClass) 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 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)) => properties => view(tilesKey) map - (tile => copyTileParam(tile, properties)) + 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 @@ -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. object CoreManager { val cores: List[CoreEntryBase] = List( - // TODO ADD YOUR CORE DEFINITION HERE - new CoreEntry[RocketTileParams, RocketTile](RocketTilesKey, RocketCrossingKey), - new CoreEntry[BoomTileParams, BoomTile](BoomTilesKey, BoomCrossingKey), - new CoreEntry[ArianeTileParams, ArianeTile](ArianeTilesKey, ArianeCrossingKey) + // TODO ADD YOUR CORE DEFINITION HERE; note that the + new CoreEntry[RocketTileParams, RocketTile]("Rocket", RocketTilesKey, RocketCrossingKey), + new CoreEntry[BoomTileParams, BoomTile]("Boom", BoomTilesKey, BoomCrossingKey), + new CoreEntry[ArianeTileParams, ArianeTile]("Ariane", ArianeTilesKey, ArianeCrossingKey) ) } diff --git a/generators/chipyard/src/main/scala/GenericCoreConfig.scala b/generators/chipyard/src/main/scala/GenericCoreConfig.scala new file mode 100644 index 00000000..ac099742 --- /dev/null +++ b/generators/chipyard/src/main/scala/GenericCoreConfig.scala @@ -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)) +) \ No newline at end of file diff --git a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala index a36131b1..5855613e 100644 --- a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala +++ b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala @@ -33,8 +33,15 @@ class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipS val suiteHelper = new TestSuiteHelper // Use Xlen as a proxy for detecting if we are a processor-like target // The underlying test suites expect this field to be defined - if (p.lift(XLen).nonEmpty) - CoreManager.cores map (core => suiteHelper.addGenericTestSuites(core.tileParamsLookup)) + if (p.lift(XLen).nonEmpty) { + 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 // TODO: find a more elegant way to do this. either through From e021f161dca48ea7b8136208a6c7e1b5c5aff23a Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Wed, 3 Jun 2020 20:57:31 -0700 Subject: [PATCH 13/20] Remove Debug message --- generators/chipyard/src/main/scala/GenericCoreConfig.scala | 3 --- 1 file changed, 3 deletions(-) diff --git a/generators/chipyard/src/main/scala/GenericCoreConfig.scala b/generators/chipyard/src/main/scala/GenericCoreConfig.scala index ac099742..63bc749f 100644 --- a/generators/chipyard/src/main/scala/GenericCoreConfig.scala +++ b/generators/chipyard/src/main/scala/GenericCoreConfig.scala @@ -101,9 +101,6 @@ class CopyParam(paramExtracted: SubParameterBase) { } paramCtor.newInstance(newValueList:_*) } - - // For debug purpose - print what's in the object - override def toString(): String = paramClass.getSimpleName + "(" + entries.toString + ")" } object CopyParam { From 0f116cb7174bd7baab083975527289c5aa7fed4a Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Thu, 4 Jun 2020 00:17:05 -0700 Subject: [PATCH 14/20] Tile construction delayed --- generators/chipyard/src/main/scala/CoreManager.scala | 10 ++++++++-- generators/chipyard/src/main/scala/Subsystem.scala | 9 +++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/generators/chipyard/src/main/scala/CoreManager.scala b/generators/chipyard/src/main/scala/CoreManager.scala index 57b63743..9dc55eff 100644 --- a/generators/chipyard/src/main/scala/CoreManager.scala +++ b/generators/chipyard/src/main/scala/CoreManager.scala @@ -21,7 +21,7 @@ sealed trait CoreEntryBase { 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) - (implicit p: Parameters, valName: ValName): Seq[(TileParams, RocketCrossingParams, BaseTile)] + (implicit p: Parameters, valName: ValName): Seq[(TileParams, RocketCrossingParams, () => BaseTile)] } // Implementation of third-party core entries @@ -53,7 +53,13 @@ class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTi case (param, crossing) => ( param, crossing, - LazyModule(tileCtor.newInstance(param, crossing, PriorityMuxHartIdFromSeq(tileParams), logicalTreeNode, p.asInstanceOf[Parameters]).asInstanceOf[TileT]) + (() => LazyModule(tileCtor.newInstance( + param, + crossing, + PriorityMuxHartIdFromSeq(tileParams), + logicalTreeNode, + p.asInstanceOf[Parameters] + ).asInstanceOf[TileT])) ) } } diff --git a/generators/chipyard/src/main/scala/Subsystem.scala b/generators/chipyard/src/main/scala/Subsystem.scala index 6410ac4e..fa5988e2 100644 --- a/generators/chipyard/src/main/scala/Subsystem.scala +++ b/generators/chipyard/src/main/scala/Subsystem.scala @@ -34,7 +34,9 @@ trait HasChipyardTiles extends HasTiles val module: HasChipyardTilesModuleImp // Generate tiles info from the list of cores in CoreManager - val allTilesInfo: Seq[(TileParams, RocketCrossingParams, BaseTile)] = + // Note: the 0-arity function is used to delay the construction of tiles to make sure that they are created + // in order + val allTilesInfo: Seq[(TileParams, RocketCrossingParams, () => BaseTile)] = (CoreManager.cores flatMap (core => core.instantiateTile(perTileOrGlobalSetting _, logicalTreeNode))) // Make a tile and wire its nodes into the system, @@ -44,8 +46,11 @@ trait HasChipyardTiles extends HasTiles // This MUST be performed in order of hartid // There is something weird with registering tile-local interrupt controllers to the CLINT. // TODO: investigate why + require((allTilesInfo map (info => info._1.hartId)).max == allTilesInfo.size - 1) val tiles = allTilesInfo.sortWith(_._1.hartId < _._1.hartId).map { - case (param, crossing, tile) => { + case (param, crossing, tileCtor) => { + val tile = tileCtor() + connectMasterPortsToSBus(tile, crossing) connectSlavePortsToCBus(tile, crossing) connectInterrupts(tile, debugOpt, clintOpt, plicOpt) From 98f6f9292eceede4c4e213991487275b58456560 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sat, 6 Jun 2020 16:22:59 -0700 Subject: [PATCH 15/20] Change Generic Config --- .../src/main/scala/ConfigFragments.scala | 21 +- .../chipyard/src/main/scala/CoreManager.scala | 12 +- .../src/main/scala/GenericCoreConfig.scala | 253 +++++++++++------- 3 files changed, 169 insertions(+), 117 deletions(-) diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index 4d0e0725..da1372db 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -13,6 +13,7 @@ import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams import freechips.rocketchip.util.{AsyncResetReg} import boom.common.{BoomTilesKey} +import ariane.ArianeTilesKey import testchipip._ import hwacha.{Hwacha} @@ -22,7 +23,8 @@ import sifive.blocks.devices.uart._ import sifive.blocks.devices.spi._ import chipyard.{BuildTop, BuildSystem} -import chipyard.GenericCoreConfig +import chipyard.TilesKey +import chipyard.TileSeq._ /** * 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)) }) -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) => { 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) }) -class WithTraceIO extends GenericCoreConfig( - newValues = Map("trace" -> true), - specialCase = (site, here, up) => { - case TracePortKey => Some(TracePortParams()) - } -) \ No newline at end of file +class WithTraceIO extends Config((site, here, up) => { + case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy(trace = true)) + case ArianeTilesKey => up(ArianeTilesKey) map (tile => tile.copy(trace = true)) + case TracePortKey => Some(TracePortParams()) +}) \ No newline at end of file diff --git a/generators/chipyard/src/main/scala/CoreManager.scala b/generators/chipyard/src/main/scala/CoreManager.scala index 9dc55eff..b5129217 100644 --- a/generators/chipyard/src/main/scala/CoreManager.scala +++ b/generators/chipyard/src/main/scala/CoreManager.scala @@ -18,8 +18,10 @@ import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams} // Base trait for all third-party core entries sealed trait CoreEntryBase { val name: String + + def keyEqual(key: Any): Boolean 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) (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 tileCtor = tileClass.getConstructors.filter(ctor => ctor.getParameterTypes()(4) == classOf[Parameters]).head + def keyEqual(key: Any) = key == tilesKey + // Tile parameter lookup using correct type 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 def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => Seq[RocketCrossingParams], logicalTreeNode: LogicalTreeNode) (implicit p: Parameters, valName: ValName) = { diff --git a/generators/chipyard/src/main/scala/GenericCoreConfig.scala b/generators/chipyard/src/main/scala/GenericCoreConfig.scala index 63bc749f..159b8b69 100644 --- a/generators/chipyard/src/main/scala/GenericCoreConfig.scala +++ b/generators/chipyard/src/main/scala/GenericCoreConfig.scala @@ -15,116 +15,165 @@ 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] +// Case class to change common parameters visible in the base traits. Some fields in the base traits may not be configurable as a +// case class constructor parameter for some cores, and those field will be ignored when applied. +case class GenericCoreParams( + val bootFreqHz: BigInt, + val useVM: Boolean, + val useUser: Boolean, + val useSupervisor: Boolean, + val useDebug: Boolean, + 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. -// 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 +case class GenericTileParams( + val core: GenericCoreParams, + val icache: Option[ICacheParams], + val dcache: Option[DCacheParams], + val btb: Option[BTBParams], + 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 -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 - } +// Extractor to capture TilesKey +object TilesKey { + def unapply(key: Any): Option[Field[Seq[_]]] = + if ((CoreManager.cores filter (core => core.keyEqual(key))).size != 0) Some(key.asInstanceOf[Field[Seq[_]]]) else 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 +class TileSeq(list: Seq[Any]) { + def tileMap(f: GenericTileParams => GenericTileParams): Seq[TileParams] = { + // If this is not an unpacked tile key, simply throw a type exception + // Static type checking is not possible when this class is used with TilesKey extractor + val tileList = list.asInstanceOf[Seq[TileParams]] - // 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:_*) + tileList map (tileParams => f(new GenericTileParams(tileParams)).convert) } } - -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") - } +object TileSeq { + implicit def convertSeq(s: Seq[Any]) = new TileSeq(s) } - -// 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)) -) \ No newline at end of file From 119a44b1219a6930bcf895d91cd9b7f7d0867f7f Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sat, 13 Jun 2020 01:36:14 -0700 Subject: [PATCH 16/20] Use config to manage core registration and custom tests --- .../src/main/scala/ConfigFragments.scala | 9 +- .../chipyard/src/main/scala/CoreManager.scala | 53 +++++++++- ...reConfig.scala => GenericCoreParams.scala} | 97 +++++++------------ .../chipyard/src/main/scala/Subsystem.scala | 2 +- .../chipyard/src/main/scala/TestSuites.scala | 15 +++ .../scala/stage/phases/AddDefaultTests.scala | 16 ++- 6 files changed, 111 insertions(+), 81 deletions(-) rename generators/chipyard/src/main/scala/{GenericCoreConfig.scala => GenericCoreParams.scala} (69%) diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index da1372db..8336bdc5 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -23,8 +23,7 @@ import sifive.blocks.devices.uart._ import sifive.blocks.devices.spi._ import chipyard.{BuildTop, BuildSystem} -import chipyard.TilesKey -import chipyard.TileSeq._ +import chipyard.{GenericTilesKey, GenericTileConfig} /** * TODO: Why do we need this? @@ -61,8 +60,8 @@ class WithSPIFlash(size: BigInt = 0x10000000) extends Config((site, here, up) => SPIFlashParams(rAddress = 0x10040000, fAddress = 0x20000000, fSize = size)) }) -class WithL2TLBs(entries: Int) extends Config((site, here, up) => { - case TilesKey(tilesKey) => up(tilesKey) tileMap (tile => tile.copy( +class WithL2TLBs(entries: Int) extends GenericTileConfig((site, here, up) => { + case GenericTilesKey(key) => up(GenericTilesKey(key)) map (tile => tile.copy( core = tile.core.copy(nL2TLBEntries = entries) )) }) @@ -150,4 +149,4 @@ class WithTraceIO extends Config((site, here, up) => { case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy(trace = true)) case ArianeTilesKey => up(ArianeTilesKey) map (tile => tile.copy(trace = true)) case TracePortKey => Some(TracePortParams()) -}) \ No newline at end of file +}) diff --git a/generators/chipyard/src/main/scala/CoreManager.scala b/generators/chipyard/src/main/scala/CoreManager.scala index b5129217..d013cc7c 100644 --- a/generators/chipyard/src/main/scala/CoreManager.scala +++ b/generators/chipyard/src/main/scala/CoreManager.scala @@ -15,6 +15,21 @@ import freechips.rocketchip.tile._ import boom.common.{BoomTile, BoomTilesKey, BoomCrossingKey, BoomTileParams} import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams} +case object CoreEntryKey extends Field[Seq[CoreEntryBase]](Nil) + +// If this key is encountered by a GenericTilesKey extractor, throw immediately +// Inside the body of GenericTileConfig, suppressed will be set to true to prevent the extractor from throwing +case class GenericTilesKeyChecker(suppressed: Boolean) extends Field[Int](0) +case class GenericTilesKeyImp(key: Field[Seq[TileParams]]) extends Field[Seq[GenericTileParams]](Nil) +object GenericTilesKey { + def apply(key: Field[Seq[TileParams]]) = GenericTilesKeyImp(key) + def unapply(key: Any): Option[Field[Seq[TileParams]]] = key match { + case GenericTilesKeyChecker(suppressed) if !suppressed => throw new Exception("GenericTilesKey must be in GenericTilesConfig") + case GenericTilesKeyImp(key) => Some(key) + case _ => None + } +} + // Base trait for all third-party core entries sealed trait CoreEntryBase { val name: String @@ -45,6 +60,11 @@ class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTi // Instantiate a tile and zip it with its parameter info, used by subsystem def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => Seq[RocketCrossingParams], logicalTreeNode: LogicalTreeNode) (implicit p: Parameters, valName: ValName) = { + // Sanity check of GenericTilesKey outside of GenericTileConfig + // People would shoot themselves in the foot easily with this design, so a sanity check is necessary + // Simply trigger the exception by looking up the checker key + p(GenericTilesKeyChecker(false)) + val tileParams = p(tilesKey) val crossings = crossingLookup(p(crossingKey), tileParams.size) (tileParams zip crossings) map { @@ -63,12 +83,41 @@ class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTi } } +// Config fragment to register a core +class RegisterCore[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTile : TypeTag]( + name: String, + tilesKey: Field[Seq[TileParamsT]], + crossingKey: Field[Seq[RocketCrossingParams]] +) extends Config((site, here, up) => { + case CoreEntryKey => new CoreEntry[TileParamsT, TileT](name, tilesKey, crossingKey) +: up(CoreEntryKey) +}) + +// The config used along with GenericTilesKey. +// It change a lookup for registered tile parameter into a lookup with GenericTilesKey in the function body temporarily. +class GenericTileConfig(f: (View, View, View) => PartialFunction[Any, Any]) extends Config( + new Config((site, here, up) => { + case GenericTilesKeyChecker(_) => up(GenericTilesKeyChecker(true)) + case key if CoreManager.keyMatch(up, key) => up(GenericTilesKey(key.asInstanceOf[Field[Seq[TileParams]]])) map (t => t.convert) + }) ++ + new Config(f) ++ + new Config((site, here, up) => { + case GenericTilesKeyChecker(_) => up(GenericTilesKeyChecker(false)) + case GenericTilesKey(key) => up(key) map (t => new GenericTileParams(t)) + }) +) + // A list of all cores. object CoreManager { - val cores: List[CoreEntryBase] = List( - // TODO ADD YOUR CORE DEFINITION HERE; note that the + // Built-in cores. + val base_cores: List[CoreEntryBase] = List( new CoreEntry[RocketTileParams, RocketTile]("Rocket", RocketTilesKey, RocketCrossingKey), new CoreEntry[BoomTileParams, BoomTile]("Boom", BoomTilesKey, BoomCrossingKey), new CoreEntry[ArianeTileParams, ArianeTile]("Ariane", ArianeTilesKey, ArianeCrossingKey) ) + + // Look up all cores that are registered in the current config view. + def cores(view: View): Seq[CoreEntryBase] = view(CoreEntryKey) ++ base_cores + + // Check if the key is among the currently registered cores. + def keyMatch(view: View, key: Any) = (cores(view) filter (c => c.keyEqual(key))).size != 0 } diff --git a/generators/chipyard/src/main/scala/GenericCoreConfig.scala b/generators/chipyard/src/main/scala/GenericCoreParams.scala similarity index 69% rename from generators/chipyard/src/main/scala/GenericCoreConfig.scala rename to generators/chipyard/src/main/scala/GenericCoreParams.scala index 159b8b69..28db42b1 100644 --- a/generators/chipyard/src/main/scala/GenericCoreConfig.scala +++ b/generators/chipyard/src/main/scala/GenericCoreParams.scala @@ -15,6 +15,36 @@ import freechips.rocketchip.tile._ import boom.common.{BoomTile, BoomTilesKey, BoomCrossingKey, BoomTileParams} import ariane.{ArianeTile, ArianeTilesKey, ArianeCrossingKey, ArianeTileParams} +// Trait for generic case class of base trait for copying +trait ConcreteBaseTrait[Base] { + this: Product => + val _origin: Base + + // Convert back to core-specific tile + def convert: Base = { + // Reflection Info of this class + val fieldNames = (this.getClass.getDeclaredFields map (f => f.getName)).init + + // 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 map { + case c: ConcreteBaseTrait[_] => c.convert + case v => v + } + 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[Base] + } +} + // Case class to change common parameters visible in the base traits. Some fields in the base traits may not be configurable as a // case class constructor parameter for some cores, and those field will be ignored when applied. case class GenericCoreParams( @@ -50,7 +80,7 @@ case class GenericCoreParams( val mtvecWritable: Boolean, // The original object val _origin: CoreParams -) extends CoreParams { +) extends CoreParams with ConcreteBaseTrait[CoreParams] { def this(coreParams: CoreParams) = this( bootFreqHz = coreParams.bootFreqHz, useVM = coreParams.useVM, @@ -86,27 +116,6 @@ case class GenericCoreParams( _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 } @@ -121,8 +130,8 @@ case class GenericTileParams( val blockerCtrlAddr: Option[BigInt], val name: Option[String], // The original object - val _origin: TileParams -) extends TileParams { + val _origin: TileParams, +) extends TileParams with ConcreteBaseTrait[TileParams] { // Copy constructor to build the params def this(tileParams: TileParams) = this( core = new GenericCoreParams(tileParams.core), @@ -136,44 +145,4 @@ case class GenericTileParams( _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] - } -} - -// Extractor to capture TilesKey -object TilesKey { - def unapply(key: Any): Option[Field[Seq[_]]] = - if ((CoreManager.cores filter (core => core.keyEqual(key))).size != 0) Some(key.asInstanceOf[Field[Seq[_]]]) else None -} - -class TileSeq(list: Seq[Any]) { - def tileMap(f: GenericTileParams => GenericTileParams): Seq[TileParams] = { - // If this is not an unpacked tile key, simply throw a type exception - // Static type checking is not possible when this class is used with TilesKey extractor - val tileList = list.asInstanceOf[Seq[TileParams]] - - tileList map (tileParams => f(new GenericTileParams(tileParams)).convert) - } -} -object TileSeq { - implicit def convertSeq(s: Seq[Any]) = new TileSeq(s) } diff --git a/generators/chipyard/src/main/scala/Subsystem.scala b/generators/chipyard/src/main/scala/Subsystem.scala index fa5988e2..4ac92c4e 100644 --- a/generators/chipyard/src/main/scala/Subsystem.scala +++ b/generators/chipyard/src/main/scala/Subsystem.scala @@ -37,7 +37,7 @@ trait HasChipyardTiles extends HasTiles // Note: the 0-arity function is used to delay the construction of tiles to make sure that they are created // in order val allTilesInfo: Seq[(TileParams, RocketCrossingParams, () => BaseTile)] = - (CoreManager.cores flatMap (core => core.instantiateTile(perTileOrGlobalSetting _, logicalTreeNode))) + (CoreManager.cores(p) flatMap (core => core.instantiateTile(perTileOrGlobalSetting _, logicalTreeNode))) // Make a tile and wire its nodes into the system, // according to the specified type of clock crossing. diff --git a/generators/chipyard/src/main/scala/TestSuites.scala b/generators/chipyard/src/main/scala/TestSuites.scala index 2261000f..5a929010 100644 --- a/generators/chipyard/src/main/scala/TestSuites.scala +++ b/generators/chipyard/src/main/scala/TestSuites.scala @@ -2,6 +2,7 @@ package chipyard import scala.collection.mutable.{LinkedHashSet} +import freechips.rocketchip.config.{Parameters, Config, Field, View} import freechips.rocketchip.subsystem.{RocketTilesKey} import freechips.rocketchip.tile.{XLen, TileParams} import freechips.rocketchip.config.{Parameters, Field} @@ -102,3 +103,17 @@ class TestSuiteHelper } } } + +/** + * Config key of custom test suite. + */ +case object TestSuitesKey extends Field[(Seq[TileParams], TestSuiteHelper, Parameters) => Unit]((tiles, helper, p) => helper.addGenericTestSuites(tiles)(p)) + +/** + * Config fragment to add custom test suite factory function. + * + * @param suiteFactory Test suite factory function. It takes a list of TileParams to be instantiated and the test suite helper. + */ +class WithTestSuite(suiteFactory: (Seq[TileParams], TestSuiteHelper, Parameters) => Unit) extends Config((site, here, up) => { + case TestSuitesKey => suiteFactory +}) diff --git a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala index 5855613e..b170706e 100644 --- a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala +++ b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala @@ -19,6 +19,7 @@ import freechips.rocketchip.util.HasRocketChipStageUtils import freechips.rocketchip.tile.XLen import chipyard.{TestSuiteHelper, CoreManager} +import chipyard.TestSuitesKey class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { // Make sure we run both after RocketChip's version of this phase, and Rocket Chip's annotation emission phase @@ -33,15 +34,12 @@ class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipS val suiteHelper = new TestSuiteHelper // Use Xlen as a proxy for detecting if we are a processor-like target // The underlying test suites expect this field to be defined - if (p.lift(XLen).nonEmpty) { - 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 (p.lift(XLen).nonEmpty) + // If a custom test suite is set up, use the custom test suite + if (p.lift(TestSuitesKey).nonEmpty) + CoreManager.cores(p) map (core => p(TestSuitesKey).apply(core.tileParamsLookup, suiteHelper, p)) + else + CoreManager.cores(p) map (core => suiteHelper.addGenericTestSuites(core.tileParamsLookup)) // if hwacha parameter exists then generate its tests // TODO: find a more elegant way to do this. either through From 1c5bc7d0fff0dc20c8952e50b8bb724ede6da464 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Wed, 24 Jun 2020 20:55:37 -0700 Subject: [PATCH 17/20] Integrate with new Rocket tile API --- .../src/main/scala/ConfigFragments.scala | 17 +-- .../chipyard/src/main/scala/CoreManager.scala | 123 ------------------ ...icCoreParams.scala => GenericParams.scala} | 37 +++++- .../chipyard/src/main/scala/TestSuites.scala | 26 ++-- .../scala/stage/phases/AddDefaultTests.scala | 8 +- 5 files changed, 56 insertions(+), 155 deletions(-) delete mode 100644 generators/chipyard/src/main/scala/CoreManager.scala rename generators/chipyard/src/main/scala/{GenericCoreParams.scala => GenericParams.scala} (82%) diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index 1d6281cf..d66d3a07 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -26,7 +26,7 @@ import sifive.blocks.devices.uart._ import sifive.blocks.devices.spi._ import chipyard.{BuildTop, BuildSystem} -import chipyard.{GenericTilesKey, GenericTileConfig} +import chipyard.GenericCanAttachTile /** * TODO: Why do we need this? @@ -65,11 +65,8 @@ class WithSPIFlash(size: BigInt = 0x10000000) extends Config((site, here, up) => class WithL2TLBs(entries: Int) extends Config((site, here, up) => { case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(nL2TLBEntries = entries))) - case tp: BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(nL2TLBEntries = entries))) - case other => other + case GenericCanAttachTile(tp) => tp.copy(tileParams = tp.tileParams.copy( + core = tp.tileParams.core.copy(nL2TLBEntries = entries))).convert } }) @@ -110,7 +107,6 @@ class WithMultiRoCCHwacha(harts: Int*) extends Config((site, here, up) => { } }) - class WithTraceIO extends Config((site, here, up) => { case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { case tp: BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( @@ -124,10 +120,7 @@ class WithTraceIO extends Config((site, here, up) => { class WithNPerfCounters(n: Int = 29) extends Config((site, here, up) => { case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(nPerfCounters = n))) - case tp: BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(nPerfCounters = n))) - case other => other + case GenericCanAttachTile(tp) => tp.copy(tileParams = tp.tileParams.copy( + core = tp.tileParams.core.copy(nPerfCounters = n))).convert } }) diff --git a/generators/chipyard/src/main/scala/CoreManager.scala b/generators/chipyard/src/main/scala/CoreManager.scala deleted file mode 100644 index d013cc7c..00000000 --- a/generators/chipyard/src/main/scala/CoreManager.scala +++ /dev/null @@ -1,123 +0,0 @@ -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} - -case object CoreEntryKey extends Field[Seq[CoreEntryBase]](Nil) - -// If this key is encountered by a GenericTilesKey extractor, throw immediately -// Inside the body of GenericTileConfig, suppressed will be set to true to prevent the extractor from throwing -case class GenericTilesKeyChecker(suppressed: Boolean) extends Field[Int](0) -case class GenericTilesKeyImp(key: Field[Seq[TileParams]]) extends Field[Seq[GenericTileParams]](Nil) -object GenericTilesKey { - def apply(key: Field[Seq[TileParams]]) = GenericTilesKeyImp(key) - def unapply(key: Any): Option[Field[Seq[TileParams]]] = key match { - case GenericTilesKeyChecker(suppressed) if !suppressed => throw new Exception("GenericTilesKey must be in GenericTilesConfig") - case GenericTilesKeyImp(key) => Some(key) - case _ => None - } -} - -// Base trait for all third-party core entries -sealed trait CoreEntryBase { - val name: String - - def keyEqual(key: Any): Boolean - def tileParamsLookup(implicit p: Parameters): Seq[TileParams] - - def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => Seq[RocketCrossingParams], logicalTreeNode: LogicalTreeNode) - (implicit p: Parameters, valName: ValName): Seq[(TileParams, RocketCrossingParams, () => BaseTile)] -} - -// Implementation of third-party core entries -class CoreEntry[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTile : TypeTag]( - val name: String, - tilesKey: Field[Seq[TileParamsT]], - crossingKey: Field[Seq[RocketCrossingParams]] -) extends CoreEntryBase { - // 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 tileCtor = tileClass.getConstructors.filter(ctor => ctor.getParameterTypes()(4) == classOf[Parameters]).head - - def keyEqual(key: Any) = key == tilesKey - - // Tile parameter lookup using correct type - def tileParamsLookup(implicit p: Parameters) = p(tilesKey) - - // Instantiate a tile and zip it with its parameter info, used by subsystem - def instantiateTile(crossingLookup: (Seq[RocketCrossingParams], Int) => Seq[RocketCrossingParams], logicalTreeNode: LogicalTreeNode) - (implicit p: Parameters, valName: ValName) = { - // Sanity check of GenericTilesKey outside of GenericTileConfig - // People would shoot themselves in the foot easily with this design, so a sanity check is necessary - // Simply trigger the exception by looking up the checker key - p(GenericTilesKeyChecker(false)) - - val tileParams = p(tilesKey) - val crossings = crossingLookup(p(crossingKey), tileParams.size) - (tileParams zip crossings) map { - case (param, crossing) => ( - param, - crossing, - (() => LazyModule(tileCtor.newInstance( - param, - crossing, - PriorityMuxHartIdFromSeq(tileParams), - logicalTreeNode, - p.asInstanceOf[Parameters] - ).asInstanceOf[TileT])) - ) - } - } -} - -// Config fragment to register a core -class RegisterCore[TileParamsT <: TileParams with Product: TypeTag, TileT <: BaseTile : TypeTag]( - name: String, - tilesKey: Field[Seq[TileParamsT]], - crossingKey: Field[Seq[RocketCrossingParams]] -) extends Config((site, here, up) => { - case CoreEntryKey => new CoreEntry[TileParamsT, TileT](name, tilesKey, crossingKey) +: up(CoreEntryKey) -}) - -// The config used along with GenericTilesKey. -// It change a lookup for registered tile parameter into a lookup with GenericTilesKey in the function body temporarily. -class GenericTileConfig(f: (View, View, View) => PartialFunction[Any, Any]) extends Config( - new Config((site, here, up) => { - case GenericTilesKeyChecker(_) => up(GenericTilesKeyChecker(true)) - case key if CoreManager.keyMatch(up, key) => up(GenericTilesKey(key.asInstanceOf[Field[Seq[TileParams]]])) map (t => t.convert) - }) ++ - new Config(f) ++ - new Config((site, here, up) => { - case GenericTilesKeyChecker(_) => up(GenericTilesKeyChecker(false)) - case GenericTilesKey(key) => up(key) map (t => new GenericTileParams(t)) - }) -) - -// A list of all cores. -object CoreManager { - // Built-in cores. - val base_cores: List[CoreEntryBase] = List( - new CoreEntry[RocketTileParams, RocketTile]("Rocket", RocketTilesKey, RocketCrossingKey), - new CoreEntry[BoomTileParams, BoomTile]("Boom", BoomTilesKey, BoomCrossingKey), - new CoreEntry[ArianeTileParams, ArianeTile]("Ariane", ArianeTilesKey, ArianeCrossingKey) - ) - - // Look up all cores that are registered in the current config view. - def cores(view: View): Seq[CoreEntryBase] = view(CoreEntryKey) ++ base_cores - - // Check if the key is among the currently registered cores. - def keyMatch(view: View, key: Any) = (cores(view) filter (c => c.keyEqual(key))).size != 0 -} diff --git a/generators/chipyard/src/main/scala/GenericCoreParams.scala b/generators/chipyard/src/main/scala/GenericParams.scala similarity index 82% rename from generators/chipyard/src/main/scala/GenericCoreParams.scala rename to generators/chipyard/src/main/scala/GenericParams.scala index 28db42b1..8ed0d0f3 100644 --- a/generators/chipyard/src/main/scala/GenericCoreParams.scala +++ b/generators/chipyard/src/main/scala/GenericParams.scala @@ -6,15 +6,12 @@ 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.subsystem._ 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} - // Trait for generic case class of base trait for copying trait ConcreteBaseTrait[Base] { this: Product => @@ -146,3 +143,35 @@ case class GenericTileParams( _origin = tileParams ) } + +case class GenericTileCrossingParamsLike( + val crossingType: ClockCrossingType, + val master: TilePortParamsLike, + val slave: TilePortParamsLike, + val _origin: TileCrossingParamsLike +) extends TileCrossingParamsLike with ConcreteBaseTrait[TileCrossingParamsLike] { + def this(crossing: TileCrossingParamsLike) = this( + crossingType = crossing.crossingType, + master = crossing.master, + slave = crossing.slave, + _origin = crossing + ) +} + +case class GenericCanAttachTileImpl( + val tileParams: GenericTileParams, + val crossingParams: TileCrossingParamsLike, + val lookup: LookupByHartIdImpl, + val _origin: CanAttachTile, +) extends ConcreteBaseTrait[CanAttachTile] { + def this(param: CanAttachTile) = this( + tileParams = new GenericTileParams(param.tileParams), + crossingParams = new GenericTileCrossingParamsLike(param.crossingParams), + lookup = param.lookup, + _origin = param + ) +} + +object GenericCanAttachTile { + def unapply(tile: CanAttachTile) = Some(new GenericCanAttachTileImpl(tile)) +} diff --git a/generators/chipyard/src/main/scala/TestSuites.scala b/generators/chipyard/src/main/scala/TestSuites.scala index a3565a53..77aab39b 100644 --- a/generators/chipyard/src/main/scala/TestSuites.scala +++ b/generators/chipyard/src/main/scala/TestSuites.scala @@ -3,8 +3,8 @@ package chipyard import scala.collection.mutable.{LinkedHashSet} import freechips.rocketchip.subsystem._ -import freechips.rocketchip.tile.{XLen} -import freechips.rocketchip.config.{Parameters} +import freechips.rocketchip.tile.{XLen, TileParams} +import freechips.rocketchip.config.{Parameters, Field, Config} import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite, RocketTestSuite} import boom.common.{BoomTileAttachParams} @@ -83,16 +83,17 @@ class TestSuiteHelper if (cfg.fLen >= 64) addSuites(env.map(rv64ud)) } - if (coreParams.useAtomics) { - if (tileParams.dcache.flatMap(_.scratch).isEmpty) - addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) - else - addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC)) - } - if (coreParams.useCompressed) addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) - val (rvi, rvu) = - if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u) - else ((if (vm) rv32i else rv32pi), rv32u) + } + if (coreParams.useAtomics) { + if (tileParams.dcache.flatMap(_.scratch).isEmpty) + addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) + else + addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC)) + } + if (coreParams.useCompressed) addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) + val (rvi, rvu) = + if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u) + else ((if (vm) rv32i else rv32pi), rv32u) addSuites(rvi.map(_("p"))) addSuites(rvu.map(_("p"))) @@ -116,4 +117,3 @@ case object TestSuitesKey extends Field[(Seq[TileParams], TestSuiteHelper, Param class WithTestSuite(suiteFactory: (Seq[TileParams], TestSuiteHelper, Parameters) => Unit) extends Config((site, here, up) => { case TestSuitesKey => suiteFactory }) - diff --git a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala index b170706e..623dbce4 100644 --- a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala +++ b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala @@ -15,10 +15,11 @@ import firrtl.options.Viewer.view import freechips.rocketchip.stage.RocketChipOptions import freechips.rocketchip.stage.phases.{RocketTestSuiteAnnotation} import freechips.rocketchip.system.{RocketTestSuite, TestGeneration} +import freechips.rocketchip.subsystem.{TilesLocated, InSubsystem} import freechips.rocketchip.util.HasRocketChipStageUtils import freechips.rocketchip.tile.XLen -import chipyard.{TestSuiteHelper, CoreManager} +import chipyard.TestSuiteHelper import chipyard.TestSuitesKey class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils { @@ -34,12 +35,13 @@ class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipS val suiteHelper = new TestSuiteHelper // Use Xlen as a proxy for detecting if we are a processor-like target // The underlying test suites expect this field to be defined + val tileParams = p(TilesLocated(InSubsystem)) map (tp => tp.tileParams) if (p.lift(XLen).nonEmpty) // If a custom test suite is set up, use the custom test suite if (p.lift(TestSuitesKey).nonEmpty) - CoreManager.cores(p) map (core => p(TestSuitesKey).apply(core.tileParamsLookup, suiteHelper, p)) + p(TestSuitesKey).apply(tileParams, suiteHelper, p) else - CoreManager.cores(p) map (core => suiteHelper.addGenericTestSuites(core.tileParamsLookup)) + suiteHelper.addGenericTestSuites(tileParams) // if hwacha parameter exists then generate its tests // TODO: find a more elegant way to do this. either through From c85d8c4211c3c888a0ba0b80a92ee5d5b23bbc39 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Mon, 29 Jun 2020 11:42:34 -0700 Subject: [PATCH 18/20] Remove generic parameter from this PR --- .../src/main/scala/ConfigFragments.scala | 48 +++-- .../src/main/scala/GenericParams.scala | 177 ------------------ .../chipyard/src/main/scala/TestSuites.scala | 13 +- .../src/main/scala/config/BoomConfigs.scala | 1 + .../src/main/scala/config/HeteroConfigs.scala | 1 + .../src/main/scala/config/RocketConfigs.scala | 1 + .../scala/stage/phases/AddDefaultTests.scala | 18 +- 7 files changed, 42 insertions(+), 217 deletions(-) delete mode 100644 generators/chipyard/src/main/scala/GenericParams.scala diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index d66d3a07..da048ff1 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -25,8 +25,7 @@ import sifive.blocks.devices.gpio._ import sifive.blocks.devices.uart._ import sifive.blocks.devices.spi._ -import chipyard.{BuildTop, BuildSystem} -import chipyard.GenericCanAttachTile +import chipyard.{BuildTop, BuildSystem, TestSuitesKey, TestSuiteHelper} /** * TODO: Why do we need this? @@ -65,8 +64,11 @@ class WithSPIFlash(size: BigInt = 0x10000000) extends Config((site, here, up) => class WithL2TLBs(entries: Int) extends Config((site, here, up) => { case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case GenericCanAttachTile(tp) => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(nL2TLBEntries = entries))).convert + case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( + core = tp.tileParams.core.copy(nL2TLBEntries = entries))) + case tp: BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( + core = tp.tileParams.core.copy(nL2TLBEntries = entries))) + case other => other } }) @@ -97,15 +99,18 @@ class WithMultiRoCC extends Config((site, here, up) => { * * @param harts harts to specify which will get a Hwacha */ -class WithMultiRoCCHwacha(harts: Int*) extends Config((site, here, up) => { - case MultiRoCCKey => { - up(MultiRoCCKey, site) ++ harts.distinct.map{ i => - (i -> Seq((p: Parameters) => { - LazyModule(new Hwacha()(p)).suggestName("hwacha") - })) +class WithMultiRoCCHwacha(harts: Int*) extends Config( + new chipyard.config.WithHwachaTest ++ + new Config((site, here, up) => { + case MultiRoCCKey => { + up(MultiRoCCKey, site) ++ harts.distinct.map{ i => + (i -> Seq((p: Parameters) => { + LazyModule(new Hwacha()(p)).suggestName("hwacha") + })) + } } - } -}) + }) +) class WithTraceIO extends Config((site, here, up) => { case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { @@ -120,7 +125,22 @@ class WithTraceIO extends Config((site, here, up) => { class WithNPerfCounters(n: Int = 29) extends Config((site, here, up) => { case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map { - case GenericCanAttachTile(tp) => tp.copy(tileParams = tp.tileParams.copy( - core = tp.tileParams.core.copy(nPerfCounters = n))).convert + case tp: RocketTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( + core = tp.tileParams.core.copy(nPerfCounters = n))) + case tp: BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy( + core = tp.tileParams.core.copy(nPerfCounters = n))) + case other => other } }) + +class WithHwachaTest extends Config((site, here, up) => { + case TestSuitesKey => (tileParams: Seq[TileParams], suiteHelper: TestSuiteHelper, p: Parameters) => { + up(TestSuitesKey).apply(tileParams, suiteHelper, p) + import hwacha.HwachaTestSuites._ + suiteHelper.addSuites(rv64uv.map(_("p"))) + suiteHelper.addSuites(rv64uv.map(_("vp"))) + suiteHelper.addSuite(rv64sv("p")) + suiteHelper.addSuite(hwachaBmarks) + "SRC_EXTENSION = $(base_dir)/hwacha/$(src_path)/*.scala" + "\nDISASM_EXTENSION = --extension=hwacha" + } +}) \ No newline at end of file diff --git a/generators/chipyard/src/main/scala/GenericParams.scala b/generators/chipyard/src/main/scala/GenericParams.scala deleted file mode 100644 index 8ed0d0f3..00000000 --- a/generators/chipyard/src/main/scala/GenericParams.scala +++ /dev/null @@ -1,177 +0,0 @@ -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._ -import freechips.rocketchip.diplomacy.{LazyModule, ClockCrossingType, ValName} -import freechips.rocketchip.diplomaticobjectmodel.logicaltree.LogicalTreeNode -import freechips.rocketchip.rocket._ -import freechips.rocketchip.tile._ - -// Trait for generic case class of base trait for copying -trait ConcreteBaseTrait[Base] { - this: Product => - val _origin: Base - - // Convert back to core-specific tile - def convert: Base = { - // Reflection Info of this class - val fieldNames = (this.getClass.getDeclaredFields map (f => f.getName)).init - - // 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 map { - case c: ConcreteBaseTrait[_] => c.convert - case v => v - } - 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[Base] - } -} - -// Case class to change common parameters visible in the base traits. Some fields in the base traits may not be configurable as a -// case class constructor parameter for some cores, and those field will be ignored when applied. -case class GenericCoreParams( - val bootFreqHz: BigInt, - val useVM: Boolean, - val useUser: Boolean, - val useSupervisor: Boolean, - val useDebug: Boolean, - 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 with ConcreteBaseTrait[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 - ) - - // Implement abstract function as placeholder - def lrscCycles: Int = _origin.lrscCycles -} - -case class GenericTileParams( - val core: GenericCoreParams, - val icache: Option[ICacheParams], - val dcache: Option[DCacheParams], - val btb: Option[BTBParams], - val hartId: Int, - val beuAddr: Option[BigInt], - val blockerCtrlAddr: Option[BigInt], - val name: Option[String], - // The original object - val _origin: TileParams, -) extends TileParams with ConcreteBaseTrait[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 - ) -} - -case class GenericTileCrossingParamsLike( - val crossingType: ClockCrossingType, - val master: TilePortParamsLike, - val slave: TilePortParamsLike, - val _origin: TileCrossingParamsLike -) extends TileCrossingParamsLike with ConcreteBaseTrait[TileCrossingParamsLike] { - def this(crossing: TileCrossingParamsLike) = this( - crossingType = crossing.crossingType, - master = crossing.master, - slave = crossing.slave, - _origin = crossing - ) -} - -case class GenericCanAttachTileImpl( - val tileParams: GenericTileParams, - val crossingParams: TileCrossingParamsLike, - val lookup: LookupByHartIdImpl, - val _origin: CanAttachTile, -) extends ConcreteBaseTrait[CanAttachTile] { - def this(param: CanAttachTile) = this( - tileParams = new GenericTileParams(param.tileParams), - crossingParams = new GenericTileCrossingParamsLike(param.crossingParams), - lookup = param.lookup, - _origin = param - ) -} - -object GenericCanAttachTile { - def unapply(tile: CanAttachTile) = Some(new GenericCanAttachTileImpl(tile)) -} diff --git a/generators/chipyard/src/main/scala/TestSuites.scala b/generators/chipyard/src/main/scala/TestSuites.scala index 77aab39b..9ca2c08c 100644 --- a/generators/chipyard/src/main/scala/TestSuites.scala +++ b/generators/chipyard/src/main/scala/TestSuites.scala @@ -107,13 +107,8 @@ class TestSuiteHelper /** * Config key of custom test suite. */ -case object TestSuitesKey extends Field[(Seq[TileParams], TestSuiteHelper, Parameters) => Unit]((tiles, helper, p) => helper.addGenericTestSuites(tiles)(p)) - -/** - * Config fragment to add custom test suite factory function. - * - * @param suiteFactory Test suite factory function. It takes a list of TileParams to be instantiated and the test suite helper. - */ -class WithTestSuite(suiteFactory: (Seq[TileParams], TestSuiteHelper, Parameters) => Unit) extends Config((site, here, up) => { - case TestSuitesKey => suiteFactory +case object TestSuitesKey extends Field[(Seq[TileParams], TestSuiteHelper, Parameters) => String]((tiles, helper, p) => { + helper.addGenericTestSuites(tiles)(p) + // Return an empty string as makefile additional snippets + "" }) diff --git a/generators/chipyard/src/main/scala/config/BoomConfigs.scala b/generators/chipyard/src/main/scala/config/BoomConfigs.scala index 7b66e3b3..414f10af 100644 --- a/generators/chipyard/src/main/scala/config/BoomConfigs.scala +++ b/generators/chipyard/src/main/scala/config/BoomConfigs.scala @@ -106,6 +106,7 @@ class HwachaLargeBoomConfig extends Config( new chipyard.config.WithBootROM ++ new chipyard.config.WithUART ++ new chipyard.config.WithL2TLBs(1024) ++ + new chipyard.config.WithHwachaTest ++ new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator new freechips.rocketchip.subsystem.WithNoMMIOPort ++ new freechips.rocketchip.subsystem.WithNoSlavePort ++ diff --git a/generators/chipyard/src/main/scala/config/HeteroConfigs.scala b/generators/chipyard/src/main/scala/config/HeteroConfigs.scala index a7d1c133..4930ddee 100644 --- a/generators/chipyard/src/main/scala/config/HeteroConfigs.scala +++ b/generators/chipyard/src/main/scala/config/HeteroConfigs.scala @@ -36,6 +36,7 @@ class HwachaLargeBoomAndHwachaRocketConfig extends Config( new chipyard.config.WithBootROM ++ new chipyard.config.WithUART ++ new chipyard.config.WithL2TLBs(1024) ++ + new chipyard.config.WithHwachaTest ++ new hwacha.DefaultHwachaConfig ++ // add hwacha to all harts new boom.common.WithNLargeBooms(1) ++ new freechips.rocketchip.subsystem.WithNoMMIOPort ++ diff --git a/generators/chipyard/src/main/scala/config/RocketConfigs.scala b/generators/chipyard/src/main/scala/config/RocketConfigs.scala index 06257c7b..566e2757 100644 --- a/generators/chipyard/src/main/scala/config/RocketConfigs.scala +++ b/generators/chipyard/src/main/scala/config/RocketConfigs.scala @@ -34,6 +34,7 @@ class HwachaRocketConfig extends Config( new chipyard.config.WithBootROM ++ new chipyard.config.WithUART ++ new chipyard.config.WithL2TLBs(1024) ++ + new chipyard.config.WithHwachaTest ++ new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator new freechips.rocketchip.subsystem.WithNoMMIOPort ++ new freechips.rocketchip.subsystem.WithNoSlavePort ++ diff --git a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala index 623dbce4..177d26b0 100644 --- a/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala +++ b/generators/chipyard/src/main/scala/stage/phases/AddDefaultTests.scala @@ -38,24 +38,8 @@ class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipS val tileParams = p(TilesLocated(InSubsystem)) map (tp => tp.tileParams) if (p.lift(XLen).nonEmpty) // If a custom test suite is set up, use the custom test suite - if (p.lift(TestSuitesKey).nonEmpty) - p(TestSuitesKey).apply(tileParams, suiteHelper, p) - else - suiteHelper.addGenericTestSuites(tileParams) + annotations += CustomMakefragSnippet(p(TestSuitesKey).apply(tileParams, suiteHelper, p)) - // if hwacha parameter exists then generate its tests - // TODO: find a more elegant way to do this. either through - // trying to disambiguate BuildRoCC, having a AccelParamsKey, - // or having the Accelerator/Tile add its own tests - import hwacha.HwachaTestSuites._ - if (Try(p(hwacha.HwachaNLanes)).getOrElse(0) > 0) { - suiteHelper.addSuites(rv64uv.map(_("p"))) - suiteHelper.addSuites(rv64uv.map(_("vp"))) - suiteHelper.addSuite(rv64sv("p")) - suiteHelper.addSuite(hwachaBmarks) - annotations += CustomMakefragSnippet( - "SRC_EXTENSION = $(base_dir)/hwacha/$(src_path)/*.scala" + "\nDISASM_EXTENSION = --extension=hwacha") - } RocketTestSuiteAnnotation(suiteHelper.suites.values.toSeq) +: annotations } From d77c4afb36ec37414dadbef63904376f8e0853d3 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Mon, 29 Jun 2020 12:05:24 -0700 Subject: [PATCH 19/20] Rollback .gitignore --- .gitignore | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.gitignore b/.gitignore index 57467069..35d9b2d8 100644 --- a/.gitignore +++ b/.gitignore @@ -10,10 +10,6 @@ target *# *~ .idea -.bloop -.metals -project/metals.sbt -.vscode .DS_Store env.sh riscv-tools-install From 763ba42b4c35915d1824b662fe73976697b0662b Mon Sep 17 00:00:00 2001 From: Albert Ou Date: Wed, 8 Jul 2020 12:36:09 -0700 Subject: [PATCH 20/20] Bump testchipip for FDT alignment and minLatency fixes --- generators/testchipip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/testchipip b/generators/testchipip index 29eb87c9..8b5c89a5 160000 --- a/generators/testchipip +++ b/generators/testchipip @@ -1 +1 @@ -Subproject commit 29eb87c938a2106249b85e3b3dffd00046f5077c +Subproject commit 8b5c89a5f7120e64a7ac5ce5210165426a58f3de