aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.sbt4
-rw-r--r--src/main/antlr4/FIRRTL.g436
-rw-r--r--src/main/scala/firrtl/Parser.scala11
-rw-r--r--src/main/scala/firrtl/PrimOps.scala1
-rw-r--r--src/main/scala/firrtl/Visitor.scala10
5 files changed, 55 insertions, 7 deletions
diff --git a/build.sbt b/build.sbt
index 6b2dee54..ee00f0f9 100644
--- a/build.sbt
+++ b/build.sbt
@@ -14,6 +14,10 @@ libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.1.0"
libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.1.2"
+libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.2.6" % "test"
+
+libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.12.5" % "test"
+
// Assembly
assemblyJarName in assembly := "firrtl.jar"
diff --git a/src/main/antlr4/FIRRTL.g4 b/src/main/antlr4/FIRRTL.g4
index 2faef4e0..e0e10d45 100644
--- a/src/main/antlr4/FIRRTL.g4
+++ b/src/main/antlr4/FIRRTL.g4
@@ -93,12 +93,42 @@ id
| keyword
;
-// TODO add all keywords
keyword
- : dir
- | 'inst'
+ : 'circuit'
+ | 'module'
+ | 'input'
+ | 'output'
+ | 'UInt'
+ | 'SInt'
+ | 'UBits'
+ | 'SBits'
+ | 'Clock'
+ | 'wire'
+ | 'reg'
| 'mem'
| 'reset'
+ | 'data-type'
+ | 'depth'
+ | 'read-latency'
+ | 'write-latency'
+ | 'read-under-write'
+ | 'reader'
+ | 'writer'
+ | 'readwriter'
+ | 'inst'
+ | 'node'
+ | 'is'
+ | 'invalid'
+ | 'when'
+ | 'else'
+ | 'stop'
+ | 'printf'
+ | 'skip'
+ | 'old'
+ | 'new'
+ | 'undefined'
+ | 'mux'
+ | 'validif'
;
// Parentheses are added as part of name because semantics require no space between primop and open parentheses
diff --git a/src/main/scala/firrtl/Parser.scala b/src/main/scala/firrtl/Parser.scala
index 98864e92..41426357 100644
--- a/src/main/scala/firrtl/Parser.scala
+++ b/src/main/scala/firrtl/Parser.scala
@@ -3,13 +3,18 @@ package firrtl
import org.antlr.v4.runtime._;
import org.antlr.v4.runtime.atn._;
import org.antlr.v4.runtime.tree._;
+import com.typesafe.scalalogging.LazyLogging
import java.io.FileInputStream
import scala.collection.JavaConverters._
import scala.io.Source
import Utils._
import antlr._
-object Parser
+class ParserException(message: String) extends Exception(message)
+case class ParameterNotSpecifiedException(message: String) extends ParserException(message)
+case class ParameterRedefinedException(message: String) extends ParserException(message)
+
+object Parser extends LazyLogging
{
/** Takes Iterator over lines of FIRRTL, returns AST (root node is Circuit)
*
@@ -17,6 +22,7 @@ object Parser
*/
def parse(filename: String, lines: Iterator[String]): Circuit = {
val fixedInput = Translator.addBrackets(lines)
+ //logger.debug("Preprocessed Input:\n" + fixedInput.result)
val antlrStream = new ANTLRInputStream(fixedInput.result)
val lexer = new FIRRTLLexer(antlrStream)
val tokens = new CommonTokenStream(lexer)
@@ -28,6 +34,9 @@ object Parser
// Concrete Syntax Tree
val cst = parser.circuit
+ val numSyntaxErrors = parser.getNumberOfSyntaxErrors
+ if (numSyntaxErrors > 0) throw new ParserException(s"${numSyntaxErrors} syntax error(s) detected")
+
val visitor = new Visitor(filename)
//val ast = visitor.visitCircuit(cst) match {
val ast = visitor.visit(cst) match {
diff --git a/src/main/scala/firrtl/PrimOps.scala b/src/main/scala/firrtl/PrimOps.scala
index 56d1053c..790fa538 100644
--- a/src/main/scala/firrtl/PrimOps.scala
+++ b/src/main/scala/firrtl/PrimOps.scala
@@ -42,6 +42,7 @@ object PrimOps extends LazyLogging {
HEAD_OP -> "head",
TAIL_OP -> "tail"
)
+ lazy val listing: Seq[String] = PrimOps.mapPrimOp2String.map { case (k,v) => v } toSeq
private val mapString2PrimOp = mapPrimOp2String.map(_.swap)
def fromString(op: String): PrimOp = mapString2PrimOp(op)
diff --git a/src/main/scala/firrtl/Visitor.scala b/src/main/scala/firrtl/Visitor.scala
index 3f5b64e6..2ba12b92 100644
--- a/src/main/scala/firrtl/Visitor.scala
+++ b/src/main/scala/firrtl/Visitor.scala
@@ -113,7 +113,7 @@ class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
val seq = map getOrElse (field, Seq())
map + (field -> (seq :+ children(2)))
} else { // data-type, depth, read-latency, write-latency, read-under-write
- if (map.contains(field)) throw new Exception(s"Redefinition of mem field ${field}")
+ if (map.contains(field)) throw new ParameterRedefinedException(s"Redefinition of ${field}")
else map + (field -> Seq(children(2)))
}
parseChildren(children.drop(3), newMap) // We consume tokens in groups of three (eg. 'depth' '=>' 5)
@@ -124,8 +124,12 @@ class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
// Build map of different Memory fields to their values
val map = try {
parseChildren(ctx.children.drop(4), Map[String, Seq[ParseTree]]()) // First 4 tokens are 'mem' id ':' '{', skip to fields
- } catch {
- case e: Exception => throw new Exception(s"[${info}] ${e.getMessage}") // attach line number
+ } catch { // attach line number
+ case e: ParameterRedefinedException => throw new ParameterRedefinedException(s"[${info}] ${e.message}")
+ }
+ // Check for required fields
+ Seq("data-type", "depth", "read-latency", "write-latency") foreach { field =>
+ map.getOrElse(field, throw new ParameterNotSpecifiedException(s"[${info}] Required mem field ${field} not found"))
}
// Each memory field value has been left as ParseTree type, need to convert
// TODO Improve? Remove dynamic typecast of data-type