aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjackkoenig2015-11-24 19:18:01 -0800
committerjackkoenig2015-11-24 19:18:01 -0800
commit71f0319e8d27d1f175b4747c0367843a6ceab986 (patch)
treeacd1c96a30f4b04fcc6202cd9f9f59c9e9de432a /src
parent876c5e0a93c21a2108804eb972289f77c250e28b (diff)
In process of adding FAME-1 transformation, updated todos in grammar file, updated Makefile to play nicer when firrtl is a submodule, fixed bug in Translator for single line scopes, fixed firrtl-scala script to point to firrtl.Driver instead of old firrtl.Test
Diffstat (limited to 'src')
-rw-r--r--src/main/antlr4/FIRRTL.g420
-rw-r--r--src/main/scala/firrtl/Driver.scala49
-rw-r--r--src/main/scala/firrtl/Passes.scala57
-rw-r--r--src/main/scala/firrtl/Translator.scala36
4 files changed, 122 insertions, 40 deletions
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