From 2a68cc0636580db1a5fa98e87727bb3ec870e0bc Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Wed, 27 Oct 2021 15:51:21 -0700 Subject: Add java reflection to hierarchy (#2209) * Add Hierarchy trait * Add Hierarchy trait * Add Hierarchy scaladoc * Add license * Add isA and tests * Add back isA * Make calculate via lazy val * Apply suggestions from code review Co-authored-by: Megan Wachs * Add shouldNot compile * Update src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala Co-authored-by: Jack Koenig * Made protected vals private Co-authored-by: Megan Wachs Co-authored-by: Jack Koenig Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>--- .../chisel3/experimental/hierarchy/Hierarchy.scala | 31 ++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala index 8dbc5a54..d1ccfb1b 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala @@ -4,7 +4,7 @@ package chisel3.experimental.hierarchy import chisel3._ import scala.collection.mutable.{HashMap, HashSet} -import scala.reflect.runtime.universe.WeakTypeTag +import scala.reflect.runtime.universe.TypeTag import chisel3.internal.BaseModule.IsClone import chisel3.experimental.BaseModule import _root_.firrtl.annotations.IsModule @@ -25,12 +25,39 @@ sealed trait Hierarchy[+A] { private[chisel3] val cache = HashMap[Data, Data]() private[chisel3] def getInnerDataContext: Option[BaseModule] + /** Determine whether underlying proto is of type provided. + * + * @note IMPORTANT: this function requires summoning a TypeTag[B], which will fail if B is an inner class. + * @note IMPORTANT: this function IGNORES type parameters, akin to normal type erasure. + * @note IMPORTANT: this function relies on Java reflection for underlying proto, but Scala reflection for provided type + * + * E.g. isA[List[Int]] will return true, even if underlying proto is of type List[String] + * @return Whether underlying proto is of provided type (with caveats outlined above) + */ + def isA[B : TypeTag]: Boolean = { + val tptag = implicitly[TypeTag[B]] + val name = tptag.tpe.toString + inBaseClasses(name) + } + + private lazy val superClasses = calculateSuperClasses(proto.getClass()) + private def calculateSuperClasses(clz: Class[_]): Set[String] = { + if(clz != null) { + Set(clz.getCanonicalName()) ++ + clz.getInterfaces().flatMap(i => calculateSuperClasses(i)) ++ + calculateSuperClasses(clz.getSuperclass()) + } else { + Set.empty[String] + } + } + private def inBaseClasses(clz: String): Boolean = superClasses.contains(clz) + /** Used by Chisel's internal macros. DO NOT USE in your normal Chisel code!!! * Instead, mark the field you are accessing with [[@public]] * * Given a selector function (that) which selects a member from the original, return the - * corresponding member from the hierarhcy. + * corresponding member from the hierarchy. * * Our @instantiable and @public macros generate the calls to this apply method * -- cgit v1.2.3