diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/scala/chisel3/package.scala | 8 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/BundleLiteralSpec.scala | 136 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/DataPrint.scala | 18 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/LiteralExtractorSpec.scala | 30 |
4 files changed, 122 insertions, 70 deletions
diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index 02c4ecf5..7587f211 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -511,5 +511,13 @@ package object chisel3 { // scalastyle:ignore package.object.name class dump extends chisel3.internal.naming.dump // scalastyle:ignore class.name class treedump extends chisel3.internal.naming.treedump // scalastyle:ignore class.name class chiselName extends chisel3.internal.naming.chiselName // scalastyle:ignore class.name + + object BundleLiterals { + implicit class AddBundleLiteralConstructor[T <: Bundle](x: T) { + def Lit(elems: (T => (Data, Data))*): T = { + x._makeLit(elems: _*) + } + } + } } } diff --git a/src/test/scala/chiselTests/BundleLiteralSpec.scala b/src/test/scala/chiselTests/BundleLiteralSpec.scala index 9db602ee..2a6c53d5 100644 --- a/src/test/scala/chiselTests/BundleLiteralSpec.scala +++ b/src/test/scala/chiselTests/BundleLiteralSpec.scala @@ -3,47 +3,25 @@ package chiselTests import chisel3._ -import chisel3.core.FixedPoint -import chisel3.experimental.RawModule import chisel3.testers.BasicTester -import org.scalatest._ +import chisel3.experimental.RawModule +import chisel3.experimental.BundleLiterals._ +import chisel3.core.BundleLiteralException class BundleLiteralSpec extends ChiselFlatSpec { class MyBundle extends Bundle { val a = UInt(8.W) val b = Bool() - - // Bundle literal constructor code, which will be auto-generated using macro annotations in - // the future. - import chisel3.core.BundleLitBinding - import chisel3.internal.firrtl.{ULit, Width} - // Full bundle literal constructor - def Lit(aVal: UInt, bVal: Bool): MyBundle = { // scalastyle:ignore method.name - val clone = cloneType - clone.selfBind(BundleLitBinding(Map( - clone.a -> litArgOfBits(aVal), - clone.b -> litArgOfBits(bVal) - ))) - clone - } - // Partial bundle literal constructor - def Lit(aVal: UInt): MyBundle = { // scalastyle:ignore method.name - val clone = cloneType - clone.selfBind(BundleLitBinding(Map( - clone.a -> litArgOfBits(aVal) - ))) - clone - } } "bundle literals" should "work in RTL" in { - val outsideBundleLit = (new MyBundle).Lit(42.U, true.B) + val outsideBundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B) assertTesterPasses{ new BasicTester{ // TODO: add direct bundle compare operations, when that feature is added chisel3.assert(outsideBundleLit.a === 42.U) chisel3.assert(outsideBundleLit.b === true.B) - val bundleLit = (new MyBundle).Lit(42.U, true.B) + val bundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B) chisel3.assert(bundleLit.a === 42.U) chisel3.assert(bundleLit.b === true.B) @@ -62,7 +40,7 @@ class BundleLiteralSpec extends ChiselFlatSpec { "partial bundle literals" should "work in RTL" in { assertTesterPasses{ new BasicTester{ - val bundleLit = (new MyBundle).Lit(42.U) + val bundleLit = (new MyBundle).Lit(_.a -> 42.U) chisel3.assert(bundleLit.a === 42.U) val bundleWire = Wire(new MyBundle) @@ -73,4 +51,106 @@ class BundleLiteralSpec extends ChiselFlatSpec { stop() } } } + + class MyOuterBundle extends Bundle { + val a = new MyBundle + val b = new Bundle { + val c = Bool() + val d = UInt(8.W) + } + } + + "contained bundles" should "work" in { + assertTesterPasses{ new BasicTester{ + // Specify the inner Bundle value as a Bundle literal + val explicitBundleLit = (new MyOuterBundle).Lit( + _.a -> (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B) + ) + chisel3.assert(explicitBundleLit.a.a === 42.U) + chisel3.assert(explicitBundleLit.a.b === true.B) + + // Specify the inner Bundle fields directly + val expandedBundleLit = (new MyOuterBundle).Lit( + _.a.a -> 42.U, _.a.b -> true.B, + _.b.c -> false.B, _.b.d -> 255.U + ) + chisel3.assert(expandedBundleLit.a.a === 42.U) + chisel3.assert(expandedBundleLit.a.b === true.B) + chisel3.assert(expandedBundleLit.b.c === false.B) + chisel3.assert(expandedBundleLit.b.d === 255.U) + + // Anonymously contruct the inner Bundle literal + // A bit of weird syntax that depends on implementation details of the Bundle literal constructor + val childBundleLit = (new MyOuterBundle).Lit( + b => b.b -> b.b.Lit(_.c -> false.B, _.d -> 255.U) + ) + chisel3.assert(childBundleLit.b.c === false.B) + chisel3.assert(childBundleLit.b.d === 255.U) + + stop() + } } + } + + "Bundle literals" should "assign" in { + assertTesterPasses{ new BasicTester{ + val bundleWire = Wire(Output(new MyBundle)) + val bundleLit = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B) + bundleWire := bundleLit + + chisel3.assert(bundleWire.a === 42.U) + chisel3.assert(bundleWire.b === true.B) + stop() + } } + } + + "partially initialized Bundle literals" should "assign" in { + assertTesterPasses{ new BasicTester{ + val bundleWire = Wire(Output(new MyBundle)) + val bundleLit = (new MyBundle).Lit(_.a -> 42.U) + bundleWire := bundleLit + + chisel3.assert(bundleWire.a === 42.U) + stop() + } } + } + + "bundle literals with bad field specifiers" should "fail" in { + val exc = intercept[BundleLiteralException] { elaborate { new RawModule { + val bundle = new MyBundle + bundle.Lit(x => bundle.a -> 0.U) // DONT DO THIS, this gets past a syntax error to exercise the failure + }}} + exc.getMessage should include ("not a field") + } + + "bundle literals with duplicate fields" should "fail" in { + val exc = intercept[BundleLiteralException] { elaborate { new RawModule { + (new MyBundle).Lit(_.a -> 0.U, _.a -> 0.U) + }}} + exc.getMessage should include ("duplicate") + exc.getMessage should include (".a") + } + + "bundle literals with non-literal values" should "fail" in { + val exc = intercept[BundleLiteralException] { elaborate { new RawModule { + (new MyBundle).Lit(_.a -> UInt()) + }}} + exc.getMessage should include ("non-literal value") + exc.getMessage should include (".a") + } + + "bundle literals with non-type-equivalent element fields" should "fail" in { + val exc = intercept[BundleLiteralException] { elaborate { new RawModule { + (new MyBundle).Lit(_.a -> true.B) + }}} + exc.getMessage should include ("non-type-equivalent value") + exc.getMessage should include (".a") + } + + "bundle literals with non-type-equivalent sub-bundles" should "fail" in { + val exc = intercept[BundleLiteralException] { elaborate { new RawModule { + (new MyOuterBundle).Lit(_.b -> (new MyBundle).Lit(_.a -> 0.U)) + }}} + exc.getMessage should include ("non-type-equivalent value") + exc.getMessage should include (".b") + } } diff --git a/src/test/scala/chiselTests/DataPrint.scala b/src/test/scala/chiselTests/DataPrint.scala index bec722f3..57e44c36 100644 --- a/src/test/scala/chiselTests/DataPrint.scala +++ b/src/test/scala/chiselTests/DataPrint.scala @@ -6,30 +6,16 @@ import org.scalatest._ import chisel3._ import chisel3.experimental.{ChiselEnum, FixedPoint, RawModule, MultiIOModule} +import chisel3.experimental.BundleLiterals._ class DataPrintSpec extends ChiselFlatSpec with Matchers { object EnumTest extends ChiselEnum { val sNone, sOne, sTwo = Value } - // TODO: dedup w/ BundleLiteralSpec class BundleTest extends Bundle { val a = UInt(8.W) val b = Bool() - - // Bundle literal constructor code, which will be auto-generated using macro annotations in - // the future. - import chisel3.core.BundleLitBinding - import chisel3.internal.firrtl.{ULit, Width} - // Full bundle literal constructor - def Lit(aVal: UInt, bVal: Bool): BundleTest = { // scalastyle:ignore method.name - val clone = cloneType - clone.selfBind(BundleLitBinding(Map( - clone.a -> litArgOfBits(aVal), - clone.b -> litArgOfBits(bVal) - ))) - clone - } } "Data types" should "have a meaningful string representation" in { @@ -82,7 +68,7 @@ class DataPrintSpec extends ChiselFlatSpec with Matchers { EnumTest.sNone.toString should be ("EnumTest(0=sNone)") EnumTest.sTwo.toString should be ("EnumTest(2=sTwo)") EnumTest(1.U).toString should be ("EnumTest(1=sOne)") - (new BundleTest).Lit(2.U, false.B).toString should be ("BundleTest(a=UInt<8>(2), b=Bool(false))") + (new BundleTest).Lit(_.a -> 2.U, _.b -> false.B).toString should be ("BundleTest(a=UInt<8>(2), b=Bool(false))") new Bundle { val a = UInt(8.W) }.toString should be ("AnonymousBundle") diff --git a/src/test/scala/chiselTests/LiteralExtractorSpec.scala b/src/test/scala/chiselTests/LiteralExtractorSpec.scala index 25979488..c2d84831 100644 --- a/src/test/scala/chiselTests/LiteralExtractorSpec.scala +++ b/src/test/scala/chiselTests/LiteralExtractorSpec.scala @@ -5,6 +5,7 @@ package chiselTests import chisel3._ import chisel3.core.FixedPoint import chisel3.experimental.RawModule +import chisel3.experimental.BundleLiterals._ import chisel3.testers.BasicTester import org.scalatest._ @@ -61,20 +62,10 @@ class LiteralExtractorSpec extends ChiselFlatSpec { class InsideBundle extends Bundle { val x = SInt(8.W) val y = FixedPoint(8.W, 4.BP) - - import chisel3.core.BundleLitBinding - def Lit(aVal: SInt, bVal: FixedPoint): InsideBundle = { // scalastyle:ignore method.name - val clone = cloneType - clone.selfBind(BundleLitBinding(Map( - clone.x -> litArgOfBits(aVal), - clone.y -> litArgOfBits(bVal) - ))) - clone - } } class LitInsideOutsideTester(outsideLiteral: InsideBundle) extends BasicTester { - val insideLiteral = (new InsideBundle).Lit(7.S, 6.125.F(4.BP)) + val insideLiteral = (new InsideBundle).Lit(_.x -> 7.S, _.y -> 6.125.F(4.BP)) // the following errors with "assertion failed" @@ -92,7 +83,7 @@ class LiteralExtractorSpec extends ChiselFlatSpec { stop() } - val outsideLiteral = (new InsideBundle).Lit(7.S, 6.125.F(4.BP)) + val outsideLiteral = (new InsideBundle).Lit(_.x -> 7.S, _.y -> 6.125.F(4.BP)) assertTesterPasses{ new LitInsideOutsideTester(outsideLiteral) } } @@ -102,21 +93,8 @@ class LiteralExtractorSpec extends ChiselFlatSpec { class MyBundle extends Bundle { val a = UInt(8.W) val b = Bool() - - // Bundle literal constructor code, which will be auto-generated using macro annotations in - // the future. - import chisel3.core.BundleLitBinding - import chisel3.internal.firrtl.{ULit, Width} - def Lit(aVal: UInt, bVal: Bool): MyBundle = { // scalastyle:ignore method.name - val clone = cloneType - clone.selfBind(BundleLitBinding(Map( - clone.a -> litArgOfBits(aVal), - clone.b -> litArgOfBits(bVal) - ))) - clone - } } - val myBundleLiteral = (new MyBundle).Lit(42.U, true.B) + val myBundleLiteral = (new MyBundle).Lit(_.a -> 42.U, _.b -> true.B) assert(myBundleLiteral.a.litValue == 42) assert(myBundleLiteral.b.litValue == 1) assert(myBundleLiteral.b.litToBoolean == true) |
