Scala/Chisel 中的函数式 for 循环
Posted
技术标签:
【中文标题】Scala/Chisel 中的函数式 for 循环【英文标题】:Functional for loop in Scala/Chisel 【发布时间】:2020-05-23 05:53:55 【问题描述】:我正在尝试找到以下算法的等效功能(不是真正的 Scala 或 Chisel 语法):
val x = Wire(Vec(n, UInt(L.W)))
val z = Wire(UInt(L.W))
var y = 0;
for (i <- 0 to (L-1))
y = 0;
for (j <- 0 to (n-1))
y = y || x(j, i)
z(i) = y;
原来的问题
我有n
总线,每个总线都有L
线。我想创建一个OR
门,它具有来自每条总线的相应位并产生输出。我知道的归约运算符在单总线上工作。例如,我可以使用x(1).orR
创建一个或门,但如何在总线阵列上实现这一点。我假设 Chisel 需要所有与硬件相关的行为模型才能在本质上起作用。所以,我的问题有两个:
-
我是否总是需要使用函数式编程在 Chisel 中编写行为模型?
我能否创建一个功能性的 for 循环来实现上述目标。
【问题讨论】:
查看 Kamyar 对主要问题的回答。我只想提一下,当您编写 Chisel 时,您不是在编写行为模型。相反,您正在编写一个在执行时生成硬件的程序。 Chisel 提供像Reg
和 Wire
这样的原语以及像 UInt
、Vec
和 Bundle
这样的硬件类型。您的 Scala 代码是一个运行的程序,将这些原语与对它们的操作组合在一起(如按位或:|
)以构建我们作为 Verilog 发出的硬件图。希望这会有所帮助!
@JackKoenig 所以你的意思是我不能任意定义使用def
的方法来实现组合逻辑并期望Chisel 产生优化的硬件?换句话说,在描述硬件时,我们应该根据 Reg、RegNext 等所谓的 Chisel 原语来设计硬件?我假设 reduce 函数本身是一种被建模为 OR 门的行为。
您可以编写任意 Scala 组合 Chisel 原语,它会生成硬件。 Chisel 将执行简单的优化,但它将真正的优化留给您的标准综合流程。当我说 Chisel 不是行为综合时,我的意思是它不是分析 Scala AST 并尝试生成硬件。相反,它只是运行 Scala 程序,有效地展开诸如 for 循环之类的事情。 Chisel 本身不进行综合,它只是一个库,提供设计人员可以用来构建自己的抽象的原语。
这是我去年在波特兰 Latch Up 的一次演讲,我试图用一个详细的例子来解释这一点:youtube.com/watch?v=dbOi_Gboi_0
【参考方案1】:
z := x.reduce(_ | _)
或使用 tree reduction 以获得更有效的硬件描述:
io.z := io.x.reduceTree(_ | _)
在此处查看生成的 Verilog: https://scastie.scala-lang.org/kammoh/lxOjBBtXTJ69bqgYVClexw/2
Scala 是一种多范式编程语言,它支持函数式、面向对象甚至命令式模型。您不必必须在 Chisel 中使用函数式编程范式,但它绝对可以让您的代码更加优雅和可读。
【讨论】:
很好的答案,谢谢 Kamyar。我只想指出,虽然reduceTree
使用的节点更少,因此在 Verilog 中看起来更好,但它的合成应该与线性 reduce
完全相同。
感谢@JackKoenig!我同意综合工具可能会通过两种描述推断出相同的硬件(这就是为什么我说更有效的硬件“描述”而不是硬件),但我认为生成的硬件可能也可能不同取决于工具所施加的优化工作的质量和选择级别?【参考方案2】:
我不做 Chisel,所以我无法测试它,但我认为没有那些讨厌的可变变量,它会做同样的事情。
(0 until L).foldLeft((Wire(Vec(n,UInt(L.W))), Wire(UInt(L.W))))
case ((x,z),i) =>
z(i) = (0 until n).foldLeft(0)case (y,j) => y || x(j,i)
【讨论】:
以上是关于Scala/Chisel 中的函数式 for 循环的主要内容,如果未能解决你的问题,请参考以下文章
在 Scala/Chisel 中使用类型参数覆盖/重载运算符