aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack2016-01-30 15:22:08 -0800
committerazidar2016-02-09 18:55:26 -0800
commit1613a7127dd74427786baa093b0dde5a76265b78 (patch)
tree9b5b212617439fc05f518f8e788a0872be7f230c
parent2aea6744256d5be73fef044565c96c39589520f8 (diff)
Restructure passes to be new subpackage with more modular design, add new structures Compiler and Emitter, deprecate old Passes object, update Driver to use new constructs
-rw-r--r--src/main/scala/firrtl/Compiler.scala65
-rw-r--r--src/main/scala/firrtl/Driver.scala145
-rw-r--r--src/main/scala/firrtl/Emitter.scala41
-rw-r--r--src/main/scala/firrtl/Passes.scala1
-rw-r--r--src/main/scala/firrtl/passes/Passes.scala152
5 files changed, 265 insertions, 139 deletions
diff --git a/src/main/scala/firrtl/Compiler.scala b/src/main/scala/firrtl/Compiler.scala
new file mode 100644
index 00000000..18bec9dc
--- /dev/null
+++ b/src/main/scala/firrtl/Compiler.scala
@@ -0,0 +1,65 @@
+
+package firrtl
+
+import com.typesafe.scalalogging.LazyLogging
+import java.io.Writer
+
+import Utils._
+import firrtl.passes._
+
+trait Compiler extends LazyLogging {
+ def run(c: Circuit, w: Writer)
+}
+
+object FIRRTLCompiler extends Compiler {
+ def run(c: Circuit, w: Writer) = {
+ FIRRTLEmitter.run(c, w)
+ w.close
+ }
+}
+
+object VerilogCompiler extends Compiler {
+ // Copied from Stanza implementation
+ val passes = Seq(
+ CheckHighForm,
+ ToWorkingIR,
+ ResolveKinds,
+ InferTypes,
+ CheckTypes,
+ ResolveGenders,
+ CheckGenders,
+ InferWidths,
+ CheckWidths,
+ PullMuxes,
+ ExpandConnects,
+ RemoveAccesses,
+ ExpandWhens,
+ CheckInitialization,
+ ConstProp,
+ ResolveKinds,
+ InferTypes,
+ CheckTypes,
+ ResolveGenders,
+ CheckGenders,
+ InferWidths,
+ CheckWidths,
+ LowerTypes,
+ ResolveKinds,
+ InferTypes,
+ CheckTypes,
+ ResolveGenders,
+ CheckGenders,
+ InferWidths,
+ CheckWidths,
+ VerilogWrap,
+ SplitExp,
+ VerilogRename
+ )
+ def run(c: Circuit, w: Writer)
+ {
+ val loweredIR = PassUtils.executePasses(c, passes)
+ VerilogEmitter.run(loweredIR, w)
+ w.close
+ }
+
+}
diff --git a/src/main/scala/firrtl/Driver.scala b/src/main/scala/firrtl/Driver.scala
index 8876aac4..14861f5e 100644
--- a/src/main/scala/firrtl/Driver.scala
+++ b/src/main/scala/firrtl/Driver.scala
@@ -12,150 +12,17 @@ import Utils._
import DebugUtils._
import Passes._
-trait DriverPass {
- def run(input: String, output: String) : Unit
-}
-case class StanzaPass(val passes : Seq[String]) extends DriverPass with LazyLogging {
- def run(input : String, output : String): Unit = {
- val cmd = Seq("firrtl-stanza", "-i", input, "-o", output, "-b", "firrtl") ++ passes.flatMap(x=>Seq("-x", x))
- logger.info(cmd.mkString(" "))
- val ret = cmd.!!
- logger.info(ret)
- }
-}
-case class ScalaPass(val func : Circuit => Circuit) extends DriverPass with LazyLogging {
- def run(input : String, output : String): Unit = {
- var ast = Parser.parse(input, Source.fromFile(input).getLines)
- val newast = func(ast)
- logger.info("Writing to " + output)
- val writer = new PrintWriter(new File(output))
- writer.write(newast.serialize())
- writer.close()
- }
-}
-object StanzaPass {
- def apply(pass: String): StanzaPass = StanzaPass(Seq(pass))
-}
-
-object DriverPasses {
- private def aggregateStanzaPasses(passes: Seq[DriverPass]): Seq[DriverPass] = {
- if (passes.isEmpty) return Seq()
- val span = passes.span(x => x match {
- case p : StanzaPass => true
- case _ => false
- })
- if (span._1.isEmpty) {
- Seq(span._2.head) ++ aggregateStanzaPasses(span._2.tail)
- } else {
- Seq(StanzaPass(span._1.flatMap(x=>x.asInstanceOf[StanzaPass].passes))) ++ aggregateStanzaPasses(span._2)
- }
- }
-
- def optimize(passes: Seq[DriverPass]): Seq[DriverPass] = {
- aggregateStanzaPasses(aggregateStanzaPasses(passes))
- }
-}
-
object Driver extends LazyLogging {
private val usage = """
Usage: java -cp utils/bin/firrtl.jar firrtl.Driver [options] -i <input> -o <output>
"""
private val defaultOptions = Map[Symbol, Any]().withDefaultValue(false)
- // Appends 0 to the filename and appends .tmp to the extension
- private def genTempFilename(filename: String): String = {
- val pat = """(.*/)([^/]*)([.][^/.]*)""".r
- val (path, name, ext) = filename match {
- case pat(path, name, ext) => (path, name, ext + ".tmp")
- case _ => ("./", "temp", ".tmp")
- }
- var count = 0
- while( Files.exists(Paths.get(path + name + count + ext )) )
- count += 1
- path + name + count + ext
- }
-
- val defaultPasses = DriverPasses.optimize(Seq(
- StanzaPass("cinfertypes"),
-// =====================================
- StanzaPass("cinfermdir"),
-// =====================================
- StanzaPass("removechirrtl"),
-// =====================================
- StanzaPass("high-form-check"),
-// =====================================
- StanzaPass("to-working-ir"),
-// =====================================
- StanzaPass("resolve-kinds"),
- StanzaPass("infer-types"),
- StanzaPass("check-types"),
- StanzaPass("resolve-genders"),
- StanzaPass("check-genders"),
- StanzaPass("infer-widths"),
- StanzaPass("width-check"),
-// =====================================
- ScalaPass(resolve),
-// =====================================
- StanzaPass("resolve"),
-// =====================================
- //StanzaPass("pull-muxes"),
-// =====================================
- //StanzaPass("expand-connects"),
-// =====================================
- StanzaPass("remove-access"),
-// =====================================
- StanzaPass("expand-whens"),
-// =====================================
- StanzaPass("check-init"),
-// =====================================
- StanzaPass("const-prop"),
-// =====================================
- StanzaPass("resolve-kinds"),
- StanzaPass("infer-types"),
- StanzaPass("check-types"),
- StanzaPass("resolve-genders"),
- StanzaPass("check-genders"),
- StanzaPass("infer-widths"),
- StanzaPass("width-check")
-// =====================================
- //ScalaPass(renamec)
-// ScalaPass(renameall(Map(
-// "c"->"ccc",
-// "z"->"zzz",
-// "top"->"its_a_top_module"
-// ))),
- // StanzaPass("temp-elim"), // performance pass
- ))
-
- // Parse input file and print to output
- private def firrtl(input: String, output: String)
+ private def compile(input: String, output: String, compiler: Compiler)
{
- val ast = Parser.parse(input, Source.fromFile(input).getLines)
- val writer = new PrintWriter(new File(output))
- writer.write(ast.serialize())
- writer.close()
- logger.debug(ast.toString)
- }
-
- def executePasses(ast: Circuit, passes: Seq[Circuit => Circuit]): Circuit = {
- if (passes.isEmpty) ast
- else executePasses(passes.head(ast), passes.tail)
- }
-
- private def verilog(input: String, output: String) {
- val outfile = defaultPasses.foldLeft( input ) ( (infile, pass) => {
- val outfile = genTempFilename(output)
- pass.run(infile, outfile)
- outfile
- })
-
- logger.info(outfile)
-
- // finally, convert to verilog at the end
- val cmd = Seq("firrtl-stanza", "-i", outfile, "-o", output, "-b", "verilog")
- logger.info(cmd.mkString(" "))
- val ret = cmd.!!
- logger.info(ret)
+ val parsedInput = Parser.parse(input, Source.fromFile(input).getLines)
+ val writerOutput = new PrintWriter(new File(output))
+ compiler.run(parsedInput, writerOutput)
}
def main(args: Array[String])
@@ -229,8 +96,8 @@ object Driver extends LazyLogging {
}
options('compiler) match {
- case "verilog" => verilog(input, output)
- case "firrtl" => firrtl(input, output)
+ case "verilog" => compile(input, output, VerilogCompiler)
+ case "firrtl" => compile(input, output, FIRRTLCompiler)
case other => throw new Exception("Invalid compiler! " + other)
}
}
diff --git a/src/main/scala/firrtl/Emitter.scala b/src/main/scala/firrtl/Emitter.scala
new file mode 100644
index 00000000..09302fb3
--- /dev/null
+++ b/src/main/scala/firrtl/Emitter.scala
@@ -0,0 +1,41 @@
+
+package firrtl
+
+import com.typesafe.scalalogging.LazyLogging
+import java.nio.file.{Paths, Files}
+import java.io.Writer
+import java.io.Reader
+
+import scala.sys.process._
+import scala.io.Source
+
+import Utils._
+import firrtl.passes._
+
+trait Emitter extends LazyLogging {
+ def run(c: Circuit, w: Writer)
+}
+
+object FIRRTLEmitter extends Emitter {
+ def run(c: Circuit, w: Writer) = w.write(c.serialize)
+}
+
+object VerilogEmitter extends Emitter {
+ // Currently just trap into Stanza
+ def run(c: Circuit, w: Writer)
+ {
+ logger.debug(s"Verilog Emitter is not yet implemented in Scala")
+ val toStanza = Files.createTempFile(Paths.get(""), "verilog", ".fir")
+ val fromStanza = Files.createTempFile(Paths.get(""), "verilog", ".fir")
+ Files.write(toStanza, c.serialize.getBytes)
+
+ val cmd = Seq("firrtl-stanza", "-i", toStanza.toString, "-o", fromStanza.toString, "-b", "verilog")
+ logger.debug(cmd.mkString(" "))
+ val ret = cmd.!
+ // Copy from Stanza output to user requested outputFile (we can't get filename from Writer)
+ Source.fromFile(fromStanza.toString) foreach { w.write(_) }
+
+ Files.delete(toStanza)
+ Files.delete(fromStanza)
+ }
+}
diff --git a/src/main/scala/firrtl/Passes.scala b/src/main/scala/firrtl/Passes.scala
index 464cd057..b0b93db9 100644
--- a/src/main/scala/firrtl/Passes.scala
+++ b/src/main/scala/firrtl/Passes.scala
@@ -9,6 +9,7 @@ import Utils._
import DebugUtils._
import PrimOps._
+@deprecated("This object will be replaced with package firrtl.passes")
object Passes extends LazyLogging {
// TODO Perhaps we should get rid of Logger since this map would be nice
diff --git a/src/main/scala/firrtl/passes/Passes.scala b/src/main/scala/firrtl/passes/Passes.scala
new file mode 100644
index 00000000..7c1c7bc3
--- /dev/null
+++ b/src/main/scala/firrtl/passes/Passes.scala
@@ -0,0 +1,152 @@
+
+package firrtl.passes
+
+import com.typesafe.scalalogging.LazyLogging
+import java.nio.file.{Paths, Files}
+
+// For calling Stanza
+import scala.sys.process._
+import scala.io.Source
+
+import firrtl._
+import firrtl.Utils._
+import firrtl.PrimOps._
+
+trait Pass extends LazyLogging {
+ def name: String
+ def run(c: Circuit): Circuit
+}
+
+// Trait for migration, trap to Stanza implementation for passes not yet implemented in Scala
+trait StanzaPass extends LazyLogging {
+ def stanzaPass(c: Circuit, n: String): Circuit = {
+ // For migration from Stanza, handle unimplemented Passes
+ logger.debug(s"Pass ${n} is not yet implemented in Scala")
+ val stanzaPasses = Seq("resolve", n)
+ val toStanza = Files.createTempFile(Paths.get(""), n, ".fir")
+ val fromStanza = Files.createTempFile(Paths.get(""), n, ".fir")
+ Files.write(toStanza, c.serialize.getBytes)
+
+ val cmd = Seq("firrtl-stanza", "-i", toStanza.toString, "-o", fromStanza.toString, "-b", "firrtl") ++
+ stanzaPasses.flatMap(x=>Seq("-x", x))
+ logger.debug(cmd.mkString(" "))
+ val ret = cmd.!
+ //println(ret)
+ val newC = Parser.parse(fromStanza.toString, Source.fromFile(fromStanza.toString).getLines)
+ Files.delete(toStanza)
+ Files.delete(fromStanza)
+ newC
+ }
+}
+
+object PassUtils extends LazyLogging {
+ val listOfPasses: Seq[Pass] = Seq(ToWorkingIR)
+ lazy val mapNameToPass: Map[String, Pass] = listOfPasses.map(p => p.name -> p).toMap
+
+ def executePasses(c: Circuit, passes: Seq[Pass]): Circuit = {
+ if (passes.isEmpty) c
+ else executePasses(passes.head.run(c), passes.tail)
+ }
+}
+
+// These should be distributed into separate files
+object CheckHighForm extends Pass with StanzaPass {
+ def name = "High Form Check"
+ def run (c:Circuit): Circuit = stanzaPass(c, "high-form-check")
+}
+
+object ToWorkingIR extends Pass with StanzaPass {
+ def name = "Working IR"
+ def run (c:Circuit): Circuit = stanzaPass(c, "to-working-ir")
+}
+
+object Resolve extends Pass with StanzaPass {
+ def name = "Resolve"
+ def run (c:Circuit): Circuit = stanzaPass(c, "resolve")
+}
+
+object ResolveKinds extends Pass with StanzaPass {
+ def name = "Resolve Kinds"
+ def run (c:Circuit): Circuit = stanzaPass(c, "resolve-kinds")
+}
+
+object InferTypes extends Pass with StanzaPass {
+ def name = "Infer Types"
+ def run (c:Circuit): Circuit = stanzaPass(c, "infer-types")
+}
+
+object CheckTypes extends Pass with StanzaPass {
+ def name = "Check Types"
+ def run (c:Circuit): Circuit = stanzaPass(c, "check-types")
+}
+
+object ResolveGenders extends Pass with StanzaPass {
+ def name = "Resolve Genders"
+ def run (c:Circuit): Circuit = stanzaPass(c, "resolve-genders")
+}
+
+object CheckGenders extends Pass with StanzaPass {
+ def name = "Check Genders"
+ def run (c:Circuit): Circuit = stanzaPass(c, "check-genders")
+}
+
+object InferWidths extends Pass with StanzaPass {
+ def name = "Infer Widths"
+ def run (c:Circuit): Circuit = stanzaPass(c, "infer-widths")
+}
+
+object CheckWidths extends Pass with StanzaPass {
+ def name = "Width Check"
+ def run (c:Circuit): Circuit = stanzaPass(c, "width-check")
+}
+
+object PullMuxes extends Pass with StanzaPass {
+ def name = "Pull Muxes"
+ def run (c:Circuit): Circuit = stanzaPass(c, "pull-muxes")
+}
+
+object ExpandConnects extends Pass with StanzaPass {
+ def name = "Expand Connects"
+ def run (c:Circuit): Circuit = stanzaPass(c, "expand-connects")
+}
+
+object RemoveAccesses extends Pass with StanzaPass {
+ def name = "Remove Accesses"
+ def run (c:Circuit): Circuit = stanzaPass(c, "remove-accesses")
+}
+
+object ExpandWhens extends Pass with StanzaPass {
+ def name = "Expand Whens"
+ def run (c:Circuit): Circuit = stanzaPass(c, "expand-whens")
+}
+
+object CheckInitialization extends Pass with StanzaPass {
+ def name = "Check Initialization"
+ def run (c:Circuit): Circuit = stanzaPass(c, "check-init")
+}
+
+object ConstProp extends Pass with StanzaPass {
+ def name = "Constant Propogation"
+ def run (c:Circuit): Circuit = stanzaPass(c, "const-prop")
+}
+
+object VerilogWrap extends Pass with StanzaPass {
+ def name = "Verilog Wrap"
+ def run (c:Circuit): Circuit = stanzaPass(c, "verilog-wrap")
+}
+
+object SplitExp extends Pass with StanzaPass {
+ def name = "Split Expressions"
+ def run (c:Circuit): Circuit = stanzaPass(c, "split-expressions")
+}
+
+object VerilogRename extends Pass with StanzaPass {
+ def name = "Verilog Rename"
+ def run (c:Circuit): Circuit = stanzaPass(c, "verilog-rename")
+}
+
+object LowerTypes extends Pass with StanzaPass {
+ def name = "Lower Types"
+ def run (c:Circuit): Circuit = stanzaPass(c, "lower-types")
+}
+