diff options
| -rw-r--r-- | core/src/main/scala/chisel3/StrongEnum.scala | 18 | ||||
| -rw-r--r-- | docs/src/explanations/chisel-enum.md | 19 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/StrongEnum.scala | 39 |
3 files changed, 76 insertions, 0 deletions
diff --git a/core/src/main/scala/chisel3/StrongEnum.scala b/core/src/main/scala/chisel3/StrongEnum.scala index 1d0e04d3..b3d7cf7d 100644 --- a/core/src/main/scala/chisel3/StrongEnum.scala +++ b/core/src/main/scala/chisel3/StrongEnum.scala @@ -135,6 +135,24 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea } } + /** Test if this enumeration is equal to any of the values in a given sequence + * + * @param s a [[scala.collection.Seq$ Seq]] of enumeration values to look for + * @return a hardware [[Bool]] that indicates if this value matches any of the given values + */ + final def isOneOf(s: Seq[EnumType])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { + VecInit(s.map(this === _)).asUInt().orR() + } + + /** Test if this enumeration is equal to any of the values given as arguments + * + * @param u1 the first value to look for + * @param u2 zero or more additional values to look for + * @return a hardware [[Bool]] that indicates if this value matches any of the given values + */ + final def isOneOf(u1: EnumType, u2: EnumType*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool + = isOneOf(u1 +: u2.toSeq) + def next(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = { if (litOption.isDefined) { val index = factory.all.indexOf(this) diff --git a/docs/src/explanations/chisel-enum.md b/docs/src/explanations/chisel-enum.md index 96fc9e8a..a390aea4 100644 --- a/docs/src/explanations/chisel-enum.md +++ b/docs/src/explanations/chisel-enum.md @@ -182,6 +182,25 @@ def expectedSel(sel: AluMux1Sel.Type): Boolean = sel match { } ``` +The enum value type also defines some convenience methods for working with `ChiselEnum` values. For example, continuing with the RISC-V opcode +example, one could easily create hardware signal that is only asserted on LOAD/STORE operations (when the enum value is equal to `Opcode.load` +or `Opcode.store`) using the `.isOneOf` method: + +```scala mdoc +class LoadStoreExample extends Module { + val io = IO(new Bundle { + val opcode = Input(Opcode()) + val load_or_store = Output(Bool()) + }) + io.load_or_store := io.opcode.isOneOf(Opcode.load, Opcode.store) +} +``` + +```scala mdoc:invisible +// Always need to run Chisel to see if there are elaboration errors +ChiselStage.emitVerilog(new LoadStoreExample) +``` + Some additional useful methods defined on the `ChiselEnum` object are: * `.all`: returns the enum values within the enumeration diff --git a/src/test/scala/chiselTests/StrongEnum.scala b/src/test/scala/chiselTests/StrongEnum.scala index e59a5398..d7dea571 100644 --- a/src/test/scala/chiselTests/StrongEnum.scala +++ b/src/test/scala/chiselTests/StrongEnum.scala @@ -304,6 +304,41 @@ class StrongEnumFSMTester extends BasicTester { } } +class IsOneOfTester extends BasicTester { + import EnumExample._ + + // is one of itself + assert(e0.isOneOf(e0)) + + // is one of Seq of itself + assert(e0.isOneOf(Seq(e0))) + assert(e0.isOneOf(Seq(e0, e0, e0, e0))) + assert(e0.isOneOf(e0, e0, e0, e0)) + + // is one of Seq of multiple elements + val subset = Seq(e0, e1, e2) + assert(e0.isOneOf(subset)) + assert(e1.isOneOf(subset)) + assert(e2.isOneOf(subset)) + + // is not element not in subset + assert(!e100.isOneOf(subset)) + assert(!e101.isOneOf(subset)) + + // test multiple elements with variable number of arguments + assert(e0.isOneOf(e0, e1, e2)) + assert(e1.isOneOf(e0, e1, e2)) + assert(e2.isOneOf(e0, e1, e2)) + assert(!e100.isOneOf(e0, e1, e2)) + assert(!e101.isOneOf(e0, e1, e2)) + + // is not another value + assert(!e0.isOneOf(e1)) + assert(!e2.isOneOf(e101)) + + stop() +} + class StrongEnumSpec extends ChiselFlatSpec with Utils { import chisel3.internal.ChiselException @@ -474,6 +509,10 @@ class StrongEnumSpec extends ChiselFlatSpec with Utils { val (log, _) = grabLog(ChiselStage.elaborate(new MyModule)) log should not include ("warn") } + + it should "correctly check if the enumeration is one of the values in a given sequence" in { + assertTesterPasses(new IsOneOfTester) + } } class StrongEnumAnnotator extends Module { |
