summaryrefslogtreecommitdiff
path: root/chiselFrontend
diff options
context:
space:
mode:
authorRichard Lin2019-03-25 14:04:31 -0700
committerGitHub2019-03-25 14:04:31 -0700
commit1f8a5862c9b1642757af9f2dc0a34532c0a342a6 (patch)
tree0963b2b43d887ff71f0ffc05c25b90fc76afb02f /chiselFrontend
parent9cc5a7d567e4a3038dbb2f603aa44d1d435967a1 (diff)
Check field referential equality in autoclonetype (#1047)
Diffstat (limited to 'chiselFrontend')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala36
1 files changed, 24 insertions, 12 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
index 65939ef7..b2f01c2a 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
@@ -658,6 +658,22 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
throw new AutoClonetypeException(s"Unable to automatically infer cloneType on $clazz: $desc")
}
+ def validateClone(clone: Bundle, equivDiagnostic: String): Unit = {
+ if (!clone.typeEquivalent(this)) {
+ autoClonetypeError(s"Automatically cloned $clone not type-equivalent to base $this. " + equivDiagnostic)
+ }
+
+ for ((name, field) <- elements) {
+ if (clone.elements(name) eq field) {
+ autoClonetypeError(s"Automatically cloned $clone has field $name aliased with base $this." +
+ " In the future, this can be solved by wrapping the field in Field(...)," +
+ " see https://github.com/freechipsproject/chisel3/pull/909." +
+ " For now, ensure Chisel types used in the Bundle definition are passed through constructor arguments," +
+ " or wrapped in Input(...), Output(...), or Flipped(...) if appropriate.")
+ }
+ }
+ }
+
val mirror = runtimeMirror(clazz.getClassLoader)
val classSymbolOption = try {
Some(mirror.reflect(this).symbol)
@@ -741,10 +757,7 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
clone match {
case Some(clone) =>
clone._outerInst = this._outerInst
- if (!clone.typeEquivalent(this)) {
- autoClonetypeError(s"automatically cloned $clone not type-equivalent to base." +
- " Constructor argument values were not inferred, ensure constructor is deterministic.")
- }
+ validateClone(clone, "Constructor argument values were not inferred, ensure constructor is deterministic.")
return clone.asInstanceOf[this.type]
case None =>
}
@@ -781,6 +794,8 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
try {
val clone = ctors.head.newInstance(outerClassInstance.get._2).asInstanceOf[this.type]
clone._outerInst = this._outerInst
+
+ validateClone(clone, "Outer class instance was inferred, ensure constructor is deterministic.")
return clone
} catch {
case e @ (_: java.lang.reflect.InvocationTargetException | _: IllegalArgumentException) =>
@@ -844,14 +859,11 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
val clone = classMirror.reflectConstructor(ctor).apply(ctorParamsVals:_*).asInstanceOf[this.type]
clone._outerInst = this._outerInst
- if (!clone.typeEquivalent(this)) {
- // scalastyle:off line.size.limit
- autoClonetypeError(s"Automatically cloned $clone not type-equivalent to base $this." +
- " Constructor argument values were inferred: ensure that variable names are consistent and have the same value throughout the constructor chain," +
- " and that the constructor is deterministic.")
- // scalastyle:on line.size.limit
- }
-
+ validateClone(clone,
+ "Constructor argument values were inferred:" +
+ " ensure that variable names are consistent and have the same value throughout the constructor chain," +
+ " and that the constructor is deterministic."
+ )
clone
}