diff options
| author | Adam Izraelevitz | 2021-10-27 16:52:56 -0700 |
|---|---|---|
| committer | GitHub | 2021-10-27 23:52:56 +0000 |
| commit | ef8a9c2148f01e058d2986c9d64f0c35f640790c (patch) | |
| tree | ad2c31ee8216758882cc7364c93a51c14050a6a4 /core | |
| parent | 2a68cc0636580db1a5fa98e87727bb3ec870e0bc (diff) | |
Add Select APIs for Hierarchy package (#2210)
* Add Hierarchy trait
* Add Hierarchy trait
* Add Hierarchy scaladoc
* Add license
* Add isA and tests
* Add back isA
* Add new Select APIs for hierarchy package
* Update scaladoc
* Write outlines for tests
* Add tests and fixes to new Select functions
* Make calculate via lazy val
* Apply suggestions from code review
Co-authored-by: Megan Wachs <megan@sifive.com>
* Apply suggestions from code review
Co-authored-by: Megan Wachs <megan@sifive.com>
* Clean up scaladoc
* Add shouldNot compile
* Apply suggestions from code review
Co-authored-by: Megan Wachs <megan@sifive.com>
* Bugfix all funcs should analyze root too
* Add mdoc, bugfix toDefinition
* Make func private, add scaladoc
* Update src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala
Co-authored-by: Jack Koenig <koenig@sifive.com>
* Made protected vals private
* Apply suggestions from code review
Co-authored-by: Jack Koenig <koenig@sifive.com>
* Address code review comments
* Added additional null check
Co-authored-by: Megan Wachs <megan@sifive.com>
Co-authored-by: Jack Koenig <koenig@sifive.com>
Diffstat (limited to 'core')
6 files changed, 55 insertions, 11 deletions
diff --git a/core/src/main/scala/chisel3/Module.scala b/core/src/main/scala/chisel3/Module.scala index 1ae65969..263aee61 100644 --- a/core/src/main/scala/chisel3/Module.scala +++ b/core/src/main/scala/chisel3/Module.scala @@ -88,6 +88,16 @@ object Module extends SourceInfoDoc { def reset: Reset = Builder.forcedReset /** Returns the current Module */ def currentModule: Option[BaseModule] = Builder.currentModule + + private[chisel3] def do_pseudo_apply[T <: BaseModule](bc: => T) + (implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions): T = { + val parent = Builder.currentModule + + val module: T = bc // bc is actually evaluated here + + module + } } /** Abstract base class for Modules, which behave much like Verilog modules. @@ -357,13 +367,19 @@ package experimental { // // Builder Internals - this tracks which Module RTL construction belongs to. // - if (!Builder.readyForModuleConstr) { - throwException("Error: attempted to instantiate a Module without wrapping it in Module().") + this match { + case _: PseudoModule => + case other => + if (!Builder.readyForModuleConstr) { + throwException("Error: attempted to instantiate a Module without wrapping it in Module().") + } } - readyForModuleConstr = false + if (Builder.hasDynamicContext) { + readyForModuleConstr = false - Builder.currentModule = Some(this) - Builder.whenStack = Nil + Builder.currentModule = Some(this) + Builder.whenStack = Nil + } // // Module Construction Internals diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala index 3c4c3c84..8f0c88ad 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala @@ -42,13 +42,16 @@ final case class Definition[+A] private[chisel3] (private[chisel3] cloned: Eithe /** @return the context of any Data's return from inside the instance */ private[chisel3] def getInnerDataContext: Option[BaseModule] = proto match { case value: BaseModule => - val newChild = Module.do_apply(new internal.BaseModule.DefinitionClone(value))(chisel3.internal.sourceinfo.UnlocatableSourceInfo, chisel3.ExplicitCompileOptions.Strict) + val newChild = Module.do_pseudo_apply(new internal.BaseModule.DefinitionClone(value))(chisel3.internal.sourceinfo.UnlocatableSourceInfo, chisel3.ExplicitCompileOptions.Strict) newChild._circuit = value._circuit.orElse(Some(value)) newChild._parent = None Some(newChild) case value: IsInstantiable => None } + override def toDefinition: Definition[A] = this + override def toInstance: Instance[A] = new Instance(cloned) + } /** Factory methods for constructing [[Definition]]s */ diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala index d1ccfb1b..559b0e1a 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala @@ -40,10 +40,22 @@ sealed trait Hierarchy[+A] { inBaseClasses(name) } + + // This code handles a special-case where, within an mdoc context, the type returned from + // scala reflection (typetag) looks different than when returned from java reflection. + // This function detects this case and reshapes the string to match. + private def modifyReplString(clz: String): String = { + if(clz != null) { + clz.split('.').toList match { + case "repl" :: "MdocSession" :: app :: rest => s"$app.this." + rest.mkString(".") + case other => clz + } + } else clz + } private lazy val superClasses = calculateSuperClasses(proto.getClass()) private def calculateSuperClasses(clz: Class[_]): Set[String] = { if(clz != null) { - Set(clz.getCanonicalName()) ++ + Set(modifyReplString(clz.getCanonicalName())) ++ clz.getInterfaces().flatMap(i => calculateSuperClasses(i)) ++ calculateSuperClasses(clz.getSuperclass()) } else { @@ -68,6 +80,12 @@ sealed trait Hierarchy[+A] { * @param macroGenerated a value created in the macro, to make it harder for users to use this API */ def _lookup[B, C](that: A => B)(implicit lookup: Lookupable[B], macroGenerated: chisel3.internal.MacroGenerated): lookup.C + + /** @return Return the underlying Definition[A] of this Hierarchy[A] */ + def toDefinition: Definition[A] + + /** @return Convert this Hierarchy[A] as a top-level Instance[A] */ + def toInstance: Instance[A] } // Used to effectively seal Hierarchy, without requiring Definition and Instance to be in this file. diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala index bda52c1b..49f882eb 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala @@ -17,6 +17,10 @@ import firrtl.annotations.IsModule * @param cloned The internal representation of the instance, which may be either be directly the object, or a clone of an object */ final case class Instance[+A] private [chisel3] (private[chisel3] cloned: Either[A, IsClone[A]]) extends SealedHierarchy[A] { + cloned match { + case Left(p: IsClone[_]) => chisel3.internal.throwException("Cannot have a Left with a clone!") + case other => //Ok + } /** @return the context of any Data's return from inside the instance */ private[chisel3] def getInnerDataContext: Option[BaseModule] = cloned match { @@ -52,7 +56,8 @@ final case class Instance[+A] private [chisel3] (private[chisel3] cloned: Either } /** Returns the definition of this Instance */ - def toDefinition: Definition[A] = new Definition(Left(proto)) + override def toDefinition: Definition[A] = new Definition(Left(proto)) + override def toInstance: Instance[A] = this } diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala index 2242c1c4..771e2070 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala @@ -211,7 +211,7 @@ private[chisel3] object Lookupable { // Recursive call def rec[A <: BaseModule](m: A): Either[A, IsClone[A]] = { def clone(x: A, p: Option[BaseModule], name: () => String): Either[A, IsClone[A]] = { - val newChild = Module.do_apply(new internal.BaseModule.InstanceClone(x, name)) + val newChild = Module.do_pseudo_apply(new internal.BaseModule.InstanceClone(x, name)) newChild._parent = p Right(newChild) } @@ -233,7 +233,7 @@ private[chisel3] object Lookupable { rec(m) match { case Left(mx) => Right(mx) case Right(i: InstanceClone[_]) => - val newChild = Module.do_apply(new InstanceClone(m._proto, () => m.instanceName)) + val newChild = Module.do_pseudo_apply(new InstanceClone(m._proto, () => m.instanceName)) newChild._parent = i._parent Right(newChild) } @@ -241,7 +241,7 @@ private[chisel3] object Lookupable { rec(m) match { case Left(mx) => Right(mx) case Right(i: InstanceClone[_]) => - val newChild = Module.do_apply(new InstanceClone(m._proto, () => m.instanceName)) + val newChild = Module.do_pseudo_apply(new InstanceClone(m._proto, () => m.instanceName)) newChild._parent = i._parent Right(newChild) } diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala index 57e7578a..3761b371 100644 --- a/core/src/main/scala/chisel3/internal/Builder.scala +++ b/core/src/main/scala/chisel3/internal/Builder.scala @@ -561,6 +561,8 @@ private[chisel3] object Builder extends LazyLogging { // A bare api call is, e.g. calling Wire() from the scala console). ) } + def hasDynamicContext: Boolean = dynamicContextVar.value.isDefined + def readyForModuleConstr: Boolean = dynamicContext.readyForModuleConstr def readyForModuleConstr_=(target: Boolean): Unit = { dynamicContext.readyForModuleConstr = target |
