summaryrefslogtreecommitdiff
path: root/src/main/scala/chisel3/aop/Select.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/chisel3/aop/Select.scala')
-rw-r--r--src/main/scala/chisel3/aop/Select.scala1228
1 files changed, 614 insertions, 614 deletions
diff --git a/src/main/scala/chisel3/aop/Select.scala b/src/main/scala/chisel3/aop/Select.scala
index 738d6f31..19317f2a 100644
--- a/src/main/scala/chisel3/aop/Select.scala
+++ b/src/main/scala/chisel3/aop/Select.scala
@@ -1,614 +1,614 @@
-// SPDX-License-Identifier: Apache-2.0
-
-package chisel3.aop
-
-import chisel3._
-import chisel3.internal.{HasId}
-import chisel3.experimental.BaseModule
-import chisel3.experimental.FixedPoint
-import chisel3.internal.firrtl.{Definition => DefinitionIR, _}
-import chisel3.experimental.hierarchy._
-import chisel3.internal.PseudoModule
-import chisel3.internal.BaseModule.ModuleClone
-import firrtl.annotations.ReferenceTarget
-import scala.reflect.runtime.universe.TypeTag
-
-import scala.collection.mutable
-import chisel3.internal.naming.chiselName
-
-/** Use to select Chisel components in a module, after that module has been constructed
- * Useful for adding additional Chisel annotations or for use within an [[Aspect]]
- */
-object Select {
-
- /** Return just leaf components of expanded node
- *
- * @param d Component to find leafs if aggregate typed. Intermediate fields/indicies are not included
- */
- def getLeafs(d: Data): Seq[Data] = d match {
- case r: Record => r.elementsIterator.flatMap(getLeafs).toSeq
- case v: Vec[_] => v.getElements.flatMap(getLeafs)
- case other => Seq(other)
- }
-
- /** Return all expanded components, including intermediate aggregate nodes
- *
- * @param d Component to find leafs if aggregate typed. Intermediate fields/indicies ARE included
- */
- def getIntermediateAndLeafs(d: Data): Seq[Data] = d match {
- case r: Record => r +: r.elementsIterator.flatMap(getIntermediateAndLeafs).toSeq
- case v: Vec[_] => v +: v.getElements.flatMap(getIntermediateAndLeafs)
- case other => Seq(other)
- }
-
- /** Selects all instances/modules directly instantiated within given definition
- *
- * @param parent
- */
- def instancesIn(parent: Hierarchy[BaseModule]): Seq[Instance[BaseModule]] = {
- check(parent)
- implicit val mg = new chisel3.internal.MacroGenerated {}
- parent.proto._component.get match {
- case d: DefModule =>
- d.commands.collect {
- case d: DefInstance =>
- d.id match {
- case p: chisel3.internal.BaseModule.IsClone[_] =>
- parent._lookup { x => new Instance(Clone(p)).asInstanceOf[Instance[BaseModule]] }
- case other: BaseModule =>
- parent._lookup { x => other }
- }
- }
- case other => Nil
- }
- }
-
- /** Selects all Instances of instances/modules directly instantiated within given module, of provided type
- *
- * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class.
- * @note IMPORTANT: this function ignores type parameters. E.g. instancesOf[List[Int]] would return List[String].
- *
- * @param parent hierarchy which instantiates the returned Definitions
- */
- def instancesOf[T <: BaseModule: TypeTag](parent: Hierarchy[BaseModule]): Seq[Instance[T]] = {
- check(parent)
- implicit val mg = new chisel3.internal.MacroGenerated {}
- parent.proto._component.get match {
- case d: DefModule =>
- d.commands.flatMap {
- case d: DefInstance =>
- d.id match {
- case p: chisel3.internal.BaseModule.IsClone[_] =>
- val i = parent._lookup { x => new Instance(Clone(p)).asInstanceOf[Instance[BaseModule]] }
- if (i.isA[T]) Some(i.asInstanceOf[Instance[T]]) else None
- case other: BaseModule =>
- val i = parent._lookup { x => other }
- if (i.isA[T]) Some(i.asInstanceOf[Instance[T]]) else None
- }
- case other => None
- }
- case other => Nil
- }
- }
-
- /** Selects all Instances directly and indirectly instantiated within given root hierarchy, of provided type
- *
- * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class.
- * @note IMPORTANT: this function ignores type parameters. E.g. allInstancesOf[List[Int]] would return List[String].
- *
- * @param root top of the hierarchy to search for instances/modules of given type
- */
- def allInstancesOf[T <: BaseModule: TypeTag](root: Hierarchy[BaseModule]): Seq[Instance[T]] = {
- val soFar = if (root.isA[T]) Seq(root.toInstance.asInstanceOf[Instance[T]]) else Nil
- val allLocalInstances = instancesIn(root)
- soFar ++ (allLocalInstances.flatMap(allInstancesOf[T]))
- }
-
- /** Selects the Definitions of all instances/modules directly instantiated within given module
- *
- * @param parent
- */
- def definitionsIn(parent: Hierarchy[BaseModule]): Seq[Definition[BaseModule]] = {
- type DefType = Definition[BaseModule]
- implicit val mg = new chisel3.internal.MacroGenerated {}
- check(parent)
- val defs = parent.proto._component.get match {
- case d: DefModule =>
- d.commands.collect {
- case i: DefInstance =>
- i.id match {
- case p: chisel3.internal.BaseModule.IsClone[_] =>
- parent._lookup { x => new Definition(Proto(p.getProto)).asInstanceOf[Definition[BaseModule]] }
- case other: BaseModule =>
- parent._lookup { x => other.toDefinition }
- }
- }
- case other => Nil
- }
- val (_, defList) = defs.foldLeft((Set.empty[DefType], List.empty[DefType])) {
- case ((set, list), definition: Definition[BaseModule]) =>
- if (set.contains(definition)) (set, list) else (set + definition, definition +: list)
- }
- defList.reverse
- }
-
- /** Selects all Definitions of instances/modules directly instantiated within given module, of provided type
- *
- * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class.
- * @note IMPORTANT: this function ignores type parameters. E.g. definitionsOf[List[Int]] would return List[String].
- *
- * @param parent hierarchy which instantiates the returned Definitions
- */
- def definitionsOf[T <: BaseModule: TypeTag](parent: Hierarchy[BaseModule]): Seq[Definition[T]] = {
- check(parent)
- implicit val mg = new chisel3.internal.MacroGenerated {}
- type DefType = Definition[T]
- val defs = parent.proto._component.get match {
- case d: DefModule =>
- d.commands.flatMap {
- case d: DefInstance =>
- d.id match {
- case p: chisel3.internal.BaseModule.IsClone[_] =>
- val d = parent._lookup { x => new Definition(Clone(p)).asInstanceOf[Definition[BaseModule]] }
- if (d.isA[T]) Some(d.asInstanceOf[Definition[T]]) else None
- case other: BaseModule =>
- val d = parent._lookup { x => other.toDefinition }
- if (d.isA[T]) Some(d.asInstanceOf[Definition[T]]) else None
- }
- case other => None
- }
- }
- val (_, defList) = defs.foldLeft((Set.empty[DefType], List.empty[DefType])) {
- case ((set, list), definition: Definition[T]) =>
- if (set.contains(definition)) (set, list) else (set + definition, definition +: list)
- }
- defList.reverse
- }
-
- /** Selects all Definition's directly and indirectly instantiated within given root hierarchy, of provided type
- *
- * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class, i.e.
- * a class defined within another class.
- * @note IMPORTANT: this function ignores type parameters. E.g. allDefinitionsOf[List[Int]] would return List[String].
- *
- * @param root top of the hierarchy to search for definitions of given type
- */
- def allDefinitionsOf[T <: BaseModule: TypeTag](root: Hierarchy[BaseModule]): Seq[Definition[T]] = {
- type DefType = Definition[T]
- val allDefSet = mutable.HashSet[Definition[BaseModule]]()
- val defSet = mutable.HashSet[DefType]()
- val defList = mutable.ArrayBuffer[DefType]()
- def rec(hier: Definition[BaseModule]): Unit = {
- if (hier.isA[T] && !defSet.contains(hier.asInstanceOf[DefType])) {
- defSet += hier.asInstanceOf[DefType]
- defList += hier.asInstanceOf[DefType]
- }
- allDefSet += hier
- val allDefs = definitionsIn(hier)
- allDefs.collect {
- case d if !allDefSet.contains(d) => rec(d)
- }
- }
- rec(root.toDefinition)
- defList.toList
- }
-
- /** Collects all components selected by collector within module and all children modules it instantiates
- * directly or indirectly
- * Accepts a collector function, rather than a collector partial function (see [[collectDeep]])
- *
- * @note This API will not work with the new experimental hierarchy package. Instead, use allInstancesOf or allDefinitionsOf.
- *
- * @param module Module to collect components, as well as all children module it directly and indirectly instantiates
- * @param collector Collector function to pick, given a module, which components to collect
- * @param tag Required for generics to work, should ignore this
- * @tparam T Type of the component that will be collected
- */
- def getDeep[T](module: BaseModule)(collector: BaseModule => Seq[T]): Seq[T] = {
- check(module)
- val myItems = collector(module)
- val deepChildrenItems = instances(module).flatMap { i =>
- getDeep(i)(collector)
- }
- myItems ++ deepChildrenItems
- }
-
- /** Collects all components selected by collector within module and all children modules it instantiates
- * directly or indirectly
- * Accepts a collector partial function, rather than a collector function (see [[getDeep]])
- *
- * @note This API will not work with the new experimental hierarchy package. Instead, use allInstancesOf or allDefinitionsOf.
- *
- * @param module Module to collect components, as well as all children module it directly and indirectly instantiates
- * @param collector Collector partial function to pick, given a module, which components to collect
- * @param tag Required for generics to work, should ignore this
- * @tparam T Type of the component that will be collected
- */
- def collectDeep[T](module: BaseModule)(collector: PartialFunction[BaseModule, T]): Iterable[T] = {
- check(module)
- val myItems = collector.lift(module)
- val deepChildrenItems = instances(module).flatMap { i =>
- collectDeep(i)(collector)
- }
- myItems ++ deepChildrenItems
- }
-
- /** Selects all modules directly instantiated within given module
- *
- * @note This API will not work with the new experimental hierarchy package. Instead, use instancesIn or definitionsIn.
- *
- * @param module
- */
- def instances(module: BaseModule): Seq[BaseModule] = {
- check(module)
- module._component.get match {
- case d: DefModule =>
- d.commands.flatMap {
- case i: DefInstance =>
- i.id match {
- case m: ModuleClone[_] if !m._madeFromDefinition => None
- case _: PseudoModule =>
- throw new Exception(
- "instances, collectDeep, and getDeep are currently incompatible with Definition/Instance!"
- )
- case other => Some(other)
- }
- case _ => None
- }
- case other => Nil
- }
- }
-
- /** Selects all registers directly instantiated within given module
- * @param module
- */
- def registers(module: BaseModule): Seq[Data] = {
- check(module)
- module._component.get.asInstanceOf[DefModule].commands.collect {
- case r: DefReg => r.id
- case r: DefRegInit => r.id
- }
- }
-
- /** Selects all ios on a given module
- * @param module
- */
- def ios(module: BaseModule): Seq[Data] = {
- check(module)
- module._component.get.asInstanceOf[DefModule].ports.map(_.id)
- }
-
- /** Selects all ios directly on a given Instance or Definition of a module
- * @param parent the Definition or Instance to get the IOs of
- */
- def ios[T <: BaseModule](parent: Hierarchy[T]): Seq[Data] = {
- check(parent)
- implicit val mg = new chisel3.internal.MacroGenerated {}
- parent._lookup { x => ios(parent.proto) }
- }
-
- /** Selects all SyncReadMems directly contained within given module
- * @param module
- */
- def syncReadMems(module: BaseModule): Seq[SyncReadMem[_]] = {
- check(module)
- module._component.get.asInstanceOf[DefModule].commands.collect {
- case r: DefSeqMemory => r.id.asInstanceOf[SyncReadMem[_]]
- }
- }
-
- /** Selects all Mems directly contained within given module
- * @param module
- */
- def mems(module: BaseModule): Seq[Mem[_]] = {
- check(module)
- module._component.get.asInstanceOf[DefModule].commands.collect {
- case r: DefMemory => r.id.asInstanceOf[Mem[_]]
- }
- }
-
- /** Selects all arithmetic or logical operators directly instantiated within given module
- * @param module
- */
- def ops(module: BaseModule): Seq[(String, Data)] = {
- check(module)
- module._component.get.asInstanceOf[DefModule].commands.collect {
- case d: DefPrim[_] => (d.op.name, d.id)
- }
- }
-
- /** Selects a kind of arithmetic or logical operator directly instantiated within given module
- * The kind of operators are contained in [[chisel3.internal.firrtl.PrimOp]]
- * @param opKind the kind of operator, e.g. "mux", "add", or "bits"
- * @param module
- */
- def ops(opKind: String)(module: BaseModule): Seq[Data] = {
- check(module)
- module._component.get.asInstanceOf[DefModule].commands.collect {
- case d: DefPrim[_] if d.op.name == opKind => d.id
- }
- }
-
- /** Selects all wires in a module
- * @param module
- */
- def wires(module: BaseModule): Seq[Data] = {
- check(module)
- module._component.get.asInstanceOf[DefModule].commands.collect {
- case r: DefWire => r.id
- }
- }
-
- /** Selects all memory ports, including their direction and memory
- * @param module
- */
- def memPorts(module: BaseModule): Seq[(Data, MemPortDirection, MemBase[_])] = {
- check(module)
- module._component.get.asInstanceOf[DefModule].commands.collect {
- case r: DefMemPort[_] => (r.id, r.dir, r.source.id.asInstanceOf[MemBase[_ <: Data]])
- }
- }
-
- /** Selects all memory ports of a given direction, including their memory
- * @param dir The direction of memory ports to select
- * @param module
- */
- def memPorts(dir: MemPortDirection)(module: BaseModule): Seq[(Data, MemBase[_])] = {
- check(module)
- module._component.get.asInstanceOf[DefModule].commands.collect {
- case r: DefMemPort[_] if r.dir == dir => (r.id, r.source.id.asInstanceOf[MemBase[_ <: Data]])
- }
- }
-
- /** Selects all components who have been set to be invalid, even if they are later connected to
- * @param module
- */
- def invalids(module: BaseModule): Seq[Data] = {
- check(module)
- module._component.get.asInstanceOf[DefModule].commands.collect {
- case DefInvalid(_, arg) => getData(arg)
- }
- }
-
- /** Selects all components who are attached to a given signal, within a module
- * @param module
- */
- def attachedTo(module: BaseModule)(signal: Data): Set[Data] = {
- check(module)
- module._component.get
- .asInstanceOf[DefModule]
- .commands
- .collect {
- case Attach(_, seq) if seq.contains(signal) => seq
- }
- .flatMap { seq => seq.map(_.id.asInstanceOf[Data]) }
- .toSet
- }
-
- /** Selects all connections to a signal or its parent signal(s) (if the signal is an element of an aggregate signal)
- * The when predicates surrounding each connection are included in the returned values
- *
- * E.g. if signal = io.foo.bar, connectionsTo will return all connections to io, io.foo, and io.bar
- * @param module
- * @param signal
- */
- def connectionsTo(module: BaseModule)(signal: Data): Seq[PredicatedConnect] = {
- check(module)
- val sensitivitySignals = getIntermediateAndLeafs(signal).toSet
- val predicatedConnects = mutable.ArrayBuffer[PredicatedConnect]()
- val isPort = module._component.get
- .asInstanceOf[DefModule]
- .ports
- .flatMap { p => getIntermediateAndLeafs(p.id) }
- .contains(signal)
- var prePredicates: Seq[Predicate] = Nil
- var seenDef = isPort
- searchWhens(
- module,
- (cmd: Command, preds) => {
- cmd match {
- case cmd: DefinitionIR if cmd.id.isInstanceOf[Data] =>
- val x = getIntermediateAndLeafs(cmd.id.asInstanceOf[Data])
- if (x.contains(signal)) prePredicates = preds
- case Connect(_, loc @ Node(d: Data), exp) =>
- val effected = getEffected(loc).toSet
- if (sensitivitySignals.intersect(effected).nonEmpty) {
- val expData = getData(exp)
- prePredicates.reverse
- .zip(preds.reverse)
- .foreach(x => assert(x._1 == x._2, s"Prepredicates $x must match for signal $signal"))
- predicatedConnects += PredicatedConnect(preds.dropRight(prePredicates.size), d, expData, isBulk = false)
- }
- case BulkConnect(_, loc @ Node(d: Data), exp) =>
- val effected = getEffected(loc).toSet
- if (sensitivitySignals.intersect(effected).nonEmpty) {
- val expData = getData(exp)
- prePredicates.reverse
- .zip(preds.reverse)
- .foreach(x => assert(x._1 == x._2, s"Prepredicates $x must match for signal $signal"))
- predicatedConnects += PredicatedConnect(preds.dropRight(prePredicates.size), d, expData, isBulk = true)
- }
- case other =>
- }
- }
- )
- predicatedConnects.toSeq
- }
-
- /** Selects all stop statements, and includes the predicates surrounding the stop statement
- *
- * @param module
- */
- def stops(module: BaseModule): Seq[Stop] = {
- val stops = mutable.ArrayBuffer[Stop]()
- searchWhens(
- module,
- (cmd: Command, preds: Seq[Predicate]) => {
- cmd match {
- case chisel3.internal.firrtl.Stop(_, _, clock, ret) =>
- stops += Stop(preds, ret, getId(clock).asInstanceOf[Clock])
- case other =>
- }
- }
- )
- stops.toSeq
- }
-
- /** Selects all printf statements, and includes the predicates surrounding the printf statement
- *
- * @param module
- */
- def printfs(module: BaseModule): Seq[Printf] = {
- val printfs = mutable.ArrayBuffer[Printf]()
- searchWhens(
- module,
- (cmd: Command, preds: Seq[Predicate]) => {
- cmd match {
- case chisel3.internal.firrtl.Printf(id, _, clock, pable) =>
- printfs += Printf(id, preds, pable, getId(clock).asInstanceOf[Clock])
- case other =>
- }
- }
- )
- printfs.toSeq
- }
-
- // Checks that a module has finished its construction
- private def check(module: BaseModule): Unit = {
- require(module.isClosed, "Can't use Selector on modules that have not finished construction!")
- require(module._component.isDefined, "Can't use Selector on modules that don't have components!")
- }
- private def check(hierarchy: Hierarchy[BaseModule]): Unit = check(hierarchy.proto)
-
- // Given a loc, return all subcomponents of id that could be assigned to in connect
- private def getEffected(a: Arg): Seq[Data] = a match {
- case Node(id: Data) => getIntermediateAndLeafs(id)
- case Slot(imm, name) => Seq(imm.id.asInstanceOf[Record].elements(name))
- case Index(imm, value) => getEffected(imm)
- }
-
- // Given an arg, return the corresponding id. Don't use on a loc of a connect.
- private def getId(a: Arg): HasId = a match {
- case Node(id) => id
- case l: ULit => l.num.U(l.w)
- case l: SLit => l.num.S(l.w)
- case l: FPLit => FixedPoint(l.num, l.w, l.binaryPoint)
- case other =>
- sys.error(s"Something went horribly wrong! I was expecting ${other} to be a lit or a node!")
- }
-
- private def getData(a: Arg): Data = a match {
- case Node(data: Data) => data
- case other =>
- sys.error(s"Something went horribly wrong! I was expecting ${other} to be Data!")
- }
-
- // Given an id, either get its name or its value, if its a lit
- private def getName(i: HasId): String = try {
- i.toTarget match {
- case r: ReferenceTarget =>
- val str = r.serialize
- str.splitAt(str.indexOf('>'))._2.drop(1)
- }
- } catch {
- case e: ChiselException =>
- i.getOptionRef.get match {
- case l: LitArg => l.num.intValue.toString
- }
- }
-
- // Collects when predicates as it searches through a module, then applying processCommand to non-when related commands
- private def searchWhens(module: BaseModule, processCommand: (Command, Seq[Predicate]) => Unit) = {
- check(module)
- module._component.get.asInstanceOf[DefModule].commands.foldLeft((Seq.empty[Predicate], Option.empty[Predicate])) {
- (blah, cmd) =>
- (blah, cmd) match {
- case ((preds, o), cmd) =>
- cmd match {
- case WhenBegin(_, Node(pred: Bool)) => (When(pred) +: preds, None)
- case WhenBegin(_, l: LitArg) if l.num == BigInt(1) => (When(true.B) +: preds, None)
- case WhenBegin(_, l: LitArg) if l.num == BigInt(0) => (When(false.B) +: preds, None)
- case other: WhenBegin =>
- sys.error(s"Something went horribly wrong! I was expecting ${other.pred} to be a lit or a bool!")
- case _: WhenEnd => (preds.tail, Some(preds.head))
- case AltBegin(_) if o.isDefined => (o.get.not +: preds, o)
- case _: AltBegin =>
- sys.error(s"Something went horribly wrong! I was expecting ${o} to be nonEmpty!")
- case OtherwiseEnd(_, _) => (preds.tail, None)
- case other =>
- processCommand(cmd, preds)
- (preds, o)
- }
- }
- }
- }
-
- trait Serializeable {
- def serialize: String
- }
-
- /** Used to indicates a when's predicate (or its otherwise predicate)
- */
- trait Predicate extends Serializeable {
- val bool: Bool
- def not: Predicate
- }
-
- /** Used to represent [[chisel3.when]] predicate
- *
- * @param bool the when predicate
- */
- case class When(bool: Bool) extends Predicate {
- def not: WhenNot = WhenNot(bool)
- def serialize: String = s"${getName(bool)}"
- }
-
- /** Used to represent the `otherwise` predicate of a [[chisel3.when]]
- *
- * @param bool the when predicate corresponding to this otherwise predicate
- */
- case class WhenNot(bool: Bool) extends Predicate {
- def not: When = When(bool)
- def serialize: String = s"!${getName(bool)}"
- }
-
- /** Used to represent a connection or bulk connection
- *
- * Additionally contains the sequence of when predicates seen when the connection is declared
- *
- * @param preds
- * @param loc
- * @param exp
- * @param isBulk
- */
- case class PredicatedConnect(preds: Seq[Predicate], loc: Data, exp: Data, isBulk: Boolean) extends Serializeable {
- def serialize: String = {
- val moduleTarget = loc.toTarget.moduleTarget.serialize
- s"$moduleTarget: when(${preds.map(_.serialize).mkString(" & ")}): ${getName(loc)} ${if (isBulk) "<>" else ":="} ${getName(exp)}"
- }
- }
-
- /** Used to represent a [[chisel3.stop]]
- *
- * @param preds
- * @param ret
- * @param clock
- */
- case class Stop(preds: Seq[Predicate], ret: Int, clock: Clock) extends Serializeable {
- def serialize: String = {
- s"stop when(${preds.map(_.serialize).mkString(" & ")}) on ${getName(clock)}: $ret"
- }
- }
-
- /** Used to represent a [[chisel3.printf]]
- *
- * @param preds
- * @param pable
- * @param clock
- */
- case class Printf(id: printf.Printf, preds: Seq[Predicate], pable: Printable, clock: Clock) extends Serializeable {
- def serialize: String = {
- s"printf when(${preds.map(_.serialize).mkString(" & ")}) on ${getName(clock)}: $pable"
- }
- }
-}
+// // SPDX-License-Identifier: Apache-2.0
+
+// package chisel3.aop
+
+// import chisel3._
+// import chisel3.internal.{HasId}
+// import chisel3.experimental.BaseModule
+// import chisel3.experimental.FixedPoint
+// import chisel3.internal.firrtl.{Definition => DefinitionIR, _}
+// import chisel3.experimental.hierarchy._
+// import chisel3.internal.PseudoModule
+// import chisel3.internal.BaseModule.ModuleClone
+// import firrtl.annotations.ReferenceTarget
+// import scala.reflect.runtime.universe.TypeTag
+
+// import scala.collection.mutable
+// import chisel3.internal.naming.chiselName
+
+// /** Use to select Chisel components in a module, after that module has been constructed
+// * Useful for adding additional Chisel annotations or for use within an [[Aspect]]
+// */
+// object Select {
+
+// /** Return just leaf components of expanded node
+// *
+// * @param d Component to find leafs if aggregate typed. Intermediate fields/indicies are not included
+// */
+// def getLeafs(d: Data): Seq[Data] = d match {
+// case r: Record => r.elementsIterator.flatMap(getLeafs).toSeq
+// case v: Vec[_] => v.getElements.flatMap(getLeafs)
+// case other => Seq(other)
+// }
+
+// /** Return all expanded components, including intermediate aggregate nodes
+// *
+// * @param d Component to find leafs if aggregate typed. Intermediate fields/indicies ARE included
+// */
+// def getIntermediateAndLeafs(d: Data): Seq[Data] = d match {
+// case r: Record => r +: r.elementsIterator.flatMap(getIntermediateAndLeafs).toSeq
+// case v: Vec[_] => v +: v.getElements.flatMap(getIntermediateAndLeafs)
+// case other => Seq(other)
+// }
+
+// /** Selects all instances/modules directly instantiated within given definition
+// *
+// * @param parent
+// */
+// def instancesIn(parent: Hierarchy[BaseModule]): Seq[Instance[BaseModule]] = {
+// check(parent)
+// implicit val mg = new chisel3.internal.MacroGenerated {}
+// parent.proto._component.get match {
+// case d: DefModule =>
+// d.commands.collect {
+// case d: DefInstance =>
+// d.id match {
+// case p: chisel3.internal.BaseModule.IsClone[_] =>
+// parent._lookup { x => new Instance(Clone(p)).asInstanceOf[Instance[BaseModule]] }
+// case other: BaseModule =>
+// parent._lookup { x => other }
+// }
+// }
+// case other => Nil
+// }
+// }
+
+// /** Selects all Instances of instances/modules directly instantiated within given module, of provided type
+// *
+// * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class.
+// * @note IMPORTANT: this function ignores type parameters. E.g. instancesOf[List[Int]] would return List[String].
+// *
+// * @param parent hierarchy which instantiates the returned Definitions
+// */
+// def instancesOf[T <: BaseModule: TypeTag](parent: Hierarchy[BaseModule]): Seq[Instance[T]] = {
+// check(parent)
+// implicit val mg = new chisel3.internal.MacroGenerated {}
+// parent.proto._component.get match {
+// case d: DefModule =>
+// d.commands.flatMap {
+// case d: DefInstance =>
+// d.id match {
+// case p: chisel3.internal.BaseModule.IsClone[_] =>
+// val i = parent._lookup { x => new Instance(Clone(p)).asInstanceOf[Instance[BaseModule]] }
+// if (i.isA[T]) Some(i.asInstanceOf[Instance[T]]) else None
+// case other: BaseModule =>
+// val i = parent._lookup { x => other }
+// if (i.isA[T]) Some(i.asInstanceOf[Instance[T]]) else None
+// }
+// case other => None
+// }
+// case other => Nil
+// }
+// }
+
+// /** Selects all Instances directly and indirectly instantiated within given root hierarchy, of provided type
+// *
+// * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class.
+// * @note IMPORTANT: this function ignores type parameters. E.g. allInstancesOf[List[Int]] would return List[String].
+// *
+// * @param root top of the hierarchy to search for instances/modules of given type
+// */
+// def allInstancesOf[T <: BaseModule: TypeTag](root: Hierarchy[BaseModule]): Seq[Instance[T]] = {
+// val soFar = if (root.isA[T]) Seq(root.toInstance.asInstanceOf[Instance[T]]) else Nil
+// val allLocalInstances = instancesIn(root)
+// soFar ++ (allLocalInstances.flatMap(allInstancesOf[T]))
+// }
+
+// /** Selects the Definitions of all instances/modules directly instantiated within given module
+// *
+// * @param parent
+// */
+// def definitionsIn(parent: Hierarchy[BaseModule]): Seq[Definition[BaseModule]] = {
+// type DefType = Definition[BaseModule]
+// implicit val mg = new chisel3.internal.MacroGenerated {}
+// check(parent)
+// val defs = parent.proto._component.get match {
+// case d: DefModule =>
+// d.commands.collect {
+// case i: DefInstance =>
+// i.id match {
+// case p: chisel3.internal.BaseModule.IsClone[_] =>
+// parent._lookup { x => new Definition(Proto(p.getProto)).asInstanceOf[Definition[BaseModule]] }
+// case other: BaseModule =>
+// parent._lookup { x => other.toDefinition }
+// }
+// }
+// case other => Nil
+// }
+// val (_, defList) = defs.foldLeft((Set.empty[DefType], List.empty[DefType])) {
+// case ((set, list), definition: Definition[BaseModule]) =>
+// if (set.contains(definition)) (set, list) else (set + definition, definition +: list)
+// }
+// defList.reverse
+// }
+
+// /** Selects all Definitions of instances/modules directly instantiated within given module, of provided type
+// *
+// * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class.
+// * @note IMPORTANT: this function ignores type parameters. E.g. definitionsOf[List[Int]] would return List[String].
+// *
+// * @param parent hierarchy which instantiates the returned Definitions
+// */
+// def definitionsOf[T <: BaseModule: TypeTag](parent: Hierarchy[BaseModule]): Seq[Definition[T]] = {
+// check(parent)
+// implicit val mg = new chisel3.internal.MacroGenerated {}
+// type DefType = Definition[T]
+// val defs = parent.proto._component.get match {
+// case d: DefModule =>
+// d.commands.flatMap {
+// case d: DefInstance =>
+// d.id match {
+// case p: chisel3.internal.BaseModule.IsClone[_] =>
+// val d = parent._lookup { x => new Definition(Clone(p)).asInstanceOf[Definition[BaseModule]] }
+// if (d.isA[T]) Some(d.asInstanceOf[Definition[T]]) else None
+// case other: BaseModule =>
+// val d = parent._lookup { x => other.toDefinition }
+// if (d.isA[T]) Some(d.asInstanceOf[Definition[T]]) else None
+// }
+// case other => None
+// }
+// }
+// val (_, defList) = defs.foldLeft((Set.empty[DefType], List.empty[DefType])) {
+// case ((set, list), definition: Definition[T]) =>
+// if (set.contains(definition)) (set, list) else (set + definition, definition +: list)
+// }
+// defList.reverse
+// }
+
+// /** Selects all Definition's directly and indirectly instantiated within given root hierarchy, of provided type
+// *
+// * @note IMPORTANT: this function requires summoning a TypeTag[T], which will fail if T is an inner class, i.e.
+// * a class defined within another class.
+// * @note IMPORTANT: this function ignores type parameters. E.g. allDefinitionsOf[List[Int]] would return List[String].
+// *
+// * @param root top of the hierarchy to search for definitions of given type
+// */
+// def allDefinitionsOf[T <: BaseModule: TypeTag](root: Hierarchy[BaseModule]): Seq[Definition[T]] = {
+// type DefType = Definition[T]
+// val allDefSet = mutable.HashSet[Definition[BaseModule]]()
+// val defSet = mutable.HashSet[DefType]()
+// val defList = mutable.ArrayBuffer[DefType]()
+// def rec(hier: Definition[BaseModule]): Unit = {
+// if (hier.isA[T] && !defSet.contains(hier.asInstanceOf[DefType])) {
+// defSet += hier.asInstanceOf[DefType]
+// defList += hier.asInstanceOf[DefType]
+// }
+// allDefSet += hier
+// val allDefs = definitionsIn(hier)
+// allDefs.collect {
+// case d if !allDefSet.contains(d) => rec(d)
+// }
+// }
+// rec(root.toDefinition)
+// defList.toList
+// }
+
+// /** Collects all components selected by collector within module and all children modules it instantiates
+// * directly or indirectly
+// * Accepts a collector function, rather than a collector partial function (see [[collectDeep]])
+// *
+// * @note This API will not work with the new experimental hierarchy package. Instead, use allInstancesOf or allDefinitionsOf.
+// *
+// * @param module Module to collect components, as well as all children module it directly and indirectly instantiates
+// * @param collector Collector function to pick, given a module, which components to collect
+// * @param tag Required for generics to work, should ignore this
+// * @tparam T Type of the component that will be collected
+// */
+// def getDeep[T](module: BaseModule)(collector: BaseModule => Seq[T]): Seq[T] = {
+// check(module)
+// val myItems = collector(module)
+// val deepChildrenItems = instances(module).flatMap { i =>
+// getDeep(i)(collector)
+// }
+// myItems ++ deepChildrenItems
+// }
+
+// /** Collects all components selected by collector within module and all children modules it instantiates
+// * directly or indirectly
+// * Accepts a collector partial function, rather than a collector function (see [[getDeep]])
+// *
+// * @note This API will not work with the new experimental hierarchy package. Instead, use allInstancesOf or allDefinitionsOf.
+// *
+// * @param module Module to collect components, as well as all children module it directly and indirectly instantiates
+// * @param collector Collector partial function to pick, given a module, which components to collect
+// * @param tag Required for generics to work, should ignore this
+// * @tparam T Type of the component that will be collected
+// */
+// def collectDeep[T](module: BaseModule)(collector: PartialFunction[BaseModule, T]): Iterable[T] = {
+// check(module)
+// val myItems = collector.lift(module)
+// val deepChildrenItems = instances(module).flatMap { i =>
+// collectDeep(i)(collector)
+// }
+// myItems ++ deepChildrenItems
+// }
+
+// /** Selects all modules directly instantiated within given module
+// *
+// * @note This API will not work with the new experimental hierarchy package. Instead, use instancesIn or definitionsIn.
+// *
+// * @param module
+// */
+// def instances(module: BaseModule): Seq[BaseModule] = {
+// check(module)
+// module._component.get match {
+// case d: DefModule =>
+// d.commands.flatMap {
+// case i: DefInstance =>
+// i.id match {
+// case m: ModuleClone[_] if !m._madeFromDefinition => None
+// case _: PseudoModule =>
+// throw new Exception(
+// "instances, collectDeep, and getDeep are currently incompatible with Definition/Instance!"
+// )
+// case other => Some(other)
+// }
+// case _ => None
+// }
+// case other => Nil
+// }
+// }
+
+// /** Selects all registers directly instantiated within given module
+// * @param module
+// */
+// def registers(module: BaseModule): Seq[Data] = {
+// check(module)
+// module._component.get.asInstanceOf[DefModule].commands.collect {
+// case r: DefReg => r.id
+// case r: DefRegInit => r.id
+// }
+// }
+
+// /** Selects all ios on a given module
+// * @param module
+// */
+// def ios(module: BaseModule): Seq[Data] = {
+// check(module)
+// module._component.get.asInstanceOf[DefModule].ports.map(_.id)
+// }
+
+// /** Selects all ios directly on a given Instance or Definition of a module
+// * @param parent the Definition or Instance to get the IOs of
+// */
+// def ios[T <: BaseModule](parent: Hierarchy[T]): Seq[Data] = {
+// check(parent)
+// implicit val mg = new chisel3.internal.MacroGenerated {}
+// parent._lookup { x => ios(parent.proto) }
+// }
+
+// /** Selects all SyncReadMems directly contained within given module
+// * @param module
+// */
+// def syncReadMems(module: BaseModule): Seq[SyncReadMem[_]] = {
+// check(module)
+// module._component.get.asInstanceOf[DefModule].commands.collect {
+// case r: DefSeqMemory => r.id.asInstanceOf[SyncReadMem[_]]
+// }
+// }
+
+// /** Selects all Mems directly contained within given module
+// * @param module
+// */
+// def mems(module: BaseModule): Seq[Mem[_]] = {
+// check(module)
+// module._component.get.asInstanceOf[DefModule].commands.collect {
+// case r: DefMemory => r.id.asInstanceOf[Mem[_]]
+// }
+// }
+
+// /** Selects all arithmetic or logical operators directly instantiated within given module
+// * @param module
+// */
+// def ops(module: BaseModule): Seq[(String, Data)] = {
+// check(module)
+// module._component.get.asInstanceOf[DefModule].commands.collect {
+// case d: DefPrim[_] => (d.op.name, d.id)
+// }
+// }
+
+// /** Selects a kind of arithmetic or logical operator directly instantiated within given module
+// * The kind of operators are contained in [[chisel3.internal.firrtl.PrimOp]]
+// * @param opKind the kind of operator, e.g. "mux", "add", or "bits"
+// * @param module
+// */
+// def ops(opKind: String)(module: BaseModule): Seq[Data] = {
+// check(module)
+// module._component.get.asInstanceOf[DefModule].commands.collect {
+// case d: DefPrim[_] if d.op.name == opKind => d.id
+// }
+// }
+
+// /** Selects all wires in a module
+// * @param module
+// */
+// def wires(module: BaseModule): Seq[Data] = {
+// check(module)
+// module._component.get.asInstanceOf[DefModule].commands.collect {
+// case r: DefWire => r.id
+// }
+// }
+
+// /** Selects all memory ports, including their direction and memory
+// * @param module
+// */
+// def memPorts(module: BaseModule): Seq[(Data, MemPortDirection, MemBase[_])] = {
+// check(module)
+// module._component.get.asInstanceOf[DefModule].commands.collect {
+// case r: DefMemPort[_] => (r.id, r.dir, r.source.id.asInstanceOf[MemBase[_ <: Data]])
+// }
+// }
+
+// /** Selects all memory ports of a given direction, including their memory
+// * @param dir The direction of memory ports to select
+// * @param module
+// */
+// def memPorts(dir: MemPortDirection)(module: BaseModule): Seq[(Data, MemBase[_])] = {
+// check(module)
+// module._component.get.asInstanceOf[DefModule].commands.collect {
+// case r: DefMemPort[_] if r.dir == dir => (r.id, r.source.id.asInstanceOf[MemBase[_ <: Data]])
+// }
+// }
+
+// /** Selects all components who have been set to be invalid, even if they are later connected to
+// * @param module
+// */
+// def invalids(module: BaseModule): Seq[Data] = {
+// check(module)
+// module._component.get.asInstanceOf[DefModule].commands.collect {
+// case DefInvalid(_, arg) => getData(arg)
+// }
+// }
+
+// /** Selects all components who are attached to a given signal, within a module
+// * @param module
+// */
+// def attachedTo(module: BaseModule)(signal: Data): Set[Data] = {
+// check(module)
+// module._component.get
+// .asInstanceOf[DefModule]
+// .commands
+// .collect {
+// case Attach(_, seq) if seq.contains(signal) => seq
+// }
+// .flatMap { seq => seq.map(_.id.asInstanceOf[Data]) }
+// .toSet
+// }
+
+// /** Selects all connections to a signal or its parent signal(s) (if the signal is an element of an aggregate signal)
+// * The when predicates surrounding each connection are included in the returned values
+// *
+// * E.g. if signal = io.foo.bar, connectionsTo will return all connections to io, io.foo, and io.bar
+// * @param module
+// * @param signal
+// */
+// def connectionsTo(module: BaseModule)(signal: Data): Seq[PredicatedConnect] = {
+// check(module)
+// val sensitivitySignals = getIntermediateAndLeafs(signal).toSet
+// val predicatedConnects = mutable.ArrayBuffer[PredicatedConnect]()
+// val isPort = module._component.get
+// .asInstanceOf[DefModule]
+// .ports
+// .flatMap { p => getIntermediateAndLeafs(p.id) }
+// .contains(signal)
+// var prePredicates: Seq[Predicate] = Nil
+// var seenDef = isPort
+// searchWhens(
+// module,
+// (cmd: Command, preds) => {
+// cmd match {
+// case cmd: DefinitionIR if cmd.id.isInstanceOf[Data] =>
+// val x = getIntermediateAndLeafs(cmd.id.asInstanceOf[Data])
+// if (x.contains(signal)) prePredicates = preds
+// case Connect(_, loc @ Node(d: Data), exp) =>
+// val effected = getEffected(loc).toSet
+// if (sensitivitySignals.intersect(effected).nonEmpty) {
+// val expData = getData(exp)
+// prePredicates.reverse
+// .zip(preds.reverse)
+// .foreach(x => assert(x._1 == x._2, s"Prepredicates $x must match for signal $signal"))
+// predicatedConnects += PredicatedConnect(preds.dropRight(prePredicates.size), d, expData, isBulk = false)
+// }
+// case BulkConnect(_, loc @ Node(d: Data), exp) =>
+// val effected = getEffected(loc).toSet
+// if (sensitivitySignals.intersect(effected).nonEmpty) {
+// val expData = getData(exp)
+// prePredicates.reverse
+// .zip(preds.reverse)
+// .foreach(x => assert(x._1 == x._2, s"Prepredicates $x must match for signal $signal"))
+// predicatedConnects += PredicatedConnect(preds.dropRight(prePredicates.size), d, expData, isBulk = true)
+// }
+// case other =>
+// }
+// }
+// )
+// predicatedConnects.toSeq
+// }
+
+// /** Selects all stop statements, and includes the predicates surrounding the stop statement
+// *
+// * @param module
+// */
+// def stops(module: BaseModule): Seq[Stop] = {
+// val stops = mutable.ArrayBuffer[Stop]()
+// searchWhens(
+// module,
+// (cmd: Command, preds: Seq[Predicate]) => {
+// cmd match {
+// case chisel3.internal.firrtl.Stop(_, _, clock, ret) =>
+// stops += Stop(preds, ret, getId(clock).asInstanceOf[Clock])
+// case other =>
+// }
+// }
+// )
+// stops.toSeq
+// }
+
+// /** Selects all printf statements, and includes the predicates surrounding the printf statement
+// *
+// * @param module
+// */
+// def printfs(module: BaseModule): Seq[Printf] = {
+// val printfs = mutable.ArrayBuffer[Printf]()
+// searchWhens(
+// module,
+// (cmd: Command, preds: Seq[Predicate]) => {
+// cmd match {
+// case chisel3.internal.firrtl.Printf(id, _, clock, pable) =>
+// printfs += Printf(id, preds, pable, getId(clock).asInstanceOf[Clock])
+// case other =>
+// }
+// }
+// )
+// printfs.toSeq
+// }
+
+// // Checks that a module has finished its construction
+// private def check(module: BaseModule): Unit = {
+// require(module.isClosed, "Can't use Selector on modules that have not finished construction!")
+// require(module._component.isDefined, "Can't use Selector on modules that don't have components!")
+// }
+// private def check(hierarchy: Hierarchy[BaseModule]): Unit = check(hierarchy.proto)
+
+// // Given a loc, return all subcomponents of id that could be assigned to in connect
+// private def getEffected(a: Arg): Seq[Data] = a match {
+// case Node(id: Data) => getIntermediateAndLeafs(id)
+// case Slot(imm, name) => Seq(imm.id.asInstanceOf[Record].elements(name))
+// case Index(imm, value) => getEffected(imm)
+// }
+
+// // Given an arg, return the corresponding id. Don't use on a loc of a connect.
+// private def getId(a: Arg): HasId = a match {
+// case Node(id) => id
+// case l: ULit => l.num.U(l.w)
+// case l: SLit => l.num.S(l.w)
+// case l: FPLit => FixedPoint(l.num, l.w, l.binaryPoint)
+// case other =>
+// sys.error(s"Something went horribly wrong! I was expecting ${other} to be a lit or a node!")
+// }
+
+// private def getData(a: Arg): Data = a match {
+// case Node(data: Data) => data
+// case other =>
+// sys.error(s"Something went horribly wrong! I was expecting ${other} to be Data!")
+// }
+
+// // Given an id, either get its name or its value, if its a lit
+// private def getName(i: HasId): String = try {
+// i.toTarget match {
+// case r: ReferenceTarget =>
+// val str = r.serialize
+// str.splitAt(str.indexOf('>'))._2.drop(1)
+// }
+// } catch {
+// case e: ChiselException =>
+// i.getOptionRef.get match {
+// case l: LitArg => l.num.intValue.toString
+// }
+// }
+
+// // Collects when predicates as it searches through a module, then applying processCommand to non-when related commands
+// private def searchWhens(module: BaseModule, processCommand: (Command, Seq[Predicate]) => Unit) = {
+// check(module)
+// module._component.get.asInstanceOf[DefModule].commands.foldLeft((Seq.empty[Predicate], Option.empty[Predicate])) {
+// (blah, cmd) =>
+// (blah, cmd) match {
+// case ((preds, o), cmd) =>
+// cmd match {
+// case WhenBegin(_, Node(pred: Bool)) => (When(pred) +: preds, None)
+// case WhenBegin(_, l: LitArg) if l.num == BigInt(1) => (When(true.B) +: preds, None)
+// case WhenBegin(_, l: LitArg) if l.num == BigInt(0) => (When(false.B) +: preds, None)
+// case other: WhenBegin =>
+// sys.error(s"Something went horribly wrong! I was expecting ${other.pred} to be a lit or a bool!")
+// case _: WhenEnd => (preds.tail, Some(preds.head))
+// case AltBegin(_) if o.isDefined => (o.get.not +: preds, o)
+// case _: AltBegin =>
+// sys.error(s"Something went horribly wrong! I was expecting ${o} to be nonEmpty!")
+// case OtherwiseEnd(_, _) => (preds.tail, None)
+// case other =>
+// processCommand(cmd, preds)
+// (preds, o)
+// }
+// }
+// }
+// }
+
+// trait Serializeable {
+// def serialize: String
+// }
+
+// /** Used to indicates a when's predicate (or its otherwise predicate)
+// */
+// trait Predicate extends Serializeable {
+// val bool: Bool
+// def not: Predicate
+// }
+
+// /** Used to represent [[chisel3.when]] predicate
+// *
+// * @param bool the when predicate
+// */
+// case class When(bool: Bool) extends Predicate {
+// def not: WhenNot = WhenNot(bool)
+// def serialize: String = s"${getName(bool)}"
+// }
+
+// /** Used to represent the `otherwise` predicate of a [[chisel3.when]]
+// *
+// * @param bool the when predicate corresponding to this otherwise predicate
+// */
+// case class WhenNot(bool: Bool) extends Predicate {
+// def not: When = When(bool)
+// def serialize: String = s"!${getName(bool)}"
+// }
+
+// /** Used to represent a connection or bulk connection
+// *
+// * Additionally contains the sequence of when predicates seen when the connection is declared
+// *
+// * @param preds
+// * @param loc
+// * @param exp
+// * @param isBulk
+// */
+// case class PredicatedConnect(preds: Seq[Predicate], loc: Data, exp: Data, isBulk: Boolean) extends Serializeable {
+// def serialize: String = {
+// val moduleTarget = loc.toTarget.moduleTarget.serialize
+// s"$moduleTarget: when(${preds.map(_.serialize).mkString(" & ")}): ${getName(loc)} ${if (isBulk) "<>" else ":="} ${getName(exp)}"
+// }
+// }
+
+// /** Used to represent a [[chisel3.stop]]
+// *
+// * @param preds
+// * @param ret
+// * @param clock
+// */
+// case class Stop(preds: Seq[Predicate], ret: Int, clock: Clock) extends Serializeable {
+// def serialize: String = {
+// s"stop when(${preds.map(_.serialize).mkString(" & ")}) on ${getName(clock)}: $ret"
+// }
+// }
+
+// /** Used to represent a [[chisel3.printf]]
+// *
+// * @param preds
+// * @param pable
+// * @param clock
+// */
+// case class Printf(id: printf.Printf, preds: Seq[Predicate], pable: Printable, clock: Clock) extends Serializeable {
+// def serialize: String = {
+// s"printf when(${preds.map(_.serialize).mkString(" & ")}) on ${getName(clock)}: $pable"
+// }
+// }
+// }