aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorjackkoenig2016-01-27 19:39:31 -0800
committerjackkoenig2016-01-27 19:39:31 -0800
commitb7dcc8ccbb1459a604353a8137081a9b156d276e (patch)
treeb830b173e56b12fcb63c96a66e084d979ed0dbfd /src/main
parent6c2b6ea5e4ec00aae0963402e2565e91e95098ac (diff)
WIP Moving Scala FIRRTL to match spec 0.2.0. Not everything is implemented (notably stop, printf, mux, validif, ubits, sbits, readers, writers, and readwriters are incomplete)
Diffstat (limited to 'src/main')
-rw-r--r--src/main/antlr4/FIRRTL.g4167
-rw-r--r--src/main/scala/firrtl/DebugUtils.scala3
-rw-r--r--src/main/scala/firrtl/IR.scala149
-rw-r--r--src/main/scala/firrtl/Passes.scala88
-rw-r--r--src/main/scala/firrtl/PrimOps.scala116
-rw-r--r--src/main/scala/firrtl/Primops.scala119
-rw-r--r--src/main/scala/firrtl/Utils.scala150
-rw-r--r--src/main/scala/firrtl/Visitor.scala137
8 files changed, 456 insertions, 473 deletions
diff --git a/src/main/antlr4/FIRRTL.g4 b/src/main/antlr4/FIRRTL.g4
index dd270d17..8394d3f2 100644
--- a/src/main/antlr4/FIRRTL.g4
+++ b/src/main/antlr4/FIRRTL.g4
@@ -6,11 +6,7 @@ grammar FIRRTL;
/* 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?
@@ -19,80 +15,76 @@ circuit
;
module
- : 'module' id ':' '{' port* blockStmt '}'
+ : 'module' id ':' '{' port* block '}'
;
port
- : portKind id ':' type
+ : dir id ':' type
;
-portKind
+dir
: 'input'
| 'output'
;
type
- : 'UInt' ('<' width '>')?
- | 'SInt' ('<' width '>')?
+ : 'UInt' ('<' IntLit '>')?
+ | 'SInt' ('<' IntLit '>')?
| 'Clock'
| '{' field* '}' // Bundle
| type '[' IntLit ']' // Vector
;
field
- : orientation id ':' type
- ;
-
-orientation
- : 'flip'
- | // Nothing
+ : 'flip'? id ':' type
;
-width
- : IntLit
- | '?'
- ;
-
-// Much faster than replacing blockStmt with stmt+
-blockStmt
+// Much faster than replacing block with stmt+
+block
: (stmt)*
;
stmt
: 'wire' id ':' type
- | 'reg' id ':' type exp exp
- | 'smem' id ':' type exp
- | 'cmem' id ':' type exp
- | 'inst' id (':' | 'of') id // FIXME which should it be? ':' or 'of'
+ | 'reg' id ':' type exp (exp exp)?
+ | 'mem' id ':' '{' 'data-type' '=>' type
+ 'depth' '=>' IntLit
+ 'read-latency' '=>' IntLit
+ 'write-latency' '=>' IntLit
+ 'read-under-write' '=>' ruw
+ ('reader' '=>' id)*
+ ('writer' '=>' id)*
+ ('readwriter' '=>' id)*
+ '}'
+ | 'inst' id 'of' id
| 'node' id '=' exp
- | 'poison' id ':' type // Poison, FIXME
- | dir 'accessor' id '=' exp '[' exp ']' exp? // FIXME what is this extra exp?
- | exp ':=' exp // Connect
- | 'onreset' exp ':=' exp
- | exp '<>' exp // Bulk Connect
- | exp '[' IntLit 'through' IntLit ']' ':=' exp // SubWordConnect
- | 'when' exp ':' '{' blockStmt '}' ( 'else' ':' '{' blockStmt '}' )?
- | 'assert' exp
+ | exp '<=' exp
+ | exp '<-' exp
+ | exp 'is' 'invalid'
+ | 'when' exp ':' '{' block '}' ( 'else' ':' '{' block '}' )?
+ | 'stop(' exp exp IntLit ')'
+ | 'printf(' exp exp StringLit (exp)* ')'
| 'skip'
;
-// Accessor Direction
-dir
- : 'infer'
- | 'read'
- | 'write'
- | 'rdwr'
+ruw
+ : 'old'
+ | 'new'
+ | 'undefined'
;
-// TODO implement
-// What is exp?
exp
- : 'UInt' ('<' width '>')? '(' (IntLit) ')' // FIXME what does "ints" mean?
- | 'SInt' ('<' width '>')? '(' (IntLit) ')' // FIXME same
+ : 'UInt' ('<' IntLit '>')? '(' IntLit ')'
+ | 'SInt' ('<' IntLit '>')? '(' IntLit ')'
+ | 'UBits' ('<' IntLit '>')? '(' StringLit ')'
+ | 'SBits' ('<' IntLit '>')? '(' StringLit ')'
| id // Ref
- | exp '.' id // FIXME Does this work for no space?
+ | exp '.' id
| exp '[' IntLit ']'
- | primop '(' exp* IntLit* ')' // FIXME Need a big check here
+ | exp '[' exp ']'
+ | 'mux(' exp exp exp ')'
+ | 'validif(' exp exp ')'
+ | primop exp* IntLit* ')'
;
id
@@ -100,57 +92,58 @@ id
| keyword
;
-// FIXME need to make sure this is exhaustive including all FIRRTL keywords that are legal IDs
+// TODO add all keywords
keyword
- : primop
- | dir
+ : dir
| 'inst'
;
+// Parentheses are added as part of name because semantics require no space between primop and open parentheses
+// (And ANTLR either ignores whitespace or considers it everywhere)
primop
- : 'add'
- | 'sub'
- | 'addw'
- | 'subw'
- | 'mul'
- | 'div'
- | 'mod'
- | 'quo'
- | 'rem'
- | 'lt'
- | 'leq'
- | 'gt'
- | 'geq'
- | 'eq'
- | 'neq'
- | 'eqv'
- | 'neqv'
- | 'mux'
- | 'pad'
- | 'asUInt'
- | 'asSInt'
- | 'shl'
- | 'shr'
- | 'dshl'
- | 'dshr'
- | 'cvt'
- | 'neg'
- | 'not'
- | 'and'
- | 'or'
- | 'xor'
- | 'andr'
- | 'orr'
- | 'xorr'
- | 'cat'
- | 'bit'
- | 'bits'
+ : 'add('
+ | 'sub('
+ | 'mul('
+ | 'div('
+ | 'rem('
+ | 'lt('
+ | 'leq('
+ | 'gt('
+ | 'geq('
+ | 'eq('
+ | 'neq('
+ | 'pad('
+ | 'asUInt('
+ | 'asSInt('
+ | 'asClock('
+ | 'shl('
+ | 'shr('
+ | 'dshl('
+ | 'dshr('
+ | 'cvt('
+ | 'neg('
+ | 'not('
+ | 'and('
+ | 'or('
+ | 'xor('
+ | 'andr('
+ | 'orr('
+ | 'xorr('
+ | 'cat('
+ | 'bits('
+ | 'head('
+ | 'tail('
;
/*------------------------------------------------------------------
* LEXER RULES
*------------------------------------------------------------------*/
+StringLit
+ : '"' .*? '"'
+ ;
+
+
Id
: IdNondigit
( IdNondigit
@@ -199,3 +192,5 @@ Newline
: ( '\r'? '\n' )+
-> skip
;
+
+
diff --git a/src/main/scala/firrtl/DebugUtils.scala b/src/main/scala/firrtl/DebugUtils.scala
index 5d58fba6..8151e2a6 100644
--- a/src/main/scala/firrtl/DebugUtils.scala
+++ b/src/main/scala/firrtl/DebugUtils.scala
@@ -8,6 +8,7 @@ private object DebugUtils {
implicit class DebugASTUtils(ast: AST) {
// Is this actually any use?
+ /*
def preOrderTraversal(f: AST => Unit): Unit = {
f(ast)
ast match {
@@ -66,6 +67,6 @@ private object DebugUtils {
//case _ => throw new Exception(s"Unsupported FIRRTL node ${ast.getClass.getSimpleName}!")
case _ =>
}
- }
+ } */
}
}
diff --git a/src/main/scala/firrtl/IR.scala b/src/main/scala/firrtl/IR.scala
index e7356abc..858f48cf 100644
--- a/src/main/scala/firrtl/IR.scala
+++ b/src/main/scala/firrtl/IR.scala
@@ -1,9 +1,4 @@
-/* TODO
- * - Should Info be a FIRRTL node?
- *
- */
-
package firrtl
import scala.collection.Seq
@@ -21,102 +16,90 @@ case class FileInfo(file: String, line: Int, column: Int) extends Info {
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 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: 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 Index(exp: Exp, value: BigInt, tpe: Type) extends Exp //SubIndex, add SubAccess
-case class DoPrimop(op: Primop, args: Seq[Exp], consts: Seq[BigInt], tpe: Type) extends Exp
-
-// THIS GOES BYE BYE
-trait AccessorDir extends AST
-case object Infer extends AccessorDir
-case object Read extends AccessorDir
-case object Write extends AccessorDir
-case object RdWr extends AccessorDir
+trait PrimOp extends AST
+case object AddOp extends PrimOp
+case object SubOp extends PrimOp
+case object MulOp extends PrimOp
+case object DivOp extends PrimOp
+case object RemOp extends PrimOp
+case object LessOp extends PrimOp
+case object LessEqOp extends PrimOp
+case object GreaterOp extends PrimOp
+case object GreaterEqOp extends PrimOp
+case object EqualOp extends PrimOp
+case object NEqualOp extends PrimOp
+case object PadOp extends PrimOp
+case object AsUIntOp extends PrimOp
+case object AsSIntOp extends PrimOp
+case object AsClockOp extends PrimOp
+case object ShiftLeftOp extends PrimOp
+case object ShiftRightOp extends PrimOp
+case object DynShiftLeftOp extends PrimOp
+case object DynShiftRightOp extends PrimOp
+case object ConvertOp extends PrimOp
+case object NegOp extends PrimOp
+case object BitNotOp extends PrimOp
+case object BitAndOp extends PrimOp
+case object BitOrOp extends PrimOp
+case object BitXorOp extends PrimOp
+case object BitAndReduceOp extends PrimOp
+case object BitOrReduceOp extends PrimOp
+case object BitXorReduceOp extends PrimOp
+case object ConcatOp extends PrimOp
+case object BitsSelectOp extends PrimOp
+case object HeadOp extends PrimOp
+case object TailOp extends PrimOp
+
+trait Expression extends AST
+case class Ref(name: String, tpe: Type) extends Expression
+case class SubField(exp: Expression, name: String, tpe: Type) extends Expression
+case class SubIndex(exp: Expression, value: BigInt, tpe: Type) extends Expression
+case class SubAccess(exp: Expression, index: Expression, tpe: Type) extends Expression
+case class Mux(cond: Expression, tval: Expression, fval: Expression, tpe: Type) extends Expression
+case class ValidIf(cond: Expression, value: Expression, tpe: Type) extends Expression
+case class UIntValue(value: BigInt, width: Width) extends Expression
+case class SIntValue(value: BigInt, width: Width) extends Expression
+case class DoPrim(op: PrimOp, args: Seq[Expression], consts: Seq[BigInt], tpe: Type) extends Expression
trait Stmt extends AST
case class DefWire(info: Info, name: String, tpe: Type) extends Stmt
-case class DefReg(info: Info, name: String, tpe: Type, clock: Exp, reset: Exp) extends Stmt //Added init value
-case class DefMemory(info: Info, name: String, seq: Boolean, tpe: Type, clock: Exp) extends Stmt //very different
-case class DefInst(info: Info, name: String, module: Exp) extends Stmt
-case class DefNode(info: Info, name: String, value: Exp) extends Stmt
-case class DefPoison(info: Info, name: String, tpe: Type) extends Stmt
-case class DefAccessor(info: Info, name: String, dir: AccessorDir, source: Exp, index: Exp) extends Stmt //BYE BYE
-case class OnReset(info: Info, lhs: Exp, rhs: Exp) extends Stmt //BYE BYE
-case class Connect(info: Info, lhs: Exp, rhs: Exp) extends Stmt
-case class BulkConnect(info: Info, lhs: Exp, rhs: Exp) extends Stmt
-case class When(info: Info, pred: Exp, conseq: Stmt, alt: Stmt) extends Stmt
-case class Assert(info: Info, pred: Exp) extends Stmt //Now Stop, with clk and enable and int, add Print
-case class Block(stmts: Seq[Stmt]) extends Stmt
-case object EmptyStmt extends Stmt //Now Empty
+case class DefRegister(info: Info, name: String, tpe: Type, clock: Expression, reset: Expression, init: Expression) extends Stmt
+case class DefInstance(info: Info, name: String, module: String) extends Stmt
+case class DefMemory(info: Info, name: String, dataType: Type, depth: Int, writeLatency: Int,
+ readLatency: Int, readers: Seq[String], writers: Seq[String], readwriters: Seq[String]) extends Stmt
+case class DefNode(info: Info, name: String, value: Expression) extends Stmt
+case class Conditionally(info: Info, pred: Expression, conseq: Stmt, alt: Stmt) extends Stmt
+case class Begin(stmts: Seq[Stmt]) extends Stmt
+case class BulkConnect(info: Info, loc: Expression, exp: Expression) extends Stmt
+case class Connect(info: Info, loc: Expression, exp: Expression) extends Stmt
+case class IsInvalid(info: Info, exp: Expression) extends Stmt
+case class Stop(info: Info, ret: Int, clk: Expression, en: Expression) extends Stmt
+case class Print(info: Info, string: String, args: Seq[Expression], clk: Expression, en: Expression) extends Stmt
+case object Empty extends Stmt
trait Width extends AST
case class IntWidth(width: BigInt) extends Width
case object UnknownWidth extends Width
-trait FieldDir extends AST
-case object Default extends FieldDir
-case object Reverse extends FieldDir
+trait Flip extends AST
+case object Default extends Flip
+case object Reverse extends Flip
-case class Field(name: String, dir: FieldDir, tpe: Type) extends AST
+case class Field(name: String, flip: Flip, tpe: Type) extends AST
trait Type extends AST
case class UIntType(width: Width) extends Type
case class SIntType(width: Width) extends Type
-case object ClockType extends Type
case class BundleType(fields: Seq[Field]) extends Type
case class VectorType(tpe: Type, size: BigInt) extends Type
+case object ClockType extends Type
case object UnknownType extends Type
-trait PortDir extends AST
-case object Input extends PortDir
-case object Output extends PortDir
+trait Direction extends AST
+case object Input extends Direction
+case object Output extends Direction
-case class Port(info: Info, name: String, dir: PortDir, tpe: Type) extends AST
+case class Port(info: Info, name: String, dir: Direction, tpe: Type) extends AST
case class Module(info: Info, name: String, ports: Seq[Port], stmt: Stmt) extends AST
diff --git a/src/main/scala/firrtl/Passes.scala b/src/main/scala/firrtl/Passes.scala
index 9469b6cb..b73ee727 100644
--- a/src/main/scala/firrtl/Passes.scala
+++ b/src/main/scala/firrtl/Passes.scala
@@ -5,7 +5,7 @@ import com.typesafe.scalalogging.LazyLogging
import Utils._
import DebugUtils._
-import Primops._
+import PrimOps._
object Passes extends LazyLogging {
@@ -56,22 +56,23 @@ object Passes extends LazyLogging {
}
private def getVectorSubtype(t: Type): Type = t.getType // Added for clarity
// TODO Add genders
- private def inferExpTypes(typeMap: TypeMap)(exp: Exp): Exp = {
+ private def inferExpTypes(typeMap: TypeMap)(exp: Expression): Expression = {
logger.debug(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
+ case e: SubField => SubField(e.exp, e.name, getBundleSubtype(e.exp.getType, e.name))
+ case e: SubIndex => SubIndex(e.exp, e.value, getVectorSubtype(e.exp.getType))
+ case e: SubAccess => SubAccess(e.exp, e.index, getVectorSubtype(e.exp.getType))
+ case e: DoPrim => lowerAndTypePrimOp(e)
+ case e: Expression => e
}
}
private def inferTypes(typeMap: TypeMap, stmt: Stmt): (Stmt, TypeMap) = {
logger.debug(s"inferTypes called on ${stmt.getClass.getSimpleName} ")
stmt.map(inferExpTypes(typeMap)) match {
- case b: Block => {
+ case b: Begin => {
var tMap = typeMap
// TODO FIXME is map correctly called in sequential order
val body = b.stmts.map { s =>
@@ -79,19 +80,17 @@ object Passes extends LazyLogging {
tMap = ret._2
ret._1
}
- (Block(body), tMap)
+ (Begin(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: DefRegister => (s, typeMap ++ Map(s.name -> s.tpe))
+ case s: DefMemory => (s, typeMap ++ Map(s.name -> s.dataType))
+ case s: DefInstance => (s, typeMap ++ Map(s.name -> typeMap(s.module)))
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
+ case s: Conditionally => { // 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)
+ (Conditionally(s.info, s.pred, conseq, alt), cMap ++ aMap)
}
case s: Stmt => (s, typeMap)
}
@@ -116,19 +115,25 @@ object Passes extends LazyLogging {
def renameall(s : String)(implicit map : Map[String,String]) : String =
map getOrElse (s, s)
- def renameall(e : Exp)(implicit map : Map[String,String]) : Exp = {
+ def renameall(e : Expression)(implicit map : Map[String,String]) : Expression = {
logger.debug(s"renameall called on expression ${e.toString}")
e match {
case p : Ref =>
Ref(renameall(p.name), p.tpe)
- case p : Subfield =>
- Subfield(renameall(p.exp), renameall(p.name), p.tpe)
- case p : Index =>
- Index(renameall(p.exp), p.value, p.tpe)
- case p : DoPrimop =>
+ case p : SubField =>
+ SubField(renameall(p.exp), renameall(p.name), p.tpe)
+ case p : SubIndex =>
+ SubIndex(renameall(p.exp), p.value, p.tpe)
+ case p : SubAccess =>
+ SubAccess(renameall(p.exp), renameall(p.index), p.tpe)
+ case p : Mux =>
+ Mux(renameall(p.cond), renameall(p.tval), renameall(p.fval), p.tpe)
+ case p : ValidIf =>
+ ValidIf(renameall(p.cond), renameall(p.value), p.tpe)
+ case p : DoPrim =>
println( p.args.map(x => renameall(x)) )
- DoPrimop(p.op, p.args.map(x => renameall(x)), p.consts, p.tpe)
- case p : Exp => p
+ DoPrim(p.op, p.args.map(renameall), p.consts, p.tpe)
+ case p : Expression => p
}
}
@@ -138,30 +143,29 @@ object Passes extends LazyLogging {
s match {
case p : DefWire =>
DefWire(p.info, renameall(p.name), p.tpe)
- case p: DefReg =>
- DefReg(p.info, renameall(p.name), p.tpe, p.clock, p.reset)
+ case p: DefRegister =>
+ DefRegister(p.info, renameall(p.name), p.tpe, p.clock, p.reset, p.init)
case p : DefMemory =>
- DefMemory(p.info, renameall(p.name), p.seq, p.tpe, p.clock)
- case p : DefInst =>
- DefInst(p.info, renameall(p.name), renameall(p.module))
+ DefMemory(p.info, renameall(p.name), p.dataType, p.depth, p.writeLatency, p.readLatency,
+ p.readers, p.writers, p.readwriters)
+ case p : DefInstance =>
+ DefInstance(p.info, renameall(p.name), renameall(p.module))
case p : DefNode =>
DefNode(p.info, renameall(p.name), renameall(p.value))
- case p : DefPoison =>
- DefPoison(p.info, renameall(p.name), p.tpe)
- case p : DefAccessor =>
- DefAccessor(p.info, renameall(p.name), p.dir, renameall(p.source), renameall(p.index))
- case p : OnReset =>
- OnReset(p.info, renameall(p.lhs), renameall(p.rhs))
case p : Connect =>
- Connect(p.info, renameall(p.lhs), renameall(p.rhs))
+ Connect(p.info, renameall(p.loc), renameall(p.exp))
case p : BulkConnect =>
- BulkConnect(p.info, renameall(p.lhs), renameall(p.rhs))
- case p : When =>
- When(p.info, renameall(p.pred), renameall(p.conseq), renameall(p.alt))
- case p : Assert =>
- Assert(p.info, renameall(p.pred))
- case p : Block =>
- Block(p.stmts.map(renameall))
+ BulkConnect(p.info, renameall(p.loc), renameall(p.exp))
+ case p : IsInvalid =>
+ IsInvalid(p.info, renameall(p.exp))
+ case p : Stop =>
+ Stop(p.info, p.ret, renameall(p.clk), renameall(p.en))
+ case p : Print =>
+ Print(p.info, p.string, p.args.map(renameall), renameall(p.clk), renameall(p.en))
+ case p : Conditionally =>
+ Conditionally(p.info, renameall(p.pred), renameall(p.conseq), renameall(p.alt))
+ case p : Begin =>
+ Begin(p.stmts.map(renameall))
case p : Stmt => p
}
}
diff --git a/src/main/scala/firrtl/PrimOps.scala b/src/main/scala/firrtl/PrimOps.scala
new file mode 100644
index 00000000..0da0e01e
--- /dev/null
+++ b/src/main/scala/firrtl/PrimOps.scala
@@ -0,0 +1,116 @@
+
+package firrtl
+
+import com.typesafe.scalalogging.LazyLogging
+
+import Utils._
+import DebugUtils._
+
+object PrimOps extends LazyLogging {
+
+ private val mapPrimOp2String = Map[PrimOp, String](
+ AddOp -> "add",
+ SubOp -> "sub",
+ MulOp -> "mul",
+ DivOp -> "div",
+ RemOp -> "rem",
+ LessOp -> "lt",
+ LessEqOp -> "leq",
+ GreaterOp -> "gt",
+ GreaterEqOp -> "geq",
+ EqualOp -> "eq",
+ NEqualOp -> "neq",
+ PadOp -> "pad",
+ AsUIntOp -> "asUInt",
+ AsSIntOp -> "asSInt",
+ AsClockOp -> "asClock",
+ ShiftLeftOp -> "shl",
+ ShiftRightOp -> "shr",
+ DynShiftLeftOp -> "dshl",
+ DynShiftRightOp -> "dshr",
+ ConvertOp -> "cvt",
+ NegOp -> "neg",
+ BitNotOp -> "not",
+ BitAndOp -> "and",
+ BitOrOp -> "or",
+ BitXorOp -> "xor",
+ BitAndReduceOp -> "andr",
+ BitOrReduceOp -> "orr",
+ BitXorReduceOp -> "xorr",
+ ConcatOp -> "cat",
+ BitsSelectOp -> "bits",
+ HeadOp -> "head",
+ TailOp -> "tail"
+ )
+ 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: DoPrim): DoPrim = {
+ def uAnd(op1: Expression, op2: Expression): 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: Expression): 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}")
+ // TODO fix this
+ val tpe = UIntType(UnknownWidth)
+ //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 _ => ???
+ //}
+ DoPrim(e.op, e.args, e.consts, tpe)
+ }
+
+}
diff --git a/src/main/scala/firrtl/Primops.scala b/src/main/scala/firrtl/Primops.scala
deleted file mode 100644
index 59a6c1ff..00000000
--- a/src/main/scala/firrtl/Primops.scala
+++ /dev/null
@@ -1,119 +0,0 @@
-
-package firrtl
-
-import com.typesafe.scalalogging.LazyLogging
-
-import Utils._
-import DebugUtils._
-
-object Primops extends LazyLogging {
-
- 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): 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/Utils.scala b/src/main/scala/firrtl/Utils.scala
index fc2efba8..e0452cfa 100644
--- a/src/main/scala/firrtl/Utils.scala
+++ b/src/main/scala/firrtl/Utils.scala
@@ -13,7 +13,7 @@ package firrtl
import scala.collection.mutable.StringBuilder
import java.io.PrintWriter
-import Primops._
+import PrimOps._
//import scala.reflect.runtime.universe._
object Utils {
@@ -44,7 +44,7 @@ object Utils {
implicit class ASTUtils(ast: AST) {
def getType(): Type =
ast match {
- case e: Exp => e.getType
+ case e: Expression => e.getType
case s: Stmt => s.getType
//case f: Field => f.getType
case t: Type => t.getType
@@ -53,30 +53,36 @@ object Utils {
}
}
- implicit class PrimopUtils(op: Primop) {
+ implicit class PrimOpUtils(op: PrimOp) {
def serialize(implicit flags: FlagMap = FlagMap): String = op.getString
}
- implicit class ExpUtils(exp: Exp) {
+ implicit class ExpUtils(exp: Expression) {
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: Index => s"${s.exp.serialize}[${s.value}]"
- case p: DoPrimop =>
+ case s: SubField => s"${s.exp.serialize}.${s.name}"
+ case s: SubIndex => s"${s.exp.serialize}[${s.value}]"
+ case s: SubAccess => s"${s.exp.serialize}[${s.index.serialize}]"
+ case m: Mux => s"mux(${m.cond.serialize}, ${m.tval.serialize}, ${m.fval.serialize})"
+ case v: ValidIf => s"validif(${v.cond.serialize}, ${v.value.serialize})"
+ case p: DoPrim =>
s"${p.op.serialize}(" + (p.args.map(_.serialize) ++ p.consts.map(_.toString)).mkString(", ") + ")"
}
ret + debug(exp)
}
- def map(f: Exp => Exp): Exp =
+ def map(f: Expression => Expression): Expression =
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
+ case s: SubField => SubField(f(s.exp), s.name, s.tpe)
+ case s: SubIndex => SubIndex(f(s.exp), s.value, s.tpe)
+ case s: SubAccess => SubAccess(f(s.exp), f(s.index), s.tpe)
+ case m: Mux => Mux(f(m.cond), f(m.tval), f(m.fval), m.tpe)
+ case v: ValidIf => ValidIf(f(v.cond), f(v.value), v.tpe)
+ case p: DoPrim => DoPrim(p.op, p.args.map(f), p.consts, p.tpe)
+ case e: Expression => e
}
def getType(): Type = {
@@ -84,23 +90,15 @@ object Utils {
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
+ case s: SubField => s.tpe
+ case s: SubIndex => s.tpe
+ case s: SubAccess => s.tpe
+ case p: DoPrim => p.tpe
+ case m: Mux => m.tpe
+ case v: ValidIf => v.tpe
}
}
}
-
- // AccessorDir
- implicit class AccessorDirUtils(dir: AccessorDir) {
- def serialize(implicit flags: FlagMap = FlagMap): String =
- dir match {
- case Infer => "infer"
- case Read => "read"
- case Write => "write"
- case RdWr => "rdwr"
- }
- }
// Some Scala implicit magic to solve type erasure on Stmt map function overloading
private trait StmtMagnet {
@@ -110,24 +108,22 @@ object Utils {
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 w: Conditionally => Conditionally(w.info, w.pred, f(w.conseq), f(w.alt))
+ case b: Begin => Begin(b.stmts.map(f))
case s: Stmt => s
}
}
- implicit def forExp(f: Exp => Exp) = new StmtMagnet {
+ implicit def forExp(f: Expression => Expression) = 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))
+ stmt match {
+ case r: DefRegister => DefRegister(r.info, r.name, r.tpe, f(r.clock), f(r.reset), f(r.init))
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 c: Connect => Connect(c.info, f(c.loc), f(c.exp))
+ case b: BulkConnect => BulkConnect(b.info, f(b.loc), f(b.exp))
+ case w: Conditionally => Conditionally(w.info, f(w.pred), w.conseq, w.alt)
+ case i: IsInvalid => IsInvalid(i.info, f(i.exp))
+ case s: Stop => Stop(s.info, s.ret, f(s.clk), f(s.en))
+ case p: Print => Print(p.info, p.string, p.args.map(f), f(p.clk), f(p.en))
case s: Stmt => s
}
}
@@ -138,33 +134,40 @@ object Utils {
{
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") +
- s" ${m.name} : ${m.tpe.serialize}, ${m.clock.serialize}"
- case i: DefInst => s"inst ${i.name} of ${i.module.serialize}"
+ case r: DefRegister =>
+ s"reg ${r.name} : ${r.tpe.serialize}, ${r.clock.serialize}, ${r.reset.serialize}, ${r.init.serialize}"
+ case i: DefInstance => s"inst ${i.name} of ${i.module}"
+ case m: DefMemory => s"mem ${m.name} : " + newline + withIndent {
+ s"data-type => ${m.dataType}" + newline +
+ s"depth => ${m.depth}" + newline +
+ s"read-latency => ${m.readLatency}" + newline +
+ s"write-latency => ${m.writeLatency}" + newline +
+ m.readers.map(r => s"reader => ${r}" + newline) +
+ m.writers.map(w => s"writer => ${w}" + newline) +
+ m.readwriters.map(rw => s"readwriter => ${rw}" + newline) +
+ s"read-under-write => undefined" // TODO implement
+ }
case n: DefNode => s"node ${n.name} = ${n.value.serialize}"
- case p: DefPoison => s"poison ${p.name} : ${p.tpe.serialize}"
- case a: DefAccessor => s"${a.dir.serialize} accessor ${a.name} = ${a.source.serialize}[${a.index.serialize}]"
- case c: Connect => s"${c.lhs.serialize} := ${c.rhs.serialize}"
- case o: OnReset => s"onreset ${o.lhs.serialize} := ${o.rhs.serialize}"
- case b: BulkConnect => s"${b.lhs.serialize} <> ${b.rhs.serialize}"
- case w: When => {
+ case c: Connect => s"${c.loc.serialize} <= ${c.exp.serialize}"
+ case b: BulkConnect => s"${b.loc.serialize} <- ${b.exp.serialize}"
+ case w: Conditionally => {
var str = new StringBuilder(s"when ${w.pred.serialize} : ")
withIndent { str ++= w.conseq.serialize }
- if( w.alt != EmptyStmt ) {
+ if( w.alt != Empty ) {
str ++= newline + "else :"
withIndent { str ++= w.alt.serialize }
}
str.result
}
- //case b: Block => b.stmts.map(newline ++ _.serialize).mkString
- case b: Block => {
+ case b: Begin => {
val s = new StringBuilder
b.stmts.foreach { s ++= newline ++ _.serialize }
s.result + debug(b)
}
- case a: Assert => s"assert ${a.pred.serialize}"
- case EmptyStmt => "skip"
+ case i: IsInvalid => s"${i.exp} is invalid"
+ case s: Stop => s"stop(${s.clk}, ${s.en}, ${s.ret})"
+ case p: Print => s"printf(${p.clk}, ${p.en}, ${p.string}" + p.args.map(_.serialize).mkString(", ")
+ case Empty => "skip"
}
ret + debug(stmt)
}
@@ -174,10 +177,9 @@ object Utils {
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 s: DefWire => s.tpe
+ case s: DefRegister => s.tpe
+ case s: DefMemory => s.dataType
case _ => UnknownType
}
}
@@ -192,23 +194,23 @@ object Utils {
}
}
- implicit class FieldDirUtils(dir: FieldDir) {
+ implicit class FlipUtils(f: Flip) {
def serialize(implicit flags: FlagMap = FlagMap): String = {
- val s = dir match {
+ val s = f match {
case Reverse => "flip"
case Default => ""
}
- s + debug(dir)
+ s + debug(f)
}
- def flip(): FieldDir = {
- dir match {
+ def flip(): Flip = {
+ f match {
case Reverse => Default
case Default => Reverse
}
}
- def toPortDir(): PortDir = {
- dir match {
+ def toDirection(): Direction = {
+ f match {
case Default => Output
case Reverse => Input
}
@@ -217,11 +219,11 @@ object Utils {
implicit class FieldUtils(field: Field) {
def serialize(implicit flags: FlagMap = FlagMap): String =
- s"${field.dir.serialize} ${field.name} : ${field.tpe.serialize}" + debug(field)
- def flip(): Field = Field(field.name, field.dir.flip, field.tpe)
+ s"${field.flip.serialize}${field.name} : ${field.tpe.serialize}" + debug(field)
+ def flip(): Field = Field(field.name, field.flip.flip, field.tpe)
def getType(): Type = field.tpe
- def toPort(): Port = Port(NoInfo, field.name, field.dir.toPortDir, field.tpe)
+ def toPort(): Port = Port(NoInfo, field.name, field.flip.toDirection, field.tpe)
}
implicit class TypeUtils(t: Type) {
@@ -253,16 +255,16 @@ object Utils {
}
}
- implicit class PortDirUtils(p: PortDir) {
+ implicit class DirectionUtils(d: Direction) {
def serialize(implicit flags: FlagMap = FlagMap): String = {
- val s = p match {
+ val s = d match {
case Input => "input"
case Output => "output"
}
- s + debug(p)
+ s + debug(d)
}
- def toFieldDir(): FieldDir = {
- p match {
+ def toFlip(): Flip = {
+ d match {
case Input => Reverse
case Output => Default
}
@@ -273,7 +275,7 @@ object Utils {
def serialize(implicit flags: FlagMap = FlagMap): String =
s"${p.dir.serialize} ${p.name} : ${p.tpe.serialize}" + debug(p)
def getType(): Type = p.tpe
- def toField(): Field = Field(p.name, p.dir.toFieldDir, p.tpe)
+ def toField(): Field = Field(p.name, p.dir.toFlip, p.tpe)
}
implicit class ModuleUtils(m: Module) {
diff --git a/src/main/scala/firrtl/Visitor.scala b/src/main/scala/firrtl/Visitor.scala
index d5220206..a1963265 100644
--- a/src/main/scala/firrtl/Visitor.scala
+++ b/src/main/scala/firrtl/Visitor.scala
@@ -1,9 +1,7 @@
/*
- * TODO FIXME
+ * TODO
+ * - Implement UBits and SBits
* - 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
@@ -14,7 +12,7 @@ import org.antlr.v4.runtime.tree.ErrorNode
import org.antlr.v4.runtime.tree.TerminalNode
import scala.collection.JavaConversions._
import antlr._
-import Primops._
+import PrimOps._
class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
{
@@ -39,6 +37,7 @@ class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
case _ => throw new Exception("Invalid String for conversion to BigInt " + s)
}
}
+ private def string2Int(s: String): Int = string2BigInt(s).toInt
private def getInfo(ctx: ParserRuleContext): Info =
FileInfo(filename, ctx.getStart().getLine(), ctx.getStart().getCharPositionInLine())
@@ -46,12 +45,12 @@ class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
Circuit(getInfo(ctx), ctx.id.getText, ctx.module.map(visitModule))
private def visitModule[AST](ctx: FIRRTLParser.ModuleContext): Module =
- Module(getInfo(ctx), ctx.id.getText, ctx.port.map(visitPort), visitBlockStmt(ctx.blockStmt))
+ Module(getInfo(ctx), ctx.id.getText, ctx.port.map(visitPort), visitBlock(ctx.block))
private def visitPort[AST](ctx: FIRRTLParser.PortContext): Port =
- Port(getInfo(ctx), ctx.id.getText, visitPortKind(ctx.portKind), visitType(ctx.`type`))
-
- private def visitPortKind[AST](ctx: FIRRTLParser.PortKindContext): PortDir =
+ Port(getInfo(ctx), ctx.id.getText, visitDir(ctx.dir), visitType(ctx.`type`))
+
+ private def visitDir[AST](ctx: FIRRTLParser.DirContext): Direction =
ctx.getText match {
case "input" => Input
case "output" => Output
@@ -60,9 +59,9 @@ 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" => if (ctx.getChildCount > 1) UIntType( visitWidth(ctx.width) )
+ case "UInt" => if (ctx.getChildCount > 1) UIntType(IntWidth(string2BigInt(ctx.IntLit.getText)))
else UIntType( UnknownWidth )
- case "SInt" => if (ctx.getChildCount > 1) SIntType( visitWidth(ctx.width) )
+ case "SInt" => if (ctx.getChildCount > 1) SIntType(IntWidth(string2BigInt(ctx.IntLit.getText)))
else SIntType( UnknownWidth )
case "Clock" => ClockType
case "{" => BundleType(ctx.field.map(visitField))
@@ -70,90 +69,92 @@ class Visitor(val fullFilename: String) extends FIRRTLBaseVisitor[AST]
}
}
- private def visitField[AST](ctx: FIRRTLParser.FieldContext): Field =
- Field(ctx.id.getText, visitOrientation(ctx.orientation), visitType(ctx.`type`))
-
- private def visitOrientation[AST](ctx: FIRRTLParser.OrientationContext): FieldDir =
- ctx.getText match {
- case "flip" => Reverse
- case _ => Default
- }
-
- private def visitWidth[AST](ctx: FIRRTLParser.WidthContext): Width = {
- val text = ctx.getText
- text match {
- case "?" => UnknownWidth
- case _ => IntWidth(string2BigInt(text))
- }
+ private def visitField[AST](ctx: FIRRTLParser.FieldContext): Field = {
+ val flip = if(ctx.getChild(0).getText == "flip") Reverse else Default
+ Field(ctx.id.getText, flip, visitType(ctx.`type`))
}
-
- private def visitBlockStmt[AST](ctx: FIRRTLParser.BlockStmtContext): Stmt =
- Block(ctx.stmt.map(visitStmt))
+
+
+ // visitBlock
+ private def visitBlock[AST](ctx: FIRRTLParser.BlockContext): Stmt =
+ Begin(ctx.stmt.map(visitStmt))
private def visitStmt[AST](ctx: FIRRTLParser.StmtContext): Stmt = {
val info = getInfo(ctx)
ctx.getChild(0).getText match {
case "wire" => DefWire(info, ctx.id(0).getText, visitType(ctx.`type`))
- case "reg" => DefReg(info, ctx.id(0).getText, visitType(ctx.`type`),
- visitExp(ctx.exp(0)), visitExp(ctx.exp(1)))
- case "smem" => DefMemory(info, ctx.id(0).getText, true,
- visitType(ctx.`type`), visitExp(ctx.exp(0)))
- case "cmem" => DefMemory(info, ctx.id(0).getText, false,
- visitType(ctx.`type`), visitExp(ctx.exp(0)))
- case "inst" => DefInst(info, ctx.id(0).getText, Ref(ctx.id(1).getText, UnknownType))
+ case "reg" => {
+ val name = ctx.id(0).getText
+ val tpe = visitType(ctx.`type`)
+ val (reset, init) = if (ctx.getChildCount > 5) (visitExp(ctx.exp(1)), visitExp(ctx.exp(2)))
+ else (UIntValue(0, IntWidth(1)), Ref(name, tpe))
+ DefRegister(info, name, tpe, visitExp(ctx.exp(0)), reset, init)
+ }
+ case "mem" => DefMemory(info, ctx.id(0).getText, visitType(ctx.`type`), string2Int(ctx.IntLit(0).getText),
+ string2Int(ctx.IntLit(2).getText), string2Int(ctx.IntLit(1).getText),
+ Seq(), Seq(), Seq()) // TODO implement readers and writers
+ case "inst" => DefInstance(info, ctx.id(0).getText, ctx.id(1).getText)
case "node" => DefNode(info, ctx.id(0).getText, visitExp(ctx.exp(0)))
- case "poison" => DefPoison(info, ctx.id(0).getText, visitType(ctx.`type`))
- case "onreset" => OnReset(info, visitExp(ctx.exp(0)), visitExp(ctx.exp(1)))
case "when" => {
- val alt = if (ctx.blockStmt.length > 1) visitBlockStmt(ctx.blockStmt(1)) else EmptyStmt
- When(info, visitExp(ctx.exp(0)), visitBlockStmt(ctx.blockStmt(0)), alt)
+ val alt = if (ctx.block.length > 1) visitBlock(ctx.block(1)) else Empty
+ Conditionally(info, visitExp(ctx.exp(0)), visitBlock(ctx.block(0)), alt)
}
- case "assert" => Assert(info, visitExp(ctx.exp(0)))
- case "skip" => EmptyStmt
+ // TODO implement stop
+ // TODO implement printf
+ case "skip" => Empty
// If we don't match on the first child, try the next one
case _ => {
ctx.getChild(1).getText match {
- case "accessor" => DefAccessor(info, ctx.id(0).getText,
- visitDir(ctx.dir), visitExp(ctx.exp(0)), visitExp(ctx.exp(1)))
- case ":=" => Connect(info, visitExp(ctx.exp(0)), visitExp(ctx.exp(1)) )
- case "<>" => BulkConnect(info, visitExp(ctx.exp(0)), visitExp(ctx.exp(1)) )
+ case "<=" => Connect(info, visitExp(ctx.exp(0)), visitExp(ctx.exp(1)) )
+ case "<-" => BulkConnect(info, visitExp(ctx.exp(0)), visitExp(ctx.exp(1)) )
+ case "is" => IsInvalid(info, visitExp(ctx.exp(0)))
}
}
}
}
-
- private def visitDir[AST](ctx: FIRRTLParser.DirContext): AccessorDir =
- ctx.getText match {
- case "infer" => Infer
- case "read" => Read
- case "write" => Write
- case "rdwr" => RdWr // TODO remove exceptions for unmatched things
- }
+
+ // add visitRuw ?
+ //T visitRuw(FIRRTLParser.RuwContext ctx);
+ //private def visitRuw[AST](ctx: FIRRTLParser.RuwContext):
- private def visitExp[AST](ctx: FIRRTLParser.ExpContext): Exp =
+ // TODO
+ // - Add mux
+ // - Add validif
+ private def visitExp[AST](ctx: FIRRTLParser.ExpContext): Expression =
if( ctx.getChildCount == 1 )
Ref(ctx.getText, UnknownType)
else
ctx.getChild(0).getText match {
- case "UInt" => {
- val width = if (ctx.getChildCount > 4) visitWidth(ctx.width) else UnknownWidth
- UIntValue(string2BigInt(ctx.IntLit(0).getText), width)
+ case "UInt" => { // This could be better
+ val (width, value) =
+ if (ctx.getChildCount > 4)
+ (IntWidth(string2BigInt(ctx.IntLit(0).getText)), string2BigInt(ctx.IntLit(1).getText))
+ else (UnknownWidth, string2BigInt(ctx.IntLit(0).getText))
+ UIntValue(value, 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)
+ val (width, value) =
+ if (ctx.getChildCount > 4)
+ (IntWidth(string2BigInt(ctx.IntLit(0).getText)), string2BigInt(ctx.IntLit(1).getText))
+ else (UnknownWidth, string2BigInt(ctx.IntLit(0).getText))
+ SIntValue(value, width)
}
case _ =>
ctx.getChild(1).getText match {
- case "." => new Subfield(visitExp(ctx.exp(0)), ctx.id.getText, UnknownType)
- 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)), UnknownType)
+ case "." => new SubField(visitExp(ctx.exp(0)), ctx.id.getText, UnknownType)
+ case "[" => if (ctx.IntLit != null)
+ new SubIndex(visitExp(ctx.exp(0)), string2BigInt(ctx.IntLit(0).getText), UnknownType)
+ else new SubAccess(visitExp(ctx.exp(0)), visitExp(ctx.exp(1)), UnknownType)
+ // Assume primop
+ case _ => DoPrim(visitPrimop(ctx.primop), ctx.exp.map(visitExp),
+ ctx.IntLit.map(x => string2BigInt(x.getText)), UnknownType)
}
}
-
- private def visitPrimop[AST](ctx: FIRRTLParser.PrimopContext): Primop = fromString(ctx.getText)
+
+ // stripSuffix("(") is included because in ANTLR concrete syntax we have to include open parentheses,
+ // see grammar file for more details
+ private def visitPrimop[AST](ctx: FIRRTLParser.PrimopContext): PrimOp = fromString(ctx.getText.stripSuffix("("))
+
+ // visit Id and Keyword?
}