diff options
| author | Megan Wachs | 2021-10-05 10:27:18 -0700 |
|---|---|---|
| committer | GitHub | 2021-10-05 17:27:18 +0000 |
| commit | ce15ad50a5c175db06c3bba5e3bf46b6c5466c47 (patch) | |
| tree | bcec55dbb92bc827b3d3ec973481baa4d380c489 | |
| parent | 790a1806c7c5333cea15abbd2657fa893beb92c9 (diff) | |
Remove all Bundle cloneTypes and chiselRuntimeDeprecate its use (#2052)
* Remove all manual cloneTypes and make it chisel runtime deprecated to add one
* runtime deprecate cloneType with runtime reflection
* [Backport this commit] Bundle: add check that override def cloneType still works (will be made an error later)
* Plugin: make it an error to override cloneType and add a test for that
* Docs: can't compile the cloneType anymore
* BundleSpec: comment out failing test I cannot get to fail or ignore
Co-authored-by: Jack Koenig <koenig@sifive.com>
| -rw-r--r-- | core/src/main/scala/chisel3/Aggregate.scala | 4 | ||||
| -rw-r--r-- | docs/src/explanations/bundles-and-vecs.md | 65 | ||||
| -rw-r--r-- | no-plugin-tests/src/test/scala/chiselTests/NoPluginBundleSpec.scala | 36 | ||||
| -rw-r--r-- | plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala | 5 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/BitPat.scala | 1 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/Decoupled.scala | 6 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/Enum.scala | 1 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/Valid.scala | 2 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/AutoClonetypeSpec.scala | 1 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/BundleSpec.scala | 17 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala | 5 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/CompatibilitySpec.scala | 2 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/CompileOptionsTest.scala | 2 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/ComplexAssign.scala | 5 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/PrintableSpec.scala | 1 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/RecordSpec.scala | 1 |
16 files changed, 77 insertions, 77 deletions
diff --git a/core/src/main/scala/chisel3/Aggregate.scala b/core/src/main/scala/chisel3/Aggregate.scala index 17e46cb3..1892f7c2 100644 --- a/core/src/main/scala/chisel3/Aggregate.scala +++ b/core/src/main/scala/chisel3/Aggregate.scala @@ -1146,6 +1146,10 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { */ protected def _cloneTypeImpl: Bundle = { assert(Builder.allowReflectiveAutoCloneType, "reflective autoclonetype is disallowed, this should only happen in testing") + Builder.deprecated( + "The runtime reflection inference for cloneType (_cloneTypeImpl) is deprecated as of Chisel 3.5: " + + "Use the Compiler Plugin to infer cloneType" + ) // This attempts to infer constructor and arguments to clone this Bundle subtype without // requiring the user explicitly overriding cloneType. import scala.language.existentials diff --git a/docs/src/explanations/bundles-and-vecs.md b/docs/src/explanations/bundles-and-vecs.md index 78626c42..e683667d 100644 --- a/docs/src/explanations/bundles-and-vecs.md +++ b/docs/src/explanations/bundles-and-vecs.md @@ -128,48 +128,19 @@ class ModuleProgrammaticMixedVec(x: Int, y: Int) extends Module { } ``` -### A note on `cloneType` +### A note on `cloneType` (For Chisel < 3.5) -Since Chisel is built on top of Scala and the JVM, it needs to know how to construct copies of bundles for various -purposes (creating wires, IOs, etc). If you have a parametrized bundle and Chisel can't automatically figure out how to -clone your bundle, you will need to create a custom `cloneType` method in your bundle. Most of the time, this is as -simple as `override def cloneType = (new YourBundleHere(...)).asInstanceOf[this.type]`. +NOTE: This section **only applies to Chisel before Chisel 3.5**. +As of Chisel 3.5, `Bundle`s should **not** `override def cloneType`, +as this is a compiler error when using the chisel3 compiler plugin for inferring `cloneType`. -Note that in the vast majority of cases, **this is not required** as Chisel can figure out how to clone most bundles -automatically. - -Here is an example of a parametrized bundle (`ExampleBundle`) that features a custom `cloneType`. - -```scala mdoc:silent -class ExampleBundle(a: Int, b: Int) extends Bundle { - val foo = UInt(a.W) - val bar = UInt(b.W) - override def cloneType = (new ExampleBundle(a, b)).asInstanceOf[this.type] -} - -class ExampleBundleModule(btype: ExampleBundle) extends Module { - val io = IO(new Bundle { - val out = Output(UInt(32.W)) - val b = Input(chiselTypeOf(btype)) - }) - io.out := io.b.foo + io.b.bar -} - -class Top extends Module { - val io = IO(new Bundle { - val out = Output(UInt(32.W)) - val in = Input(UInt(17.W)) - }) - val x = Wire(new ExampleBundle(31, 17)) - x := DontCare - val m = Module(new ExampleBundleModule(x)) - m.io.b.foo := io.in - m.io.b.bar := io.in - io.out := m.io.out -} -``` - -Generally cloneType can be automatically defined if all arguments to the Bundle are vals e.g. +Since Chisel is built on top of Scala and the JVM, +it needs to know how to construct copies of `Bundle`s for various +purposes (creating wires, IOs, etc). +If you have a parametrized `Bundle` and Chisel can't automatically figure out how to +clone it, you will need to create a custom `cloneType` method in your bundle. +In the vast majority of cases, **this is not required** +as Chisel can figure out how to clone most `Bundle`s automatically: ```scala mdoc:silent class MyCloneTypeBundle(val bitwidth: Int) extends Bundle { @@ -178,13 +149,15 @@ class MyCloneTypeBundle(val bitwidth: Int) extends Bundle { } ``` -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`. +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`, and define a `cloneType` method with +`override def cloneType = (new YourBundleHere(...)).asInstanceOf[this.type]`. -For example, consider the following Bundle. Because its `gen` variable is not a `private val`, the user has to -explicitly define the `cloneType` method. +For example, consider the following `Bundle`. Because its `gen` variable is not a `private val`, the user has to +explicitly define the `cloneType` method: -```scala mdoc:silent +<!-- Cannot compile this because the cloneType is now an error --> +```scala import chisel3.util.{Decoupled, Irrevocable} class RegisterWriteIOExplicitCloneType[T <: Data](gen: T) extends Bundle { val request = Flipped(Decoupled(gen)) @@ -196,8 +169,10 @@ class RegisterWriteIOExplicitCloneType[T <: Data](gen: T) extends Bundle { We can make this this infer cloneType by making `gen` private since it is a "type parameter": ```scala mdoc:silent +import chisel3.util.{Decoupled, Irrevocable} class RegisterWriteIO[T <: Data](private val gen: T) extends Bundle { val request = Flipped(Decoupled(gen)) val response = Irrevocable(Bool()) } ``` + diff --git a/no-plugin-tests/src/test/scala/chiselTests/NoPluginBundleSpec.scala b/no-plugin-tests/src/test/scala/chiselTests/NoPluginBundleSpec.scala new file mode 100644 index 00000000..b73be483 --- /dev/null +++ b/no-plugin-tests/src/test/scala/chiselTests/NoPluginBundleSpec.scala @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chiselTests + +import chisel3._ +import chisel3.stage.ChiselStage +import chisel3.testers.BasicTester + + + +trait BundleSpecUtils { + + class BundleBaz(val w: Int) extends Bundle { + val baz = UInt(w.W) + // (if we don't have the val on the val w: Int then it is an Exception) + // Check that we get a runtime deprecation warning if we don't have this: + // override def cloneType = (new BundleBaz(w)).asInstanceOf[this.type] + } + +} + +class NoPluginBundleSpec extends ChiselFlatSpec with BundleSpecUtils with Utils { + + "No override def cloneType" should "give a runtime deprecation warning without compiler plugin" in { + class MyModule extends MultiIOModule { + val in = IO(Input(new BundleBaz(w = 3))) + val out = IO(Output(in.cloneType)) + } + val (log, _) = grabLog( + ChiselStage.elaborate(new MyModule()) + ) + log should include ("warn") + log should include ("deprecated") + log should include ("The runtime reflection inference for cloneType") + } +} diff --git a/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala b/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala index 5fe63991..67d744fc 100644 --- a/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala +++ b/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala @@ -69,11 +69,14 @@ private[plugin] class BundleComponent(val global: Global, arguments: ChiselPlugi case con: DefDef if con.symbol.isPrimaryConstructor => primaryConstructor = Some(con) case d: DefDef if isNullaryMethodNamed("_cloneTypeImpl", d) => - val msg = "Users cannot override _cloneTypeImpl. Let the compiler plugin generate it. If you must, override cloneType instead." + val msg = "Users cannot override _cloneTypeImpl. Let the compiler plugin generate it." global.globalError(d.pos, msg) case d: DefDef if isNullaryMethodNamed("_usingPlugin", d) => val msg = "Users cannot override _usingPlugin, it is for the compiler plugin's use only." global.globalError(d.pos, msg) + case d: DefDef if isNullaryMethodNamed("cloneType", d) => + val msg = "Users cannot override cloneType. Let the compiler plugin generate it." + global.globalError(d.pos, msg) case _ => } (primaryConstructor, paramAccessors.toList) diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index 0dcb2466..d607be4f 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -4,7 +4,6 @@ package chisel3.util import scala.language.experimental.macros import chisel3._ -import chisel3.internal.chiselRuntimeDeprecated import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform} diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index 8909ffe3..0e05d114 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -82,9 +82,6 @@ object ReadyValidIO { * @param gen the type of data to be wrapped in DecoupledIO */ class DecoupledIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) -{ - override def cloneType: this.type = new DecoupledIO(gen).asInstanceOf[this.type] -} /** This factory adds a decoupled handshaking protocol to a data bundle. */ object Decoupled @@ -123,9 +120,6 @@ object Decoupled * @param gen the type of data to be wrapped in IrrevocableIO */ class IrrevocableIO[+T <: Data](gen: T) extends ReadyValidIO[T](gen) -{ - override def cloneType: this.type = new IrrevocableIO(gen).asInstanceOf[this.type] -} /** Factory adds an irrevocable handshaking protocol to a data bundle. */ object Irrevocable diff --git a/src/main/scala/chisel3/util/Enum.scala b/src/main/scala/chisel3/util/Enum.scala index bf150464..4501a2de 100644 --- a/src/main/scala/chisel3/util/Enum.scala +++ b/src/main/scala/chisel3/util/Enum.scala @@ -6,7 +6,6 @@ package chisel3.util import chisel3._ -import chisel3.internal.chiselRuntimeDeprecated /** Defines a set of unique UInt constants * diff --git a/src/main/scala/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala index 6c6d685e..838d43ca 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -29,8 +29,6 @@ class Valid[+T <: Data](gen: T) extends Bundle { * @return a Chisel [[Bool]] true if `valid` is asserted */ def fire(dummy: Int = 0): Bool = valid - - override def cloneType: this.type = Valid(gen).asInstanceOf[this.type] } /** Factory for generating "valid" interfaces. A "valid" interface is a data-communicating interface between a producer diff --git a/src/test/scala/chiselTests/AutoClonetypeSpec.scala b/src/test/scala/chiselTests/AutoClonetypeSpec.scala index fcbc4785..3f33fda8 100644 --- a/src/test/scala/chiselTests/AutoClonetypeSpec.scala +++ b/src/test/scala/chiselTests/AutoClonetypeSpec.scala @@ -327,7 +327,6 @@ class AutoClonetypeSpec extends ChiselFlatSpec with Utils { it should "support Bundles that implement their own cloneType" in { class MyBundle(i: Int) extends Bundle { val foo = UInt(i.W) - override def cloneType = new MyBundle(i).asInstanceOf[this.type] } elaborate { new MultiIOModule { val in = IO(Input(new MyBundle(8))) diff --git a/src/test/scala/chiselTests/BundleSpec.scala b/src/test/scala/chiselTests/BundleSpec.scala index 1d392f5c..51dedfb1 100644 --- a/src/test/scala/chiselTests/BundleSpec.scala +++ b/src/test/scala/chiselTests/BundleSpec.scala @@ -10,25 +10,20 @@ trait BundleSpecUtils { class BundleFooBar extends Bundle { val foo = UInt(16.W) val bar = UInt(16.W) - override def cloneType: this.type = (new BundleFooBar).asInstanceOf[this.type] } class BundleBarFoo extends Bundle { val bar = UInt(16.W) val foo = UInt(16.W) - override def cloneType: this.type = (new BundleBarFoo).asInstanceOf[this.type] } class BundleFoo extends Bundle { val foo = UInt(16.W) - override def cloneType: this.type = (new BundleFoo).asInstanceOf[this.type] } class BundleBar extends Bundle { val bar = UInt(16.W) - override def cloneType: this.type = (new BundleBar).asInstanceOf[this.type] } class BadSeqBundle extends Bundle { val bar = Seq(UInt(16.W), UInt(8.W), UInt(4.W)) - override def cloneType: this.type = (new BadSeqBundle).asInstanceOf[this.type] } class MyModule(output: Bundle, input: Bundle) extends Module { @@ -162,4 +157,16 @@ class BundleSpec extends ChiselFlatSpec with BundleSpecUtils with Utils { } } } + + // This tests the interaction of override def cloneType and the plugin. + // We are commenting it for now because although this code fails to compile + // as expected when just copied here, the test version is not seeing the failure. + // """ + // class BundleBaz(w: Int) extends Bundle { + // val baz = UInt(w.W) + // // This is a compiler error when using the plugin, which we test below. + // override def cloneType = (new BundleBaz(w)).asInstanceOf[this.type] + // } + // """ shouldNot compile + } diff --git a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala index 1795cc1f..4b03dfa5 100644 --- a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala +++ b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala @@ -12,8 +12,6 @@ object CompatibilityComponents { class ChiselBundle extends Bundle { val a = UInt(width = 32) val b = UInt(width = 32).flip - - override def cloneType: this.type = (new ChiselBundle).asInstanceOf[this.type] } class ChiselRecord extends Record { val elements = ListMap("a" -> UInt(width = 32), "b" -> UInt(width = 32).flip) @@ -48,8 +46,6 @@ object Chisel3Components { class Chisel3Bundle extends Bundle { val a = Output(UInt(32.W)) val b = Input(UInt(32.W)) - - override def cloneType: this.type = (new Chisel3Bundle).asInstanceOf[this.type] } class Chisel3Record extends Record { @@ -341,7 +337,6 @@ class CompatibiltyInteroperabilitySpec extends ChiselFlatSpec { val foo = maybeFlip(new Bundle { val bar = UInt(INPUT, width = 8) }) - override def cloneType = (new MyBundle(extraFlip)).asInstanceOf[this.type] } } import chisel3._ diff --git a/src/test/scala/chiselTests/CompatibilitySpec.scala b/src/test/scala/chiselTests/CompatibilitySpec.scala index 2d4ad517..bf8cd3fc 100644 --- a/src/test/scala/chiselTests/CompatibilitySpec.scala +++ b/src/test/scala/chiselTests/CompatibilitySpec.scala @@ -195,11 +195,9 @@ class CompatibiltySpec extends ChiselFlatSpec with ScalaCheckDrivenPropertyCheck class SmallBundle extends Bundle { val f1 = UInt(width = 4) val f2 = UInt(width = 5) - override def cloneType: this.type = (new SmallBundle).asInstanceOf[this.type] } class BigBundle extends SmallBundle { val f3 = UInt(width = 6) - override def cloneType: this.type = (new BigBundle).asInstanceOf[this.type] } "A Module with missing bundle fields when compiled with the Chisel compatibility package" should "not throw an exception" in { diff --git a/src/test/scala/chiselTests/CompileOptionsTest.scala b/src/test/scala/chiselTests/CompileOptionsTest.scala index 9c88c1e0..1ecf97f0 100644 --- a/src/test/scala/chiselTests/CompileOptionsTest.scala +++ b/src/test/scala/chiselTests/CompileOptionsTest.scala @@ -14,11 +14,9 @@ class CompileOptionsSpec extends ChiselFlatSpec with Utils { class SmallBundle extends Bundle { val f1 = UInt(4.W) val f2 = UInt(5.W) - override def cloneType: this.type = (new SmallBundle).asInstanceOf[this.type] } class BigBundle extends SmallBundle { val f3 = UInt(6.W) - override def cloneType: this.type = (new BigBundle).asInstanceOf[this.type] } "A Module with missing bundle fields when compiled with implicit Strict.CompileOption " should "throw an exception" in { diff --git a/src/test/scala/chiselTests/ComplexAssign.scala b/src/test/scala/chiselTests/ComplexAssign.scala index 36fb59c2..222b6373 100644 --- a/src/test/scala/chiselTests/ComplexAssign.scala +++ b/src/test/scala/chiselTests/ComplexAssign.scala @@ -7,10 +7,7 @@ import chisel3.testers.BasicTester import chisel3.util._ import org.scalacheck.Shrink -class Complex[T <: Data](val re: T, val im: T) extends Bundle { - override def cloneType: this.type = - new Complex(re.cloneType, im.cloneType).asInstanceOf[this.type] -} +class Complex[T <: Data](val re: T, val im: T) extends Bundle class ComplexAssign(w: Int) extends Module { val io = IO(new Bundle { diff --git a/src/test/scala/chiselTests/PrintableSpec.scala b/src/test/scala/chiselTests/PrintableSpec.scala index 95103352..c7e819ec 100644 --- a/src/test/scala/chiselTests/PrintableSpec.scala +++ b/src/test/scala/chiselTests/PrintableSpec.scala @@ -139,7 +139,6 @@ class PrintableSpec extends AnyFlatSpec with Matchers { } class MyBundle extends Bundle { val foo = UInt(32.W) - override def cloneType: this.type = (new MyBundle).asInstanceOf[this.type] } class MyModule extends BasicTester { override def desiredName: String = "MyModule" diff --git a/src/test/scala/chiselTests/RecordSpec.scala b/src/test/scala/chiselTests/RecordSpec.scala index c21d455c..f0edca8b 100644 --- a/src/test/scala/chiselTests/RecordSpec.scala +++ b/src/test/scala/chiselTests/RecordSpec.scala @@ -12,7 +12,6 @@ trait RecordSpecUtils { class MyBundle extends Bundle { val foo = UInt(32.W) val bar = UInt(32.W) - override def cloneType: this.type = (new MyBundle).asInstanceOf[this.type] } // Useful for constructing types from CustomBundle // This is a def because each call to this needs to return a new instance |
