我是使用 Chisel3 构建硬件组件的新手。现在,我正在尝试制作一个小模块,其中有 2 个输入(向量 A 和向量 B)和 1 个输出(输出 1 位无符号整数)。 Out 是 A 和 B 的点积。
我声明了模块 DotProduct 来进行计算。这是我的代码:
class RealDotProduct extends Module {
val io = IO(new Bundle {
val vectorA = Input(Vec(2, UInt(2.W)))
val vectorB = Input(Vec(2, UInt(2.W)))
val out = Output(UInt(1.W))
})
val product = 0.U
//Loop to calculate the inner (dot) product
for (i <- 0 until 2) {
product := product + io.vectorA(i) * io.vectorB(i)
}
io.out := product
}
而且,这是我的简单测试
class RealDotProductTests(c: RealDotProduct) extends PeekPokeTester(c) {
import scala.collection.immutable._
val in_a = Vector(0,1)
val in_b = Vector(2,3)
for (i <- 0 until 2) {
poke (c.io.vectorA(i), in_a(i))
poke (c.io.vectorB(i), in_b(i))
}
step(1)
expect(c.io.out, 3)
}
class RealDotProductTester extends ChiselFlatSpec {
behavior of "RealDotProduct"
backends foreach {backend =>
it should s"perform correct math operation on dynamic operand in $backend" in {
Driver(() => new RealDotProduct, backend)((c) => new RealDotProductTests(c)) should be (true)
}
}
}
object RealDotProductMain extends App {
iotesters.Driver.execute(args, () => new RealDotProduct) {
c => new RealDotProductTests(c)
}
}
我使用 sbt 运行测试并得到错误日志:
[info] [0.001] Elaborating design...
[error] chisel3.internal.ChiselException: Cannot reassign to read-only UInt<1>(0)
[error] ...
[error] at real_dot_product.RealDotProduct.$anonfun$new$1(RealDotProduct.scala:22)
[error] at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:158)
[error] at real_dot_product.RealDotProduct.<init>(RealDotProduct.scala:21)
[error] at real_dot_product.RealDotProductMain$.$anonfun$new$1(RealDotProductMain.scala:27)
[error] ychiselp... (Stack trace trimmed to user code only, rerun with --full-stacktrace if you wish to see the full stack trace)
[error] (run-main-0) java.lang.Exception: Failed to elaborate Chisel circuit
[error] java.lang.Exception: Failed to elaborate Chisel circuit
[error] at chisel3.iotesters.setupVerilatorBackend$.apply(VerilatorBackend.scala:286)
[error] at chisel3.iotesters.Driver$.$anonfun$execute$2(Driver.scala:55)
编码?
非常感谢你们。
最佳答案
答案1:
Chisel 正在组装代表您想要的硬件的连接图。您遇到的问题之一是您将多次连接到电线 product
.这在软件中是有意义的,但在硬件中则不然。
如果你要口头描述你想做什么,它可能是这样的,“将 inA 和 inB 中的每个元素配对并将它们相乘,然后将这些产品的总和相加。在 Chisel 中,一种方法是像这样。
val products = io.vectorA.zip(io.vectorB).map { case (a, b) => a * b }
val sum = product.reduce { case (a, b) => a + b }
io,out := sum
zip 将两个输入的元素配对
vec
s。该映射将每对值转换为一系列产品。然后你可以用reduce总结这些产品。您的 IO 端口的宽度也有一点问题。您的
out
端口没有足够的位来包含两个向量的内积。 Chisel 可以处理一些关于计算需要多少位的工作,但对于 IO 端口,您仍然需要仔细考虑需要多少位。很快,随着您对使用集合的 scala 习惯用法(例如
Vec
、 Seq
)更加熟悉,您将能够编写更多此类模块简而言之,类似:
io.out := io.vectorA.zip(io.vectorB).map(_ * _).reduce(_ + _)
答案2:
只需在测试器中编写一个函数来计算该值。纠正它的基本方法是
变量总和 = 0
for(i <- in_a.indices) {
总和 += (in_a(i) * in_b(i))
}
...
期望(c.io.out,总和)
你可以做一些更花哨的事情。关于输出的位宽。它可能应该足够大以处理您期望从任意输入的计算中获得的最大值。
关于scala - 使用 Chisel3 的两个信号 4 位之间的内积(点积。),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59091338/