summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/scala/chisel3/StrongEnum.scala34
1 files changed, 30 insertions, 4 deletions
diff --git a/core/src/main/scala/chisel3/StrongEnum.scala b/core/src/main/scala/chisel3/StrongEnum.scala
index 7d328eb7..1d0e04d3 100644
--- a/core/src/main/scala/chisel3/StrongEnum.scala
+++ b/core/src/main/scala/chisel3/StrongEnum.scala
@@ -131,7 +131,7 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea
if (litOption.isDefined) {
true.B
} else {
- factory.all.map(this === _).reduce(_ || _)
+ if (factory.isTotal) true.B else factory.all.map(this === _).reduce(_ || _)
}
}
@@ -233,6 +233,12 @@ abstract class EnumFactory {
private[chisel3] val enumTypeName = getClass.getName.init
+ // Do all bitvectors of this Enum's width represent legal states?
+ private[chisel3] def isTotal: Boolean = {
+ (this.getWidth < 31) && // guard against Integer overflow
+ (enumRecords.size == (1 << this.getWidth))
+ }
+
private[chisel3] def globalAnnotation: EnumDefChiselAnnotation =
EnumDefChiselAnnotation(enumTypeName, (enumNames, enumValues).zipped.toMap)
@@ -277,7 +283,7 @@ abstract class EnumFactory {
def apply(): Type = new Type
- def apply(n: UInt)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Type = {
+ private def castImpl(n: UInt, warn: Boolean)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Type = {
if (n.litOption.isDefined) {
enumInstances.find(_.litValue == n.litValue) match {
case Some(result) => result
@@ -288,8 +294,9 @@ 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 {
- Builder.warning(s"Casting non-literal UInt to $enumTypeName. You can check that its value is legal by calling isValid")
-
+ if (warn && !this.isTotal) {
+ Builder.warning(s"Casting non-literal UInt to $enumTypeName. You can use $enumTypeName.safe to cast without this warning.")
+ }
val glue = Wire(new UnsafeEnum(width))
glue := n
val result = Wire(new Type)
@@ -297,6 +304,25 @@ abstract class EnumFactory {
result
}
}
+
+ /** Cast an [[UInt]] to the type of this Enum
+ *
+ * @note will give a Chisel elaboration time warning if the argument could hit invalid states
+ * @param n the UInt to cast
+ * @return the equivalent Enum to the value of the cast UInt
+ */
+ def apply(n: UInt)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Type = castImpl(n, warn = true)
+
+ /** Safely cast an [[UInt]] to the type of this Enum
+ *
+ * @param n the UInt to cast
+ * @return the equivalent Enum to the value of the cast UInt and a Bool indicating if the
+ * Enum is valid
+ */
+ def safe(n: UInt)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): (Type, Bool) = {
+ val t = castImpl(n, warn = false)
+ (t, t.isValid)
+ }
}