summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVerneri Hirvonen2021-07-08 18:59:12 +0300
committerGitHub2021-07-08 15:59:12 +0000
commitbb520b8573328fda5f7b3c3892e6995fbe1b4239 (patch)
tree3c2280100553ddab64b23e9e41baa0c34ff7950a
parentf1e37900170124254f3cf4599a45e7a485c17a91 (diff)
Add `isOneOf` method to `ChiselEnum` (#1966)
* Add @ekiwi's code as a starting point * Add test for ChiselEnum isOneOf method * Make isOneOfTester naming consistent with other testers * Add scaladoc comments for isOneOf * Add isOneOf tests that use the method that takes variable number of args * Add guide level documentation example for isOneOf
-rw-r--r--core/src/main/scala/chisel3/StrongEnum.scala18
-rw-r--r--docs/src/explanations/chisel-enum.md19
-rw-r--r--src/test/scala/chiselTests/StrongEnum.scala39
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 {