Skip to content

Commit 262e428

Browse files
Fix extmodule emission when instantiating an imported Definition multiple times (#4759)
1 parent 425bdd2 commit 262e428

File tree

2 files changed

+27
-18
lines changed

2 files changed

+27
-18
lines changed

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

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,23 @@ object Instance extends SourceInfoDoc {
124124
}
125125
}
126126

127+
private class ImportedDefinitionExtModule(
128+
override val desiredName: String,
129+
val importedDefinition: Definition[BaseModule with IsInstantiable]
130+
) extends ExtModule {
131+
override private[chisel3] def _isImportedDefinition = true
132+
override def generateComponent(): Option[Component] = {
133+
require(!_closed, s"Can't generate $desiredName module more than once")
134+
_closed = true
135+
val firrtlPorts = importedDefinition.proto.getModulePortsAndLocators.map { case (port, sourceInfo) =>
136+
Port(port, port.specifiedDirection, sourceInfo): @nowarn // Deprecated code allowed for internal use
137+
}
138+
val component =
139+
DefBlackBox(this, importedDefinition.proto.name, firrtlPorts, SpecifiedDirection.Unspecified, params)
140+
Some(component)
141+
}
142+
}
143+
127144
/** A constructs an [[Instance]] from a [[Definition]]
128145
*
129146
* @param definition the Module being created
@@ -136,10 +153,11 @@ object Instance extends SourceInfoDoc {
136153
): Instance[T] = {
137154
// Check to see if the module is already defined internally or externally
138155
val existingMod = Builder.definitions.view.map(_.proto).exists {
139-
case c: Class => c == definition.proto
140-
case c: RawModule => c == definition.proto
141-
case c: BaseBlackBox => c.name == definition.proto.name
142-
case c: BaseIntrinsicModule => c.name == definition.proto.name
156+
case c: Class => c == definition.proto
157+
case c: RawModule => c == definition.proto
158+
case c: ImportedDefinitionExtModule => c.importedDefinition == definition
159+
case c: BaseBlackBox => c.name == definition.proto.name
160+
case c: BaseIntrinsicModule => c.name == definition.proto.name
143161
case _ => false
144162
}
145163

@@ -152,20 +170,7 @@ object Instance extends SourceInfoDoc {
152170
s"Imported Definition information not found for ${definition.proto.name} - possibly forgot to add ImportDefinition annotation?"
153171
)
154172
)
155-
class EmptyExtModule extends ExtModule {
156-
override def desiredName: String = extModName
157-
override private[chisel3] def _isImportedDefinition = true
158-
override def generateComponent(): Option[Component] = {
159-
require(!_closed, s"Can't generate $desiredName module more than once")
160-
_closed = true
161-
val firrtlPorts = definition.proto.getModulePortsAndLocators.map { case (port, sourceInfo) =>
162-
Port(port, port.specifiedDirection, sourceInfo): @nowarn // Deprecated code allowed for internal use
163-
}
164-
val component = DefBlackBox(this, definition.proto.name, firrtlPorts, SpecifiedDirection.Unspecified, params)
165-
Some(component)
166-
}
167-
}
168-
Definition(new EmptyExtModule() {})
173+
Definition(new ImportedDefinitionExtModule(extModName, definition))
169174
}
170175

171176
val ports = experimental.CloneModuleAsRecord(definition.proto)

src/test/scala-2/chiselTests/experimental/hierarchy/SeparateElaborationSpec.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ class SeparateElaborationSpec extends AnyFunSpec with Matchers with Utils with T
142142
args = Array("-td", testDir, "--full-stacktrace", "--target", "chirrtl"),
143143
annotations = Seq(ChiselGeneratorAnnotation(() => new Testbench(dutDef)), ImportDefinitionAnnotation(dutDef))
144144
)
145+
146+
val tbFir = Source.fromFile(s"${testDir}/Testbench.fir").getLines().mkString
147+
assert("extmodule AddOne".r.findAllMatchIn(tbFir).length == 1)
148+
assert("""inst \S+ of AddOne""".r.findAllMatchIn(tbFir).length == 2)
145149
}
146150
}
147151

0 commit comments

Comments
 (0)