1

I have a multicore rocket-chip system. However I'd like one of those rocket tiles to be asynchronous from the rest.

We're trying to do that with the following:

class WithTilesCrossing extends Config((site, here, up) => {
  case RocketCrossingKey => site(RocketTilesKey).head.hartId match {
    case 2 => up(RocketCrossingKey) map { r =>
      r.copy(crossingType = AsynchronousCrossing(),
             master = TileMasterPortParams())}
    case _ => up(RocketCrossingKey) map { r =>
      r.copy(crossingType = SynchronousCrossing(BufferParams(1)),
             master = TileMasterPortParams())}
  }
})

So that is the hart with hartId = 2 should be async, the rest should be synchronous.

The above, when added to our config, doesn't appear to do anything.

However, if I use the WithAsynchronousRocketTiles from src/main/scala/subsystem/Config.scala then I get all of the tiles converted to async.

So, how would I do just a single tile?

Update based on Jack's suggestion:

Trying that code straight up gave:

[error] Config.scala:189:16: not found: value crossingType
[error]         r.copy(crossingType = AsynchronousCrossing(),
[error]                ^
[error] Config.scala:190:11: not found: value master
[error]           master = TileMasterPortParams())
[error]           ^
[error] Config.scala:192:16: not found: value crossingType
[error]         r.copy(crossingType = SynchronousCrossing(BufferParams(1)),
[error]                ^
[error] Config.scala:193:11: not found: value master
[error]           master = TileMasterPortParams())
[error]           ^
[error] four errors found

Which is surprising. So I thought I might need to do the up() thing and tried this:

  case RocketCrossingKey => site(RocketTilesKey).map { r =>
    r.hartId match {
      case 2 => up(RocketCrossingKey) map { k => k.copy(crossingType = AsynchronousCrossing(), master = TileMasterPortParams()) }
      case _ => up(RocketCrossingKey) map { k => k.copy(crossingType = SynchronousCrossing(BufferParams(1)), master = TileMasterPortParams()) }
    }
  }

However that results in an elab error:

[error] Caused by: java.lang.ClassCastException: scala.collection.immutable.$colon$colon cannot be cast to freechips.rocketchip.subsystem.RocketCrossingParams
[error]         at freechips.rocketchip.subsystem.HasRocketTiles.$anonfun$rocketTiles$1(RocketSubsystem.scala:41)
[error]         at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:234)
[error]         at scala.collection.immutable.List.foreach(List.scala:389)
[error]         at scala.collection.TraversableLike.map(TraversableLike.scala:234)
[error]         at scala.collection.TraversableLike.map$(TraversableLike.scala:227)
[error]         at scala.collection.immutable.List.map(List.scala:295)
[error]         at freechips.rocketchip.subsystem.HasRocketTiles.$init$(RocketSubsystem.scala:41)
[error]         at freechips.rocketchip.subsystem.RocketSubsystem.<init>(RocketSubsystem.scala:70)

So still stuck on how to modify this original RocketCrossingParams on a per-tile basis and return it.

jbaxter
  • 182
  • 10

1 Answers1

1

Looking at the definition of RocketCrossingKey:

case object RocketCrossingKey extends Field[Seq[RocketCrossingParams]](List(RocketCrossingParams()))

You'll notice that the type is Seq[RocketCrossingParams]. This implies (although I may be wrong), that we have 1 RocketCrossingParams per tile. In your code snippet, you are only looking at the first of the this Seq (via .head) checking if it's hartId is equal to 2, and then if so, iterating on all of the RocketCrossingKeys and setting them to AsynchronousCrossing.

Try something like the following where we iterate on them and only replace the index for the one with hartId == 2:

case RocketCrossingKey => site(RocketTilesKey).map { r =>
  if (r.hartId == 2) { // or you can match on it, whatever
    r.copy(crossingType = AsynchronousCrossing(),
           master = TileMasterPortParams())
  } else {
    r.copy(crossingType = SynchronousCrossing(BufferParams(1)),
           master = TileMasterPortParams())
  }
}

EDIT: I missed the fact that there is both RocketCrossingKey and RocketTilesKey

So the issue here is that there are two parallel Seqs of parameters:

  • RocketTilesKey which gives us RocketTileParams, 1 for each tile
  • RocketCrossingKey which gives us RocketCrossingParams, 1 for each tile OR if there's only 1, it applies to all

It's also possible that there is no RocketTileParams containing hartId == 2, so let's handle everything appropriately:

  case RocketCrossingKey =>
    val tileParams = site(RocketTilesKey)
    val crossingParams = site(RocketCrossingKey)

    // One might assume hartId 2 == index 2 but that may not be the case
    // Also there may not even *be* a tile with hartId == 2
    val indexOfHartId2: Option[Int] =
      tileParams.zipWithIndex.collectFirst { case (r, idx) if r.hartId == 2 => idx }

    indexOfHartId2.map { idx =>
      // This duplicates logic from HasTiles.perTileOrGlobalSetting
      // If there's only 1, it applies to all
      val crossings = site(RocketCrossingKey) match {
        case Seq(one) => List.fill(tileParams.size)(one)
        case many     => many
      }
      // Back to the original answer using the proper index for hartId == 2
      crossings.zipWithIndex.map { case (c, i) =>
        if (i == idx) { // or you can match on it, whatever
          c.copy(crossingType = AsynchronousCrossing(),
                 master = TileMasterPortParams())
        } else {
          c.copy(crossingType = SynchronousCrossing(BufferParams(1)),
                 master = TileMasterPortParams())
        }
      }
    }.getOrElse(crossingParams) // If we don't even have hardId == 2, return original value
Jack Koenig
  • 5,840
  • 15
  • 21
  • 1
    Ah, that makes sense, thanks very much! However, my Scala/Chisel skills are not able to massage your suggestion into something which works. Trying your code as-is says it can't find `crossingType` or `master`?? (Sorry the following is mangled by stackoverflow's awful formatting rules in these comments :-/) `[error] Config.scala:189:16: not found: value crossingType [error] r.copy(crossingType = AsynchronousCrossing(), [error] ^ [error] Config.scala:190:11: not found: value master [error] master = TileMasterPortParams()) [error] ^` – jbaxter Mar 21 '20 at 00:26