diff options
| author | Jack | 2016-01-30 15:22:08 -0800 |
|---|---|---|
| committer | azidar | 2016-02-09 18:55:26 -0800 |
| commit | 1613a7127dd74427786baa093b0dde5a76265b78 (patch) | |
| tree | 9b5b212617439fc05f518f8e788a0872be7f230c | |
| parent | 2aea6744256d5be73fef044565c96c39589520f8 (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.scala | 65 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Driver.scala | 145 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Emitter.scala | 41 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Passes.scala | 1 | ||||
| -rw-r--r-- | src/main/scala/firrtl/passes/Passes.scala | 152 |
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") +} + |
