text: // SPDX-License-Identifier: Apache-2.0
  
  package firrtl.passes
  package clocklist
  
  import firrtl._
  import firrtl.ir._
  import wiring.Lineage
  import Utils._
  import memlib.AnalysisUtils._
  
  object ClockListUtils {
  
    /** Returns a list of clock outputs from instances of external modules
      */
    def getSourceList(moduleMap: Map[String, DefModule])(lin: Lineage): Seq[String] = {
      val s = lin.foldLeft(Seq[String]()) {
        case (sL, (i, l)) =>
          val sLx = getSourceList(moduleMap)(l)
          val sLxx = sLx.map(i + "$" + _)
          sL ++ sLxx
      }
      val sourceList = moduleMap(lin.name) match {
        case ExtModule(i, n, ports, dn, p) =>
          val portExps = ports.flatMap { p => create_exps(WRef(p.name, p.tpe, PortKind, to_flow(p.direction))) }
          portExps.filter(e => (e.tpe == ClockType) && (flow(e) == SinkFlow)).map(_.serialize)
        case _ => Nil
      }
      val sx = sourceList ++ s
      sx
    }
  
    /** Returns a map from instance name to its clock origin.
      *  Child instances are not included if they share the same clock as their parent
      */
    def getOrigins(
      connects:  Connects,
      me:        String,
      moduleMap: Map[String, DefModule]
    )(lin:       Lineage
    ): Map[String, String] = {
      val sep = if (me == "") "" else "$"
      // Get origins from all children
      val childrenOrigins = lin.foldLeft(Map[String, String]()) {
        case (o, (i, l)) =>
          o ++ getOrigins(connects, me + sep + i, moduleMap)(l)
      }
      // If I have a clock, get it
      val clockOpt = moduleMap(lin.name) match {
        case Module(i, n, ports, b)        => ports.collectFirst { case p if p.name == "clock" => me + sep + "clock" }
        case ExtModule(i, n, ports, dn, p) => None
      }
      // Return new origins with direct children removed, if they match my clock
      clockOpt match {
        case Some(clock) =>
          val myOrigin = getOrigin(connects, clock).serialize
          childrenOrigins.foldLeft(Map(me -> myOrigin)) {
            case (o, (childInstance, childOrigin)) =>
              val childrenInstances = lin.children.map { case (instance, _) => me + sep + instance }
              // If direct child shares my origin, omit it
              if (childOrigin == myOrigin && childrenInstances.contains(childInstance)) o
              else o + (childInstance -> childOrigin)
          }
        case None => childrenOrigins
      }
    }
  }
  