"для цикла", чтобы уменьшить кодирование на Chisel3.2 - PullRequest
2 голосов
/ 10 октября 2019

Я хочу закодировать с помощью for-loop для избыточной части.

Кодирование.

//Priority Encoder
class P_Encoder(NumInputs: UInt) extends Module {
    val io = new Bundle {
        val Req[NumInputs]          = Bool(INPUT)                   //Requests
        val Rls[NumInputs]          = Bool(INPUT)                   //Releases
        val Grant[NumInputs]        = UInt(OUTPUT(log(NumInputs)))  //Grants
    }

    val cnt = 0
    for (i<-0 to NumInputs-1) {
        when (io.Req[i] & !io.Rls[i]) {
            cnt         := cnt + 1.W
            io.Grant[i] = cnt
        }
        else {
            io.Grant[i] = 0.W
        }
    }
}

Я хочу закодировать с помощью "for-loop" для кодирования избыточной части.

Ответы [ 2 ]

2 голосов
/ 10 октября 2019

Есть несколько незначительных проблем с этим кодом:

  • Обычно мы называем переменные, начинающиеся со строчной буквы в Scala, это в основном стиль, но он имеет семантическое значение в определенных обстоятельствах(например, сопоставление с образцом)
  • Квадратные скобки используются только для параметров типа (например, обобщений Java), при индексировании в Scala используются нормальные скобки
  • Входной Vec of Bools обычно определяется как: val req = Input(Vec(numInputs, Bool()))(при условии import chisel3._, но это также должно работать в Chisel._ для долота 3.2)
  • if и else используются для статической параметризации (т. е. во время разработки аппаратного обеспечения), тогда как when и.otherwise используются для динамической логики (например, фактические муксы)
  • UInt для типов оборудования, если у вас есть статический параметр (например, numInputs), используйте Scala Int

Помимо мелких синтаксических вещей, самая хитрая часть правильного понимания этого кода - это понимание различия между конструкциями Scala, которые выполняются только на разработке Тиме (т.е. когда программа Scala генерирует аппаратное обеспечение), по сравнению с тем, что фактически отображается в аппаратном обеспечении. Я бы посоветовал прочитать эту ветку из списка рассылки пользователей зубил для получения дополнительной информации о некоторых вещах: https://groups.google.com/d/msg/chisel-users/gRoNnH-Y5hE/ynDCtmNPCAAJ

Я немного запутался относительно того, какое значение io.grant должно получить,но я предполагаю, что это должен быть индекс с самым высоким приоритетом io.req. Вот непроверенная версия вашего кода, которую я считаю должен работать и делать то, что вы хотите:

//Priority Encoder
class P_Encoder(numInputs: Int) extends Module {
    // We wrap ports in IO
    val io = IO(new Bundle {
        val req        = Input(Vec(numInputs, Bool()))
        val rls        = Input(Vec(numInputs, Bool()))
        val grant      = Output(UInt(log2Up(numInputs).W))
    })
    io.grant := 0.U // default grant value
    // Due to Chisel last connect semantics, the last connection wins
    // Thus the highest index will have priority
    for (i <- 0 to numInputs - 1) {
        when (io.req(i) && !io.rls(i)) {
            io.grant := i.U
        }
    }
}

Этот код хитрый, потому что он смешивает цикл разработки for с оборудованием when s и соединения, я собираюсь вручную развернуть этот цикл, чтобы проиллюстрировать, что он делает:

    io.grant := 0.U
    when (io.req(0) && !io.rls(0)) {
        io.grant := 0.U
    }
    when (io.req(1) && !io.rls(1)) {
        io.grant := 1.U
    }
    when (io.req(2) && !io.rls(2)) {
        io.grant := 2.U
    }
    ...

В качестве альтернативы, мы можем просто повторно использовать встроенную утилиту PriorityEncoder, если нам нужно

import chisel3.util.PriorityEncoder
val enables = io.req.zip(io.rls).map { case (x, y) => x && !y }
// PriorityEncoder gives priority to *lowest* order bit
io.grant := PriorityEncoder(enables)
1 голос
/ 10 октября 2019

Я согласен со всем, что говорит @jkoenig. В другом примере, предполагающем структуру ввода-вывода Джека, иногда мне нравится использовать foldLeft в сочетании с when / elsewhen

io.rel.zip(io.req).zipWithIndex.foldLeft(when(false.B){}) { case (lastWhen,((req, rel), index)) =>
    lastWhen.elsewhen(req && !rel) {
      io.grant := index.U
    }
  } otherwise {
    io.grant := 0.U
  }

when и elsewhen, оба возвращают WhenClause, чтоможет быть использован с foldLeft для продолжения добавления предложений.

...