首页 > 解决方案 > "for-loop" 减少 Chisel3.2 上的编码

问题描述

我想用 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”来编码冗余部分。

标签: chisel

解决方案


这段代码有几个小问题:

  • 通常我们在Scala中以小写字母开头命名变量,这主要是样式,但在某些情况下它确实具有语义意义(如模式匹配)
  • 方括号仅用于类型参数(如 Java 泛型),索引在 Scala 中使用普通括号
  • Bools 的输入 Vec 通常定义为:(val req = Input(Vec(numInputs, Bool()))假设import chisel3._,但这也适用于Chisel._Chisel 3.2)
  • ifelse用于静态参数化(即在硬件细化时),而when.otherwise用于动态逻辑(例如,实际多路复用器)
  • UInt适用于硬件类型,如果您有静态参数(如numInputs),请使用 ScalaInt

除了少量的语法内容之外,正确编写此代码最棘手的部分是了解仅在化时(即 Scala 程序生成硬件时)运行的 Scala 构造与硬件中实际显示的构造之间的区别. 我建议从 chisel-users 邮件列表中阅读此线程,以了解有关其中一些内容的更多上下文: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)

推荐阅读