diff options
| author | Andrew Waterman | 2016-01-28 12:15:53 -0800 |
|---|---|---|
| committer | Andrew Waterman | 2016-01-28 12:15:53 -0800 |
| commit | 7eff2b0a16e1ca982c227bd498720981c883686b (patch) | |
| tree | 767a04718b16750b33dd4e2d629d3e836bb7f637 /src/main/scala/Chisel/Bits.scala | |
| parent | 6d37cc8b9d731fa4c844f097b11057c46771961b (diff) | |
| parent | 41674d5e130f64d7489fdb8583b8f4ad88b64aeb (diff) | |
Merge branch 'master' into scalastyle
Diffstat (limited to 'src/main/scala/Chisel/Bits.scala')
| -rw-r--r-- | src/main/scala/Chisel/Bits.scala | 76 |
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) } } |
