diff options
| author | grebe | 2017-01-13 09:51:18 -0800 |
|---|---|---|
| committer | Chick Markley | 2017-01-13 09:51:18 -0800 |
| commit | f19653fbe9d2e1b49c49c31ddb98a758c390ba94 (patch) | |
| tree | cd295142ab5a0040c4beb5606fc1c2cdc2901e28 | |
| parent | 3215df07a97b58babb1deb3fab0928198b1daad2 (diff) | |
Make fromBits work with types other than UInt (#424)
* Make fromBits work with types other than UInt
* Oops, left in a println
* Add test for truncation/expansion
* Fix stuff that broke when FixedPoint fromBits PR was merged.
* Use .BP shorthand added in previous PR
5 files changed, 114 insertions, 25 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 26c971b3..559a55bc 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -21,6 +21,21 @@ sealed abstract class Aggregate extends Data { pushCommand(BulkConnect(sourceInfo, this.lref, that.lref)) override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = SeqUtils.do_asUInt(this.flatten) + def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = { + var i = 0 + val wire = Wire(this.chiselCloneType) + val bits = + if (that.width.known && that.width.get >= wire.width.get) { + that + } else { + Wire(that.cloneTypeWidth(wire.width), init = that) + } + for (x <- wire.flatten) { + x := x.fromBits(bits(i + x.getWidth-1, i)) + i += x.getWidth + } + wire.asInstanceOf[this.type] + } } object Vec { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index c5fc10e7..e885f1ee 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -292,12 +292,6 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg]) pushOp(DefPrim(sourceInfo, UInt(w), ConcatOp, this.ref, that.ref)) } - override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = { - val res = Wire(this, null).asInstanceOf[this.type] - res := that - res - } - /** Default print as [[Decimal]] */ final def toPrintable: Printable = Decimal(this) } @@ -519,6 +513,14 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) throwException(s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint") } } + def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = { + val res = Wire(this, null).asInstanceOf[this.type] + res := (that match { + case u: UInt => u + case _ => that.asUInt + }) + res + } } // This is currently a factory because both Bits and UInt inherit it. @@ -655,6 +657,14 @@ sealed class SInt private[core] (width: Width, lit: Option[SLit] = None) throwException(s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint") } } + def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = { + val res = Wire(this, null).asInstanceOf[this.type] + res := (that match { + case s: SInt => s + case _ => that.asSInt + }) + res + } } trait SIntFactory { @@ -916,13 +926,15 @@ sealed class FixedPoint private (width: Width, val binaryPoint: BinaryPoint, lit override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) override def do_asSInt(implicit sourceInfo: SourceInfo): SInt = pushOp(DefPrim(sourceInfo, SInt(this.width), AsSIntOp, ref)) - //TODO(chick): Consider "convert" as an arithmetic conversion to UInt/SInt - - override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = { + def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = { val res = Wire(this, null).asInstanceOf[this.type] - res := that.asFixedPoint(this.binaryPoint) + res := (that match { + case fp: FixedPoint => fp.asSInt.asFixedPoint(this.binaryPoint) + case _ => that.asFixedPoint(this.binaryPoint) + }) res } + //TODO(chick): Consider "convert" as an arithmetic conversion to UInt/SInt } /** Use PrivateObject to force users to specify width and binaryPoint by name diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 57ed0c59..6e80f045 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -238,21 +238,7 @@ abstract class Data extends HasId { */ def fromBits(that: Bits): this.type = macro CompileOptionsTransform.thatArg - def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = { - var i = 0 - val wire = Wire(this.chiselCloneType) - val bits = - if (that.width.known && that.width.get >= wire.width.get) { - that - } else { - Wire(that.cloneTypeWidth(wire.width), init = that) - } - for (x <- wire.flatten) { - x := bits(i + x.getWidth-1, i) - i += x.getWidth - } - wire.asInstanceOf[this.type] - } + def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type /** Packs the value of this object as plain Bits. * @@ -337,4 +323,9 @@ sealed class Clock extends Element(Width(1)) { def toPrintable: Printable = PString("CLOCK") override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) + override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = { + val ret = Wire(this.cloneType) + ret := that + ret.asInstanceOf[this.type] + } } diff --git a/src/test/scala/chiselTests/FixedPointSpec.scala b/src/test/scala/chiselTests/FixedPointSpec.scala index a08de073..4e6af33b 100644 --- a/src/test/scala/chiselTests/FixedPointSpec.scala +++ b/src/test/scala/chiselTests/FixedPointSpec.scala @@ -22,15 +22,19 @@ class FixedPointLiteralSpec extends FlatSpec with Matchers { class FixedPointFromBitsTester extends BasicTester { val uint = 3.U(4.W) val sint = -3.S + val fp = FixedPoint.fromDouble(3.0, width = 4, binaryPoint = 0) val fp_tpe = FixedPoint(4.W, 1.BP) val uint_result = FixedPoint.fromDouble(1.5, width = 4, binaryPoint = 1) val sint_result = FixedPoint.fromDouble(-1.5, width = 4, binaryPoint = 1) + val fp_result = FixedPoint.fromDouble(1.5, width = 4, binaryPoint = 1) val uint2fp = fp_tpe.fromBits(uint) val sint2fp = fp_tpe.fromBits(sint) + val fp2fp = fp_tpe.fromBits(fp) assert(uint2fp === uint_result) assert(sint2fp === sint_result) + assert(fp2fp === fp_result) stop() } diff --git a/src/test/scala/chiselTests/FromBitsTester.scala b/src/test/scala/chiselTests/FromBitsTester.scala new file mode 100644 index 00000000..5809b386 --- /dev/null +++ b/src/test/scala/chiselTests/FromBitsTester.scala @@ -0,0 +1,67 @@ +// See LICENSE for license details. + +package chiselTests + +import org.scalatest._ + +import chisel3._ +import chisel3.testers.BasicTester +import chisel3.util._ +import chisel3.core.DataMirror + +class FromBitsBundleTester extends BasicTester { + class MultiTypeBundle extends Bundle { + val u = UInt(4.W) + val s = SInt(4.W) + val fp = FixedPoint(4.W, 3.BP) + } + + val bun = new MultiTypeBundle + + val bunFromBits = bun.fromBits( ((4 << 8) + (15 << 4) + (12 << 0)).U ) + + assert(bunFromBits.u === 4.U) + assert(bunFromBits.s === -1.S) + assert(bunFromBits.fp === FixedPoint.fromDouble(-0.5, width=4, binaryPoint=3)) + + stop() +} + +class FromBitsVecTester extends BasicTester { + val vec = Vec(4, SInt(4.W)).fromBits( ((15 << 12) + (0 << 8) + (1 << 4) + (2 << 0)).U ) + + assert(vec(0) === 2.S) + assert(vec(1) === 1.S) + assert(vec(2) === 0.S) + assert(vec(3) === -1.S) + + stop() +} + +class FromBitsTruncationTester extends BasicTester { + val truncate = UInt(3.W).fromBits( (64 + 3).U ) + val expand = UInt(3.W).fromBits( 1.U ) + + assert( DataMirror.widthOf(truncate).get == 3 ) + assert( truncate === 3.U ) + assert( DataMirror.widthOf(expand).get == 3 ) + assert( expand === 1.U ) + + stop() +} + +class FromBitsSpec extends ChiselFlatSpec { + behavior of "fromBits" + + it should "work with Bundles containing Bits Types" in { + assertTesterPasses{ new FromBitsBundleTester } + } + + it should "work with Vecs containing Bits Types" in { + assertTesterPasses{ new FromBitsVecTester } + } + + it should "expand and truncate UInts of different width" in { + assertTesterPasses{ new FromBitsTruncationTester } + } +} |
