From ff583e9e1f5c136d65f510c35584fe2ffff46815 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Wed, 20 May 2020 15:44:07 -0700 Subject: [PATCH 01/63] 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/63] 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/63] 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/63] 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/63] 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/63] 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/63] 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/63] 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/63] 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/63] 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/63] 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/63] 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/63] 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/63] 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/63] 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/63] 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 5acf583d88088f3d36f9c2ec7fc903ac1c095749 Mon Sep 17 00:00:00 2001 From: Sam Steffl Date: Thu, 18 Jun 2020 13:55:33 -0700 Subject: [PATCH 17/63] OpenROAD synthesis complete with fake rams on nangate45 --- vlsi/.gitignore | 3 +- vlsi/Makefile | 20 +++-- vlsi/example-nangate45.yml | 144 ++++++++++++++++++++++++++++++++++++ vlsi/example-vlsi-nangate45 | 29 ++++++++ vlsi/hammer | 2 +- 5 files changed, 188 insertions(+), 10 deletions(-) create mode 100644 vlsi/example-nangate45.yml create mode 100755 vlsi/example-vlsi-nangate45 diff --git a/vlsi/.gitignore b/vlsi/.gitignore index 4cbcfe8f..abe3347f 100644 --- a/vlsi/.gitignore +++ b/vlsi/.gitignore @@ -3,4 +3,5 @@ __pycache__ hammer*.log build src/test/output-*.json -generated-src \ No newline at end of file +generated-src +output.json diff --git a/vlsi/Makefile b/vlsi/Makefile index 42af7ba2..912eecdd 100644 --- a/vlsi/Makefile +++ b/vlsi/Makefile @@ -19,18 +19,22 @@ include $(base_dir)/variables.mk ######################################################################################### sim_name ?= vcs # needed for GenerateSimFiles, but is unused tech_name ?= asap7 -tech_dir ?= $(if $(filter $(tech_name), asap7), $(vlsi_dir)/hammer/src/hammer-vlsi/technology/$(tech_name), $(vlsi_dir)/hammer-$(tech_name)-plugin/$(tech_name)) +tech_dir ?= $(if $(filter $(tech_name),asap7 nangate45),\ + $(vlsi_dir)/hammer/src/hammer-vlsi/technology/$(tech_name), \ + $(vlsi_dir)/hammer-$(tech_name)-plugin/$(tech_name)) SMEMS_COMP ?= $(tech_dir)/sram-compiler.json SMEMS_CACHE ?= $(tech_dir)/sram-cache.json SMEMS_HAMMER ?= $(build_dir)/$(long_name).mems.hammer.json -ifeq ($(tech_name),asap7) - MACROCOMPILER_MODE ?= --mode synflops -else - MACROCOMPILER_MODE ?= -l $(SMEMS_CACHE) -hir $(SMEMS_HAMMER) -endif +MACROCOMPILER_MODE ?= $(if $(filter $(tech_name),asap7),\ + --mode synflops,\ + -l $(SMEMS_CACHE) -hir $(SMEMS_HAMMER) --mode strict) ENV_YML ?= $(vlsi_dir)/env.yml -INPUT_CONFS ?= example.yml -HAMMER_EXEC ?= ./example-vlsi +INPUT_CONFS ?= $(if $(filter $(tech_name),nangate45),\ + example-nangate45.yml,\ + example.yml) +HAMMER_EXEC ?= $(if $(filter $(tech_name),nangate45),\ + example-vlsi-nangate45,\ + example-vlsi) VLSI_TOP ?= $(TOP) VLSI_HARNESS_DUT_NAME ?= dut VLSI_OBJ_DIR ?= $(vlsi_dir)/build diff --git a/vlsi/example-nangate45.yml b/vlsi/example-nangate45.yml new file mode 100644 index 00000000..de4d912f --- /dev/null +++ b/vlsi/example-nangate45.yml @@ -0,0 +1,144 @@ +# Technology Setup +# Technology used is nanagate45 +vlsi.core.technology: nangate45 +# Specify dir with ASAP7 tarball +technology.nangate45.install_dir: "/k/work/OpenROAD-flow/tools/OpenROAD" + +vlsi.core.max_threads: 12 + +# General Hammer Inputs + +# Hammer will auto-generate a CPF for simple power designs; see hammer/src/hammer-vlsi/defaults.yml for more info +vlsi.inputs.power_spec_mode: "auto" +vlsi.inputs.power_spec_type: "cpf" + +# Specify clock signals +vlsi.inputs.clocks: [ + {name: "clock", period: "5ns", uncertainty: "0.5ns"} +] + +# Generate Make include to aid in flow +vlsi.core.build_system: make + +# Power Straps +#par.power_straps_mode: generate +#par.generate_power_straps_method: by_tracks +#par.blockage_spacing: 2.0 +#par.generate_power_straps_options: +# by_tracks: +# strap_layers: +# - metal3 +# - metal4 +# - metal5 +# - metal6 +# - metal7 +# - metal8 +# pin_layers: +# - metal7 +# - metal8 +# track_width: 7 # minimum allowed for M2 & M3 +# track_spacing: 0 +# track_spacing_M3: 1 # to avoid M2 shorts at higher density +# track_start: 10 +# power_utilization: 0.05 +# power_utilization_M8: 1.0 +# power_utilization_M9: 1.0 + +# Placement Constraints +# For ASAP7, all numbers must be 4x larger than final GDS +vlsi.inputs.placement_constraints: + - path: "ChipTop" + type: toplevel + x: 0 + y: 0 + width: 1387.38 + height: 1199.1 + margins: + left: 0 + right: 0 + top: 0 + bottom: 0 +# - path: "Sha3AccelwBB/dco" +# type: hardmacro +# x: 108 +# y: 108 +# width: 128 +# height: 128 +# orientation: r0 +# top_layer: M9 +# - path: "Sha3AccelwBB/place_obs_bottom" +# type: obstruction +# obs_types: ["place"] +# x: 0 +# y: 0 +# width: 300 +# height: 1.08 # 1 core site tall, necessary to avoid shorts + +# Pin placement constraints +#vlsi.inputs.pin_mode: generated +#vlsi.inputs.pin.generate_mode: semi_auto +#vlsi.inputs.pin.assignments: [ +# {pins: "*", layers: ["metal7", "metal8"]} +#] + +# Paths to extra libraries +#vlsi.technology.extra_libraries_meta: ["append", "deepsubst"] +#vlsi.technology.extra_libraries: +# - library: +# nldm liberty file_deepsubst_meta: "local" +# nldm liberty file: "extra_libraries/example/ExampleDCO_PVT_0P63V_100C.lib" +# lef file_deepsubst_meta: "local" +# lef file: "extra_libraries/example/ExampleDCO.lef" +# gds file_deepsubst_meta: "local" +# gds file: "extra_libraries/example/ExampleDCO.gds" +# corner: +# nmos: "slow" +# pmos: "slow" +# temperature: "100 C" +# supplies: +# VDD: "0.63 V" +# GND: "0 V" +# - library: +# nldm liberty file_deepsubst_meta: "local" +# nldm liberty file: "extra_libraries/example/ExampleDCO_PVT_0P77V_0C.lib" +# lef file_deepsubst_meta: "local" +# lef file: "extra_libraries/example/ExampleDCO.lef" +# gds file_deepsubst_meta: "local" +# gds file: "extra_libraries/example/ExampleDCO.gds" +# corner: +# nmos: "fast" +# pmos: "fast" +# temperature: "0 C" +# supplies: +# VDD: "0.77 V" +# GND: "0 V" + +# Because the DCO is a dummy layout, we treat it as a physical-only cell +#par.inputs.physical_only_cells_mode: append +#par.inputs.physical_only_cells_list: +# - ExampleDCO + +# SRAM Compiler compiler options +vlsi.core.sram_generator_tool: "sram_compiler" +## You should specify a location for the SRAM generator in the tech plugin +vlsi.core.sram_generator_tool_path: ["hammer/src/hammer-vlsi/technology/nangate45"] +vlsi.core.sram_generator_tool_path_meta: "append" + +# Tool options. Replace with your tool plugin of choice. +# yosys options +vlsi.core.synthesis_tool: "yosys" +vlsi.core.synthesis_tool_path: ["hammer/src/hammer-vlsi/synthesis/yosys"] +vlsi.core.synthesis_tool_path_meta: "append" + +# Innovus options +#vlsi.core.par_tool: "innovus" +#vlsi.core.par_tool_path: ["hammer-cadence-plugins/par"] +#vlsi.core.par_tool_path_meta: "append" +#par.innovus.version: "181" +#par.innovus.design_flow_effort: "standard" +#par.inputs.gds_merge: true +## Calibre options +#vlsi.core.drc_tool: "calibre" +#vlsi.core.drc_tool_path: ["hammer-mentor-plugins/drc"] +#vlsi.core.lvs_tool: "calibre" +#vlsi.core.lvs_tool_path: ["hammer-mentor-plugins/lvs"] diff --git a/vlsi/example-vlsi-nangate45 b/vlsi/example-vlsi-nangate45 new file mode 100755 index 00000000..39b9a493 --- /dev/null +++ b/vlsi/example-vlsi-nangate45 @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +import os + +import hammer_vlsi +from hammer_vlsi import CLIDriver, HammerToolHookAction + +from typing import Dict, Callable, Optional, List + +def example_place_tap_cells(x: hammer_vlsi.HammerTool) -> bool: + x.append("") + return True + +def example_add_fillers(x: hammer_vlsi.HammerTool) -> bool: + x.append("") + return True + +class ExampleDriver(CLIDriver): + def get_extra_par_hooks(self) -> List[HammerToolHookAction]: + extra_hooks = [ + # make_pre_insertion_hook will execute the custom hook before the specified step + hammer_vlsi.HammerTool.make_pre_insertion_hook("route_design", example_add_fillers), + + # make_replacement_hook will replace the specified step with a custom hook + hammer_vlsi.HammerTool.make_replacement_hook("place_tap_cells", example_place_tap_cells), + ] + return extra_hooks + +if __name__ == '__main__': + ExampleDriver().main() diff --git a/vlsi/hammer b/vlsi/hammer index bd94e1ed..657feaed 160000 --- a/vlsi/hammer +++ b/vlsi/hammer @@ -1 +1 @@ -Subproject commit bd94e1ed7a5f70fe85ea833cb89836efefe53dc7 +Subproject commit 657feaed58014f4ef5b76acaa1e0cc559f182bda From 254304428bfcce91dd9c396c9fdcb7c7a12c135f Mon Sep 17 00:00:00 2001 From: Sam Steffl Date: Fri, 19 Jun 2020 12:03:59 -0700 Subject: [PATCH 18/63] refactored openroad stuff into OpenROADTool base class. fixed PR suggestions --- vlsi/Makefile | 22 +++++++++++----------- vlsi/example-nangate45.yml | 3 ++- vlsi/hammer | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/vlsi/Makefile b/vlsi/Makefile index 912eecdd..e969ba14 100644 --- a/vlsi/Makefile +++ b/vlsi/Makefile @@ -20,28 +20,28 @@ include $(base_dir)/variables.mk sim_name ?= vcs # needed for GenerateSimFiles, but is unused tech_name ?= asap7 tech_dir ?= $(if $(filter $(tech_name),asap7 nangate45),\ - $(vlsi_dir)/hammer/src/hammer-vlsi/technology/$(tech_name), \ - $(vlsi_dir)/hammer-$(tech_name)-plugin/$(tech_name)) + $(vlsi_dir)/hammer/src/hammer-vlsi/technology/$(tech_name), \ + $(vlsi_dir)/hammer-$(tech_name)-plugin/$(tech_name)) SMEMS_COMP ?= $(tech_dir)/sram-compiler.json SMEMS_CACHE ?= $(tech_dir)/sram-cache.json SMEMS_HAMMER ?= $(build_dir)/$(long_name).mems.hammer.json MACROCOMPILER_MODE ?= $(if $(filter $(tech_name),asap7),\ - --mode synflops,\ - -l $(SMEMS_CACHE) -hir $(SMEMS_HAMMER) --mode strict) + --mode synflops,\ + -l $(SMEMS_CACHE) -hir $(SMEMS_HAMMER) --mode strict) ENV_YML ?= $(vlsi_dir)/env.yml INPUT_CONFS ?= $(if $(filter $(tech_name),nangate45),\ - example-nangate45.yml,\ - example.yml) + example-nangate45.yml,\ + example.yml) HAMMER_EXEC ?= $(if $(filter $(tech_name),nangate45),\ - example-vlsi-nangate45,\ - example-vlsi) + example-vlsi-nangate45,\ + example-vlsi) VLSI_TOP ?= $(TOP) VLSI_HARNESS_DUT_NAME ?= dut VLSI_OBJ_DIR ?= $(vlsi_dir)/build -ifneq ($(CUSTOM_VLOG), ) - OBJ_DIR ?= $(VLSI_OBJ_DIR)/custom-$(VLSI_TOP) +ifneq ($(CUSTOM_VLOG),) + OBJ_DIR ?= $(VLSI_OBJ_DIR)/custom-$(VLSI_TOP) else - OBJ_DIR ?= $(VLSI_OBJ_DIR)/$(long_name)-$(VLSI_TOP) + OBJ_DIR ?= $(VLSI_OBJ_DIR)/$(long_name)-$(VLSI_TOP) endif ######################################################################################### diff --git a/vlsi/example-nangate45.yml b/vlsi/example-nangate45.yml index de4d912f..b4c1288a 100644 --- a/vlsi/example-nangate45.yml +++ b/vlsi/example-nangate45.yml @@ -1,7 +1,8 @@ # Technology Setup -# Technology used is nanagate45 vlsi.core.technology: nangate45 + # Specify dir with ASAP7 tarball +# TODO: figure out how to remove this, or override it within OpenROADTool technology.nangate45.install_dir: "/k/work/OpenROAD-flow/tools/OpenROAD" vlsi.core.max_threads: 12 diff --git a/vlsi/hammer b/vlsi/hammer index 657feaed..c5a3cdf8 160000 --- a/vlsi/hammer +++ b/vlsi/hammer @@ -1 +1 @@ -Subproject commit 657feaed58014f4ef5b76acaa1e0cc559f182bda +Subproject commit c5a3cdf84987a46c91f3f879541060757bf225fb From c5c272b90dbc3532de5429056cd43c30dc28c25c Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Fri, 19 Jun 2020 13:51:57 -0700 Subject: [PATCH 19/63] Custom core doc first draft --- docs/Customization/Custom-Core.rst | 286 ++++++++++++++++++++++ docs/Customization/Heterogeneous-SoCs.rst | 2 + docs/Customization/index.rst | 2 + 3 files changed, 290 insertions(+) create mode 100644 docs/Customization/Custom-Core.rst diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst new file mode 100644 index 00000000..bffdc236 --- /dev/null +++ b/docs/Customization/Custom-Core.rst @@ -0,0 +1,286 @@ +.. _custom_core: + +Adding a custom core +==================== + +You may want to add a custom RISC-V core to Chipyard generator. If the top module of your core is not in Chisel, +you will first need to create a Verilog blackbox for it. See ::ref:`_incorporating-verilog-blocks` for instructions. +Once you have a top module in Chisel, you are ready to create integrate it with Chipyard. + +.. note:: + + RoCC is not supported by custom core currently. Please use Rocket or Boom if you need to use RoCC. + +.. note:: + + Custom core doesn't support FireSim at this time. + +Parameter Case Classes +---------------------- + +Chipyard will generate a core for every ``TileParams`` object it discovered in the current config. +``TileParams`` is a trait containing the information needed to create a tile, and every custom core must implement +their own version of ``TileParams``, as well as ``CoreParams`` which is passed as a field in ``TileParams``. + +``TileParams`` holds the parameters that are the same for every generated core, while ``CoreParams`` contains those +that can vary from cores to cores. They must be implemented as case classes with fields that can be overridden by +other config fragments as the constructor parameters. See the appendix at the bottom of the page for a list of +variable to be implemented. You can also add custom fields to them, but standard fields should always be preferred. + +Now you have your parameter classes, you will need config keys to hold them. There are two required keys: + +.. code-block:: scala + + case object MyTilesKey extends Field[Seq[MyTileParams]](Nil) + case object MyCrossingKey extends Field[Seq[RocketCrossingParams]](List(RocketCrossingParams())) + +``MyCrossingKey`` here is used to store information about the clock-crossing behavior of the core, and it is normally +set to its default values. + +``TileParams`` and ``CoreParams`` contains the following fields: + +.. code-block:: scala + + trait TileParams { + val core: CoreParams // Core parameters (see below) + val icache: Option[ICacheParams] // Not used if you use your own I1 cache + val dcache: Option[DCacheParams] // Not used if you use your own D1 cache + val btb: Option[BTBParams] // Not used if you use your own BTB / branch predictor + val hartId: Int // Hart ID: Must be unique within a design config + val beuAddr: Option[BigInt] + val blockerCtrlAddr: Option[BigInt] + val name: Option[String] // Name of the core + } + + trait CoreParams { + val bootFreqHz: BigInt // Frequency + val useVM: Boolean // Support virtual memory + val useUser: Boolean // Support user mode + val useSupervisor: Boolean // Support supervisor mode + val useDebug: Boolean // Support RISC-V debug specs + val useAtomics: Boolean // Support A extension + val useAtomicsOnlyForIO: Boolean // Support A extension for memory-mapped IO (may be true even if useAtomics is false) + val useCompressed: Boolean // Support C extension + val useVector: Boolean = false // Support V extension + val useSCIE: Boolean + val useRVE: Boolean + val mulDiv: Option[MulDivParams] // M extension and related setting (Only used by Rocket core, simply use its default value) + val fpu: Option[FPUParams] // F and D extensions and related setting (see below) + val fetchWidth: Int // Max # of insts fetched every cycle + val decodeWidth: Int // Max # of insts decoded every cycle + val retireWidth: Int // Max # of insts retired every cycle + val instBits: Int // Instruction bits (if 32 bit and 64 bit are both supported, use 64) + val nLocalInterrupts: Int // # of local interrupts (see SiFive interrupt cookbook) + val nPMPs: Int // # of Physical Memory Protection units + val pmpGranularity: Int // Size of the smallest unit of region for PMP unit (must be power of 2) + val nBreakpoints: Int // # of breakpoints supported (in RISC-V debug specs) + val useBPWatch: Boolean + val nPerfCounters: Int // # of supported performance counters + val haveBasicCounters: Boolean // Support basic counters defined in the RISC-V counter extension + val haveFSDirty: Boolean + val misaWritable: Boolean // Support writable misa CSR (like variable instruction bits) + val haveCFlush: Boolean + val nL2TLBEntries: Int // # of L2 TLB entries + val mtvecInit: Option[BigInt] // mtvec CSR (of V extension) initial value + val mtvecWritable: Boolean // If mtvec CSR is writable + + // Normally, you don't need to change these values (except lrscCycles) + def customCSRs(implicit p: Parameters): CustomCSRs = new CustomCSRs + + def hasSupervisorMode: Boolean = useSupervisor || useVM + def instBytes: Int = instBits / 8 + def fetchBytes: Int = fetchWidth * instBytes + // This field is used only with the D1 cache of Rocket chip. Simply set it to the default value 80. + def lrscCycles: Int + + def dcacheReqTagBits: Int = 6 + + def minFLen: Int = 32 + def vLen: Int = 0 + def sLen: Int = 0 + def eLen(xLen: Int, fLen: Int): Int = xLen max fLen + def vMemDataBits: Int = 0 + } + + case class FPUParams( + minFLen: Int = 32, // Minimum floating point length (no need to change) + fLen: Int = 64, // Maximum floating point length, use 32 if only single precision is supported + divSqrt: Boolean = true, // Div/Sqrt operation supported + sfmaLatency: Int = 3, // + dfmaLatency: Int = 4 + ) + +Most of the fields here are originally designed for Rocket core and contains some architecture-specific details, but +many of them are general enough to be useful for other cores. It is strongly recommended to use these fields instead +of creating your own custom fields when applicable. + +Tile Class +---------- + +In Chipyard, all connections with other components on SoC are defined a core's `Tile` class, while the implementation +of the actual hardware are in the implementation class. This structure allows Chipyard to use the Diplomacy framework +to resolve paramters and connections before elaboration. + +All tile classes implement ``BaseTile`` and will normally implement ``SinksExternalInterrupts`` and ``SourcesExternalNotifications``, +which allow the tile to accept external interrupt. A typical tile has the following form: + +.. code-block:: scala + + class MyTile( + val myParams: MyTileParams, + crossing: ClockCrossingType, + lookup: LookupByHartIdImpl, + q: Parameters, + logicalTreeNode: LogicalTreeNode) + extends BaseTile(myParams, crossing, lookup, q) + with SinksExternalInterrupts + with SourcesExternalNotifications + { + + // Private constructor ensures altered LazyModule.p is used implicitly + def this(params: MyTileParams, crossing: RocketCrossingParams, lookup: LookupByHartIdImpl, logicalTreeNode: LogicalTreeNode)(implicit p: Parameters) = + this(params, crossing.crossingType, lookup, p, logicalTreeNode) + + // Require TileLink nodes + val intOutwardNode = IntIdentityNode() + val masterNode = visibilityNode + val slaveNode = TLIdentityNode() + + // Implementation class (See below) + override lazy val module = new MyTileModuleImp(this) + + // Required entry of CPU device in the device tree for interrupt purpose + val cpuDevice: SimpleDevice = new SimpleDevice("cpu", Seq("my-organization,my-cpu", "riscv")) { + override def parent = Some(ResourceAnchors.cpus) + override def describe(resources: ResourceBindings): Description = { + val Description(name, mapping) = super.describe(resources) + Description(name, mapping ++ + cpuProperties ++ + nextLevelCacheProperty ++ + tileProperties) + } + } + + ResourceBinding { + Resource(cpuDevice, "reg").bind(ResourceAddress(hartId)) + } + + // (Connection to bus, interrupt, etc.) + } + +TileLink Connection +------------------- + +Chipyard use TileLink as its onboard bus protocol, and if your core doesn't use TileLink, you will need to convert them +in the tile class. Below is an example of how to connect a core using AXI4 to the TileLink bus: + +.. code-block:: scala + + val memoryTap = TLIdentityNode() // Every bus connection should have their own tap node + (tlMasterXbar.node // tlMasterXbar is the bus crossbar to be used when this core / tile is acting as a master; otherwise, use tlSlaveXBar + := memoryTap + := TLBuffer() + := TLFIFOFixer(TLFIFOFixer.all) // fix FIFO ordering + := TLWidthWidget(beatBytes) // reduce size of TL + := AXI4ToTL() // convert to TL + := AXI4UserYanker(Some(2)) // remove user field on AXI interface. need but in reality user intf. not needed + := AXI4Fragmenter() // deal with multi-beat xacts + := memAXI4Node) // The custom node, see below + +Remember, you may not need all of these intermediate widgets. See :::ref:`Diplomatic-Widgets` for the meaning of each intermediate +widget. If you are using TileLink, then you only need the tap node and the TileLink node used by your components. Also, Chipyard +support AHB, APB and AXIS, and most of the AXI4 widgets has equivalent widget for these bus protocol. See the reference page for +more info. + +``memAXI4Node`` is an AXI4 master node and is defined as following in our example: + +.. code-block:: scala + + val memAXI4Node = AXI4MasterNode( + Seq(AXI4MasterPortParameters( + masters = Seq(AXI4MasterParameters( + name = portName, + id = IdRange(0, 1 << idBits)))))) + +where ``portName`` and ``idBits`` are the parameter provides by the tile. Make sure to read :::ref:`node-tyoes` to check out what +type of nodes Chipyard supports and their parameters! + +Also, by default, there are boundary buffers for both master and slave connections to the bus when they are leaving the tile, and you +can override the following two functions to control how to buffer the bus requests/responses: + +.. code-block:: scala + + protected def makeMasterBoundaryBuffers(implicit p: Parameters): TLBuffer + protected def makeSlaveBoundaryBuffers(implicit p: Parameters): TLBuffer + +Interrupt +--------- + +Chipyard allows a tile to either receive interrupts from other devices or initiate interrupts to notify other cores/devices. +In the tile that inherited ``SinksExternalInterrupts``, one can create a ``TileInterrupts`` object (a Chisel bundle) and +call ``decodeCoreInterrupts`` with the object as the argument. You can then read the interrupt bits from the object. +The definition of ``TileInterrupts`` is + +.. code-block:: scala + + class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) { + val debug = Bool() // debug interrupt + val mtip = Bool() // Machine level timer interrupt + val msip = Bool() // Machine level software interrupt + val meip = Bool() // Machine level external interrupt + val seip = usingSupervisor.option(Bool()) // Valid only if supervisor mode is supported + val lip = Vec(coreParams.nLocalInterrupts, Bool()) // Local interrupts + } + +This function should be in the implementation class since it involves hardware generation. +Also, the tile can also notify other cores or devices for some events by calling following functions (in implementation class): + +.. code-block:: scala + + def reportHalt(could_halt: Option[Bool]) // Triggered when there is an unrecoverable hardware error (halt the machine) + def reportHalt(errors: Seq[CanHaveErrors]) // Varient for standard error bundle (used only by cache when there's an ECC error) + reportCease(could_cease: Option[Bool], quiescenceCycles: Int = 8) // Triggered when the core stop retiring instructions (like clock gating) + reportWFI(could_wfi: Option[Bool]) // Triggered when a WFI instruciton is executed + +Implementation Class +-------------------- + +The implementation class is of the following form: + +.. code-block:: scala + + class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){ + // annotate the parameters + Annotated.params(this, outer.tileParams) + + // TODO: Create the top module of the core and connect it with the ports in "outer" + } + +In the body of this class, you can look up any parameters by calling ``p({key})``, where ``{key}`` is the config key of +the value you want to look up. For a list of available keys, see the appendix below. + +If you create an AXI4 node (or equivalents), you will need to connect them to your core. + +Integrate the Core +------------------ + +To use your core in a set of config, you would need a config fragment that would create a ``TileParams`` object of your core in +the current config. An example of such config will be like this: + +.. code-block:: scala + + class WithNMyCores(n: Int) extends Config( + new RegisterCore(new CoreEntry[MyTileParams, MyTile]("MyCore", MyTilesKey, MyCrossingKey)) ++ + new Config((site, here, up) => { + case MyTilesKey => { + List.tabulate(n)(i => MyTileParams(hartId = i)) + } + }) + ) + +Where ``RegisterCore`` will register the core with chipyard so that it can be recognized by generic config. This is required for +all custom cores. You can also create other config fragments to change other parameters. + +Now you have finished all the steps to prepare your cores for Chipyard! To generate the custom core, simply follow the instructions +in :::ref:`_custom_chisel` to add your project to the build system, then create a config by following the steps in :::ref:`_hetero_socs_`. +You can now run any desired workflow for the new config just as you do for the built-in cores. diff --git a/docs/Customization/Heterogeneous-SoCs.rst b/docs/Customization/Heterogeneous-SoCs.rst index c640e31c..204b3159 100644 --- a/docs/Customization/Heterogeneous-SoCs.rst +++ b/docs/Customization/Heterogeneous-SoCs.rst @@ -1,3 +1,5 @@ +.. _hetero_socs_: + Heterogeneous SoCs =============================== diff --git a/docs/Customization/index.rst b/docs/Customization/index.rst index 9421b79a..38fdf622 100644 --- a/docs/Customization/index.rst +++ b/docs/Customization/index.rst @@ -7,6 +7,8 @@ These guides will walk you through customization of your system-on-chip: - How to include your custom Chisel sources in the Chipyard build system +- Adding custom core + - Adding custom RoCC accelerators to an existing Chipyard core (BOOM or Rocket) - Adding custom MMIO widgets to the Chipyard memory system by Tilelink or AXI4, with custom Top-level IOs From c407e39cd8c9a4a8dd2e2f19138174cc4cd6dffb Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sat, 20 Jun 2020 01:04:56 -0700 Subject: [PATCH 20/63] Completed most documentation (without AXI4 bus) --- docs/Customization/Custom-Core.rst | 78 ++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index bffdc236..5a5cc627 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -11,10 +11,6 @@ Once you have a top module in Chisel, you are ready to create integrate it with RoCC is not supported by custom core currently. Please use Rocket or Boom if you need to use RoCC. -.. note:: - - Custom core doesn't support FireSim at this time. - Parameter Case Classes ---------------------- @@ -37,18 +33,19 @@ Now you have your parameter classes, you will need config keys to hold them. The ``MyCrossingKey`` here is used to store information about the clock-crossing behavior of the core, and it is normally set to its default values. -``TileParams`` and ``CoreParams`` contains the following fields: +``TileParams`` and ``CoreParams`` contains the following fields (you may ignore any fields marked "Rocket specific" and +use their default values, although it is recommended to use them if you need a custom field with similar purposes) : .. code-block:: scala trait TileParams { val core: CoreParams // Core parameters (see below) - val icache: Option[ICacheParams] // Not used if you use your own I1 cache - val dcache: Option[DCacheParams] // Not used if you use your own D1 cache - val btb: Option[BTBParams] // Not used if you use your own BTB / branch predictor + val icache: Option[ICacheParams] // Rocket specific: I1 cache option + val dcache: Option[DCacheParams] // Rocket specific: D1 cache option + val btb: Option[BTBParams] // Rocket specific: BTB / branch predictor option val hartId: Int // Hart ID: Must be unique within a design config - val beuAddr: Option[BigInt] - val blockerCtrlAddr: Option[BigInt] + val beuAddr: Option[BigInt] // Rocket specific: Bus Error Unit for Rocket Core + val blockerCtrlAddr: Option[BigInt] // Rocket specific: Bus Blocker for Rocket Core val name: Option[String] // Name of the core } @@ -62,9 +59,9 @@ set to its default values. val useAtomicsOnlyForIO: Boolean // Support A extension for memory-mapped IO (may be true even if useAtomics is false) val useCompressed: Boolean // Support C extension val useVector: Boolean = false // Support V extension - val useSCIE: Boolean - val useRVE: Boolean - val mulDiv: Option[MulDivParams] // M extension and related setting (Only used by Rocket core, simply use its default value) + val useSCIE: Boolean // Support custom instructions (in custom-0 and custom-1) + val useRVE: Boolean // Use E base ISA + val mulDiv: Option[MulDivParams] // *Rocket specific: M extension related setting (Use Some(MulDivParams()) to indicate M extension supported) val fpu: Option[FPUParams] // F and D extensions and related setting (see below) val fetchWidth: Int // Max # of insts fetched every cycle val decodeWidth: Int // Max # of insts decoded every cycle @@ -73,13 +70,13 @@ set to its default values. val nLocalInterrupts: Int // # of local interrupts (see SiFive interrupt cookbook) val nPMPs: Int // # of Physical Memory Protection units val pmpGranularity: Int // Size of the smallest unit of region for PMP unit (must be power of 2) - val nBreakpoints: Int // # of breakpoints supported (in RISC-V debug specs) - val useBPWatch: Boolean + val nBreakpoints: Int // # of hardware breakpoints supported (in RISC-V debug specs) + val useBPWatch: Boolean // Support hardware breakpoints val nPerfCounters: Int // # of supported performance counters val haveBasicCounters: Boolean // Support basic counters defined in the RISC-V counter extension - val haveFSDirty: Boolean + val haveFSDirty: Boolean // If true, the core will set FS field in mstatus CSR to dirty when appropriate val misaWritable: Boolean // Support writable misa CSR (like variable instruction bits) - val haveCFlush: Boolean + val haveCFlush: Boolean // Rocket specific: enables Rocket's custom instruction extension to flush the cache val nL2TLBEntries: Int // # of L2 TLB entries val mtvecInit: Option[BigInt] // mtvec CSR (of V extension) initial value val mtvecWritable: Boolean // If mtvec CSR is writable @@ -90,7 +87,7 @@ set to its default values. def hasSupervisorMode: Boolean = useSupervisor || useVM def instBytes: Int = instBits / 8 def fetchBytes: Int = fetchWidth * instBytes - // This field is used only with the D1 cache of Rocket chip. Simply set it to the default value 80. + // Rocket specific: Longest possible latency of Rocket core D1 cache. Simply set it to the default value 80. def lrscCycles: Int def dcacheReqTagBits: Int = 6 @@ -106,8 +103,8 @@ set to its default values. minFLen: Int = 32, // Minimum floating point length (no need to change) fLen: Int = 64, // Maximum floating point length, use 32 if only single precision is supported divSqrt: Boolean = true, // Div/Sqrt operation supported - sfmaLatency: Int = 3, // - dfmaLatency: Int = 4 + sfmaLatency: Int = 3, // Rocket specific: Fused multiply-add pipeline latency (single precision) + dfmaLatency: Int = 4 // Rocket specific: Fused multiply-add pipeline latency (double precision) ) Most of the fields here are originally designed for Rocket core and contains some architecture-specific details, but @@ -213,6 +210,8 @@ can override the following two functions to control how to buffer the bus reques protected def makeMasterBoundaryBuffers(implicit p: Parameters): TLBuffer protected def makeSlaveBoundaryBuffers(implicit p: Parameters): TLBuffer +You can find more information on ``TLBuffer`` in :::ref:`Diplomatic-Widgets`. + Interrupt --------- @@ -240,7 +239,40 @@ Also, the tile can also notify other cores or devices for some events by calling def reportHalt(could_halt: Option[Bool]) // Triggered when there is an unrecoverable hardware error (halt the machine) def reportHalt(errors: Seq[CanHaveErrors]) // Varient for standard error bundle (used only by cache when there's an ECC error) reportCease(could_cease: Option[Bool], quiescenceCycles: Int = 8) // Triggered when the core stop retiring instructions (like clock gating) - reportWFI(could_wfi: Option[Bool]) // Triggered when a WFI instruciton is executed + reportWFI(could_wfi: Option[Bool]) // Triggered when a WFI instruction is executed + +Trace (Optional) +---------------- + +Chipyard provides a set of ports for instruction trace that conforms with related RISC-V standard. +If you are using FireSim, it is recommended to implement these trace ports to enable FireSim to read trace. + +There are one inbound node ``traceAuxSinkNode.bundle: TraceAux`` and two outbound nodes ``traceCoreSourceNode.bundle: TraceCoreInterface`` +and ``bpwatchSourceNode.bundle: Vec[BPWatch]``. Note that the length of ``bpwatchSourceNode`` is equal to the max number of +breakpoints (set by ``nBreakpoints`` in ``CoreParams``). Below is the definition of these types: + +.. code-block:: scala + + // Control signal from the external tracer + class TraceAux extends Bundle { + val enable = Bool() // Enable trace output + val stall = Bool() // If true, the core should stall + } + // Check RISC-V Processor Trace spec V1.0 for more information of this interface + class TraceCoreInterface (val params: TraceCoreParams) extends Bundle { + val group = Vec(params.nGroups, new TraceCoreGroup(params)) + val priv = UInt(4.W) + val tval = UInt(params.xlen.W) + val cause = UInt(params.xlen.W) + } + // Address Breakpoint and watchpoint info (n is the retire width) + class BPWatch (val n: Int) extends Bundle() { + val valid = Vec(n, Bool()) // Valid bit of the output + val rvalid = Vec(n, Bool()) // Break on read + val wvalid = Vec(n, Bool()) // Break on write + val ivalid = Vec(n, Bool()) // Break on execute + val action = UInt(3.W) // Exception code (3 usually) + } Implementation Class -------------------- @@ -261,6 +293,10 @@ the value you want to look up. For a list of available keys, see the appendix be If you create an AXI4 node (or equivalents), you will need to connect them to your core. +.. warning:: + + TODO: Documenting bus connection + Integrate the Core ------------------ From c617c4db24d6a58deb45399d1c655c57390170e6 Mon Sep 17 00:00:00 2001 From: Sam Steffl Date: Sat, 20 Jun 2020 13:15:56 -0700 Subject: [PATCH 21/63] openroad floorplanning broken at TritonMacroPlace. needs debugging --- vlsi/Makefile | 6 +- vlsi/{example.yml => example-asap7.yml} | 0 vlsi/example-nangate45.yml | 129 +++++------------------- vlsi/example-vlsi | 16 ++- vlsi/example-vlsi-nangate45 | 29 ------ vlsi/hammer | 2 +- 6 files changed, 43 insertions(+), 139 deletions(-) rename vlsi/{example.yml => example-asap7.yml} (100%) delete mode 100755 vlsi/example-vlsi-nangate45 diff --git a/vlsi/Makefile b/vlsi/Makefile index e969ba14..a9e3d3a5 100644 --- a/vlsi/Makefile +++ b/vlsi/Makefile @@ -31,10 +31,8 @@ MACROCOMPILER_MODE ?= $(if $(filter $(tech_name),asap7),\ ENV_YML ?= $(vlsi_dir)/env.yml INPUT_CONFS ?= $(if $(filter $(tech_name),nangate45),\ example-nangate45.yml,\ - example.yml) -HAMMER_EXEC ?= $(if $(filter $(tech_name),nangate45),\ - example-vlsi-nangate45,\ - example-vlsi) + example-asap7.yml) +HAMMER_EXEC ?= example-vlsi VLSI_TOP ?= $(TOP) VLSI_HARNESS_DUT_NAME ?= dut VLSI_OBJ_DIR ?= $(vlsi_dir)/build diff --git a/vlsi/example.yml b/vlsi/example-asap7.yml similarity index 100% rename from vlsi/example.yml rename to vlsi/example-asap7.yml diff --git a/vlsi/example-nangate45.yml b/vlsi/example-nangate45.yml index b4c1288a..7d43d068 100644 --- a/vlsi/example-nangate45.yml +++ b/vlsi/example-nangate45.yml @@ -1,15 +1,22 @@ +#---------------------- # Technology Setup +#---------------------- + vlsi.core.technology: nangate45 -# Specify dir with ASAP7 tarball +# the nangate45.tech.json can't reference the $OPENROAD environment variable, +# so we need to set the install dir here. # TODO: figure out how to remove this, or override it within OpenROADTool technology.nangate45.install_dir: "/k/work/OpenROAD-flow/tools/OpenROAD" vlsi.core.max_threads: 12 +#---------------------- # General Hammer Inputs +#---------------------- -# Hammer will auto-generate a CPF for simple power designs; see hammer/src/hammer-vlsi/defaults.yml for more info +# Hammer will auto-generate a CPF for simple power designs; +# see hammer/src/hammer-vlsi/defaults.yml for more info vlsi.inputs.power_spec_mode: "auto" vlsi.inputs.power_spec_type: "cpf" @@ -21,125 +28,45 @@ vlsi.inputs.clocks: [ # Generate Make include to aid in flow vlsi.core.build_system: make -# Power Straps -#par.power_straps_mode: generate -#par.generate_power_straps_method: by_tracks -#par.blockage_spacing: 2.0 -#par.generate_power_straps_options: -# by_tracks: -# strap_layers: -# - metal3 -# - metal4 -# - metal5 -# - metal6 -# - metal7 -# - metal8 -# pin_layers: -# - metal7 -# - metal8 -# track_width: 7 # minimum allowed for M2 & M3 -# track_spacing: 0 -# track_spacing_M3: 1 # to avoid M2 shorts at higher density -# track_start: 10 -# power_utilization: 0.05 -# power_utilization_M8: 1.0 -# power_utilization_M9: 1.0 - +#---------------------- # Placement Constraints -# For ASAP7, all numbers must be 4x larger than final GDS +#---------------------- + +# For nangate45, size should be multiple of (0.19,1.4) placement grid vlsi.inputs.placement_constraints: - path: "ChipTop" type: toplevel x: 0 y: 0 - width: 1387.38 - height: 1199.1 + width: 3334.72 + height: 2398.2 margins: left: 0 right: 0 top: 0 bottom: 0 -# - path: "Sha3AccelwBB/dco" -# type: hardmacro -# x: 108 -# y: 108 -# width: 128 -# height: 128 -# orientation: r0 -# top_layer: M9 -# - path: "Sha3AccelwBB/place_obs_bottom" -# type: obstruction -# obs_types: ["place"] -# x: 0 -# y: 0 -# width: 300 -# height: 1.08 # 1 core site tall, necessary to avoid shorts - -# Pin placement constraints -#vlsi.inputs.pin_mode: generated -#vlsi.inputs.pin.generate_mode: semi_auto -#vlsi.inputs.pin.assignments: [ -# {pins: "*", layers: ["metal7", "metal8"]} -#] - -# Paths to extra libraries -#vlsi.technology.extra_libraries_meta: ["append", "deepsubst"] -#vlsi.technology.extra_libraries: -# - library: -# nldm liberty file_deepsubst_meta: "local" -# nldm liberty file: "extra_libraries/example/ExampleDCO_PVT_0P63V_100C.lib" -# lef file_deepsubst_meta: "local" -# lef file: "extra_libraries/example/ExampleDCO.lef" -# gds file_deepsubst_meta: "local" -# gds file: "extra_libraries/example/ExampleDCO.gds" -# corner: -# nmos: "slow" -# pmos: "slow" -# temperature: "100 C" -# supplies: -# VDD: "0.63 V" -# GND: "0 V" -# - library: -# nldm liberty file_deepsubst_meta: "local" -# nldm liberty file: "extra_libraries/example/ExampleDCO_PVT_0P77V_0C.lib" -# lef file_deepsubst_meta: "local" -# lef file: "extra_libraries/example/ExampleDCO.lef" -# gds file_deepsubst_meta: "local" -# gds file: "extra_libraries/example/ExampleDCO.gds" -# corner: -# nmos: "fast" -# pmos: "fast" -# temperature: "0 C" -# supplies: -# VDD: "0.77 V" -# GND: "0 V" - -# Because the DCO is a dummy layout, we treat it as a physical-only cell -#par.inputs.physical_only_cells_mode: append -#par.inputs.physical_only_cells_list: -# - ExampleDCO # SRAM Compiler compiler options vlsi.core.sram_generator_tool: "sram_compiler" ## You should specify a location for the SRAM generator in the tech plugin -vlsi.core.sram_generator_tool_path: ["hammer/src/hammer-vlsi/technology/nangate45"] +vlsi.core.sram_generator_tool_path: [ + "hammer/src/hammer-vlsi/technology/nangate45"] vlsi.core.sram_generator_tool_path_meta: "append" +#---------------------- # Tool options. Replace with your tool plugin of choice. -# yosys options +#---------------------- + +# OpenROAD-yosys options vlsi.core.synthesis_tool: "yosys" vlsi.core.synthesis_tool_path: ["hammer/src/hammer-vlsi/synthesis/yosys"] vlsi.core.synthesis_tool_path_meta: "append" -# Innovus options -#vlsi.core.par_tool: "innovus" -#vlsi.core.par_tool_path: ["hammer-cadence-plugins/par"] -#vlsi.core.par_tool_path_meta: "append" -#par.innovus.version: "181" -#par.innovus.design_flow_effort: "standard" -#par.inputs.gds_merge: true -## Calibre options -#vlsi.core.drc_tool: "calibre" +# OpenROAD-par options +vlsi.core.par_tool: "openroad" +vlsi.core.par_tool_path: ["hammer/src/hammer-vlsi/par"] +vlsi.core.par_tool_path_meta: "append" + +## OpenROAD-drc options (no lvs) +#vlsi.core.drc_tool: "openroad" #vlsi.core.drc_tool_path: ["hammer-mentor-plugins/drc"] -#vlsi.core.lvs_tool: "calibre" -#vlsi.core.lvs_tool_path: ["hammer-mentor-plugins/lvs"] diff --git a/vlsi/example-vlsi b/vlsi/example-vlsi index f853a1ed..550b56c5 100755 --- a/vlsi/example-vlsi +++ b/vlsi/example-vlsi @@ -1,4 +1,8 @@ #!/usr/bin/env python3 +# +# NOTE: this ExampleDriver works for asap7 and nangate45. the custom hooks are +# only used for asap7 though. + import os import hammer_vlsi @@ -7,21 +11,24 @@ from hammer_vlsi import CLIDriver, HammerToolHookAction from typing import Dict, Callable, Optional, List def example_place_tap_cells(x: hammer_vlsi.HammerTool) -> bool: - x.append(''' + if x.get_setting("vlsi.core.technology") == "asap7": + x.append(''' # TODO # Place custom TCL here ''') return True def example_add_fillers(x: hammer_vlsi.HammerTool) -> bool: - x.append(''' + if x.get_setting("vlsi.core.technology") == "asap7": + x.append(''' # TODO # Place custom TCL here ''') return True def example_tool_settings(x: hammer_vlsi.HammerTool) -> bool: - x.append(''' + if x.get_setting("vlsi.core.technology") == "asap7": + x.append(''' # TODO # Place custom TCL here set_db route_design_bottom_routing_layer 2 @@ -34,7 +41,8 @@ def scale_final_gds(x: hammer_vlsi.HammerTool) -> bool: Scale the final GDS by a factor of 4 hammer/src/hammer-vlsi/technology/asap7/__init__.py implements scale_gds_script """ - x.append(''' + if x.get_setting("vlsi.core.technology") == "asap7": + x.append(''' # Write script out to a temporary file and execute it set fp [open "{script_file}" "w"] puts -nonewline $fp "{script_text}" diff --git a/vlsi/example-vlsi-nangate45 b/vlsi/example-vlsi-nangate45 deleted file mode 100755 index 39b9a493..00000000 --- a/vlsi/example-vlsi-nangate45 +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python3 -import os - -import hammer_vlsi -from hammer_vlsi import CLIDriver, HammerToolHookAction - -from typing import Dict, Callable, Optional, List - -def example_place_tap_cells(x: hammer_vlsi.HammerTool) -> bool: - x.append("") - return True - -def example_add_fillers(x: hammer_vlsi.HammerTool) -> bool: - x.append("") - return True - -class ExampleDriver(CLIDriver): - def get_extra_par_hooks(self) -> List[HammerToolHookAction]: - extra_hooks = [ - # make_pre_insertion_hook will execute the custom hook before the specified step - hammer_vlsi.HammerTool.make_pre_insertion_hook("route_design", example_add_fillers), - - # make_replacement_hook will replace the specified step with a custom hook - hammer_vlsi.HammerTool.make_replacement_hook("place_tap_cells", example_place_tap_cells), - ] - return extra_hooks - -if __name__ == '__main__': - ExampleDriver().main() diff --git a/vlsi/hammer b/vlsi/hammer index c5a3cdf8..4d431566 160000 --- a/vlsi/hammer +++ b/vlsi/hammer @@ -1 +1 @@ -Subproject commit c5a3cdf84987a46c91f3f879541060757bf225fb +Subproject commit 4d431566a87bac14454c969e7073a63b86e31161 From 486cc5fce14c69c07cc55145fafc5c4c7d1d7a8c Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Sat, 20 Jun 2020 13:57:11 -0700 Subject: [PATCH 22/63] [firechip] Add a small target that should fit on all hosts --- .../firechip/src/main/scala/TargetConfigs.scala | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/generators/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala index 63b4d2fe..830188f3 100644 --- a/generators/firechip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -125,6 +125,20 @@ class FireSimQuadRocketConfig extends Config( new WithFireSimConfigTweaks ++ new chipyard.QuadRocketConfig) +// Should fit on all supported hosts +class FireSimSmallSystemConfig extends Config( + new WithDefaultFireSimBridges ++ + new WithDefaultMemModel ++ + new WithBootROM ++ + new WithPeripheryBusFrequency(BigInt(3200000000L)) ++ + new WithoutClockGating ++ + new WithoutTLMonitors ++ + new freechips.rocketchip.subsystem.WithExtMemSize(1 << 28) ++ + new testchipip.WithTSI ++ + new testchipip.WithBlockDevice ++ + new chipyard.config.WithUART ++ + new freechips.rocketchip.subsystem.WithInclusiveCache(nWays = 2, capacityKB = 64) ++ + new chipyard.RocketConfig) //***************************************************************** // Boom config, base off chipyard's LargeBoomConfig From 74807d6f293aea05a42da576666da52dbef519e4 Mon Sep 17 00:00:00 2001 From: Sam Steffl Date: Mon, 22 Jun 2020 11:42:54 -0700 Subject: [PATCH 23/63] passes macro_place at 20% utilization --- vlsi/example-nangate45.yml | 2 +- vlsi/hammer | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vlsi/example-nangate45.yml b/vlsi/example-nangate45.yml index 7d43d068..ecc07d59 100644 --- a/vlsi/example-nangate45.yml +++ b/vlsi/example-nangate45.yml @@ -39,7 +39,7 @@ vlsi.inputs.placement_constraints: x: 0 y: 0 width: 3334.72 - height: 2398.2 + height: 3798.2 margins: left: 0 right: 0 diff --git a/vlsi/hammer b/vlsi/hammer index 4d431566..0e79b8c3 160000 --- a/vlsi/hammer +++ b/vlsi/hammer @@ -1 +1 @@ -Subproject commit 4d431566a87bac14454c969e7073a63b86e31161 +Subproject commit 0e79b8c31c47988b1dc0dd5d83101ab4a5b26fe0 From 34bc8da0024df1957d7a760d0ac23ed0d8a31874 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Mon, 22 Jun 2020 17:57:17 -0700 Subject: [PATCH 24/63] Add a list of common config keys --- docs/Customization/Custom-Core.rst | 98 ++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 5 deletions(-) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index 5a5cc627..6d0a9956 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -199,8 +199,8 @@ more info. name = portName, id = IdRange(0, 1 << idBits)))))) -where ``portName`` and ``idBits`` are the parameter provides by the tile. Make sure to read :::ref:`node-tyoes` to check out what -type of nodes Chipyard supports and their parameters! +where ``portName`` and ``idBits`` (number of bits to represent a port ID) are the parameter provides by the tile. +Make sure to read :::ref:`node-tyoes` to check out what type of nodes Chipyard supports and their parameters! Also, by default, there are boundary buffers for both master and slave connections to the bus when they are leaving the tile, and you can override the following two functions to control how to buffer the bus requests/responses: @@ -291,11 +291,19 @@ The implementation class is of the following form: In the body of this class, you can look up any parameters by calling ``p({key})``, where ``{key}`` is the config key of the value you want to look up. For a list of available keys, see the appendix below. -If you create an AXI4 node (or equivalents), you will need to connect them to your core. +If you create an AXI4 node (or equivalents), you will need to connect them to your core. You can connect a port like this: -.. warning:: +.. code-block:: scala - TODO: Documenting bus connection + outer.myAXI4Node.out foreach { case (out, edgeOut) => + // Connect your module IO port to "out" + // The type of "out" here is AXI4Bundle, which is defined in generators/rocket-chip/src/main/scala/amba/axi4/Bundles.scala + // Please refer to this file for the definition of the ports. + // If you are using APB, check APBBundle in generators/rocket-chip/src/main/scala/amba/apb/Bundles.scala + // If you are using AHB, check AHBSlaveBundle or AHBMasterBundle in generators/rocket-chip/src/main/scala/amba/ahb/Bundles.scala + // (choose one depends on the type of AHB node you create) + // If you are using AXIS, check AXISBundle and AXISBundleBits in generators/rocket-chip/src/main/scala/amba/axis/Bundles.scala + } Integrate the Core ------------------ @@ -320,3 +328,83 @@ all custom cores. You can also create other config fragments to change other par Now you have finished all the steps to prepare your cores for Chipyard! To generate the custom core, simply follow the instructions in :::ref:`_custom_chisel` to add your project to the build system, then create a config by following the steps in :::ref:`_hetero_socs_`. You can now run any desired workflow for the new config just as you do for the built-in cores. + +Appendix: Common Config Keys +---------------------------- + +Chipyard provide a set of keys to store standard parameters. Below are some of the most common key used in core integration. +(Note that internal fields are hidden) + +.. code-block:: scala + + // keys + // Parameters exposed to the top-level design, set based on external requirements, etc. See RISC-V debug specs for more info. + case object DebugModuleKey extends Field[Option[DebugModuleParams]](Some(DebugModuleParams())) + case object BootROMParams extends Field[BootROMParams] // See chipyard boot process tutorial + case object CLINTKey extends Field[Option[CLINTParams]](None) // Core Local Interrupter setting (See SiFive Interrupt Cookbook) + case object PLICKey extends Field[Option[PLICParams]](None) // Platform Level Interrupt Controller setting (See SiFive Interrupt Cookbook) + case object CacheBlockBytes extends Field[Int](64) // # of bytes in a cache block + case object BroadcastKey extends Field(BroadcastParams()) // L2 Cache broadcast setting + case object BankedL2Key extends Field(BankedL2Params()) // L2 Cache memory setting + case object PgLevels extends Field[Int](2) // Page Level of virtual memory + case object ASIdBits extends Field[Int](0) // Max # of bits for Address Space Identifer (See specs) + case object ExtMem extends Field[Option[MemoryPortParams]](None) // External DRAM setting + case object ExtBus extends Field[Option[MasterPortParams]](None) // External (off-chip) output bus setting + case object ExtIn extends Field[Option[SlavePortParams]](None) // External (off-chip) input bus setting + case object MaxHartIdBits extends Field[Int] // Max # of bits used to represent a Hart ID + case object XLen extends Field[Int] // Instruction bits (32 or 64) + case object BuildRoCC extends Field[Seq[Parameters => LazyRoCC]](Nil) // See custom ROCC tutorial + + // Values + case class DebugModuleParams ( + nDMIAddrSize : Int = 7, // Size of the Debug Bus Address + nProgramBufferWords: Int = 16, // Number of 32-bit words for Program Buffer + nAbstractDataWords : Int = 4, // Number of 32-bit words for Abstract Commands + nScratch : Int = 1, // Number of scratch memories used + hasBusMaster : Boolean = false, // Whether or not a bus master should be included + clockGate : Boolean = true, // Use clock gating + maxSupportedSBAccess : Int = 32, // Maximum transaction size supported by System Bus Access logic. + supportQuickAccess : Boolean = false, // Whether or not to support the quick access command. + supportHartArray : Boolean = true, // Whether or not to implement the hart array register (if >1 hart). + nHaltGroups : Int = 1, // Number of halt groups (group of harts that are halted together) + nExtTriggers : Int = 0, // Number of extra triggers + hasHartResets : Boolean = false, // Whether harts can be reseted with debugging system + hasImplicitEbreak : Boolean = false, // There is an additional RO program buffer word containing an ebreak + hasAuthentication : Boolean = false, // Has authentication (to prevent unauthorized users to use debugging system) + crossingHasSafeReset : Boolean = true // Include "safe" logic in Async Crossings so that only one side needs to be reset. + ) + case class CLINTParams( + baseAddress: BigInt = 0x02000000, // Default interrupt handler base address for CLINT + intStages: Int = 0 // # of cycles (stages) interrupts are delayed + ) + case class PLICParams( + baseAddress: BigInt = 0xC000000, // Default interrupt handler base address for PLIC + maxPriorities: Int = 7, // Maximum allowed interrupt priority (cannot be over 7) + intStages: Int = 0, // # of cycles (stages) interrupts are delayed + maxHarts: Int = PLICConsts.maxMaxHarts // Maximum number or hart / core connected to it + ) + case class BroadcastParams( + nTrackers: Int = 4, // # of broadcast tracker + bufferless: Boolean = false // Bufferless broadcast + ) + case class BankedL2Params( + nBanks: Int = 1 // Number of banks in L2 cache + ) + case class MasterPortParams( + base: BigInt, // Base memory address for this port + size: BigInt, // Size of this external memory + beatBytes: Int, // Interface width in bytes + idBits: Int, // # of bits in the port ID + maxXferBytes: Int = 256, // Maximum bytes in one transfer transaction + executable: Boolean = true // If the data from this port can be executed as instruciton + ) + /** Specifies the width of external slave ports */ + case class SlavePortParams( + beatBytes: Int, // Interface width in bytes + idBits: Int, // # of bits in the port ID + sourceBits: Int // # of bits in the source address + ) + case class MemoryPortParams( + master: MasterPortParams, // The memory port setting + nMemoryChannels: Int // Number of memory channel + ) From bfb09a68b40325b13eb46b5e52ffd01b6349f041 Mon Sep 17 00:00:00 2001 From: Sam Steffl Date: Wed, 24 Jun 2020 11:22:05 -0700 Subject: [PATCH 25/63] openroad backend works for RocketConfig through drc. no docs --- vlsi/example-nangate45.yml | 7 ++++--- vlsi/hammer | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/vlsi/example-nangate45.yml b/vlsi/example-nangate45.yml index ecc07d59..c1c3ba63 100644 --- a/vlsi/example-nangate45.yml +++ b/vlsi/example-nangate45.yml @@ -67,6 +67,7 @@ vlsi.core.par_tool: "openroad" vlsi.core.par_tool_path: ["hammer/src/hammer-vlsi/par"] vlsi.core.par_tool_path_meta: "append" -## OpenROAD-drc options (no lvs) -#vlsi.core.drc_tool: "openroad" -#vlsi.core.drc_tool_path: ["hammer-mentor-plugins/drc"] +# OpenROAD-drc options (no lvs) +vlsi.core.drc_tool: "openroad" +vlsi.core.drc_tool_path: ["hammer/src/hammer-vlsi/drc"] +vlsi.core.drc_tool_path_meta: "append" diff --git a/vlsi/hammer b/vlsi/hammer index 0e79b8c3..70d9feec 160000 --- a/vlsi/hammer +++ b/vlsi/hammer @@ -1 +1 @@ -Subproject commit 0e79b8c31c47988b1dc0dd5d83101ab4a5b26fe0 +Subproject commit 70d9feec73a9633a9462ac5896f9c35201ba0bc3 From 774716ac9dcc046136449f28d0a1950eb5dd07f3 Mon Sep 17 00:00:00 2001 From: Sam Steffl Date: Wed, 24 Jun 2020 12:05:38 -0700 Subject: [PATCH 26/63] udpated docs --- vlsi/hammer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vlsi/hammer b/vlsi/hammer index 70d9feec..528e745c 160000 --- a/vlsi/hammer +++ b/vlsi/hammer @@ -1 +1 @@ -Subproject commit 70d9feec73a9633a9462ac5896f9c35201ba0bc3 +Subproject commit 528e745c54c3901a311aade7c928e866de1d42d2 From 1c5bc7d0fff0dc20c8952e50b8bb724ede6da464 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Wed, 24 Jun 2020 20:55:37 -0700 Subject: [PATCH 27/63] 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 1dd3ea4aebdcc720af33495fb12b364b643b76de Mon Sep 17 00:00:00 2001 From: David Biancolin Date: Sat, 27 Jun 2020 13:44:52 -0700 Subject: [PATCH 28/63] Update TargetConfigs.scala --- generators/firechip/src/main/scala/TargetConfigs.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/generators/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala index 830188f3..87662b03 100644 --- a/generators/firechip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -125,7 +125,8 @@ class FireSimQuadRocketConfig extends Config( new WithFireSimConfigTweaks ++ new chipyard.QuadRocketConfig) -// Should fit on all supported hosts +// A stripped down configuration that should fit on all supported hosts. +// Flat to avoid having to reorganize the config class hierarchy to remove certain features class FireSimSmallSystemConfig extends Config( new WithDefaultFireSimBridges ++ new WithDefaultMemModel ++ From 7b5f474b041a30ff06eb29ee8dbf6914277ba171 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sun, 28 Jun 2020 21:26:50 -0700 Subject: [PATCH 29/63] Finished Custom Core Docs --- docs/Customization/Custom-Core.rst | 26 +++++++------------ docs/Customization/index.rst | 1 + .../NodeTypes.rst | 2 ++ docs/TileLink-Diplomacy-Reference/Widgets.rst | 2 ++ 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index 6d0a9956..e2723336 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -4,7 +4,7 @@ Adding a custom core ==================== You may want to add a custom RISC-V core to Chipyard generator. If the top module of your core is not in Chisel, -you will first need to create a Verilog blackbox for it. See ::ref:`_incorporating-verilog-blocks` for instructions. +you will first need to create a Verilog blackbox for it. See :ref:`incorporating-verilog-blocks` for instructions. Once you have a top module in Chisel, you are ready to create integrate it with Chipyard. .. note:: @@ -184,7 +184,7 @@ in the tile class. Below is an example of how to connect a core using AXI4 to th := AXI4Fragmenter() // deal with multi-beat xacts := memAXI4Node) // The custom node, see below -Remember, you may not need all of these intermediate widgets. See :::ref:`Diplomatic-Widgets` for the meaning of each intermediate +Remember, you may not need all of these intermediate widgets. See :ref:`diplomatic_widgets` for the meaning of each intermediate widget. If you are using TileLink, then you only need the tap node and the TileLink node used by your components. Also, Chipyard support AHB, APB and AXIS, and most of the AXI4 widgets has equivalent widget for these bus protocol. See the reference page for more info. @@ -200,7 +200,7 @@ more info. id = IdRange(0, 1 << idBits)))))) where ``portName`` and ``idBits`` (number of bits to represent a port ID) are the parameter provides by the tile. -Make sure to read :::ref:`node-tyoes` to check out what type of nodes Chipyard supports and their parameters! +Make sure to read :ref:`node_types` to check out what type of nodes Chipyard supports and their parameters! Also, by default, there are boundary buffers for both master and slave connections to the bus when they are leaving the tile, and you can override the following two functions to control how to buffer the bus requests/responses: @@ -210,7 +210,7 @@ can override the following two functions to control how to buffer the bus reques protected def makeMasterBoundaryBuffers(implicit p: Parameters): TLBuffer protected def makeSlaveBoundaryBuffers(implicit p: Parameters): TLBuffer -You can find more information on ``TLBuffer`` in :::ref:`Diplomatic-Widgets`. +You can find more information on ``TLBuffer`` in :ref:`diplomatic_widgets`. Interrupt --------- @@ -313,20 +313,14 @@ the current config. An example of such config will be like this: .. code-block:: scala - class WithNMyCores(n: Int) extends Config( - new RegisterCore(new CoreEntry[MyTileParams, MyTile]("MyCore", MyTilesKey, MyCrossingKey)) ++ - new Config((site, here, up) => { - case MyTilesKey => { - List.tabulate(n)(i => MyTileParams(hartId = i)) - } - }) - ) - -Where ``RegisterCore`` will register the core with chipyard so that it can be recognized by generic config. This is required for -all custom cores. You can also create other config fragments to change other parameters. + class WithNMyCores(n: Int) extends Config((site, here, up) => { + case MyTilesKey => { + List.tabulate(n)(i => MyTileParams(hartId = i)) + } + }) Now you have finished all the steps to prepare your cores for Chipyard! To generate the custom core, simply follow the instructions -in :::ref:`_custom_chisel` to add your project to the build system, then create a config by following the steps in :::ref:`_hetero_socs_`. +in :ref:`custom_chisel` to add your project to the build system, then create a config by following the steps in :ref:`hetero_socs_`. You can now run any desired workflow for the new config just as you do for the built-in cores. Appendix: Common Config Keys diff --git a/docs/Customization/index.rst b/docs/Customization/index.rst index 38fdf622..a7b571b6 100644 --- a/docs/Customization/index.rst +++ b/docs/Customization/index.rst @@ -37,6 +37,7 @@ We recommend reading all these pages in order. Hit next to get started! Heterogeneous-SoCs Custom-Chisel + Custom-Core RoCC-or-MMIO RoCC-Accelerators MMIO-Peripherals diff --git a/docs/TileLink-Diplomacy-Reference/NodeTypes.rst b/docs/TileLink-Diplomacy-Reference/NodeTypes.rst index ddb53c9f..32953944 100644 --- a/docs/TileLink-Diplomacy-Reference/NodeTypes.rst +++ b/docs/TileLink-Diplomacy-Reference/NodeTypes.rst @@ -1,3 +1,5 @@ +.. _node_types: + TileLink Node Types =================== diff --git a/docs/TileLink-Diplomacy-Reference/Widgets.rst b/docs/TileLink-Diplomacy-Reference/Widgets.rst index 7eba871b..791c1b9b 100644 --- a/docs/TileLink-Diplomacy-Reference/Widgets.rst +++ b/docs/TileLink-Diplomacy-Reference/Widgets.rst @@ -1,3 +1,5 @@ +.. _diplomatic_widgets: + Diplomatic Widgets ================== From c85d8c4211c3c888a0ba0b80a92ee5d5b23bbc39 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Mon, 29 Jun 2020 11:42:34 -0700 Subject: [PATCH 30/63] 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 31/63] 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 863f723708f39304293e6aba52bca2d47e130c85 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Tue, 30 Jun 2020 12:26:26 -0700 Subject: [PATCH 32/63] Pipe through AXI4 MMIO and Slave ports to ChipTop | IOBinders fix * Fixes bug with AXI4 MMIO ports not being generated properly due to IOBinders issue. Additionally adds IOCells to AXI4 ports so that they appear in ChipTop * Change IOBinders to also require passing p: Parameters to child functions. Serialization of type targets via ClassTags fails for compound types, so we cannot use `BaseSubsystem with HasSomeTrait` as the type target in OverrideIOBinders. --- .circleci/config.yml | 9 ++ .circleci/defaults.sh | 32 ++--- .../chipyard/src/main/scala/ChipTop.scala | 3 +- .../chipyard/src/main/scala/IOBinders.scala | 117 ++++++++++-------- .../src/main/scala/config/RocketConfigs.scala | 18 +++ .../src/main/scala/BridgeBinders.scala | 39 +++--- tools/barstools | 2 +- 7 files changed, 132 insertions(+), 88 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index ab123661..b6556850 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -287,6 +287,11 @@ jobs: steps: - prepare-rtl: project-key: "chipyard-spiflashread" + prepare-chipyard-mmios: + executor: main-env + steps: + - prepare-rtl: + project-key: "chipyard-mmios" chipyard-rocket-run-tests: executor: main-env steps: @@ -531,6 +536,10 @@ workflows: - install-riscv-toolchain - install-verilator + - prepare-chipyard-mmios: + requires: + - install-riscv-toolchain + # Run the respective tests # Run the example tests diff --git a/.circleci/defaults.sh b/.circleci/defaults.sh index b9aeeb3b..7cb8c1e2 100755 --- a/.circleci/defaults.sh +++ b/.circleci/defaults.sh @@ -47,23 +47,25 @@ LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim # key value store to get the build strings declare -A mapping -mapping["chipyard-rocket"]="SUB_PROJECT=chipyard" -mapping["chipyard-sha3"]="SUB_PROJECT=chipyard CONFIG=Sha3RocketConfig" -mapping["chipyard-streaming-fir"]="SUB_PROJECT=chipyard CONFIG=StreamingFIRRocketConfig" -mapping["chipyard-streaming-passthrough"]="SUB_PROJECT=chipyard CONFIG=StreamingPassthroughRocketConfig" -mapping["chipyard-hetero"]="SUB_PROJECT=chipyard CONFIG=LargeBoomAndRocketConfig" -mapping["chipyard-boom"]="SUB_PROJECT=chipyard CONFIG=SmallBoomConfig" -mapping["chipyard-blkdev"]="SUB_PROJECT=chipyard CONFIG=SimBlockDeviceRocketConfig" -mapping["chipyard-hwacha"]="SUB_PROJECT=chipyard CONFIG=HwachaRocketConfig" -mapping["chipyard-gemmini"]="SUB_PROJECT=chipyard CONFIG=GemminiRocketConfig" -mapping["chipyard-ariane"]="SUB_PROJECT=chipyard CONFIG=ArianeConfig" -mapping["chipyard-spiflashread"]="SUB_PROJECT=chipyard CONFIG=LargeSPIFlashROMRocketConfig" -mapping["chipyard-spiflashwrite"]="SUB_PROJECT=chipyard CONFIG=SmallSPIFlashRocketConfig" -mapping["tracegen"]="SUB_PROJECT=chipyard CONFIG=NonBlockingTraceGenL2Config TOP=TraceGenSystem" -mapping["tracegen-boom"]="SUB_PROJECT=chipyard CONFIG=BoomTraceGenConfig TOP=TraceGenSystem" -mapping["chipyard-nvdla"]="SUB_PROJECT=chipyard CONFIG=SmallNVDLARocketConfig" +mapping["chipyard-rocket"]="" +mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig" +mapping["chipyard-streaming-fir"]=" CONFIG=StreamingFIRRocketConfig" +mapping["chipyard-streaming-passthrough"]=" CONFIG=StreamingPassthroughRocketConfig" +mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig" +mapping["chipyard-boom"]=" CONFIG=SmallBoomConfig" +mapping["chipyard-blkdev"]=" CONFIG=SimBlockDeviceRocketConfig" +mapping["chipyard-hwacha"]=" CONFIG=HwachaRocketConfig" +mapping["chipyard-gemmini"]=" CONFIG=GemminiRocketConfig" +mapping["chipyard-ariane"]=" CONFIG=ArianeConfig" +mapping["chipyard-spiflashread"]=" CONFIG=LargeSPIFlashROMRocketConfig" +mapping["chipyard-spiflashwrite"]=" CONFIG=SmallSPIFlashRocketConfig" +mapping["chipyard-mmios"]=" CONFIG=MMIORocketConfig verilog" +mapping["tracegen"]=" CONFIG=NonBlockingTraceGenL2Config TOP=TraceGenSystem" +mapping["tracegen-boom"]=" CONFIG=BoomTraceGenConfig TOP=TraceGenSystem" +mapping["chipyard-nvdla"]=" CONFIG=SmallNVDLARocketConfig" mapping["firesim"]="SCALA_TEST=firesim.firesim.RocketNICF1Tests" mapping["firesim-multiclock"]="SCALA_TEST=firesim.firesim.RocketMulticlockF1Tests" mapping["fireboom"]="SCALA_TEST=firesim.firesim.BoomF1Tests" mapping["icenet"]="SUB_PROJECT=icenet" mapping["testchipip"]="SUB_PROJECT=testchipip" + diff --git a/generators/chipyard/src/main/scala/ChipTop.scala b/generators/chipyard/src/main/scala/ChipTop.scala index d0b4df02..ea0c804d 100644 --- a/generators/chipyard/src/main/scala/ChipTop.scala +++ b/generators/chipyard/src/main/scala/ChipTop.scala @@ -70,12 +70,13 @@ abstract class BaseChipTop()(implicit val p: Parameters) extends RawModule with val lSystem = p(BuildSystem)(p).suggestName("system") val system = withClockAndReset(systemClock, systemReset) { Module(lSystem.module) } + // Call all of the IOBinders and provide them with a default clock and reset withClockAndReset(systemClock, systemReset) { // Call each IOBinder on both the lazyModule instance and the module // instance. Generally, an IOBinder PF should only be defined on one, so // this should not lead to two invocations. - val (_ports, _iocells, _harnessFunctions) = p(IOBinders).values.flatMap(f => f(lSystem) ++ f(system)).unzip3 + val (_ports, _iocells, _harnessFunctions) = p(IOBinders).values.flatMap(f => f(lSystem, p) ++ f(system, p)).unzip3 // We ignore _ports for now... iocells ++= _iocells.flatten harnessFunctions ++= _harnessFunctions.flatten diff --git a/generators/chipyard/src/main/scala/IOBinders.scala b/generators/chipyard/src/main/scala/IOBinders.scala index 1a366d19..2b7cd41c 100644 --- a/generators/chipyard/src/main/scala/IOBinders.scala +++ b/generators/chipyard/src/main/scala/IOBinders.scala @@ -9,7 +9,7 @@ import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.devices.debug._ import freechips.rocketchip.subsystem._ import freechips.rocketchip.system.{SimAXIMem} -import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4EdgeParameters} +import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters} import freechips.rocketchip.util._ import freechips.rocketchip.groundtest.{GroundTestSubsystemModuleImp, GroundTestSubsystem} @@ -48,17 +48,17 @@ type TestHarnessFunction = (chipyard.TestHarness) => Seq[Any] // 3. An optional function to call inside the test harness (e.g. to connect the IOs) type IOBinderTuple = (Seq[Data], Seq[IOCell], Option[TestHarnessFunction]) -case object IOBinders extends Field[Map[String, (Any) => Seq[IOBinderTuple]]]( - Map[String, (Any) => Seq[IOBinderTuple]]().withDefaultValue((Any) => Nil) +case object IOBinders extends Field[Map[String, (Any, Parameters) => Seq[IOBinderTuple]]]( + Map[String, (Any, Parameters) => Seq[IOBinderTuple]]().withDefaultValue((Any, Parameters) => Nil) ) // This macro overrides previous matches on some Top mixin. This is useful for // binders which drive IO, since those typically cannot be composed -class OverrideIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { +class OverrideIOBinder[T](fn: => (T, Parameters) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> - ((t: Any) => { + ((t: Any, p: Parameters) => { t match { - case system: T => fn(system) + case system: T => fn(system, p) case _ => Nil } }) @@ -67,12 +67,12 @@ class OverrideIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassT // This macro composes with previous matches on some Top mixin. This is useful for // annotation-like binders, since those can typically be composed -class ComposeIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { +class ComposeIOBinder[T](fn: => (T, Parameters) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> - ((t: Any) => { + ((t: Any, p: Parameters) => { t match { - case system: T => (up(IOBinders, site)(tag.runtimeClass.toString)(system) - ++ fn(system)) + case system: T => (up(IOBinders, site)(tag.runtimeClass.toString)(system, p) + ++ fn(system, p)) case _ => Nil } }) @@ -185,10 +185,19 @@ object AddIOCells { (port, ios) } - def axi4(io: Seq[AXI4Bundle], node: AXI4SlaveNode): Seq[(AXI4Bundle, AXI4EdgeParameters, Seq[IOCell])] = { + def axi4(io: Seq[AXI4Bundle], node: AXI4SlaveNode, name: String): Seq[(AXI4Bundle, AXI4EdgeParameters, Seq[IOCell])] = { io.zip(node.in).zipWithIndex.map{ case ((mem_axi4, (_, edge)), i) => { - val (port, ios) = IOCell.generateIOFromSignal(mem_axi4, Some(s"iocell_mem_axi4_${i}")) - port.suggestName(s"mem_axi4_${i}") + val (port, ios) = IOCell.generateIOFromSignal(mem_axi4, Some(s"iocell_${name}_axi4_slave_${i}")) + port.suggestName(s"${name}_axi4_slave_${i}") + (port, edge, ios) + }} + } + def axi4(io: Seq[AXI4Bundle], node: AXI4MasterNode, name: String): Seq[(AXI4Bundle, AXI4EdgeParameters, Seq[IOCell])] = { + io.zip(node.out).zipWithIndex.map{ case ((mem_axi4, (_, edge)), i) => { + //val (port, ios) = IOCell.generateIOFromSignal(mem_axi4, Some(s"iocell_${name}_axi4_master_${i}")) + val port = IO(Flipped(AXI4Bundle(edge.bundle))) + val ios = IOCell.generateFromSignal(mem_axi4, port, Some(s"iocell_${name}_axi4_master_${i}")) + port.suggestName(s"${name}_axi4_master_${i}") (port, edge, ios) }} } @@ -202,7 +211,7 @@ object AddIOCells { // DOC include start: WithGPIOTiedOff class WithGPIOTiedOff extends OverrideIOBinder({ - (system: HasPeripheryGPIOModuleImp) => { + (system: HasPeripheryGPIOModuleImp, p) => { val (ports2d, ioCells2d) = AddIOCells.gpio(system.gpio) val harnessFn = (th: chipyard.TestHarness) => { ports2d.flatten.foreach(_ <> AnalogConst(0)); Nil } Seq((ports2d.flatten, ioCells2d.flatten, Some(harnessFn))) @@ -211,7 +220,7 @@ class WithGPIOTiedOff extends OverrideIOBinder({ // DOC include end: WithGPIOTiedOff class WithUARTAdapter extends OverrideIOBinder({ - (system: HasPeripheryUARTModuleImp) => { + (system: HasPeripheryUARTModuleImp, p) => { val (ports, ioCells2d) = AddIOCells.uart(system.uart) val harnessFn = (th: chipyard.TestHarness) => { UARTAdapter.connect(ports)(system.p); Nil } Seq((ports, ioCells2d.flatten, Some(harnessFn))) @@ -219,7 +228,7 @@ class WithUARTAdapter extends OverrideIOBinder({ }) class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideIOBinder({ - (system: HasPeripherySPIFlashModuleImp) => { + (system: HasPeripherySPIFlashModuleImp, p) => { val (ports, ioCells2d) = AddIOCells.spi(system.qspi, "qspi") val harnessFn = (th: chipyard.TestHarness) => { SimSPIFlashModel.connect(ports, th.reset, rdOnly)(system.p); Nil } Seq((ports, ioCells2d.flatten, Some(harnessFn))) @@ -227,7 +236,7 @@ class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideIOBinder({ }) class WithSimBlockDevice extends OverrideIOBinder({ - (system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev => + (system: CanHavePeripheryBlockDeviceModuleImp, p) => system.bdev.map { bdev => val (port, ios) = AddIOCells.blockDev(bdev) val harnessFn = (th: chipyard.TestHarness) => { SimBlockDevice.connect(th.clock, th.reset.asBool, Some(port))(system.p) @@ -238,7 +247,7 @@ class WithSimBlockDevice extends OverrideIOBinder({ }) class WithBlockDeviceModel extends OverrideIOBinder({ - (system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev => + (system: CanHavePeripheryBlockDeviceModuleImp, p) => system.bdev.map { bdev => val (port, ios) = AddIOCells.blockDev(bdev) val harnessFn = (th: chipyard.TestHarness) => { BlockDeviceModel.connect(Some(port))(system.p) @@ -249,11 +258,11 @@ class WithBlockDeviceModel extends OverrideIOBinder({ }) class WithLoopbackNIC extends OverrideIOBinder({ - (system: CanHavePeripheryIceNICModuleImp) => system.connectNicLoopback(); Nil + (system: CanHavePeripheryIceNICModuleImp, p) => system.connectNicLoopback(); Nil }) class WithSimNIC extends OverrideIOBinder({ - (system: CanHavePeripheryIceNICModuleImp) => system.connectSimNetwork(system.clock, system.reset.asBool); Nil + (system: CanHavePeripheryIceNICModuleImp, p) => system.connectSimNetwork(system.clock, system.reset.asBool); Nil }) // Note: The parameters instance is accessible only through the BaseSubsystem @@ -262,16 +271,16 @@ class WithSimNIC extends OverrideIOBinder({ // accessible to the IOBinder // DOC include start: WithSimAXIMem class WithSimAXIMem extends OverrideIOBinder({ - (system: CanHaveMasterAXI4MemPort with BaseSubsystem) => { - val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node) + (system: CanHaveMasterAXI4MemPort, p) => { + val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node, "mem") // TODO: we are inlining the connectMem method of SimAXIMem because // it takes in a dut rather than seq of axi4 ports val harnessFn = (th: chipyard.TestHarness) => { peiTuples.map { case (port, edge, ios) => - val mem = LazyModule(new SimAXIMem(edge, size = system.p(ExtMem).get.master.size)(system.p)) + val mem = LazyModule(new SimAXIMem(edge, size = p(ExtMem).get.master.size)(p)) Module(mem.module).suggestName("mem") mem.io_axi4.head <> port - } + } Nil } Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn))) @@ -280,12 +289,12 @@ class WithSimAXIMem extends OverrideIOBinder({ // DOC include end: WithSimAXIMem class WithBlackBoxSimMem extends OverrideIOBinder({ - (system: CanHaveMasterAXI4MemPort with BaseSubsystem) => { - val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node) + (system: CanHaveMasterAXI4MemPort, p) => { + val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node, "mem") val harnessFn = (th: chipyard.TestHarness) => { peiTuples.map { case (port, edge, ios) => - val memSize = system.p(ExtMem).get.master.size - val lineSize = system.p(CacheBlockBytes) + val memSize = p(ExtMem).get.master.size + val lineSize = p(CacheBlockBytes) val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle)) mem.io.axi <> port mem.io.clock := th.clock @@ -298,15 +307,26 @@ class WithBlackBoxSimMem extends OverrideIOBinder({ }) class WithSimAXIMMIO extends OverrideIOBinder({ - (system: CanHaveMasterAXI4MMIOPort with BaseSubsystem) => SimAXIMem.connectMMIO(system)(system.p); Nil + (system: CanHaveMasterAXI4MMIOPort, p) => { + val peiTuples = AddIOCells.axi4(system.mmio_axi4, system.mmioAXI4Node, "mmio_mem") + val harnessFn = (th: chipyard.TestHarness) => { + peiTuples.zipWithIndex.map { case ((port, edge, ios), i) => + val mmio_mem = LazyModule(new SimAXIMem(edge, size = 4096)(p)) + Module(mmio_mem.module).suggestName(s"mmio_mem_${i}") + mmio_mem.io_axi4.head <> port + } + Nil + } + Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn))) + } }) class WithDontTouchPorts extends OverrideIOBinder({ - (system: DontTouch) => system.dontTouchPorts(); Nil + (system: DontTouch, p) => system.dontTouchPorts(); Nil }) class WithTieOffInterrupts extends OverrideIOBinder({ - (system: HasExtInterruptsModuleImp) => { + (system: HasExtInterruptsModuleImp, p) => { val (port, ioCells) = IOCell.generateIOFromSignal(system.interrupts, Some("iocell_interrupts")) port.suggestName("interrupts") val harnessFn = (th: chipyard.TestHarness) => { port := 0.U; Nil } @@ -315,26 +335,21 @@ class WithTieOffInterrupts extends OverrideIOBinder({ }) class WithTieOffL2FBusAXI extends OverrideIOBinder({ - (system: CanHaveSlaveAXI4Port with BaseSubsystem) => { - system.l2_frontend_bus_axi4.foreach(axi => { - axi.tieoff() - experimental.DataMirror.directionOf(axi.ar.ready) match { - case ActualDirection.Input => - axi.r.bits := DontCare - axi.b.bits := DontCare - case ActualDirection.Output => - axi.aw.bits := DontCare - axi.ar.bits := DontCare - axi.w.bits := DontCare - case _ => throw new Exception("Unknown AXI port direction") + (system: CanHaveSlaveAXI4Port, p) => { + val peiTuples = AddIOCells.axi4(system.l2_frontend_bus_axi4, system.l2FrontendAXI4Node, "l2_fbus") + val harnessFn = (th: chipyard.TestHarness) => { + peiTuples.zipWithIndex.map { case ((port, edge, ios), i) => + port := DontCare // tieoff doesn't completely tie-off, for some reason + port.tieoff() } - }) - Nil + Nil + } + Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn))) } }) class WithTiedOffDebug extends OverrideIOBinder({ - (system: HasPeripheryDebugModuleImp) => { + (system: HasPeripheryDebugModuleImp, p) => { val (psdPort, resetctrlOpt, debugPortOpt, ioCells) = AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p) val harnessFn = (th: chipyard.TestHarness) => { @@ -352,7 +367,7 @@ class WithTiedOffDebug extends OverrideIOBinder({ }) class WithSimDebug extends OverrideIOBinder({ - (system: HasPeripheryDebugModuleImp) => { + (system: HasPeripheryDebugModuleImp, p) => { val (psdPort, resetctrlPortOpt, debugPortOpt, ioCells) = AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p) val harnessFn = (th: chipyard.TestHarness) => { @@ -367,7 +382,7 @@ class WithSimDebug extends OverrideIOBinder({ }) class WithTiedOffSerial extends OverrideIOBinder({ - (system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial => + (system: CanHavePeripherySerialModuleImp, p) => system.serial.map({ serial => val (port, ioCells) = AddIOCells.serial(serial) val harnessFn = (th: chipyard.TestHarness) => { SerialAdapter.tieoff(port) @@ -378,7 +393,7 @@ class WithTiedOffSerial extends OverrideIOBinder({ }) class WithSimSerial extends OverrideIOBinder({ - (system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial => + (system: CanHavePeripherySerialModuleImp, p) => system.serial.map({ serial => val (port, ioCells) = AddIOCells.serial(serial) val harnessFn = (th: chipyard.TestHarness) => { val ser_success = SerialAdapter.connectSimSerial(port, th.clock, th.harnessReset) @@ -390,7 +405,7 @@ class WithSimSerial extends OverrideIOBinder({ }) class WithTraceGenSuccessBinder extends OverrideIOBinder({ - (system: TraceGenSystemModuleImp) => { + (system: TraceGenSystemModuleImp, p) => { val (successPort, ioCells) = IOCell.generateIOFromSignal(system.success, Some("iocell_success")) successPort.suggestName("success") val harnessFn = (th: chipyard.TestHarness) => { when (successPort) { th.success := true.B }; Nil } @@ -399,7 +414,7 @@ class WithTraceGenSuccessBinder extends OverrideIOBinder({ }) class WithSimDromajoBridge extends ComposeIOBinder({ - (system: CanHaveTraceIOModuleImp) => { + (system: CanHaveTraceIOModuleImp, p) => { system.traceIO match { case Some(t) => t.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) } Nil } diff --git a/generators/chipyard/src/main/scala/config/RocketConfigs.scala b/generators/chipyard/src/main/scala/config/RocketConfigs.scala index 06257c7b..3dc7d22d 100644 --- a/generators/chipyard/src/main/scala/config/RocketConfigs.scala +++ b/generators/chipyard/src/main/scala/config/RocketConfigs.scala @@ -542,3 +542,21 @@ class LargeNVDLARocketConfig extends Config( new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ new freechips.rocketchip.system.BaseConfig) + +class MMIORocketConfig extends Config( + new chipyard.iobinders.WithUARTAdapter ++ + new chipyard.iobinders.WithTieOffInterrupts ++ + new chipyard.iobinders.WithBlackBoxSimMem ++ + new chipyard.iobinders.WithTiedOffDebug ++ + new chipyard.iobinders.WithSimSerial ++ + new chipyard.iobinders.WithTieOffL2FBusAXI ++ // Tie-off the incoming MMIO port + new chipyard.iobinders.WithSimAXIMMIO ++ // Attach a simulated memory to the outwards MMIO port + new testchipip.WithTSI ++ + new chipyard.config.WithBootROM ++ + new chipyard.config.WithUART ++ + new chipyard.config.WithL2TLBs(1024) ++ + new freechips.rocketchip.subsystem.WithInclusiveCache ++ + new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ + new freechips.rocketchip.system.BaseConfig) diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index eeb19559..6af7bd0a 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -35,29 +35,28 @@ object MainMemoryConsts { } class WithSerialBridge extends OverrideIOBinder({ - (system: CanHavePeripherySerialModuleImp) => - system.serial.foreach(s => SerialBridge(system.clock, s, MainMemoryConsts.globalName)(system.p)); Nil + (system: CanHavePeripherySerialModuleImp, p) => + system.serial.foreach(s => SerialBridge(system.clock, s, MainMemoryConsts.globalName)(p)); Nil }) class WithNICBridge extends OverrideIOBinder({ - (system: CanHavePeripheryIceNICModuleImp) => - system.net.foreach(n => NICBridge(system.clock, n)(system.p)); Nil + (system: CanHavePeripheryIceNICModuleImp, p) => + system.net.foreach(n => NICBridge(system.clock, n)(p)); Nil }) class WithUARTBridge extends OverrideIOBinder({ - (system: HasPeripheryUARTModuleImp) => - system.uart.foreach(u => UARTBridge(system.clock, u)(system.p)); Nil + (system: HasPeripheryUARTModuleImp, p) => + system.uart.foreach(u => UARTBridge(system.clock, u)(p)); Nil }) class WithBlockDeviceBridge extends OverrideIOBinder({ - (system: CanHavePeripheryBlockDeviceModuleImp) => - system.bdev.foreach(b => BlockDevBridge(system.clock, b, system.reset.toBool)(system.p)); Nil + (system: CanHavePeripheryBlockDeviceModuleImp, p) => + system.bdev.foreach(b => BlockDevBridge(system.clock, b, system.reset.toBool)(p)); Nil }) class WithFASEDBridge extends OverrideIOBinder({ - (system: CanHaveMasterAXI4MemPort with BaseSubsystem) => { - implicit val p = system.p + (system: CanHaveMasterAXI4MemPort, p) => { (system.mem_axi4 zip system.memAXI4Node.in).foreach({ case (axi4, (_, edge)) => val nastiKey = NastiParameters(axi4.r.bits.data.getWidth, axi4.ar.bits.addr.getWidth, @@ -73,26 +72,26 @@ class WithFASEDBridge extends OverrideIOBinder({ }) class WithTracerVBridge extends ComposeIOBinder({ - (system: CanHaveTraceIOModuleImp) => - system.traceIO.foreach(_.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p))); Nil + (system: CanHaveTraceIOModuleImp, p) => + system.traceIO.foreach(_.traces.map(tileTrace => TracerVBridge(tileTrace)(p))); Nil }) class WithDromajoBridge extends ComposeIOBinder({ - (system: CanHaveTraceIOModuleImp) => { - system.traceIO.foreach(_.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p))); Nil + (system: CanHaveTraceIOModuleImp, p) => { + system.traceIO.foreach(_.traces.map(tileTrace => DromajoBridge(tileTrace)(p))); Nil } }) class WithTraceGenBridge extends OverrideIOBinder({ - (system: TraceGenSystemModuleImp) => + (system: TraceGenSystemModuleImp, p) => GroundTestBridge(system.clock, system.success)(system.p); Nil }) class WithFireSimMultiCycleRegfile extends ComposeIOBinder({ - (system: HasTilesModuleImp) => { + (system: HasTilesModuleImp, p) => { system.outer.tiles.map { case r: RocketTile => { annotate(MemModelAnnotation(r.module.core.rocketImpl.rf.rf)) @@ -116,13 +115,13 @@ class WithFireSimMultiCycleRegfile extends ComposeIOBinder({ }) class WithTiedOffSystemGPIO extends OverrideIOBinder({ - (system: HasPeripheryGPIOModuleImp) => + (system: HasPeripheryGPIOModuleImp, p) => system.gpio.foreach(_.pins.foreach(_.i.ival := false.B)); Nil }) class WithTiedOffSystemDebug extends OverrideIOBinder({ - (system: HasPeripheryDebugModuleImp) => { - Debug.tieoffDebug(system.debug, system.resetctrl, Some(system.psd))(system.p) + (system: HasPeripheryDebugModuleImp, p) => { + Debug.tieoffDebug(system.debug, system.resetctrl, Some(system.psd))(p) // tieoffDebug doesn't actually tie everything off :/ system.debug.foreach { d => d.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare }) @@ -133,7 +132,7 @@ class WithTiedOffSystemDebug extends OverrideIOBinder({ }) class WithTiedOffSystemInterrupts extends OverrideIOBinder({ - (system: HasExtInterruptsModuleImp) => + (system: HasExtInterruptsModuleImp, p) => system.interrupts := 0.U; Nil }) diff --git a/tools/barstools b/tools/barstools index 7e6e19b8..aa1c90c4 160000 --- a/tools/barstools +++ b/tools/barstools @@ -1 +1 @@ -Subproject commit 7e6e19b8adf3b625b31b09173ecae5f634c83e1b +Subproject commit aa1c90c4ccb73c2c379550f3296892cc81e8a195 From 104c350a59af995d0d36affc5f1203582be838ca Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Thu, 2 Jul 2020 15:56:15 -0700 Subject: [PATCH 33/63] Custom Core Integration Doc, 1st Revision --- docs/Customization/Custom-Core.rst | 113 +++++++++----------- docs/TileLink-Diplomacy-Reference/index.rst | 2 + 2 files changed, 51 insertions(+), 64 deletions(-) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index e2723336..dcf2c257 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -7,34 +7,32 @@ You may want to add a custom RISC-V core to Chipyard generator. If the top modul you will first need to create a Verilog blackbox for it. See :ref:`incorporating-verilog-blocks` for instructions. Once you have a top module in Chisel, you are ready to create integrate it with Chipyard. +``generators/ariane/src/main/scala/ArianeTile.scala`` and ``generators/boom/src/main/scala/common/tile.scala`` +provide two examples of how to integrate a core. + .. note:: - RoCC is not supported by custom core currently. Please use Rocket or Boom if you need to use RoCC. + RoCC is not supported by custom core currently. Please use Rocket or Boom as the RoCC base core if you need to use RoCC. Parameter Case Classes ---------------------- -Chipyard will generate a core for every ``TileParams`` object it discovered in the current config. -``TileParams`` is a trait containing the information needed to create a tile, and every custom core must implement -their own version of ``TileParams``, as well as ``CoreParams`` which is passed as a field in ``TileParams``. +Chipyard will generate a core for every ``InstantiableTileParams`` object it discovered in the current config. +This object is derived from``TileParams``, a trait containing the information needed to create a tile. All cores must have +their own implementation of ``InstantiableTileParams``, as well as ``CoreParams`` which is passed as a field in ``TileParams``. -``TileParams`` holds the parameters that are the same for every generated core, while ``CoreParams`` contains those -that can vary from cores to cores. They must be implemented as case classes with fields that can be overridden by +``TileParams`` holds the parameters for the tile, which are the same for every generated core, while ``CoreParams`` +contains the parameters for individual cores. They must be implemented as case classes with fields that can be overridden by other config fragments as the constructor parameters. See the appendix at the bottom of the page for a list of variable to be implemented. You can also add custom fields to them, but standard fields should always be preferred. -Now you have your parameter classes, you will need config keys to hold them. There are two required keys: +``InstantiableTileParams[TileType]`` holds the constructor of ``TileType`` on top of the fields of ``TileParams``. +All custom cores will also need to implement ``instantiate()`` in their tile parameter class to return a new instance +of the tile class ``TileType``. -.. code-block:: scala - - case object MyTilesKey extends Field[Seq[MyTileParams]](Nil) - case object MyCrossingKey extends Field[Seq[RocketCrossingParams]](List(RocketCrossingParams())) - -``MyCrossingKey`` here is used to store information about the clock-crossing behavior of the core, and it is normally -set to its default values. - -``TileParams`` and ``CoreParams`` contains the following fields (you may ignore any fields marked "Rocket specific" and -use their default values, although it is recommended to use them if you need a custom field with similar purposes) : +``TileParams``, ``InstantiableTileParams[TileType]`` and ``CoreParams`` contains the following fields (you may ignore +any fields marked "Rocket specific" and use their default values, although it is recommended to use them if you +need a custom field with similar purposes): .. code-block:: scala @@ -49,6 +47,11 @@ use their default values, although it is recommended to use them if you need a c val name: Option[String] // Name of the core } + abstract class InstantiableTileParams[TileType <: BaseTile] extends TileParams { + def instantiate(crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl) + (implicit p: Parameters): TileType + } + trait CoreParams { val bootFreqHz: BigInt // Frequency val useVM: Boolean // Support virtual memory @@ -87,7 +90,7 @@ use their default values, although it is recommended to use them if you need a c def hasSupervisorMode: Boolean = useSupervisor || useVM def instBytes: Int = instBits / 8 def fetchBytes: Int = fetchWidth * instBytes - // Rocket specific: Longest possible latency of Rocket core D1 cache. Simply set it to the default value 80. + // Rocket specific: Longest possible latency of Rocket core D1 cache. Simply set it to the default value 80 if you don't use it. def lrscCycles: Int def dcacheReqTagBits: Int = 6 @@ -109,14 +112,23 @@ use their default values, although it is recommended to use them if you need a c Most of the fields here are originally designed for Rocket core and contains some architecture-specific details, but many of them are general enough to be useful for other cores. It is strongly recommended to use these fields instead -of creating your own custom fields when applicable. +of creating your own custom fields when applicable. + +.. note:: + + Implementations may choose to ignore some fields here or use them in a non-standard way, but using an inaccurate + value may break Chipyard components that rely on them (e.g. inaccurate indication of supported ISA extension will + result in incorrect test suite being generated) as well as any custom module that use them. ALWAYS document any + fields you ignore or with altered usage in your core implementation, and if you are implementing other devices that + would look up these config values, also document them. "Rocket specific" values are generally safe to ignore, but + you should document them if you use them. Tile Class ---------- -In Chipyard, all connections with other components on SoC are defined a core's `Tile` class, while the implementation -of the actual hardware are in the implementation class. This structure allows Chipyard to use the Diplomacy framework -to resolve paramters and connections before elaboration. +In Chipyard, all Tiles are diplomatically instantiated. In the first phase, diplomatic nodes which specify Tile-to-System +interconnects are evaluated, while in the second "Module Implementation" phase, hardware is elaborated. +See :ref:`tilelink_and_diplomacy` for more details. All tile classes implement ``BaseTile`` and will normally implement ``SinksExternalInterrupts`` and ``SourcesExternalNotifications``, which allow the tile to accept external interrupt. A typical tile has the following form: @@ -169,7 +181,8 @@ TileLink Connection ------------------- Chipyard use TileLink as its onboard bus protocol, and if your core doesn't use TileLink, you will need to convert them -in the tile class. Below is an example of how to connect a core using AXI4 to the TileLink bus: +in the tile class. Below is an example of how to connect a core using AXI4 to the TileLink bus with converters provided by +Chipyards: .. code-block:: scala @@ -185,9 +198,12 @@ in the tile class. Below is an example of how to connect a core using AXI4 to th := memAXI4Node) // The custom node, see below Remember, you may not need all of these intermediate widgets. See :ref:`diplomatic_widgets` for the meaning of each intermediate -widget. If you are using TileLink, then you only need the tap node and the TileLink node used by your components. Also, Chipyard -support AHB, APB and AXIS, and most of the AXI4 widgets has equivalent widget for these bus protocol. See the reference page for -more info. +widget. If you are using TileLink, then you only need the tap node and the TileLink node used by your components. Chipyard also +provides converters for AHB, APB and AXIS, and most of the AXI4 widgets has equivalent widget for these bus protocol; see the +source files in ``generators/rocket-chip/src/main/scala/amba`` for more info. + +If you are using other bus protocol, you may implement your own converters, using the files in ``generators/rocket-chip/src/main/scala/amba`` +as the template, but it is not recommended unless you are familiar with TileLink. ``memAXI4Node`` is an AXI4 master node and is defined as following in our example: @@ -232,7 +248,8 @@ The definition of ``TileInterrupts`` is } This function should be in the implementation class since it involves hardware generation. -Also, the tile can also notify other cores or devices for some events by calling following functions (in implementation class): +Also, the tile can also notify other cores or devices for some events by calling following functions in ``SourcesExternalNotifications`` +from the implementation class: .. code-block:: scala @@ -241,39 +258,6 @@ Also, the tile can also notify other cores or devices for some events by calling reportCease(could_cease: Option[Bool], quiescenceCycles: Int = 8) // Triggered when the core stop retiring instructions (like clock gating) reportWFI(could_wfi: Option[Bool]) // Triggered when a WFI instruction is executed -Trace (Optional) ----------------- - -Chipyard provides a set of ports for instruction trace that conforms with related RISC-V standard. -If you are using FireSim, it is recommended to implement these trace ports to enable FireSim to read trace. - -There are one inbound node ``traceAuxSinkNode.bundle: TraceAux`` and two outbound nodes ``traceCoreSourceNode.bundle: TraceCoreInterface`` -and ``bpwatchSourceNode.bundle: Vec[BPWatch]``. Note that the length of ``bpwatchSourceNode`` is equal to the max number of -breakpoints (set by ``nBreakpoints`` in ``CoreParams``). Below is the definition of these types: - -.. code-block:: scala - - // Control signal from the external tracer - class TraceAux extends Bundle { - val enable = Bool() // Enable trace output - val stall = Bool() // If true, the core should stall - } - // Check RISC-V Processor Trace spec V1.0 for more information of this interface - class TraceCoreInterface (val params: TraceCoreParams) extends Bundle { - val group = Vec(params.nGroups, new TraceCoreGroup(params)) - val priv = UInt(4.W) - val tval = UInt(params.xlen.W) - val cause = UInt(params.xlen.W) - } - // Address Breakpoint and watchpoint info (n is the retire width) - class BPWatch (val n: Int) extends Bundle() { - val valid = Vec(n, Bool()) // Valid bit of the output - val rvalid = Vec(n, Bool()) // Break on read - val wvalid = Vec(n, Bool()) // Break on write - val ivalid = Vec(n, Bool()) // Break on execute - val action = UInt(3.W) // Exception code (3 usually) - } - Implementation Class -------------------- @@ -313,12 +297,13 @@ the current config. An example of such config will be like this: .. code-block:: scala - class WithNMyCores(n: Int) extends Config((site, here, up) => { - case MyTilesKey => { - List.tabulate(n)(i => MyTileParams(hartId = i)) - } + class WithNMyCores(n: Int, hartidOffset: Int) extends Config((site, here, up) => { + case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem)) :++ List.tabulate(n)(i => MyTileParams(hartId = i + hartidOffset)) }) +Chipyard looks up the tile parameters in the field ``TilesLocated(InSubsystem)``, whose type is a list of ``InstantiableTileParams``. +This config fragment simply appends new tile parameters to the end of this list. + Now you have finished all the steps to prepare your cores for Chipyard! To generate the custom core, simply follow the instructions in :ref:`custom_chisel` to add your project to the build system, then create a config by following the steps in :ref:`hetero_socs_`. You can now run any desired workflow for the new config just as you do for the built-in cores. diff --git a/docs/TileLink-Diplomacy-Reference/index.rst b/docs/TileLink-Diplomacy-Reference/index.rst index dfc2ec5a..9c70287d 100644 --- a/docs/TileLink-Diplomacy-Reference/index.rst +++ b/docs/TileLink-Diplomacy-Reference/index.rst @@ -1,3 +1,5 @@ +.. _tilelink_and_diplomacy: + TileLink and Diplomacy Reference ================================ From a7047c4ba2e7b9c4a2433a3e8ff0346bc3a67ab5 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 1 Jul 2020 12:21:51 -0700 Subject: [PATCH 34/63] Fix FireChip BridgeBinders --- .../chipyard/src/main/scala/ChipTop.scala | 3 +- .../chipyard/src/main/scala/IOBinders.scala | 84 +++++++++++-------- .../src/main/scala/BridgeBinders.scala | 54 ++++++------ 3 files changed, 79 insertions(+), 62 deletions(-) diff --git a/generators/chipyard/src/main/scala/ChipTop.scala b/generators/chipyard/src/main/scala/ChipTop.scala index ea0c804d..d0b4df02 100644 --- a/generators/chipyard/src/main/scala/ChipTop.scala +++ b/generators/chipyard/src/main/scala/ChipTop.scala @@ -70,13 +70,12 @@ abstract class BaseChipTop()(implicit val p: Parameters) extends RawModule with val lSystem = p(BuildSystem)(p).suggestName("system") val system = withClockAndReset(systemClock, systemReset) { Module(lSystem.module) } - // Call all of the IOBinders and provide them with a default clock and reset withClockAndReset(systemClock, systemReset) { // Call each IOBinder on both the lazyModule instance and the module // instance. Generally, an IOBinder PF should only be defined on one, so // this should not lead to two invocations. - val (_ports, _iocells, _harnessFunctions) = p(IOBinders).values.flatMap(f => f(lSystem, p) ++ f(system, p)).unzip3 + val (_ports, _iocells, _harnessFunctions) = p(IOBinders).values.flatMap(f => f(lSystem) ++ f(system)).unzip3 // We ignore _ports for now... iocells ++= _iocells.flatten harnessFunctions ++= _harnessFunctions.flatten diff --git a/generators/chipyard/src/main/scala/IOBinders.scala b/generators/chipyard/src/main/scala/IOBinders.scala index 2b7cd41c..115723ab 100644 --- a/generators/chipyard/src/main/scala/IOBinders.scala +++ b/generators/chipyard/src/main/scala/IOBinders.scala @@ -5,7 +5,7 @@ import chisel3._ import chisel3.experimental.{Analog, IO} import freechips.rocketchip.config.{Field, Config, Parameters} -import freechips.rocketchip.diplomacy.{LazyModule} +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike} import freechips.rocketchip.devices.debug._ import freechips.rocketchip.subsystem._ import freechips.rocketchip.system.{SimAXIMem} @@ -48,17 +48,32 @@ type TestHarnessFunction = (chipyard.TestHarness) => Seq[Any] // 3. An optional function to call inside the test harness (e.g. to connect the IOs) type IOBinderTuple = (Seq[Data], Seq[IOCell], Option[TestHarnessFunction]) -case object IOBinders extends Field[Map[String, (Any, Parameters) => Seq[IOBinderTuple]]]( - Map[String, (Any, Parameters) => Seq[IOBinderTuple]]().withDefaultValue((Any, Parameters) => Nil) +case object IOBinders extends Field[Map[String, (Any) => Seq[IOBinderTuple]]]( + Map[String, (Any) => Seq[IOBinderTuple]]().withDefaultValue((Any) => Nil) ) +// Note: The parameters instance is accessible only through LazyModule +// or LazyModuleImpLike. The self-type requirement in traits like +// CanHaveMasterAXI4MemPort is insufficient to make it accessible to the IOBinder +// As a result, IOBinders only work on Modules which inherit LazyModule or +// or LazyModuleImpLike +object GetSystemParameters { + def apply(s: Any): Parameters = { + s match { + case s: LazyModule => s.p + case s: LazyModuleImpLike => s.p + case _ => throw new Exception(s"Trying to get Parameters from a system that is not LazyModule or LazyModuleImpLike") + } + } +} + // This macro overrides previous matches on some Top mixin. This is useful for // binders which drive IO, since those typically cannot be composed -class OverrideIOBinder[T](fn: => (T, Parameters) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { +class OverrideIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> - ((t: Any, p: Parameters) => { + ((t: Any) => { t match { - case system: T => fn(system, p) + case system: T => fn(system) case _ => Nil } }) @@ -67,12 +82,12 @@ class OverrideIOBinder[T](fn: => (T, Parameters) => Seq[IOBinderTuple])(implicit // This macro composes with previous matches on some Top mixin. This is useful for // annotation-like binders, since those can typically be composed -class ComposeIOBinder[T](fn: => (T, Parameters) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { +class ComposeIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> - ((t: Any, p: Parameters) => { + ((t: Any) => { t match { - case system: T => (up(IOBinders, site)(tag.runtimeClass.toString)(system, p) - ++ fn(system, p)) + case system: T => (up(IOBinders, site)(tag.runtimeClass.toString)(system) + ++ fn(system)) case _ => Nil } }) @@ -211,7 +226,7 @@ object AddIOCells { // DOC include start: WithGPIOTiedOff class WithGPIOTiedOff extends OverrideIOBinder({ - (system: HasPeripheryGPIOModuleImp, p) => { + (system: HasPeripheryGPIOModuleImp) => { val (ports2d, ioCells2d) = AddIOCells.gpio(system.gpio) val harnessFn = (th: chipyard.TestHarness) => { ports2d.flatten.foreach(_ <> AnalogConst(0)); Nil } Seq((ports2d.flatten, ioCells2d.flatten, Some(harnessFn))) @@ -220,7 +235,7 @@ class WithGPIOTiedOff extends OverrideIOBinder({ // DOC include end: WithGPIOTiedOff class WithUARTAdapter extends OverrideIOBinder({ - (system: HasPeripheryUARTModuleImp, p) => { + (system: HasPeripheryUARTModuleImp) => { val (ports, ioCells2d) = AddIOCells.uart(system.uart) val harnessFn = (th: chipyard.TestHarness) => { UARTAdapter.connect(ports)(system.p); Nil } Seq((ports, ioCells2d.flatten, Some(harnessFn))) @@ -228,7 +243,7 @@ class WithUARTAdapter extends OverrideIOBinder({ }) class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideIOBinder({ - (system: HasPeripherySPIFlashModuleImp, p) => { + (system: HasPeripherySPIFlashModuleImp) => { val (ports, ioCells2d) = AddIOCells.spi(system.qspi, "qspi") val harnessFn = (th: chipyard.TestHarness) => { SimSPIFlashModel.connect(ports, th.reset, rdOnly)(system.p); Nil } Seq((ports, ioCells2d.flatten, Some(harnessFn))) @@ -236,7 +251,7 @@ class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideIOBinder({ }) class WithSimBlockDevice extends OverrideIOBinder({ - (system: CanHavePeripheryBlockDeviceModuleImp, p) => system.bdev.map { bdev => + (system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev => val (port, ios) = AddIOCells.blockDev(bdev) val harnessFn = (th: chipyard.TestHarness) => { SimBlockDevice.connect(th.clock, th.reset.asBool, Some(port))(system.p) @@ -247,7 +262,7 @@ class WithSimBlockDevice extends OverrideIOBinder({ }) class WithBlockDeviceModel extends OverrideIOBinder({ - (system: CanHavePeripheryBlockDeviceModuleImp, p) => system.bdev.map { bdev => + (system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev => val (port, ios) = AddIOCells.blockDev(bdev) val harnessFn = (th: chipyard.TestHarness) => { BlockDeviceModel.connect(Some(port))(system.p) @@ -258,26 +273,23 @@ class WithBlockDeviceModel extends OverrideIOBinder({ }) class WithLoopbackNIC extends OverrideIOBinder({ - (system: CanHavePeripheryIceNICModuleImp, p) => system.connectNicLoopback(); Nil + (system: CanHavePeripheryIceNICModuleImp) => system.connectNicLoopback(); Nil }) class WithSimNIC extends OverrideIOBinder({ - (system: CanHavePeripheryIceNICModuleImp, p) => system.connectSimNetwork(system.clock, system.reset.asBool); Nil + (system: CanHavePeripheryIceNICModuleImp) => system.connectSimNetwork(system.clock, system.reset.asBool); Nil }) -// Note: The parameters instance is accessible only through the BaseSubsystem -// or some parent class (IsAttachable, BareSubsystem -> LazyModule). The -// self-type requirement in CanHaveMasterAXI4MemPort is insufficient to make it -// accessible to the IOBinder // DOC include start: WithSimAXIMem class WithSimAXIMem extends OverrideIOBinder({ - (system: CanHaveMasterAXI4MemPort, p) => { + (system: CanHaveMasterAXI4MemPort) => { + implicit val p: Parameters = GetSystemParameters(system) val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node, "mem") // TODO: we are inlining the connectMem method of SimAXIMem because // it takes in a dut rather than seq of axi4 ports val harnessFn = (th: chipyard.TestHarness) => { peiTuples.map { case (port, edge, ios) => - val mem = LazyModule(new SimAXIMem(edge, size = p(ExtMem).get.master.size)(p)) + val mem = LazyModule(new SimAXIMem(edge, size = p(ExtMem).get.master.size)) Module(mem.module).suggestName("mem") mem.io_axi4.head <> port } @@ -289,7 +301,8 @@ class WithSimAXIMem extends OverrideIOBinder({ // DOC include end: WithSimAXIMem class WithBlackBoxSimMem extends OverrideIOBinder({ - (system: CanHaveMasterAXI4MemPort, p) => { + (system: CanHaveMasterAXI4MemPort) => { + implicit val p: Parameters = GetSystemParameters(system) val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node, "mem") val harnessFn = (th: chipyard.TestHarness) => { peiTuples.map { case (port, edge, ios) => @@ -307,11 +320,12 @@ class WithBlackBoxSimMem extends OverrideIOBinder({ }) class WithSimAXIMMIO extends OverrideIOBinder({ - (system: CanHaveMasterAXI4MMIOPort, p) => { + (system: CanHaveMasterAXI4MMIOPort) => { + implicit val p: Parameters = GetSystemParameters(system) val peiTuples = AddIOCells.axi4(system.mmio_axi4, system.mmioAXI4Node, "mmio_mem") val harnessFn = (th: chipyard.TestHarness) => { peiTuples.zipWithIndex.map { case ((port, edge, ios), i) => - val mmio_mem = LazyModule(new SimAXIMem(edge, size = 4096)(p)) + val mmio_mem = LazyModule(new SimAXIMem(edge, size = 4096)) Module(mmio_mem.module).suggestName(s"mmio_mem_${i}") mmio_mem.io_axi4.head <> port } @@ -322,11 +336,11 @@ class WithSimAXIMMIO extends OverrideIOBinder({ }) class WithDontTouchPorts extends OverrideIOBinder({ - (system: DontTouch, p) => system.dontTouchPorts(); Nil + (system: DontTouch) => system.dontTouchPorts(); Nil }) class WithTieOffInterrupts extends OverrideIOBinder({ - (system: HasExtInterruptsModuleImp, p) => { + (system: HasExtInterruptsModuleImp) => { val (port, ioCells) = IOCell.generateIOFromSignal(system.interrupts, Some("iocell_interrupts")) port.suggestName("interrupts") val harnessFn = (th: chipyard.TestHarness) => { port := 0.U; Nil } @@ -335,7 +349,7 @@ class WithTieOffInterrupts extends OverrideIOBinder({ }) class WithTieOffL2FBusAXI extends OverrideIOBinder({ - (system: CanHaveSlaveAXI4Port, p) => { + (system: CanHaveSlaveAXI4Port) => { val peiTuples = AddIOCells.axi4(system.l2_frontend_bus_axi4, system.l2FrontendAXI4Node, "l2_fbus") val harnessFn = (th: chipyard.TestHarness) => { peiTuples.zipWithIndex.map { case ((port, edge, ios), i) => @@ -349,7 +363,7 @@ class WithTieOffL2FBusAXI extends OverrideIOBinder({ }) class WithTiedOffDebug extends OverrideIOBinder({ - (system: HasPeripheryDebugModuleImp, p) => { + (system: HasPeripheryDebugModuleImp) => { val (psdPort, resetctrlOpt, debugPortOpt, ioCells) = AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p) val harnessFn = (th: chipyard.TestHarness) => { @@ -367,7 +381,7 @@ class WithTiedOffDebug extends OverrideIOBinder({ }) class WithSimDebug extends OverrideIOBinder({ - (system: HasPeripheryDebugModuleImp, p) => { + (system: HasPeripheryDebugModuleImp) => { val (psdPort, resetctrlPortOpt, debugPortOpt, ioCells) = AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p) val harnessFn = (th: chipyard.TestHarness) => { @@ -382,7 +396,7 @@ class WithSimDebug extends OverrideIOBinder({ }) class WithTiedOffSerial extends OverrideIOBinder({ - (system: CanHavePeripherySerialModuleImp, p) => system.serial.map({ serial => + (system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial => val (port, ioCells) = AddIOCells.serial(serial) val harnessFn = (th: chipyard.TestHarness) => { SerialAdapter.tieoff(port) @@ -393,7 +407,7 @@ class WithTiedOffSerial extends OverrideIOBinder({ }) class WithSimSerial extends OverrideIOBinder({ - (system: CanHavePeripherySerialModuleImp, p) => system.serial.map({ serial => + (system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial => val (port, ioCells) = AddIOCells.serial(serial) val harnessFn = (th: chipyard.TestHarness) => { val ser_success = SerialAdapter.connectSimSerial(port, th.clock, th.harnessReset) @@ -405,7 +419,7 @@ class WithSimSerial extends OverrideIOBinder({ }) class WithTraceGenSuccessBinder extends OverrideIOBinder({ - (system: TraceGenSystemModuleImp, p) => { + (system: TraceGenSystemModuleImp) => { val (successPort, ioCells) = IOCell.generateIOFromSignal(system.success, Some("iocell_success")) successPort.suggestName("success") val harnessFn = (th: chipyard.TestHarness) => { when (successPort) { th.success := true.B }; Nil } @@ -414,7 +428,7 @@ class WithTraceGenSuccessBinder extends OverrideIOBinder({ }) class WithSimDromajoBridge extends ComposeIOBinder({ - (system: CanHaveTraceIOModuleImp, p) => { + (system: CanHaveTraceIOModuleImp) => { system.traceIO match { case Some(t) => t.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) } Nil } diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index 6af7bd0a..eba57451 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -26,7 +26,7 @@ import ariane.ArianeTile import boom.common.{BoomTile} -import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder} +import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder, GetSystemParameters} import testchipip.{CanHaveTraceIOModuleImp} object MainMemoryConsts { @@ -35,63 +35,67 @@ object MainMemoryConsts { } class WithSerialBridge extends OverrideIOBinder({ - (system: CanHavePeripherySerialModuleImp, p) => - system.serial.foreach(s => SerialBridge(system.clock, s, MainMemoryConsts.globalName)(p)); Nil + (system: CanHavePeripherySerialModuleImp) => + system.serial.foreach(s => SerialBridge(system.clock, s, MainMemoryConsts.globalName)(system.p)); Nil }) class WithNICBridge extends OverrideIOBinder({ - (system: CanHavePeripheryIceNICModuleImp, p) => - system.net.foreach(n => NICBridge(system.clock, n)(p)); Nil + (system: CanHavePeripheryIceNICModuleImp) => + system.net.foreach(n => NICBridge(system.clock, n)(system.p)); Nil }) class WithUARTBridge extends OverrideIOBinder({ - (system: HasPeripheryUARTModuleImp, p) => - system.uart.foreach(u => UARTBridge(system.clock, u)(p)); Nil + (system: HasPeripheryUARTModuleImp) => + system.uart.foreach(u => UARTBridge(system.clock, u)(system.p)); Nil }) class WithBlockDeviceBridge extends OverrideIOBinder({ - (system: CanHavePeripheryBlockDeviceModuleImp, p) => - system.bdev.foreach(b => BlockDevBridge(system.clock, b, system.reset.toBool)(p)); Nil + (system: CanHavePeripheryBlockDeviceModuleImp) => + system.bdev.foreach(b => BlockDevBridge(system.clock, b, system.reset.toBool)(system.p)); Nil }) class WithFASEDBridge extends OverrideIOBinder({ - (system: CanHaveMasterAXI4MemPort, p) => { + (system: CanHaveMasterAXI4MemPort) => { + implicit val p: Parameters = GetSystemParameters(system) (system.mem_axi4 zip system.memAXI4Node.in).foreach({ case (axi4, (_, edge)) => val nastiKey = NastiParameters(axi4.r.bits.data.getWidth, axi4.ar.bits.addr.getWidth, axi4.ar.bits.id.getWidth) - FASEDBridge(system.module.clock, axi4, system.module.reset.toBool, - CompleteConfig(p(firesim.configs.MemModelKey), - nastiKey, - Some(AXI4EdgeSummary(edge)), - Some(MainMemoryConsts.globalName))) + system match { + case s: BaseSubsystem => FASEDBridge(s.module.clock, axi4, s.module.reset.toBool, + CompleteConfig(p(firesim.configs.MemModelKey), + nastiKey, + Some(AXI4EdgeSummary(edge)), + Some(MainMemoryConsts.globalName))) + case _ => throw new Exception("Attempting to attach FASED Bridge to misconfigured design") + } }) Nil } }) class WithTracerVBridge extends ComposeIOBinder({ - (system: CanHaveTraceIOModuleImp, p) => - system.traceIO.foreach(_.traces.map(tileTrace => TracerVBridge(tileTrace)(p))); Nil + (system: CanHaveTraceIOModuleImp) => + system.traceIO.foreach(_.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p))); Nil }) class WithDromajoBridge extends ComposeIOBinder({ - (system: CanHaveTraceIOModuleImp, p) => { - system.traceIO.foreach(_.traces.map(tileTrace => DromajoBridge(tileTrace)(p))); Nil + (system: CanHaveTraceIOModuleImp) => { + system.traceIO.foreach(_.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p))); Nil } }) class WithTraceGenBridge extends OverrideIOBinder({ - (system: TraceGenSystemModuleImp, p) => + (system: TraceGenSystemModuleImp) => GroundTestBridge(system.clock, system.success)(system.p); Nil }) class WithFireSimMultiCycleRegfile extends ComposeIOBinder({ - (system: HasTilesModuleImp, p) => { + (system: HasTilesModuleImp) => { system.outer.tiles.map { case r: RocketTile => { annotate(MemModelAnnotation(r.module.core.rocketImpl.rf.rf)) @@ -115,13 +119,13 @@ class WithFireSimMultiCycleRegfile extends ComposeIOBinder({ }) class WithTiedOffSystemGPIO extends OverrideIOBinder({ - (system: HasPeripheryGPIOModuleImp, p) => + (system: HasPeripheryGPIOModuleImp) => system.gpio.foreach(_.pins.foreach(_.i.ival := false.B)); Nil }) class WithTiedOffSystemDebug extends OverrideIOBinder({ - (system: HasPeripheryDebugModuleImp, p) => { - Debug.tieoffDebug(system.debug, system.resetctrl, Some(system.psd))(p) + (system: HasPeripheryDebugModuleImp) => { + Debug.tieoffDebug(system.debug, system.resetctrl, Some(system.psd))(system.p) // tieoffDebug doesn't actually tie everything off :/ system.debug.foreach { d => d.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare }) @@ -132,7 +136,7 @@ class WithTiedOffSystemDebug extends OverrideIOBinder({ }) class WithTiedOffSystemInterrupts extends OverrideIOBinder({ - (system: HasExtInterruptsModuleImp, p) => + (system: HasExtInterruptsModuleImp) => system.interrupts := 0.U; Nil }) From 744e73fa9223c9b5571b91d388566b8a07ba8949 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sun, 5 Jul 2020 21:05:21 -0700 Subject: [PATCH 35/63] Editing Docs --- docs/Customization/Custom-Core.rst | 179 ++++++------------ .../src/main/scala/example/TutorialTile.scala | 179 ++++++++++++++++++ 2 files changed, 241 insertions(+), 117 deletions(-) create mode 100644 generators/chipyard/src/main/scala/example/TutorialTile.scala diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index dcf2c257..17b9b125 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -3,21 +3,24 @@ Adding a custom core ==================== -You may want to add a custom RISC-V core to Chipyard generator. If the top module of your core is not in Chisel, -you will first need to create a Verilog blackbox for it. See :ref:`incorporating-verilog-blocks` for instructions. -Once you have a top module in Chisel, you are ready to create integrate it with Chipyard. - -``generators/ariane/src/main/scala/ArianeTile.scala`` and ``generators/boom/src/main/scala/common/tile.scala`` -provide two examples of how to integrate a core. +You may want to integrate a custom RISC-V core into the Chipyard framework. This documentation page provides a step-to-step +instruction on how to achieve this. .. note:: - RoCC is not supported by custom core currently. Please use Rocket or Boom as the RoCC base core if you need to use RoCC. + RoCC is currently not supported by cores other than Rocket and BOOM. Please use Rocket or BOOM as the RoCC base core if you need to use RoCC. -Parameter Case Classes ----------------------- -Chipyard will generate a core for every ``InstantiableTileParams`` object it discovered in the current config. +Wrap Verilog Module with Blackbox (Optional) +-------------------------------------------- + +Since Chipyard uses Scala and Chisel, if the top module of your core is not in Chisel, you will first need to create a Verilog +blackbox for it so that it can be processed by Chipyard. See :ref:`incorporating-verilog-blocks` for instructions. + +Create Parameter Case Classes +----------------------------- + +Chipyard will generate a core for every ``InstantiableTileParams`` object it discovered in the ``TilesLocated(InSubsystem)`` key. This object is derived from``TileParams``, a trait containing the information needed to create a tile. All cores must have their own implementation of ``InstantiableTileParams``, as well as ``CoreParams`` which is passed as a field in ``TileParams``. @@ -41,7 +44,7 @@ need a custom field with similar purposes): val icache: Option[ICacheParams] // Rocket specific: I1 cache option val dcache: Option[DCacheParams] // Rocket specific: D1 cache option val btb: Option[BTBParams] // Rocket specific: BTB / branch predictor option - val hartId: Int // Hart ID: Must be unique within a design config + val hartId: Int // Hart ID: Must be unique within a design config (This MUST be a case class parameter) val beuAddr: Option[BigInt] // Rocket specific: Bus Error Unit for Rocket Core val blockerCtrlAddr: Option[BigInt] // Rocket specific: Bus Blocker for Rocket Core val name: Option[String] // Name of the core @@ -110,110 +113,64 @@ need a custom field with similar purposes): dfmaLatency: Int = 4 // Rocket specific: Fused multiply-add pipeline latency (double precision) ) -Most of the fields here are originally designed for Rocket core and contains some architecture-specific details, but +Most of the fields here are originally designed for the Rocket core and thus contain some implementation-specific details, but many of them are general enough to be useful for other cores. It is strongly recommended to use these fields instead of creating your own custom fields when applicable. +You will also need a ``CanAttachTile`` class to add the tile config into the config system, with the following format: + +.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala + :language: scala + :lines: 61-67 + .. note:: Implementations may choose to ignore some fields here or use them in a non-standard way, but using an inaccurate - value may break Chipyard components that rely on them (e.g. inaccurate indication of supported ISA extension will - result in incorrect test suite being generated) as well as any custom module that use them. ALWAYS document any + value may break Chipyard components that rely on them (e.g. an inaccurate indication of supported ISA extension will + result in an incorrect test suite being generated) as well as any custom modules that use them. ALWAYS document any fields you ignore or with altered usage in your core implementation, and if you are implementing other devices that would look up these config values, also document them. "Rocket specific" values are generally safe to ignore, but you should document them if you use them. -Tile Class ----------- +Create Tile Class +----------------- In Chipyard, all Tiles are diplomatically instantiated. In the first phase, diplomatic nodes which specify Tile-to-System interconnects are evaluated, while in the second "Module Implementation" phase, hardware is elaborated. -See :ref:`tilelink_and_diplomacy` for more details. +See :ref:`tilelink_and_diplomacy` for more details. In this step, you will need to implement a tile class for your core. All tile classes implement ``BaseTile`` and will normally implement ``SinksExternalInterrupts`` and ``SourcesExternalNotifications``, which allow the tile to accept external interrupt. A typical tile has the following form: -.. code-block:: scala +.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala + :language: scala + :lines: 87-125, 143 - class MyTile( - val myParams: MyTileParams, - crossing: ClockCrossingType, - lookup: LookupByHartIdImpl, - q: Parameters, - logicalTreeNode: LogicalTreeNode) - extends BaseTile(myParams, crossing, lookup, q) - with SinksExternalInterrupts - with SourcesExternalNotifications - { +Connect TileLink Buses +---------------------- - // Private constructor ensures altered LazyModule.p is used implicitly - def this(params: MyTileParams, crossing: RocketCrossingParams, lookup: LookupByHartIdImpl, logicalTreeNode: LogicalTreeNode)(implicit p: Parameters) = - this(params, crossing.crossingType, lookup, p, logicalTreeNode) - - // Require TileLink nodes - val intOutwardNode = IntIdentityNode() - val masterNode = visibilityNode - val slaveNode = TLIdentityNode() - - // Implementation class (See below) - override lazy val module = new MyTileModuleImp(this) - - // Required entry of CPU device in the device tree for interrupt purpose - val cpuDevice: SimpleDevice = new SimpleDevice("cpu", Seq("my-organization,my-cpu", "riscv")) { - override def parent = Some(ResourceAnchors.cpus) - override def describe(resources: ResourceBindings): Description = { - val Description(name, mapping) = super.describe(resources) - Description(name, mapping ++ - cpuProperties ++ - nextLevelCacheProperty ++ - tileProperties) - } - } - - ResourceBinding { - Resource(cpuDevice, "reg").bind(ResourceAddress(hartId)) - } - - // (Connection to bus, interrupt, etc.) - } - -TileLink Connection -------------------- - -Chipyard use TileLink as its onboard bus protocol, and if your core doesn't use TileLink, you will need to convert them +Chipyard use TileLink as its onboard bus protocol. If your core doesn't use TileLink, you will need to insert converters +between the core's memory protocol and TileLink in the Tile module. in the tile class. Below is an example of how to connect a core using AXI4 to the TileLink bus with converters provided by -Chipyards: +Rocket chip: -.. code-block:: scala - - val memoryTap = TLIdentityNode() // Every bus connection should have their own tap node - (tlMasterXbar.node // tlMasterXbar is the bus crossbar to be used when this core / tile is acting as a master; otherwise, use tlSlaveXBar - := memoryTap - := TLBuffer() - := TLFIFOFixer(TLFIFOFixer.all) // fix FIFO ordering - := TLWidthWidget(beatBytes) // reduce size of TL - := AXI4ToTL() // convert to TL - := AXI4UserYanker(Some(2)) // remove user field on AXI interface. need but in reality user intf. not needed - := AXI4Fragmenter() // deal with multi-beat xacts - := memAXI4Node) // The custom node, see below +.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala + :language: scala + :lines: 133-142 Remember, you may not need all of these intermediate widgets. See :ref:`diplomatic_widgets` for the meaning of each intermediate widget. If you are using TileLink, then you only need the tap node and the TileLink node used by your components. Chipyard also provides converters for AHB, APB and AXIS, and most of the AXI4 widgets has equivalent widget for these bus protocol; see the source files in ``generators/rocket-chip/src/main/scala/amba`` for more info. -If you are using other bus protocol, you may implement your own converters, using the files in ``generators/rocket-chip/src/main/scala/amba`` +If you are using some other bus protocol, you may implement your own converters, using the files in ``generators/rocket-chip/src/main/scala/amba`` as the template, but it is not recommended unless you are familiar with TileLink. ``memAXI4Node`` is an AXI4 master node and is defined as following in our example: -.. code-block:: scala - - val memAXI4Node = AXI4MasterNode( - Seq(AXI4MasterPortParameters( - masters = Seq(AXI4MasterParameters( - name = portName, - id = IdRange(0, 1 << idBits)))))) +.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala + :language: scala + :lines: 126-132 where ``portName`` and ``idBits`` (number of bits to represent a port ID) are the parameter provides by the tile. Make sure to read :ref:`node_types` to check out what type of nodes Chipyard supports and their parameters! @@ -228,8 +185,8 @@ can override the following two functions to control how to buffer the bus reques You can find more information on ``TLBuffer`` in :ref:`diplomatic_widgets`. -Interrupt ---------- +Connect Interrupt +----------------- Chipyard allows a tile to either receive interrupts from other devices or initiate interrupts to notify other cores/devices. In the tile that inherited ``SinksExternalInterrupts``, one can create a ``TileInterrupts`` object (a Chisel bundle) and @@ -258,48 +215,33 @@ from the implementation class: reportCease(could_cease: Option[Bool], quiescenceCycles: Int = 8) // Triggered when the core stop retiring instructions (like clock gating) reportWFI(could_wfi: Option[Bool]) // Triggered when a WFI instruction is executed -Implementation Class --------------------- +Create Implementation Class +--------------------------- -The implementation class is of the following form: +The implementation class for your core is of the following form: -.. code-block:: scala - - class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){ - // annotate the parameters - Annotated.params(this, outer.tileParams) - - // TODO: Create the top module of the core and connect it with the ports in "outer" - } +.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala + :language: scala + :lines: 145-149, 160 In the body of this class, you can look up any parameters by calling ``p({key})``, where ``{key}`` is the config key of -the value you want to look up. For a list of available keys, see the appendix below. +the value you want to look up. For a list of frequently used keys, see the appendix below. If you create an AXI4 node (or equivalents), you will need to connect them to your core. You can connect a port like this: -.. code-block:: scala +.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala + :language: scala + :lines: 151-159 - outer.myAXI4Node.out foreach { case (out, edgeOut) => - // Connect your module IO port to "out" - // The type of "out" here is AXI4Bundle, which is defined in generators/rocket-chip/src/main/scala/amba/axi4/Bundles.scala - // Please refer to this file for the definition of the ports. - // If you are using APB, check APBBundle in generators/rocket-chip/src/main/scala/amba/apb/Bundles.scala - // If you are using AHB, check AHBSlaveBundle or AHBMasterBundle in generators/rocket-chip/src/main/scala/amba/ahb/Bundles.scala - // (choose one depends on the type of AHB node you create) - // If you are using AXIS, check AXISBundle and AXISBundleBits in generators/rocket-chip/src/main/scala/amba/axis/Bundles.scala - } +Create Config Fragments to Integrate the Core +--------------------------------------------- -Integrate the Core ------------------- - -To use your core in a set of config, you would need a config fragment that would create a ``TileParams`` object of your core in +To use your core in a Chipyard config, you would need a config fragment that would create a ``TileParams`` object of your core in the current config. An example of such config will be like this: -.. code-block:: scala - - class WithNMyCores(n: Int, hartidOffset: Int) extends Config((site, here, up) => { - case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem)) :++ List.tabulate(n)(i => MyTileParams(hartId = i + hartidOffset)) - }) +.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala + :language: scala + :lines: 162-179 Chipyard looks up the tile parameters in the field ``TilesLocated(InSubsystem)``, whose type is a list of ``InstantiableTileParams``. This config fragment simply appends new tile parameters to the end of this list. @@ -308,6 +250,9 @@ Now you have finished all the steps to prepare your cores for Chipyard! To gener in :ref:`custom_chisel` to add your project to the build system, then create a config by following the steps in :ref:`hetero_socs_`. You can now run any desired workflow for the new config just as you do for the built-in cores. +If you would like to see how an actual core are integrated into Chipyard, ``generators/ariane/src/main/scala/ArianeTile.scala`` +provides a concrete example of integrating a third party Verilog core Ariane. + Appendix: Common Config Keys ---------------------------- diff --git a/generators/chipyard/src/main/scala/example/TutorialTile.scala b/generators/chipyard/src/main/scala/example/TutorialTile.scala new file mode 100644 index 00000000..12173184 --- /dev/null +++ b/generators/chipyard/src/main/scala/example/TutorialTile.scala @@ -0,0 +1,179 @@ +package chipyard.example + +import chisel3._ +import chisel3.util._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.diplomaticobjectmodel.logicaltree.{LogicalTreeNode} +import freechips.rocketchip.rocket._ +import freechips.rocketchip.subsystem.{RocketCrossingParams} +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.interrupts._ +import freechips.rocketchip.util._ +import freechips.rocketchip.tile._ +import freechips.rocketchip.amba.axi4._ + +// Example parameter class copied from Ariane, not included in documentation but for compile check only +// If you are here for documentation, DO NOT copy MyCoreParams and MyTileParams directly - always figure +// out what parameters you need before you write the parameter class +case class MyCoreParams( + bootFreqHz: BigInt = BigInt(1700000000), + rasEntries: Int = 4, + btbEntries: Int = 16, + bhtEntries: Int = 16, + enableToFromHostCaching: Boolean = false, +) extends CoreParams { + val useVM: Boolean = true + val useUser: Boolean = true + val useSupervisor: Boolean = false + val useDebug: Boolean = true + val useAtomics: Boolean = true + val useAtomicsOnlyForIO: Boolean = false // copied from Rocket + val useCompressed: Boolean = true + override val useVector: Boolean = false + val useSCIE: Boolean = false + val useRVE: Boolean = false + val mulDiv: Option[MulDivParams] = Some(MulDivParams()) // copied from Rocket + val fpu: Option[FPUParams] = Some(FPUParams()) // copied fma latencies from Rocket + val nLocalInterrupts: Int = 0 + val nPMPs: Int = 0 // TODO: Check + val pmpGranularity: Int = 4 // copied from Rocket + val nBreakpoints: Int = 0 // TODO: Check + val useBPWatch: Boolean = false + val nPerfCounters: Int = 29 + val haveBasicCounters: Boolean = true + val haveFSDirty: Boolean = false + val misaWritable: Boolean = false + val haveCFlush: Boolean = false + val nL2TLBEntries: Int = 512 // copied from Rocket + val mtvecInit: Option[BigInt] = Some(BigInt(0)) // copied from Rocket + val mtvecWritable: Boolean = true // copied from Rocket + val instBits: Int = if (useCompressed) 16 else 32 + val lrscCycles: Int = 80 // copied from Rocket + val decodeWidth: Int = 1 // TODO: Check + val fetchWidth: Int = 1 // TODO: Check + val retireWidth: Int = 2 +} + +case class MyTileAttachParams( + tileParams: MyTileParams, + crossingParams: RocketCrossingParams +) extends CanAttachTile { + type TileType = MyTile + val lookup = PriorityMuxHartIdFromSeq(Seq(tileParams)) +} + +case class MyTileParams( + name: Option[String] = Some("my_tile"), + hartId: Int = 0, + trace: Boolean = false, + val core: MyCoreParams = MyCoreParams() +) extends InstantiableTileParams[MyTile] +{ + val beuAddr: Option[BigInt] = None + val blockerCtrlAddr: Option[BigInt] = None + val btb: Option[BTBParams] = Some(BTBParams()) + val boundaryBuffers: Boolean = false + val dcache: Option[DCacheParams] = Some(DCacheParams()) + val icache: Option[ICacheParams] = Some(ICacheParams()) + def instantiate(crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters): MyTile = { + new MyTile(this, crossing, lookup) + } +} + +class MyTile( + val myParams: MyTileParams, + crossing: ClockCrossingType, + lookup: LookupByHartIdImpl, + q: Parameters) + extends BaseTile(myParams, crossing, lookup, q) + with SinksExternalInterrupts + with SourcesExternalNotifications +{ + + // Private constructor ensures altered LazyModule.p is used implicitly + def this(params: MyTileParams, crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters) = + this(params, crossing.crossingType, lookup, p) + + // Require TileLink nodes + val intOutwardNode = IntIdentityNode() + val masterNode = visibilityNode + val slaveNode = TLIdentityNode() + + // Implementation class (See below) + override lazy val module = new MyTileModuleImp(this) + + // Required entry of CPU device in the device tree for interrupt purpose + val cpuDevice: SimpleDevice = new SimpleDevice("cpu", Seq("my-organization,my-cpu", "riscv")) { + override def parent = Some(ResourceAnchors.cpus) + override def describe(resources: ResourceBindings): Description = { + val Description(name, mapping) = super.describe(resources) + Description(name, mapping ++ + cpuProperties ++ + nextLevelCacheProperty ++ + tileProperties) + } + } + + ResourceBinding { + Resource(cpuDevice, "reg").bind(ResourceAddress(hartId)) + } + + // (Connection to bus, interrupt, etc.) + // # of bits used in TileLink ID for master node. 4 bits can support 16 master nodes, but you can have a longer ID if you need more. + val idBits = 4 + val memAXI4Node = AXI4MasterNode( + Seq(AXI4MasterPortParameters( + masters = Seq(AXI4MasterParameters( + name = "myPortName", + id = IdRange(0, 1 << idBits)))))) + val memoryTap = TLIdentityNode() // Every bus connection should have their own tap node + (tlMasterXbar.node // tlMasterXbar is the bus crossbar to be used when this core / tile is acting as a master; otherwise, use tlSlaveXBar + := memoryTap + := TLBuffer() + := TLFIFOFixer(TLFIFOFixer.all) // fix FIFO ordering + := TLWidthWidget(masterPortBeatBytes) // reduce size of TL + := AXI4ToTL() // convert to TL + := AXI4UserYanker(Some(2)) // remove user field on AXI interface. need but in reality user intf. not needed + := AXI4Fragmenter() // deal with multi-beat xacts + := memAXI4Node) // The custom node, see below +} + +class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){ + // annotate the parameters + Annotated.params(this, outer.myParams) + + // TODO: Create the top module of the core and connect it with the ports in "outer" + + outer.memAXI4Node.out foreach { case (out, edgeOut) => + // Connect your module IO port to "out" + // The type of "out" here is AXI4Bundle, which is defined in generators/rocket-chip/src/main/scala/amba/axi4/Bundles.scala + // Please refer to this file for the definition of the ports. + // If you are using APB, check APBBundle in generators/rocket-chip/src/main/scala/amba/apb/Bundles.scala + // If you are using AHB, check AHBSlaveBundle or AHBMasterBundle in generators/rocket-chip/src/main/scala/amba/ahb/Bundles.scala + // (choose one depends on the type of AHB node you create) + // If you are using AXIS, check AXISBundle and AXISBundleBits in generators/rocket-chip/src/main/scala/amba/axis/Bundles.scala + } +} + +class WithNMyCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends Config((site, here, up) => { + case TilesLocated(InSubsystem) => { + // Calculate the next available hart ID (since hart ID cannot be duplicated) + val prev = up(TilesLocated(InSubsystem), site) + val idOffset = overrideIdOffset.getOrElse(prev.size) + // Create TileAttachParams for every core to be instantiated + (0 until n).map { i => + MyTileAttachParams( + tileParams = MyTileParams(hartId = i + idOffset), + crossingParams = RocketCrossingParams() + ) + } ++ prev + } + // Configurate # of bytes in one memory / IO transaction. For RV64, one load/store instruction can transfer 8 bytes at most. + case SystemBusKey => up(SystemBusKey, site).copy(beatBytes = 8) + // The # of instruction bits. Use maximum # of bits if your core supports both 32 and 64 bits. + case XLen => 64 +}) From 6cb8a60a808d426a111cd470cf360460bbde3cbd Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sun, 5 Jul 2020 21:18:31 -0700 Subject: [PATCH 36/63] Remove Key List --- docs/Customization/Custom-Core.rst | 83 ------------------------------ 1 file changed, 83 deletions(-) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index 17b9b125..94d47505 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -224,9 +224,6 @@ The implementation class for your core is of the following form: :language: scala :lines: 145-149, 160 -In the body of this class, you can look up any parameters by calling ``p({key})``, where ``{key}`` is the config key of -the value you want to look up. For a list of frequently used keys, see the appendix below. - If you create an AXI4 node (or equivalents), you will need to connect them to your core. You can connect a port like this: .. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala @@ -252,83 +249,3 @@ You can now run any desired workflow for the new config just as you do for the b If you would like to see how an actual core are integrated into Chipyard, ``generators/ariane/src/main/scala/ArianeTile.scala`` provides a concrete example of integrating a third party Verilog core Ariane. - -Appendix: Common Config Keys ----------------------------- - -Chipyard provide a set of keys to store standard parameters. Below are some of the most common key used in core integration. -(Note that internal fields are hidden) - -.. code-block:: scala - - // keys - // Parameters exposed to the top-level design, set based on external requirements, etc. See RISC-V debug specs for more info. - case object DebugModuleKey extends Field[Option[DebugModuleParams]](Some(DebugModuleParams())) - case object BootROMParams extends Field[BootROMParams] // See chipyard boot process tutorial - case object CLINTKey extends Field[Option[CLINTParams]](None) // Core Local Interrupter setting (See SiFive Interrupt Cookbook) - case object PLICKey extends Field[Option[PLICParams]](None) // Platform Level Interrupt Controller setting (See SiFive Interrupt Cookbook) - case object CacheBlockBytes extends Field[Int](64) // # of bytes in a cache block - case object BroadcastKey extends Field(BroadcastParams()) // L2 Cache broadcast setting - case object BankedL2Key extends Field(BankedL2Params()) // L2 Cache memory setting - case object PgLevels extends Field[Int](2) // Page Level of virtual memory - case object ASIdBits extends Field[Int](0) // Max # of bits for Address Space Identifer (See specs) - case object ExtMem extends Field[Option[MemoryPortParams]](None) // External DRAM setting - case object ExtBus extends Field[Option[MasterPortParams]](None) // External (off-chip) output bus setting - case object ExtIn extends Field[Option[SlavePortParams]](None) // External (off-chip) input bus setting - case object MaxHartIdBits extends Field[Int] // Max # of bits used to represent a Hart ID - case object XLen extends Field[Int] // Instruction bits (32 or 64) - case object BuildRoCC extends Field[Seq[Parameters => LazyRoCC]](Nil) // See custom ROCC tutorial - - // Values - case class DebugModuleParams ( - nDMIAddrSize : Int = 7, // Size of the Debug Bus Address - nProgramBufferWords: Int = 16, // Number of 32-bit words for Program Buffer - nAbstractDataWords : Int = 4, // Number of 32-bit words for Abstract Commands - nScratch : Int = 1, // Number of scratch memories used - hasBusMaster : Boolean = false, // Whether or not a bus master should be included - clockGate : Boolean = true, // Use clock gating - maxSupportedSBAccess : Int = 32, // Maximum transaction size supported by System Bus Access logic. - supportQuickAccess : Boolean = false, // Whether or not to support the quick access command. - supportHartArray : Boolean = true, // Whether or not to implement the hart array register (if >1 hart). - nHaltGroups : Int = 1, // Number of halt groups (group of harts that are halted together) - nExtTriggers : Int = 0, // Number of extra triggers - hasHartResets : Boolean = false, // Whether harts can be reseted with debugging system - hasImplicitEbreak : Boolean = false, // There is an additional RO program buffer word containing an ebreak - hasAuthentication : Boolean = false, // Has authentication (to prevent unauthorized users to use debugging system) - crossingHasSafeReset : Boolean = true // Include "safe" logic in Async Crossings so that only one side needs to be reset. - ) - case class CLINTParams( - baseAddress: BigInt = 0x02000000, // Default interrupt handler base address for CLINT - intStages: Int = 0 // # of cycles (stages) interrupts are delayed - ) - case class PLICParams( - baseAddress: BigInt = 0xC000000, // Default interrupt handler base address for PLIC - maxPriorities: Int = 7, // Maximum allowed interrupt priority (cannot be over 7) - intStages: Int = 0, // # of cycles (stages) interrupts are delayed - maxHarts: Int = PLICConsts.maxMaxHarts // Maximum number or hart / core connected to it - ) - case class BroadcastParams( - nTrackers: Int = 4, // # of broadcast tracker - bufferless: Boolean = false // Bufferless broadcast - ) - case class BankedL2Params( - nBanks: Int = 1 // Number of banks in L2 cache - ) - case class MasterPortParams( - base: BigInt, // Base memory address for this port - size: BigInt, // Size of this external memory - beatBytes: Int, // Interface width in bytes - idBits: Int, // # of bits in the port ID - maxXferBytes: Int = 256, // Maximum bytes in one transfer transaction - executable: Boolean = true // If the data from this port can be executed as instruciton - ) - /** Specifies the width of external slave ports */ - case class SlavePortParams( - beatBytes: Int, // Interface width in bytes - idBits: Int, // # of bits in the port ID - sourceBits: Int // # of bits in the source address - ) - case class MemoryPortParams( - master: MasterPortParams, // The memory port setting - nMemoryChannels: Int // Number of memory channel - ) From 661038f992b281b0f39ea58c45216128e476a18f Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Fri, 3 Jul 2020 16:21:30 -0700 Subject: [PATCH 37/63] Deduplicate across Chiypard configs into a ChipyardBaseConfig --- docs/Customization/Heterogeneous-SoCs.rst | 51 +- .../src/main/scala/ConfigFragments.scala | 13 + .../main/scala/config/AbstractConfig.scala | 26 + .../src/main/scala/config/ArianeConfigs.scala | 35 +- .../src/main/scala/config/BoomConfigs.scala | 141 +----- .../src/main/scala/config/HeteroConfigs.scala | 104 +--- .../src/main/scala/config/RocketConfigs.scala | 461 ++---------------- .../RocketConfigs.scala.patch | 16 +- 8 files changed, 129 insertions(+), 718 deletions(-) create mode 100644 generators/chipyard/src/main/scala/config/AbstractConfig.scala diff --git a/docs/Customization/Heterogeneous-SoCs.rst b/docs/Customization/Heterogeneous-SoCs.rst index c640e31c..155d623d 100644 --- a/docs/Customization/Heterogeneous-SoCs.rst +++ b/docs/Customization/Heterogeneous-SoCs.rst @@ -8,7 +8,7 @@ Creating a Rocket and BOOM System ------------------------------------------- Instantiating an SoC with Rocket and BOOM cores is all done with the configuration system and two specific config fragments. -Both BOOM and Rocket have config fragments labelled ``WithNBoomCores(X)`` and ``WithNBigCores(X)`` that automatically create ``X`` copies of the core/tile [1]_. +Both BOOM and Rocket have config fragments labelled ``WithN{Small|Medium|Large|etc.}BoomCores(X)`` and ``WithNBigCores(X)`` that automatically create ``X`` copies of the core/tile [1]_. When used together you can create a heterogeneous system. The following example shows a dual core BOOM with a single core Rocket. @@ -18,52 +18,6 @@ The following example shows a dual core BOOM with a single core Rocket. :start-after: DOC include start: DualBoomAndRocket :end-before: DOC include end: DualBoomAndRocket -In this example, the ``WithNBoomCores`` and ``WithNBigCores`` config fragments set up the default parameters for the multiple BOOM and Rocket cores, respectively. -However, for BOOM, an extra config fragment called ``WithLargeBooms`` is added to override the default parameters with a different set of more common default parameters. -This config fragment applies to all BOOM cores in the system and changes the parameters for each. - -Great! Now you have a heterogeneous setup with BOOMs and Rockets. -The final thing you need to make this system work is to renumber the ``hartId``'s of the cores so that each core has a unique ``hartId`` (a ``hartId`` is the hardware thread id of the core). -The ``WithRenumberHarts`` config fragment solves this by assigning a unique ``hartId`` to all cores in the system (it can label the Rocket cores first or the BOOM cores first). -The reason this is needed is because by default the ``WithN...Cores(X)`` config fragment assumes that there are only BOOM or only Rocket cores in the system. -Thus, without the ``WithRenumberHarts`` config fragment, each set of cores is labeled starting from zero causing multiple cores to be assigned the same ``hartId``. - -Another alternative option to create a multi heterogeneous core system is to override the parameters yourself so you can specify the core parameters per core. -The config fragment to add to your system would look something like the following. - -.. code-block:: scala - - // create 6 cores (4 boom and 2 rocket) - class WithHeterCoresSetup extends Config((site, here, up) => { - case BoomTilesKey => { - val boomTile0 = BoomTileParams(...) // params for boom core 0 - val boomTile1 = BoomTileParams(...) // params for boom core 1 - val boomTile2 = BoomTileParams(...) // params for boom core 2 - val boomTile3 = BoomTileParams(...) // params for boom core 3 - Seq(boomTile0, boomTile1, boomTile2, boomTile3) - } - - case RocketTilesKey => { - val rocketTile0 = RocketTileParams(...) // params for rocket core 0 - val rocketTile1 = RocketTileParams(...) // params for rocket core 1 - Seq(rocketTile0, rocketTile1) - } - }) - -Then you could use this new config fragment like the following. - -.. code-block:: scala - - class SixCoreConfig extends Config( - new WithTSI ++ - new WithBootROM ++ - new WithUART ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new WithHeterCoresSetup ++ - new freechips.rocketchip.system.BaseConfig) - -Note, in this setup you need to specify the ``hartId`` of each core in the "TileParams", where each ``hartId`` is unique. Adding Hwachas ------------------------------------------- @@ -92,8 +46,7 @@ An example is shown below with two BOOM cores, and one Rocket tile with a RoCC a :start-after: DOC include start: DualBoomAndRocketOneHwacha :end-before: DOC include end: DualBoomAndRocketOneHwacha -In this example, the ``WithRenumberHarts`` relabels the ``hartId``'s of all the BOOM/Rocket cores. -Then after that is applied to the parameters, the ``WithMultiRoCCHwacha`` config fragment assigns a Hwacha accelerator to a particular ``hartId`` (in this case, the ``hartId`` of ``2`` corresponds to the Rocket core). +The ``WithMultiRoCCHwacha`` config fragment assigns a Hwacha accelerator to a particular ``hartId`` (in this case, the ``hartId`` of ``2`` corresponds to the Rocket core). Finally, the ``WithMultiRoCC`` config fragment is called. This config fragment sets the ``BuildRoCC`` key to use the ``MultiRoCCKey`` instead of the default. This must be used after all the RoCC parameters are set because it needs to override the ``BuildRoCC`` parameter. diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index ad33fa47..024f5695 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -130,3 +130,16 @@ class WithNPerfCounters(n: Int = 29) extends Config((site, here, up) => { case other => other } }) + +class WithRocketICacheScratchpad extends Config((site, here, up) => { + case RocketTilesKey => up(RocketTilesKey, site) map { r => + r.copy(icache = r.icache.map(_.copy(itimAddr = Some(0x100000 + r.hartId * 0x10000)))) + } +}) + +class WithRocketDCacheScratchpad extends Config((site, here, up) => { + case RocketTilesKey => up(RocketTilesKey, site) map { r => + r.copy(dcache = r.dcache.map(_.copy(nSets = 32, nWays = 1, scratch = Some(0x200000 + r.hartId * 0x10000)))) + } +}) + diff --git a/generators/chipyard/src/main/scala/config/AbstractConfig.scala b/generators/chipyard/src/main/scala/config/AbstractConfig.scala new file mode 100644 index 00000000..22f64925 --- /dev/null +++ b/generators/chipyard/src/main/scala/config/AbstractConfig.scala @@ -0,0 +1,26 @@ +package chipyard.config + +import freechips.rocketchip.config.{Config} + +// -------------- +// Chipyard abstract ("base") configuration +// NOTE: This configuration is NOT INSTANTIABLE, as it defines a empty system with no tiles +// -------------- + +class AbstractConfig extends Config( + new chipyard.iobinders.WithUARTAdapter ++ // display UART with a SimUARTAdapter + new chipyard.iobinders.WithTieOffInterrupts ++ // tie off top-level interrupts + new chipyard.iobinders.WithBlackBoxSimMem ++ // drive the master AXI4 memory with a blackbox DRAMSim model + new chipyard.iobinders.WithTiedOffDebug ++ // tie off debug (since we are using SimSerial for testing) + new chipyard.iobinders.WithSimSerial ++ // drive TSI with SimSerial for testing + new testchipip.WithTSI ++ // use testchipip serial offchip link + new chipyard.config.WithBootROM ++ // use default bootrom + new chipyard.config.WithUART ++ // add a UART + new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs + new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip) + new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip) + new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache + new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts + new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ // hierarchical buses including mbus+l2 + new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system + diff --git a/generators/chipyard/src/main/scala/config/ArianeConfigs.scala b/generators/chipyard/src/main/scala/config/ArianeConfigs.scala index 6fb2ef00..7bc985aa 100644 --- a/generators/chipyard/src/main/scala/config/ArianeConfigs.scala +++ b/generators/chipyard/src/main/scala/config/ArianeConfigs.scala @@ -9,34 +9,11 @@ import freechips.rocketchip.config.{Config} // --------------------- class ArianeConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ // display UART with a SimUARTAdapter - new chipyard.iobinders.WithTieOffInterrupts ++ // tie off top-level interrupts - new chipyard.iobinders.WithSimAXIMem ++ // drive the master AXI4 memory with a SimAXIMem - new chipyard.iobinders.WithTiedOffDebug ++ // tie off debug (since we are using SimSerial for testing) - new chipyard.iobinders.WithSimSerial ++ // drive TSI with SimSerial for testing - new testchipip.WithTSI ++ // use testchipip serial offchip link - new chipyard.config.WithBootROM ++ // use default bootrom - new chipyard.config.WithUART ++ // add a UART - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip) - new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip) - new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts - new ariane.WithNArianeCores(1) ++ // single Ariane core - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ // hierarchical buses including mbus+l2 - new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system + new ariane.WithNArianeCores(1) ++ // single Ariane core + new chipyard.config.AbstractConfig) class dmiArianeConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithSimAXIMem ++ - new chipyard.iobinders.WithTiedOffSerial ++ - new chipyard.iobinders.WithSimDebug ++ // add SimDebug and use it to drive simulation - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new ariane.WithNArianeCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.iobinders.WithTiedOffSerial ++ // Tie off the serial port, override default instantiation of SimSerial + new chipyard.iobinders.WithSimDebug ++ // add SimDebug and use it to drive simulation, override default tie-off debug + new ariane.WithNArianeCores(1) ++ // single Ariane core + new chipyard.config.AbstractConfig) diff --git a/generators/chipyard/src/main/scala/config/BoomConfigs.scala b/generators/chipyard/src/main/scala/config/BoomConfigs.scala index 7b66e3b3..1f41c252 100644 --- a/generators/chipyard/src/main/scala/config/BoomConfigs.scala +++ b/generators/chipyard/src/main/scala/config/BoomConfigs.scala @@ -7,151 +7,40 @@ import freechips.rocketchip.config.{Config} // --------------------- class SmallBoomConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ // display UART with a SimUARTAdapter - new chipyard.iobinders.WithTieOffInterrupts ++ // tie off top-level interrupts - new chipyard.iobinders.WithBlackBoxSimMem ++ // drive the master AXI4 memory with a SimAXIMem - new chipyard.iobinders.WithTiedOffDebug ++ // tie off debug (since we are using SimSerial for testing) - new chipyard.iobinders.WithSimSerial ++ // drive TSI with SimSerial for testing - new testchipip.WithTSI ++ // use testchipip serial offchip link - new chipyard.config.WithBootROM ++ // use default bootrom - new chipyard.config.WithUART ++ // add a UART - new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip) - new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip) - new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts new boom.common.WithNSmallBooms(1) ++ // small boom config - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ // hierarchical buses including mbus+l2 - new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system + new chipyard.config.AbstractConfig) class MediumBoomConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new boom.common.WithNMediumBooms(1) ++ // medium boom config - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new boom.common.WithNMediumBooms(1) ++ // medium boom config + new chipyard.config.AbstractConfig) class LargeBoomConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new boom.common.WithNLargeBooms(1) ++ // large boom config - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) class MegaBoomConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new boom.common.WithNMegaBooms(1) ++ // mega boom config - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new boom.common.WithBoomBranchPrintf ++ + new boom.common.WithNMegaBooms(1) ++ // mega boom config + new chipyard.config.AbstractConfig) class DualSmallBoomConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new boom.common.WithNSmallBooms(2) ++ // 2 boom cores - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new boom.common.WithNSmallBooms(2) ++ // 2 boom cores + new chipyard.config.AbstractConfig) class HwachaLargeBoomConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ + new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator new boom.common.WithNLargeBooms(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) class LoopbackNICLargeBoomConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new chipyard.iobinders.WithLoopbackNIC ++ // drive NIC IOs with loopback - new testchipip.WithTSI ++ - new icenet.WithIceNIC ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ + new chipyard.iobinders.WithLoopbackNIC ++ // drive NIC IOs with loopback + new icenet.WithIceNIC ++ // build a NIC new boom.common.WithNLargeBooms(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) class DromajoBoomConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ new chipyard.iobinders.WithSimDromajoBridge ++ // attach Dromajo - new testchipip.WithTSI ++ new chipyard.config.WithTraceIO ++ // enable the traceio - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new boom.common.WithNSmallBooms(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) diff --git a/generators/chipyard/src/main/scala/config/HeteroConfigs.scala b/generators/chipyard/src/main/scala/config/HeteroConfigs.scala index a7d1c133..9eb0b2f5 100644 --- a/generators/chipyard/src/main/scala/config/HeteroConfigs.scala +++ b/generators/chipyard/src/main/scala/config/HeteroConfigs.scala @@ -7,108 +7,38 @@ import freechips.rocketchip.config.{Config} // --------------------- class LargeBoomAndRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ // display UART with a SimUARTAdapter - new chipyard.iobinders.WithTieOffInterrupts ++ // tie off top-level interrupts - new chipyard.iobinders.WithBlackBoxSimMem ++ // drive the master AXI4 memory with a SimAXIMem - new chipyard.iobinders.WithTiedOffDebug ++ // tie off debug (since we are using SimSerial for testing) - new chipyard.iobinders.WithSimSerial ++ // drive TSI with SimSerial for testing - new testchipip.WithTSI ++ // use testchipip serial offchip link - new chipyard.config.WithBootROM ++ // use default bootrom - new chipyard.config.WithUART ++ // add a UART - new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs new boom.common.WithNLargeBooms(1) ++ // single-core boom - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip) - new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip) - new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ // hierarchical buses including mbus+l2 - new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system + new chipyard.config.AbstractConfig) // DOC include start: BoomAndRocketWithHwacha class HwachaLargeBoomAndHwachaRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new hwacha.DefaultHwachaConfig ++ // add hwacha to all harts - new boom.common.WithNLargeBooms(1) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new hwacha.DefaultHwachaConfig ++ // add hwacha to all harts + new boom.common.WithNLargeBooms(1) ++ // add 1 boom core + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // add 1 rocket core + new chipyard.config.AbstractConfig) // DOC include end: BoomAndRocketWithHwacha -// DOC include start: DualBoomAndRocketOneHwacha +// DOC include start: DualBoomAndRocketOneHwacha class LargeBoomAndHwachaRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ new chipyard.config.WithMultiRoCC ++ // support heterogeneous rocc new chipyard.config.WithMultiRoCCHwacha(1) ++ // put hwacha on hart-1 (rocket) - new chipyard.config.WithL2TLBs(1024) ++ - new boom.common.WithNLargeBooms(1) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new hwacha.DefaultHwachaConfig ++ // set default hwacha config keys + new boom.common.WithNLargeBooms(1) ++ // add 1 boom core + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // add 1 rocket core + new chipyard.config.AbstractConfig) // DOC include end: DualBoomAndRocketOneHwacha // DOC include start: DualBoomAndRocket class DualLargeBoomAndDualRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new boom.common.WithNLargeBooms(2) ++ // 2 boom cores - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new freechips.rocketchip.subsystem.WithNBigCores(2) ++ // 2 rocket cores - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new boom.common.WithNLargeBooms(2) ++ // add 2 boom cores + new freechips.rocketchip.subsystem.WithNBigCores(2) ++ // add 2 rocket cores + new chipyard.config.AbstractConfig) // DOC include end: DualBoomAndRocket class LargeBoomAndRocketWithControlCoreConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNSmallCores(1) ++ // Add a small control core - new boom.common.WithNLargeBooms(1) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) - + new freechips.rocketchip.subsystem.WithNSmallCores(1) ++ // Add a small "control" core + new boom.common.WithNLargeBooms(1) ++ // Add 1 boom core + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // add 1 rocket core + new chipyard.config.AbstractConfig) diff --git a/generators/chipyard/src/main/scala/config/RocketConfigs.scala b/generators/chipyard/src/main/scala/config/RocketConfigs.scala index 3dc7d22d..8e6e4867 100644 --- a/generators/chipyard/src/main/scala/config/RocketConfigs.scala +++ b/generators/chipyard/src/main/scala/config/RocketConfigs.scala @@ -7,556 +7,179 @@ import freechips.rocketchip.config.{Config} // -------------- class RocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ // display UART with a SimUARTAdapter - new chipyard.iobinders.WithTieOffInterrupts ++ // tie off top-level interrupts - new chipyard.iobinders.WithBlackBoxSimMem ++ // drive the master AXI4 memory with a blackbox DRAMSim model - new chipyard.iobinders.WithTiedOffDebug ++ // tie off debug (since we are using SimSerial for testing) - new chipyard.iobinders.WithSimSerial ++ // drive TSI with SimSerial for testing - new testchipip.WithTSI ++ // use testchipip serial offchip link - new chipyard.config.WithBootROM ++ // use default bootrom - new chipyard.config.WithUART ++ // add a UART - new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip) - new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip) - new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ // hierarchical buses including mbus+l2 - new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system + new chipyard.config.AbstractConfig) class HwachaRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include start: GemminiRocketConfig class GemminiRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ new gemmini.DefaultGemminiConfig ++ // use Gemmini systolic array GEMM accelerator - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include end: GemminiRocketConfig -class RoccRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithRoccExample ++ // use example RoCC-based accelerator - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) - // DOC include start: JtagRocket class jtagRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithSimDebug ++ // add SimJtag and SimSerial, use both to drive sim - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ + new chipyard.iobinders.WithSimDebug ++ // add SimDebug, in addition to default SimSerial new freechips.rocketchip.subsystem.WithJtagDTM ++ // sets DTM communication interface to JTAG - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include end: JtagRocket // DOC include start: DmiRocket class dmiRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffSerial ++ - new chipyard.iobinders.WithSimDebug ++ // add SimDebug and use it to drive simulation - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ + new chipyard.iobinders.WithTiedOffSerial ++ // tie-off serial, override default add SimSerial + new chipyard.iobinders.WithSimDebug ++ // add SimDebug, override default tie-off debug new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include end: DmiRocket // DOC include start: GCDTLRocketConfig class GCDTLRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithL2TLBs(1024) ++ new chipyard.example.WithGCD(useAXI4=false, useBlackBox=false) ++ // Use GCD Chisel, connect Tilelink - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include end: GCDTLRocketConfig // DOC include start: GCDAXI4BlackBoxRocketConfig class GCDAXI4BlackBoxRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithL2TLBs(1024) ++ new chipyard.example.WithGCD(useAXI4=true, useBlackBox=true) ++ // Use GCD blackboxed verilog, connect by AXI4->Tilelink - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include end: GCDAXI4BlackBoxRocketConfig class LargeSPIFlashROMRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ new chipyard.iobinders.WithSimSPIFlashModel(true) ++ // add the SPI flash model in the harness (read-only) - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ new chipyard.config.WithSPIFlash ++ // add the SPI flash controller - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) class SmallSPIFlashRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ new chipyard.iobinders.WithSimSPIFlashModel(false) ++ // add the SPI flash model in the harness (writeable) - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ new chipyard.config.WithSPIFlash(0x100000) ++ // add the SPI flash controller (1 MiB) - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) class SimAXIRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithSimAXIMem ++ // drive the master AXI4 memory with a SimAXIMem, a 1-cycle magic memory - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ + new chipyard.iobinders.WithSimAXIMem ++ // drive the master AXI4 memory with a SimAXIMem, a 1-cycle magic memory, instead of default SimDRAM new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) class SimBlockDeviceRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ new chipyard.iobinders.WithSimBlockDevice ++ // drive block-device IOs with SimBlockDevice - new testchipip.WithTSI ++ new testchipip.WithBlockDevice ++ // add block-device module to peripherybus - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) class BlockDeviceModelRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ new chipyard.iobinders.WithBlockDeviceModel ++ // drive block-device IOs with a BlockDeviceModel - new testchipip.WithTSI ++ new testchipip.WithBlockDevice ++ // add block-device module to periphery bus - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include start: GPIORocketConfig class GPIORocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ new chipyard.iobinders.WithGPIOTiedOff ++ // tie off GPIO inputs into the top - new testchipip.WithTSI ++ new chipyard.config.WithGPIO ++ // add GPIOs to the peripherybus - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include end: GPIORocketConfig class QuadRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(4) ++ // quad-core (4 RocketTiles) - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) class RV32RocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithRV32 ++ // set RocketTiles to be 32-bit - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) class GB1MemoryRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ new freechips.rocketchip.subsystem.WithExtMemSize((1<<30) * 1L) ++ // use 1GB simulated external memory - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include start: Sha3Rocket class Sha3RocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ new sha3.WithSha3Accel ++ // add SHA3 rocc accelerator - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include end: Sha3Rocket // DOC include start: InitZeroRocketConfig class InitZeroRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ new chipyard.example.WithInitZero(0x88000000L, 0x1000L) ++ // add InitZero - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include end: InitZeroRocketConfig class LoopbackNICRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ new chipyard.iobinders.WithLoopbackNIC ++ // drive NIC IOs with loopback - new testchipip.WithTSI ++ new icenet.WithIceNIC ++ // add an IceNIC - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include start: l1scratchpadrocket -class L1ScratchpadSmallRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ +class ScratchpadOnlyRocketConfig extends Config( new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // remove offchip mem port new freechips.rocketchip.subsystem.WithNBanks(0) ++ new freechips.rocketchip.subsystem.WithNoMemPort ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use rocket l1 scratchpad - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ - new freechips.rocketchip.subsystem.WithNSmallCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use rocket l1 DCache scratchpad as base phys mem + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new chipyard.config.AbstractConfig) // DOC include end: l1scratchpadrocket +class L1ScratchpadRocketConfig extends Config( + new chipyard.config.WithRocketICacheScratchpad ++ // use rocket ICache scratchpad + new chipyard.config.WithRocketDCacheScratchpad ++ // use rocket DCache scratchpad + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new chipyard.config.AbstractConfig) + // DOC include start: mbusscratchpadrocket class MbusScratchpadRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ new testchipip.WithBackingScratchpad ++ // add mbus backing scratchpad - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove offchip mem port - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include end: mbusscratchpadrocket // DOC include start: RingSystemBusRocket class RingSystemBusRocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ new testchipip.WithRingSystemBus ++ // Ring-topology system bus - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include end: RingSystemBusRocket class StreamingPassthroughRocketConfig extends Config( new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled streaming passthrough - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include start: StreamingFIRRocketConfig class StreamingFIRRocketConfig extends Config ( new chipyard.example.WithStreamingFIR ++ // use top with tilelink-controlled streaming FIR - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) // DOC include end: StreamingFIRRocketConfig class SmallNVDLARocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ new nvidia.blocks.dla.WithNVDLA("small") ++ // add a small NVDLA - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) class LargeNVDLARocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ new nvidia.blocks.dla.WithNVDLA("large", true) ++ // add a large NVDLA with synth. rams - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) class MMIORocketConfig extends Config( - new chipyard.iobinders.WithUARTAdapter ++ - new chipyard.iobinders.WithTieOffInterrupts ++ - new chipyard.iobinders.WithBlackBoxSimMem ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithSimSerial ++ new chipyard.iobinders.WithTieOffL2FBusAXI ++ // Tie-off the incoming MMIO port new chipyard.iobinders.WithSimAXIMMIO ++ // Attach a simulated memory to the outwards MMIO port - new testchipip.WithTSI ++ - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ - new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ + new freechips.rocketchip.subsystem.WithDefaultMMIOPort ++ // add default external master port + new freechips.rocketchip.subsystem.WithDefaultSlavePort ++ // add default external slave port new freechips.rocketchip.subsystem.WithNBigCores(1) ++ - new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ - new freechips.rocketchip.system.BaseConfig) + new chipyard.config.AbstractConfig) diff --git a/scripts/tutorial-patches/RocketConfigs.scala.patch b/scripts/tutorial-patches/RocketConfigs.scala.patch index cc9910c7..351f8ca2 100644 --- a/scripts/tutorial-patches/RocketConfigs.scala.patch +++ b/scripts/tutorial-patches/RocketConfigs.scala.patch @@ -1,13 +1,13 @@ diff --git a/generators/chipyard/src/main/scala/config/RocketConfigs.scala b/generators/chipyard/src/main/scala/config/RocketConfigs.scala -index f29c580..0bd36ca 100644 +index 8e6e486..fc3a811 100644 --- a/generators/chipyard/src/main/scala/config/RocketConfigs.scala +++ b/generators/chipyard/src/main/scala/config/RocketConfigs.scala -@@ -333,7 +333,7 @@ class Sha3RocketConfig extends Config( - new chipyard.config.WithBootROM ++ - new chipyard.config.WithUART ++ - new chipyard.config.WithL2TLBs(1024) ++ +@@ -105,7 +105,7 @@ class GB1MemoryRocketConfig extends Config( + + // DOC include start: Sha3Rocket + class Sha3RocketConfig extends Config( - new sha3.WithSha3Accel ++ // add SHA3 rocc accelerator +// new sha3.WithSha3Accel ++ // add SHA3 rocc accelerator - new freechips.rocketchip.subsystem.WithNoMMIOPort ++ - new freechips.rocketchip.subsystem.WithNoSlavePort ++ - new freechips.rocketchip.subsystem.WithInclusiveCache ++ + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new chipyard.config.AbstractConfig) + // DOC include end: Sha3Rocket From 19152d3b73f1c2255ce378501f6c01f9363b75e9 Mon Sep 17 00:00:00 2001 From: alonamid Date: Mon, 6 Jul 2020 20:29:34 -0700 Subject: [PATCH 38/63] Update README.md (#619) --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c2feb678..285d337b 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,9 @@ If used for research, please cite Chipyard by the following publication: journal={IEEE Micro}, title={Chipyard: Integrated Design, Simulation, and Implementation Framework for Custom SoCs}, year={2020}, - pages={}, + volume={40}, + number={4}, + pages={10-21}, doi={10.1109/MM.2020.2996616}, ISSN={1937-4143}, } From b55e579c91386f86bcd945412e6d4ac6ba301edc Mon Sep 17 00:00:00 2001 From: Albert Ou Date: Tue, 7 Jul 2020 23:00:14 -0700 Subject: [PATCH 39/63] Override default baud rate for FireChip This avoids target software needing to explicitly set the divisor to match the UART bridge. --- generators/chipyard/src/main/scala/ConfigFragments.scala | 6 +++--- generators/firechip/src/main/scala/TargetConfigs.scala | 7 ++++--- generators/sifive-blocks | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index da048ff1..dde0e6d8 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -51,9 +51,9 @@ class WithGPIO extends Config((site, here, up) => { }) // DOC include end: gpio config fragment -class WithUART extends Config((site, here, up) => { +class WithUART(baudrate: BigInt = 115200) extends Config((site, here, up) => { case PeripheryUARTKey => Seq( - UARTParams(address = 0x54000000L, nTxEntries = 256, nRxEntries = 256)) + UARTParams(address = 0x54000000L, nTxEntries = 256, nRxEntries = 256, initBaudRate = baudrate)) }) class WithSPIFlash(size: BigInt = 0x10000000) extends Config((site, here, up) => { @@ -143,4 +143,4 @@ class WithHwachaTest extends Config((site, here, up) => { 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/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala index 2828580a..8aef9f8c 100644 --- a/generators/firechip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -69,7 +69,8 @@ class WithNVDLASmall extends nvidia.blocks.dla.WithNVDLA("small") class WithFireSimConfigTweaks extends Config( // Required*: When using FireSim-as-top to provide a correct path to the target bootrom source new WithBootROM ++ - // Optional*: Removing this will require target-software changes to properly capture UART output + // Optional*: Removing this will require adjusting the UART baud rate and + // potential target-software changes to properly capture UART output new WithPeripheryBusFrequency(BigInt(3200000000L)) ++ // Required: Existing FAME-1 transform cannot handle black-box clock gates new WithoutClockGating ++ @@ -85,8 +86,8 @@ class WithFireSimConfigTweaks extends Config( new testchipip.WithTSI ++ // Optional: Removing this will require using an initramfs under linux new testchipip.WithBlockDevice ++ - // Required*: - new chipyard.config.WithUART + // Required*: Scale default baud rate with periphery bus frequency + new chipyard.config.WithUART(BigInt(3686400L)) ) /******************************************************************************* diff --git a/generators/sifive-blocks b/generators/sifive-blocks index c1dee823..c240e629 160000 --- a/generators/sifive-blocks +++ b/generators/sifive-blocks @@ -1 +1 @@ -Subproject commit c1dee8234c23c8fc454108e59ecba20987f95cde +Subproject commit c240e629e2fc111cbb12e4fe707be898b5204984 From 763ba42b4c35915d1824b662fe73976697b0662b Mon Sep 17 00:00:00 2001 From: Albert Ou Date: Wed, 8 Jul 2020 12:36:09 -0700 Subject: [PATCH 40/63] 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 From 9ad9d00a232ec38dc19269b61df2a5e0151dad8a Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Wed, 8 Jul 2020 16:02:31 -0700 Subject: [PATCH 41/63] Second revision --- docs/Customization/Custom-Core.rst | 66 ++++++++++++------- .../src/main/scala/example/TutorialTile.scala | 22 ++++++- 2 files changed, 62 insertions(+), 26 deletions(-) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index 94d47505..9a2249ba 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -121,7 +121,8 @@ You will also need a ``CanAttachTile`` class to add the tile config into the con .. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala :language: scala - :lines: 61-67 + :start-after: DOC include start: CanAttachTile + :end-before: DOC include end: CanAttachTile .. note:: @@ -137,14 +138,17 @@ Create Tile Class In Chipyard, all Tiles are diplomatically instantiated. In the first phase, diplomatic nodes which specify Tile-to-System interconnects are evaluated, while in the second "Module Implementation" phase, hardware is elaborated. -See :ref:`tilelink_and_diplomacy` for more details. In this step, you will need to implement a tile class for your core. +See :ref:`tilelink_and_diplomacy` for more details. In this step, you will need to implement a tile class for your core, +which specifies the constraints on the core's parameters and the connections with other diplomatic nodes. This class +usually contains Diplomacy/TileLink code only, and Chisel RTL code should not go here. All tile classes implement ``BaseTile`` and will normally implement ``SinksExternalInterrupts`` and ``SourcesExternalNotifications``, which allow the tile to accept external interrupt. A typical tile has the following form: .. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala :language: scala - :lines: 87-125, 143 + :start-after: DOC include start: Tile class + :end-before: DOC include end: Tile class Connect TileLink Buses ---------------------- @@ -156,7 +160,8 @@ Rocket chip: .. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala :language: scala - :lines: 133-142 + :start-after: DOC include start: AXI4 convert + :end-before: DOC include end: AXI4 convert Remember, you may not need all of these intermediate widgets. See :ref:`diplomatic_widgets` for the meaning of each intermediate widget. If you are using TileLink, then you only need the tap node and the TileLink node used by your components. Chipyard also @@ -170,7 +175,8 @@ as the template, but it is not recommended unless you are familiar with TileLink .. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala :language: scala - :lines: 126-132 + :start-after: DOC include start: AXI4 node + :end-before: DOC include end: AXI4 node where ``portName`` and ``idBits`` (number of bits to represent a port ID) are the parameter provides by the tile. Make sure to read :ref:`node_types` to check out what type of nodes Chipyard supports and their parameters! @@ -185,12 +191,36 @@ can override the following two functions to control how to buffer the bus reques You can find more information on ``TLBuffer`` in :ref:`diplomatic_widgets`. +Create Implementation Class +--------------------------- + +The implementation class contains the parameterized, actual hardware that depends on the values resolved by the Diplomacy +framework according to the info provided in the Tile class. This class will normally contains Chisel RTL codes, and if your +core is in Verilog, you will need to put the black box class you created in the first step here and connect it with the buses +and other components. No Diplomacy/TileLink code should be in this class; you should only connect the IO signals in TileLink +interfaces or other diplomatically defined components, which are located in the tile class. + +The implementation class for your core is of the following form: + +.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala + :language: scala + :start-after: DOC include start: Implementation class + :end-before: DOC include end: Implementation class + +If you create an AXI4 node (or equivalents), you will need to connect them to your core. You can connect a port like this: + +.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala + :language: scala + :start-after: DOC include start: AXI4 connect + :end-before: DOC include end: AXI4 connect + Connect Interrupt ----------------- Chipyard allows a tile to either receive interrupts from other devices or initiate interrupts to notify other cores/devices. In the tile that inherited ``SinksExternalInterrupts``, one can create a ``TileInterrupts`` object (a Chisel bundle) and -call ``decodeCoreInterrupts`` with the object as the argument. You can then read the interrupt bits from the object. +call ``decodeCoreInterrupts`` with the object as the argument. Note that you should call this function in the implementation +class since it returns a Chisel bundle used by RTL code. You can then read the interrupt bits from the object. The definition of ``TileInterrupts`` is .. code-block:: scala @@ -204,7 +234,6 @@ The definition of ``TileInterrupts`` is val lip = Vec(coreParams.nLocalInterrupts, Bool()) // Local interrupts } -This function should be in the implementation class since it involves hardware generation. Also, the tile can also notify other cores or devices for some events by calling following functions in ``SourcesExternalNotifications`` from the implementation class: @@ -215,21 +244,6 @@ from the implementation class: reportCease(could_cease: Option[Bool], quiescenceCycles: Int = 8) // Triggered when the core stop retiring instructions (like clock gating) reportWFI(could_wfi: Option[Bool]) // Triggered when a WFI instruction is executed -Create Implementation Class ---------------------------- - -The implementation class for your core is of the following form: - -.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala - :language: scala - :lines: 145-149, 160 - -If you create an AXI4 node (or equivalents), you will need to connect them to your core. You can connect a port like this: - -.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala - :language: scala - :lines: 151-159 - Create Config Fragments to Integrate the Core --------------------------------------------- @@ -238,7 +252,8 @@ the current config. An example of such config will be like this: .. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala :language: scala - :lines: 162-179 + :start-after: DOC include start: Config fragment + :end-before: DOC include end: Config fragment Chipyard looks up the tile parameters in the field ``TilesLocated(InSubsystem)``, whose type is a list of ``InstantiableTileParams``. This config fragment simply appends new tile parameters to the end of this list. @@ -247,5 +262,6 @@ Now you have finished all the steps to prepare your cores for Chipyard! To gener in :ref:`custom_chisel` to add your project to the build system, then create a config by following the steps in :ref:`hetero_socs_`. You can now run any desired workflow for the new config just as you do for the built-in cores. -If you would like to see how an actual core are integrated into Chipyard, ``generators/ariane/src/main/scala/ArianeTile.scala`` -provides a concrete example of integrating a third party Verilog core Ariane. +If you would like to see an example of a complete third-party Verilog core integrated into Chipyard, ``generators/ariane/src/main/scala/ArianeTile.scala`` +provides a concrete example of the Ariane core. Note that this particular example includes additional nuances with respect to the interaction of the AXI +interface with the memory coherency system. \ No newline at end of file diff --git a/generators/chipyard/src/main/scala/example/TutorialTile.scala b/generators/chipyard/src/main/scala/example/TutorialTile.scala index 12173184..41f79892 100644 --- a/generators/chipyard/src/main/scala/example/TutorialTile.scala +++ b/generators/chipyard/src/main/scala/example/TutorialTile.scala @@ -58,6 +58,7 @@ case class MyCoreParams( val retireWidth: Int = 2 } +// DOC include start: CanAttachTile case class MyTileAttachParams( tileParams: MyTileParams, crossingParams: RocketCrossingParams @@ -65,6 +66,7 @@ case class MyTileAttachParams( type TileType = MyTile val lookup = PriorityMuxHartIdFromSeq(Seq(tileParams)) } +// DOC include end: CanAttachTile case class MyTileParams( name: Option[String] = Some("my_tile"), @@ -84,6 +86,7 @@ case class MyTileParams( } } +// DOC include start: Tile class class MyTile( val myParams: MyTileParams, crossing: ClockCrossingType, @@ -123,6 +126,10 @@ class MyTile( } // (Connection to bus, interrupt, etc.) +// } + // DOC include end: Tile class + + // DOC include start: AXI4 node // # of bits used in TileLink ID for master node. 4 bits can support 16 master nodes, but you can have a longer ID if you need more. val idBits = 4 val memAXI4Node = AXI4MasterNode( @@ -131,6 +138,9 @@ class MyTile( name = "myPortName", id = IdRange(0, 1 << idBits)))))) val memoryTap = TLIdentityNode() // Every bus connection should have their own tap node + // DOC include end: AXI4 node + + // DOC include start: AXI4 convert (tlMasterXbar.node // tlMasterXbar is the bus crossbar to be used when this core / tile is acting as a master; otherwise, use tlSlaveXBar := memoryTap := TLBuffer() @@ -140,14 +150,20 @@ class MyTile( := AXI4UserYanker(Some(2)) // remove user field on AXI interface. need but in reality user intf. not needed := AXI4Fragmenter() // deal with multi-beat xacts := memAXI4Node) // The custom node, see below + // DOC include end: AXI4 convert + } +// DOC include start: Implementation class class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){ // annotate the parameters Annotated.params(this, outer.myParams) - // TODO: Create the top module of the core and connect it with the ports in "outer" + // TODO: Create the top module of the core and connect it with the ports in "outer" } +//} + // DOC include end: Implementation class + // DOC include start: AXI4 connect outer.memAXI4Node.out foreach { case (out, edgeOut) => // Connect your module IO port to "out" // The type of "out" here is AXI4Bundle, which is defined in generators/rocket-chip/src/main/scala/amba/axi4/Bundles.scala @@ -157,8 +173,11 @@ class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){ // (choose one depends on the type of AHB node you create) // If you are using AXIS, check AXISBundle and AXISBundleBits in generators/rocket-chip/src/main/scala/amba/axis/Bundles.scala } + // DOC include end: AXI4 connect + } +// DOC include start: Config fragment class WithNMyCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends Config((site, here, up) => { case TilesLocated(InSubsystem) => { // Calculate the next available hart ID (since hart ID cannot be duplicated) @@ -177,3 +196,4 @@ class WithNMyCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends Con // The # of instruction bits. Use maximum # of bits if your core supports both 32 and 64 bits. case XLen => 64 }) +// DOC include end: Config fragment From 11c87777fe7ce8dba0854d2bcc65321f8e0d27a7 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 9 Jul 2020 11:29:58 -0700 Subject: [PATCH 42/63] Remove BOOM debug print --- generators/chipyard/src/main/scala/config/BoomConfigs.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/generators/chipyard/src/main/scala/config/BoomConfigs.scala b/generators/chipyard/src/main/scala/config/BoomConfigs.scala index 1f41c252..8b7cd31e 100644 --- a/generators/chipyard/src/main/scala/config/BoomConfigs.scala +++ b/generators/chipyard/src/main/scala/config/BoomConfigs.scala @@ -19,7 +19,6 @@ class LargeBoomConfig extends Config( new chipyard.config.AbstractConfig) class MegaBoomConfig extends Config( - new boom.common.WithBoomBranchPrintf ++ new boom.common.WithNMegaBooms(1) ++ // mega boom config new chipyard.config.AbstractConfig) @@ -43,4 +42,3 @@ class DromajoBoomConfig extends Config( new chipyard.config.WithTraceIO ++ // enable the traceio new boom.common.WithNSmallBooms(1) ++ new chipyard.config.AbstractConfig) - From 8124ce3df1483b5a1321f60005bf86c0c296cec4 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 9 Jul 2020 12:38:21 -0700 Subject: [PATCH 43/63] Add FIRRTL_LOGLEVEL variable --- variables.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/variables.mk b/variables.mk index 48da498e..e6de6ca0 100644 --- a/variables.mk +++ b/variables.mk @@ -152,6 +152,8 @@ define run_scala_main endef endif +FIRRTL_LOGLEVEL ?= error + ######################################################################################### # output directory for tests ######################################################################################### From 2196a621c67d1cc598116ddfd498719c57d4f17a Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 9 Jul 2020 12:39:17 -0700 Subject: [PATCH 44/63] Pass FIRRTL_LOGLEVEL to GenerateTopAndHarness --- common.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.mk b/common.mk index 62e4399e..71f4440c 100644 --- a/common.mk +++ b/common.mk @@ -104,7 +104,7 @@ $(TOP_TARGETS) $(HARNESS_TARGETS): firrtl_temp @echo "" > /dev/null firrtl_temp: $(FIRRTL_FILE) $(ANNO_FILE) $(VLOG_SOURCES) - $(call run_scala_main,tapeout,barstools.tapeout.transforms.GenerateTopAndHarness,-o $(TOP_FILE) -tho $(HARNESS_FILE) -i $(FIRRTL_FILE) --syn-top $(TOP) --harness-top $(VLOG_MODEL) -faf $(ANNO_FILE) -tsaof $(TOP_ANNO) -tdf $(sim_top_blackboxes) -tsf $(TOP_FIR) -thaof $(HARNESS_ANNO) -hdf $(sim_harness_blackboxes) -thf $(HARNESS_FIR) $(REPL_SEQ_MEM) $(HARNESS_CONF_FLAGS) -td $(build_dir)) && touch $(sim_top_blackboxes) $(sim_harness_blackboxes) + $(call run_scala_main,tapeout,barstools.tapeout.transforms.GenerateTopAndHarness,-o $(TOP_FILE) -tho $(HARNESS_FILE) -i $(FIRRTL_FILE) --syn-top $(TOP) --harness-top $(VLOG_MODEL) -faf $(ANNO_FILE) -tsaof $(TOP_ANNO) -tdf $(sim_top_blackboxes) -tsf $(TOP_FIR) -thaof $(HARNESS_ANNO) -hdf $(sim_harness_blackboxes) -thf $(HARNESS_FIR) $(REPL_SEQ_MEM) $(HARNESS_CONF_FLAGS) -td $(build_dir) -ll $(FIRRTL_LOGLEVEL)) && touch $(sim_top_blackboxes) $(sim_harness_blackboxes) # DOC include end: FirrtlCompiler # This file is for simulation only. VLSI flows should replace this file with one containing hard SRAMs From ced7ea634cc2eae5a8045a20ce81c177f347c0b3 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sun, 12 Jul 2020 01:08:13 -0700 Subject: [PATCH 45/63] 3rd Revision --- docs/Customization/Custom-Core.rst | 41 +++++++++++-------- .../src/main/scala/example/TutorialTile.scala | 4 +- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index 9a2249ba..d6a19f04 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -3,8 +3,8 @@ Adding a custom core ==================== -You may want to integrate a custom RISC-V core into the Chipyard framework. This documentation page provides a step-to-step -instruction on how to achieve this. +You may want to integrate a custom RISC-V core into the Chipyard framework. This documentation page provides step-by-step +instructions on how to achieve this. .. note:: @@ -24,18 +24,18 @@ Chipyard will generate a core for every ``InstantiableTileParams`` object it dis This object is derived from``TileParams``, a trait containing the information needed to create a tile. All cores must have their own implementation of ``InstantiableTileParams``, as well as ``CoreParams`` which is passed as a field in ``TileParams``. -``TileParams`` holds the parameters for the tile, which are the same for every generated core, while ``CoreParams`` -contains the parameters for individual cores. They must be implemented as case classes with fields that can be overridden by +``TileParams`` holds the parameters for the tile, which include parameters for all components in the tile (e.g. +core, cache, MMU, etc.), while ``CoreParams`` contains parameters specific to the core on the tile. +They must be implemented as case classes with fields that can be overridden by other config fragments as the constructor parameters. See the appendix at the bottom of the page for a list of variable to be implemented. You can also add custom fields to them, but standard fields should always be preferred. -``InstantiableTileParams[TileType]`` holds the constructor of ``TileType`` on top of the fields of ``TileParams``. +``InstantiableTileParams[TileType]`` holds the constructor of ``TileType`` on top of the fields of ``TileParams``, +where ``TileType`` is the tile class (see the next section). All custom cores will also need to implement ``instantiate()`` in their tile parameter class to return a new instance of the tile class ``TileType``. -``TileParams``, ``InstantiableTileParams[TileType]`` and ``CoreParams`` contains the following fields (you may ignore -any fields marked "Rocket specific" and use their default values, although it is recommended to use them if you -need a custom field with similar purposes): +``TileParams``, ``InstantiableTileParams[TileType]`` and ``CoreParams`` contains the following fields: .. code-block:: scala @@ -113,9 +113,11 @@ need a custom field with similar purposes): dfmaLatency: Int = 4 // Rocket specific: Fused multiply-add pipeline latency (double precision) ) -Most of the fields here are originally designed for the Rocket core and thus contain some implementation-specific details, but -many of them are general enough to be useful for other cores. It is strongly recommended to use these fields instead -of creating your own custom fields when applicable. +Most of the fields here (marked "Rocket spcific") are originally designed for the Rocket core and thus contain some +implementation-specific details, but many of them are general enough to be useful for other cores. You may ignore +any fields marked "Rocket specific" and use their default values; however, if you need to store additional information +with meaning or usage similar to these "Rocket specific" fields, it is recommended to use these fields instead of +creating your own custom fields. You will also need a ``CanAttachTile`` class to add the tile config into the config system, with the following format: @@ -124,6 +126,9 @@ You will also need a ``CanAttachTile`` class to add the tile config into the con :start-after: DOC include start: CanAttachTile :end-before: DOC include end: CanAttachTile +During elaboration, Chipyard will look for subclasses of ``CanAttachTile`` in the config system and instantiate a tile +from the parameters in this class for every such class it found. + .. note:: Implementations may choose to ignore some fields here or use them in a non-standard way, but using an inaccurate @@ -153,8 +158,8 @@ which allow the tile to accept external interrupt. A typical tile has the follow Connect TileLink Buses ---------------------- -Chipyard use TileLink as its onboard bus protocol. If your core doesn't use TileLink, you will need to insert converters -between the core's memory protocol and TileLink in the Tile module. +Chipyard uses TileLink as its onboard bus protocol. If your core doesn't use TileLink, you will need to insert converters +between the core's memory protocol and TileLink within the Tile module. in the tile class. Below is an example of how to connect a core using AXI4 to the TileLink bus with converters provided by Rocket chip: @@ -195,8 +200,8 @@ Create Implementation Class --------------------------- The implementation class contains the parameterized, actual hardware that depends on the values resolved by the Diplomacy -framework according to the info provided in the Tile class. This class will normally contains Chisel RTL codes, and if your -core is in Verilog, you will need to put the black box class you created in the first step here and connect it with the buses +framework according to the info provided in the Tile class. This class will normally contains Chisel RTL code. If your +core is in Verilog, you will need to instantiate the black box class that wraps your Verilog implementation and connect it with the buses and other components. No Diplomacy/TileLink code should be in this class; you should only connect the IO signals in TileLink interfaces or other diplomatically defined components, which are located in the tile class. @@ -247,7 +252,7 @@ from the implementation class: Create Config Fragments to Integrate the Core --------------------------------------------- -To use your core in a Chipyard config, you would need a config fragment that would create a ``TileParams`` object of your core in +To use your core in a Chipyard config, you will need a config fragment that will create a ``TileParams`` object of your core in the current config. An example of such config will be like this: .. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala @@ -260,8 +265,8 @@ This config fragment simply appends new tile parameters to the end of this list. Now you have finished all the steps to prepare your cores for Chipyard! To generate the custom core, simply follow the instructions in :ref:`custom_chisel` to add your project to the build system, then create a config by following the steps in :ref:`hetero_socs_`. -You can now run any desired workflow for the new config just as you do for the built-in cores. +You can now run most desired workflows for the new config just as you would for the built-in cores (depending on the functionality your core supports). If you would like to see an example of a complete third-party Verilog core integrated into Chipyard, ``generators/ariane/src/main/scala/ArianeTile.scala`` provides a concrete example of the Ariane core. Note that this particular example includes additional nuances with respect to the interaction of the AXI -interface with the memory coherency system. \ No newline at end of file +interface with the memory coherency system. diff --git a/generators/chipyard/src/main/scala/example/TutorialTile.scala b/generators/chipyard/src/main/scala/example/TutorialTile.scala index 41f79892..75ff1e5b 100644 --- a/generators/chipyard/src/main/scala/example/TutorialTile.scala +++ b/generators/chipyard/src/main/scala/example/TutorialTile.scala @@ -125,7 +125,7 @@ class MyTile( Resource(cpuDevice, "reg").bind(ResourceAddress(hartId)) } - // (Connection to bus, interrupt, etc.) + // TODO: Create TileLink nodes and connections here. // } // DOC include end: Tile class @@ -159,7 +159,7 @@ class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){ // annotate the parameters Annotated.params(this, outer.myParams) - // TODO: Create the top module of the core and connect it with the ports in "outer" } + // TODO: Create the top module of the core and connect it with the ports in "outer" //} // DOC include end: Implementation class From 14399e88b3fb7c048244c93d53c6600129f5c500 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sun, 12 Jul 2020 01:23:34 -0700 Subject: [PATCH 46/63] Minor change --- docs/Customization/Custom-Core.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index d6a19f04..16d19f27 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -225,7 +225,7 @@ Connect Interrupt Chipyard allows a tile to either receive interrupts from other devices or initiate interrupts to notify other cores/devices. In the tile that inherited ``SinksExternalInterrupts``, one can create a ``TileInterrupts`` object (a Chisel bundle) and call ``decodeCoreInterrupts`` with the object as the argument. Note that you should call this function in the implementation -class since it returns a Chisel bundle used by RTL code. You can then read the interrupt bits from the object. +class since it returns a Chisel bundle used by RTL code. You can then read the interrupt bits from the resulting object. The definition of ``TileInterrupts`` is .. code-block:: scala From 7ea464dc906eb629db1df7deb67ca9641ce01298 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Tue, 14 Jul 2020 12:49:36 -0700 Subject: [PATCH 47/63] 4th revision --- docs/Customization/Custom-Core.rst | 26 ++++++++++++++----- .../src/main/scala/example/TutorialTile.scala | 25 ++++++++++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index 16d19f27..4a7f57f1 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -224,9 +224,9 @@ Connect Interrupt Chipyard allows a tile to either receive interrupts from other devices or initiate interrupts to notify other cores/devices. In the tile that inherited ``SinksExternalInterrupts``, one can create a ``TileInterrupts`` object (a Chisel bundle) and -call ``decodeCoreInterrupts`` with the object as the argument. Note that you should call this function in the implementation -class since it returns a Chisel bundle used by RTL code. You can then read the interrupt bits from the resulting object. -The definition of ``TileInterrupts`` is +call ``decodeCoreInterrupts()`` with the object as the argument. Note that you should call this function in the implementation +class since it returns a Chisel bundle used by RTL code. You can then read the interrupt bits from the ``TileInterrupts`` bundle +we create above. The definition of ``TileInterrupts`` is .. code-block:: scala @@ -239,15 +239,29 @@ The definition of ``TileInterrupts`` is val lip = Vec(coreParams.nLocalInterrupts, Bool()) // Local interrupts } +Here is an example on how to connect these signals in the implementation class: + +.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala + :language: scala + :start-after: DOC include start: connect interrupt + :end-before: DOC include end: connect interrupt + Also, the tile can also notify other cores or devices for some events by calling following functions in ``SourcesExternalNotifications`` from the implementation class: .. code-block:: scala def reportHalt(could_halt: Option[Bool]) // Triggered when there is an unrecoverable hardware error (halt the machine) - def reportHalt(errors: Seq[CanHaveErrors]) // Varient for standard error bundle (used only by cache when there's an ECC error) - reportCease(could_cease: Option[Bool], quiescenceCycles: Int = 8) // Triggered when the core stop retiring instructions (like clock gating) - reportWFI(could_wfi: Option[Bool]) // Triggered when a WFI instruction is executed + def reportHalt(errors: Seq[CanHaveErrors]) // Varient for standard error bundle (Rocket specific: used only by cache when there's an ECC error) + def reportCease(could_cease: Option[Bool], quiescenceCycles: Int = 8) // Triggered when the core stop retiring instructions (like clock gating) + def reportWFI(could_wfi: Option[Bool]) // Triggered when a WFI instruction is executed + +Here is an example on how to use these functions to raise interrupt. + +.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala + :language: scala + :start-after: DOC include start: raise interrupt + :end-before: DOC include end: raise interrupt Create Config Fragments to Integrate the Core --------------------------------------------- diff --git a/generators/chipyard/src/main/scala/example/TutorialTile.scala b/generators/chipyard/src/main/scala/example/TutorialTile.scala index 75ff1e5b..c8f71b85 100644 --- a/generators/chipyard/src/main/scala/example/TutorialTile.scala +++ b/generators/chipyard/src/main/scala/example/TutorialTile.scala @@ -163,6 +163,31 @@ class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){ //} // DOC include end: Implementation class + // DOC include start: connect interrupt + // For example, our core support debug interrupt and machine-level interrupt, and suppose the following two signals + // are the interrupt inputs to the core. (DO NOT COPY this code - if your core treat each type of interrupt differently, + // you need to connect them to different interrupt ports of your core) + val debug_i = Wire(Bool()) + val mtip_i = Wire(Bool()) + // We create a bundle here and decode the interrupt. + val int_bundle = new TileInterrupts() + outer.decodeCoreInterrupts(int_bundle) + debug_i := int_bundle.debug + mtip_i := int_bundle.meip & int_bundle.msip & int_bundle.mtip + // DOC include end: connect interrupt + + // DOC include start: raise interrupt + // This is a demo. You should call these function according to your core + // Suppose that the following signal is from the decoder indicating a WFI instruction is received. + val wfi_o = Wire(Bool()) + outer.reportWFI(Some(wfi_o)) + // Suppose that the following signal indicate an unreconverable hardware error. + val halt_o = Wire(Bool()) + outer.reportHalt(Some(halt_o)) + // Suppose that our core never stall for a long time / stop retiring. Use None to indicate that this interrupt never fires. + outer.reportCease(None) + // DOC include end: raise interrupt + // DOC include start: AXI4 connect outer.memAXI4Node.out foreach { case (out, edgeOut) => // Connect your module IO port to "out" From 9fbc0a5bea7fe7f1b20a46389b18c9e71ee78f4e Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Wed, 15 Jul 2020 11:08:36 -0700 Subject: [PATCH 48/63] Add links --- docs/Customization/Custom-Core.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index 4a7f57f1..3d6a6393 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -39,6 +39,7 @@ of the tile class ``TileType``. .. code-block:: scala + // The two classes below can be found in https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/BaseTile.scala. trait TileParams { val core: CoreParams // Core parameters (see below) val icache: Option[ICacheParams] // Rocket specific: I1 cache option @@ -55,6 +56,7 @@ of the tile class ``TileType``. (implicit p: Parameters): TileType } + // This class can be found in https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/Core.scala. trait CoreParams { val bootFreqHz: BigInt // Frequency val useVM: Boolean // Support virtual memory @@ -105,6 +107,7 @@ of the tile class ``TileType``. def vMemDataBits: Int = 0 } + // This class can be found in https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/FPU.scala. case class FPUParams( minFLen: Int = 32, // Minimum floating point length (no need to change) fLen: Int = 64, // Maximum floating point length, use 32 if only single precision is supported @@ -191,6 +194,9 @@ can override the following two functions to control how to buffer the bus reques .. code-block:: scala + // This two functions can be found in https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/BaseTile.scala, + // in the class "BaseTile". + // By default, their value is "TLBuffer(BufferParams.none)". protected def makeMasterBoundaryBuffers(implicit p: Parameters): TLBuffer protected def makeSlaveBoundaryBuffers(implicit p: Parameters): TLBuffer @@ -230,6 +236,7 @@ we create above. The definition of ``TileInterrupts`` is .. code-block:: scala + // This class can be found in https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/Interrupts.scala. class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) { val debug = Bool() // debug interrupt val mtip = Bool() // Machine level timer interrupt @@ -251,6 +258,8 @@ from the implementation class: .. code-block:: scala + // These functions can be found in https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/Interrupts.scala, + // in the trait "SourcesExternalNotifications". def reportHalt(could_halt: Option[Bool]) // Triggered when there is an unrecoverable hardware error (halt the machine) def reportHalt(errors: Seq[CanHaveErrors]) // Varient for standard error bundle (Rocket specific: used only by cache when there's an ECC error) def reportCease(could_cease: Option[Bool], quiescenceCycles: Int = 8) // Triggered when the core stop retiring instructions (like clock gating) From fddf2181471a1d227f75c592e394ec0bc39cc6c7 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Thu, 16 Jul 2020 15:39:07 -0700 Subject: [PATCH 49/63] 5th revision --- .../src/main/scala/example/TutorialTile.scala | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/generators/chipyard/src/main/scala/example/TutorialTile.scala b/generators/chipyard/src/main/scala/example/TutorialTile.scala index c8f71b85..1f58e5e4 100644 --- a/generators/chipyard/src/main/scala/example/TutorialTile.scala +++ b/generators/chipyard/src/main/scala/example/TutorialTile.scala @@ -126,7 +126,6 @@ class MyTile( } // TODO: Create TileLink nodes and connections here. -// } // DOC include end: Tile class // DOC include start: AXI4 node @@ -160,7 +159,20 @@ class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){ Annotated.params(this, outer.myParams) // TODO: Create the top module of the core and connect it with the ports in "outer" -//} + + // If your core is in Verilog (assume your blackbox is called "MyCoreBlackbox"), instantiate it here like + // val core = Module(new MyCoreBlackbox(params...)) + // (as described in the blackbox tutorial) and connect appropriate signals. See the blackbox tutorial + // (link on the top of the page) for more info. + // You can look at https://github.com/ucb-bar/ariane-wrapper/blob/master/src/main/scala/ArianeTile.scala + // for a Verilog example. + + // If your core is in Chisel, you can simply instantiate the top module here like other Chisel module + // and connect appropriate signal. You can even implement this class as your top module. + // See https://github.com/riscv-boom/riscv-boom/blob/master/src/main/scala/common/tile.scala and + // https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/RocketTile.scala for + // Chisel example. + // DOC include end: Implementation class // DOC include start: connect interrupt From ae1e44a9e360f51abb925958fab0686f36eb8d8b Mon Sep 17 00:00:00 2001 From: banahogg Date: Sat, 18 Jul 2020 17:44:52 -0700 Subject: [PATCH 50/63] Update BOOM URL in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 285d337b..ab542cf3 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ These additional publications cover many of the internal components used in Chip [berkeley]: https://berkeley.edu [riscv]: https://riscv.org/ [rocket-chip]: https://github.com/freechipsproject/rocket-chip -[boom]: https://github.com/ucb-bar/riscv-boom +[boom]: https://github.com/riscv-boom/riscv-boom [firemarshal]: https://github.com/firesim/FireMarshal/ [ariane]: https://github.com/pulp-platform/ariane/ [gemmini]: https://github.com/ucb-bar/gemmini From 2c7e7f3199d497668a20d8a635dfb2aeca27b81d Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sun, 19 Jul 2020 21:36:50 -0700 Subject: [PATCH 51/63] Fixed file links --- docs/Customization/Custom-Core.rst | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index 3d6a6393..fa14fff6 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -35,11 +35,14 @@ where ``TileType`` is the tile class (see the next section). All custom cores will also need to implement ``instantiate()`` in their tile parameter class to return a new instance of the tile class ``TileType``. -``TileParams``, ``InstantiableTileParams[TileType]`` and ``CoreParams`` contains the following fields: +``TileParams`` (in the file `BaseTile.scala `_) , +``InstantiableTileParams`` (in the file `BaseTile.scala `_), +``CoreParams`` (in the file `Core.scala `_), +and ``FPUParams`` (in the file `FPU.scala `_) +contains the following fields: .. code-block:: scala - // The two classes below can be found in https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/BaseTile.scala. trait TileParams { val core: CoreParams // Core parameters (see below) val icache: Option[ICacheParams] // Rocket specific: I1 cache option @@ -56,7 +59,6 @@ of the tile class ``TileType``. (implicit p: Parameters): TileType } - // This class can be found in https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/Core.scala. trait CoreParams { val bootFreqHz: BigInt // Frequency val useVM: Boolean // Support virtual memory @@ -106,8 +108,7 @@ of the tile class ``TileType``. def eLen(xLen: Int, fLen: Int): Int = xLen max fLen def vMemDataBits: Int = 0 } - - // This class can be found in https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/FPU.scala. + case class FPUParams( minFLen: Int = 32, // Minimum floating point length (no need to change) fLen: Int = 64, // Maximum floating point length, use 32 if only single precision is supported @@ -191,11 +192,11 @@ Make sure to read :ref:`node_types` to check out what type of nodes Chipyard sup Also, by default, there are boundary buffers for both master and slave connections to the bus when they are leaving the tile, and you can override the following two functions to control how to buffer the bus requests/responses: +(You can find the definition of these two functions in the class ``BaseTile`` in the file +`BaseTile.scala `_) .. code-block:: scala - // This two functions can be found in https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/BaseTile.scala, - // in the class "BaseTile". // By default, their value is "TLBuffer(BufferParams.none)". protected def makeMasterBoundaryBuffers(implicit p: Parameters): TLBuffer protected def makeSlaveBoundaryBuffers(implicit p: Parameters): TLBuffer @@ -232,11 +233,11 @@ Chipyard allows a tile to either receive interrupts from other devices or initia In the tile that inherited ``SinksExternalInterrupts``, one can create a ``TileInterrupts`` object (a Chisel bundle) and call ``decodeCoreInterrupts()`` with the object as the argument. Note that you should call this function in the implementation class since it returns a Chisel bundle used by RTL code. You can then read the interrupt bits from the ``TileInterrupts`` bundle -we create above. The definition of ``TileInterrupts`` is +we create above. The definition of ``TileInterrupts`` +(in the file `Interrupts.scala `_) is .. code-block:: scala - // This class can be found in https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/Interrupts.scala. class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) { val debug = Bool() // debug interrupt val mtip = Bool() // Machine level timer interrupt @@ -255,11 +256,11 @@ Here is an example on how to connect these signals in the implementation class: Also, the tile can also notify other cores or devices for some events by calling following functions in ``SourcesExternalNotifications`` from the implementation class: +(These functions can be found in in the trait ``SourcesExternalNotifications`` in the file +`Interrupts.scala `_) .. code-block:: scala - // These functions can be found in https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/Interrupts.scala, - // in the trait "SourcesExternalNotifications". def reportHalt(could_halt: Option[Bool]) // Triggered when there is an unrecoverable hardware error (halt the machine) def reportHalt(errors: Seq[CanHaveErrors]) // Varient for standard error bundle (Rocket specific: used only by cache when there's an ECC error) def reportCease(could_cease: Option[Bool], quiescenceCycles: Int = 8) // Triggered when the core stop retiring instructions (like clock gating) From 0a39819f442ce54d3b280870eab0d3e398235f6c Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sun, 19 Jul 2020 21:46:32 -0700 Subject: [PATCH 52/63] Add source file note --- docs/Customization/Custom-Core.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index fa14fff6..4f529efc 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -10,6 +10,11 @@ instructions on how to achieve this. RoCC is currently not supported by cores other than Rocket and BOOM. Please use Rocket or BOOM as the RoCC base core if you need to use RoCC. +.. note:: + + This page contains links to the files that contains important definitions in the Rocket chip repository, which is maintained separately + from Chipyard. If you find any discrepency between the code on this page and the code in the source file, please report it through + GitHub issues! Wrap Verilog Module with Blackbox (Optional) -------------------------------------------- From 692b120b65ab72f6e3f1a7885efed74057b08747 Mon Sep 17 00:00:00 2001 From: Zitao Fang Date: Sun, 19 Jul 2020 21:48:07 -0700 Subject: [PATCH 53/63] Fixed typo --- docs/Customization/Custom-Core.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Customization/Custom-Core.rst b/docs/Customization/Custom-Core.rst index 4f529efc..a76741ec 100644 --- a/docs/Customization/Custom-Core.rst +++ b/docs/Customization/Custom-Core.rst @@ -13,7 +13,7 @@ instructions on how to achieve this. .. note:: This page contains links to the files that contains important definitions in the Rocket chip repository, which is maintained separately - from Chipyard. If you find any discrepency between the code on this page and the code in the source file, please report it through + from Chipyard. If you find any discrepancy between the code on this page and the code in the source file, please report it through GitHub issues! Wrap Verilog Module with Blackbox (Optional) From b719919934b3e9663edb5753d97ca5639641b9c6 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 16 Jul 2020 18:30:05 -0700 Subject: [PATCH 54/63] Add RANDOM_SEED variable to set random init for VCS and Verilator simulations --- common.mk | 10 +++++----- generators/tracegen/tracegen.mk | 2 +- sims/vcs/Makefile | 6 ++---- sims/verilator/Makefile | 9 ++++++++- vcs.mk | 8 ++++++++ 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/common.mk b/common.mk index 71f4440c..9d322f00 100644 --- a/common.mk +++ b/common.mk @@ -141,19 +141,19 @@ verilog: $(sim_vsrcs) ######################################################################################### .PHONY: run-binary run-binary-fast run-binary-debug run-fast run-binary: $(output_dir) $(sim) - (set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $(BINARY) >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log) + (set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $(BINARY) >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log) ######################################################################################### # helper rules to run simulator as fast as possible ######################################################################################### run-binary-fast: $(output_dir) $(sim) - (set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(PERMISSIVE_OFF) $(BINARY) >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log) + (set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(WAVEFORM_FLAG) $(PERMISSIVE_OFF) $(BINARY) >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log) run-fast: run-asm-tests-fast run-bmark-tests-fast @@ -167,10 +167,10 @@ $(output_dir)/%: $(RISCV)/riscv64-unknown-elf/share/riscv-tests/isa/% $(output_d ln -sf $< $@ $(output_dir)/%.run: $(output_dir)/% $(sim) - (set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(PERMISSIVE_OFF) $< >(spike-dasm > $@) | tee $<.log) + (set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $< >(spike-dasm > $@) | tee $<.log) ######################################################################################### # include build/project specific makefrags made from the generator diff --git a/generators/tracegen/tracegen.mk b/generators/tracegen/tracegen.mk index fc4bd246..fec62288 100644 --- a/generators/tracegen/tracegen.mk +++ b/generators/tracegen/tracegen.mk @@ -9,7 +9,7 @@ $(AXE): $(wildcard $(AXE_DIR)/*.[ch]) $(AXE_DIR)/make.sh cd $(AXE_DIR) && ./make.sh $(output_dir)/tracegen.out: $(sim) - mkdir -p $(output_dir) && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) none $@ + mkdir -p $(output_dir) && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) none $@ $(output_dir)/tracegen.result: $(output_dir)/tracegen.out $(AXE) $(base_dir)/scripts/check-tracegen.sh $< > $@ diff --git a/sims/vcs/Makefile b/sims/vcs/Makefile index df2dbbe6..14ebae59 100644 --- a/sims/vcs/Makefile +++ b/sims/vcs/Makefile @@ -47,13 +47,11 @@ VCS_OPTS = -notice -line $(VCS_CC_OPTS) $(VCS_NONCC_OPTS) $(VCS_DEFINE_OPTS) $(E # vcs simulator rules ######################################################################################### $(sim): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) $(EXTRA_SIM_REQS) - rm -rf csrc && $(VCS) $(VCS_OPTS) -o $@ \ - -debug_pp + rm -rf csrc && $(VCS) $(VCS_OPTS) -o $@ $(sim_debug): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) $(EXTRA_SIM_REQS) rm -rf csrc && $(VCS) $(VCS_OPTS) -o $@ \ - +define+DEBUG \ - -debug_pp + +define+DEBUG ######################################################################################### # create a vcs vpd rule diff --git a/sims/verilator/Makefile b/sims/verilator/Makefile index 667c856c..3d676efd 100644 --- a/sims/verilator/Makefile +++ b/sims/verilator/Makefile @@ -30,6 +30,13 @@ sim_debug = $(sim_dir)/$(sim_prefix)-$(MODEL_PACKAGE)-$(CONFIG)-debug WAVEFORM_FLAG=-v$(sim_out_name).vcd +# If verilator seed unspecified, verilator uses srand as random seed +ifdef RANDOM_SEED +SEED_FLAG=+verilator+seed+I$(RANDOM_SEED) +else +SEED_FLAG= +endif + .PHONY: default debug default: $(sim) debug: $(sim_debug) @@ -145,7 +152,7 @@ $(sim_debug): $(model_mk_debug) $(dramsim_lib) $(output_dir)/%.vpd: $(output_dir)/% $(sim_debug) rm -f $@.vcd && mkfifo $@.vcd vcd2vpd $@.vcd $@ > /dev/null & - (set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) -v$@.vcd $(PERMISSIVE_OFF) $< >(spike-dasm > $<.out) | tee $<.log) + (set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) -v$@.vcd $(PERMISSIVE_OFF) $< >(spike-dasm > $<.out) | tee $<.log) ######################################################################################### # general cleanup rule diff --git a/vcs.mk b/vcs.mk index 96cd0636..93e75c19 100644 --- a/vcs.mk +++ b/vcs.mk @@ -1,5 +1,13 @@ WAVEFORM_FLAG=+vcdplusfile=$(sim_out_name).vpd +# If ntb_random_seed unspecified, vcs uses 1 as constant seed. +# Set ntb_random_seed_automatic to actually get a random seed +ifdef RANDOM_SEED +SEED_FLAG=+ntb_random_seed=$(RANDOM_SEED) +else +SEED_FLAG=+ntb_random_seed_automatic +endif + CLOCK_PERIOD ?= 1.0 RESET_DELAY ?= 777.7 From df07790a5adb8e5c2f98bfc678a4d8203b902067 Mon Sep 17 00:00:00 2001 From: Nathan Pemberton Date: Fri, 17 Jul 2020 12:22:22 -0400 Subject: [PATCH 55/63] Bump FireMarshal/QEMU/riscv-isa-sim for OpenSBI --- software/firemarshal | 2 +- toolchains/qemu | 2 +- toolchains/riscv-tools/riscv-isa-sim | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/software/firemarshal b/software/firemarshal index 6c6a08f9..83b86610 160000 --- a/software/firemarshal +++ b/software/firemarshal @@ -1 +1 @@ -Subproject commit 6c6a08f9790c660823e9f858ca87f93b2502fa44 +Subproject commit 83b866104c6860b5d03989a6cf8439aa6934b398 diff --git a/toolchains/qemu b/toolchains/qemu index 4f591025..fdd76fec 160000 --- a/toolchains/qemu +++ b/toolchains/qemu @@ -1 +1 @@ -Subproject commit 4f59102571fce49af180cfc6d4cdd2b5df7bdb14 +Subproject commit fdd76fecdde1ad444ff4deb7f1c4f7e4a1ef97d6 diff --git a/toolchains/riscv-tools/riscv-isa-sim b/toolchains/riscv-tools/riscv-isa-sim index 9443c1db..8d860c19 160000 --- a/toolchains/riscv-tools/riscv-isa-sim +++ b/toolchains/riscv-tools/riscv-isa-sim @@ -1 +1 @@ -Subproject commit 9443c1dbac0301faf3a47c5e6914cc7dcb34983e +Subproject commit 8d860c190640e19e0f23a21d2479b4a36d13d342 From 16d4186ea4e8d275a6bdd55dd0c1ea8f6e145597 Mon Sep 17 00:00:00 2001 From: Sam Steffl Date: Fri, 31 Jul 2020 10:29:53 -0700 Subject: [PATCH 56/63] updated openroad hash --- vlsi/hammer | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vlsi/hammer b/vlsi/hammer index 528e745c..cbc907df 160000 --- a/vlsi/hammer +++ b/vlsi/hammer @@ -1 +1 @@ -Subproject commit 528e745c54c3901a311aade7c928e866de1d42d2 +Subproject commit cbc907dfe8005a8d72f1b2fb7b414ad9dbfe14b1 From d7f3f91f18de038b69b9ba8cbd6a894437c543b0 Mon Sep 17 00:00:00 2001 From: Howard Mao Date: Thu, 30 Jul 2020 10:58:35 -0700 Subject: [PATCH 57/63] implement fast loadmem feature --- docs/Simulation/Software-RTL-Simulation.rst | 23 +++++++++++++++++++++ generators/testchipip | 2 +- sims/firesim | 2 +- variables.mk | 5 +++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/docs/Simulation/Software-RTL-Simulation.rst b/docs/Simulation/Software-RTL-Simulation.rst index bdafd60f..93e4dcc6 100644 --- a/docs/Simulation/Software-RTL-Simulation.rst +++ b/docs/Simulation/Software-RTL-Simulation.rst @@ -62,6 +62,12 @@ For instance, to run one of the riscv-tools assembly tests. .. Note:: In a VCS simulator, the simulator name will be ``simv-chipyard-RocketConfig`` instead of ``simulator-chipyard-RocketConfig``. +The makefiles have a ``run-binary`` rule that simplifies running the simulation executable. It adds many of the common command line options for you and redirects the output to a file. + +.. code-block:: shell + + make run-binary BINARY=$RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-simple + Alternatively, we can run a pre-packaged suite of RISC-V assembly or benchmark tests, by adding the make target ``run-asm-tests`` or ``run-bmark-tests``. For example: @@ -126,6 +132,23 @@ All ``make`` targets that can be applied to the default example, can also be app Finally, in the ``generated-src/<...>--/`` directory resides all of the collateral and Verilog source files for the build/simulation. Specifically, the SoC top-level (``TOP``) Verilog file is denoted with ``*.top.v`` while the ``TestHarness`` file is denoted with ``*.harness.v``. +Fast Memory Loading +------------------- + +The simulator loads the program binary over a simulated serial line. This can be quite slow if there is a lot of static data, so the simulator also allows data to be loaded from a file directly into the DRAM model. + +.. code-block:: shell + + make run-binary BINARY=test.riscv LOADMEM=testdata.hex LOADMEM_ADDR=81000000 + +The ``.hex`` file should be a text file with a hexadecimal number on each line. + +.. code-block:: text + + deadbeef + 0123 + +Each line uses little-endian order, so this file would produce the bytes "ef be ad de 01 23". ``LOADMEM_ADDR`` specifies which address in memory (in hexadecimal) to write the first byte to. The default is 0x81000000. Generating Waveforms ----------------------- diff --git a/generators/testchipip b/generators/testchipip index 8b5c89a5..3366844f 160000 --- a/generators/testchipip +++ b/generators/testchipip @@ -1 +1 @@ -Subproject commit 8b5c89a5f7120e64a7ac5ce5210165426a58f3de +Subproject commit 3366844f50a7969f1997125c07ce8d00e5494cf0 diff --git a/sims/firesim b/sims/firesim index 8064d880..ec9d615f 160000 --- a/sims/firesim +++ b/sims/firesim @@ -1 +1 @@ -Subproject commit 8064d8808b9c936711361532a95affbfc2fcbdca +Subproject commit ec9d615f6db72684cfee16a2b57f50493b63ca1f diff --git a/variables.mk b/variables.mk index 48da498e..1aa129f3 100644 --- a/variables.mk +++ b/variables.mk @@ -163,7 +163,12 @@ output_dir=$(sim_dir)/output/$(long_name) PERMISSIVE_ON=+permissive PERMISSIVE_OFF=+permissive-off BINARY ?= +LOADMEM ?= +LOADMEM_ADDR ?= 81000000 override SIM_FLAGS += +dramsim +dramsim_ini_dir=$(TESTCHIP_DIR)/src/main/resources/dramsim2_ini +max-cycles=$(timeout_cycles) +ifneq ($(LOADMEM),) +override SIM_FLAGS += +loadmem=$(LOADMEM) +loadmem_addr=$(LOADMEM_ADDR) +endif VERBOSE_FLAGS ?= +verbose sim_out_name = $(output_dir)/$(subst $() $(),_,$(notdir $(basename $(BINARY)))) From 813d1fdb9e37391e9a6e9445bedcb7181be74e23 Mon Sep 17 00:00:00 2001 From: Howard Mao Date: Mon, 3 Aug 2020 16:09:16 -0700 Subject: [PATCH 58/63] bump firesim --- sims/firesim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sims/firesim b/sims/firesim index ec9d615f..b13e7529 160000 --- a/sims/firesim +++ b/sims/firesim @@ -1 +1 @@ -Subproject commit ec9d615f6db72684cfee16a2b57f50493b63ca1f +Subproject commit b13e75296c44b1f3fa987d15df6a595668842dfe From 93c7fef9424a25fc8157c1ad6d504cd5cca126df Mon Sep 17 00:00:00 2001 From: Colin Schmidt Date: Wed, 5 Aug 2020 09:54:07 -0700 Subject: [PATCH 59/63] We need to uppercase hex chars for bc --- common.mk | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/common.mk b/common.mk index 9d322f00..6679457e 100644 --- a/common.mk +++ b/common.mk @@ -157,6 +157,30 @@ run-binary-debug: $(output_dir) $(sim_debug) run-fast: run-asm-tests-fast run-bmark-tests-fast +######################################################################################### +# helper rules to run simulator with fast loadmem via hex files +######################################################################################### +$(binary_hex): $(output_dir) $(BINARY) + hex_bytes=$(shell readelf --segments --wide $(BINARY) | grep LOAD | tail -n 1 | tr -s [:space:] | cut -f4,6 -d' ' | tr -d x | tr [:lower:] [:upper:] | tr ' ' + | sed 's/0000000008/ibase=16;/' | bc);\ + power_2_bytes=`python -c "import math; print int(pow(2,math.ceil(math.log($$hex_bytes)/math.log(2))))"`;\ + elf2hex 64 $$power_2_bytes $(BINARY) $(shell echo "ibase=16;$(LOADMEM_ADDR)" | bc) > $(binary_hex) + +run-binary-hex: $(output_dir) $(sim) $(binary_hex) +run-binary-hex: run-binary +run-binary-hex: override LOADMEM_ADDR = 80000000 +run-binary-hex: override LOADMEM = $(binary_hex) +run-binary-hex: override SIM_FLAGS += +loadmem=$(LOADMEM) +loadmem_addr=$(LOADMEM_ADDR) +run-binary-debug-hex: $(output_dir) $(sim) $(binary_hex) +run-binary-debug-hex: run-binary-debug +run-binary-debug-hex: override LOADMEM_ADDR = 80000000 +run-binary-debug-hex: override LOADMEM = $(binary_hex) +run-binary-debug-hex: override SIM_FLAGS += +loadmem=$(LOADMEM) +loadmem_addr=$(LOADMEM_ADDR) +run-binary-fast-hex: $(output_dir) $(sim) $(binary_hex) +run-binary-fast-hex: run-binary-fast +run-binary-fast-hex: override LOADMEM_ADDR = 80000000 +run-binary-fast-hex: override LOADMEM = $(binary_hex) +run-binary-fast-hex: override SIM_FLAGS += +loadmem=$(LOADMEM) +loadmem_addr=$(LOADMEM_ADDR) + ######################################################################################### # run assembly/benchmarks rules ######################################################################################### From 5bfc289677fcff16c19a71c6b79006a0c31b09c7 Mon Sep 17 00:00:00 2001 From: Colin Schmidt Date: Wed, 5 Aug 2020 09:55:31 -0700 Subject: [PATCH 60/63] Bump fesvr for better loadmem impl. Fix verilator loadmem support --- .../utilities/src/main/resources/csrc/emulator.cc | 10 ++-------- toolchains/esp-tools/riscv-isa-sim | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/generators/utilities/src/main/resources/csrc/emulator.cc b/generators/utilities/src/main/resources/csrc/emulator.cc index 0a3b46da..27a8aa4a 100644 --- a/generators/utilities/src/main/resources/csrc/emulator.cc +++ b/generators/utilities/src/main/resources/csrc/emulator.cc @@ -116,7 +116,6 @@ int main(int argc, char** argv) FILE * vcdfile = NULL; uint64_t start = 0; #endif - char ** htif_argv = NULL; int verilog_plusargs_legal = 1; opterr = 1; @@ -252,10 +251,6 @@ done_processing: usage(argv[0]); return 1; } - int htif_argc = 1 + argc - optind; - htif_argv = (char **) malloc((htif_argc) * sizeof (char *)); - htif_argv[0] = argv[0]; - for (int i = 1; optind < argc;) htif_argv[i++] = argv[optind++]; if (verbose) fprintf(stderr, "using random seed %u\n", random_seed); @@ -278,8 +273,8 @@ done_processing: #endif jtag = new remote_bitbang_t(rbb_port); - dtm = new dtm_t(htif_argc, htif_argv); - tsi = new tsi_t(htif_argc, htif_argv); + dtm = new dtm_t(argc, argv); + tsi = new tsi_t(argc, argv); signal(SIGTERM, handle_sigterm); @@ -364,6 +359,5 @@ done_processing: if (tsi) delete tsi; if (jtag) delete jtag; if (tile) delete tile; - if (htif_argv) free(htif_argv); return ret; } diff --git a/toolchains/esp-tools/riscv-isa-sim b/toolchains/esp-tools/riscv-isa-sim index 13384cac..2bc65d1b 160000 --- a/toolchains/esp-tools/riscv-isa-sim +++ b/toolchains/esp-tools/riscv-isa-sim @@ -1 +1 @@ -Subproject commit 13384cac1e54828200067ff890f564a505a4ebb3 +Subproject commit 2bc65d1bf6605077e3740941c086724beb35db05 From edbb86ef982c08859842c923b2d7c46ef5d011c3 Mon Sep 17 00:00:00 2001 From: Colin Schmidt Date: Wed, 5 Aug 2020 11:17:48 -0700 Subject: [PATCH 61/63] Move elf2hex preprocessing into separate script --- common.mk | 4 +--- scripts/smartelf2hex.sh | 14 ++++++++++++++ variables.mk | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100755 scripts/smartelf2hex.sh diff --git a/common.mk b/common.mk index 6679457e..43615a92 100644 --- a/common.mk +++ b/common.mk @@ -161,9 +161,7 @@ run-fast: run-asm-tests-fast run-bmark-tests-fast # helper rules to run simulator with fast loadmem via hex files ######################################################################################### $(binary_hex): $(output_dir) $(BINARY) - hex_bytes=$(shell readelf --segments --wide $(BINARY) | grep LOAD | tail -n 1 | tr -s [:space:] | cut -f4,6 -d' ' | tr -d x | tr [:lower:] [:upper:] | tr ' ' + | sed 's/0000000008/ibase=16;/' | bc);\ - power_2_bytes=`python -c "import math; print int(pow(2,math.ceil(math.log($$hex_bytes)/math.log(2))))"`;\ - elf2hex 64 $$power_2_bytes $(BINARY) $(shell echo "ibase=16;$(LOADMEM_ADDR)" | bc) > $(binary_hex) + $(base_dir)/scripts/smartelf2hex.sh $(BINARY) > $(binary_hex) run-binary-hex: $(output_dir) $(sim) $(binary_hex) run-binary-hex: run-binary diff --git a/scripts/smartelf2hex.sh b/scripts/smartelf2hex.sh new file mode 100755 index 00000000..782977ff --- /dev/null +++ b/scripts/smartelf2hex.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# This script find the appropriate arguments to pass to elf2hex by inspecting the given RISC-V elf binary +# First and only argument is the binary to be converted. +# The output of this script should be redirected to a file (as with normal elf2hex). + +binary=$1 +segments=`readelf --segments --wide $binary` +entry_hex=`echo -e "$segments" | grep "Entry point" | cut -f3 -d' ' | sed 's/0x//' | tr [:lower:] [:upper:]` +entry_dec=`bc <<< "ibase=16;$entry_hex"` +length_hex=`echo "$segments" | grep LOAD | tail -n 1 | tr -s [:space:] | cut -f4,6 -d' '` +length_dec=`echo $length_hex | tr -d x | tr [:lower:] [:upper:] | tr ' ' + | sed 's/^/ibase=16;/' | sed "s/$/-$entry_hex/" | bc` +power_2_length=`echo "x=l($length_dec)/l(2); scale=0; 2^((x+1)/1)" | bc -l` +elf2hex 64 $power_2_length $binary $entry_dec diff --git a/variables.mk b/variables.mk index 61602507..d7eccb49 100644 --- a/variables.mk +++ b/variables.mk @@ -173,6 +173,7 @@ override SIM_FLAGS += +loadmem=$(LOADMEM) +loadmem_addr=$(LOADMEM_ADDR) endif VERBOSE_FLAGS ?= +verbose sim_out_name = $(output_dir)/$(subst $() $(),_,$(notdir $(basename $(BINARY)))) +binary_hex= $(sim_out_name).loadmem_hex ######################################################################################### # build output directory for compilation From caab6fb968c866c24b31c3dc6f5c3c1a3a2a87b8 Mon Sep 17 00:00:00 2001 From: Colin Schmidt Date: Wed, 5 Aug 2020 11:27:14 -0700 Subject: [PATCH 62/63] Add run-binary-hex docs --- docs/Simulation/Software-RTL-Simulation.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/Simulation/Software-RTL-Simulation.rst b/docs/Simulation/Software-RTL-Simulation.rst index 93e4dcc6..28ae223e 100644 --- a/docs/Simulation/Software-RTL-Simulation.rst +++ b/docs/Simulation/Software-RTL-Simulation.rst @@ -150,6 +150,12 @@ The ``.hex`` file should be a text file with a hexadecimal number on each line. Each line uses little-endian order, so this file would produce the bytes "ef be ad de 01 23". ``LOADMEM_ADDR`` specifies which address in memory (in hexadecimal) to write the first byte to. The default is 0x81000000. +A special target that facilitates automatically generating a hex file for an entire elf RISC-V exectuable and then running the simulator with the appropriate flags is also available. + +.. code-block:: shell + + make run-binary-hex BINARY=test.riscv + Generating Waveforms ----------------------- From 8499b769410a4d7c16e387cb0a6c200c3bf6f5d3 Mon Sep 17 00:00:00 2001 From: Colin Schmidt Date: Wed, 5 Aug 2020 15:36:13 -0700 Subject: [PATCH 63/63] Bump esp-spike to master --- toolchains/esp-tools/riscv-isa-sim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/toolchains/esp-tools/riscv-isa-sim b/toolchains/esp-tools/riscv-isa-sim index 2bc65d1b..a1ff6b03 160000 --- a/toolchains/esp-tools/riscv-isa-sim +++ b/toolchains/esp-tools/riscv-isa-sim @@ -1 +1 @@ -Subproject commit 2bc65d1bf6605077e3740941c086724beb35db05 +Subproject commit a1ff6b03f7f630a06327798238256973568e3837