summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMegan Wachs2021-10-05 10:27:18 -0700
committerGitHub2021-10-05 17:27:18 +0000
commitce15ad50a5c175db06c3bba5e3bf46b6c5466c47 (patch)
treebcec55dbb92bc827b3d3ec973481baa4d380c489
parent790a1806c7c5333cea15abbd2657fa893beb92c9 (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.scala4
-rw-r--r--docs/src/explanations/bundles-and-vecs.md65
-rw-r--r--no-plugin-tests/src/test/scala/chiselTests/NoPluginBundleSpec.scala36
-rw-r--r--plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala5
-rw-r--r--src/main/scala/chisel3/util/BitPat.scala1
-rw-r--r--src/main/scala/chisel3/util/Decoupled.scala6
-rw-r--r--src/main/scala/chisel3/util/Enum.scala1
-rw-r--r--src/main/scala/chisel3/util/Valid.scala2
-rw-r--r--src/test/scala/chiselTests/AutoClonetypeSpec.scala1
-rw-r--r--src/test/scala/chiselTests/BundleSpec.scala17
-rw-r--r--src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala5
-rw-r--r--src/test/scala/chiselTests/CompatibilitySpec.scala2
-rw-r--r--src/test/scala/chiselTests/CompileOptionsTest.scala2
-rw-r--r--src/test/scala/chiselTests/ComplexAssign.scala5
-rw-r--r--src/test/scala/chiselTests/PrintableSpec.scala1
-rw-r--r--src/test/scala/chiselTests/RecordSpec.scala1
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