4. Config Exercise

Configs describe what goes into our final system and what parameters our designs are elaborated with. You can find the configs in $chipyard/generators/chipyard/src/main/scala/config.

Look at the configs located in $chipyard/generators/chipyard/src/main/scala/config/RocketConfigs.scala, specifically RocketConfig

class RocketConfig extends Config(
  new freechips.rocketchip.subsystem.WithNBigCores(1) ++         // single rocket-core
  new chipyard.config.AbstractConfig)                            // builds one on top of another, so the single rocket-core is built on top of the AbstractConfig

Let's break this down. RocketConfig is a scala class that extends the Config class, which can be found in the org.chipsalliance.cde scala package. The scala code for the Config class is quite complex and is not necessary to know for this class. However, you should understand the general pattern for constructing your own config.

This config contains two config fragments: freechips.rocketchip.subsystem.WithNBigCores(1) and chipyard.config.AbstractConfig.

Let's look at the AbstractConfig class first. We can use the package name to figure out which directory to search -> /generators/chipyard/src/main/scala/config/AbstractConfig.scala. Another option to find the class is to use the grep or git grep commands. Looking at the AbstractConfig class tells us that it is also composed of config fragments. Take a moment to look through the config fragments and the comments describing them. Notice any familiar hardware components?

Make sure you have sourced the environment script before using git grep. Additionally, you may want to use the --recurse-submodules flag to search text in both the outer Chipyard repo and inside submodules.

Now, let's look at the WithNBigCores fragment, which we can see belongs to rocket-chip. We follow the package names again to /generators/rocket-chip/src/main/scala/subsystem/Configs.scala. Instead of being made up of smaller config fragments, this config directly adds to the Chipyard system. It takes 3 parameters, two of which have default values. We see from our RocketConfig that we are setting the number of cores to 1. To briefly summarize the scala code inside the body of the config, the config instantiates parameters for a Rocket tile with a large core, then places n of those tiles on the SoC.

class WithNBigCores(
  n: Int,
  overrideIdOffset: Option[Int] = None,
  crossing: RocketCrossingParams = RocketCrossingParams()
) extends Config((site, here, up) => {
  case TilesLocated(InSubsystem) => {
    val prev = up(TilesLocated(InSubsystem), site)
    val idOffset = overrideIdOffset.getOrElse(prev.size)
    val big = RocketTileParams(
      core   = RocketCoreParams(mulDiv = Some(MulDivParams(
        mulUnroll = 8,
        mulEarlyOut = true,
        divEarlyOut = true))),
      dcache = Some(DCacheParams(
        rowBits = site(SystemBusKey).beatBits,
        nMSHRs = 0,
        blockBytes = site(CacheBlockBytes))),
      icache = Some(ICacheParams(
        rowBits = site(SystemBusKey).beatBits,
        blockBytes = site(CacheBlockBytes))))
    List.tabulate(n)(i => RocketTileAttachParams(
      big.copy(hartId = i + idOffset),
      crossing
    )) ++ prev
  }
})

Putting these two fragments together, we see that our RocketConfig contains all of the system-building code from the AbstractConfig and one RocketTile with a big rocket core.

To put this in context of the entire Chipyard system, RocketConfig is part of the "Digital System configuration" depicted below. It is built on top of the AbstractConfig which contains the config fragments for IO Binders and Harness Binders (depicted below).

For more information on how configs are constructed, see the below resource:

pageConfigs, Parameters, Mixins, and Everything In Between

Let's dive deeper into our RocketConfig. Read through the following examples to see how to search through Chipyard code and find which components are added to our SoC.

QuestionAnswerHow we found the answer?

Is UART enabled? If so, which config fragments enabled it?

Yes; chipyard.config.WithUART, chipyard.iobinders.WithUARTIOCells, chipyard.harness.WithUARTAdapter.

We grep for AbstractConfig in $chipyard/generators/chipyard/src/main/scala/and find AbstractConfig at $chipyard/generators/chipyard/src/main/scala/config/AbstractConfig.scala. We search for UART and find the corresponding config fragments.

How many bytes are in a block for the L1 DCache? How many sets are in the L1 DCache? Ways?

64 Block Bytes, 64 Sets, 4 Ways

We don't see anything about L1 DCaches in AbstractConfigWe grep for WithNBigCores at $chipyard/generators/rocket-chip/src/main/scala/. We find it in $chipyard/generators/rocket-chip/src/main/scala/subsystem/Configs.scala We see that the fragment instantiates a dcache with DCacheParams We notice it passes in CacheBlockBytes to blockBytes. So, we grep for CacheBlockBytes in $chipyard/generators/rocket-chip/src/main/scala/ and see

src/main/scala/subsystem/BankedL2Params.scala:case object CacheBlockBytes extends Field[Int](64)

Then, we grep for DCacheParams and find it in$chipyard/generators/rocket-chip/src/main/scala/rocket/HellaCache.scala where we find the nSets and nWays fields

Is there an L2 used in this config? What size?

Yes. 1 bank, 8 ways, 512Kb.

We once again start looking at RocketConfig which leads us to AbstractConfig. Looking at the comments of the various config fragments we see the comment // use Sifive L2 cache next to new freechips.rocketchip.subsystem.WithInclusiveCache ++ (You can read more about SiFive here). We could have grepped in the generators directory for WithInclusiveCache or noticed that a sifive-cache submodule existed under $chipyard/generators. Navigating through it we eventually find the WithInclusiveCache class at block-inclusivecache-sifive/design/craft/inclusivecache/src/Configs.scala.

Inspect MysteryRocketConfig & answer the following questions. You should be able to find the answers or clues to the answers by grepping in $chipyard/generators/chipyard/src/main/scala/, $chipyard/generators/rocket-chip/src/main/scala/ or $chipyard/generators/testchipip/src/main/scala/.

4.1. How many bytes are in a block for the L1 ICache? How many sets are in the L1 ICache? Ways?

4.2. What type of L1 data memory does this config have? What is the size of the memory? What is the base address?

4.3. Does this config support custom boot? If yes, what is the custom boot address?

4.4. What accelerator does this config contain? Is the accelerator connected through MMIO or RoCC?

4.5. Does this config include an FPU (floating point unit)?

4.6. Does this config include a multiply-divide pipeline?

Next Step

page5. Elaborating Chisel

Last updated