如何使单个 Rocket 磁贴与系统的其余部分异步

How do I make an individual Rocket tile asynchronous to the rest of the system

我有一个多核火箭芯片系统。但是我希望其中一个火箭瓦片与其余的不同步。

我们正在尝试通过以下方式做到这一点:

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())}
  }
})

所以这就是 hartId = 2 的哈特应该是异步的,其余的应该是同步的。

以上内容添加到我们的配置后,似乎没有任何作用。

但是,如果我使用 src/main/scala/subsystem/Config.scala 中的 WithAsynchronousRocketTiles,那么我会将所有图块转换为异步。

那么,我将如何只制作一个图块?

根据杰克的建议更新:

直接尝试该代码给出了:

[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

这令人惊讶。所以我想我可能需要做 up() 事情并尝试了这个:

  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()) }
    }
  }

但是这会导致 elab 错误:

[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(RocketSubsystem.scala:41)
[error]         at scala.collection.TraversableLike.$anonfun$map(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)

所以仍然停留在如何修改这个原始 RocketCrossingParams 和 return 的基础上。

正在查看definition of RocketCrossingKey:

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

您会注意到类型是 Seq[RocketCrossingParams]。这意味着(尽管我可能是错的),我们每个图块有 1 RocketCrossingParams。在您的代码片段中,您只查看 this Seq 的第一个(通过 .head)检查它的 hartId 是否等于 2,如果是,则迭代所有RocketCrossingKeys 并将它们设置为 AsynchronousCrossing.

尝试类似下面的方法,我们在其中迭代它们,只用 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())
  }
}

编辑: 我错过了同时存在 RocketCrossingKeyRocketTilesKey

的事实

所以这里的问题是有两个并行的Seq参数:

  • RocketTilesKey 这给了我们 RocketTileParams,每个图块 1 个
  • RocketCrossingKey 这给了我们 RocketCrossingParams,每个方块 1 个 或者 如果只有 1 个,它适用于所有

也有可能没有RocketTileParams包含hartId == 2,所以让我们妥善处理:

  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