summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/chisel3/core
diff options
context:
space:
mode:
authorChick Markley2016-10-25 08:59:15 -0700
committerGitHub2016-10-25 08:59:15 -0700
commite00ae6ff3518d517733f5cfe3959e8b31c5876b5 (patch)
tree93063422d03f13c6585b7a582dcf24c1f27b0b6a /chiselFrontend/src/main/scala/chisel3/core
parenta44c7aede6902533ea79fcf6a3fbed234b4456c0 (diff)
FixedPoint number support for chisel3 (#328)
* FixedPoint number support for chisel3 FixedPoint numbers have a width and a binary position Either, neither or both maybe inferred. Firrtl will convert these to SInts during lowering passes * Fixes based on Jack's comments on PR #328 * Add experimental warning to FixedPoint class and object * Fixed comment per Adam's comment on PR #328
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/core')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Bits.scala229
1 files changed, 229 insertions, 0 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
index a5d954b6..7ee11b92 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
@@ -250,6 +250,18 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg])
def do_asSInt(implicit sourceInfo: SourceInfo): SInt
+ /** Reinterpret cast as a FixedPoint.
+ *
+ * @note value not guaranteed to be preserved: for example, an UInt of width
+ * 3 and value 7 (0b111) would become a FixedInt with value -1, the interpretation
+ * of the number is also affected by the specified binary point. Caution advised
+ */
+ final def asFixedPoint(that: BinaryPoint): FixedPoint = macro SourceInfoTransform.thatArg
+
+ def do_asFixedPoint(that: BinaryPoint)(implicit sourceInfo: SourceInfo): FixedPoint = {
+ throwException(s"Cannot call .asFixedPoint on $this")
+ }
+
/** Reinterpret cast to Bits. */
@deprecated("Use asUInt, which does the same thing but returns a more concrete type", "chisel3")
final def asBits(): Bits = macro SourceInfoTransform.noArg
@@ -508,6 +520,15 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None)
override def do_asSInt(implicit sourceInfo: SourceInfo): SInt =
pushOp(DefPrim(sourceInfo, SInt(width), AsSIntOp, ref))
override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = this
+ override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo): FixedPoint = {
+ binaryPoint match {
+ case KnownBinaryPoint(value) =>
+ val iLit = ILit(value)
+ pushOp(DefPrim(sourceInfo, FixedPoint(width, binaryPoint), AsFixedPointOp, ref, iLit))
+ case _ =>
+ throwException(s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint")
+ }
+ }
}
// This is currently a factory because both Bits and UInt inherit it.
@@ -684,6 +705,9 @@ sealed class SInt private (width: Width, lit: Option[SLit] = None)
override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref))
override def do_asSInt(implicit sourceInfo: SourceInfo): SInt = this
+ override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo): FixedPoint = {
+ pushOp(DefPrim(sourceInfo, FixedPoint(width, binaryPoint), AsFixedPointOp, ref))
+ }
}
object SInt {
@@ -852,3 +876,208 @@ object Mux {
}
}
+//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.
+ *
+ * IMPORTANT: The API provided here is experimental and may change in the future.
+ *
+ * @param width bit width of the fixed point number
+ * @param binaryPoint the position of the binary point with respect to the right most bit of the width
+ * currently this should be positive but it is hoped to soon support negative points
+ * and thus use this field as a simple exponent
+ * @param lit
+ */
+sealed class FixedPoint private (width: Width, val binaryPoint: BinaryPoint, lit: Option[FPLit] = None)
+ extends Bits(width, lit) with Num[FixedPoint] {
+ private[core] override def cloneTypeWidth(w: Width): this.type =
+ new FixedPoint(w, binaryPoint).asInstanceOf[this.type]
+ private[chisel3] def toType = s"Fixed$width$binaryPoint"
+
+ def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
+ case _: FixedPoint => this connect that
+ case _ => this badConnect that
+ }
+
+ private[chisel3] def fromInt(value: BigInt, width: Int): this.type = {
+ throwException(s"Don't use $this.fromInt($value, $width): Use literal constructors instead")
+ }
+
+ final def unary_- (): FixedPoint = macro SourceInfoTransform.noArg
+ final def unary_-% (): FixedPoint = macro SourceInfoTransform.noArg
+
+ def unary_- (implicit sourceInfo: SourceInfo): FixedPoint = FixedPoint.fromBigInt(0) - this
+ def unary_-% (implicit sourceInfo: SourceInfo): FixedPoint = FixedPoint.fromBigInt(0) -% this
+
+ /** add (default - no growth) operator */
+ override def do_+ (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint =
+ this +% that
+ /** subtract (default - no growth) operator */
+ override def do_- (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint =
+ this -% that
+ override def do_* (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint =
+ binop(sourceInfo, FixedPoint(this.width + that.width, this.binaryPoint + that.binaryPoint), TimesOp, that)
+ override def do_/ (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint =
+ throwException(s"division is illegal on FixedPoint types")
+ override def do_% (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint =
+ throwException(s"mod is illegal on FixedPoint types")
+
+ final def * (that: UInt): FixedPoint = macro SourceInfoTransform.thatArg
+ def do_* (that: UInt)(implicit sourceInfo: SourceInfo): FixedPoint =
+ binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that)
+
+ final def * (that: SInt): FixedPoint = macro SourceInfoTransform.thatArg
+ def do_* (that: SInt)(implicit sourceInfo: SourceInfo): FixedPoint =
+ binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that)
+
+ /** add (width +1) operator */
+ final def +& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
+ /** add (no growth) operator */
+ final def +% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
+ /** subtract (width +1) operator */
+ final def -& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
+ /** subtract (no growth) operator */
+ final def -% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
+
+ def do_+& (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint =
+ binop(sourceInfo, FixedPoint((this.width max that.width) + 1, this.binaryPoint max that.binaryPoint), AddOp, that)
+ def do_+% (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint =
+ (this +& that).tail(1).asFixedPoint(this.binaryPoint max that.binaryPoint)
+ def do_-& (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint =
+ binop(sourceInfo, FixedPoint((this.width max that.width) + 1, this.binaryPoint max that.binaryPoint), SubOp, that)
+ def do_-% (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint =
+ (this -& that).tail(1).asFixedPoint(this.binaryPoint max that.binaryPoint)
+
+ final def & (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
+ final def | (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
+ final def ^ (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg
+
+ def do_& (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint =
+ throwException(s"And is illegal between $this and $that")
+ def do_| (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint =
+ throwException(s"Or is illegal between $this and $that")
+ def do_^ (that: FixedPoint)(implicit sourceInfo: SourceInfo): FixedPoint =
+ throwException(s"Xor is illegal between $this and $that")
+
+ final def setBinaryPoint(that: Int): FixedPoint = macro SourceInfoTransform.thatArg
+
+ def do_setBinaryPoint(that: Int)(implicit sourceInfo: SourceInfo): FixedPoint =
+ binop(sourceInfo, FixedPoint(this.width, KnownBinaryPoint(that)), SetBinaryPoint, that)
+
+ /** Returns this wire bitwise-inverted. */
+ def do_unary_~ (implicit sourceInfo: SourceInfo): FixedPoint =
+ throwException(s"Not is illegal on $this")
+
+ // TODO(chick): Consider comparison with UInt and SInt
+ override def do_< (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessOp, that)
+ override def do_> (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterOp, that)
+ override def do_<= (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessEqOp, that)
+ override def do_>= (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterEqOp, that)
+
+ final def != (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg
+ final def =/= (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg
+ final def === (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg
+
+ def do_!= (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, NotEqualOp, that)
+ def do_=/= (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, NotEqualOp, that)
+ def do_=== (that: FixedPoint)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, EqualOp, that)
+
+ final def abs(): UInt = macro SourceInfoTransform.noArg
+
+ def do_abs(implicit sourceInfo: SourceInfo): UInt = {
+ Mux(this < FixedPoint.fromBigInt(0), (FixedPoint.fromBigInt(0)-this).asUInt, this.asUInt)
+ }
+
+ override def do_<< (that: Int)(implicit sourceInfo: SourceInfo): FixedPoint =
+ binop(sourceInfo, FixedPoint(this.width + that, this.binaryPoint), ShiftLeftOp, that)
+ override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo): FixedPoint =
+ this << that.toInt
+ override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): FixedPoint =
+ binop(sourceInfo, FixedPoint(this.width.dynamicShiftLeft(that.width), this.binaryPoint), DynamicShiftLeftOp, that)
+ override def do_>> (that: Int)(implicit sourceInfo: SourceInfo): FixedPoint =
+ binop(sourceInfo, FixedPoint(this.width.shiftRight(that), this.binaryPoint), ShiftRightOp, that)
+ override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo): FixedPoint =
+ this >> that.toInt
+ override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo): FixedPoint =
+ binop(sourceInfo, FixedPoint(this.width, this.binaryPoint), DynamicShiftRightOp, that)
+
+ override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref))
+ override def do_asSInt(implicit sourceInfo: SourceInfo): SInt = pushOp(DefPrim(sourceInfo, SInt(this.width), AsSIntOp, ref))
+ //TODO(chick): Consider "convert" as an arithmetic conversion to UInt/SInt
+}
+
+/** Use PrivateObject to force users to specify width and binaryPoint by name
+ */
+sealed trait PrivateType
+private case object PrivateObject extends PrivateType
+
+/**
+ * Factory and convenience methods for the FixedPoint class
+ * IMPORTANT: The API provided here is experimental and may change in the future.
+ */
+object FixedPoint {
+ /** Create an FixedPoint type with inferred width. */
+ def apply(): FixedPoint = apply(Width(), BinaryPoint())
+
+ /** Create an FixedPoint type or port with fixed width. */
+ def apply(width: Int, binaryPoint: Int): FixedPoint = apply(Width(width), BinaryPoint(binaryPoint))
+ /** Create an FixedPoint port with inferred width. */
+ def apply(dir: Direction): FixedPoint = apply(dir, Width(), BinaryPoint())
+
+ /** Create an FixedPoint literal with inferred width from BigInt.
+ * Use PrivateObject to force users to specify width and binaryPoint by name
+ */
+ def fromBigInt(value: BigInt, width: Int = -1, binaryPoint: Int = 0): FixedPoint =
+ if(width == -1) {
+ apply(value, Width(), BinaryPoint(binaryPoint))
+ }
+ else {
+ apply(value, Width(width), BinaryPoint(binaryPoint))
+ }
+ /** Create an FixedPoint literal with inferred width from Double.
+ * Use PrivateObject to force users to specify width and binaryPoint by name
+ */
+ def fromDouble(value: Double, dummy: PrivateType = PrivateObject,
+ width: Int = -1, binaryPoint: Int = 0): FixedPoint = {
+ fromBigInt(
+ toBigInt(value, binaryPoint), width = width, binaryPoint = binaryPoint
+ )
+ }
+
+ /** Create an FixedPoint type with specified width and binary position. */
+ def apply(width: Width, binaryPoint: BinaryPoint): FixedPoint = new FixedPoint(width, binaryPoint)
+ /** Create an FixedPoint port with specified width and binary position. */
+ def apply(dir: Direction, width: Width, binaryPoint: BinaryPoint): FixedPoint = new FixedPoint(width, binaryPoint)
+ def apply(value: BigInt, width: Width, binaryPoint: BinaryPoint): FixedPoint = {
+ val lit = FPLit(value, width, binaryPoint)
+ val newLiteral = new FixedPoint(lit.width, lit.binaryPoint, Some(lit))
+ newLiteral.binding = LitBinding()
+ 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
+ }
+
+}