summaryrefslogtreecommitdiff
path: root/core/src/main/scala/chisel3/Num.scala
diff options
context:
space:
mode:
authorJack Koenig2020-03-25 19:51:46 -0700
committerGitHub2020-03-25 19:51:46 -0700
commitdbb024a9adee6d82f37e357cf8b55456674ff65c (patch)
tree578858ab6d219ca6daf44cf87b73f75054989097 /core/src/main/scala/chisel3/Num.scala
parent6263fcc56b630b7181eb30680cadcdbb2bdf91dc (diff)
parentfbf5e6f1a0e8bf535d465b748ad554575fe62156 (diff)
Merge pull request #1384 from freechipsproject/no-more-compile-internal
No more compile internal
Diffstat (limited to 'core/src/main/scala/chisel3/Num.scala')
-rw-r--r--core/src/main/scala/chisel3/Num.scala308
1 files changed, 308 insertions, 0 deletions
diff --git a/core/src/main/scala/chisel3/Num.scala b/core/src/main/scala/chisel3/Num.scala
new file mode 100644
index 00000000..7a6b0744
--- /dev/null
+++ b/core/src/main/scala/chisel3/Num.scala
@@ -0,0 +1,308 @@
+// See LICENSE for license details.
+
+package chisel3
+
+import chisel3.internal.ChiselException
+import chisel3.internal.firrtl.{BinaryPoint, KnownBinaryPoint}
+
+import scala.language.experimental.macros
+import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform}
+
+// scalastyle:off method.name
+
+// REVIEW TODO: Further discussion needed on what Num actually is.
+
+/** Abstract trait defining operations available on numeric-like hardware data types.
+ *
+ * @tparam T the underlying type of the number
+ * @groupdesc Arithmetic Arithmetic hardware operators
+ * @groupdesc Comparison Comparison hardware operators
+ * @groupdesc Logical Logical hardware operators
+ * @define coll numeric-like type
+ * @define numType hardware type
+ * @define canHaveHighCost can result in significant cycle time and area costs
+ * @define canGenerateA This method generates a
+ * @define singleCycleMul @note $canGenerateA fully combinational multiplier which $canHaveHighCost.
+ * @define singleCycleDiv @note $canGenerateA fully combinational divider which $canHaveHighCost.
+ * @define maxWidth @note The width of the returned $numType is `max(width of this, width of that)`.
+ * @define maxWidthPlusOne @note The width of the returned $numType is `max(width of this, width of that) + 1`.
+ * @define sumWidth @note The width of the returned $numType is `width of this` + `width of that`.
+ * @define unchangedWidth @note The width of the returned $numType is unchanged, i.e., the `width of this`.
+ */
+trait Num[T <: Data] {
+ self: Num[T] =>
+ // def << (b: T): T
+ // def >> (b: T): T
+ //def unary_-(): T
+
+ // REVIEW TODO: double check ops conventions against FIRRTL
+
+ /** Addition operator
+ *
+ * @param that a $numType
+ * @return the sum of this $coll and `that`
+ * $maxWidth
+ * @group Arithmetic
+ */
+ final def + (that: T): T = macro SourceInfoTransform.thatArg
+
+ /** @group SourceInfoTransformMacro */
+ def do_+ (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T
+
+ /** Multiplication operator
+ *
+ * @param that a $numType
+ * @return the product of this $coll and `that`
+ * $sumWidth
+ * $singleCycleMul
+ * @group Arithmetic
+ */
+ final def * (that: T): T = macro SourceInfoTransform.thatArg
+
+ /** @group SourceInfoTransformMacro */
+ def do_* (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T
+
+ /** Division operator
+ *
+ * @param that a $numType
+ * @return the quotient of this $coll divided by `that`
+ * $singleCycleDiv
+ * @todo full rules
+ * @group Arithmetic
+ */
+ final def / (that: T): T = macro SourceInfoTransform.thatArg
+
+ /** @group SourceInfoTransformMacro */
+ def do_/ (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T
+
+ /** Modulo operator
+ *
+ * @param that a $numType
+ * @return the remainder of this $coll divided by `that`
+ * $singleCycleDiv
+ * @group Arithmetic
+ */
+ final def % (that: T): T = macro SourceInfoTransform.thatArg
+
+ /** @group SourceInfoTransformMacro */
+ def do_% (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T
+
+ /** Subtraction operator
+ *
+ * @param that a $numType
+ * @return the difference of this $coll less `that`
+ * $maxWidthPlusOne
+ * @group Arithmetic
+ */
+ final def - (that: T): T = macro SourceInfoTransform.thatArg
+
+ /** @group SourceInfoTransformMacro */
+ def do_- (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T
+
+ /** Less than operator
+ *
+ * @param that a $numType
+ * @return a hardware [[Bool]] asserted if this $coll is less than `that`
+ * @group Comparison
+ */
+ final def < (that: T): Bool = macro SourceInfoTransform.thatArg
+
+ /** @group SourceInfoTransformMacro */
+ def do_< (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool
+
+ /** Less than or equal to operator
+ *
+ * @param that a $numType
+ * @return a hardware [[Bool]] asserted if this $coll is less than or equal to `that`
+ * @group Comparison
+ */
+ final def <= (that: T): Bool = macro SourceInfoTransform.thatArg
+
+ /** @group SourceInfoTransformMacro */
+ def do_<= (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool
+
+ /** Greater than operator
+ *
+ * @param that a hardware component
+ * @return a hardware [[Bool]] asserted if this $coll is greater than `that`
+ * @group Comparison
+ */
+ final def > (that: T): Bool = macro SourceInfoTransform.thatArg
+
+ /** @group SourceInfoTransformMacro */
+ def do_> (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool
+
+ /** Greater than or equal to operator
+ *
+ * @param that a hardware component
+ * @return a hardware [[Bool]] asserted if this $coll is greather than or equal to `that`
+ * @group Comparison
+ */
+ final def >= (that: T): Bool = macro SourceInfoTransform.thatArg
+
+ /** @group SourceInfoTransformMacro */
+ def do_>= (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool
+
+ /** Absolute value operator
+ *
+ * @return a $numType with a value equal to the absolute value of this $coll
+ * $unchangedWidth
+ * @group Arithmetic
+ */
+ final def abs(): T = macro SourceInfoTransform.noArg
+
+ /** @group SourceInfoTransformMacro */
+ def do_abs(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T
+
+ /** Minimum operator
+ *
+ * @param that a hardware $coll
+ * @return a $numType with a value equal to the mimimum value of this $coll and `that`
+ * $maxWidth
+ * @group Arithmetic
+ */
+ final def min(that: T): T = macro SourceInfoTransform.thatArg
+
+ /** @group SourceInfoTransformMacro */
+ def do_min(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T =
+ Mux(this < that, this.asInstanceOf[T], that)
+
+ /** Maximum operator
+ *
+ * @param that a $numType
+ * @return a $numType with a value equal to the mimimum value of this $coll and `that`
+ * $maxWidth
+ * @group Arithmetic
+ */
+ final def max(that: T): T = macro SourceInfoTransform.thatArg
+
+ /** @group SourceInfoTransformMacro */
+ 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 > MaxBitsBigIntToBigDecimal) {
+ 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