“ for-loop”以减少在Chisel3.2上的编码

时间:2019-10-10 15:40:41

标签: chisel

我想使用for循环来编写冗​​余部分。

编码。

//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 个答案:

答案 0 :(得分:2)

此代码存在一些小问题:

  • 通常我们在Scala中以小写字母开头的变量被命名,这主要是样式,但是在某些情况下(例如模式匹配)它确实具有语义含义
  • 方括号仅用于类型参数(例如Java泛型),索引在Scala中使用普通括号
  • 布尔的输入Vec通常定义为:val req = Input(Vec(numInputs, Bool()))(假设import chisel3._,但对于凿子3.2,这也应在Chisel._中起作用)
  • ifelse用于静态参数化(即,在硬件制造时),而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和连接混合在一起,我将手动展开此循环以说明其功能:

    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 :(得分:1)

我同意@jkoenig所说的一切。 在另一个假设杰克的IO结构的示例中,有时候我喜欢 将foldLeftwhen / 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
  }

whenelsewhen都返回一个WhenClause,可以将其与foldLeft一起使用以继续添加子句。