diff --git a/core/src/main/scala/chisel3/internal/firrtl/IR.scala b/core/src/main/scala/chisel3/internal/firrtl/IR.scala index fe04bc7681c..2117d08d608 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -171,7 +171,9 @@ private[chisel3] object ir { val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n s"asSInt(${ULit(unsigned, width).name})" } - def minWidth: Int = (if (w.known) 0 else 1) + n.bitLength + + // Special case for 0 which can be specified to zero-width (but defaults to 1 bit). + def minWidth: Int = if (n == 0 && w.known) 0 else 1 + n.bitLength def cloneWithWidth(newWidth: Width): this.type = { SLit(n, newWidth).asInstanceOf[this.type] diff --git a/src/test/scala-2/chiselTests/SIntOps.scala b/src/test/scala-2/chiselTests/SIntOps.scala index 273fcb67b4b..02144d9fb3f 100644 --- a/src/test/scala-2/chiselTests/SIntOps.scala +++ b/src/test/scala-2/chiselTests/SIntOps.scala @@ -284,4 +284,18 @@ class SIntOpsSpec extends AnyPropSpec with Matchers with ShiftRightWidthBehavior blit.x.litOption should be(Some(2)) blit.y.litOption should be(Some(9)) } + + property("SInt literals with too small of a width should be rejected") { + // Sanity checks. + 0.S.getWidth should be(1) + 0.S(0.W).getWidth should be(0) + -1.S.getWidth should be(1) + 1.S.getWidth should be(2) + // The real check. + -2.S.getWidth should be(2) + an[IllegalArgumentException] shouldBe thrownBy(-2.S(1.W)) + 0xde.S.getWidth should be(9) + an[IllegalArgumentException] shouldBe thrownBy(0xde.S(8.W)) + an[IllegalArgumentException] shouldBe thrownBy(0xde.S(4.W)) + } }