diff options
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3/Bits.scala')
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Bits.scala | 1834 |
1 files changed, 1834 insertions, 0 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/Bits.scala b/chiselFrontend/src/main/scala/chisel3/Bits.scala new file mode 100644 index 00000000..2a8e8d1e --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/Bits.scala @@ -0,0 +1,1834 @@ +// See LICENSE for license details. + +package chisel3 + +import scala.language.experimental.macros +import collection.mutable + +import chisel3.experimental.{FixedPoint, RawModule} +import chisel3.internal._ +import chisel3.internal.Builder.{pushCommand, pushOp} +import chisel3.internal.firrtl._ +import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, + UIntTransform} +import chisel3.internal.firrtl.PrimOp._ + +// scalastyle:off method.name line.size.limit file.size.limit + +/** Element is a leaf data type: it cannot contain other [[Data]] objects. Example uses are for representing primitive + * data types, like integers and bits. + * + * @define coll element + */ +abstract class Element extends Data { + private[chisel3] final def allElements: Seq[Element] = Seq(this) + def widthKnown: Boolean = width.known + def name: String = getRef.name + + private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) { + binding = target + val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection) + direction = ActualDirection.fromSpecified(resolvedDirection) + } + + private[chisel3] override def topBindingOpt: Option[TopBinding] = super.topBindingOpt match { + // Translate Bundle lit bindings to Element lit bindings + case Some(BundleLitBinding(litMap)) => litMap.get(this) match { + case Some(litArg) => Some(ElementLitBinding(litArg)) + case _ => Some(DontCareBinding()) + } + case topBindingOpt => topBindingOpt + } + + private[chisel3] def litArgOption: Option[LitArg] = topBindingOpt match { + case Some(ElementLitBinding(litArg)) => Some(litArg) + case _ => None + } + + override def litOption: Option[BigInt] = litArgOption.map(_.num) + private[chisel3] def litIsForcedWidth: Option[Boolean] = litArgOption.map(_.forcedWidth) + + // provide bits-specific literal handling functionality here + override private[chisel3] def ref: Arg = topBindingOpt match { + case Some(ElementLitBinding(litArg)) => litArg + case Some(BundleLitBinding(litMap)) => litMap.get(this) match { + case Some(litArg) => litArg + case _ => throwException(s"internal error: DontCare should be caught before getting ref") + } + case _ => super.ref + } + + private[chisel3] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { + // If the source is a DontCare, generate a DefInvalid for the sink, + // otherwise, issue a Connect. + if (that == DontCare) { + pushCommand(DefInvalid(sourceInfo, Node(this))) + } else { + pushCommand(Connect(sourceInfo, Node(this), that.ref)) + } + } +} + +/** Exists to unify common interfaces of [[Bits]] and [[Reset]]. + * + * @note This is a workaround because macros cannot override abstract methods. + */ +private[chisel3] sealed trait ToBoolable extends Element { + + /** Casts this $coll to a [[Bool]] + * + * @note The width must be known and equal to 1 + */ + final def asBool(): Bool = macro SourceInfoWhiteboxTransform.noArg + + /** @group SourceInfoTransformMacro */ + def do_asBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool + + /** Casts this $coll to a [[Bool]] + * + * @note The width must be known and equal to 1 + */ + final def toBool(): Bool = macro SourceInfoWhiteboxTransform.noArg + + /** @group SourceInfoTransformMacro */ + def do_toBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool +} + +/** A data type for values represented by a single bitvector. This provides basic bitwise operations. + * + * @groupdesc Bitwise Bitwise hardware operators + * @define coll [[Bits]] + * @define sumWidthInt @note The width of the returned $coll is `width of this` + `that`. + * @define sumWidth @note The width of the returned $coll is `width of this` + `width of that`. + * @define unchangedWidth @note The width of the returned $coll is unchanged, i.e., the `width of this`. + */ +sealed abstract class Bits(private[chisel3] val width: Width) extends Element with ToBoolable { //scalastyle:off number.of.methods + // TODO: perhaps make this concrete? + // Arguments for: self-checking code (can't do arithmetic on bits) + // Arguments against: generates down to a FIRRTL UInt anyways + + // Only used for in a few cases, hopefully to be removed + private[chisel3] def cloneTypeWidth(width: Width): this.type + + def cloneType: this.type = cloneTypeWidth(width) + + /** Tail operator + * + * @param n the number of bits to remove + * @return This $coll with the `n` most significant bits removed. + * @group Bitwise + */ + final def tail(n: Int): UInt = macro SourceInfoTransform.nArg + + /** Head operator + * + * @param n the number of bits to take + * @return The `n` most significant bits of this $coll + * @group Bitwise + */ + final def head(n: Int): UInt = macro SourceInfoTransform.nArg + + /** @group SourceInfoTransformMacro */ + def do_tail(n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { + val w = width match { + case KnownWidth(x) => + require(x >= n, s"Can't tail($n) for width $x < $n") + Width(x - n) + case UnknownWidth() => Width() + } + binop(sourceInfo, UInt(width = w), TailOp, n) + } + + /** @group SourceInfoTransformMacro */ + def do_head(n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { + width match { + case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n") + case UnknownWidth() => + } + binop(sourceInfo, UInt(Width(n)), HeadOp, n) + } + + /** Returns the specified bit on this $coll as a [[Bool]], statically addressed. + * + * @param x an index + * @return the specified bit + */ + final def apply(x: BigInt): Bool = macro SourceInfoTransform.xArg + + /** @group SourceInfoTransformMacro */ + final def do_apply(x: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { + if (x < 0) { + Builder.error(s"Negative bit indices are illegal (got $x)") + } + // This preserves old behavior while a more more consistent API is under debate + // See https://github.com/freechipsproject/chisel3/issues/867 + litOption.map { value => + (((value >> castToInt(x, "Index")) & 1) == 1).asBool + }.getOrElse { + requireIsHardware(this, "bits to be indexed") + pushOp(DefPrim(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x))) + } + } + + /** Returns the specified bit on this $coll as a [[Bool]], statically addressed. + * + * @param x an index + * @return the specified bit + * @note convenience method allowing direct use of [[scala.Int]] without implicits + */ + final def apply(x: Int): Bool = macro SourceInfoTransform.xArg + + /** @group SourceInfoTransformMacro */ + final def do_apply(x: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = apply(BigInt(x)) + + /** Returns the specified bit on this wire as a [[Bool]], dynamically addressed. + * + * @param x a hardware component whose value will be used for dynamic addressing + * @return the specified bit + */ + final def apply(x: UInt): Bool = macro SourceInfoTransform.xArg + + /** @group SourceInfoTransformMacro */ + final def do_apply(x: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { + val theBits = this >> x + theBits(0) + } + + /** Returns a subset of bits on this $coll from `hi` to `lo` (inclusive), statically addressed. + * + * @example + * {{{ + * myBits = 0x5 = 0b101 + * myBits(1,0) => 0b01 // extracts the two least significant bits + * }}} + * @param x the high bit + * @param y the low bit + * @return a hardware component contain the requested bits + */ + final def apply(x: Int, y: Int): UInt = macro SourceInfoTransform.xyArg + + /** @group SourceInfoTransformMacro */ + final def do_apply(x: Int, y: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { + if (x < y || y < 0) { + Builder.error(s"Invalid bit range ($x,$y)") + } + val w = x - y + 1 + // This preserves old behavior while a more more consistent API is under debate + // See https://github.com/freechipsproject/chisel3/issues/867 + litOption.map { value => + ((value >> y) & ((BigInt(1) << w) - 1)).asUInt(w.W) + }.getOrElse { + requireIsHardware(this, "bits to be sliced") + pushOp(DefPrim(sourceInfo, UInt(Width(w)), BitsExtractOp, this.ref, ILit(x), ILit(y))) + } + } + + // REVIEW TODO: again, is this necessary? Or just have this and use implicits? + /** Returns a subset of bits on this $coll from `hi` to `lo` (inclusive), statically addressed. + * + * @example + * {{{ + * myBits = 0x5 = 0b101 + * myBits(1,0) => 0b01 // extracts the two least significant bits + * }}} + * @param x the high bit + * @param y the low bit + * @return a hardware component contain the requested bits + */ + final def apply(x: BigInt, y: BigInt): UInt = macro SourceInfoTransform.xyArg + + /** @group SourceInfoTransformMacro */ + final def do_apply(x: BigInt, y: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + apply(castToInt(x, "High index"), castToInt(y, "Low index")) + + private[chisel3] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T = { + requireIsHardware(this, "bits operated on") + pushOp(DefPrim(sourceInfo, dest, op, this.ref)) + } + private[chisel3] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: BigInt): T = { + requireIsHardware(this, "bits operated on") + pushOp(DefPrim(sourceInfo, dest, op, this.ref, ILit(other))) + } + private[chisel3] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: Bits): T = { + requireIsHardware(this, "bits operated on") + requireIsHardware(other, "bits operated on") + pushOp(DefPrim(sourceInfo, dest, op, this.ref, other.ref)) + } + private[chisel3] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool = { + requireIsHardware(this, "bits operated on") + requireIsHardware(other, "bits operated on") + pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref)) + } + private[chisel3] def redop(sourceInfo: SourceInfo, op: PrimOp): Bool = { + requireIsHardware(this, "bits operated on") + pushOp(DefPrim(sourceInfo, Bool(), op, this.ref)) + } + + /** Pad operator + * + * @param that the width to pad to + * @return this @coll zero padded up to width `that`. If `that` is less than the width of the original component, + * this method returns the original component. + * @note For [[SInt]]s only, this will do sign extension. + * @group Bitwise + */ + final def pad(that: Int): this.type = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_pad(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = this.width match { + case KnownWidth(w) if w >= that => this + case _ => binop(sourceInfo, cloneTypeWidth(this.width max Width(that)), PadOp, that) + } + + /** Bitwise inversion operator + * + * @return this $coll with each bit inverted + * @group Bitwise + */ + final def unary_~ (): Bits = macro SourceInfoWhiteboxTransform.noArg + + /** @group SourceInfoTransformMacro */ + def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + + /** Static left shift operator + * + * @param that an amount to shift by + * @return this $coll with `that` many zeros concatenated to its least significant end + * $sumWidthInt + * @group Bitwise + */ + // REVIEW TODO: redundant + // REVIEW TODO: should these return this.type or Bits? + final def << (that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + + /** Static left shift operator + * + * @param that an amount to shift by + * @return this $coll with `that` many zeros concatenated to its least significant end + * $sumWidthInt + * @group Bitwise + */ + final def << (that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + + /** Dynamic left shift operator + * + * @param that a hardware component + * @return this $coll dynamically shifted left by `that` many places, shifting in zeros from the right + * @note The width of the returned $coll is `width of this + pow(2, width of that) - 1`. + * @group Bitwise + */ + final def << (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + + /** Static right shift operator + * + * @param that an amount to shift by + * @return this $coll with `that` many least significant bits truncated + * $unchangedWidth + * @group Bitwise + */ + // REVIEW TODO: redundant + final def >> (that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + + /** Static right shift operator + * + * @param that an amount to shift by + * @return this $coll with `that` many least significant bits truncated + * $unchangedWidth + * @group Bitwise + */ + final def >> (that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + + /** Dynamic right shift operator + * + * @param that a hardware component + * @return this $coll dynamically shifted right by the value of `that` component, inserting zeros into the most + * significant bits. + * $unchangedWidth + * @group Bitwise + */ + final def >> (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + + /** Returns the contents of this wire as a [[scala.collection.Seq]] of [[Bool]]. */ + final def toBools(): Seq[Bool] = macro SourceInfoTransform.noArg + + /** @group SourceInfoTransformMacro */ + @chiselRuntimeDeprecated + @deprecated("Use asBools instead", "3.2") + def do_toBools(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Seq[Bool] = do_asBools + + /** Returns the contents of this wire as a [[scala.collection.Seq]] of [[Bool]]. */ + final def asBools(): Seq[Bool] = macro SourceInfoTransform.noArg + + /** @group SourceInfoTransformMacro */ + def do_asBools(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Seq[Bool] = + Seq.tabulate(this.getWidth)(i => this(i)) + + /** Reinterpret this $coll as an [[SInt]] + * + * @note The arithmetic value is not preserved if the most-significant bit is set. For example, a [[UInt]] of + * width 3 and value 7 (0b111) would become an [[SInt]] of width 3 and value -1. + */ + final def asSInt(): SInt = macro SourceInfoTransform.noArg + + /** @group SourceInfoTransformMacro */ + def do_asSInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt + + /** Reinterpret this $coll as a [[FixedPoint]]. + * + * @note The value is not guaranteed to be preserved. For example, a [[UInt]] of width 3 and value 7 (0b111) would + * become a [[FixedPoint]] with value -1. The interpretation of the number is also affected by the specified binary + * point. '''Caution is advised!''' + */ + final def asFixedPoint(that: BinaryPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_asFixedPoint(that: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + throwException(s"Cannot call .asFixedPoint on $this") + } + + /** Reinterpret cast to Bits. */ + @chiselRuntimeDeprecated + @deprecated("Use asUInt, which does the same thing but returns a more concrete type", "chisel3") + final def asBits(implicit compileOptions: CompileOptions): Bits = { + implicit val sourceInfo = DeprecatedSourceInfo + do_asUInt + } + + @chiselRuntimeDeprecated + @deprecated("Use asSInt, which makes the reinterpret cast more explicit", "chisel3") + final def toSInt(implicit compileOptions: CompileOptions): SInt = { + implicit val sourceInfo = DeprecatedSourceInfo + do_asSInt + } + + @chiselRuntimeDeprecated + @deprecated("Use asUInt, which makes the reinterpret cast more explicit", "chisel3") + final def toUInt(implicit compileOptions: CompileOptions): UInt = { + implicit val sourceInfo = DeprecatedSourceInfo + do_asUInt + } + + final def do_asBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { + width match { + case KnownWidth(1) => this(0) + case _ => throwException(s"can't covert ${this.getClass.getSimpleName}$width to Bool") + } + } + + @chiselRuntimeDeprecated + @deprecated("Use asBool instead", "3.2") + final def do_toBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = do_asBool + + /** Concatenation operator + * + * @param that a hardware component + * @return this $coll concatenated to the most significant end of `that` + * $sumWidth + * @group Bitwise + */ + final def ## (that: Bits): UInt = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_## (that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { + val w = this.width + that.width + pushOp(DefPrim(sourceInfo, UInt(w), ConcatOp, this.ref, that.ref)) + } + + /** Default print as [[Decimal]] */ + final def toPrintable: Printable = Decimal(this) + + protected final def validateShiftAmount(x: Int): Int = { + if (x < 0) + Builder.error(s"Negative shift amounts are illegal (got $x)") + x + } +} + +// 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`. + */ +abstract 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` + * $maxWidthPlusOne + * @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]) +} + +/** A data type for unsigned integers, represented as a binary bitvector. Defines arithmetic operations between other + * integer types. + * + * @define coll [[UInt]] + * @define numType $coll + * @define expandingWidth @note The width of the returned $coll is `width of this` + `1`. + * @define constantWidth @note The width of the returned $coll is unchanged, i.e., `width of this`. + */ +sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[UInt] { + override def toString: String = { + val bindingString = litOption match { + case Some(value) => s"($value)" + case _ => bindingToString + } + s"UInt$width$bindingString" + } + + private[chisel3] override def typeEquivalent(that: Data): Boolean = + that.isInstanceOf[UInt] && this.width == that.width + + private[chisel3] override def cloneTypeWidth(w: Width): this.type = + new UInt(w).asInstanceOf[this.type] + + // TODO: refactor to share documentation with Num or add independent scaladoc + /** Unary negation (expanding width) + * + * @return a $coll equal to zero minus this $coll + * $constantWidth + * @group Arithmetic + */ + final def unary_- (): UInt = macro SourceInfoTransform.noArg + + /** Unary negation (constant width) + * + * @return a $coll equal to zero minus this $coll shifted right by one. + * $constantWidth + * @group Arithmetic + */ + final def unary_-% (): UInt = macro SourceInfoTransform.noArg + + /** @group SourceInfoTransformMacro */ + def do_unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : UInt = 0.U - this + /** @group SourceInfoTransformMacro */ + def do_unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = 0.U -% this + + override def do_+ (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this +% that + override def do_- (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this -% that + override def do_/ (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width), DivideOp, that) + override def do_% (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width), RemOp, that) + override def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width + that.width), TimesOp, that) + + /** Multiplication operator + * + * @param that a hardware [[SInt]] + * @return the product of this $coll and `that` + * $sumWidth + * $singleCycleMul + * @group Arithmetic + */ + final def * (that: SInt): SInt = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ + def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = that * this + + /** Addition operator (expanding width) + * + * @param that a hardware $coll + * @return the sum of this $coll and `that` + * $maxWidthPlusOne + * @group Arithmetic + */ + final def +& (that: UInt): UInt = macro SourceInfoTransform.thatArg + + /** Addition operator (constant width) + * + * @param that a hardware $coll + * @return the sum of this $coll and `that` + * $maxWidth + * @group Arithmetic + */ + final def +% (that: UInt): UInt = macro SourceInfoTransform.thatArg + + /** Subtraction operator (increasing width) + * + * @param that a hardware $coll + * @return the difference of this $coll less `that` + * $maxWidthPlusOne + * @group Arithmetic + */ + final def -& (that: UInt): UInt = macro SourceInfoTransform.thatArg + + /** Subtraction operator (constant width) + * + * @param that a hardware $coll + * @return the difference of this $coll less `that` + * $maxWidth + * @group Arithmetic + */ + final def -% (that: UInt): UInt = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_+& (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt((this.width max that.width) + 1), AddOp, that) + /** @group SourceInfoTransformMacro */ + def do_+% (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + (this +& that).tail(1) + /** @group SourceInfoTransformMacro */ + def do_-& (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + (this subtractAsSInt that).asUInt + /** @group SourceInfoTransformMacro */ + def do_-% (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + (this subtractAsSInt that).tail(1) + + /** Bitwise and operator + * + * @param that a hardware $coll + * @return the bitwise and of this $coll and `that` + * $maxWidth + * @group Bitwise + */ + final def & (that: UInt): UInt = macro SourceInfoTransform.thatArg + + /** Bitwise or operator + * + * @param that a hardware $coll + * @return the bitwise or of this $coll and `that` + * $maxWidth + * @group Bitwise + */ + final def | (that: UInt): UInt = macro SourceInfoTransform.thatArg + + /** Bitwise exclusive or (xor) operator + * + * @param that a hardware $coll + * @return the bitwise xor of this $coll and `that` + * $maxWidth + * @group Bitwise + */ + final def ^ (that: UInt): UInt = macro SourceInfoTransform.thatArg + + // override def abs: UInt = macro SourceInfoTransform.noArg + def do_abs(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this + + /** @group SourceInfoTransformMacro */ + def do_& (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width max that.width), BitAndOp, that) + /** @group SourceInfoTransformMacro */ + def do_| (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width max that.width), BitOrOp, that) + /** @group SourceInfoTransformMacro */ + def do_^ (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width max that.width), BitXorOp, that) + + /** @group SourceInfoTransformMacro */ + def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + unop(sourceInfo, UInt(width = width), BitNotOp) + + // REVIEW TODO: Can these be defined on Bits? + /** Or reduction operator + * + * @return a hardware [[Bool]] resulting from every bit of this $coll or'd together + * @group Bitwise + */ + final def orR(): Bool = macro SourceInfoTransform.noArg + + /** And reduction operator + * + * @return a hardware [[Bool]] resulting from every bit of this $coll and'd together + * @group Bitwise + */ + final def andR(): Bool = macro SourceInfoTransform.noArg + + /** Exclusive or (xor) reduction operator + * + * @return a hardware [[Bool]] resulting from every bit of this $coll xor'd together + * @group Bitwise + */ + final def xorR(): Bool = macro SourceInfoTransform.noArg + + /** @group SourceInfoTransformMacro */ + def do_orR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this =/= 0.U + /** @group SourceInfoTransformMacro */ + def do_andR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = width match { + // Generate a simpler expression if the width is known + case KnownWidth(w) => this === ((BigInt(1) << w) - 1).U + case UnknownWidth() => ~this === 0.U + } + /** @group SourceInfoTransformMacro */ + def do_xorR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = redop(sourceInfo, XorReduceOp) + + override def do_< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that) + override def do_> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that) + override def do_<= (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that) + override def do_>= (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that) + + @chiselRuntimeDeprecated + @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") + final def != (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this =/= that + + /** Dynamic not equals operator + * + * @param that a hardware $coll + * @return a hardware [[Bool]] asserted if this $coll is not equal to `that` + * @group Comparison + */ + final def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg + + /** Dynamic equals operator + * + * @param that a hardware $coll + * @return a hardware [[Bool]] asserted if this $coll is equal to `that` + * @group Comparison + */ + final def === (that: UInt): Bool = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_=/= (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) + /** @group SourceInfoTransformMacro */ + def do_=== (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that) + + /** Unary not + * + * @return a hardware [[Bool]] asserted if this $coll equals zero + * @group Bitwise + */ + final def unary_! () : Bool = macro SourceInfoTransform.noArg + + /** @group SourceInfoTransformMacro */ + def do_unary_! (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : Bool = this === 0.U(1.W) + + override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width + that), ShiftLeftOp, validateShiftAmount(that)) + override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + this << castToInt(that, "Shift amount") + override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width.dynamicShiftLeft(that.width)), DynamicShiftLeftOp, that) + override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width.shiftRight(that)), ShiftRightOp, validateShiftAmount(that)) + override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + this >> castToInt(that, "Shift amount") + override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width), DynamicShiftRightOp, that) + + /** Conditionally set or clear a bit + * + * @param off a dynamic offset + * @param dat set if true, clear if false + * @return a hrdware $coll with bit `off` set or cleared based on the value of `dat` + * $unchangedWidth + */ + final def bitSet(off: UInt, dat: Bool): UInt = macro UIntTransform.bitset + + /** @group SourceInfoTransformMacro */ + def do_bitSet(off: UInt, dat: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { + val bit = 1.U(1.W) << off + Mux(dat, this | bit, ~(~this | bit)) + } + + // TODO: this eventually will be renamed as toSInt, once the existing toSInt + // completes its deprecation phase. + /** Zero extend as [[SInt]] + * + * @return an [[SInt]] equal to this $coll with an additional zero in its most significant bit + * @note The width of the returned [[SInt]] is `width of this` + `1`. + */ + final def zext(): SInt = macro SourceInfoTransform.noArg + /** @group SourceInfoTransformMacro */ + def do_zext(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + pushOp(DefPrim(sourceInfo, SInt(width + 1), ConvertOp, ref)) + + override def do_asSInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + pushOp(DefPrim(sourceInfo, SInt(width), AsSIntOp, ref)) + override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this + override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): 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") + } + } + + private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions): Unit = { + this := that.asUInt + } + + private def subtractAsSInt(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt((this.width max that.width) + 1), SubOp, that) +} + +// This is currently a factory because both Bits and UInt inherit it. +trait UIntFactoryBase { + /** Create a UInt type with inferred width. */ + def apply(): UInt = apply(Width()) + /** Create a UInt port with specified width. */ + def apply(width: Width): UInt = new UInt(width) + + /** Create a UInt literal with specified width. */ + protected[chisel3] def Lit(value: BigInt, width: Width): UInt = { + val lit = ULit(value, width) + val result = new UInt(lit.width) + // Bind result to being an Literal + lit.bindLitArg(result) + } + + /** Create a UInt with the specified range */ + def apply(range: Range): UInt = { + apply(range.getWidth) + } + /** Create a UInt with the specified range */ + def apply(range: (NumericBound[Int], NumericBound[Int])): UInt = { + apply(KnownUIntRange(range._1, range._2)) + } +} + +/** A data type for signed integers, represented as a binary bitvector. Defines arithmetic operations between other + * integer types. + * + * @define coll [[SInt]] + * @define numType $coll + * @define expandingWidth @note The width of the returned $coll is `width of this` + `1`. + * @define constantWidth @note The width of the returned $coll is unchanged, i.e., `width of this`. + */ +sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[SInt] { + override def toString: String = { + val bindingString = litOption match { + case Some(value) => s"($value)" + case _ => bindingToString + } + s"SInt$width$bindingString" + } + + private[chisel3] override def typeEquivalent(that: Data): Boolean = + this.getClass == that.getClass && this.width == that.width // TODO: should this be true for unspecified widths? + + private[chisel3] override def cloneTypeWidth(w: Width): this.type = + new SInt(w).asInstanceOf[this.type] + + /** Unary negation (expanding width) + * + * @return a hardware $coll equal to zero minus this $coll + * $constantWidth + * @group Arithmetic + */ + final def unary_- (): SInt = macro SourceInfoTransform.noArg + + /** Unary negation (constant width) + * + * @return a hardware $coll equal to zero minus `this` shifted right by one + * $constantWidth + * @group Arithmetic + */ + final def unary_-% (): SInt = macro SourceInfoTransform.noArg + + /** @group SourceInfoTransformMacro */ + def unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = 0.S - this + /** @group SourceInfoTransformMacro */ + def unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = 0.S -% this + + /** add (default - no growth) operator */ + override def do_+ (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + this +% that + /** subtract (default - no growth) operator */ + override def do_- (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + this -% that + override def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt(this.width + that.width), TimesOp, that) + override def do_/ (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt(this.width), DivideOp, that) + override def do_% (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt(this.width), RemOp, that) + + /** Multiplication operator + * + * @param that a hardware $coll + * @return the product of this $coll and `that` + * $sumWidth + * $singleCycleMul + * @group Arithmetic + */ + final def * (that: UInt): SInt = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ + def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = { + val thatToSInt = that.zext() + val result = binop(sourceInfo, SInt(this.width + thatToSInt.width), TimesOp, thatToSInt) + result.tail(1).asSInt + } + + /** Addition operator (expanding width) + * + * @param that a hardware $coll + * @return the sum of this $coll and `that` + * $maxWidthPlusOne + * @group Arithmetic + */ + final def +& (that: SInt): SInt = macro SourceInfoTransform.thatArg + + /** Addition operator (constant width) + * + * @param that a hardware $coll + * @return the sum of this $coll and `that` shifted right by one + * $maxWidth + * @group Arithmetic + */ + final def +% (that: SInt): SInt = macro SourceInfoTransform.thatArg + + /** Subtraction operator (increasing width) + * + * @param that a hardware $coll + * @return the difference of this $coll less `that` + * $maxWidthPlusOne + * @group Arithmetic + */ + final def -& (that: SInt): SInt = macro SourceInfoTransform.thatArg + + /** Subtraction operator (constant width) + * + * @param that a hardware $coll + * @return the difference of this $coll less `that` shifted right by one + * $maxWidth + * @group Arithmetic + */ + final def -% (that: SInt): SInt = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_+& (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt((this.width max that.width) + 1), AddOp, that) + /** @group SourceInfoTransformMacro */ + def do_+% (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + (this +& that).tail(1).asSInt + /** @group SourceInfoTransformMacro */ + def do_-& (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt((this.width max that.width) + 1), SubOp, that) + /** @group SourceInfoTransformMacro */ + def do_-% (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + (this -& that).tail(1).asSInt + + /** Bitwise and operator + * + * @param that a hardware $coll + * @return the bitwise and of this $coll and `that` + * $maxWidth + * @group Bitwise + */ + final def & (that: SInt): SInt = macro SourceInfoTransform.thatArg + + /** Bitwise or operator + * + * @param that a hardware $coll + * @return the bitwise or of this $coll and `that` + * $maxWidth + * @group Bitwise + */ + final def | (that: SInt): SInt = macro SourceInfoTransform.thatArg + + /** Bitwise exclusive or (xor) operator + * + * @param that a hardware $coll + * @return the bitwise xor of this $coll and `that` + * $maxWidth + * @group Bitwise + */ + final def ^ (that: SInt): SInt = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_& (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, UInt(this.width max that.width), BitAndOp, that).asSInt + /** @group SourceInfoTransformMacro */ + def do_| (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, UInt(this.width max that.width), BitOrOp, that).asSInt + /** @group SourceInfoTransformMacro */ + def do_^ (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, UInt(this.width max that.width), BitXorOp, that).asSInt + + /** @group SourceInfoTransformMacro */ + def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + unop(sourceInfo, UInt(width = width), BitNotOp).asSInt + + override def do_< (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that) + override def do_> (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that) + override def do_<= (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that) + override def do_>= (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that) + + @chiselRuntimeDeprecated + @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") + final def != (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this =/= that + + /** Dynamic not equals operator + * + * @param that a hardware $coll + * @return a hardware [[Bool]] asserted if this $coll is not equal to `that` + * @group Comparison + */ + final def =/= (that: SInt): Bool = macro SourceInfoTransform.thatArg + + /** Dynamic equals operator + * + * @param that a hardware $coll + * @return a hardware [[Bool]] asserted if this $coll is equal to `that` + * @group Comparison + */ + final def === (that: SInt): Bool = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_=/= (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) + /** @group SourceInfoTransformMacro */ + def do_=== (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that) + +// final def abs(): UInt = macro SourceInfoTransform.noArg + + def do_abs(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = { + Mux(this < 0.S, (-this), this) + } + + override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt(this.width + that), ShiftLeftOp, validateShiftAmount(that)) + override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + this << castToInt(that, "Shift amount") + override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt(this.width.dynamicShiftLeft(that.width)), DynamicShiftLeftOp, that) + override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt(this.width.shiftRight(that)), ShiftRightOp, validateShiftAmount(that)) + override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + this >> castToInt(that, "Shift amount") + override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt(this.width), DynamicShiftRightOp, that) + + override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) + override def do_asSInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = this + override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): 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") + } + } + + private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { + this := that.asSInt + } +} + +trait SIntFactoryBase { + /** Create an SInt type with inferred width. */ + def apply(): SInt = apply(Width()) + /** Create a SInt type or port with fixed width. */ + def apply(width: Width): SInt = new SInt(width) + + /** Create a SInt with the specified range */ + def apply(range: Range): SInt = { + apply(range.getWidth) + } + /** Create a SInt with the specified range */ + def apply(range: (NumericBound[Int], NumericBound[Int])): SInt = { + apply(KnownSIntRange(range._1, range._2)) + } + + /** Create an SInt literal with specified width. */ + protected[chisel3] def Lit(value: BigInt, width: Width): SInt = { + val lit = SLit(value, width) + val result = new SInt(lit.width) + lit.bindLitArg(result) + } +} + +object SInt extends SIntFactoryBase + +sealed trait Reset extends Element with ToBoolable + +// REVIEW TODO: Why does this extend UInt and not Bits? Does defining airth +// operations on a Bool make sense? +/** A data type for booleans, defined as a single bit indicating true or false. + * + * @define coll [[Bool]] + * @define numType $coll + */ +sealed class Bool() extends UInt(1.W) with Reset { + override def toString: String = { + val bindingString = litToBooleanOption match { + case Some(value) => s"($value)" + case _ => bindingToString + } + s"Bool$bindingString" + } + + private[chisel3] override def cloneTypeWidth(w: Width): this.type = { + require(!w.known || w.get == 1) + new Bool().asInstanceOf[this.type] + } + + /** Convert to a [[scala.Option]] of [[scala.Boolean]] */ + def litToBooleanOption: Option[Boolean] = litOption.map { + case intVal if intVal == 1 => true + case intVal if intVal == 0 => false + case intVal => throwException(s"Boolean with unexpected literal value $intVal") + } + + /** Convert to a [[scala.Boolean]] */ + def litToBoolean: Boolean = litToBooleanOption.get + + // REVIEW TODO: Why does this need to exist and have different conventions + // than Bits? + + /** Bitwise and operator + * + * @param that a hardware $coll + * @return the bitwise and of this $coll and `that` + * @group Bitwise + */ + final def & (that: Bool): Bool = macro SourceInfoTransform.thatArg + + /** Bitwise or operator + * + * @param that a hardware $coll + * @return the bitwise or of this $coll and `that` + * @group Bitwise + */ + final def | (that: Bool): Bool = macro SourceInfoTransform.thatArg + + /** Bitwise exclusive or (xor) operator + * + * @param that a hardware $coll + * @return the bitwise xor of this $coll and `that` + * @group Bitwise + */ + final def ^ (that: Bool): Bool = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_& (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + binop(sourceInfo, Bool(), BitAndOp, that) + /** @group SourceInfoTransformMacro */ + def do_| (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + binop(sourceInfo, Bool(), BitOrOp, that) + /** @group SourceInfoTransformMacro */ + def do_^ (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + binop(sourceInfo, Bool(), BitXorOp, that) + + /** @group SourceInfoTransformMacro */ + override def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + unop(sourceInfo, Bool(), BitNotOp) + + /** Logical or operator + * + * @param that a hardware $coll + * @return the lgocial or of this $coll and `that` + * @note this is equivalent to [[Bool!.|(that:chisel3\.Bool)* Bool.|)]] + * @group Logical + */ + def || (that: Bool): Bool = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_|| (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this | that + + /** Logical and operator + * + * @param that a hardware $coll + * @return the lgocial and of this $coll and `that` + * @note this is equivalent to [[Bool!.&(that:chisel3\.Bool)* Bool.&]] + * @group Logical + */ + def && (that: Bool): Bool = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_&& (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this & that + + /** Reinterprets this $coll as a clock */ + def asClock(): Clock = macro SourceInfoTransform.noArg + + /** @group SourceInfoTransformMacro */ + def do_asClock(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Clock = pushOp(DefPrim(sourceInfo, Clock(), AsClockOp, ref)) +} + +trait BoolFactoryBase { + /** Creates an empty Bool. + */ + def apply(): Bool = new Bool() + + /** Creates Bool literal. + */ + protected[chisel3] def Lit(x: Boolean): Bool = { + val result = new Bool() + val lit = ULit(if (x) 1 else 0, Width(1)) + // Ensure we have something capable of generating a name. + lit.bindLitArg(result) + } +} + +object Bool extends BoolFactoryBase + +package experimental { + //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 + * @define coll [[FixedPoint]] + * @define numType $coll + * @define expandingWidth @note The width of the returned $coll is `width of this` + `1`. + * @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] { + import FixedPoint.Implicits._ + + override def toString: String = { + val bindingString = litToDoubleOption match { + case Some(value) => s"($value)" + case _ => bindingToString + } + s"FixedPoint$width$binaryPoint$bindingString" + } + + private[chisel3] override def typeEquivalent(that: Data): Boolean = that match { + case that: FixedPoint => this.width == that.width && this.binaryPoint == that.binaryPoint // TODO: should this be true for unspecified widths? + case _ => false + } + + private[chisel3] override def cloneTypeWidth(w: Width): this.type = + new FixedPoint(w, binaryPoint).asInstanceOf[this.type] + + override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match { + case _: FixedPoint|DontCare => super.connect(that) + 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 + * $expandingWidth + * @group Arithmetic + */ + final def unary_- (): FixedPoint = macro SourceInfoTransform.noArg + + /** Unary negation (constant width) + * + * @return a hardware $coll equal to zero minus `this` shifted right by one + * $constantWidth + * @group Arithmetic + */ + final def unary_-% (): FixedPoint = macro SourceInfoTransform.noArg + + /** @group SourceInfoTransformMacro */ + def unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = FixedPoint.fromBigInt(0) - this + /** @group SourceInfoTransformMacro */ + def unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = FixedPoint.fromBigInt(0) -% this + + /** add (default - no growth) operator */ + override def do_+ (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + this +% that + /** subtract (default - no growth) operator */ + override def do_- (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + this -% that + override def do_* (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width + that.width, this.binaryPoint + that.binaryPoint), TimesOp, that) + override def do_/ (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + throwException(s"division is illegal on FixedPoint types") + override def do_% (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + throwException(s"mod is illegal on FixedPoint types") + + + /** Multiplication operator + * + * @param that a hardware [[UInt]] + * @return the product of this $coll and `that` + * $sumWidth + * $singleCycleMul + * @group Arithmetic + */ + final def * (that: UInt): FixedPoint = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ + def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that) + + /** Multiplication operator + * + * @param that a hardware [[SInt]] + * @return the product of this $coll and `that` + * $sumWidth + * $singleCycleMul + * @group Arithmetic + */ + final def * (that: SInt): FixedPoint = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ + def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that) + + /** Addition operator (expanding width) + * + * @param that a hardware $coll + * @return the sum of this $coll and `that` + * $maxWidthPlusOne + * @group Arithmetic + */ + final def +& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** Addition operator (constant width) + * + * @param that a hardware $coll + * @return the sum of this $coll and `that` shifted right by one + * $maxWidth + * @group Arithmetic + */ + final def +% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** Subtraction operator (increasing width) + * + * @param that a hardware $coll + * @return the difference of this $coll less `that` + * $maxWidthPlusOne + * @group Arithmetic + */ + final def -& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** Subtraction operator (constant width) + * + * @param that a hardware $coll + * @return the difference of this $coll less `that` shifted right by one + * $maxWidth + * @group Arithmetic + */ + final def -% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_+& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + (this.width, that.width, this.binaryPoint, that.binaryPoint) match { + case (KnownWidth(thisWidth), KnownWidth(thatWidth), KnownBinaryPoint(thisBP), KnownBinaryPoint(thatBP)) => + val thisIntWidth = thisWidth - thisBP + val thatIntWidth = thatWidth - thatBP + val newBinaryPoint = thisBP max thatBP + val newWidth = (thisIntWidth max thatIntWidth) + newBinaryPoint + 1 + binop(sourceInfo, FixedPoint(newWidth.W, newBinaryPoint.BP), AddOp, that) + case _ => + val newBinaryPoint = this.binaryPoint max that.binaryPoint + binop(sourceInfo, FixedPoint(UnknownWidth(), newBinaryPoint), AddOp, that) + } + } + + /** @group SourceInfoTransformMacro */ + def do_+% (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + (this +& that).tail(1).asFixedPoint(this.binaryPoint max that.binaryPoint) + /** @group SourceInfoTransformMacro */ + def do_-& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + (this.width, that.width, this.binaryPoint, that.binaryPoint) match { + case (KnownWidth(thisWidth), KnownWidth(thatWidth), KnownBinaryPoint(thisBP), KnownBinaryPoint(thatBP)) => + val thisIntWidth = thisWidth - thisBP + val thatIntWidth = thatWidth - thatBP + val newBinaryPoint = thisBP max thatBP + val newWidth = (thisIntWidth max thatIntWidth) + newBinaryPoint + 1 + binop(sourceInfo, FixedPoint(newWidth.W, newBinaryPoint.BP), SubOp, that) + case _ => + val newBinaryPoint = this.binaryPoint max that.binaryPoint + binop(sourceInfo, FixedPoint(UnknownWidth(), newBinaryPoint), SubOp, that) + } + } + + /** @group SourceInfoTransformMacro */ + def do_-% (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + (this -& that).tail(1).asFixedPoint(this.binaryPoint max that.binaryPoint) + + /** Bitwise and operator + * + * @param that a hardware $coll + * @return the bitwise and of this $coll and `that` + * $maxWidth + * @group Bitwise + */ + final def & (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** Bitwise or operator + * + * @param that a hardware $coll + * @return the bitwise or of this $coll and `that` + * $maxWidth + * @group Bitwise + */ + final def | (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** Bitwise exclusive or (xor) operator + * + * @param that a hardware $coll + * @return the bitwise xor of this $coll and `that` + * $maxWidth + * @group Bitwise + */ + final def ^ (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + throwException(s"And is illegal between $this and $that") + /** @group SourceInfoTransformMacro */ + def do_| (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + throwException(s"Or is illegal between $this and $that") + /** @group SourceInfoTransformMacro */ + def do_^ (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + throwException(s"Xor is illegal between $this and $that") + + final def setBinaryPoint(that: Int): FixedPoint = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_setBinaryPoint(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = this.binaryPoint match { + case KnownBinaryPoint(value) => + binop(sourceInfo, FixedPoint(this.width + (that - value), KnownBinaryPoint(that)), SetBinaryPoint, that) + case _ => + binop(sourceInfo, FixedPoint(UnknownWidth(), KnownBinaryPoint(that)), SetBinaryPoint, that) + } + + /** @group SourceInfoTransformMacro */ + def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + throwException(s"Not is illegal on $this") + + // TODO(chick): Consider comparison with UInt and SInt + override def do_< (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that) + override def do_> (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that) + override def do_<= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that) + override def do_>= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that) + + final def != (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + + /** Dynamic not equals operator + * + * @param that a hardware $coll + * @return a hardware [[Bool]] asserted if this $coll is not equal to `that` + * @group Comparison + */ + final def =/= (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + + /** Dynamic equals operator + * + * @param that a hardware $coll + * @return a hardware [[Bool]] asserted if this $coll is equal to `that` + * @group Comparison + */ + final def === (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_!= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) + /** @group SourceInfoTransformMacro */ + def do_=/= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) + /** @group SourceInfoTransformMacro */ + def do_=== (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that) + + def do_abs(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + // TODO: remove this once we have CompileOptions threaded through the macro system. + import chisel3.ExplicitCompileOptions.NotStrict + Mux(this < 0.F(0.BP), 0.F(0.BP) - this, this) + } + + override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width + that, this.binaryPoint), ShiftLeftOp, validateShiftAmount(that)) + override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + (this << castToInt(that, "Shift amount")).asFixedPoint(this.binaryPoint) + override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width.dynamicShiftLeft(that.width), this.binaryPoint), DynamicShiftLeftOp, that) + override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width.shiftRight(that), this.binaryPoint), ShiftRightOp, validateShiftAmount(that)) + override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + (this >> castToInt(that, "Shift amount")).asFixedPoint(this.binaryPoint) + override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width, this.binaryPoint), DynamicShiftRightOp, that) + + override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) + override def do_asSInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = pushOp(DefPrim(sourceInfo, SInt(this.width), AsSIntOp, ref)) + + override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): 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") + } + } + + private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { + // TODO: redefine as just asFixedPoint on that, where FixedPoint.asFixedPoint just works. + this := (that match { + case fp: FixedPoint => fp.asSInt.asFixedPoint(this.binaryPoint) + case _ => that.asFixedPoint(this.binaryPoint) + }) + } + //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 { + + import FixedPoint.Implicits._ + /** Create an FixedPoint type with inferred width. */ + def apply(): FixedPoint = apply(Width(), BinaryPoint()) + + /** Create an FixedPoint type or port with fixed width. */ + @chiselRuntimeDeprecated + @deprecated("Use FixedPoint(width: Width, binaryPoint: BinaryPoint) example FixedPoint(16.W, 8.BP)", "chisel3") + def apply(width: Int, binaryPoint: Int): FixedPoint = apply(Width(width), BinaryPoint(binaryPoint)) + + /** Create an FixedPoint type or port with fixed width. */ + def apply(width: Width, binaryPoint: BinaryPoint): FixedPoint = new FixedPoint(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: Width, binaryPoint: BinaryPoint): FixedPoint = { + apply(value, 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, binaryPoint: BinaryPoint = 0.BP): FixedPoint = { + apply(value, 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, binaryPoint: Int): 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 + */ + @chiselRuntimeDeprecated + @deprecated("use fromDouble(value: Double, width: Width, binaryPoint: BinaryPoint)", "chisel3") + 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 literal with inferred width from Double. + * Use PrivateObject to force users to specify width and binaryPoint by name + */ + def fromDouble(value: Double, 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 = { + val lit = FPLit(value, width, binaryPoint) + val newLiteral = new FixedPoint(lit.width, lit.binaryPoint) + // Ensure we have something capable of generating a name. + 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) { + @deprecated("Use notation <double>.F(<binary_point>.BP) instead", "chisel3") + def F(binaryPoint: Int): FixedPoint = FixedPoint.fromDouble(double, binaryPoint = binaryPoint) + + def F(binaryPoint: BinaryPoint): FixedPoint = { + FixedPoint.fromDouble(double, Width(), binaryPoint) + } + + def F(width: Width, binaryPoint: BinaryPoint): FixedPoint = { + FixedPoint.fromDouble(double, width, binaryPoint) + } + } + + // implicit class fromIntToBinaryPoint(val int: Int) extends AnyVal { + implicit class fromIntToBinaryPoint(int: Int) { + def BP: BinaryPoint = BinaryPoint(int) // scalastyle:ignore method.name + } + + } + + } + /** Data type for representing bidirectional bitvectors of a given width + * + * Analog support is limited to allowing wiring up of Verilog BlackBoxes with bidirectional (inout) + * pins. There is currently no support for reading or writing of Analog types within Chisel code. + * + * Given that Analog is bidirectional, it is illegal to assign a direction to any Analog type. It + * is legal to "flip" the direction (since Analog can be a member of aggregate types) which has no + * effect. + * + * Analog types are generally connected using the bidirectional [[attach]] mechanism, but also + * support limited bulkconnect `<>`. Analog types are only allowed to be bulk connected *once* in a + * given module. This is to prevent any surprising consequences of last connect semantics. + * + * @note This API is experimental and subject to change + */ + final class Analog private (private[chisel3] val width: Width) extends Element { + require(width.known, "Since Analog is only for use in BlackBoxes, width must be known") + + override def toString: String = { + s"Analog$width$bindingToString" + } + + private[chisel3] override def typeEquivalent(that: Data): Boolean = + that.isInstanceOf[Analog] && this.width == that.width + + override def litOption: Option[BigInt] = None + + def cloneType: this.type = new Analog(width).asInstanceOf[this.type] + + // Used to enforce single bulk connect of Analog types, multi-attach is still okay + // Note that this really means 1 bulk connect per Module because a port can + // be connected in the parent module as well + private[chisel3] val biConnectLocs = mutable.Map.empty[RawModule, SourceInfo] + + // Define setter/getter pairing + // Analog can only be bound to Ports and Wires (and Unbound) + private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) { + SpecifiedDirection.fromParent(parentDirection, specifiedDirection) match { + case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => + case x => throwException(s"Analog may not have explicit direction, got '$x'") + } + val targetTopBinding = target match { + case target: TopBinding => target + case ChildBinding(parent) => parent.topBinding + // See https://github.com/freechipsproject/chisel3/pull/946 + case SampleElementBinding(parent) => parent.topBinding + } + + // Analog counts as different directions based on binding context + targetTopBinding match { + case WireBinding(_) => direction = ActualDirection.Unspecified // internal wire + case PortBinding(_) => direction = ActualDirection.Bidirectional(ActualDirection.Default) + case x => throwException(s"Analog can only be Ports and Wires, not '$x'") + } + binding = target + } + + override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + throwException("Analog does not support asUInt") + + private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions): Unit = { + throwException("Analog does not support connectFromBits") + } + + final def toPrintable: Printable = PString("Analog") + } + /** Object that provides factory methods for [[Analog]] objects + * + * @note This API is experimental and subject to change + */ + object Analog { + def apply(width: Width): Analog = new Analog(width) + } +} |
