summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchick2019-12-12 12:06:15 -0800
committerchick2019-12-18 13:57:50 -0800
commit0bcce65d5e3001b1b7098aa2c1ccd60fcc2a6628 (patch)
treeba737c4c886005552b0e95fb48f5ff5cbdc31ea9
parent954cc41e1349d0df6d2250d6270590340cd36e82 (diff)
- New trait HasBinaryPoint which provides literal values as double and big decimal
- made .F and .I work for creating fixed point and interval lits from big decimal - Added NumObject trait which provides new math conversions - Made a Num object that extends NumObject - Add this trait to FixedPoint and Interval for backward compatibility - Removed code that is now in NumObject, keeping things DRY - Add tests to FixedPointSpec to show lit conversion to double and big decimal - Add tests to IntervalSpec to show lit conversion to double and big decimal - Add tests to LiteralExtractorSpec to show general math conversions between BigInts with binary points and double and big decimal
-rw-r--r--chiselFrontend/src/main/scala/chisel3/Aggregate.scala2
-rw-r--r--chiselFrontend/src/main/scala/chisel3/Bits.scala160
-rw-r--r--chiselFrontend/src/main/scala/chisel3/Num.scala129
-rw-r--r--chiselFrontend/src/main/scala/chisel3/package.scala3
-rw-r--r--src/main/scala/chisel3/stage/package.scala1
-rw-r--r--src/test/scala/chiselTests/FixedPointSpec.scala15
-rw-r--r--src/test/scala/chiselTests/IntervalSpec.scala59
-rw-r--r--src/test/scala/chiselTests/LiteralExtractorSpec.scala43
8 files changed, 315 insertions, 97 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/Aggregate.scala
index 42b40ed9..8141fdba 100644
--- a/chiselFrontend/src/main/scala/chisel3/Aggregate.scala
+++ b/chiselFrontend/src/main/scala/chisel3/Aggregate.scala
@@ -43,7 +43,7 @@ sealed abstract class Aggregate extends Data {
}
}
- override def litOption: Option[BigInt] = ??? // TODO implement me
+ override def litOption: Option[BigInt] = None // TODO implement me
/** Returns a Seq of the immediate contents of this Aggregate, in order.
*/
diff --git a/chiselFrontend/src/main/scala/chisel3/Bits.scala b/chiselFrontend/src/main/scala/chisel3/Bits.scala
index 28d1690d..633636fd 100644
--- a/chiselFrontend/src/main/scala/chisel3/Bits.scala
+++ b/chiselFrontend/src/main/scala/chisel3/Bits.scala
@@ -1179,6 +1179,43 @@ package experimental {
import chisel3.internal.firrtl.BinaryPoint
+ /** Chisel types that have binary points support retrieving
+ * literal values as `Double` or `BigDecimal`
+ */
+ trait HasBinaryPoint { self: Bits =>
+ def binaryPoint: BinaryPoint
+
+ /** Return the [[Double]] value of this instance if it is a Literal
+ * @note this method may return throw an exception if the literal value won't fit in a Double
+ */
+ def litToDoubleOption: Option[Double] = {
+ litOption match {
+ case Some(bigInt: BigInt) =>
+ Some(Num.toDouble(bigInt, binaryPoint))
+ case _ => None
+ }
+ }
+
+ /** Return the double value of this instance assuming it is a literal (convenience method)
+ */
+ def litToDouble: Double = litToDoubleOption.get
+
+ /** Return the [[BigDecimal]] value of this instance if it is a Literal
+ * @note this method may return throw an exception if the literal value won't fit in a BigDecimal
+ */
+ def litToBigDecimalOption: Option[BigDecimal] = {
+ litOption match {
+ case Some(bigInt: BigInt) =>
+ Some(Num.toBigDecimal(bigInt, binaryPoint))
+ case _ => None
+ }
+ }
+
+ /** Return the [[BigDecimal]] value of this instance assuming it is a literal (convenience method)
+ * @return
+ */
+ def litToBigDecimal: BigDecimal = litToBigDecimalOption.get
+ }
//scalastyle:off number.of.methods
/** A sealed class representing a fixed point number that has a bit width and a binary point The width and binary point
* may be inferred.
@@ -1195,7 +1232,7 @@ package experimental {
* @define constantWidth @note The width of the returned $coll is unchanged, i.e., `width of this`.
*/
sealed class FixedPoint private(width: Width, val binaryPoint: BinaryPoint)
- extends Bits(width) with Num[FixedPoint] {
+ extends Bits(width) with Num[FixedPoint] with HasBinaryPoint {
override def toString: String = {
val bindingString = litToDoubleOption match {
@@ -1218,16 +1255,6 @@ package experimental {
case _ => this badConnect that
}
- /** Convert to a [[scala.Option]] of [[scala.Boolean]] */
- def litToDoubleOption: Option[Double] = litOption.map { intVal =>
- val multiplier = math.pow(2, binaryPoint.get)
- intVal.toDouble / multiplier
- }
-
- /** Convert to a [[scala.Option]] */
- def litToDouble: Double = litToDoubleOption.get
-
-
/** Unary negation (expanding width)
*
* @return a hardware $coll equal to zero minus this $coll
@@ -1519,7 +1546,7 @@ package experimental {
* Factory and convenience methods for the FixedPoint class
* IMPORTANT: The API provided here is experimental and may change in the future.
*/
- object FixedPoint {
+ object FixedPoint extends NumObject {
import FixedPoint.Implicits._
@@ -1559,6 +1586,14 @@ package experimental {
toBigInt(value, binaryPoint.get), width = width, binaryPoint = binaryPoint
)
}
+ /** Create an FixedPoint literal with inferred width from BigDecimal.
+ * Use PrivateObject to force users to specify width and binaryPoint by name
+ */
+ def fromBigDecimal(value: BigDecimal, width: Width, binaryPoint: BinaryPoint): FixedPoint = {
+ fromBigInt(
+ toBigInt(value, binaryPoint.get), width = width, binaryPoint = binaryPoint
+ )
+ }
/** Create an FixedPoint port with specified width and binary position. */
def apply(value: BigInt, width: Width, binaryPoint: BinaryPoint): FixedPoint = {
@@ -1568,34 +1603,10 @@ package experimental {
lit.bindLitArg(newLiteral)
}
- /**
- * How to create a bigint from a double with a specific binaryPoint
- * @param x a double value
- * @param binaryPoint a binaryPoint that you would like to use
- * @return
- */
- def toBigInt(x: Double, binaryPoint: Int): BigInt = {
- val multiplier = math.pow(2, binaryPoint)
- val result = BigInt(math.round(x * multiplier))
- result
- }
-
- /**
- * converts a bigInt with the given binaryPoint into the double representation
- * @param i a bigint
- * @param binaryPoint the implied binaryPoint of @i
- * @return
- */
- def toDouble(i: BigInt, binaryPoint: Int): Double = {
- val multiplier = math.pow(2, binaryPoint)
- val result = i.toDouble / multiplier
- result
- }
object Implicits {
- // implicit class fromDoubleToLiteral(val double: Double) extends AnyVal {
implicit class fromDoubleToLiteral(double: Double) {
def F(binaryPoint: BinaryPoint): FixedPoint = {
FixedPoint.fromDouble(double, Width(), binaryPoint)
@@ -1605,6 +1616,16 @@ package experimental {
FixedPoint.fromDouble(double, width, binaryPoint)
}
}
+
+ implicit class fromBigDecimalToLiteral(bigDecimal: BigDecimal) {
+ def F(binaryPoint: BinaryPoint): FixedPoint = {
+ FixedPoint.fromBigDecimal(bigDecimal, Width(), binaryPoint)
+ }
+
+ def F(width: Width, binaryPoint: BinaryPoint): FixedPoint = {
+ FixedPoint.fromBigDecimal(bigDecimal, width, binaryPoint)
+ }
+ }
}
}
@@ -1627,7 +1648,7 @@ package experimental {
* @param range a range specifies min, max and binary point
*/
sealed class Interval private[chisel3] (val range: chisel3.internal.firrtl.IntervalRange)
- extends Bits(range.getWidth) with Num[Interval] {
+ extends Bits(range.getWidth) with Num[Interval] with HasBinaryPoint {
override def toString: String = {
val bindingString = litOption match {
@@ -2071,7 +2092,7 @@ package experimental {
* Factory and convenience methods for the Interval class
* IMPORTANT: The API provided here is experimental and may change in the future.
*/
- object Interval {
+ object Interval extends NumObject {
/** Create an Interval type with inferred width and binary point. */
def apply(): Interval = Interval(range"[?,?]")
@@ -2155,78 +2176,31 @@ package experimental {
case _ =>
}
val lit = IntervalLit(value, width, binaryPoint)
- val bound = firrtlir.Closed(Interval.toDouble(value, binaryPoint.asInstanceOf[KnownBinaryPoint].value))
+ val bound = firrtlir.Closed(Interval.toBigDecimal(value, binaryPoint.asInstanceOf[KnownBinaryPoint].value))
val result = new Interval(IntervalRange(bound, bound, binaryPoint))
lit.bindLitArg(result)
}
protected[chisel3] def Lit(value: BigInt, range: IntervalRange): Interval = {
val lit = IntervalLit(value, range.getWidth, range.binaryPoint)
- val bigDecimal = BigDecimal(value)
+ val bigDecimal = BigDecimal(value) / (1 << lit.binaryPoint.get)
val inRange = (range.lowerBound, range.upperBound) match {
case (firrtlir.Closed(l), firrtlir.Closed(u)) => l <= bigDecimal && bigDecimal <= u
- case (firrtlir.Closed(l), firrtlir.Open(u)) => l <= bigDecimal && bigDecimal <= u
- case (firrtlir.Open(l), firrtlir.Closed(u)) => l <= bigDecimal && bigDecimal <= u
- case (firrtlir.Open(l), firrtlir.Open(u)) => l <= bigDecimal && bigDecimal <= u
+ case (firrtlir.Closed(l), firrtlir.Open(u)) => l <= bigDecimal && bigDecimal < u
+ case (firrtlir.Open(l), firrtlir.Closed(u)) => l < bigDecimal && bigDecimal <= u
+ case (firrtlir.Open(l), firrtlir.Open(u)) => l < bigDecimal && bigDecimal < u
}
if(! inRange) {
throw new ChiselException(
- s"Error literal interval value $value is not contained in specified range $range"
+ s"Error literal interval value $bigDecimal is not contained in specified range $range"
)
}
val result = Interval(range)
lit.bindLitArg(result)
}
- /** How to create a BigInt from a double with a specific binaryPoint
- *
- * @param x a double value
- * @param binaryPoint a binaryPoint that you would like to use
- * @return
- */
- def toBigInt(x: Double, binaryPoint: BinaryPoint): BigInt = {
- val intBinaryPoint = binaryPoint match {
- case KnownBinaryPoint(n) => n
- case b =>
- throw new ChiselException(s"Error converting Double $x to BigInt, binary point must be known, not $b")
- }
- val multiplier = BigInt(1) << intBinaryPoint
- val result = BigInt(math.round(x * multiplier.doubleValue))
- result
-
- }
-
- /**
- * How to create a BigInt from a BigDecimal with a specific binaryPoint
- *
- * @param b a BigDecimal value
- * @param binaryPoint a binaryPoint that you would like to use
- * @return
- */
- def toBigInt(b: BigDecimal, binaryPoint: BinaryPoint): BigInt = {
- val bp = binaryPoint match {
- case KnownBinaryPoint(n) => n
- case x =>
- throw new ChiselException(s"Error converting BigDecimal $b to BigInt, binary point must be known, not $x")
- }
- (b * math.pow(2.0, bp.toDouble)).toBigInt
- }
-
- /**
- * converts a bigInt with the given binaryPoint into the double representation
- *
- * @param i a BigInt
- * @param binaryPoint the implied binaryPoint of @i
- * @return
- */
- def toDouble(i: BigInt, binaryPoint: Int): Double = {
- val multiplier = BigInt(1) << binaryPoint
- val result = i.toDouble / multiplier.doubleValue
- result
- }
-
/**
- * This returns the smallest number that can legally fit in range, if possible
+ * This returns the smallest Interval literal that can legally fit in range, if possible
* If the lower bound or binary point is not known then return None
*
* @param range use to figure low number
@@ -2245,7 +2219,7 @@ package experimental {
}
/**
- * This returns the largest number that can legally fit in range, if possible
+ * This returns the largest Interval literal that can legally fit in range, if possible
* If the upper bound or binary point is not known then return None
*
* @param range use to figure low number
diff --git a/chiselFrontend/src/main/scala/chisel3/Num.scala b/chiselFrontend/src/main/scala/chisel3/Num.scala
index 8984697f..e4d61d94 100644
--- a/chiselFrontend/src/main/scala/chisel3/Num.scala
+++ b/chiselFrontend/src/main/scala/chisel3/Num.scala
@@ -2,6 +2,9 @@
package chisel3
+import chisel3.internal.ChiselException
+import chisel3.internal.firrtl.{BinaryPoint, KnownBinaryPoint}
+
import scala.language.experimental.macros
import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform}
@@ -177,3 +180,129 @@ trait Num[T <: Data] {
def do_max(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T =
Mux(this < that, that, this.asInstanceOf[T])
}
+
+object Num extends NumObject
+
+/** NumbObject has a lot of convenience methods for converting between
+ * BigInts and Double and BigDecimal
+ * For backwards compatibility this is used with FixedPoint and Interval objects
+ * but is better used with the Num Object
+ *
+ */
+trait NumObject {
+ val MaxBitsBigIntToBigDecimal = 108
+ val MaxBitsBigIntToDouble = 53
+
+ /**
+ * How to create a bigint from a double with a specific binaryPoint
+ * @param x a double value
+ * @param binaryPoint a binaryPoint that you would like to use
+ * @return
+ */
+ def toBigInt(x: Double, binaryPoint: Int): BigInt = {
+ val multiplier = math.pow(2, binaryPoint)
+ val result = BigInt(math.round(x * multiplier))
+ result
+ }
+
+ /**
+ * How to create a bigint from a big decimal with a specific binaryPoint
+ * @param x a BigDecimal value
+ * @param binaryPoint a binaryPoint that you would like to use
+ * @return
+ */
+ def toBigInt(x: Double, binaryPoint: BinaryPoint): BigInt = {
+ binaryPoint match {
+ case KnownBinaryPoint(n) => toBigInt(x, n)
+ case x =>
+ throw new ChiselException(s"Error converting Double $x to BigInt, binary point must be known, not $x")
+ }
+ }
+
+ /**
+ * How to create a bigint from a big decimal with a specific binaryPoint (int)
+ * @param x a BigDecimal value
+ * @param binaryPoint a binaryPoint that you would like to use
+ * @return
+ */
+ def toBigInt(x: BigDecimal, binaryPoint: Int): BigInt = {
+ val multiplier = math.pow(2, binaryPoint)
+ val result = (x * multiplier).rounded.toBigInt()
+ result
+ }
+
+ /**
+ * How to create a bigint from a big decimal with a specific binaryPoint
+ * @param value a BigDecimal value
+ * @param binaryPoint a binaryPoint that you would like to use
+ * @return
+ */
+ def toBigInt(value: BigDecimal, binaryPoint: BinaryPoint): BigInt = {
+ binaryPoint match {
+ case KnownBinaryPoint(n) => toBigInt(value, n)
+ case x =>
+ throw new ChiselException(s"Error converting BigDecimal $value to BigInt, binary point must be known, not $x")
+ }
+ }
+
+ /**
+ * converts a bigInt with the given binaryPoint into the double representation
+ * @param i a bigint
+ * @param binaryPoint the implied binaryPoint of @i
+ * @return
+ */
+ def toDouble(i: BigInt, binaryPoint: Int): Double = {
+ if(i.bitLength >= 54) {
+ throw new ChiselException(
+ s"BigInt $i with bitlength ${i.bitLength} is too big, precision lost with > $MaxBitsBigIntToDouble bits"
+ )
+ }
+ val multiplier = math.pow(2, binaryPoint)
+ val result = i.toDouble / multiplier
+ result
+ }
+
+ /**
+ * converts a bigInt with the given binaryPoint into the double representation
+ * @param value a bigint
+ * @param binaryPoint the implied binaryPoint of @i
+ * @return
+ */
+ def toDouble(value: BigInt, binaryPoint: BinaryPoint): Double = {
+ binaryPoint match {
+ case KnownBinaryPoint(n) => toDouble(value, n)
+ case x =>
+ throw new ChiselException(s"Error converting BigDecimal $value to BigInt, binary point must be known, not $x")
+ } }
+
+ /**
+ * converts a bigInt with the given binaryPoint into the BigDecimal representation
+ * @param value a bigint
+ * @param binaryPoint the implied binaryPoint of @i
+ * @return
+ */
+ def toBigDecimal(value: BigInt, binaryPoint: Int): BigDecimal = {
+ if(value.bitLength > 108) {
+ throw new ChiselException(
+ s"BigInt $value with bitlength ${value.bitLength} is too big, precision lost with > $MaxBitsBigIntToBigDecimal bits"
+ )
+ }
+ val multiplier = BigDecimal(1.0) / BigDecimal(math.pow(2, binaryPoint))
+ val result = BigDecimal(value) * multiplier
+ result
+ }
+
+ /**
+ * converts a bigInt with the given binaryPoint into the BigDecimal representation
+ * @param value a bigint
+ * @param binaryPoint the implied binaryPoint of @i
+ * @return
+ */
+ def toBigDecimal(value: BigInt, binaryPoint: BinaryPoint): BigDecimal = {
+ binaryPoint match {
+ case KnownBinaryPoint(n) => toBigDecimal(value, n)
+ case x =>
+ throw new ChiselException(s"Error converting BigDecimal $value to BigInt, binary point must be known, not $x")
+ }
+ }
+} \ No newline at end of file
diff --git a/chiselFrontend/src/main/scala/chisel3/package.scala b/chiselFrontend/src/main/scala/chisel3/package.scala
index 3af21d57..65bfdeb7 100644
--- a/chiselFrontend/src/main/scala/chisel3/package.scala
+++ b/chiselFrontend/src/main/scala/chisel3/package.scala
@@ -115,6 +115,9 @@ package object chisel3 { // scalastyle:ignore package.object.name
implicit class fromDoubleToLiteral(double: Double)
extends experimental.FixedPoint.Implicits.fromDoubleToLiteral(double)
+ implicit class fromBigDecimalToLiteral(bigDecimal: BigDecimal)
+ extends experimental.FixedPoint.Implicits.fromBigDecimalToLiteral(bigDecimal)
+
// Interval is experimental for now, but we alias the implicit conversion classes here
// to minimize disruption with existing code.
implicit class fromIntToLiteralInterval(int: Int)
diff --git a/src/main/scala/chisel3/stage/package.scala b/src/main/scala/chisel3/stage/package.scala
index 67d38ae7..57766be6 100644
--- a/src/main/scala/chisel3/stage/package.scala
+++ b/src/main/scala/chisel3/stage/package.scala
@@ -28,7 +28,6 @@ package object stage {
private[chisel3] implicit object ChiselExecutionResultView extends OptionsView[ChiselExecutionResult] {
- lazy val dummyWriteEmitted = new firrtl.stage.phases.WriteEmitted
lazy val dummyConvert = new Convert
lazy val dummyEmitter = new Emitter
diff --git a/src/test/scala/chiselTests/FixedPointSpec.scala b/src/test/scala/chiselTests/FixedPointSpec.scala
index a928f08e..e97c6be7 100644
--- a/src/test/scala/chiselTests/FixedPointSpec.scala
+++ b/src/test/scala/chiselTests/FixedPointSpec.scala
@@ -19,6 +19,21 @@ class FixedPointLiteralSpec extends FlatSpec with Matchers {
initialDouble should be(finalDouble)
}
+
+ they should "have their literals support to double and to BigDecimal" in {
+ val d = -7.125
+ val lit1 = d.F(3.BP)
+ lit1.litToDouble should be (d)
+
+ val d2 = BigDecimal("1232123213131123.125")
+ val lit2 = d2.F(3.BP)
+ lit2.litToBigDecimal should be (d2)
+
+ // Numbers that are too big will throw exception
+ intercept[ChiselException] {
+ lit2.litToDouble
+ }
+ }
}
//noinspection TypeAnnotation,EmptyParenMethodAccessedAsParameterless
diff --git a/src/test/scala/chiselTests/IntervalSpec.scala b/src/test/scala/chiselTests/IntervalSpec.scala
index 863771a3..ae7fdabf 100644
--- a/src/test/scala/chiselTests/IntervalSpec.scala
+++ b/src/test/scala/chiselTests/IntervalSpec.scala
@@ -456,12 +456,69 @@ class IntervalSpec extends FreeSpec with Matchers with ChiselRunners {
() =>
new BasicTester {
val x = 5.I(range"[0,4]")
- }
+ }
).elaborate
}
}
}
+ "Interval literals support to double and to BigDecimal" in {
+ val d = -7.125
+ val lit1 = d.I(3.BP)
+ lit1.litToDouble should be (d)
+
+ val d2 = BigDecimal("1232123213131123.125")
+ val lit2 = d2.I(3.BP)
+ lit2.litToBigDecimal should be (d2)
+
+ // Numbers that are too big will throw exception
+ intercept[ChiselException] {
+ lit2.litToDouble
+ }
+ }
+
+ "Interval literals creation handles edge cases" - {
+ "value at closed boundaries works" in {
+ val inputRange = range"[-6, 6].2"
+ val in1 = (-6.0).I(inputRange)
+ val in2 = 6.0.I(inputRange)
+ BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be (-6)
+ BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be (6)
+ intercept[ChiselException] {
+ (-6.25).I(inputRange)
+ }
+ intercept[ChiselException] {
+ (6.25).I(inputRange)
+ }
+ }
+ "value at open boundaries works" in {
+ val inputRange = range"(-6, 6).2"
+ val in1 = (-5.75).I(inputRange)
+ val in2 = 5.75.I(inputRange)
+ BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be (-5.75)
+ BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be (5.75)
+ intercept[ChiselException] {
+ (-6.0).I(inputRange)
+ }
+ intercept[ChiselException] {
+ (6.0).I(inputRange)
+ }
+ }
+ "values not precisely at open boundaries works but are converted to nearest match" in {
+ val inputRange = range"(-6, 6).2"
+ val in1 = (-5.95).I(inputRange)
+ val in2 = 5.95.I(inputRange)
+ BigDecimal(in1.litValue()) / (1 << inputRange.binaryPoint.get) should be (-5.75)
+ BigDecimal(in2.litValue()) / (1 << inputRange.binaryPoint.get) should be (5.75)
+ intercept[ChiselException] {
+ (-6.1).I(inputRange)
+ }
+ intercept[ChiselException] {
+ (6.1).I(inputRange)
+ }
+ }
+ }
+
"Let's take a look at the results of squeeze over small range" in {
assertTesterPasses {
new ClipSqueezeWrapDemo(
diff --git a/src/test/scala/chiselTests/LiteralExtractorSpec.scala b/src/test/scala/chiselTests/LiteralExtractorSpec.scala
index b56672af..145c1ef2 100644
--- a/src/test/scala/chiselTests/LiteralExtractorSpec.scala
+++ b/src/test/scala/chiselTests/LiteralExtractorSpec.scala
@@ -3,7 +3,7 @@
package chiselTests
import chisel3._
-import chisel3.experimental.FixedPoint
+import chisel3.experimental._
import chisel3.experimental.BundleLiterals._
import chisel3.testers.BasicTester
@@ -55,6 +55,47 @@ class LiteralExtractorSpec extends ChiselFlatSpec {
}}
}
+ "doubles and big decimals" should "round trip properly" in {
+ intercept[ChiselException] {
+ Num.toBigDecimal(BigInt("1" * 109, 2), 0.BP) // this only works if number takes less than 109 bits
+ }
+
+ intercept[ChiselException] {
+ Num.toDouble(BigInt("1" * 54, 2), 0.BP) // this only works if number takes less than 54 bits
+ }
+
+ val bigInt108 = BigInt("1" * 108, 2)
+ val bigDecimal = Num.toBigDecimal(bigInt108, 2)
+
+ val bigIntFromBigDecimal = Num.toBigInt(bigDecimal, 2)
+
+ bigIntFromBigDecimal should be (bigInt108)
+
+ val bigInt53 = BigInt("1" * 53, 2)
+
+ val double = Num.toDouble(bigInt53, 2)
+
+ val bigIntFromDouble = Num.toBigInt(double, 2)
+
+ bigIntFromDouble should be (bigInt53)
+ }
+
+ "encoding and decoding of Intervals" should "round trip" in {
+ val rangeMin = BigDecimal(-31.5)
+ val rangeMax = BigDecimal(32.5)
+ val range = range"($rangeMin, $rangeMax).2"
+ for(value <- (rangeMin - 4) to (rangeMax + 4) by 2.25) {
+ if (value < rangeMin || value > rangeMax) {
+ intercept[ChiselException] {
+ val literal = value.I(range)
+ }
+ } else {
+ val literal = value.I(range)
+ literal.isLit() should be(true)
+ literal.litValue().toDouble / 4.0 should be(value)
+ }
+ }
+ }
"literals declared outside a builder context" should "compare with those inside builder context" in {
class InsideBundle extends Bundle {