Skip to content

Commit 88cb4d3

Browse files
committed
Hierarchy updates
Refactor cross-compilation logic
1 parent e694a6a commit 88cb4d3

File tree

5 files changed

+141
-157
lines changed

5 files changed

+141
-157
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package chisel3.experimental.hierarchy.core
2+
3+
import chisel3._
4+
import scala.reflect.runtime.universe.TypeTag
5+
6+
trait HierarchyProto[+A] {
7+
private[chisel3] def underlying: Underlying[A]
8+
private[chisel3] def proto: A = underlying match {
9+
case Proto(value) => value
10+
case Clone(i: IsClone[A]) => i.getProto
11+
}
12+
}
13+
14+
trait HierarchyIsA[+A] extends HierarchyProto[A] {
15+
// This code handles a special-case where, within an mdoc context, the type returned from
16+
// scala reflection (typetag) looks different than when returned from java reflection.
17+
// This function detects this case and reshapes the string to match.
18+
private def modifyReplString(clz: String): String = {
19+
if (clz != null) {
20+
clz.split('.').toList match {
21+
case "repl" :: "MdocSession" :: app :: rest => s"$app.this." + rest.mkString(".")
22+
case other => clz
23+
}
24+
} else clz
25+
}
26+
27+
private lazy val superClasses = calculateSuperClasses(super.proto.getClass())
28+
private def calculateSuperClasses(clz: Class[_]): Set[String] = {
29+
if (clz != null) {
30+
Set(modifyReplString(clz.getCanonicalName())) ++
31+
clz.getInterfaces().flatMap(i => calculateSuperClasses(i)) ++
32+
calculateSuperClasses(clz.getSuperclass())
33+
} else {
34+
Set.empty[String]
35+
}
36+
}
37+
private def inBaseClasses(clz: String): Boolean = superClasses.contains(clz)
38+
39+
/** Determine whether underlying proto is of type provided.
40+
*
41+
* @note IMPORTANT: this function requires summoning a TypeTag[B], which will fail if B is an inner class.
42+
* @note IMPORTANT: this function IGNORES type parameters, akin to normal type erasure.
43+
* @note IMPORTANT: this function relies on Java reflection for underlying proto, but Scala reflection for provided type
44+
*
45+
* E.g. isA[List[Int]] will return true, even if underlying proto is of type List[String]
46+
* @return Whether underlying proto is of provided type (with caveats outlined above)
47+
*/
48+
def isA[B: TypeTag]: Boolean = {
49+
val tptag = implicitly[TypeTag[B]]
50+
// drop any type information for the comparison, because the proto will not have that information.
51+
val name = tptag.tpe.toString.takeWhile(_ != '[')
52+
inBaseClasses(name)
53+
}
54+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package chisel3.experimental.hierarchy.core
2+
3+
import chisel3._
4+
5+
trait HierarchyProto[+A] {
6+
private[chisel3] def underlying: Underlying[A]
7+
private[chisel3] def proto: A = underlying match {
8+
case Proto(value) => value
9+
case Clone(i: IsClone[A]) => i.getProto
10+
}
11+
}
12+
13+
trait HierarchyIsA[+A] extends HierarchyProto[A] {
14+
// This code handles a special-case where, within an mdoc context, the type returned from
15+
// scala reflection (typetag) looks different than when returned from java reflection.
16+
// This function detects this case and reshapes the string to match.
17+
private def modifyReplString(clz: String): String = {
18+
if (clz != null) {
19+
clz.split('.').toList match {
20+
case "repl" :: "MdocSession" :: app :: rest => s"$app.this." + rest.mkString(".")
21+
case other => clz
22+
}
23+
} else clz
24+
}
25+
26+
private lazy val superClasses = calculateSuperClasses(super.proto.getClass())
27+
private def calculateSuperClasses(clz: Class[_]): Set[String] = {
28+
if (clz != null) {
29+
Set(modifyReplString(clz.getCanonicalName())) ++
30+
clz.getInterfaces().flatMap(i => calculateSuperClasses(i)) ++
31+
calculateSuperClasses(clz.getSuperclass())
32+
} else {
33+
Set.empty[String]
34+
}
35+
}
36+
private def inBaseClasses(clz: String): Boolean = superClasses.contains(clz)
37+
38+
/** Determine whether underlying proto is of type provided.
39+
*
40+
* @note IMPORTANT: this function requires summoning a TypeTag[B], which will fail if B is an inner class.
41+
* @note IMPORTANT: this function IGNORES type parameters, akin to normal type erasure.
42+
* @note IMPORTANT: this function relies on Java reflection for underlying proto, but Scala reflection for provided type
43+
*
44+
* E.g. isA[List[Int]] will return true, even if underlying proto is of type List[String]
45+
* @return Whether underlying proto is of provided type (with caveats outlined above)
46+
*/
47+
def isA[B]: Boolean = false // TODO
48+
}

core/src/main/scala-3/chisel3/experimental/hierarchy/core/Hierarchy.scala

Lines changed: 0 additions & 63 deletions
This file was deleted.

core/src/main/scala-2/chisel3/experimental/hierarchy/core/Hierarchy.scala renamed to core/src/main/scala/chisel3/experimental/hierarchy/core/Hierarchy.scala

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,56 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
13
package chisel3.experimental.hierarchy.core
24

35
import chisel3._
6+
47
import scala.collection.mutable.{HashMap, HashSet}
58
import chisel3.experimental.BaseModule
69
import _root_.firrtl.annotations.IsModule
7-
import scala.reflect.runtime.universe.TypeTag
810

9-
trait Hierarchy[+A] extends HierarchyImpl[A] {
11+
import scala.annotation.implicitNotFound
12+
13+
/** Super-trait for Instance and Definition
14+
*
15+
* Enables writing functions which are Instance/Definition agnostic
16+
*/
17+
sealed trait Hierarchy[+A] extends HierarchyIsA[A] {
1018

11-
/** Determine whether underlying proto is of type provided.
19+
/** Updated by calls to [[_lookup]], to avoid recloning returned Data's */
20+
private[chisel3] val cache = HashMap[Data, Data]()
21+
private[chisel3] def getInnerDataContext: Option[BaseModule]
22+
23+
/** Used by Chisel's internal macros. DO NOT USE in your normal Chisel code!!!
24+
* Instead, mark the field you are accessing with [[public]]
25+
*
26+
* Given a selector function (that) which selects a member from the original, return the
27+
* corresponding member from the hierarchy.
1228
*
13-
* @note IMPORTANT: this function requires summoning a TypeTag[B], which will fail if B is an inner class.
14-
* @note IMPORTANT: this function IGNORES type parameters, akin to normal type erasure.
15-
* @note IMPORTANT: this function relies on Java reflection for underlying proto, but Scala reflection for provided type
29+
* Our @instantiable and @public macros generate the calls to this apply method
1630
*
17-
* E.g. isA[List[Int]] will return true, even if underlying proto is of type List[String]
18-
* @return Whether underlying proto is of provided type (with caveats outlined above)
31+
* By calling this function, we summon the proper Lookupable typeclass from our implicit scope.
32+
*
33+
* @param that a user-specified lookup function
34+
* @param lookup typeclass which contains the correct lookup function, based on the types of A and B
35+
* @param macroGenerated a value created in the macro, to make it harder for users to use this API
1936
*/
20-
def isA[B: TypeTag]: Boolean = {
21-
val tptag = implicitly[TypeTag[B]]
22-
// drop any type information for the comparison, because the proto will not have that information.
23-
val name = tptag.tpe.toString.takeWhile(_ != '[')
24-
inBaseClasses(name)
25-
}
37+
def _lookup[B, C](
38+
that: A => B
39+
)(
40+
implicit lookup: Lookupable[B],
41+
macroGenerated: chisel3.internal.MacroGenerated
42+
): lookup.C
2643

44+
/** @return Return the underlying Definition[A] of this Hierarchy[A] */
45+
def toDefinition: Definition[A]
46+
47+
/** @return Convert this Hierarchy[A] as a top-level Instance[A] */
48+
def toInstance: Instance[A]
2749
}
2850

51+
// Used to effectively seal Hierarchy, without requiring Definition and Instance to be in this file.
52+
private[chisel3] trait SealedHierarchy[+A] extends Hierarchy[A]
53+
2954
object Hierarchy {
3055
implicit class HierarchyBaseModuleExtensions[T <: BaseModule](i: Hierarchy[T]) {
3156

core/src/main/scala/chisel3/experimental/hierarchy/core/HierarchyImpl.scala

Lines changed: 0 additions & 80 deletions
This file was deleted.

0 commit comments

Comments
 (0)