summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormergify[bot]2022-08-12 20:04:33 +0000
committerGitHub2022-08-12 20:04:33 +0000
commit7bad3d2ec316f24f3da79d1dfef19e128cfe8bf5 (patch)
tree67337939dbb98f8a6c127560156213c3c2420515
parentdb18ae16a26dab5231ca83172c88b9735a977582 (diff)
Add ability to suppress enum cast warnings (#2671) (#2674)
(cherry picked from commit 1ad820f7f549eddcd7188b737f59a240e48a7f0a) Co-authored-by: Zachary Yedidia <zyedidia@gmail.com>
-rw-r--r--core/src/main/scala/chisel3/StrongEnum.scala32
-rw-r--r--core/src/main/scala/chisel3/internal/Builder.scala4
-rw-r--r--docs/src/explanations/chisel-enum.md25
-rw-r--r--src/test/scala/chiselTests/StrongEnum.scala41
4 files changed, 101 insertions, 1 deletions
diff --git a/core/src/main/scala/chisel3/StrongEnum.scala b/core/src/main/scala/chisel3/StrongEnum.scala
index cd6f11ee..6d8ceb2f 100644
--- a/core/src/main/scala/chisel3/StrongEnum.scala
+++ b/core/src/main/scala/chisel3/StrongEnum.scala
@@ -339,7 +339,7 @@ abstract class EnumFactory {
} else if (n.getWidth > this.getWidth) {
throwException(s"The UInt being cast to $enumTypeName is wider than $enumTypeName's width ($getWidth)")
} else {
- if (warn && !this.isTotal) {
+ if (!Builder.suppressEnumCastWarning && warn && !this.isTotal) {
Builder.warning(
s"Casting non-literal UInt to $enumTypeName. You can use $enumTypeName.safe to cast without this warning."
)
@@ -409,3 +409,33 @@ private[chisel3] class UnsafeEnum(override val width: Width) extends EnumType(Un
override def cloneType: this.type = new UnsafeEnum(width).asInstanceOf[this.type]
}
private object UnsafeEnum extends EnumFactory
+
+/** Suppress enum cast warnings
+ *
+ * Users should use [[EnumFactory.safe <EnumType>.safe]] when possible.
+ *
+ * This is primarily used for casting from [[UInt]] to a Bundle type that contains an Enum.
+ * {{{
+ * class MyBundle extends Bundle {
+ * val addr = UInt(8.W)
+ * val op = OpEnum()
+ * }
+ *
+ * // Since this is a cast to a Bundle, cannot use OpCode.safe
+ * val bundle = suppressEnumCastWarning {
+ * someUInt.asTypeOf(new MyBundle)
+ * }
+ * }}}
+ */
+object suppressEnumCastWarning {
+ def apply[T](block: => T): T = {
+ val parentWarn = Builder.suppressEnumCastWarning
+
+ Builder.suppressEnumCastWarning = true
+
+ val res = block // execute block
+
+ Builder.suppressEnumCastWarning = parentWarn
+ res
+ }
+}
diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala
index 25f4c44c..b2c98309 100644
--- a/core/src/main/scala/chisel3/internal/Builder.scala
+++ b/core/src/main/scala/chisel3/internal/Builder.scala
@@ -435,6 +435,7 @@ private[chisel3] class DynamicContext(
var currentReset: Option[Reset] = None
val errors = new ErrorLog
val namingStack = new NamingStack
+
// Used to indicate if this is the top-level module of full elaboration, or from a Definition
var inDefinition: Boolean = false
}
@@ -451,6 +452,9 @@ private[chisel3] object Builder extends LazyLogging {
dynamicContextVar.value.get
}
+ // Used to suppress warnings when casting from a UInt to an Enum
+ var suppressEnumCastWarning: Boolean = false
+
// Returns the current dynamic context
def captureContext(): DynamicContext = dynamicContext
// Sets the current dynamic contents
diff --git a/docs/src/explanations/chisel-enum.md b/docs/src/explanations/chisel-enum.md
index a390aea4..16b5570d 100644
--- a/docs/src/explanations/chisel-enum.md
+++ b/docs/src/explanations/chisel-enum.md
@@ -17,6 +17,7 @@ import chisel3._
import chisel3.util._
import chisel3.stage.ChiselStage
import chisel3.experimental.ChiselEnum
+import chisel3.experimental.suppressEnumCastWarning
```
```scala mdoc:invisible
@@ -167,6 +168,30 @@ val (log2, _) = grabLog(ChiselStage.emitChirrtl(new SafeFromUInt))
println(s"```\n$log2```")
```
+You can also suppress the warning by using `suppressEnumCastWarning`. This is
+primarily used for casting from [[UInt]] to a Bundle type that contains an
+Enum, where the [[UInt]] is known to be valid for the Bundle type.
+
+```scala mdoc
+class MyBundle extends Bundle {
+ val addr = UInt(8.W)
+ val op = Opcode()
+}
+
+class SuppressedFromUInt extends Module {
+ val in = IO(Input(UInt(15.W)))
+ val out = IO(Output(new MyBundle()))
+ suppressEnumCastWarning {
+ out := in.asTypeOf(new MyBundle)
+ }
+}
+```
+
+```scala mdoc:invisible
+val (log3, _) = grabLog(ChiselStage.emitChirrtl(new SuppressedFromUInt))
+assert(log3.isEmpty)
+```
+
## Testing
The _Type_ of the enums values is `<ChiselEnum Object>.Type` which can be useful for passing the values
diff --git a/src/test/scala/chiselTests/StrongEnum.scala b/src/test/scala/chiselTests/StrongEnum.scala
index 44ed77f9..5b1b13fd 100644
--- a/src/test/scala/chiselTests/StrongEnum.scala
+++ b/src/test/scala/chiselTests/StrongEnum.scala
@@ -5,6 +5,7 @@ package chiselTests
import chisel3._
import chisel3.experimental.ChiselEnum
import chisel3.experimental.AffectsChiselPrefix
+import chisel3.experimental.suppressEnumCastWarning
import chisel3.internal.firrtl.UnknownWidth
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
import chisel3.util._
@@ -481,6 +482,46 @@ class StrongEnumSpec extends ChiselFlatSpec with Utils {
(log should not).include("warn")
}
+ it should "suppress warning using suppressEnumCastWarning" in {
+ object TestEnum extends ChiselEnum {
+ val e0, e1, e2 = Value
+ }
+
+ class MyModule extends Module {
+ val in = IO(Input(UInt(2.W)))
+ val out = IO(Output(TestEnum()))
+ suppressEnumCastWarning {
+ val res = TestEnum(in)
+ out := res
+ }
+ }
+ val (log, _) = grabLog(ChiselStage.elaborate(new MyModule))
+ (log should not).include("warn")
+ }
+
+ it should "suppress exactly one warning using suppressEnumCastWarning" in {
+ object TestEnum1 extends ChiselEnum {
+ val e0, e1, e2 = Value
+ }
+ object TestEnum2 extends ChiselEnum {
+ val e0, e1, e2 = Value
+ }
+
+ class MyModule extends Module {
+ val in = IO(Input(UInt(2.W)))
+ val out1 = IO(Output(TestEnum1()))
+ val out2 = IO(Output(TestEnum2()))
+ suppressEnumCastWarning {
+ out1 := TestEnum1(in)
+ }
+ out2 := TestEnum2(in)
+ }
+ val (log, _) = grabLog(ChiselStage.elaborate(new MyModule))
+ log should include("warn")
+ log should include("TestEnum2") // not suppressed
+ (log should not).include("TestEnum1") // suppressed
+ }
+
"Casting a UInt to an Enum with .safe" should "NOT warn" in {
object MyEnum extends ChiselEnum {
val e0, e1, e2 = Value