From b72cc42f4f23906db0f201b1d9543a64accbc2ec Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Thu, 6 Oct 2022 21:26:30 +0000 Subject: Update toPrintable for Enums (#2707) (#2763) (cherry picked from commit 0ff99ca8d573e3487ef496a21c95d962689c3cba) Co-authored-by: Aditya Naik <91489422+adkian-sifive@users.noreply.github.com>--- core/src/main/scala/chisel3/StrongEnum.scala | 25 ++++++++++++++++- src/test/scala/chiselTests/StrongEnum.scala | 42 ++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) 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 { -- cgit v1.2.3