Skip to content

Commit

Permalink
Preserve literal value across .asSInt and .zext
Browse files Browse the repository at this point in the history
  • Loading branch information
jackkoenig committed Jun 6, 2024
1 parent d35daa2 commit e32aedc
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
23 changes: 19 additions & 4 deletions core/src/main/scala/chisel3/Bits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -778,11 +778,26 @@ 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 (w > 0 && value.testBit(w - 1)) { // if width is 0, just return value (which will be 0)
// If the most significant bit the SInt will be negative and we need to reinterpret
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))) // Zero-width
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 @@ -247,4 +247,9 @@ class SIntOpsSpec extends ChiselPropSpec with Utils with ShiftRightWidthBehavior
}
}
}

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 @@ -611,4 +611,22 @@ class UIntOpsSpec extends ChiselPropSpec with Matchers with Utils with ShiftRigh
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 e32aedc

Please sign in to comment.