summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authorJack Koenig2021-01-19 15:54:49 -0800
committerGitHub2021-01-19 15:54:49 -0800
commitcdb7bb27bd675a8a114701b97a45c56e26ef42b5 (patch)
treec60b6b87501ba3fba0a70130905611cd512e5e43 /core/src
parente94d41fc779e4e6b0b957a85da23532f23c45948 (diff)
Add when.cond for getting the current when condition (#1694)
This is useful for libraries to guard operations implemented via annotations or BlackBoxes by the current when predicate
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/scala/chisel3/When.scala60
1 files changed, 52 insertions, 8 deletions
diff --git a/core/src/main/scala/chisel3/When.scala b/core/src/main/scala/chisel3/When.scala
index 048ac08a..a2c20d9a 100644
--- a/core/src/main/scala/chisel3/When.scala
+++ b/core/src/main/scala/chisel3/When.scala
@@ -3,11 +3,10 @@
package chisel3
import scala.language.experimental.macros
-
import chisel3.internal._
import chisel3.internal.Builder.pushCommand
import chisel3.internal.firrtl._
-import chisel3.internal.sourceinfo.{SourceInfo}
+import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo}
object when {
/** Create a `when` condition block, where whether a block of logic is
@@ -29,7 +28,30 @@ object when {
*/
def apply(cond: => Bool)(block: => Any)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): WhenContext = {
- new WhenContext(sourceInfo, Some(() => cond), block)
+ new WhenContext(sourceInfo, Some(() => cond), block, 0, Nil)
+ }
+
+ /** Returns the current `when` condition
+ *
+ * This is the conjunction of conditions for all `whens` going up the call stack
+ * {{{
+ * when (a) {
+ * when (b) {
+ * when (c) {
+ * }.otherwise {
+ * when.cond // this is equal to: a && b && !c
+ * }
+ * }
+ * }
+ * }}}
+ * */
+ def cond: Bool = {
+ implicit val compileOptions = ExplicitCompileOptions.Strict
+ implicit val sourceInfo = UnlocatableSourceInfo
+ val whens = Builder.whenStack
+ whens.foldRight(true.B) {
+ case (ctx, acc) => acc && ctx.localCond()
+ }
}
}
@@ -43,10 +65,32 @@ object when {
* succeeding elsewhen or otherwise; therefore, this information is
* added by preprocessing the command queue.
*/
-final class WhenContext(sourceInfo: SourceInfo, cond: Option[() => Bool], block: => Any, firrtlDepth: Int = 0) {
+final class WhenContext private[chisel3] (
+ sourceInfo: SourceInfo,
+ cond: Option[() => Bool],
+ block: => Any,
+ firrtlDepth: Int,
+ // For capturing conditions from prior whens or elsewhens
+ altConds: List[() => Bool]
+) {
+
+ @deprecated("Use when(...) { ... }, this should never have been public", "Chisel 3.4.2")
+ def this(sourceInfo: SourceInfo, cond: Option[() => Bool], block: => Any, firrtlDepth: Int = 0) =
+ this(sourceInfo, cond, block, firrtlDepth, Nil)
private var scopeOpen = false
+ /** Returns the local condition, inverted for an otherwise */
+ private[chisel3] def localCond(): Bool = {
+ implicit val compileOptions = ExplicitCompileOptions.Strict
+ implicit val sourceInfo = UnlocatableSourceInfo
+ val alt = altConds.foldRight(true.B) {
+ case (c, acc) => acc & !c()
+ }
+ cond.map(alt && _())
+ .getOrElse(alt)
+ }
+
/** This block of logic gets executed if above conditions have been
* false and this condition is true. The lazy argument pattern
* makes it possible to delay evaluation of cond, emitting the
@@ -54,7 +98,7 @@ final class WhenContext(sourceInfo: SourceInfo, cond: Option[() => Bool], block:
* the correct place.
*/
def elsewhen (elseCond: => Bool)(block: => Any)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): WhenContext = {
- new WhenContext(sourceInfo, Some(() => elseCond), block, firrtlDepth + 1)
+ new WhenContext(sourceInfo, Some(() => elseCond), block, firrtlDepth + 1, cond ++: altConds)
}
/** This block of logic gets executed only if the above conditions
@@ -65,7 +109,7 @@ final class WhenContext(sourceInfo: SourceInfo, cond: Option[() => Bool], block:
* place.
*/
def otherwise(block: => Any)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit =
- new WhenContext(sourceInfo, None, block, firrtlDepth + 1)
+ new WhenContext(sourceInfo, None, block, firrtlDepth + 1, cond ++: altConds)
def active(): Boolean = scopeOpen
@@ -79,13 +123,13 @@ final class WhenContext(sourceInfo: SourceInfo, cond: Option[() => Bool], block:
scopeOpen = true
block
} catch {
- case ret: scala.runtime.NonLocalReturnControl[_] =>
+ case _: scala.runtime.NonLocalReturnControl[_] =>
throwException("Cannot exit from a when() block with a \"return\"!" +
" Perhaps you meant to use Mux or a Wire as a return value?"
)
}
scopeOpen = false
Builder.popWhen()
- cond.foreach( c => pushCommand(WhenEnd(sourceInfo,firrtlDepth)) )
+ cond.foreach(_ => pushCommand(WhenEnd(sourceInfo,firrtlDepth)))
if (cond.isEmpty) { pushCommand(OtherwiseEnd(sourceInfo,firrtlDepth)) }
}