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?
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