简体   繁体   English

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

[英]Inner product (Dot product .) between two signal 4 bits using Chisel3

I'm a fresher in using Chisel3 to build the hardware components.我是使用 Chisel3 构建硬件组件的新手。 Now, I'm trying to make a small module in which there are 2 inputs (vector A and vector B) and 1 outputs (out with 1 bits Unsigned Integer).现在,我正在尝试制作一个小模块,其中有 2 个输入(向量 A 和向量 B)和 1 个输出(输出为 1 位无符号整数)。 Out is a Dot Product of A and B. Out 是 A 和 B 的点积。

I declared the module DotProduct to make the calculation.我声明了模块 DotProduct 来进行计算。 Here is my code:这是我的代码:

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
}

And, here is my simple test而且,这是我的简单测试

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)
  }
}

I run the test using sbt and I got the error log:我使用 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)
  • Question 1: Could you please show me where is the problem in my coding?问题 1:能否请您告诉我编码中的问题在哪里?
  • Question 2: What should I replace 3 in expect(c.io.out,3) in case I want to run many test with random value for vectorA and vector B?问题2:我应该在的情况下更换3预期(c.io.out,3)我想运行许多测试与vectorA和随机值向量B?

Thanks a lot guys.非常感谢各位。

Answer1: Chisel is assembling a graph of connections representing the hardware you want.答案 1:Chisel 正在组装表示您想要的硬件的连接图。 One of the problems you have is that you are connecting things multiple times to the wire product .您遇到的问题之一是您多次将东西连接到电线product That can make sense in software but not so much in hardware.这在软件中可能有意义,但在硬件中则不然。

If you were to describe what you wanted to do verbally, it would probably be something like, "pair up each element from inA and inB and multiply them together, then add up the sum of those products. In Chisel one way to do this is like this.如果你要口头描述你想做什么,它可能是这样的,“将 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

The zip pairs up the elements of your two input vec s. zip 将您的两个输入vec的元素配对。 The map converts each pair of values to a sequence of products.该映射将每对值转换为一系列产品。 You can then sum up those products with reduce.然后你可以用reduce来总结这些产品。

You also have a bit of a problem with widths in your IO ports.您的 IO 端口的宽度也有一些问题。 Your out port does not have enough bits to contain the inner product of the two vectors.您的out端口没有足够的位来包含两个向量的内积。 Chisel can handle some of the work about how many bits you need for your computation, but for IO ports you still need to think carefully about how many bits you want. Chisel 可以处理有关计算需要多少位的一些工作,但是对于 IO 端口,您仍然需要仔细考虑您需要多少位。

Very soon, as you become more comfortable with the scala idioms for working with collections (things like, Vec , Seq ) you will be able write this kind of module even more succinctly, something like:很快,当您对使用集合(例如VecSeq类的东西)的 scala 习语变得更加熟悉时,您将能够更简洁地编写这种模块,例如:

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

Answer2: Just write a function in your tester to compute the value.答案 2:只需在测试仪中编写一个函数来计算值。 The basic way to right it would be something like纠正它的基本方法是这样的

var sum = 0 for(i <- in_a.indices) { sum += (in_a(i) * in_b(i)) } var sum = 0 for(i <- in_a.indices) { sum += (in_a(i) * in_b(i)) }

... expect(c.io.out, sum) ...期望(c.io.out,总和)

You could do something fancier.你可以做一些更有趣的事情。 In regards to the bit width of the out.关于输出的位宽。 It should probably be big enough to handle the largest value you expect from the computation for arbitrary inputs.它可能应该足够大以处理您期望从任意输入的计算中获得的最大值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM