summaryrefslogtreecommitdiff
path: root/core/src/main/scala/chisel3/StrongEnum.scala
diff options
context:
space:
mode:
authorJack2022-11-11 06:53:04 +0000
committerJack2022-11-11 06:53:04 +0000
commit3ce953c81f06519351c48277e3474b5720ec07ff (patch)
treeac79dcb80d0528c2ae86ca21da4cf424715ab645 /core/src/main/scala/chisel3/StrongEnum.scala
parentadccde9998c91875e5490cff6d5822ffacc593ed (diff)
parentc8046636a25474be4c547c6fe9c6d742ea7b1d13 (diff)
Merge branch '3.5.x' into 3.5-release
Diffstat (limited to 'core/src/main/scala/chisel3/StrongEnum.scala')
-rw-r--r--core/src/main/scala/chisel3/StrongEnum.scala57
1 files changed, 55 insertions, 2 deletions
diff --git a/core/src/main/scala/chisel3/StrongEnum.scala b/core/src/main/scala/chisel3/StrongEnum.scala
index cd6f11ee..3c9f4105 100644
--- a/core/src/main/scala/chisel3/StrongEnum.scala
+++ b/core/src/main/scala/chisel3/StrongEnum.scala
@@ -251,7 +251,28 @@ abstract class EnumType(private[chisel3] val factory: EnumFactory, selfAnnotatin
protected def enumTypeName: String = factory.enumTypeName
- def toPrintable: Printable = FullName(this) // TODO: Find a better pretty printer
+ def toPrintable: Printable = {
+ implicit val sourceInfo = UnlocatableSourceInfo
+ implicit val compileOptions = ExplicitCompileOptions.Strict
+ val allNames = factory.allNames.zip(factory.all)
+ val nameSize = allNames.map(_._1.length).max
+ def leftPad(str: String): String = {
+ str.reverse.padTo(nameSize, ' ').reverse
+ }
+ val allNamesPadded = allNames.map { case (name, value) => leftPad(name) -> value }
+
+ val result = Wire(Vec(nameSize, UInt(8.W))).suggestName(s"_${enumTypeName}Printable")
+ result.foreach(_ := '?'.U)
+
+ for ((name, value) <- allNamesPadded) {
+ when(this === value) {
+ for ((r, c) <- result.zip(name)) {
+ r := c.toChar.U
+ }
+ }
+ }
+ result.map(Character(_)).foldLeft(p"")(_ + _)
+ }
}
abstract class EnumFactory {
@@ -284,6 +305,8 @@ abstract class EnumFactory {
def getWidth: Int = width.get
def all: Seq[Type] = enumInstances
+ /* Accessor for Seq of names in enumRecords */
+ def allNames: Seq[String] = enumNames
private[chisel3] def nameOfValue(id: BigInt): Option[String] = {
enumRecords.find(_.inst.litValue == id).map(_.name)
@@ -339,7 +362,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 +432,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
+ }
+}