summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/src/main/scala/chisel3/StrongEnum.scala25
-rw-r--r--src/test/scala/chiselTests/StrongEnum.scala42
2 files changed, 66 insertions, 1 deletions
diff --git a/core/src/main/scala/chisel3/StrongEnum.scala b/core/src/main/scala/chisel3/StrongEnum.scala
index 6d8ceb2f..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)
diff --git a/src/test/scala/chiselTests/StrongEnum.scala b/src/test/scala/chiselTests/StrongEnum.scala
index 5b1b13fd..cee1777e 100644
--- a/src/test/scala/chiselTests/StrongEnum.scala
+++ b/src/test/scala/chiselTests/StrongEnum.scala
@@ -164,6 +164,39 @@ class StrongEnumFSM extends Module {
}
}
+object Opcode extends ChiselEnum {
+ val load = Value(0x03.U)
+ val imm = Value(0x13.U)
+ val auipc = Value(0x17.U)
+ val store = Value(0x23.U)
+ val litValues = List(0x03.U, 0x13.U, 0x17.U, 0x23.U)
+}
+
+class PrintableExecutionTest extends BasicTester {
+ val (count, done) = Counter(true.B, 6)
+ val w = WireDefault(Opcode.load)
+ when(count === 0.U) {
+ w := Opcode.load
+ }
+ when(count === 1.U) {
+ w := Opcode.imm
+ }
+ when(count === 2.U) {
+ w := Opcode.auipc
+ }
+ when(count === 3.U) {
+ w := Opcode.store
+ }
+ when(count === 4.U) { // invalid state
+ val invalidWire = WireInit(UInt(6.W), 0.U)
+ w := Opcode.safe(invalidWire)._1
+ }
+ when(done) {
+ stop()
+ }
+ printf(cf"'$w'\n")
+}
+
class CastToUIntTester extends BasicTester {
for ((enum, lit) <- EnumExample.all.zip(EnumExample.litValues)) {
val mod = Module(new CastToUInt)
@@ -555,6 +588,15 @@ class StrongEnumSpec extends ChiselFlatSpec with Utils {
it should "correctly check if the enumeration is one of the values in a given sequence" in {
assertTesterPasses(new IsOneOfTester)
}
+
+ it should "work with Printables" in {
+ val (log, _, _) = grabStdOutErr(assertTesterPasses { new PrintableExecutionTest })
+ log should include("load")
+ log should include("imm")
+ log should include("auipc")
+ log should include("store")
+ log should include("?????")
+ }
}
class StrongEnumAnnotator extends Module {