aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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")
+}
+