summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Data.scala2
-rw-r--r--src/test/scala/chiselTests/LiteralExtractorSpec.scala79
2 files changed, 81 insertions, 0 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
index 87a8d1a9..e2d8775d 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
@@ -270,6 +270,8 @@ abstract class Data extends HasId with NamedComponent {
* binding and direction are valid after this call completes.
*/
private[chisel3] def bind(target: Binding, parentDirection: SpecifiedDirection = SpecifiedDirection.Unspecified)
+ // Variant of bind that can be called from subclasses, used for bundle literals
+ protected def selfBind(target: Binding) = bind(target)
// Both _direction and _resolvedUserDirection are saved versions of computed variables (for
// efficiency, avoid expensive recomputation of frequent operations).
diff --git a/src/test/scala/chiselTests/LiteralExtractorSpec.scala b/src/test/scala/chiselTests/LiteralExtractorSpec.scala
new file mode 100644
index 00000000..531d5863
--- /dev/null
+++ b/src/test/scala/chiselTests/LiteralExtractorSpec.scala
@@ -0,0 +1,79 @@
+// See LICENSE for license details.
+
+package chiselTests
+
+import chisel3._
+import chisel3.experimental.RawModule
+import org.scalatest._
+
+class LiteralExtractorSpec extends ChiselFlatSpec {
+ "litToBigInt" should "return the literal value" in {
+ assert(0.U.litToBigInt === BigInt(0))
+ assert(1.U.litToBigInt === BigInt(1))
+ assert(42.U.litToBigInt === BigInt(42))
+
+ assert(0.S.litToBigInt === BigInt(0))
+ assert(-1.S.litToBigInt === BigInt(-1))
+ assert(-42.S.litToBigInt === BigInt(-42))
+
+ assert(true.B.litToBigInt === BigInt(1))
+ assert(false.B.litToBigInt === BigInt(0))
+
+ assert(1.25.F(2.BP).litToBigInt === BigInt("101", 2))
+ assert(2.25.F(2.BP).litToBigInt === BigInt("1001", 2))
+
+ assert(-1.25.F(2.BP).litToBigInt === BigInt("-101", 2))
+ assert(-2.25.F(2.BP).litToBigInt === BigInt("-1001", 2))
+ }
+
+ "litToBoolean" should "return the literal value" in {
+ assert(true.B.litToBoolean === true)
+ assert(false.B.litToBoolean === false)
+ }
+
+ "litToDouble" should "return the literal value" in {
+ assert(1.25.F(2.BP).litToDouble == 1.25)
+ assert(2.25.F(2.BP).litToDouble == 2.25)
+
+ assert(-1.25.F(2.BP).litToDouble == -1.25)
+ assert(-2.25.F(2.BP).litToDouble == -2.25)
+
+ // test rounding
+ assert(1.24.F(1.BP).litToDouble == 1.0)
+ assert(1.25.F(1.BP).litToDouble == 1.5)
+ }
+
+ "litToBigIntOption" should "return None for non-literal hardware" in {
+ elaborate { new RawModule {
+ val a = Wire(UInt())
+ assert(a.litToBigIntOption == None)
+ }}
+ }
+
+ "bundle literals" should "do the right thing" in {
+ 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: BigInt, bVal: Boolean): MyBundle = {
+ val clone = cloneType
+ clone.selfBind(BundleLitBinding(Map(
+ clone.a -> ULit(aVal, Width()),
+ clone.b -> ULit(if (bVal) 1 else 0, Width(1)))
+ ))
+ clone
+ }
+ }
+ val myBundleLiteral = (new MyBundle).Lit(42, true)
+ println(myBundleLiteral.a)
+ println(myBundleLiteral.b)
+ println(myBundleLiteral.a == myBundleLiteral.b)
+ assert(myBundleLiteral.a.litToBigInt == 42)
+ assert(myBundleLiteral.b.litToBigInt == 1)
+ assert(myBundleLiteral.b.litToBoolean == true)
+ }
+}