diff options
| author | chick | 2019-12-12 12:06:15 -0800 |
|---|---|---|
| committer | chick | 2019-12-18 13:57:50 -0800 |
| commit | 0bcce65d5e3001b1b7098aa2c1ccd60fcc2a6628 (patch) | |
| tree | ba737c4c886005552b0e95fb48f5ff5cbdc31ea9 /chiselFrontend/src/main/scala/chisel3/Num.scala | |
| parent | 954cc41e1349d0df6d2250d6270590340cd36e82 (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
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/Num.scala')
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Num.scala | 129 |
1 files changed, 129 insertions, 0 deletions
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 |
