aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/Utils.scala
diff options
context:
space:
mode:
authorDonggyu Kim2016-08-30 18:51:17 -0700
committerDonggyu Kim2016-09-07 16:58:06 -0700
commitd7bf6fb7b415d35f967d247119b8975c3dc885a3 (patch)
treebe6afdc75f2f209f4a412d5aafae5015da98cc2a /src/main/scala/firrtl/Utils.scala
parent296a65ebb895d100c3cbde6df7c0303d6942e5d5 (diff)
refactor checks
Diffstat (limited to 'src/main/scala/firrtl/Utils.scala')
-rw-r--r--src/main/scala/firrtl/Utils.scala53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/Utils.scala b/src/main/scala/firrtl/Utils.scala
index ea8ff4b7..29c37294 100644
--- a/src/main/scala/firrtl/Utils.scala
+++ b/src/main/scala/firrtl/Utils.scala
@@ -662,3 +662,56 @@ class MemoizedHash[T](val t: T) {
case _ => false
}
}
+
+/**
+ * Maintains a one to many graph of each modules instantiated child module.
+ * This graph can be searched for a path from a child module back to one of
+ * it's parents. If one is found a recursive loop has happened
+ * The graph is a map between the name of a node to set of names of that nodes children
+ */
+class ModuleGraph {
+ val nodes = HashMap[String, HashSet[String]]()
+
+ /**
+ * Add a child to a parent node
+ * A parent node is created if it does not already exist
+ *
+ * @param parent module that instantiates another module
+ * @param child module instantiated by parent
+ * @return a list indicating a path from child to parent, empty if no such path
+ */
+ def add(parent: String, child: String): List[String] = {
+ val childSet = nodes.getOrElseUpdate(parent, new HashSet[String])
+ childSet += child
+ pathExists(child, parent, List(child, parent))
+ }
+
+ /**
+ * Starting at the name of a given child explore the tree of all children in depth first manner.
+ * Return the first path (a list of strings) that goes from child to parent,
+ * or an empty list of no such path is found.
+ *
+ * @param child starting name
+ * @param parent name to find in children (recursively)
+ * @param path
+ * @return
+ */
+ def pathExists(child: String, parent: String, path: List[String] = Nil): List[String] = {
+ nodes.get(child) match {
+ case Some(children) =>
+ if(children(parent)) {
+ parent :: path
+ }
+ else {
+ children.foreach { grandchild =>
+ val newPath = pathExists(grandchild, parent, grandchild :: path)
+ if(newPath.nonEmpty) {
+ return newPath
+ }
+ }
+ Nil
+ }
+ case _ => Nil
+ }
+ }
+}