diff options
| author | Richard Lin | 2019-03-25 14:04:31 -0700 |
|---|---|---|
| committer | GitHub | 2019-03-25 14:04:31 -0700 |
| commit | 1f8a5862c9b1642757af9f2dc0a34532c0a342a6 (patch) | |
| tree | 0963b2b43d887ff71f0ffc05c25b90fc76afb02f /chiselFrontend/src | |
| parent | 9cc5a7d567e4a3038dbb2f603aa44d1d435967a1 (diff) | |
Check field referential equality in autoclonetype (#1047)
Diffstat (limited to 'chiselFrontend/src')
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 36 |
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 } |
