两个信号之间的内积(点积)使用Chisel3



我是使用 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:您能否告诉我问题出在哪里 编码?
  • 问题 2:如果我想用向量A 和向量 B 的随机值运行许多测试,我应该在期望 (c.io.out,3(中替换什么?

非常感谢大家。

答案 1: 凿子正在组装一个代表所需硬件的连接图。您遇到的问题之一是您多次将事物连接到电线product。这在软件中可能有意义,但在硬件中则不那么有意义。

如果你要口头描述你想做什么,它可能是这样的,"将inA和inB的每个元素配对并将它们相乘,然后将这些产品的总和相加。在凿子中,一种方法是这样的。

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的元素配对。映射将每对值转换为一系列产品。然后,您可以使用reduce总结这些产品。

IO端口的宽度也有一点问题。您的out端口没有足够的位来包含两个向量的内积。Chisel 可以处理一些关于计算需要多少位的工作,但对于 IO 端口,您仍然需要仔细考虑您想要多少位。

很快,随着您对使用集合的scala习语(例如,VecSeq(变得更加熟悉,您将能够编写更多此类模块 简而言之,像这样:

io.out := io.vectorA.zip(io.vectorB).map(_ * _).reduce(_ + _)

答案2: 只需在测试器中编写一个函数即可计算值。纠正它的基本方法是类似

变量总和 = 0 for(i <- in_a.indices( { 总和 += (in_a(i( * in_b(i(( }

。 期望(首席信息输出,总和(

你可以做一些更花哨的事情。关于输出的位宽。它可能应该足够大,以处理您期望从任意输入的计算中获得的最大值。

最新更新