Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add isOneOf method to ChiselEnum #1966

Merged
merged 6 commits into from
Jul 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions core/src/main/scala/chisel3/StrongEnum.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
19 changes: 19 additions & 0 deletions docs/src/explanations/chisel-enum.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 39 additions & 0 deletions src/test/scala/chiselTests/StrongEnum.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 {
Expand Down