summaryrefslogtreecommitdiff
path: root/src/main/scala/Chisel/Bits.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/Chisel/Bits.scala')
-rw-r--r--src/main/scala/Chisel/Bits.scala76
1 files changed, 50 insertions, 26 deletions
diff --git a/src/main/scala/Chisel/Bits.scala b/src/main/scala/Chisel/Bits.scala
index e001f864..b800644d 100644
--- a/src/main/scala/Chisel/Bits.scala
+++ b/src/main/scala/Chisel/Bits.scala
@@ -4,15 +4,13 @@ package Chisel
import internal._
import internal.Builder.pushOp
-import firrtl._
+import internal.firrtl._
import firrtl.PrimOp._
/** Element is a leaf data type: it cannot contain other Data objects. Example
* uses are for representing primitive data types, like integers and bits.
*/
-abstract class Element(dirArg: Direction, val width: Width) extends Data(dirArg) {
- private[Chisel] def flatten: IndexedSeq[UInt] = IndexedSeq(toBits)
-}
+abstract class Element(dirArg: Direction, val width: Width) extends Data(dirArg)
/** A data type for values represented by a single bitvector. Provides basic
* bitwise operations.
@@ -25,10 +23,30 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
private[Chisel] def fromInt(x: BigInt): this.type
+ private[Chisel] def flatten: IndexedSeq[Bits] = IndexedSeq(this)
+
def cloneType: this.type = cloneTypeWidth(width)
override def <> (that: Data): Unit = this := that
+ def tail(n: Int): 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(UInt(width = w), TailOp, n)
+ }
+
+ def head(n: Int): UInt = {
+ width match {
+ case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n")
+ case UnknownWidth() =>
+ }
+ binop(UInt(width = n), HeadOp, n)
+ }
+
/** Returns the specified bit on this wire as a [[Bool]], statically
* addressed.
*/
@@ -39,7 +57,7 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
if (isLit()) {
Bool(((litValue() >> x.toInt) & 1) == 1)
} else {
- pushOp(DefPrim(Bool(), BitSelectOp, this.ref, ILit(x)))
+ pushOp(DefPrim(Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x)))
}
}
@@ -92,9 +110,6 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
private[Chisel] def redop(op: PrimOp): Bool =
pushOp(DefPrim(Bool(), op, this.ref))
- /** Returns this wire bitwise-inverted. */
- def unary_~ : this.type = unop(cloneTypeWidth(width), BitNotOp)
-
/** Returns this wire zero padded up to the specified width.
*
* @note for SInts only, this does sign extension
@@ -279,19 +294,22 @@ sealed class UInt private[Chisel] (dir: Direction, width: Width, lit: Option[ULi
def unary_-% : UInt = UInt(0) -% this
def +& (other: UInt): UInt = binop(UInt((this.width max other.width) + 1), AddOp, other)
def + (other: UInt): UInt = this +% other
- def +% (other: UInt): UInt = binop(UInt(this.width max other.width), AddModOp, other)
+ def +% (other: UInt): UInt = (this +& other) tail 1
def -& (other: UInt): UInt = binop(UInt((this.width max other.width) + 1), SubOp, other)
def - (other: UInt): UInt = this -% other
- def -% (other: UInt): UInt = binop(UInt(this.width max other.width), SubModOp, other)
+ def -% (other: UInt): UInt = (this -& other) tail 1
def * (other: UInt): UInt = binop(UInt(this.width + other.width), TimesOp, other)
def * (other: SInt): SInt = other * this
def / (other: UInt): UInt = binop(UInt(this.width), DivideOp, other)
- def % (other: UInt): UInt = binop(UInt(this.width), ModOp, other)
+ def % (other: UInt): UInt = binop(UInt(this.width), RemOp, other)
def & (other: UInt): UInt = binop(UInt(this.width max other.width), BitAndOp, other)
def | (other: UInt): UInt = binop(UInt(this.width max other.width), BitOrOp, other)
def ^ (other: UInt): UInt = binop(UInt(this.width max other.width), BitXorOp, other)
+ /** Returns this wire bitwise-inverted. */
+ def unary_~ : UInt = unop(UInt(width = width), BitNotOp)
+
// REVIEW TODO: Can this be defined on Bits?
def orR: Bool = this != UInt(0)
def andR: Bool = ~this === UInt(0)
@@ -321,6 +339,7 @@ sealed class UInt private[Chisel] (dir: Direction, width: Width, lit: Option[ULi
def === (that: BitPat): Bool = that === this
def != (that: BitPat): Bool = that != this
+ def =/= (that: BitPat): Bool = that =/= this
/** Returns this UInt as a [[SInt]] with an additional zero in the MSB.
*/
@@ -409,21 +428,24 @@ sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = Non
/** add (default - no growth) operator */
def + (other: SInt): SInt = this +% other
/** add (no growth) operator */
- def +% (other: SInt): SInt = binop(SInt(this.width max other.width), AddModOp, other)
+ def +% (other: SInt): SInt = (this +& other).tail(1).asSInt
/** subtract (width +1) operator */
def -& (other: SInt): SInt = binop(SInt((this.width max other.width) + 1), SubOp, other)
/** subtract (default - no growth) operator */
def - (other: SInt): SInt = this -% other
/** subtract (no growth) operator */
- def -% (other: SInt): SInt = binop(SInt(this.width max other.width), SubModOp, other)
+ def -% (other: SInt): SInt = (this -& other).tail(1).asSInt
def * (other: SInt): SInt = binop(SInt(this.width + other.width), TimesOp, other)
def * (other: UInt): SInt = binop(SInt(this.width + other.width), TimesOp, other)
def / (other: SInt): SInt = binop(SInt(this.width), DivideOp, other)
- def % (other: SInt): SInt = binop(SInt(this.width), ModOp, other)
+ def % (other: SInt): SInt = binop(SInt(this.width), RemOp, other)
- def & (other: SInt): SInt = binop(SInt(this.width max other.width), BitAndOp, other)
- def | (other: SInt): SInt = binop(SInt(this.width max other.width), BitOrOp, other)
- def ^ (other: SInt): SInt = binop(SInt(this.width max other.width), BitXorOp, other)
+ def & (other: SInt): SInt = binop(UInt(this.width max other.width), BitAndOp, other).asSInt
+ def | (other: SInt): SInt = binop(UInt(this.width max other.width), BitOrOp, other).asSInt
+ def ^ (other: SInt): SInt = binop(UInt(this.width max other.width), BitXorOp, other).asSInt
+
+ /** Returns this wire bitwise-inverted. */
+ def unary_~ : SInt = unop(UInt(width = width), BitNotOp).asSInt
def < (other: SInt): Bool = compop(LessOp, other)
def > (other: SInt): Bool = compop(GreaterOp, other)
@@ -431,7 +453,7 @@ sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = Non
def >= (other: SInt): Bool = compop(GreaterEqOp, other)
def != (other: SInt): Bool = compop(NotEqualOp, other)
def === (other: SInt): Bool = compop(EqualOp, other)
- def abs(): UInt = Mux(this < SInt(0), (-this).toUInt, this.toUInt)
+ def abs(): UInt = Mux(this < SInt(0), (-this).asUInt, this.asUInt)
def << (other: Int): SInt = binop(SInt(this.width + other), ShiftLeftOp, other)
def << (other: BigInt): SInt = this << other.toInt
@@ -489,6 +511,9 @@ sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Wi
def | (other: Bool): Bool = binop(Bool(), BitOrOp, other)
def ^ (other: Bool): Bool = binop(Bool(), BitXorOp, other)
+ /** Returns this wire bitwise-inverted. */
+ override def unary_~ : Bool = unop(Bool(), BitNotOp)
+
/** Outputs the logical OR of two Bools.
*/
def || (that: Bool): Bool = this | that
@@ -526,21 +551,20 @@ object Mux {
case (c: UInt, a: Bool) => doMux(cond, c, a << 0).asInstanceOf[T]
case (c: Bool, a: UInt) => doMux(cond, c << 0, a).asInstanceOf[T]
case (c: Bits, a: Bits) => doMux(cond, c, a).asInstanceOf[T]
- // FIRRTL doesn't support Mux for aggregates, so use a when instead
- case _ => doWhen(cond, con, alt)
+ case _ => doAggregateMux(cond, con, alt)
}
- private def doMux[T <: Bits](cond: Bool, con: T, alt: T): T = {
+ private def doMux[T <: Data](cond: Bool, con: T, alt: T): T = {
require(con.getClass == alt.getClass, s"can't Mux between ${con.getClass} and ${alt.getClass}")
val d = alt.cloneTypeWidth(con.width max alt.width)
pushOp(DefPrim(d, MultiplexOp, cond.ref, con.ref, alt.ref))
}
- // This returns an lvalue, which it most definitely should not
- private def doWhen[T <: Data](cond: Bool, con: T, alt: T): T = {
+
+ private def doAggregateMux[T <: Data](cond: Bool, con: T, alt: T): T = {
require(con.getClass == alt.getClass, s"can't Mux between ${con.getClass} and ${alt.getClass}")
- val res = Wire(t = alt.cloneTypeWidth(con.width max alt.width), init = alt)
- when (cond) { res := con }
- res
+ for ((c, a) <- con.flatten zip alt.flatten)
+ require(c.width == a.width, "can't Mux between aggregates of different width")
+ doMux(cond, con, alt)
}
}