【发布时间】:2019-11-13 13:33:24
【问题描述】:
我正在学习凿子和火箭芯片。 火箭芯片在RVC.scala 中有一个使用 Seq 和 Cat 的代码。
val funct = Seq(0.U, 4.U, 6.U, 7.U, 0.U, 0.U, 2.U, 3.U)(Cat(x(12), x(6,5)))
但是当我像上面那样编写代码时,我得到了一个错误。 chisel 报告类型不匹配。
【问题讨论】:
标签: scala chisel rocket-chip
我正在学习凿子和火箭芯片。 火箭芯片在RVC.scala 中有一个使用 Seq 和 Cat 的代码。
val funct = Seq(0.U, 4.U, 6.U, 7.U, 0.U, 0.U, 2.U, 3.U)(Cat(x(12), x(6,5)))
但是当我像上面那样编写代码时,我得到了一个错误。 chisel 报告类型不匹配。
【问题讨论】:
标签: scala chisel rocket-chip
Scala 提供了一个非常强大的功能,称为Implicit Conversions。我将把它留给 StackOverflow 上的许多解释,以及谷歌可以找到的其他解释来解释细节和动机,但让我解释一下它们是如何在 Chisel 和 Rocket Chip 中使用的。
Scala 中的Ints(如3)等价于原始Java ints。如果您检查API docs,您将找不到任何函数def U,但在Chisel 中,我们能够将UInt 构造为3.U。这是通过一个名为fromIntToLiteral 的隐式转换 来完成的,它本质上允许我们定义def U,就好像它是在Scala 的Int 类本身上定义的一样。凭借import chisel3._,您正在导入fromIntToLiteral 并告诉Scala 编译器实际上,Int 确实 有一个名为U 的方法!
Rocket Chip 有一些作者认为有用的隐式转换。在这种情况下,freechips.rocketchip.util 包含定义 def apply(idx: UInt): T 的 SeqToAugmentedSeq,这里调用的函数*。本质上,Scala 编译器发现没有apply 方法期望在Seq 上定义UInt,因此它注意到SeqToAugmentedSeq 被导入作用域并提供了这样的方法。它进行了以下转换:
val funct = Seq(0.U, 4.U, 6.U, 7.U, 0.U, 0.U, 2.U, 3.U)(Cat(x(12), x(6,5)))
// The compiler turns this into:
val funct = (new SeqToAugmentedSeq(Seq(0.U, 4.U, 6.U, 7.U, 0.U, 0.U, 2.U, 3.U))).apply(Cat(x(12), x(6,5)))
我希望这会有所帮助!
*对象上的括号调用apply method。 myUInt(3) 等价于myUInt.apply(3)。
【讨论】:
这一行声明一个常量 Seq :
//idx:0 1 2 3 4 5 6 7
Seq(0.U, 4.U, 6.U, 7.U, 0.U, 0.U, 2.U, 3.U)
然后返回由索引Cat(x(12), x(6,5)) 给出的项目(UInt)。
x 应该被声明为和UInt 之前。如果我们声明为它:
val x = "b0001000011000001".U(16.W)
我们将有x(12) = 1.U 和x(6, 5) = 3.U(或“b11”.U)然后是Cat(x(12), x(6,5)) == "b111".U == 7.U
返回的索引是7,对应初始声明的序列Seq()中的3.U。
那么funct的值为:
val funct = 3.U
【讨论】: