summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala7
-rw-r--r--core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala29
-rw-r--r--core/src/main/scala/chisel3/internal/Builder.scala19
3 files changed, 52 insertions, 3 deletions
diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala
index 59b4c692..a8cfac2f 100644
--- a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala
+++ b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala
@@ -11,6 +11,7 @@ import chisel3.internal.sourceinfo.{DefinitionTransform, DefinitionWrapTransform
import chisel3.experimental.BaseModule
import chisel3.internal.BaseModule.IsClone
import firrtl.annotations.{IsModule, ModuleTarget}
+import firrtl.annotations.{IsModule, ModuleTarget, NoTargetAnnotation}
/** User-facing Definition type.
* Represents a definition of an object of type [[A]] which are marked as @instantiable
@@ -112,3 +113,9 @@ object Definition extends SourceInfoDoc {
}
}
+
+/** Stores a [[Definition]] that is imported so that its Instances can be
+ * compiled separately.
+ */
+case class ImportDefinitionAnnotation[T <: BaseModule with IsInstantiable](definition: Definition[T])
+ extends NoTargetAnnotation
diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala
index cc926771..9f96dff1 100644
--- a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala
+++ b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala
@@ -2,12 +2,13 @@
package chisel3.experimental.hierarchy
-import scala.collection.mutable.{ArrayBuffer, HashMap}
import scala.language.experimental.macros
import chisel3._
import chisel3.internal.BaseModule.{InstantiableClone, IsClone, ModuleClone}
+import chisel3.internal.Builder
import chisel3.internal.sourceinfo.{InstanceTransform, SourceInfo}
-import chisel3.experimental.BaseModule
+import chisel3.experimental.{BaseModule, ExtModule}
+import chisel3.internal.firrtl.{Component, DefBlackBox, DefModule, Port}
import firrtl.annotations.IsModule
/** User-facing Instance type.
@@ -107,9 +108,33 @@ object Instance extends SourceInfoDoc {
implicit sourceInfo: SourceInfo,
compileOptions: CompileOptions
): Instance[T] = {
+ // Check to see if the module is already defined internally or externally
+ val existingMod = Builder.components.map {
+ case c: DefModule if c.id == definition.proto => Some(c)
+ case c: DefBlackBox if c.name == definition.proto.name => Some(c)
+ case _ => None
+ }.flatten
+
+ if (existingMod.isEmpty) {
+ // Add a Definition that will get emitted as an ExtModule so that FIRRTL
+ // does not complain about a missing element
+ class EmptyExtModule extends ExtModule {
+ override def desiredName: String = definition.proto.name
+ override def generateComponent(): Option[Component] = {
+ require(!_closed, s"Can't generate $desiredName module more than once")
+ _closed = true
+ val firrtlPorts = definition.proto.getModulePorts.map { port => Port(port, port.specifiedDirection) }
+ val component = DefBlackBox(this, definition.proto.name, firrtlPorts, SpecifiedDirection.Unspecified, params)
+ Some(component)
+ }
+ }
+ Definition(new EmptyExtModule() {})
+ }
+
val ports = experimental.CloneModuleAsRecord(definition.proto)
val clone = ports._parent.get.asInstanceOf[ModuleClone[T]]
clone._madeFromDefinition = true
+
new Instance(Clone(clone))
}
diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala
index 4180f580..69455455 100644
--- a/core/src/main/scala/chisel3/internal/Builder.scala
+++ b/core/src/main/scala/chisel3/internal/Builder.scala
@@ -6,7 +6,7 @@ import scala.util.DynamicVariable
import scala.collection.mutable.ArrayBuffer
import chisel3._
import chisel3.experimental._
-import chisel3.experimental.hierarchy.{Clone, Instance}
+import chisel3.experimental.hierarchy.{Clone, ImportDefinitionAnnotation, Instance}
import chisel3.internal.firrtl._
import chisel3.internal.naming._
import _root_.firrtl.annotations.{CircuitName, ComponentName, IsMember, ModuleName, Named, ReferenceTarget}
@@ -364,7 +364,24 @@ private[chisel3] class ChiselContext() {
}
private[chisel3] class DynamicContext(val annotationSeq: AnnotationSeq, val throwOnFirstError: Boolean) {
+ val importDefinitionAnnos = annotationSeq.collect { case a: ImportDefinitionAnnotation[_] => a }
+
+ // Ensure there are no repeated names for imported Definitions
+ val importDefinitionNames = importDefinitionAnnos.map { a => a.definition.proto.name }
+ if (importDefinitionNames.distinct.length < importDefinitionNames.length) {
+ val duplicates = importDefinitionNames.diff(importDefinitionNames.distinct).mkString(", ")
+ throwException(s"Expected distinct imported Definition names but found duplicates for: $duplicates")
+ }
+
val globalNamespace = Namespace.empty
+
+ // Ensure imported Definitions emit as ExtModules with the correct name so
+ // that instantiations will also use the correct name and prevent any name
+ // conflicts with Modules/Definitions in this elaboration
+ importDefinitionNames.foreach { importDefName =>
+ globalNamespace.name(importDefName)
+ }
+
val components = ArrayBuffer[Component]()
val annotations = ArrayBuffer[ChiselAnnotation]()
var currentModule: Option[BaseModule] = None