aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/passes/wiring/WiringUtils.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/firrtl/passes/wiring/WiringUtils.scala')
-rw-r--r--src/main/scala/firrtl/passes/wiring/WiringUtils.scala164
1 files changed, 164 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/passes/wiring/WiringUtils.scala b/src/main/scala/firrtl/passes/wiring/WiringUtils.scala
new file mode 100644
index 00000000..bfa94a81
--- /dev/null
+++ b/src/main/scala/firrtl/passes/wiring/WiringUtils.scala
@@ -0,0 +1,164 @@
+package firrtl.passes
+package wiring
+
+import firrtl._
+import firrtl.ir._
+import firrtl.Utils._
+import firrtl.Mappers._
+import scala.collection.mutable
+import firrtl.Annotations._
+import WiringUtils._
+
+/** Declaration kind in lineage (e.g. input port, output port, wire)
+ */
+sealed trait DecKind
+case object DecInput extends DecKind
+case object DecOutput extends DecKind
+case object DecWire extends DecKind
+
+/** A lineage tree representing the instance hierarchy in a design
+ */
+case class Lineage(
+ name: String,
+ children: Seq[(String, Lineage)] = Seq.empty,
+ source: Boolean = false,
+ sink: Boolean = false,
+ sourceParent: Boolean = false,
+ sinkParent: Boolean = false,
+ sharedParent: Boolean = false,
+ addPort: Option[(String, DecKind)] = None,
+ cons: Seq[(String, String)] = Seq.empty) {
+
+ def map(f: Lineage => Lineage): Lineage =
+ this.copy(children = children.map{ case (i, m) => (i, f(m)) })
+
+ override def toString: String = shortSerialize("")
+
+ def shortSerialize(tab: String): String = s"""
+ |$tab name: $name,
+ |$tab children: ${children.map(c => tab + " " + c._2.shortSerialize(tab + " "))}
+ |""".stripMargin
+
+ def serialize(tab: String): String = s"""
+ |$tab name: $name,
+ |$tab source: $source,
+ |$tab sink: $sink,
+ |$tab sourceParent: $sourceParent,
+ |$tab sinkParent: $sinkParent,
+ |$tab sharedParent: $sharedParent,
+ |$tab addPort: $addPort
+ |$tab cons: $cons
+ |$tab children: ${children.map(c => tab + " " + c._2.serialize(tab + " "))}
+ |""".stripMargin
+}
+
+
+
+
+object WiringUtils {
+ type ChildrenMap = mutable.HashMap[String, Seq[(String, String)]]
+
+ /** Given a circuit, returns a map from module name to children
+ * instance/module names
+ */
+ def getChildrenMap(c: Circuit): ChildrenMap = {
+ val childrenMap = new ChildrenMap()
+ def getChildren(mname: String)(s: Statement): Statement = s match {
+ case s: WDefInstance =>
+ childrenMap(mname) = childrenMap(mname) :+ (s.name, s.module)
+ s
+ case s: DefInstance =>
+ childrenMap(mname) = childrenMap(mname) :+ (s.name, s.module)
+ s
+ case s => s map getChildren(mname)
+ }
+ c.modules.foreach{ m =>
+ childrenMap(m.name) = Nil
+ m map getChildren(m.name)
+ }
+ childrenMap
+ }
+
+ /** Counts the number of instances of a module declared under a top module
+ */
+ def countInstances(childrenMap: ChildrenMap, top: String, module: String): Int = {
+ if(top == module) 1
+ else childrenMap(top).foldLeft(0) { case (count, (i, child)) =>
+ count + countInstances(childrenMap, child, module)
+ }
+ }
+
+ /** Returns a module's lineage, containing all children lineages as well
+ */
+ def getLineage(childrenMap: ChildrenMap, module: String): Lineage =
+ Lineage(module, childrenMap(module) map { case (i, m) => (i, getLineage(childrenMap, m)) } )
+
+ /** Sets the sink, sinkParent, source, and sourceParent fields of every
+ * Lineage in tree
+ */
+ def setFields(sinks: Set[String], source: String)(lin: Lineage): Lineage = lin map setFields(sinks, source) match {
+ case l if sinks.contains(l.name) => l.copy(sink = true)
+ case l =>
+ val src = l.name == source
+ val sinkParent = l.children.foldLeft(false) { case (b, (i, m)) => b || m.sink || m.sinkParent }
+ val sourceParent = if(src) true else l.children.foldLeft(false) { case (b, (i, m)) => b || m.source || m.sourceParent }
+ l.copy(sinkParent=sinkParent, sourceParent=sourceParent, source=src)
+ }
+
+ /** Sets the sharedParent of lineage top
+ */
+ def setSharedParent(top: String)(lin: Lineage): Lineage = lin map setSharedParent(top) match {
+ case l if l.name == top => l.copy(sharedParent = true)
+ case l => l
+ }
+
+ /** Sets the addPort and cons fields of the lineage tree
+ */
+ def setThings(portNames:Map[String, String], compName: String)(lin: Lineage): Lineage = {
+ val funs = Seq(
+ ((l: Lineage) => l map setThings(portNames, compName)),
+ ((l: Lineage) => l match {
+ case Lineage(name, _, _, _, _, _, true, _, _) => //SharedParent
+ l.copy(addPort=Some((portNames(name), DecWire)))
+ case Lineage(name, _, _, _, true, _, _, _, _) => //SourceParent
+ l.copy(addPort=Some((portNames(name), DecOutput)))
+ case Lineage(name, _, _, _, _, true, _, _, _) => //SinkParent
+ l.copy(addPort=Some((portNames(name), DecInput)))
+ case Lineage(name, _, _, true, _, _, _, _, _) => //Sink
+ l.copy(addPort=Some((portNames(name), DecInput)))
+ case l => l
+ }),
+ ((l: Lineage) => l match {
+ case Lineage(name, _, true, _, _, _, _, _, _) => //Source
+ val tos = Seq(s"${portNames(name)}")
+ val from = compName
+ l.copy(cons = l.cons ++ tos.map(t => (t, from)))
+ case Lineage(name, _, _, _, true, _, _, _, _) => //SourceParent
+ val tos = Seq(s"${portNames(name)}")
+ val from = l.children.filter { case (i, c) => c.sourceParent }.map { case (i, c) => s"$i.${portNames(c.name)}" }.head
+ l.copy(cons = l.cons ++ tos.map(t => (t, from)))
+ case l => l
+ }),
+ ((l: Lineage) => l match {
+ case Lineage(name, _, _, _, _, true, _, _, _) => //SinkParent
+ val tos = l.children.filter { case (i, c) => (c.sinkParent || c.sink) && !c.sourceParent } map { case (i, c) => s"$i.${portNames(c.name)}" }
+ val from = s"${portNames(name)}"
+ l.copy(cons = l.cons ++ tos.map(t => (t, from)))
+ case l => l
+ })
+ )
+ funs.foldLeft(lin)((l, fun) => fun(l))
+ }
+
+ /** Return a map from module to its lineage in the tree
+ */
+ def pointToLineage(lin: Lineage): Map[String, Lineage] = {
+ val map = mutable.HashMap[String, Lineage]()
+ def onLineage(l: Lineage): Lineage = {
+ map(l.name) = l
+ l map onLineage
+ }
+ onLineage(lin)
+ map.toMap
+ }
+}