Skip to content

Commit

Permalink
Preserve literal value across .asSInt and .zext (#4151) (#4152)
Browse files Browse the repository at this point in the history
(cherry picked from commit dbbf73a)

Co-authored-by: Jack Koenig <koenig@sifive.com>
  • Loading branch information
mergify[bot] and jackkoenig authored Jun 6, 2024
1 parent f7ae1fc commit 3f53bed
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 4 deletions.
24 changes: 20 additions & 4 deletions core/src/main/scala/chisel3/Bits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -757,11 +757,27 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U
final def zext: SInt = macro SourceInfoTransform.noArg

/** @group SourceInfoTransformMacro */
def do_zext(implicit sourceInfo: SourceInfo): SInt =
pushOp(DefPrim(sourceInfo, SInt(width + 1), ConvertOp, ref))
def do_zext(implicit sourceInfo: SourceInfo): SInt = this.litOption match {
case Some(value) => SInt.Lit(value, this.width + 1)
case None => pushOp(DefPrim(sourceInfo, SInt(width + 1), ConvertOp, ref))
}

override def do_asSInt(implicit sourceInfo: SourceInfo): SInt =
pushOp(DefPrim(sourceInfo, SInt(width), AsSIntOp, ref))
override def do_asSInt(implicit sourceInfo: SourceInfo): SInt = this.litOption match {
case Some(value) =>
val w = this.width.get // Literals always have a known width, will be minimum legal width if not set
val signedValue =
// If width is 0, just return value (which will be 0).
if (w > 0 && value.testBit(w - 1)) {
// If the most significant bit is set, the SInt is negative and we need to adjust the value.
value - (BigInt(1) << w)
} else {
value
}
// Using SInt.Lit instead of .S so we can use Width argument which may be Unknown
SInt.Lit(signedValue, this.width.max(Width(1))) // SInt literal has width >= 1
case None =>
pushOp(DefPrim(sourceInfo, SInt(width), AsSIntOp, ref))
}

override private[chisel3] def _asUIntImpl(first: Boolean)(implicit sourceInfo: SourceInfo): UInt = this

Expand Down
5 changes: 5 additions & 0 deletions src/test/scala/chiselTests/SIntOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,9 @@ class SIntOpsSpec extends ChiselPropSpec with Utils {
}
}
}

property("Calling .asSInt on a SInt literal should maintain the literal value") {
3.S.asSInt.litValue should be(3)
-5.S.asSInt.litValue should be(-5)
}
}
18 changes: 18 additions & 0 deletions src/test/scala/chiselTests/UIntOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -494,4 +494,22 @@ class UIntOpsSpec extends ChiselPropSpec with Matchers with Utils {
property("Calling .asUInt on a UInt literal should maintain the literal value") {
3.U.asUInt.litValue should be(3)
}

property("Calling .asSInt on a UInt literal should reinterpret the literal value") {
5.U.asSInt.litValue should be(-3)
5.U(8.W).asSInt.litValue should be(5)
0.U.asSInt.litValue should be(0)
0.U.asSInt.widthOption should be(Some(1))
// There are no zero-width SInt literals
0.U(0.W).asSInt.widthOption should be(Some(1))
}

property("Calling .zext on a UInt literal should maintain the literal value") {
5.U.zext.litValue should be(5)
5.U.zext.getWidth should be(4)
5.U(8.W).zext.litValue should be(5)
0.U.zext.litValue should be(0)
0.U.zext.widthOption should be(Some(2))
0.U(0.W).zext.widthOption should be(Some(1))
}
}

0 comments on commit 3f53bed

Please sign in to comment.