Как сделать отдельную плитку Rocket асинхронной для остальной системы - PullRequest
1 голос
/ 20 марта 2020

У меня многоядерная система с чипом ракеты. Однако я бы хотел, чтобы одна из этих ракетных плиток была асинхронной по отношению к остальным.

Мы пытаемся сделать это следующим образом:

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 должно быть asyn c, остальные должны быть синхронными.

Вышеуказанное при добавлении в нашу конфигурацию, похоже, ничего не делает.

Однако, если я использую WithAsynchronousRocketTiles из src/main/scala/subsystem/Config.scala тогда я получаю все плитки, преобразованные в асинхронные c.

Итак, как бы мне сделать только одну плитку?

Обновление по предложению Джека:

Попробовав этот код, мы получили:

[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$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)

Так что все еще застрял на том, как изменить этот оригинал RocketCrossingParams для каждой плитки и верните его.

1 Ответ

1 голос
/ 20 марта 2020

Глядя на определение RocketCrossingKey:

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

Вы заметите, что типом является Seq[RocketCrossingParams]. Это подразумевает (хотя я могу ошибаться), что у нас 1 RocketCrossingParams на плитку. В своем фрагменте кода вы просматриваете только первый из этих 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())
  }
}

EDIT: Я упустил тот факт, что есть и RocketCrossingKey и RocketTilesKey

Итак, проблема в том, что есть два параллельных Seq s параметра:

  • 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
...