aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
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?
}