scala - 使用 Chisel3 的两个信号 4 位之间的内积(点积。)

标签 scala hdl chisel

我是使用 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 的随机值运行许多测试,我应该用什么替换 expect(c.io.out,3) 中的 3?

  • 非常感谢你们。

    最佳答案

    答案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 习惯用法(例如 VecSeq )更加熟悉,您将能够编写更多此类模块
    简而言之,类似:
      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/

    相关文章:

    generics - 如何让 XStream 很好地输出 Scala 列表?我可以编写自定义转换器吗?

    compiler-construction - 有没有办法创建在硬件中实现的高级语言解释器?

    scala - 如何删除Chisel verilog后端生成的无用寄存器?

    什么都不做的Scala语法功能?

    scala - 带有 testkit sbt 的循环项目依赖项

    scala - 试图在 Scala 中动态分配一个类

    vhdl - 用于发送串行字节的简单 VHDL 测试平台程序?

    python - 如何在cocotb中强制使用python 3?

    scala - 如何在 I/O 端口中使用 chisel3.experimental.ChiselEnum?

    chisel - 当设计中有未连接的 IO 时收到警告