aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/Passes.scala
diff options
context:
space:
mode:
authorAdam Izraelevitz2015-10-19 13:56:32 -0700
committerAdam Izraelevitz2015-10-19 13:56:32 -0700
commitf258c8394ebe7136e0eee7e1e342b5b593d1cc5d (patch)
tree5d000281afd7f217bee0c5c2030f3a17e079a3f0 /src/main/scala/firrtl/Passes.scala
parent154c7d86a104264a3e3355d105f8e60926a10626 (diff)
parent80c055ce93c9d5988c6158c4a91c01633f8ebf22 (diff)
Merge pull request #47 from jackkoenig/master
Updated Scala FIRRTL with Testing and Infer-Types Pass
Diffstat (limited to 'src/main/scala/firrtl/Passes.scala')
-rw-r--r--src/main/scala/firrtl/Passes.scala102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/Passes.scala b/src/main/scala/firrtl/Passes.scala
new file mode 100644
index 00000000..39e6b64e
--- /dev/null
+++ b/src/main/scala/firrtl/Passes.scala
@@ -0,0 +1,102 @@
+
+package firrtl
+
+import Utils._
+import DebugUtils._
+import Primops._
+
+object Passes {
+
+ private def toField(p: Port)(implicit logger: Logger): Field = {
+ logger.trace(s"toField called on port ${p.serialize}")
+ p.dir match {
+ case Input => Field(p.name, Reverse, p.tpe)
+ case Output => Field(p.name, Default, p.tpe)
+ }
+ }
+
+ /** INFER TYPES
+ *
+ * This pass infers the type field in all IR nodes by updating
+ * and passing an environment to all statements in pre-order
+ * traversal, and resolving types in expressions in post-
+ * order traversal.
+ * Type propagation for primary ops are defined here.
+ * Notable cases: LetRec requires updating environment before
+ * resolving the subexpressions in its elements.
+ * Type errors are not checked in this pass, as this is
+ * postponed for a later/earlier pass.
+ */
+ // input -> flip
+ private type TypeMap = Map[String, Type]
+ private val TypeMap = Map[String, Type]().withDefaultValue(UnknownType)
+ private def getBundleSubtype(t: Type, name: String): Type = {
+ t match {
+ case b: BundleType => {
+ val tpe = b.fields.find( _.name == name )
+ if (tpe.isEmpty) UnknownType
+ else tpe.get.tpe
+ }
+ case _ => UnknownType
+ }
+ }
+ private def getVectorSubtype(t: Type): Type = t.getType // Added for clarity
+ // TODO Add genders
+ private def inferExpTypes(typeMap: TypeMap)(exp: Exp)(implicit logger: Logger): Exp = {
+ logger.trace(s"inferTypes called on ${exp.getClass.getSimpleName}")
+ exp.map(inferExpTypes(typeMap)) match {
+ case e: UIntValue => e
+ case e: SIntValue => e
+ case e: Ref => Ref(e.name, typeMap(e.name))
+ case e: Subfield => Subfield(e.exp, e.name, getBundleSubtype(e.exp.getType, e.name))
+ case e: Index => Index(e.exp, e.value, getVectorSubtype(e.exp.getType))
+ case e: DoPrimop => lowerAndTypePrimop(e)
+ case e: Exp => e
+ }
+ }
+ private def inferTypes(typeMap: TypeMap, stmt: Stmt)(implicit logger: Logger): (Stmt, TypeMap) = {
+ logger.trace(s"inferTypes called on ${stmt.getClass.getSimpleName} ")
+ stmt.map(inferExpTypes(typeMap)) match {
+ case b: Block => {
+ var tMap = typeMap
+ // TODO FIXME is map correctly called in sequential order
+ val body = b.stmts.map { s =>
+ val ret = inferTypes(tMap, s)
+ tMap = ret._2
+ ret._1
+ }
+ (Block(body), tMap)
+ }
+ case s: DefWire => (s, typeMap ++ Map(s.name -> s.tpe))
+ case s: DefReg => (s, typeMap ++ Map(s.name -> s.tpe))
+ case s: DefMemory => (s, typeMap ++ Map(s.name -> s.tpe))
+ case s: DefInst => (s, typeMap ++ Map(s.name -> s.module.getType))
+ case s: DefNode => (s, typeMap ++ Map(s.name -> s.value.getType))
+ case s: DefPoison => (s, typeMap ++ Map(s.name -> s.tpe))
+ case s: DefAccessor => (s, typeMap ++ Map(s.name -> getVectorSubtype(s.source.getType)))
+ case s: When => { // TODO Check: Assuming else block won't see when scope
+ val (conseq, cMap) = inferTypes(typeMap, s.conseq)
+ val (alt, aMap) = inferTypes(typeMap, s.alt)
+ (When(s.info, s.pred, conseq, alt), cMap ++ aMap)
+ }
+ case s: Stmt => (s, typeMap)
+ }
+ }
+ private def inferTypes(typeMap: TypeMap, m: Module)(implicit logger: Logger): Module = {
+ logger.trace(s"inferTypes called on module ${m.name}")
+
+ val pTypeMap = m.ports.map( p => p.name -> p.tpe ).toMap
+
+ Module(m.info, m.name, m.ports, inferTypes(typeMap ++ pTypeMap, m.stmt)._1)
+ }
+ def inferTypes(c: Circuit)(implicit logger: Logger): Circuit = {
+ logger.trace(s"inferTypes called on circuit ${c.name}")
+
+ // initialize typeMap with each module of circuit mapped to their bundled IO (ports converted to fields)
+ val typeMap = c.modules.map(m => m.name -> BundleType(m.ports.map(toField(_)))).toMap
+
+ //val typeMap = c.modules.flatMap(buildTypeMap).toMap
+ Circuit(c.info, c.name, c.modules.map(inferTypes(typeMap, _)))
+ }
+
+}