Spinal无法克隆类(Spinal can’t clone class)

一、简介

当SpinalHDL想要通过cloneOf函数创建一个新的数据类型实例, 但是不能这样做时, 就会发生这个错误。出现这种情况的原因总是因为它无法检索Bundle的构造参数。

二、例子1

下述代码:

// cloneOf(this)无法检索用于构造自身的位宽
class RGB(width : Int) extends Bundle {
  val r, g, b = UInt(width bits)
}

class TopLevel extends Component {
  val tmp = Stream(new RGB(8)) // Stream需要cloneOf(new RGB(8))的功能
}

将会报错:

*** Spinal can't clone class spinal.tester.PlayDevMessages$RGB datatype
*** You have two way to solve that :
*** In place to declare a "class Bundle(args){}", create a "case class Bundle(args){}"
*** Or override by your self the bundle clone function
  ***
  Source file location of the RGB class definition via the stack trace
  ***

修复为:

case class RGB(width : Int) extends Bundle {
  val r, g, b = UInt(width bits)
}

class TopLevel extends Component {
  val tmp = Stream(RGB(8))
}

二、例子2

下列代码:

case class Xlen(val xlen: Int) {}

case class MemoryAddress()(implicit xlenConfig: Xlen) extends Bundle {
    val address = UInt(xlenConfig.xlen bits)
}

class DebugMemory(implicit config: Xlen) extends Component {
    val io = new Bundle {
        val inputAddress = in(MemoryAddress())
    }

    val someAddress = RegNext(io.inputAddress) // -> ERROR *****************************
}

报错:

[error] *** Spinal can't clone class debug.MemoryAddress datatype

在这种情况下, 一种解决方案是覆盖克隆函数来传播隐式参数。

case class MemoryAddress()(implicit xlenConfig: Xlen) extends Bundle {
  val address = UInt(xlenConfig.xlen bits)

  override def clone = MemoryAddress()
}

注意:我们需要克隆的是硬件的单元, 而不是最终在其中赋值的值

注意:另一种方法是使用ScopeProperty(请见”其他语言特性”章节中)