summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main
diff options
context:
space:
mode:
authorAlbert Magyar2017-08-17 17:55:44 -0700
committerJack Koenig2017-08-17 17:55:44 -0700
commit6297e00aa845cf6cc1275c05d313f3237e69de9d (patch)
tree05363bfee404a441d5a759e292bd894c1e2db8a6 /chiselFrontend/src/main
parent6e12ed9fd7a771eb30f44b8e1c4ab33f6ad8e0a6 (diff)
Use firrtl elses in elsewhen/otherwise case emission (#510)
Preprocess chisel3 IR before emission to determing whether whens have alternatives.
Diffstat (limited to 'chiselFrontend/src/main')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/When.scala55
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala4
2 files changed, 39 insertions, 20 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/When.scala b/chiselFrontend/src/main/scala/chisel3/core/When.scala
index 26f939ba..55012946 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/When.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/When.scala
@@ -27,35 +27,52 @@ object when { // scalastyle:ignore object.name
* }
* }}}
*/
- def apply(cond: Bool)(block: => Unit)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): WhenContext = {
- new WhenContext(sourceInfo, cond, !cond, block)
+
+ def apply(cond: => Bool)(block: => Unit)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): WhenContext = {
+ new WhenContext(sourceInfo, Some(() => cond), block)
}
}
-
-/** Internal mechanism for generating a when. Because of the way FIRRTL
- * commands are emitted, generating a FIRRTL elsewhen or nested whens inside
- * elses would be difficult. Instead, this keeps track of the negative of the
- * previous conditions, so when an elsewhen or otherwise is used, it checks
- * that both the condition is true and all the previous conditions have been
- * false.
+
+/** A WhenContext may represent a when, and elsewhen, or an
+ * otherwise. Since FIRRTL does not have an "elsif" statement,
+ * alternatives must be mapped to nested if-else statements inside
+ * the alternatives of the preceeding condition. In order to emit
+ * proper FIRRTL, it is necessary to keep track of the depth of
+ * nesting of the FIRRTL whens. Due to the "thin frontend" nature of
+ * Chisel3, it is not possible to know if a when or elsewhen has a
+ * succeeding elsewhen or otherwise; therefore, this information is
+ * added by preprocessing the command queue.
*/
-final class WhenContext(sourceInfo: SourceInfo, cond: Bool, prevCond: => Bool, block: => Unit) {
- /** This block of logic gets executed if above conditions have been false
- * and this condition is true.
+final class WhenContext(sourceInfo: SourceInfo, cond: Option[() => Bool], block: => Unit, firrtlDepth: Int = 0) {
+
+ /** 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
+ * declaration and assignment of the Bool node of the predicate in
+ * the correct place.
*/
- def elsewhen (elseCond: Bool)(block: => Unit)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): WhenContext = {
- new WhenContext(sourceInfo, prevCond && elseCond, prevCond && !elseCond, block)
+ def elsewhen (elseCond: => Bool)(block: => Unit)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): WhenContext = {
+ new WhenContext(sourceInfo, Some(() => elseCond), block, firrtlDepth+1)
}
- /** This block of logic gets executed only if the above conditions were all
- * false. No additional logic blocks may be appended past the `otherwise`.
+ /** This block of logic gets executed only if the above conditions
+ * were all false. No additional logic blocks may be appended past
+ * the `otherwise`. The lazy argument pattern makes it possible to
+ * delay evaluation of cond, emitting the declaration and
+ * assignment of the Bool node of the predicate in the correct
+ * place.
*/
def otherwise(block: => Unit)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit =
- new WhenContext(sourceInfo, prevCond, null, block)
+ new WhenContext(sourceInfo, None, block, firrtlDepth+1)
- pushCommand(WhenBegin(sourceInfo, cond.ref))
+ /*
+ *
+ */
+ if (firrtlDepth > 0) { pushCommand(AltBegin(sourceInfo)) }
+ cond.foreach( c => pushCommand(WhenBegin(sourceInfo, c().ref)) )
Builder.whenDepth += 1
block
Builder.whenDepth -= 1
- pushCommand(WhenEnd(sourceInfo))
+ cond.foreach( c => pushCommand(WhenEnd(sourceInfo,firrtlDepth)) )
+ if (cond.isEmpty) { pushCommand(OtherwiseEnd(sourceInfo,firrtlDepth)) }
}
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
index 05cde071..b499c2b1 100644
--- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
+++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
@@ -260,7 +260,9 @@ case class DefSeqMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: Int) e
case class DefMemPort[T <: Data](sourceInfo: SourceInfo, id: T, source: Node, dir: MemPortDirection, index: Arg, clock: Arg) extends Definition
case class DefInstance(sourceInfo: SourceInfo, id: BaseModule, ports: Seq[Port]) extends Definition
case class WhenBegin(sourceInfo: SourceInfo, pred: Arg) extends Command
-case class WhenEnd(sourceInfo: SourceInfo) extends Command
+case class WhenEnd(sourceInfo: SourceInfo, firrtlDepth: Int, hasAlt: Boolean = false) extends Command
+case class AltBegin(sourceInfo: SourceInfo) extends Command
+case class OtherwiseEnd(sourceInfo: SourceInfo, firrtlDepth: Int) extends Command
case class Connect(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command
case class BulkConnect(sourceInfo: SourceInfo, loc1: Node, loc2: Node) extends Command
case class Attach(sourceInfo: SourceInfo, locs: Seq[Node]) extends Command