summaryrefslogtreecommitdiff
path: root/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 /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 'src/main')
-rw-r--r--src/main/scala/chisel3/internal/firrtl/Emitter.scala29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala
index 963a713b..09984722 100644
--- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala
+++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala
@@ -75,10 +75,21 @@ private class Emitter(circuit: Circuit) {
case e: DefInvalid => s"${e.arg.fullName(ctx)} is invalid"
case e: DefInstance => s"inst ${e.name} of ${e.id.name}"
case w: WhenBegin =>
+ // When consequences are always indented
indent()
s"when ${w.pred.fullName(ctx)} :"
- case _: WhenEnd =>
+ case w: WhenEnd =>
+ // If a when has no else, the indent level must be reset to the enclosing block
unindent()
+ if (!w.hasAlt) { for (i <- 0 until w.firrtlDepth) { unindent() } }
+ s"skip"
+ case a: AltBegin =>
+ // Else blocks are always indented
+ indent()
+ s"else :"
+ case o: OtherwiseEnd =>
+ // Chisel otherwise: ends all FIRRTL associated a Chisel when, resetting indent level
+ for (i <- 0 until o.firrtlDepth) { unindent() }
s"skip"
}
firrtlLine + e.sourceInfo.makeMessage(" " + _)
@@ -120,8 +131,10 @@ private class Emitter(circuit: Circuit) {
// Firrtl extmodule can overrule name
body ++= newline + s"defname = ${bb.id.desiredName}"
body ++= newline + (bb.params map { case (n, p) => emitParam(n, p) } mkString newline)
- case mod: DefModule => for (cmd <- mod.commands) {
- body ++= newline + emit(cmd, mod)
+ case mod: DefModule => {
+ // Preprocess whens & elsewhens, marking those that have no alternative
+ val procMod = mod.copy(commands = processWhens(mod.commands))
+ for (cmd <- procMod.commands) { body ++= newline + emit(cmd, procMod)}
}
}
body ++= newline
@@ -141,6 +154,16 @@ private class Emitter(circuit: Circuit) {
sb.result
}
+ /** Preprocess the command queue, marking when/elsewhen statements
+ * that have no alternatives (elsewhens or otherwise). These
+ * alternative-free statements reset the indent level to the
+ * enclosing block upon emission.
+ */
+ private def processWhens(cmds: Seq[Command]):
+ Seq[Command] = { cmds.zip(cmds.tail).map({ case (a: WhenEnd, b:
+ AltBegin) => a.copy(hasAlt = true) case (a, b) => a }) ++
+ cmds.lastOption }
+
private var indentLevel = 0
private def newline = "\n" + (" " * indentLevel)
private def indent(): Unit = indentLevel += 1