diff options
| author | jackkoenig | 2016-01-27 19:39:31 -0800 |
|---|---|---|
| committer | jackkoenig | 2016-01-27 19:39:31 -0800 |
| commit | b7dcc8ccbb1459a604353a8137081a9b156d276e (patch) | |
| tree | b830b173e56b12fcb63c96a66e084d979ed0dbfd /src/main | |
| parent | 6c2b6ea5e4ec00aae0963402e2565e91e95098ac (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.g4 | 167 | ||||
| -rw-r--r-- | src/main/scala/firrtl/DebugUtils.scala | 3 | ||||
| -rw-r--r-- | src/main/scala/firrtl/IR.scala | 149 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Passes.scala | 88 | ||||
| -rw-r--r-- | src/main/scala/firrtl/PrimOps.scala | 116 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Primops.scala | 119 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Utils.scala | 150 | ||||
| -rw-r--r-- | src/main/scala/firrtl/Visitor.scala | 137 |
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? } |
