diff options
| -rw-r--r-- | Makefile | 22 | ||||
| -rw-r--r-- | build.sbt | 14 | ||||
| -rw-r--r-- | src/main/antlr4/FIRRTL.g4 | 20 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Driver.scala | 49 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Passes.scala | 57 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Translator.scala | 36 | ||||
| -rwxr-xr-x | utils/bin/firrtl-scala | 2 |
7 files changed, 150 insertions, 50 deletions
@@ -5,6 +5,10 @@ firrtl_dir ?= $(root_dir)/src/main/stanza install_dir ?= $(root_dir)/utils/bin stanza ?= $(install_dir)/stanza +stanza_bin ?= $(install_dir)/firrtl-stanza +scala_jar ?= $(install_dir)/firrtl.jar +scala_src=$(shell ls src/main/scala/firrtl/*.scala) +stanza_src=$(shell ls src/main/stanza/*.stanza) all-noise: ${MAKE} all || ${MAKE} fail @@ -24,6 +28,9 @@ $(root_dir)/src/lib/stanza/stamp: src/lib/stanza-$(stanza_zip_name).zip $(stanza): $(root_dir)/src/lib/stanza/stamp cd src/lib/stanza && ./stanza -platform $(stanza_target_name) -install $(stanza) +$(stanza_bin): $(stanza) $(stanza_src) + cd $(firrtl_dir) && $(stanza) -i firrtl-test-main.stanza -o $@ + build-deploy: $(stanza) cd $(firrtl_dir) && $(stanza) -i firrtl-main.stanza -o $(root_dir)/utils/bin/firrtl @@ -68,6 +75,9 @@ clean: rm -f $(test_dir)/*/*.out rm -rf src/lib/stanza rm -f $(stanza) + rm -f $(install_dir)/firrtl.jar + rm -f $(install_dir)/firrtl + rm -f $(install_dir)/firrtl-stanza riscv: cd $(test_dir)/riscv-mini && lit -v . --path=$(root_dir)/utils/bin/ @@ -87,12 +97,14 @@ fail: # Scala Added Makefile commands -build-scala: +build-scala: $(scala_jar) $(stanza_bin) $(firrtl_bin) + make set-scala + +$(scala_jar): $(scala_src) sbt "assembly" test-scala: cd $(test_dir)/parser && lit -v . --path=$(root_dir)/utils/bin/ - cd $(test_dir)/passes/infer-types && lit -v . --path=$(root_dir)/utils/bin/ set-scala: ln -f -s $(root_dir)/utils/bin/firrtl-scala $(root_dir)/utils/bin/firrtl @@ -100,4 +112,10 @@ set-scala: set-stanza: ln -f -s $(root_dir)/utils/bin/firrtl-stanza $(root_dir)/utils/bin/firrtl +set-linux: + ln -f -s $(root_dir)/utils/bin/FileCheck_linux $(root_dir)/utils/bin/FileCheck + +set-osx: + ln -f -s $(root_dir)/utils/bin/FileCheck_osx $(root_dir)/utils/bin/FileCheck + .PHONY: all install build-deploy build check clean fail succeed regress set-scala set-stanza build-scala test-scala @@ -1,12 +1,12 @@ -lazy val root = (project in file(".")). - settings( - organization := "edu.berkeley.cs", - name := "firrtl", - version := "0.1-SNAPSHOT", - scalaVersion := "2.11.4" - ) +organization := "edu.berkeley.cs" + +name := "firrtl" + +version := "0.1-SNAPSHOT" + +scalaVersion := "2.11.4" libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value diff --git a/src/main/antlr4/FIRRTL.g4 b/src/main/antlr4/FIRRTL.g4 index 96172895..dd270d17 100644 --- a/src/main/antlr4/FIRRTL.g4 +++ b/src/main/antlr4/FIRRTL.g4 @@ -4,17 +4,20 @@ grammar FIRRTL; * PARSER RULES *------------------------------------------------------------------*/ -// TODO add [info] support (all over the place) -// TODO Fix connect -// TODO Add partial connect -// TODO Should FIRRTL keywords be legal IDs? +/* TODO + * - Add [info] support (all over the place) + * - Add support for indexers + * - Add support for extmodule + * - Fix connect + * - Add partial connect + * - Should FIRRTL keywords be legal IDs? +*/ // Does there have to be at least one module? circuit : 'circuit' id ':' '{' module* '}' ; -// TODO Add support for extmodule module : 'module' id ':' '{' port* blockStmt '}' ; @@ -40,11 +43,6 @@ field : orientation id ':' type ; -// FIXME This is what the spec says it should be -//orientation -// : 'default' -// | 'reverse' -// ; orientation : 'flip' | // Nothing @@ -166,8 +164,6 @@ IdNondigit | [~!@#$%^*-+=?/] ; -// Should enforcing signed, non-neg, and positive ints be done in parser? -// => YES IntLit : '0' | ( '+' | '-' )? [1-9] ( Digit )* diff --git a/src/main/scala/firrtl/Driver.scala b/src/main/scala/firrtl/Driver.scala index 82ad269a..067ad4f4 100644 --- a/src/main/scala/firrtl/Driver.scala +++ b/src/main/scala/firrtl/Driver.scala @@ -37,7 +37,40 @@ object Driver logger.printlnDebug(ast) } - private def verilog(input: String, output: String, stanza: String)(implicit logger: Logger) + def toVerilogWithFame(input: String, output: String) + { + val stanzaPreTransform = List("rem-spec-chars", "high-form-check", + "temp-elim", "to-working-ir", "resolve-kinds", "infer-types", + "resolve-genders", "check-genders", "check-kinds", "check-types", + "expand-accessors", "lower-to-ground", "inline-indexers") + val stanzaPostTransform = List("rem-spec-chars", "high-form-check", + "temp-elim", "to-working-ir", "resolve-kinds", "infer-types", + "resolve-genders", "check-genders", "check-kinds", "check-types", + "expand-accessors", "lower-to-ground", "inline-indexers", "infer-types", + "check-genders", "expand-whens", "infer-widths", "real-ir", "width-check", + "pad-widths", "const-prop", "split-expressions", "width-check", + "high-form-check", "low-form-check", "check-init") + + // Lower-to-Ground with Stanza FIRRTL + val temp1 = genTempFilename(input) + val preCmd = Seq("firrtl-stanza", "-i", input, "-o", temp1, "-b", "firrtl") ++ stanzaPreTransform.flatMap(Seq("-x", _)) + println(preCmd.mkString(" ")) + preCmd.! + + // FAME-1 Transformation + val temp2 = genTempFilename(input) + val ast = Parser.parse(temp1) + val writer = new PrintWriter(new File(temp2)) + val ast2 = fame1Transform(ast) + writer.write(ast2.serialize()) + writer.close() + + //val postCmd = Seq("firrtl-stanza", "-i", temp2, "-o", output, "-b", "firrtl") ++ stanzaPostTransform.flatMap(Seq("-x", _)) + //println(postCmd.mkString(" ")) + //postCmd.! + } + + private def verilog(input: String, output: String)(implicit logger: Logger) { val stanzaPass = //List( List("rem-spec-chars", "high-form-check", @@ -54,11 +87,11 @@ object Driver "infer-types" -> inferTypes ) - if (stanza.isEmpty || !Files.exists(Paths.get(stanza))) - throw new FileNotFoundException("Stanza binary not found! " + stanza) + //if (stanza.isEmpty || !Files.exists(Paths.get(stanza))) + // throw new FileNotFoundException("Stanza binary not found! " + stanza) // For now, just use the stanza implementation in its entirety - val cmd = Seq(stanza, "-i", input, "-o", output, "-b", "verilog") ++ stanzaPass.flatMap(Seq("-x", _)) + val cmd = Seq("firrtl-stanza", "-i", input, "-o", output, "-b", "verilog") ++ stanzaPass.flatMap(Seq("-x", _)) println(cmd.mkString(" ")) val ret = cmd.!! println(ret) @@ -132,8 +165,6 @@ object Driver nextOption(map ++ Map('input -> value), tail) case "-o" :: value :: tail => nextOption(map ++ Map('output -> value), tail) - case "--stanza-bin" :: value :: tail => - nextOption(map ++ Map('stanza -> value), tail) case ("-h" | "--help") :: tail => nextOption(map ++ Map('help -> true), tail) case option :: tail => @@ -155,10 +186,6 @@ object Driver case s: String => s case false => throw new Exception("No output file provided!" + usage) } - val stanza = options('stanza) match { - case s: String => s - case false => "" - } val debugMode = decodeDebugMode(options('debugMode)) val printVars = options('printVars) match { case s: String => nextPrintVar(List(), s.toList) @@ -174,7 +201,7 @@ object Driver logger.warn("-p options will not print unless debugMode (-d) is debug or trace") options('compiler) match { - case "verilog" => verilog(input, output, stanza) + case "verilog" => verilog(input, output) case "firrtl" => firrtl(input, output) case other => throw new Exception("Invalid compiler! " + other) } diff --git a/src/main/scala/firrtl/Passes.scala b/src/main/scala/firrtl/Passes.scala index 39e6b64e..a76c3103 100644 --- a/src/main/scala/firrtl/Passes.scala +++ b/src/main/scala/firrtl/Passes.scala @@ -99,4 +99,61 @@ object Passes { Circuit(c.info, c.name, c.modules.map(inferTypes(typeMap, _))) } + /** FAME-1 + * + * This pass takes a lowered-to-ground circuit and performs a + * FAME-1 (Decoupled) transformation to the circuit + * + * TODO + * - SWITCH TO USING HIGH-LEVEL FIRRTL SO WE CAN MAINTAIN STRUCTURE OF BUNDLES + * - Add midas$fire : indicates when the module can operate + * - Add transform on each assignment to inputs/outputs to assign to data part of bundle + * - Add enable logic for each register + * * This should just be a when not(midas$fire) : reg := reg + * At bottom of module + * - QUESTIONS + * * Should we have Reset be a special Type? + * + * NOTES + * - How do output consumes tie in to MIDAS fire? If all of our outputs are not consumed + * in a given cycle, do we block midas$fire on the next cycle? Perhaps there should be + * a register for not having consumed all outputs last cycle + * - If our outputs are not consumed we also need to be sure not to consume out inputs, + * so the logic for this must depend on the previous cycle being consumed as well + * - We also need a way to determine the difference between the MIDAS modules and their + * connecting Queues, perhaps they should be MIDAS queues, which then perhaps prints + * out a listing of all queues so that they can be properly transformed + * * What do these MIDAS queues look like since we're enforcing true decoupled + * interfaces? + */ + private type PortMap = Map[String, Port] + //private val PortMap = Map[String, Type]().withDefaultValue(UnknownType) + private val f1TAvail = Field("avail", Default, UIntType(IntWidth(1))) + private val f1TConsume = Field("consume", Reverse, UIntType(IntWidth(1))) + private def fame1Transform(p: Port): Port = { + if( p.name == "reset" ) p // omit reset + else { + p.tpe match { + case ClockType => p // Omit clocktype + case t: BundleType => throw new Exception("Bundle Types not supported in FAME-1 Transformation!") + case t: VectorType => throw new Exception("Vector Types not supported in FAME-1 Transformation!") + case t: Type => { + Port(p.info, p.name, p.dir, BundleType( + Seq(f1TAvail, f1TConsume, Field("data", Default, t))) + ) + } + } + } + } + private def fame1Transform(m: Module): Module = { + println("fame1Transform called on module " + m.name) + val ports = m.ports.map(fame1Transform) + val portMap = Map(ports.map(p => (p.name, p))) + println(portMap) + Module(m.info, m.name, ports, m.stmt) + } + def fame1Transform(c: Circuit): Circuit = { + Circuit(c.info, c.name, c.modules.map(fame1Transform)) + } + } diff --git a/src/main/scala/firrtl/Translator.scala b/src/main/scala/firrtl/Translator.scala index a16d89d7..152cd88e 100644 --- a/src/main/scala/firrtl/Translator.scala +++ b/src/main/scala/firrtl/Translator.scala @@ -51,29 +51,31 @@ object Translator val spaces = countSpaces(text) val l = if (text.length > spaces ) { // Check that line has text in it - if (newScope) { - scope.push(countSpaces(text)) - } else { - - // Check if change in current scope - if( spaces < scope.top ) { - while( spaces < scope.top ) { - // Close scopes (adding brackets as we go) - scope.pop() - ret.deleteCharAt(ret.lastIndexOf("\n")) // Put on previous line - ret ++= " }\n" - } - if( spaces != scope.top ) - throw new Exception("Spacing does not match scope on line : " + lineNum + " : " + scope.top) + if (newScope) { + if( spaces == scope.top ) scope.push(spaces+2) // Hack for one-line scopes + else scope.push(spaces) + } + + // Check if change in current scope + if( spaces < scope.top ) { + while( spaces < scope.top ) { + // Close scopes (adding brackets as we go) + scope.pop() + ret.deleteCharAt(ret.lastIndexOf("\n")) // Put on previous line + ret ++= " }\n" } - else if( spaces > scope.top ) - throw new Exception("Invalid increase in scope on line " + lineNum) + if( spaces != scope.top ) + throw new Exception("Spacing does not match scope on line : " + lineNum + " : " + scope.top) } + else if( spaces > scope.top ) + throw new Exception("Invalid increase in scope on line " + lineNum) + // Now match on legal scope increasers text match { case Scopers(keyword, _* ) => { newScope = true - text + " { " + //text + " { " + text.replaceFirst(":", ": {") } case _ => { newScope = false diff --git a/utils/bin/firrtl-scala b/utils/bin/firrtl-scala index 4d208178..f955b9ee 100755 --- a/utils/bin/firrtl-scala +++ b/utils/bin/firrtl-scala @@ -2,6 +2,6 @@ # This may be a brittle way to find $(root_dir)/utils/bin, is there a better way? path=`dirname "$0"` -cmd="java -cp ${path}/firrtl.jar firrtl.Test ${@:1}" +cmd="java -cp ${path}/firrtl.jar firrtl.Driver ${@:1}" eval $cmd |
