2
votes

I need to implement a custom type class for Complex DSP and Complex Ring operations. I'm aware about DspTools project, but purposely want to exclude it from consideration.

I've got a hardware module, which I want to instantiate with diff type classes: UInt, SInt, FixedPoint, Real and Complex(FixedPoint, FixedPoint).

Here's my minimal class:

class Complex[A <: Data, B <: Data] (val re:A, val im:B) extends Bundle {
  override def cloneType: this.type = new Complex(re, im).asInstanceOf[this.type]
}

object Complex {    
  def apply[A <: Data, B <: Data](re:A, im:B) = new Complex(re, im)  
  implicit def UInt2Complex(re:UInt, im:UInt) = Complex(re,im)
}

When I instantiate this with different data types from Chisel3.Core, the code compiles and works. However, when I try to do :

import chisel3.core.{FixedPoint => FP}
...

  val inType  = Complex ( FP(20.W,10.BP), FP(20.W,10.BP))
  val outType = Complex ( FP(20.W,10.BP), FP(20.W,10.BP))
...

I get the code compiled, but FIRRTL emits an error:

[info] using --backend-name verilator [info] chisel3.core.Binding$RebindingException: Attempted reassignment of binding to chisel3.core.FixedPoint@d [info] at chisel3.core.Data.binding_$eq(Data.scala:250)

What's wrong with this? How to fix the issue?

2
I wonder if part of your problem is that your binary point is larger than the width of your wires. While this possibility was discussed during the implementation of FixedPoint I don't think it was explicitly coded for or tested - Chick Markley
Sorry Chick, that was a typo - Tampler

2 Answers

2
votes

The issue is that Chisel needs fresh clones of any Data when it recursively calls cloneType, and you're simply passing re and im to the Complex constructor resulting in the exact same objects. Put a little more concretely:

val a = Complex(UInt(8.W), UInt(8.W))
val b = a.cloneType
a.re eq b.re // This will be true and it *must* not be

This is kind of an age old problem that we don't have a great solution to, in your case, you should call .cloneType on re and im in Complex.cloneType

I know you aren't using DSPTools, but it can still provide a reference and they do that: https://github.com/ucb-bar/dsptools/blob/fe8f9d08987f3a403f6281ba4face1c26b627b71/src/main/scala/dsptools/numbers/chisel_concrete/DspComplex.scala#L75

1
votes

Here's the actual minimalistic implementation, which worked for me. @jkoenig pointed me to the right direction. Thanks a lot!

class Complex[A <: Data, B <: Data] (val re:A, val im:B) extends Bundle {
  override def cloneType: this.type = new Complex(re.cloneType, im.cloneType).asInstanceOf[this.type]
}

object Complex {

  def apply[A <: Data, B <: Data](re:A, im:B):Complex[A,B] = {
    val real  = re.cloneType
    val imag  = im.cloneType
    new Complex(real,imag)
  }  
}