diff options
| author | Richard Lin | 2018-01-02 13:51:36 -0800 |
|---|---|---|
| committer | GitHub | 2018-01-02 13:51:36 -0800 |
| commit | 678df42aa6bf2f4715be2d051c3c29f058948d0c (patch) | |
| tree | 0b3fb00565e1c442abd7885d490cd4324f02d3fe /src | |
| parent | cb7fcd2b18135230dc40f3c7bb98685e7ffde9d5 (diff) | |
| parent | ade792ee7c5bb718f738f5e4c3886b2e87c68756 (diff) | |
Merge pull request #723 from freechipsproject/autoclonetype
Auto clone type 🦆
Diffstat (limited to 'src')
10 files changed, 236 insertions, 9 deletions
diff --git a/src/main/scala/chisel3/testers/BasicTester.scala b/src/main/scala/chisel3/testers/BasicTester.scala index 6d1a4913..7bb441ba 100644 --- a/src/main/scala/chisel3/testers/BasicTester.scala +++ b/src/main/scala/chisel3/testers/BasicTester.scala @@ -13,7 +13,7 @@ import internal.sourceinfo.SourceInfo class BasicTester extends Module() { // The testbench has no IOs, rather it should communicate using printf, assert, and stop. - val io = IO(new Bundle()) + val io = IO(new Bundle() {}) def popCount(n: Long): Int = n.toBinaryString.count(_=='1') diff --git a/src/test/scala/chiselTests/AnalogIntegrationSpec.scala b/src/test/scala/chiselTests/AnalogIntegrationSpec.scala index 952d3872..a3e6e643 100644 --- a/src/test/scala/chiselTests/AnalogIntegrationSpec.scala +++ b/src/test/scala/chiselTests/AnalogIntegrationSpec.scala @@ -19,7 +19,7 @@ class AnalogBlackBoxPort extends Bundle { // This IO can be used for a single BlackBox or to group multiple // Has multiple ports for driving and checking but only one shared bus -class AnalogBlackBoxIO(n: Int) extends Bundle { +class AnalogBlackBoxIO(val n: Int) extends Bundle { require(n > 0) val bus = Analog(32.W) val port = Vec(n, new AnalogBlackBoxPort) diff --git a/src/test/scala/chiselTests/AutoClonetypeSpec.scala b/src/test/scala/chiselTests/AutoClonetypeSpec.scala new file mode 100644 index 00000000..1170ed12 --- /dev/null +++ b/src/test/scala/chiselTests/AutoClonetypeSpec.scala @@ -0,0 +1,115 @@ +// See LICENSE for license details. + +package chiselTests + +import chisel3._ + +import chisel3.testers.BasicTester + +class BundleWithIntArg(val i: Int) extends Bundle { + val out = UInt(i.W) +} + +class BundleWithImplicit()(implicit val ii: Int) extends Bundle { + val out = UInt(ii.W) +} + +class BundleWithArgAndImplicit(val i: Int)(implicit val ii: Int) extends Bundle { + val out1 = UInt(i.W) + val out2 = UInt(ii.W) +} + +class BaseBundleVal(val i: Int) extends Bundle { + val inner = UInt(i.W) +} +class SubBundle(i: Int, val i2: Int) extends BaseBundleVal(i) { + val inner2 = UInt(i2.W) +} +class SubBundleInvalid(i: Int, val i2: Int) extends BaseBundleVal(i+1) { + val inner2 = UInt(i2.W) +} + +class BaseBundleNonVal(i: Int) extends Bundle { + val inner = UInt(i.W) +} +class SubBundleVal(val i: Int, val i2: Int) extends BaseBundleNonVal(i) { + val inner2 = UInt(i2.W) +} + +class ModuleWithInner extends Module { + class InnerBundle(val i: Int) extends Bundle { + val out = UInt(i.W) + } + + val io = IO(new Bundle{}) + + val myWire = Wire(new InnerBundle(14)) + require(myWire.i == 14) +} + + +class AutoClonetypeSpec extends ChiselFlatSpec { + "Bundles with Scala args" should "not need clonetype" in { + elaborate { new Module { + val io = IO(new Bundle{}) + + val myWire = Wire(new BundleWithIntArg(8)) + assert(myWire.i == 8) + } } + } + + "Bundles with Scala implicit args" should "not need clonetype" in { + elaborate { new Module { + val io = IO(new Bundle{}) + + implicit val implicitInt: Int = 4 + val myWire = Wire(new BundleWithImplicit()) + + assert(myWire.ii == 4) + } } + } + + "Bundles with Scala explicit and impicit args" should "not need clonetype" in { + elaborate { new Module { + val io = IO(new Bundle{}) + + implicit val implicitInt: Int = 4 + val myWire = Wire(new BundleWithArgAndImplicit(8)) + + assert(myWire.i == 8) + assert(myWire.ii == 4) + } } + } + + "Subtyped Bundles" should "not need clonetype" in { + elaborate { new Module { + val io = IO(new Bundle{}) + + val myWire = Wire(new SubBundle(8, 4)) + + assert(myWire.i == 8) + assert(myWire.i2 == 4) + } } + elaborate { new Module { + val io = IO(new Bundle{}) + + val myWire = Wire(new SubBundleVal(8, 4)) + + assert(myWire.i == 8) + assert(myWire.i2 == 4) + } } + } + + "Subtyped Bundles that don't clone well" should "be caught" in { + a [ChiselException] should be thrownBy { + elaborate { new Module { + val io = IO(new Bundle{}) + val myWire = Wire(new SubBundleInvalid(8, 4)) + } } + } + } + + "Inner bundles with Scala args" should "not need clonetype" in { + elaborate { new ModuleWithInner } + } +} diff --git a/src/test/scala/chiselTests/AutoNestedCloneSpec.scala b/src/test/scala/chiselTests/AutoNestedCloneSpec.scala new file mode 100644 index 00000000..746780be --- /dev/null +++ b/src/test/scala/chiselTests/AutoNestedCloneSpec.scala @@ -0,0 +1,108 @@ +// See LICENSE for license details. + +package chiselTests +import Chisel.ChiselException +import org.scalatest._ +import chisel3._ + +class BundleWithAnonymousInner(val w: Int) extends Bundle { + val inner = new Bundle { + val foo = Input(UInt(w.W)) + } +} + +class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers { + behavior of "autoCloneType of inner Bundle in Chisel3" + + it should "clone a doubly-nested inner bundle successfully" in { + elaborate { + class Outer(val w: Int) extends Module { + class Middle(val w: Int) { + class InnerIOType extends Bundle { + val in = Input(UInt(w.W)) + } + def getIO = new InnerIOType + } + val io = IO(new Bundle {}) + val myWire = Wire((new Middle(w)).getIO) + } + new Outer(2) + } + } + + it should "clone an anonymous inner bundle successfully" in { + elaborate { + class TestTop(val w: Int) extends Module { + val io = IO(new Bundle {}) + val myWire = Wire(new Bundle{ val a = UInt(w.W) }) + } + new TestTop(2) + } + } + + it should "pick the correct $outer instance for an anonymous inner bundle" in { + elaborate { + class Inner(val w: Int) extends Module { + val io = IO(new Bundle{ + val in = Input(UInt(w.W)) + val out = Output(UInt(w.W)) + }) + } + class Outer(val w: Int) extends Module { + val io = IO(new Bundle{ + val in = Input(UInt(w.W)) + val out = Output(UInt(w.W)) + }) + val i = Module(new Inner(w)) + val iw = Wire(chiselTypeOf(i.io)) + iw <> io + i.io <> iw + } + new Outer(2) + } + } + + it should "clone an anonymous, bound, inner bundle of another bundle successfully" in { + elaborate { + class TestModule(w: Int) extends Module { + val io = IO(new BundleWithAnonymousInner(w) ) + val w0 = WireInit(io) + val w1 = WireInit(io.inner) + } + new TestModule(8) + } + } + + it should "clone an anonymous, inner bundle of a Module, bound to another bundle successfully" in { + elaborate { + class TestModule(w: Int) extends Module { + val bun = new Bundle { + val foo = UInt(w.W) + } + val io = IO(new Bundle { + val inner = Input(bun) + }) + val w0 = WireInit(io) + val w1 = WireInit(io.inner) + } + new TestModule(8) + } + } + + behavior of "anonymous doubly-nested inner bundle fails with clear error" + ( the[ChiselException] thrownBy { + elaborate { + class Outer(val w: Int) extends Module { + class Middle(val w: Int) { + def getIO = new Bundle { + val in = Input(UInt(w.W)) + } + } + val io = IO(new Bundle {}) + val myWire = Wire((new Middle(w)).getIO) + } + new Outer(2) + } + }).getMessage should include("Unable to determine instance") + +} diff --git a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala index 457f26de..95dc87c1 100644 --- a/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala +++ b/src/test/scala/chiselTests/CompatibilityInteroperabilitySpec.scala @@ -12,6 +12,8 @@ object CompatibilityComponents { class ChiselBundle extends Bundle { val a = UInt(width = 32) val b = UInt(width = 32).flip + + override def cloneType = (new ChiselBundle).asInstanceOf[this.type] } class ChiselRecord extends Record { val elements = ListMap("a" -> UInt(width = 32), "b" -> UInt(width = 32).flip) @@ -46,6 +48,8 @@ object Chisel3Components { class Chisel3Bundle extends Bundle { val a = Output(UInt(32.W)) val b = Input(UInt(32.W)) + + override def cloneType = (new Chisel3Bundle).asInstanceOf[this.type] } class Chisel3Record extends Record { diff --git a/src/test/scala/chiselTests/MissingCloneBindingExceptionSpec.scala b/src/test/scala/chiselTests/MissingCloneBindingExceptionSpec.scala index 43f2b0fd..fc9346a0 100644 --- a/src/test/scala/chiselTests/MissingCloneBindingExceptionSpec.scala +++ b/src/test/scala/chiselTests/MissingCloneBindingExceptionSpec.scala @@ -28,7 +28,7 @@ class MissingCloneBindingExceptionSpec extends ChiselFlatSpec with Matchers { } elaborate(new TestTop) - }).getMessage should include("needs cloneType method") + }).getMessage should include("make all parameters immutable") behavior of "missing cloneType in Chisel2" ( the[ChiselException] thrownBy { @@ -53,5 +53,5 @@ class MissingCloneBindingExceptionSpec extends ChiselFlatSpec with Matchers { } elaborate(new TestTop) - }).getMessage should include("needs cloneType method") + }).getMessage should include("make all parameters immutable") } diff --git a/src/test/scala/chiselTests/NamingAnnotationTest.scala b/src/test/scala/chiselTests/NamingAnnotationTest.scala index 699dc0fb..a7b9b75c 100644 --- a/src/test/scala/chiselTests/NamingAnnotationTest.scala +++ b/src/test/scala/chiselTests/NamingAnnotationTest.scala @@ -12,7 +12,7 @@ import chisel3.testers.BasicTester import scala.collection.mutable.ListBuffer trait NamedModuleTester extends Module { - val io = IO(new Bundle()) // Named module testers don't need IO + val io = IO(new Bundle() {}) // Named module testers don't need IO val expectedNameMap = ListBuffer[(InstanceId, String)]() val expectedModuleNameMap = ListBuffer[(Module, String)]() diff --git a/src/test/scala/chiselTests/OptionBundle.scala b/src/test/scala/chiselTests/OptionBundle.scala index 2ac661ea..03b08385 100644 --- a/src/test/scala/chiselTests/OptionBundle.scala +++ b/src/test/scala/chiselTests/OptionBundle.scala @@ -6,7 +6,7 @@ import org.scalatest._ import chisel3._ import chisel3.testers.BasicTester -class OptionBundle(hasIn: Boolean) extends Bundle { +class OptionBundle(val hasIn: Boolean) extends Bundle { val in = if (hasIn) { Some(Input(Bool())) } else { @@ -15,7 +15,7 @@ class OptionBundle(hasIn: Boolean) extends Bundle { val out = Output(Bool()) } -class OptionBundleModule(hasIn: Boolean) extends Module { +class OptionBundleModule(val hasIn: Boolean) extends Module { val io = IO(new OptionBundle(hasIn)) if (hasIn) { io.out := io.in.get diff --git a/src/test/scala/chiselTests/VectorPacketIO.scala b/src/test/scala/chiselTests/VectorPacketIO.scala index 7745db57..4a8c6f78 100644 --- a/src/test/scala/chiselTests/VectorPacketIO.scala +++ b/src/test/scala/chiselTests/VectorPacketIO.scala @@ -27,7 +27,7 @@ class Packet extends Bundle { * lines also. * The problem does not occur if the Vec is taken out */ -class VectorPacketIO(n: Int) extends Bundle { +class VectorPacketIO(val n: Int) extends Bundle { val ins = Vec(n, chisel3.util.DeqIO(new Packet())) val outs = Vec(n, chisel3.util.EnqIO(new Packet())) } diff --git a/src/test/scala/examples/VendingMachineGenerator.scala b/src/test/scala/examples/VendingMachineGenerator.scala index 55a17d9f..0a9dc3e6 100644 --- a/src/test/scala/examples/VendingMachineGenerator.scala +++ b/src/test/scala/examples/VendingMachineGenerator.scala @@ -9,7 +9,7 @@ import chisel3.util._ import VendingMachineUtils._ -class VendingMachineIO(legalCoins: Seq[Coin]) extends Bundle { +class VendingMachineIO(val legalCoins: Seq[Coin]) extends Bundle { require(legalCoins.size >= 1, "The vending machine must accept at least 1 coin!") // Order of coins by value val coins: Seq[Coin] = legalCoins sortBy (_.value) |
