diff options
Diffstat (limited to 'src/main/scala/firrtl/passes/wiring/WiringUtils.scala')
| -rw-r--r-- | src/main/scala/firrtl/passes/wiring/WiringUtils.scala | 164 |
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 + } +} |
