如何使单个 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,如果是,则迭代所有RocketCrossingKey
s 并将它们设置为 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())
}
}
编辑: 我错过了同时存在 RocketCrossingKey
和 RocketTilesKey
的事实
所以这里的问题是有两个并行的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
我有一个多核火箭芯片系统。但是我希望其中一个火箭瓦片与其余的不同步。
我们正在尝试通过以下方式做到这一点:
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,如果是,则迭代所有RocketCrossingKey
s 并将它们设置为 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())
}
}
编辑: 我错过了同时存在 RocketCrossingKey
和 RocketTilesKey
所以这里的问题是有两个并行的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