引用未完全初始化
Reference is not fully initialized
我有一个如下所示的模块:
class ComputationIO[T <: Data](val OperandType: T) extends Bundle {
val data = OperandType.cloneType
}
class Computation [T <: Data] (OperandType: T) extends Module {
val io = IO( new Bundle {
val in = Input(new ComputationIO(OperandType))
})
// REST OF THE CODE HERE...
}
而且,我正在实例化 Computation
,如下所示:
val compUnit = for (i <- 0 until nParal) yield {
val Comp = Module(new Computation(UInt(32.W)))
Comp
}
然而,尽管我将 UInt(32.W)
传递给构造函数,它给了我以下 error:
firrtl.passes.CheckInitialization$RefNotInitializedException:Reference compUnit is not fully initialized.
[error] : compUnit.io.in.OperandType <= VOID
我可以通过删除 IO class 中的 val
并覆盖 cloneType
来解决问题,如下所示:
class ComputationIO[T <: Data](OperandType: T) extends Bundle {
val data = OperandType.cloneType
override def cloneType = new ComputationIO(OperandType).asInstanceOf[this.type ]
}
但是,我想知道第一种方法的问题是什么?构造函数已初始化。因此,not fully initialized
错误没有意义。
谢谢
另一个答案中链接的 documentation 提到了这一点,但我想强调一点:
The only caveat is if you are passing something of type Data as a “generator” parameter, in which case you should make it a private val.
这是因为如果您将 class 参数设置为 val
,它将成为 class 的 public 字段。 Bundle
的硬件字段定义为“类型 Data
的 class 的 public 字段”。因此,val OperandType
是 class 的一个字段,它与写作相同:
class ComputationIO[T <: Data](_operandType: T) extends Bundle {
val OperandType = _operandType
val data = OperandType.cloneType
}
事实上,您只需要在 OperandType
上调用 cloneType
,因为您得到的字段别名是 OperandType
和 data
是完全相同的对象。
这显然只是一个问题,因为您无意中将 OperandType
作为 Bundle 的 public 字段。
您可以通过将其设为 private val
来处理此问题,这不会使其成为 Bundle
:
的字段
class ComputationIO[T <: Data](private val OperandType: T) extends Bundle {
val data = OperandType // note .cloneType not necessary
}
请注意,从 Chisel v3.4.3 开始,可选择加入 Autoclonetype2,它不需要参数为 vals 即可推断克隆类型,您可以查看 release notes 了解更多信息。 Autoclonetype2 将成为 Chisel v3.5.0 中的默认值(尚未发布)。
我有一个如下所示的模块:
class ComputationIO[T <: Data](val OperandType: T) extends Bundle {
val data = OperandType.cloneType
}
class Computation [T <: Data] (OperandType: T) extends Module {
val io = IO( new Bundle {
val in = Input(new ComputationIO(OperandType))
})
// REST OF THE CODE HERE...
}
而且,我正在实例化 Computation
,如下所示:
val compUnit = for (i <- 0 until nParal) yield {
val Comp = Module(new Computation(UInt(32.W)))
Comp
}
然而,尽管我将 UInt(32.W)
传递给构造函数,它给了我以下 error:
firrtl.passes.CheckInitialization$RefNotInitializedException:Reference compUnit is not fully initialized.
[error] : compUnit.io.in.OperandType <= VOID
我可以通过删除 IO class 中的 val
并覆盖 cloneType
来解决问题,如下所示:
class ComputationIO[T <: Data](OperandType: T) extends Bundle {
val data = OperandType.cloneType
override def cloneType = new ComputationIO(OperandType).asInstanceOf[this.type ]
}
但是,我想知道第一种方法的问题是什么?构造函数已初始化。因此,not fully initialized
错误没有意义。
谢谢
另一个答案中链接的 documentation 提到了这一点,但我想强调一点:
The only caveat is if you are passing something of type Data as a “generator” parameter, in which case you should make it a private val.
这是因为如果您将 class 参数设置为 val
,它将成为 class 的 public 字段。 Bundle
的硬件字段定义为“类型 Data
的 class 的 public 字段”。因此,val OperandType
是 class 的一个字段,它与写作相同:
class ComputationIO[T <: Data](_operandType: T) extends Bundle {
val OperandType = _operandType
val data = OperandType.cloneType
}
事实上,您只需要在 OperandType
上调用 cloneType
,因为您得到的字段别名是 OperandType
和 data
是完全相同的对象。
这显然只是一个问题,因为您无意中将 OperandType
作为 Bundle 的 public 字段。
您可以通过将其设为 private val
来处理此问题,这不会使其成为 Bundle
:
class ComputationIO[T <: Data](private val OperandType: T) extends Bundle {
val data = OperandType // note .cloneType not necessary
}
请注意,从 Chisel v3.4.3 开始,可选择加入 Autoclonetype2,它不需要参数为 vals 即可推断克隆类型,您可以查看 release notes 了解更多信息。 Autoclonetype2 将成为 Chisel v3.5.0 中的默认值(尚未发布)。