aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorazidar2015-10-27 09:57:03 -0700
committerazidar2015-10-27 09:57:03 -0700
commit852b241e274edd888499b520d320945794a26e24 (patch)
treefc4c4dac344ab3995c685bde10c6255d5ab273cc
parent4312fed3f51e1756bbc104639689098de7df0cfe (diff)
parentf258c8394ebe7136e0eee7e1e342b5b593d1cc5d (diff)
Merge branch 'master' of github.com:ucb-bar/firrtl
Conflicts: Makefile
-rw-r--r--Makefile29
-rw-r--r--README.md8
-rw-r--r--build.sbt17
-rw-r--r--project/assembly.sbt1
-rw-r--r--src/main/antlr4/FIRRTL.g414
-rw-r--r--src/main/scala/firrtl/DebugUtils.scala129
-rw-r--r--src/main/scala/firrtl/IR.scala88
-rw-r--r--src/main/scala/firrtl/Passes.scala102
-rw-r--r--src/main/scala/firrtl/Primops.scala117
-rw-r--r--src/main/scala/firrtl/Test.scala133
-rw-r--r--src/main/scala/firrtl/Translator.scala4
-rw-r--r--src/main/scala/firrtl/Utils.scala243
-rw-r--r--src/main/scala/firrtl/Visitor.scala64
-rw-r--r--src/main/stanza/ir-utils.stanza123
-rw-r--r--test/parser/bundle.fir43
-rw-r--r--test/parser/gcd.fir52
-rwxr-xr-xutils/bin/firrtl-scala7
17 files changed, 994 insertions, 180 deletions
diff --git a/Makefile b/Makefile
index ad098689..03db8221 100644
--- a/Makefile
+++ b/Makefile
@@ -33,6 +33,18 @@ build: $(stanza)
build-fast: $(stanza)
cd $(firrtl_dir) && $(stanza) -i firrtl-test-main.stanza -o $(root_dir)/utils/bin/firrtl -flags OPTIMIZE
+build-deploy:
+ cd $(firrtl_dir) && $(stanza) -i firrtl-main.stanza -o $(root_dir)/utils/bin/firrtl-stanza
+ make set-stanza
+
+build:
+ cd $(firrtl_dir) && $(stanza) -i firrtl-test-main.stanza -o $(root_dir)/utils/bin/firrtl-stanza
+ make set-stanza
+
+build-fast:
+ cd $(firrtl_dir) && $(stanza) -i firrtl-test-main.stanza -o $(root_dir)/utils/bin/firrtl-stanza -flags OPTIMIZE
+ make set-stanza
+
check:
cd $(test_dir) && lit -v . --path=$(root_dir)/utils/bin/
@@ -73,4 +85,19 @@ done: build-fast check regress
fail:
say "fail"
-.PHONY: all install build-deploy build check clean fail succeed regress
+# Scala Added Makefile commands
+
+build-scala:
+ 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
+
+set-stanza:
+ ln -f -s $(root_dir)/utils/bin/firrtl-stanza $(root_dir)/utils/bin/firrtl
+
+.PHONY: all install build-deploy build check clean fail succeed regress set-scala set-stanza build-scala test-scala
diff --git a/README.md b/README.md
index b60c7c9f..98a7868f 100644
--- a/README.md
+++ b/README.md
@@ -44,7 +44,9 @@
`make`
#### Scala implementation
-The Scala FIRRTL implementation relies upon sbt.
+The Scala FIRRTL implementation relies upon sbt 0.13.6. It uses sbt-assembly to create a fat JAR.
+Using a bash script and a symbolic link it can be used with the same command-line arguments as the stanza implementation.
Example use:
- `sbt -mem 2048 "run-main Example <input> <output>`
-This command will read in &lt;input&gt; FIRRTL file, parse it, then output the AST to &lt;output&gt;
+ `make build-scala`
+ `make set-scala` # Creates symbolic link, make set-stanza reverts to stanza implementation
+ `./utils/bin/firrtl -i <input> -o <output> -X <compiler>`
diff --git a/build.sbt b/build.sbt
index 0a083994..f363d4cf 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,10 +1,25 @@
+
+
lazy val root = (project in file(".")).
settings(
+ organization := "edu.berkeley.cs",
name := "firrtl",
- version := "1.0",
+ version := "0.1-SNAPSHOT",
scalaVersion := "2.11.4"
)
+libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value
+
+// Assembly
+
+//assemblyJarName in assembly := "firrtl.jar"
+
+test in assembly := {} // Should there be tests?
+
+assemblyOutputPath in assembly := file("./utils/bin/firrtl.jar")
+
+// ANTLRv4
+
antlr4Settings
antlr4GenVisitor in Antlr4 := true // default = false
diff --git a/project/assembly.sbt b/project/assembly.sbt
new file mode 100644
index 00000000..a815d584
--- /dev/null
+++ b/project/assembly.sbt
@@ -0,0 +1 @@
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.0")
diff --git a/src/main/antlr4/FIRRTL.g4 b/src/main/antlr4/FIRRTL.g4
index 08697bb1..96172895 100644
--- a/src/main/antlr4/FIRRTL.g4
+++ b/src/main/antlr4/FIRRTL.g4
@@ -1,7 +1,3 @@
-// Jack Koenig
-// UC Berkeley ASPIRE Lab
-// July 9, 2015
-
grammar FIRRTL;
/*------------------------------------------------------------------
@@ -33,8 +29,8 @@ portKind
;
type
- : 'UInt' '<' width '>'
- | 'SInt' '<' width '>'
+ : 'UInt' ('<' width '>')?
+ | 'SInt' ('<' width '>')?
| 'Clock'
| '{' field* '}' // Bundle
| type '[' IntLit ']' // Vector
@@ -93,8 +89,8 @@ dir
// TODO implement
// What is exp?
exp
- : 'UInt' '<' width '>' '(' (IntLit) ')' // FIXME what does "ints" mean?
- | 'SInt' '<' width '>' '(' (IntLit) ')' // FIXME same
+ : 'UInt' ('<' width '>')? '(' (IntLit) ')' // FIXME what does "ints" mean?
+ | 'SInt' ('<' width '>')? '(' (IntLit) ')' // FIXME same
| id // Ref
| exp '.' id // FIXME Does this work for no space?
| exp '[' IntLit ']'
@@ -129,6 +125,8 @@ primop
| 'geq'
| 'eq'
| 'neq'
+ | 'eqv'
+ | 'neqv'
| 'mux'
| 'pad'
| 'asUInt'
diff --git a/src/main/scala/firrtl/DebugUtils.scala b/src/main/scala/firrtl/DebugUtils.scala
new file mode 100644
index 00000000..e802d935
--- /dev/null
+++ b/src/main/scala/firrtl/DebugUtils.scala
@@ -0,0 +1,129 @@
+// Private implicit classes and other utility functions for debugging
+
+package firrtl
+
+import java.io.PrintWriter
+import Utils._
+
+private object DebugUtils {
+
+ implicit class DebugASTUtils(ast: AST) {
+ // Is this actually any use?
+ def preOrderTraversal(f: AST => Unit): Unit = {
+ f(ast)
+ ast match {
+ case a: Block => a.stmts.foreach(_.preOrderTraversal(f))
+ case a: Assert => a.pred.preOrderTraversal(f)
+ case a: When => {
+ a.pred.preOrderTraversal(f)
+ a.conseq.preOrderTraversal(f)
+ a.alt.preOrderTraversal(f)
+ }
+ case a: BulkConnect => {
+ a.lhs.preOrderTraversal(f)
+ a.rhs.preOrderTraversal(f)
+ }
+ case a: Connect => {
+ a.lhs.preOrderTraversal(f)
+ a.rhs.preOrderTraversal(f)
+ }
+ case a: OnReset => {
+ a.lhs.preOrderTraversal(f)
+ a.rhs.preOrderTraversal(f)
+ }
+ case a: DefAccessor => {
+ a.dir.preOrderTraversal(f)
+ a.source.preOrderTraversal(f)
+ a.index.preOrderTraversal(f)
+ }
+ case a: DefPoison => a.tpe.preOrderTraversal(f)
+ case a: DefNode => a.value.preOrderTraversal(f)
+ case a: DefInst => a.module.preOrderTraversal(f)
+ case a: DefMemory => {
+ a.tpe.preOrderTraversal(f)
+ a.clock.preOrderTraversal(f)
+ }
+ case a: DefReg => {
+ a.tpe.preOrderTraversal(f)
+ a.clock.preOrderTraversal(f)
+ a.reset.preOrderTraversal(f)
+ }
+ case a: DefWire => a.tpe.preOrderTraversal(f)
+ case a: Field => {
+ a.dir.preOrderTraversal(f)
+ a.tpe.preOrderTraversal(f)
+ }
+ case a: VectorType => a.tpe.preOrderTraversal(f)
+ case a: BundleType => a.fields.foreach(_.preOrderTraversal(f))
+ case a: Port => {
+ a.dir.preOrderTraversal(f)
+ a.tpe.preOrderTraversal(f)
+ }
+ case a: Module => {
+ a.ports.foreach(_.preOrderTraversal(f))
+ a.stmt.preOrderTraversal(f)
+ }
+ case a: Circuit => a.modules.foreach(_.preOrderTraversal(f))
+ //case _ => throw new Exception(s"Unsupported FIRRTL node ${ast.getClass.getSimpleName}!")
+ case _ =>
+ }
+ }
+ }
+
+
+ /** Private class for recording and organizing debug information */
+ class Logger private (
+ writer: PrintWriter,
+ printMode: Symbol,
+ printVars: List[Symbol]){
+
+ // Legal printModes: 'none, 'error, 'warn, 'info, 'debug, 'trace
+ require(List('none, 'error, 'warn, 'info, 'debug, 'trace) contains printMode)
+ val errorEnable = List('error, 'warn, 'info, 'debug, 'trace) contains printMode
+ val warnEnable = List('warn, 'info, 'debug, 'trace) contains printMode
+ val infoEnable = List('info, 'debug, 'trace) contains printMode
+ val debugEnable = List('debug, 'trace) contains printMode
+ val traceEnable = List('trace) contains printMode
+ val circuitEnable = printVars contains 'circuit
+ val debugFlags = printVars.map(_ -> true).toMap.withDefaultValue(false)
+
+ def println(message: => String){
+ writer.println(message)
+ }
+ def error(message: => String){
+ if (errorEnable) writer.println(message.split("\n").map("[error] " + _).mkString("\n"))
+ }
+ def warn(message: => String){
+ if (warnEnable) writer.println(message.split("\n").map("[warn] " + _).mkString("\n"))
+ }
+ def info(message: => String){
+ if (infoEnable) writer.println(message.split("\n").map("[info] " + _).mkString("\n"))
+ }
+ def debug(message: => String){
+ if (debugEnable) writer.println(message.split("\n").map("[debug] " + _).mkString("\n"))
+ }
+ def trace(message: => String){
+ if (traceEnable) writer.println(message.split("\n").map("[trace] " + _).mkString("\n"))
+ }
+ def printlnDebug(circuit: Circuit){
+ if (circuitEnable) this.println(circuit.serialize(debugFlags))
+ }
+ // Used if not autoflushing
+ def flush() = writer.flush()
+
+ }
+ /** Factory object for logger
+ *
+ * Logger records and organizes debug information
+ */
+ object Logger
+ {
+ def apply(writer: PrintWriter): Logger =
+ new Logger(writer, 'warn, List())
+ def apply(writer: PrintWriter, printMode: Symbol): Logger =
+ new Logger(writer, printMode, List())
+ def apply(writer: PrintWriter, printMode: Symbol, printVars: List[Symbol]): Logger =
+ new Logger(writer, printMode, printVars)
+ def apply(): Logger = new Logger(null, 'none, List())
+ }
+}
diff --git a/src/main/scala/firrtl/IR.scala b/src/main/scala/firrtl/IR.scala
index c52c45a4..5eb4e9e6 100644
--- a/src/main/scala/firrtl/IR.scala
+++ b/src/main/scala/firrtl/IR.scala
@@ -1,3 +1,9 @@
+
+/* TODO
+ * - Should FileInfo be a FIRRTL node?
+ *
+ */
+
package firrtl
import scala.collection.Seq
@@ -9,53 +15,55 @@ case class FileInfo(file: String, line: Int, column: Int) {
trait AST
-trait PrimOp extends AST
-case object Add extends PrimOp
-case object Sub extends PrimOp
-case object Addw extends PrimOp
-case object Subw extends PrimOp
-case object Mul extends PrimOp
-case object Div extends PrimOp
-case object Mod extends PrimOp
-case object Quo extends PrimOp
-case object Rem extends PrimOp
-case object Lt extends PrimOp
-case object Leq extends PrimOp
-case object Gt extends PrimOp
-case object Geq extends PrimOp
-case object Eq extends PrimOp
-case object Neq extends PrimOp
-case object Mux extends PrimOp
-case object Pad extends PrimOp
-case object AsUInt extends PrimOp
-case object AsSInt extends PrimOp
-case object Shl extends PrimOp
-case object Shr extends PrimOp
-case object Dshl extends PrimOp
-case object Dshr extends PrimOp
-case object Cvt extends PrimOp
-case object Neg extends PrimOp
-case object Not extends PrimOp
-case object And extends PrimOp
-case object Or extends PrimOp
-case object Xor extends PrimOp
-case object Andr extends PrimOp
-case object Orr extends PrimOp
-case object Xorr extends PrimOp
-case object Cat extends PrimOp
-case object Bit extends PrimOp
-case object Bits extends PrimOp
+trait Primop extends AST
+case object Add extends Primop
+case object Sub extends Primop
+case object Addw extends Primop
+case object Subw extends Primop
+case object Mul extends Primop
+case object Div extends Primop
+case object Mod extends Primop
+case object Quo extends Primop
+case object Rem extends Primop
+case object Lt extends Primop
+case object Leq extends Primop
+case object Gt extends Primop
+case object Geq extends Primop
+case object Eq extends Primop
+case object Neq extends Primop
+case object Eqv extends Primop
+case object Neqv extends Primop
+case object Mux extends Primop
+case object Pad extends Primop
+case object AsUInt extends Primop
+case object AsSInt extends Primop
+case object Shl extends Primop
+case object Shr extends Primop
+case object Dshl extends Primop
+case object Dshr extends Primop
+case object Cvt extends Primop
+case object Neg extends Primop
+case object Not extends Primop
+case object And extends Primop
+case object Or extends Primop
+case object Xor extends Primop
+case object Andr extends Primop
+case object Orr extends Primop
+case object Xorr extends Primop
+case object Cat extends Primop
+case object Bit extends Primop
+case object Bits extends Primop
// TODO stanza ir has types on many of these, why? Is it the type of what we're referencing?
// Add types, default to UNKNOWN
// TODO add type
trait Exp extends AST
-case class UIntValue(value: BigInt, width: BigInt) extends Exp
-case class SIntValue(value: BigInt, width: BigInt) extends Exp
+case class UIntValue(value: BigInt, width: Width) extends Exp
+case class SIntValue(value: BigInt, width: Width) extends Exp
case class Ref(name: String, tpe: Type) extends Exp
case class Subfield(exp: Exp, name: String, tpe: Type) extends Exp
-case class Subindex(exp: Exp, value: BigInt) extends Exp
-case class DoPrimOp(op: PrimOp, args: Seq[Exp], consts: Seq[BigInt]) extends Exp
+case class Index(exp: Exp, value: BigInt, tpe: Type) extends Exp
+case class DoPrimop(op: Primop, args: Seq[Exp], consts: Seq[BigInt], tpe: Type) extends Exp
trait AccessorDir extends AST
case object Infer extends AccessorDir
diff --git a/src/main/scala/firrtl/Passes.scala b/src/main/scala/firrtl/Passes.scala
new file mode 100644
index 00000000..39e6b64e
--- /dev/null
+++ b/src/main/scala/firrtl/Passes.scala
@@ -0,0 +1,102 @@
+
+package firrtl
+
+import Utils._
+import DebugUtils._
+import Primops._
+
+object Passes {
+
+ private def toField(p: Port)(implicit logger: Logger): Field = {
+ logger.trace(s"toField called on port ${p.serialize}")
+ p.dir match {
+ case Input => Field(p.name, Reverse, p.tpe)
+ case Output => Field(p.name, Default, p.tpe)
+ }
+ }
+
+ /** INFER TYPES
+ *
+ * This pass infers the type field in all IR nodes by updating
+ * and passing an environment to all statements in pre-order
+ * traversal, and resolving types in expressions in post-
+ * order traversal.
+ * Type propagation for primary ops are defined here.
+ * Notable cases: LetRec requires updating environment before
+ * resolving the subexpressions in its elements.
+ * Type errors are not checked in this pass, as this is
+ * postponed for a later/earlier pass.
+ */
+ // input -> flip
+ private type TypeMap = Map[String, Type]
+ private val TypeMap = Map[String, Type]().withDefaultValue(UnknownType)
+ private def getBundleSubtype(t: Type, name: String): Type = {
+ t match {
+ case b: BundleType => {
+ val tpe = b.fields.find( _.name == name )
+ if (tpe.isEmpty) UnknownType
+ else tpe.get.tpe
+ }
+ case _ => UnknownType
+ }
+ }
+ private def getVectorSubtype(t: Type): Type = t.getType // Added for clarity
+ // TODO Add genders
+ private def inferExpTypes(typeMap: TypeMap)(exp: Exp)(implicit logger: Logger): Exp = {
+ logger.trace(s"inferTypes called on ${exp.getClass.getSimpleName}")
+ exp.map(inferExpTypes(typeMap)) match {
+ case e: UIntValue => e
+ case e: SIntValue => e
+ case e: Ref => Ref(e.name, typeMap(e.name))
+ case e: Subfield => Subfield(e.exp, e.name, getBundleSubtype(e.exp.getType, e.name))
+ case e: Index => Index(e.exp, e.value, getVectorSubtype(e.exp.getType))
+ case e: DoPrimop => lowerAndTypePrimop(e)
+ case e: Exp => e
+ }
+ }
+ private def inferTypes(typeMap: TypeMap, stmt: Stmt)(implicit logger: Logger): (Stmt, TypeMap) = {
+ logger.trace(s"inferTypes called on ${stmt.getClass.getSimpleName} ")
+ stmt.map(inferExpTypes(typeMap)) match {
+ case b: Block => {
+ var tMap = typeMap
+ // TODO FIXME is map correctly called in sequential order
+ val body = b.stmts.map { s =>
+ val ret = inferTypes(tMap, s)
+ tMap = ret._2
+ ret._1
+ }
+ (Block(body), tMap)
+ }
+ case s: DefWire => (s, typeMap ++ Map(s.name -> s.tpe))
+ case s: DefReg => (s, typeMap ++ Map(s.name -> s.tpe))
+ case s: DefMemory => (s, typeMap ++ Map(s.name -> s.tpe))
+ case s: DefInst => (s, typeMap ++ Map(s.name -> s.module.getType))
+ case s: DefNode => (s, typeMap ++ Map(s.name -> s.value.getType))
+ case s: DefPoison => (s, typeMap ++ Map(s.name -> s.tpe))
+ case s: DefAccessor => (s, typeMap ++ Map(s.name -> getVectorSubtype(s.source.getType)))
+ case s: When => { // TODO Check: Assuming else block won't see when scope
+ val (conseq, cMap) = inferTypes(typeMap, s.conseq)
+ val (alt, aMap) = inferTypes(typeMap, s.alt)
+ (When(s.info, s.pred, conseq, alt), cMap ++ aMap)
+ }
+ case s: Stmt => (s, typeMap)
+ }
+ }
+ private def inferTypes(typeMap: TypeMap, m: Module)(implicit logger: Logger): Module = {
+ logger.trace(s"inferTypes called on module ${m.name}")
+
+ val pTypeMap = m.ports.map( p => p.name -> p.tpe ).toMap
+
+ Module(m.info, m.name, m.ports, inferTypes(typeMap ++ pTypeMap, m.stmt)._1)
+ }
+ def inferTypes(c: Circuit)(implicit logger: Logger): Circuit = {
+ logger.trace(s"inferTypes called on circuit ${c.name}")
+
+ // initialize typeMap with each module of circuit mapped to their bundled IO (ports converted to fields)
+ val typeMap = c.modules.map(m => m.name -> BundleType(m.ports.map(toField(_)))).toMap
+
+ //val typeMap = c.modules.flatMap(buildTypeMap).toMap
+ Circuit(c.info, c.name, c.modules.map(inferTypes(typeMap, _)))
+ }
+
+}
diff --git a/src/main/scala/firrtl/Primops.scala b/src/main/scala/firrtl/Primops.scala
new file mode 100644
index 00000000..1840b190
--- /dev/null
+++ b/src/main/scala/firrtl/Primops.scala
@@ -0,0 +1,117 @@
+
+package firrtl
+
+import Utils._
+import DebugUtils._
+
+object Primops {
+
+ private val mapPrimop2String = Map[Primop, String](
+ Add -> "add",
+ Sub -> "sub",
+ Addw -> "addw",
+ Subw -> "subw",
+ Mul -> "mul",
+ Div -> "div",
+ Mod -> "mod",
+ Quo -> "quo",
+ Rem -> "rem",
+ Lt -> "lt",
+ Leq -> "leq",
+ Gt -> "gt",
+ Geq -> "geq",
+ Eq -> "eq",
+ Neq -> "neq",
+ Eqv -> "eqv",
+ Neqv -> "neqv",
+ Mux -> "mux",
+ Pad -> "pad",
+ AsUInt -> "asUInt",
+ AsSInt -> "asSInt",
+ Shl -> "shl",
+ Shr -> "shr",
+ Dshl -> "dshl",
+ Dshr -> "dshr",
+ Cvt -> "cvt",
+ Neg -> "neg",
+ Not -> "not",
+ And -> "and",
+ Or -> "or",
+ Xor -> "xor",
+ Andr -> "andr",
+ Orr -> "orr",
+ Xorr -> "xorr",
+ Cat -> "cat",
+ Bit -> "bit",
+ Bits -> "bits"
+ )
+ private val mapString2Primop = mapPrimop2String.map(_.swap)
+ def fromString(op: String): Primop = mapString2Primop(op)
+
+ implicit class PrimopImplicits(op: Primop){
+ def getString(): String = mapPrimop2String(op)
+ }
+
+ // Borrowed from Stanza implementation
+ def lowerAndTypePrimop(e: DoPrimop)(implicit logger: Logger): DoPrimop = {
+ def uAnd(op1: Exp, op2: Exp): Type = {
+ (op1.getType, op2.getType) match {
+ case (t1: UIntType, t2: UIntType) => UIntType(UnknownWidth)
+ case (t1: SIntType, t2) => SIntType(UnknownWidth)
+ case (t1, t2: SIntType) => SIntType(UnknownWidth)
+ case _ => UnknownType
+ }
+ }
+ def ofType(op: Exp): Type = {
+ op.getType match {
+ case t: UIntType => UIntType(UnknownWidth)
+ case t: SIntType => SIntType(UnknownWidth)
+ case _ => UnknownType
+ }
+ }
+
+ logger.debug(s"lowerAndTypePrimop on ${e.op.getClass.getSimpleName}")
+ val tpe = e.op match {
+ case Add => uAnd(e.args(0), e.args(1))
+ case Sub => SIntType(UnknownWidth)
+ case Addw => uAnd(e.args(0), e.args(1))
+ case Subw => uAnd(e.args(0), e.args(1))
+ case Mul => uAnd(e.args(0), e.args(1))
+ case Div => uAnd(e.args(0), e.args(1))
+ case Mod => ofType(e.args(0))
+ case Quo => uAnd(e.args(0), e.args(1))
+ case Rem => ofType(e.args(1))
+ case Lt => UIntType(UnknownWidth)
+ case Leq => UIntType(UnknownWidth)
+ case Gt => UIntType(UnknownWidth)
+ case Geq => UIntType(UnknownWidth)
+ case Eq => UIntType(UnknownWidth)
+ case Neq => UIntType(UnknownWidth)
+ case Eqv => UIntType(UnknownWidth)
+ case Neqv => UIntType(UnknownWidth)
+ case Mux => ofType(e.args(1))
+ case Pad => ofType(e.args(0))
+ case AsUInt => UIntType(UnknownWidth)
+ case AsSInt => SIntType(UnknownWidth)
+ case Shl => ofType(e.args(0))
+ case Shr => ofType(e.args(0))
+ case Dshl => ofType(e.args(0))
+ case Dshr => ofType(e.args(0))
+ case Cvt => SIntType(UnknownWidth)
+ case Neg => SIntType(UnknownWidth)
+ case Not => ofType(e.args(0))
+ case And => ofType(e.args(0))
+ case Or => ofType(e.args(0))
+ case Xor => ofType(e.args(0))
+ case Andr => UIntType(UnknownWidth)
+ case Orr => UIntType(UnknownWidth)
+ case Xorr => UIntType(UnknownWidth)
+ case Cat => UIntType(UnknownWidth)
+ case Bit => UIntType(UnknownWidth)
+ case Bits => UIntType(UnknownWidth)
+ case _ => ???
+ }
+ DoPrimop(e.op, e.args, e.consts, tpe)
+ }
+
+}
diff --git a/src/main/scala/firrtl/Test.scala b/src/main/scala/firrtl/Test.scala
new file mode 100644
index 00000000..3a89aeef
--- /dev/null
+++ b/src/main/scala/firrtl/Test.scala
@@ -0,0 +1,133 @@
+package firrtl
+
+import java.io._
+import Utils._
+import DebugUtils._
+import Passes._
+
+object Test
+{
+ private val usage = """
+ Usage: java -cp utils/bin/firrtl.jar firrtl.Test [options] -i <input> -o <output>
+ """
+ private val defaultOptions = Map[Symbol, Any]().withDefaultValue(false)
+
+ // Parse input file and print to output
+ private def highFIRRTL(input: String, output: String)(implicit logger: Logger)
+ {
+ val ast = Parser.parse(input)
+ val writer = new PrintWriter(new File(output))
+ writer.write(ast.serialize())
+ writer.close()
+ logger.printlnDebug(ast)
+ }
+ private def verilog(input: String, output: String)(implicit logger: Logger)
+ {
+ logger.warn("Verilog compiler not fully implemented")
+ val ast = time("parse"){ Parser.parse(input) }
+ // Execute passes
+
+ logger.println("Infer Types")
+ val ast2 = time("inferTypes"){ inferTypes(ast) }
+ logger.printlnDebug(ast2)
+ logger.println("Finished Infer Types")
+ //val ast2 = ast
+
+ // Output
+ val writer = new PrintWriter(new File(output))
+ var outString = time("serialize"){ ast2.serialize() }
+ writer.write(outString)
+ writer.close()
+ }
+
+ def main(args: Array[String])
+ {
+ val arglist = args.toList
+ type OptionMap = Map[Symbol, Any]
+
+ // Default debug mode is 'debug
+ def decodeDebugMode(mode: Any): Symbol =
+ mode match {
+ case s: String => Symbol(s)
+ case _ => 'debug
+ }
+
+ def nextPrintVar(syms: List[Symbol], chars: List[Char]): List[Symbol] =
+ chars match {
+ case Nil => syms
+ case 't' :: tail => nextPrintVar(syms ++ List('types), tail)
+ case 'k' :: tail => nextPrintVar(syms ++ List('kinds), tail)
+ case 'w' :: tail => nextPrintVar(syms ++ List('widths), tail)
+ case 'T' :: tail => nextPrintVar(syms ++ List('twidths), tail)
+ case 'g' :: tail => nextPrintVar(syms ++ List('genders), tail)
+ case 'c' :: tail => nextPrintVar(syms ++ List('circuit), tail)
+ case 'd' :: tail => nextPrintVar(syms ++ List('debug), tail) // Currently ignored
+ case 'i' :: tail => nextPrintVar(syms ++ List('info), tail)
+ case char :: tail => throw new Exception("Unknown print option " + char)
+ }
+
+ def nextOption(map: OptionMap, list: List[String]): OptionMap = {
+ list match {
+ case Nil => map
+ case "-X" :: value :: tail =>
+ nextOption(map ++ Map('compiler -> value), tail)
+ case "-d" :: value :: tail =>
+ nextOption(map ++ Map('debugMode -> value), tail)
+ case "-l" :: value :: tail =>
+ nextOption(map ++ Map('log -> value), tail)
+ case "-p" :: value :: tail =>
+ nextOption(map ++ Map('printVars -> value), tail)
+ case "-i" :: value :: tail =>
+ nextOption(map ++ Map('input -> value), tail)
+ case "-o" :: value :: tail =>
+ nextOption(map ++ Map('output -> value), tail)
+ case ("-h" | "--help") :: tail =>
+ nextOption(map ++ Map('help -> true), tail)
+ case option :: tail =>
+ throw new Exception("Unknown option " + option)
+ }
+ }
+ val options = nextOption(defaultOptions, arglist)
+
+ if (options('help) == true) {
+ println(usage)
+ System.exit(0)
+ }
+
+ val input = options('input) match {
+ case s: String => s
+ case false => throw new Exception("No input file provided!" + usage)
+ }
+ val output = options('output) match {
+ case s: String => s
+ case false => throw new Exception("No output file provided!" + usage)
+ }
+ val debugMode = decodeDebugMode(options('debugMode))
+ val printVars = options('printVars) match {
+ case s: String => nextPrintVar(List(), s.toList)
+ case false => List()
+ }
+ implicit val logger = options('log) match {
+ case s: String => Logger(new PrintWriter(new FileOutputStream(s)), debugMode, printVars)
+ case false => Logger(new PrintWriter(System.err, true), debugMode, printVars)
+ }
+
+ // -p "printVars" options only print for debugMode > 'debug, warn if -p enabled and debugMode < 'debug
+ if( !logger.debugEnable && !printVars.isEmpty )
+ logger.warn("-p options will not print unless debugMode (-d) is debug or trace")
+
+ options('compiler) match {
+ case "verilog" => verilog(input, output)
+ case "HighFIRRTL" => highFIRRTL(input, output)
+ case other => throw new Exception("Invalid compiler! " + other)
+ }
+ }
+
+ def time[R](str: String)(block: => R)(implicit logger: Logger): R = {
+ val t0 = System.currentTimeMillis()
+ val result = block // call-by-name
+ val t1 = System.currentTimeMillis()
+ logger.info(s"Time to ${str}: ${t1 - t0} ms")
+ result
+ }
+}
diff --git a/src/main/scala/firrtl/Translator.scala b/src/main/scala/firrtl/Translator.scala
index eba78b39..a16d89d7 100644
--- a/src/main/scala/firrtl/Translator.scala
+++ b/src/main/scala/firrtl/Translator.scala
@@ -21,6 +21,7 @@ object Translator
def addBrackets(inputIt: Iterator[String]): StringBuilder = {
def countSpaces(s: String): Int = s.prefixLength(_ == ' ')
+ def stripComments(s: String): String = s takeWhile (!";".contains(_))
val Scopers = """\s*(circuit|module|when|else)(.*)""".r
@@ -45,7 +46,8 @@ object Translator
var newScope = true // indicates if increasing scope spacing is legal on next line
while( it.hasNext ) {
- it.next match { case (text, lineNum) =>
+ it.next match { case (lineText, lineNum) =>
+ val text = stripComments(lineText)
val spaces = countSpaces(text)
val l = if (text.length > spaces ) { // Check that line has text in it
diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala
index 916408bc..4220e07f 100644
--- a/src/main/scala/firrtl/Utils.scala
+++ b/src/main/scala/firrtl/Utils.scala
@@ -2,77 +2,94 @@
/* TODO
* - Adopt style more similar to Chisel3 Emitter?
+ * - Find way to have generic map function instead of mapE and mapS under Stmt implicits
*/
package firrtl
import scala.collection.mutable.StringBuilder
+import java.io.PrintWriter
+import Primops._
+//import scala.reflect.runtime.universe._
object Utils {
-
- implicit class BigIntUtils(bi: BigInt){
- def serialize(): String =
- "\"h0" + bi.toString(16) + "\""
- }
-
- implicit class PrimOpUtils(op: PrimOp) {
- def serialize(): String = {
- op match {
- case Add => "add"
- case Sub => "sub"
- case Addw => "addw"
- case Subw => "subw"
- case Mul => "mul"
- case Div => "div"
- case Mod => "mod"
- case Quo => "quo"
- case Rem => "rem"
- case Lt => "lt"
- case Leq => "leq"
- case Gt => "gt"
- case Geq => "geq"
- case Eq => "eq"
- case Neq => "neq"
- case Mux => "mux"
- case Pad => "pad"
- case AsUInt => "asUInt"
- case AsSInt => "asSInt"
- case Shl => "shl"
- case Shr => "shr"
- case Dshl => "dshl"
- case Dshr => "dshr"
- case Cvt => "cvt"
- case Neg => "neg"
- case Not => "not"
- case And => "and"
- case Or => "or"
- case Xor => "xor"
- case Andr => "andr"
- case Orr => "orr"
- case Xorr => "xorr"
- case Cat => "cat"
- case Bit => "bit"
- case Bits => "bits"
- }
+
+ // Is there a more elegant way to do this?
+ private type FlagMap = Map[Symbol, Boolean]
+ private val FlagMap = Map[Symbol, Boolean]().withDefaultValue(false)
+
+ def debug(node: AST)(implicit flags: FlagMap): String = {
+ if (!flags.isEmpty) {
+ var str = ""
+ if (flags('types)) {
+ val tpe = node.getType
+ if( tpe != UnknownType ) str += s"@<t:${tpe.wipeWidth.serialize}>"
+ }
+ str
}
+ else {
+ ""
+ }
+ }
+
+ implicit class BigIntUtils(bi: BigInt){
+ def serialize(implicit flags: FlagMap = FlagMap): String =
+ "\"h" + bi.toString(16) + "\""
+ }
+
+ implicit class ASTUtils(ast: AST) {
+ def getType(): Type =
+ ast match {
+ case e: Exp => e.getType
+ case s: Stmt => s.getType
+ //case f: Field => f.getType
+ case t: Type => t.getType
+ case p: Port => p.getType
+ case _ => UnknownType
+ }
+ }
+
+ implicit class PrimopUtils(op: Primop) {
+ def serialize(implicit flags: FlagMap = FlagMap): String = op.getString
}
implicit class ExpUtils(exp: Exp) {
- def serialize(): String =
- exp match {
- case v: UIntValue => s"UInt<${v.width}>(${v.value.serialize})"
- case v: SIntValue => s"SInt<${v.width}>(${v.value.serialize})"
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
+ val ret = exp match {
+ case v: UIntValue => s"UInt${v.width.serialize}(${v.value.serialize})"
+ case v: SIntValue => s"SInt${v.width.serialize}(${v.value.serialize})"
case r: Ref => r.name
case s: Subfield => s"${s.exp.serialize}.${s.name}"
- case s: Subindex => s"${s.exp.serialize}[${s.value}]"
- case p: DoPrimOp =>
+ case s: Index => s"${s.exp.serialize}[${s.value}]"
+ case p: DoPrimop =>
s"${p.op.serialize}(" + (p.args.map(_.serialize) ++ p.consts.map(_.toString)).mkString(", ") + ")"
}
+ ret + debug(exp)
+ }
+
+ def map(f: Exp => Exp): Exp =
+ exp match {
+ case s: Subfield => Subfield(f(s.exp), s.name, s.tpe)
+ case i: Index => Index(f(i.exp), i.value, i.tpe)
+ case p: DoPrimop => DoPrimop(p.op, p.args.map(f), p.consts, p.tpe)
+ case e: Exp => e
+ }
+
+ def getType(): Type = {
+ exp match {
+ case v: UIntValue => UIntType(UnknownWidth)
+ case v: SIntValue => SIntType(UnknownWidth)
+ case r: Ref => r.tpe
+ case s: Subfield => s.tpe
+ case i: Index => i.tpe
+ case p: DoPrimop => p.tpe
+ }
+ }
}
// AccessorDir
implicit class AccessorDirUtils(dir: AccessorDir) {
- def serialize(): String =
+ def serialize(implicit flags: FlagMap = FlagMap): String =
dir match {
case Infer => "infer"
case Read => "read"
@@ -81,10 +98,41 @@ object Utils {
}
}
+ // Some Scala implicit magic to solve type erasure on Stmt map function overloading
+ private trait StmtMagnet {
+ def map(stmt: Stmt): Stmt
+ }
+ private object StmtMagnet {
+ implicit def forStmt(f: Stmt => Stmt) = new StmtMagnet {
+ override def map(stmt: Stmt): Stmt =
+ stmt match {
+ case w: When => When(w.info, w.pred, f(w.conseq), f(w.alt))
+ case b: Block => Block(b.stmts.map(f))
+ case s: Stmt => s
+ }
+ }
+ implicit def forExp(f: Exp => Exp) = new StmtMagnet {
+ override def map(stmt: Stmt): Stmt =
+ stmt match {
+ case r: DefReg => DefReg(r.info, r.name, r.tpe, f(r.clock), f(r.reset))
+ case m: DefMemory => DefMemory(m.info, m.name, m.seq, m.tpe, f(m.clock))
+ case i: DefInst => DefInst(i.info, i.name, f(i.module))
+ case n: DefNode => DefNode(n.info, n.name, f(n.value))
+ case a: DefAccessor => DefAccessor(a.info, a.name, a.dir, f(a.source), f(a.index))
+ case o: OnReset => OnReset(o.info, f(o.lhs), f(o.rhs))
+ case c: Connect => Connect(c.info, f(c.lhs), f(c.rhs))
+ case b: BulkConnect => BulkConnect(b.info, f(b.lhs), f(b.rhs))
+ case w: When => When(w.info, f(w.pred), w.conseq, w.alt)
+ case a: Assert => Assert(a.info, f(a.pred))
+ case s: Stmt => s
+ }
+ }
+ }
implicit class StmtUtils(stmt: Stmt) {
- def serialize(): String =
- stmt match {
+ def serialize(implicit flags: FlagMap = FlagMap): String =
+ {
+ var ret = stmt match {
case w: DefWire => s"wire ${w.name} : ${w.tpe.serialize}"
case r: DefReg => s"reg ${r.name} : ${r.tpe.serialize}, ${r.clock.serialize}, ${r.reset.serialize}"
case m: DefMemory => (if(m.seq) "smem" else "cmem") +
@@ -109,78 +157,117 @@ object Utils {
case b: Block => {
val s = new StringBuilder
b.stmts.foreach { s ++= newline ++ _.serialize }
- s.result
- }
+ s.result + debug(b)
+ }
case a: Assert => s"assert ${a.pred.serialize}"
case EmptyStmt => "skip"
}
+ ret + debug(stmt)
+ }
+
+ // Using implicit types to allow overloading of function type to map, see StmtMagnet above
+ def map[T](f: T => T)(implicit magnet: (T => T) => StmtMagnet): Stmt = magnet(f).map(stmt)
+
+ def getType(): Type =
+ stmt match {
+ case s: DefWire => s.tpe
+ case s: DefReg => s.tpe
+ case s: DefMemory => s.tpe
+ case s: DefPoison => s.tpe
+ case _ => UnknownType
+ }
}
implicit class WidthUtils(w: Width) {
- def serialize(): String =
- w match {
- case UnknownWidth => "?"
- case w: IntWidth => w.width.toString
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
+ val s = w match {
+ case UnknownWidth => "" //"?"
+ case w: IntWidth => s"<${w.width.toString}>"
}
+ s + debug(w)
+ }
}
implicit class FieldDirUtils(dir: FieldDir) {
- def serialize(): String =
- dir match {
- case Reverse => "flip "
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
+ val s = dir match {
+ case Reverse => "flip"
case Default => ""
}
+ s + debug(dir)
+ }
}
implicit class FieldUtils(field: Field) {
- def serialize(): String =
- s"${field.dir.serialize} ${field.name} : ${field.tpe.serialize}"
+ def serialize(implicit flags: FlagMap = FlagMap): String =
+ s"${field.dir.serialize} ${field.name} : ${field.tpe.serialize}" + debug(field)
+
+ def getType(): Type = field.tpe
}
implicit class TypeUtils(t: Type) {
- def serialize(): String = {
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
val commas = ", " // for mkString in BundleType
- t match {
+ val s = t match {
case ClockType => "Clock"
- case UnknownType => "UnknownType"
- case t: UIntType => s"UInt<${t.width.serialize}>"
- case t: SIntType => s"SInt<${t.width.serialize}>"
- case t: BundleType => s"{ ${t.fields.map(_.serialize).mkString(commas)} }"
+ //case UnknownType => "UnknownType"
+ case UnknownType => "?"
+ case t: UIntType => s"UInt${t.width.serialize}"
+ case t: SIntType => s"SInt${t.width.serialize}"
+ case t: BundleType => s"{${t.fields.map(_.serialize).mkString(commas)}}"
case t: VectorType => s"${t.tpe.serialize}[${t.size}]"
}
+ s + debug(t)
}
+
+ def getType(): Type =
+ t match {
+ case v: VectorType => v.tpe
+ case tpe: Type => UnknownType
+ }
+
+ def wipeWidth(): Type =
+ t match {
+ case t: UIntType => UIntType(UnknownWidth)
+ case t: SIntType => SIntType(UnknownWidth)
+ case _ => t
+ }
}
implicit class PortDirUtils(p: PortDir) {
- def serialize(): String =
- p match {
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
+ val s = p match {
case Input => "input"
case Output => "output"
}
+ s + debug(p)
+ }
}
implicit class PortUtils(p: Port) {
- def serialize(): String =
- s"${p.dir.serialize} ${p.name} : ${p.tpe.serialize}"
+ def serialize(implicit flags: FlagMap = FlagMap): String =
+ s"${p.dir.serialize} ${p.name} : ${p.tpe.serialize}" + debug(p)
+ def getType(): Type = p.tpe
}
implicit class ModuleUtils(m: Module) {
- def serialize(): String = {
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
var s = new StringBuilder(s"module ${m.name} : ")
withIndent {
s ++= m.ports.map(newline ++ _.serialize).mkString
s ++= newline ++ m.stmt.serialize
}
+ s ++= debug(m)
s.toString
}
}
implicit class CircuitUtils(c: Circuit) {
- def serialize(): String = {
+ def serialize(implicit flags: FlagMap = FlagMap): String = {
var s = new StringBuilder(s"circuit ${c.name} : ")
- //withIndent { c.modules.foreach(s ++= newline ++ newline ++ _.serialize) }
withIndent { s ++= newline ++ c.modules.map(_.serialize).mkString(newline + newline) }
s ++= newline ++ newline
+ s ++= debug(c)
s.toString
}
}
diff --git a/src/main/scala/firrtl/Visitor.scala b/src/main/scala/firrtl/Visitor.scala
index 276facce..7d54ca1a 100644
--- a/src/main/scala/firrtl/Visitor.scala
+++ b/src/main/scala/firrtl/Visitor.scala
@@ -3,6 +3,7 @@
* - Support all integer types (not just "h...")
* - In ANTLR examples they use just visit, why am I having to use visitModule or other specific functions?
* - Make visit private?
+ * - More elegant way to insert UnknownWidth?
*/
package firrtl
@@ -13,6 +14,7 @@ import org.antlr.v4.runtime.tree.ErrorNode
import org.antlr.v4.runtime.tree.TerminalNode
import scala.collection.JavaConversions._
import antlr._
+import Primops._
class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
{
@@ -58,8 +60,10 @@ class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
// Match on a type instead of on strings?
private def visitType[AST](ctx: FIRRTLParser.TypeContext): Type = {
ctx.getChild(0).getText match {
- case "UInt" => UIntType( visitWidth(ctx.width) )
- case "SInt" => SIntType( visitWidth(ctx.width) )
+ case "UInt" => if (ctx.getChildCount > 1) UIntType( visitWidth(ctx.width) )
+ else UIntType( UnknownWidth )
+ case "SInt" => if (ctx.getChildCount > 1) SIntType( visitWidth(ctx.width) )
+ else SIntType( UnknownWidth )
case "Clock" => ClockType
case "{" => BundleType(ctx.field.map(visitField))
case _ => new VectorType( visitType(ctx.`type`), string2BigInt(ctx.IntLit.getText) )
@@ -132,54 +136,24 @@ class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
Ref(ctx.getText, UnknownType)
else
ctx.getChild(0).getText match {
- case "UInt" => UIntValue(string2BigInt(ctx.IntLit(0).getText), string2BigInt(ctx.width.getText))
- case "SInt" => SIntValue(string2BigInt(ctx.IntLit(0).getText), string2BigInt(ctx.width.getText))
+ case "UInt" => {
+ val width = if (ctx.getChildCount > 4) visitWidth(ctx.width) else UnknownWidth
+ UIntValue(string2BigInt(ctx.IntLit(0).getText), width)
+ }
+ //case "SInt" => SIntValue(string2BigInt(ctx.IntLit(0).getText), string2BigInt(ctx.width.getText))
+ case "SInt" => {
+ val width = if (ctx.getChildCount > 4) visitWidth(ctx.width) else UnknownWidth
+ SIntValue(string2BigInt(ctx.IntLit(0).getText), width)
+ }
case _ =>
ctx.getChild(1).getText match {
case "." => new Subfield(visitExp(ctx.exp(0)), ctx.id.getText, UnknownType)
- case "[" => new Subindex(visitExp(ctx.exp(0)), string2BigInt(ctx.IntLit(0).getText))
+ case "[" => new Index(visitExp(ctx.exp(0)), string2BigInt(ctx.IntLit(0).getText), UnknownType)
case "(" =>
- DoPrimOp(visitPrimop(ctx.primop), ctx.exp.map(visitExp), ctx.IntLit.map(x => string2BigInt(x.getText)))
+ DoPrimop(visitPrimop(ctx.primop), ctx.exp.map(visitExp),
+ ctx.IntLit.map(x => string2BigInt(x.getText)), UnknownType)
}
}
- // TODO can I create this and have the opposite? create map and invert it?
- private def visitPrimop[AST](ctx: FIRRTLParser.PrimopContext): PrimOp =
- ctx.getText match {
- case "add" => Add
- case "sub" => Sub
- case "addw" => Addw
- case "subw" => Subw
- case "mul" => Mul
- case "div" => Div
- case "mod" => Mod
- case "quo" => Quo
- case "rem" => Rem
- case "lt" => Lt
- case "leq" => Leq
- case "gt" => Gt
- case "geq" => Geq
- case "eq" => Eq
- case "neq" => Neq
- case "mux" => Mux
- case "pad" => Pad
- case "asUInt" => AsUInt
- case "asSInt" => AsSInt
- case "shl" => Shl
- case "shr" => Shr
- case "dshl" => Dshl
- case "dshr" => Dshr
- case "cvt" => Cvt
- case "neg" => Neg
- case "not" => Not
- case "and" => And
- case "or" => Or
- case "xor" => Xor
- case "andr" => Andr
- case "orr" => Orr
- case "xorr" => Xorr
- case "cat" => Cat
- case "bit" => Bit
- case "bits" => Bits
- }
+ private def visitPrimop[AST](ctx: FIRRTLParser.PrimopContext): Primop = fromString(ctx.getText)
}
diff --git a/src/main/stanza/ir-utils.stanza b/src/main/stanza/ir-utils.stanza
index 59c7c36a..3fd96882 100644
--- a/src/main/stanza/ir-utils.stanza
+++ b/src/main/stanza/ir-utils.stanza
@@ -548,94 +548,199 @@ public defn pow (x:Long,y:Long) -> Long :
;=================== VERILOG KEYWORDS =======================
public val v-keywords = HashTable<Symbol,True>(symbol-hash)
+v-keywords[`alias] = true
v-keywords[`always] = true
+v-keywords[`always_comb] = true
+v-keywords[`always_ff] = true
+v-keywords[`always_latch] = true
v-keywords[`and] = true
+v-keywords[`assert] = true
v-keywords[`assign] = true
+v-keywords[`assume] = true
v-keywords[`attribute] = true
+v-keywords[`automatic] = true
+v-keywords[`before] = true
v-keywords[`begin] = true
+v-keywords[`bind] = true
+v-keywords[`bins] = true
+v-keywords[`binsof] = true
+v-keywords[`bit] = true
+v-keywords[`break] = true
v-keywords[`buf] = true
v-keywords[`bufif0] = true
v-keywords[`bufif1] = true
+v-keywords[`byte] = true
v-keywords[`case] = true
v-keywords[`casex] = true
v-keywords[`casez] = true
+v-keywords[`cell] = true
+v-keywords[`chandle] = true
+v-keywords[`class] = true
+v-keywords[`clocking] = true
v-keywords[`cmos] = true
+v-keywords[`config] = true
+v-keywords[`const] = true
+v-keywords[`constraint] = true
+v-keywords[`context] = true
+v-keywords[`continue] = true
+v-keywords[`cover] = true
+v-keywords[`covergroup] = true
+v-keywords[`coverpoint] = true
+v-keywords[`cross] = true
v-keywords[`deassign] = true
v-keywords[`default] = true
v-keywords[`defparam] = true
+v-keywords[`design] = true
v-keywords[`disable] = true
+v-keywords[`dist] = true
+v-keywords[`do] = true
v-keywords[`edge] = true
v-keywords[`else] = true
v-keywords[`end] = true
v-keywords[`endattribute] = true
v-keywords[`endcase] = true
+v-keywords[`endclass] = true
+v-keywords[`endclocking] = true
+v-keywords[`endconfig] = true
v-keywords[`endfunction] = true
+v-keywords[`endgenerate] = true
+v-keywords[`endgroup] = true
+v-keywords[`endinterface] = true
v-keywords[`endmodule] = true
+v-keywords[`endpackage] = true
v-keywords[`endprimitive] = true
+v-keywords[`endprogram] = true
+v-keywords[`endproperty] = true
v-keywords[`endspecify] = true
+v-keywords[`endsequence] = true
v-keywords[`endtable] = true
v-keywords[`endtask] = true
+v-keywords[`enum] = true
v-keywords[`event] = true
+v-keywords[`expect] = true
+v-keywords[`export] = true
+v-keywords[`extends] = true
+v-keywords[`extern] = true
+v-keywords[`final] = true
+v-keywords[`first_match] = true
v-keywords[`for] = true
v-keywords[`force] = true
+v-keywords[`foreach] = true
v-keywords[`forever] = true
v-keywords[`fork] = true
+v-keywords[`forkjoin] = true
v-keywords[`function] = true
+v-keywords[`generate] = true
+v-keywords[`genvar] = true
v-keywords[`highz0] = true
v-keywords[`highz1] = true
v-keywords[`if] = true
+v-keywords[`iff] = true
v-keywords[`ifnone] = true
+v-keywords[`ignore_bins] = true
+v-keywords[`illegal_bins] = true
+v-keywords[`import] = true
+v-keywords[`incdir] = true
+v-keywords[`include] = true
v-keywords[`initial] = true
+v-keywords[`initvar] = true
v-keywords[`inout] = true
v-keywords[`input] = true
+v-keywords[`inside] = true
+v-keywords[`instance] = true
+v-keywords[`int] = true
v-keywords[`integer] = true
-v-keywords[`initvar] = true
+v-keywords[`interconnect] = true
+v-keywords[`interface] = true
+v-keywords[`intersect] = true
v-keywords[`join] = true
-v-keywords[`medium] = true
-v-keywords[`module] = true
+v-keywords[`join_any] = true
+v-keywords[`join_none] = true
v-keywords[`large] = true
+v-keywords[`liblist] = true
+v-keywords[`library] = true
+v-keywords[`local] = true
+v-keywords[`localparam] = true
+v-keywords[`logic] = true
+v-keywords[`longint] = true
v-keywords[`macromodule] = true
+v-keywords[`matches] = true
+v-keywords[`medium] = true
+v-keywords[`modport] = true
+v-keywords[`module] = true
v-keywords[`nand] = true
v-keywords[`negedge] = true
+v-keywords[`new] = true
v-keywords[`nmos] = true
v-keywords[`nor] = true
+v-keywords[`noshowcancelled] = true
v-keywords[`not] = true
v-keywords[`notif0] = true
v-keywords[`notif1] = true
+v-keywords[`null] = true
v-keywords[`or] = true
v-keywords[`output] = true
+v-keywords[`package] = true
+v-keywords[`packed] = true
v-keywords[`parameter] = true
v-keywords[`pmos] = true
v-keywords[`posedge] = true
v-keywords[`primitive] = true
+v-keywords[`priority] = true
+v-keywords[`program] = true
+v-keywords[`property] = true
+v-keywords[`protected] = true
v-keywords[`pull0] = true
v-keywords[`pull1] = true
v-keywords[`pulldown] = true
v-keywords[`pullup] = true
+v-keywords[`pulsestyle_onevent] = true
+v-keywords[`pulsestyle_ondetect] = true
+v-keywords[`pure] = true
+v-keywords[`rand] = true
+v-keywords[`randc] = true
+v-keywords[`randcase] = true
+v-keywords[`randsequence] = true
v-keywords[`rcmos] = true
v-keywords[`real] = true
v-keywords[`realtime] = true
+v-keywords[`ref] = true
v-keywords[`reg] = true
v-keywords[`release] = true
v-keywords[`repeat] = true
+v-keywords[`return] = true
v-keywords[`rnmos] = true
v-keywords[`rpmos] = true
v-keywords[`rtran] = true
v-keywords[`rtranif0] = true
v-keywords[`rtranif1] = true
v-keywords[`scalared] = true
+v-keywords[`sequence] = true
+v-keywords[`shortint] = true
+v-keywords[`shortreal] = true
+v-keywords[`showcancelled] = true
v-keywords[`signed] = true
v-keywords[`small] = true
+v-keywords[`solve] = true
v-keywords[`specify] = true
v-keywords[`specparam] = true
+v-keywords[`static] = true
v-keywords[`strength] = true
+v-keywords[`string] = true
v-keywords[`strong0] = true
v-keywords[`strong1] = true
+v-keywords[`struct] = true
+v-keywords[`super] = true
v-keywords[`supply0] = true
v-keywords[`supply1] = true
v-keywords[`table] = true
+v-keywords[`tagged] = true
v-keywords[`task] = true
+v-keywords[`this] = true
+v-keywords[`throughout] = true
v-keywords[`time] = true
+v-keywords[`timeprecision] = true
+v-keywords[`timeunit] = true
v-keywords[`tran] = true
v-keywords[`tranif0] = true
v-keywords[`tranif1] = true
@@ -645,14 +750,26 @@ v-keywords[`tri1] = true
v-keywords[`triand] = true
v-keywords[`trior] = true
v-keywords[`trireg] = true
+v-keywords[`type] = true
+v-keywords[`typedef] = true
+v-keywords[`union] = true
+v-keywords[`unique] = true
v-keywords[`unsigned] = true
+v-keywords[`use] = true
+v-keywords[`var] = true
v-keywords[`vectored] = true
+v-keywords[`virtual] = true
+v-keywords[`void] = true
v-keywords[`wait] = true
+v-keywords[`wait_order] = true
v-keywords[`wand] = true
v-keywords[`weak0] = true
v-keywords[`weak1] = true
v-keywords[`while] = true
+v-keywords[`wildcard] = true
v-keywords[`wire] = true
+v-keywords[`with] = true
+v-keywords[`within] = true
v-keywords[`wor] = true
v-keywords[`xnor] = true
v-keywords[`xor] = true
diff --git a/test/parser/bundle.fir b/test/parser/bundle.fir
new file mode 100644
index 00000000..c9600d10
--- /dev/null
+++ b/test/parser/bundle.fir
@@ -0,0 +1,43 @@
+; RUN: firrtl -i %s -o %s.out -X HighFIRRTL && cat %s.out | FileCheck %s
+circuit top :
+ module top :
+ wire z : { x : UInt, flip y: SInt}
+ z.x := UInt(1)
+ z.y := SInt(1)
+ node x = z.x
+ node y = z.y
+ wire a : UInt<3>[10]
+ a[0] := UInt(1)
+ a[1] := UInt(1)
+ a[2] := UInt(1)
+ a[3] := UInt(1)
+ a[4] := UInt(1)
+ a[5] := UInt(1)
+ a[6] := UInt(1)
+ a[7] := UInt(1)
+ a[8] := UInt(1)
+ a[9] := UInt(1)
+ node b = a[2]
+ read accessor c = a[UInt(3)]
+
+; CHECK: circuit top :
+; CHECK: module top :
+; CHECK: wire z : { x : UInt, flip y : SInt}
+; CHECK: z.x := UInt("h1")
+; CHECK: z.y := SInt("h1")
+; CHECK: node x = z.x
+; CHECK: node y = z.y
+; CHECK: wire a : UInt<3>[10]
+; CHECK: a[0] := UInt("h1")
+; CHECK: a[1] := UInt("h1")
+; CHECK: a[2] := UInt("h1")
+; CHECK: a[3] := UInt("h1")
+; CHECK: a[4] := UInt("h1")
+; CHECK: a[5] := UInt("h1")
+; CHECK: a[6] := UInt("h1")
+; CHECK: a[7] := UInt("h1")
+; CHECK: a[8] := UInt("h1")
+; CHECK: a[9] := UInt("h1")
+; CHECK: node b = a[2]
+; CHECK: read accessor c = a[UInt("h3")]
+
diff --git a/test/parser/gcd.fir b/test/parser/gcd.fir
new file mode 100644
index 00000000..3a9317b8
--- /dev/null
+++ b/test/parser/gcd.fir
@@ -0,0 +1,52 @@
+; RUN: firrtl -i %s -o %s.out -X HighFIRRTL && cat %s.out | FileCheck %s
+circuit GCD :
+ module GCD :
+ input e : UInt<1>
+ input clk : Clock
+ input reset : UInt<1>
+ output z : UInt<16>
+ output v : UInt<1>
+ input a : UInt<16>
+ input b : UInt<16>
+
+ reg x : UInt<16>,clk,reset
+ reg y : UInt<16>,clk,reset
+ node T_17 = gt(x, y)
+ when T_17 :
+ node T_18 = subw(x, y)
+ x := T_18
+ else :
+ node T_19 = subw(y, x)
+ y := T_19
+ when e :
+ x := a
+ y := b
+ z := x
+ node T_20 = eq(y, UInt<1>(0))
+ v := T_20
+
+; CHECK: circuit GCD :
+; CHECK: module GCD :
+; CHECK: input e : UInt<1>
+; CHECK: input clk : Clock
+; CHECK: input reset : UInt<1>
+; CHECK: output z : UInt<16>
+; CHECK: output v : UInt<1>
+; CHECK: input a : UInt<16>
+; CHECK: input b : UInt<16>
+; CHECK: reg x : UInt<16>, clk, reset
+; CHECK: reg y : UInt<16>, clk, reset
+; CHECK: node T_17 = gt(x, y)
+; CHECK: when T_17 :
+; CHECK: node T_18 = subw(x, y)
+; CHECK: x := T_18
+; CHECK: else :
+; CHECK: node T_19 = subw(y, x)
+; CHECK: y := T_19
+; CHECK: when e :
+; CHECK: x := a
+; CHECK: y := b
+; CHECK: z := x
+; CHECK: node T_20 = eq(y, UInt<1>("h0"))
+; CHECK: v := T_20
+
diff --git a/utils/bin/firrtl-scala b/utils/bin/firrtl-scala
new file mode 100755
index 00000000..4d208178
--- /dev/null
+++ b/utils/bin/firrtl-scala
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+# 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}"
+eval $cmd
+