From 1ee9adbec48bc8393e1c3d0ed86a548f8510d13f Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Thu, 12 May 2022 17:31:59 +0000 Subject: Support separately elaborating definition and instance in ChiselStage (backport #2512) (#2520) * Support separately elaborating definition and instance in ChiselStage (#2512) (cherry picked from commit a0aa4d1550e3fbde199a98529cffeb176fb4bed8) # Conflicts: # core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala # core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala # core/src/main/scala/chisel3/internal/Builder.scala * fixing imports (#2522) Co-authored-by: Deborah Soung --- core/src/main/scala/chisel3/internal/Builder.scala | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'core/src/main/scala/chisel3/internal') 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 -- cgit v1.2.3 From 7825b432ece7abee9c955f2429046d1c48222437 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Thu, 19 May 2022 18:32:30 +0000 Subject: Support := views to DontCare (#2536) (#2539) (cherry picked from commit 77a6c93592d5766d66f199720fc6d69478005091) Co-authored-by: Jack Koenig --- core/src/main/scala/chisel3/internal/MonoConnect.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'core/src/main/scala/chisel3/internal') diff --git a/core/src/main/scala/chisel3/internal/MonoConnect.scala b/core/src/main/scala/chisel3/internal/MonoConnect.scala index 40056c89..31364804 100644 --- a/core/src/main/scala/chisel3/internal/MonoConnect.scala +++ b/core/src/main/scala/chisel3/internal/MonoConnect.scala @@ -210,7 +210,9 @@ private[chisel3] object MonoConnect { } // Source is DontCare - it may be connected to anything. It generates a defInvalid for the sink. - case (sink, DontCare) => pushCommand(DefInvalid(sourceInfo, sink.lref)) + case (_sink: Element, DontCare) => + val sink = reify(_sink) // Handle views + pushCommand(DefInvalid(sourceInfo, sink.lref)) // DontCare as a sink is illegal. case (DontCare, _) => throw DontCareCantBeSink // Analog is illegal in mono connections. -- cgit v1.2.3 From 0c811b490f47f20f2e81c58706924e56611b6ba2 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Sun, 29 May 2022 22:07:56 +0000 Subject: Deprecate accessing the name of non-hardware Data (#2550) (#2552) This includes (and is tested) for both the old .*Name APIs and .toTarget (cherry picked from commit 6e0d8d6b12e9d8f94c2cc43b92b2366ec70dfd50) Co-authored-by: Jack Koenig --- core/src/main/scala/chisel3/internal/Builder.scala | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'core/src/main/scala/chisel3/internal') diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala index 69455455..97c3bc49 100644 --- a/core/src/main/scala/chisel3/internal/Builder.scala +++ b/core/src/main/scala/chisel3/internal/Builder.scala @@ -240,7 +240,18 @@ private[chisel3] trait HasId extends InstanceId { private def refName(c: Component): String = _ref match { case Some(arg) => arg.fullName(c) - case None => _computeName(None, None).get + case None => + // This is super hacky but this is just for a short term deprecation + // These accesses occur after Chisel elaboration so we cannot use the normal + // Builder.deprecated mechanism, we have to create our own one off ErrorLog and print the + // warning right away. + val errors = new ErrorLog + val logger = new _root_.logger.Logger(this.getClass.getName) + val msg = "Accessing the .instanceName or .toTarget of non-hardware Data is deprecated. " + + "This will become an error in Chisel 3.6." + errors.deprecated(msg, None) + errors.checkpoint(logger) + _computeName(None, None).get } // Helper for reifying views if they map to a single Target -- cgit v1.2.3 From 42f5d89045e7db323670964a982c59319cf9001f Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Mon, 6 Jun 2022 23:02:01 +0000 Subject: Add --warn:reflective-naming (backport #2561) (#2565) * Factor buildName into reusable function The new function is chisel3.internal.buildName. (cherry picked from commit 370ca8ac68f6d888dd99e1b9e63f0371add398cf) * Add --warn:reflective-naming This new argument (and associated annotation) will turn on a warning whenever reflective naming changes the name of a signal. This is provided to help migrate from Chisel 3.5 to 3.6 since reflective naming is removed in Chisel 3.6. (cherry picked from commit 97afd9b9a1155fa7cd5cedf19f9e0c15fbe899ec) Co-authored-by: Jack Koenig --- core/src/main/scala/chisel3/internal/Builder.scala | 39 +++++++++++----------- core/src/main/scala/chisel3/internal/Error.scala | 5 +++ 2 files changed, 25 insertions(+), 19 deletions(-) (limited to 'core/src/main/scala/chisel3/internal') diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala index 97c3bc49..6f02b57c 100644 --- a/core/src/main/scala/chisel3/internal/Builder.scala +++ b/core/src/main/scala/chisel3/internal/Builder.scala @@ -137,6 +137,17 @@ private[chisel3] trait HasId extends InstanceId { this } + // Private internal version of suggestName that tells you if the name changed + // Returns Some(old name, old prefix) if name changed, None otherwise + private[chisel3] def _suggestNameCheck(seed: => String): Option[(String, Prefix)] = { + val oldSeed = this.seedOpt + val oldPrefix = this.naming_prefix + suggestName(seed) + if (oldSeed.nonEmpty && (oldSeed != this.seedOpt || oldPrefix != this.naming_prefix)) { + Some(oldSeed.get -> oldPrefix) + } else None + } + /** Takes the first seed suggested. Multiple calls to this function will be ignored. * If the final computed name conflicts with another name, it may get uniquified by appending * a digit at the end. @@ -171,22 +182,6 @@ private[chisel3] trait HasId extends InstanceId { * @return the name, if it can be computed */ private[chisel3] def _computeName(defaultPrefix: Option[String], defaultSeed: Option[String]): Option[String] = { - - /** Computes a name of this signal, given the seed and prefix - * @param seed - * @param prefix - * @return - */ - def buildName(seed: String, prefix: Prefix): String = { - val builder = new StringBuilder() - prefix.foreach { p => - builder ++= p - builder += '_' - } - builder ++= seed - builder.toString - } - if (hasSeed) { Some(buildName(seedOpt.get, naming_prefix.reverse)) } else { @@ -374,7 +369,10 @@ private[chisel3] class ChiselContext() { val viewNamespace = Namespace.empty } -private[chisel3] class DynamicContext(val annotationSeq: AnnotationSeq, val throwOnFirstError: Boolean) { +private[chisel3] class DynamicContext( + val annotationSeq: AnnotationSeq, + val throwOnFirstError: Boolean, + val warnReflectiveNaming: Boolean) { val importDefinitionAnnos = annotationSeq.collect { case a: ImportDefinitionAnnotation[_] => a } // Ensure there are no repeated names for imported Definitions @@ -649,6 +647,8 @@ private[chisel3] object Builder extends LazyLogging { throwException("Error: No implicit reset.") ) + def warnReflectiveNaming: Boolean = dynamicContext.warnReflectiveNaming + // TODO(twigg): Ideally, binding checks and new bindings would all occur here // However, rest of frontend can't support this yet. def pushCommand[T <: Command](c: T): T = { @@ -690,8 +690,9 @@ private[chisel3] object Builder extends LazyLogging { throwException(m) } } - def warning(m: => String): Unit = if (dynamicContextVar.value.isDefined) errors.warning(m) - def deprecated(m: => String, location: Option[String] = None): Unit = + def warning(m: => String): Unit = if (dynamicContextVar.value.isDefined) errors.warning(m) + def warningNoLoc(m: => String): Unit = if (dynamicContextVar.value.isDefined) errors.warningNoLoc(m) + def deprecated(m: => String, location: Option[String] = None): Unit = if (dynamicContextVar.value.isDefined) errors.deprecated(m, location) /** Record an exception as an error, and throw it. diff --git a/core/src/main/scala/chisel3/internal/Error.scala b/core/src/main/scala/chisel3/internal/Error.scala index 62086870..3b0846eb 100644 --- a/core/src/main/scala/chisel3/internal/Error.scala +++ b/core/src/main/scala/chisel3/internal/Error.scala @@ -186,6 +186,11 @@ private[chisel3] class ErrorLog { def warning(m: => String): Unit = errors += new Warning(m, getUserLineNumber) + /** Log a warning message without a source locator */ + def warningNoLoc(m: => String): Unit = { + errors += new Warning(m, None) + } + /** Emit an informational message */ @deprecated("This method will be removed in 3.5", "3.4") def info(m: String): Unit = -- cgit v1.2.3 From d001b34f816f1f65d0625aebf33e5cfc5ba93e49 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Thu, 16 Jun 2022 23:15:42 +0000 Subject: Define leading '_' as API for creating temporaries (backport #2580) (#2581) * Define leading '_' as API for creating temporaries Chisel and FIRRTL have long used signals with names beginning with an underscore as an API to specify that the name does not really matter. Tools like Verilator follow a similar convention and exclude signals with underscore names from waveform dumps by default. With the introduction of compiler-plugin prefixing in Chisel 3.4, the convention remained but was hard for users to use unless the unnnamed signal existed outside of any prefix domain. Notably, unnamed signals are most useful when creating wires inside of utility methods which almost always results in the signal ending up with a prefix. With this commit, Chisel explicitly recognizes signals whos val names start with an underscore and preserve that underscore regardless of any prefixing. Chisel will also ignore such underscores when generating prefixes based on the temporary signal, preventing accidental double underscores in the names of signals that are prefixed by the temporary. (cherry picked from commit bd94366290886f3489d58f88b9768c7c11fa2cb6) * Remove unused defaultPrefix argument from _computeName (cherry picked from commit ec178aa20a830df2c8c756b9e569709a59073554) # Conflicts: # core/src/main/scala/chisel3/Module.scala # core/src/main/scala/chisel3/experimental/hierarchy/ModuleClone.scala * Resolve backport conflicts * Waive false positive binary compatibility errors Co-authored-by: Jack Koenig --- core/src/main/scala/chisel3/internal/Builder.scala | 30 ++++++++++------------ .../main/scala/chisel3/internal/firrtl/IR.scala | 2 +- 2 files changed, 14 insertions(+), 18 deletions(-) (limited to 'core/src/main/scala/chisel3/internal') diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala index 6f02b57c..6fd9bdd5 100644 --- a/core/src/main/scala/chisel3/internal/Builder.scala +++ b/core/src/main/scala/chisel3/internal/Builder.scala @@ -177,21 +177,13 @@ private[chisel3] trait HasId extends InstanceId { } /** Computes the name of this HasId, if one exists - * @param defaultPrefix Optionally provide a default prefix for computing the name * @param defaultSeed Optionally provide default seed for computing the name * @return the name, if it can be computed */ - private[chisel3] def _computeName(defaultPrefix: Option[String], defaultSeed: Option[String]): Option[String] = { - if (hasSeed) { - Some(buildName(seedOpt.get, naming_prefix.reverse)) - } else { - defaultSeed.map { default => - defaultPrefix match { - case Some(p) => buildName(default, p :: naming_prefix.reverse) - case None => buildName(default, naming_prefix.reverse) - } - } - } + private[chisel3] def _computeName(defaultSeed: Option[String]): Option[String] = { + seedOpt + .orElse(defaultSeed) + .map(name => buildName(name, naming_prefix.reverse)) } /** This resolves the precedence of [[autoSeed]] and [[suggestName]] @@ -211,9 +203,9 @@ private[chisel3] trait HasId extends InstanceId { // Uses a namespace to convert suggestion into a true name // Will not do any naming if the reference already assigned. // (e.g. tried to suggest a name to part of a Record) - private[chisel3] def forceName(prefix: Option[String], default: => String, namespace: Namespace): Unit = + private[chisel3] def forceName(default: => String, namespace: Namespace): Unit = if (_ref.isEmpty) { - val candidate_name = _computeName(prefix, Some(default)).get + val candidate_name = _computeName(Some(default)).get val available_name = namespace.name(candidate_name) setRef(Ref(available_name)) // Clear naming prefix to free memory @@ -246,7 +238,7 @@ private[chisel3] trait HasId extends InstanceId { "This will become an error in Chisel 3.6." errors.deprecated(msg, None) errors.checkpoint(logger) - _computeName(None, None).get + _computeName(None).get } // Helper for reifying views if they map to a single Target @@ -506,7 +498,11 @@ private[chisel3] object Builder extends LazyLogging { } } buildAggName(d).map { name => - pushPrefix(name) + if (isTemp(name)) { + pushPrefix(name.tail) + } else { + pushPrefix(name) + } }.isDefined } @@ -749,7 +745,7 @@ private[chisel3] object Builder extends LazyLogging { logger.info("Elaborating design...") val mod = f if (forceModName) { // This avoids definition name index skipping with D/I - mod.forceName(None, mod.name, globalNamespace) + mod.forceName(mod.name, globalNamespace) } errors.checkpoint(logger) logger.info("Done elaborating.") diff --git a/core/src/main/scala/chisel3/internal/firrtl/IR.scala b/core/src/main/scala/chisel3/internal/firrtl/IR.scala index 1ee8842f..9327c29e 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -94,7 +94,7 @@ object Arg { case Some(arg) => arg.name case None => id match { - case data: Data => data._computeName(None, Some("?")).get + case data: Data => data._computeName(Some("?")).get case _ => "?" } } -- cgit v1.2.3 From 7e67ca1ef93e53d4b9b6f8e13a21d69e0c5daac4 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Wed, 22 Jun 2022 02:01:31 +0000 Subject: Pass optional name in ImportDefinitionAnno (#2592) (#2594) Used for separate elaboration of Definition and Instance (cherry picked from commit 48d57cc8db6f38fdf0e23b7dce36caa404c871b8) Co-authored-by: Girish Pai --- core/src/main/scala/chisel3/internal/Builder.scala | 44 ++++++++++++++++------ 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'core/src/main/scala/chisel3/internal') diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala index 6fd9bdd5..35dd01ab 100644 --- a/core/src/main/scala/chisel3/internal/Builder.scala +++ b/core/src/main/scala/chisel3/internal/Builder.scala @@ -367,11 +367,30 @@ private[chisel3] class DynamicContext( val warnReflectiveNaming: 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") + // Map holding the actual names of extModules + // Pick the definition name by default in case not passed through annotation. + val importDefinitionMap = importDefinitionAnnos + .map(a => a.definition.proto.name -> a.overrideDefName.getOrElse(a.definition.proto.name)) + .toMap + + // Helper function which does 2 things + // 1. Ensure there are no repeated names for imported Definitions - both Proto Names as well as ExtMod Names + // 2. Return the distinct definition / extMod names + private def checkAndGeDistinctProtoExtModNames() = { + val importAllDefinitionProtoNames = importDefinitionAnnos.map { a => a.definition.proto.name } + val importDistinctDefinitionProtoNames = importDefinitionMap.keys.toSeq + val importAllDefinitionExtModNames = importDefinitionMap.toSeq.map(_._2) + val importDistinctDefinitionExtModNames = importAllDefinitionExtModNames.distinct + + if (importDistinctDefinitionProtoNames.length < importAllDefinitionProtoNames.length) { + val duplicates = importAllDefinitionProtoNames.diff(importDistinctDefinitionProtoNames).mkString(", ") + throwException(s"Expected distinct imported Definition names but found duplicates for: $duplicates") + } + if (importDistinctDefinitionExtModNames.length < importAllDefinitionExtModNames.length) { + val duplicates = importAllDefinitionExtModNames.diff(importDistinctDefinitionExtModNames).mkString(", ") + throwException(s"Expected distinct overrideDef names but found duplicates for: $duplicates") + } + (importAllDefinitionProtoNames ++ importAllDefinitionExtModNames).distinct } val globalNamespace = Namespace.empty @@ -379,8 +398,8 @@ private[chisel3] class DynamicContext( // 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) + checkAndGeDistinctProtoExtModNames().foreach { + globalNamespace.name(_) } val components = ArrayBuffer[Component]() @@ -447,11 +466,12 @@ private[chisel3] object Builder extends LazyLogging { def idGen: IdGen = chiselContext.get.idGen - def globalNamespace: Namespace = dynamicContext.globalNamespace - def components: ArrayBuffer[Component] = dynamicContext.components - def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations - def annotationSeq: AnnotationSeq = dynamicContext.annotationSeq - def namingStack: NamingStack = dynamicContext.namingStack + def globalNamespace: Namespace = dynamicContext.globalNamespace + def components: ArrayBuffer[Component] = dynamicContext.components + def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations + def annotationSeq: AnnotationSeq = dynamicContext.annotationSeq + def namingStack: NamingStack = dynamicContext.namingStack + def importDefinitionMap: Map[String, String] = dynamicContext.importDefinitionMap def unnamedViews: ArrayBuffer[Data] = dynamicContext.unnamedViews def viewNamespace: Namespace = chiselContext.get.viewNamespace -- cgit v1.2.3 From 94aeeb1a5c2fe38777a9004ba36f8b353e96b292 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Fri, 8 Jul 2022 23:44:45 +0000 Subject: CompileOptions: add and use emitStrictConnects (#2622) (#2623) (cherry picked from commit 11e8cc60d6268301cff352b8a1d7c4d672b5be11) Co-authored-by: Megan Wachs --- .../main/scala/chisel3/internal/BiConnect.scala | 70 +++++++++++++--------- 1 file changed, 43 insertions(+), 27 deletions(-) (limited to 'core/src/main/scala/chisel3/internal') diff --git a/core/src/main/scala/chisel3/internal/BiConnect.scala b/core/src/main/scala/chisel3/internal/BiConnect.scala index 2d6c9e4a..e8fb2361 100644 --- a/core/src/main/scala/chisel3/internal/BiConnect.scala +++ b/core/src/main/scala/chisel3/internal/BiConnect.scala @@ -55,6 +55,24 @@ private[chisel3] object BiConnect { * There is some cleverness in the use of internal try-catch to catch exceptions * during the recursive decent and then rethrow them with extra information added. * This gives the user a 'path' to where in the connections things went wrong. + * + * == Chisel Semantics and how they emit to firrtl == + * + * 1. Strict Bi-Connect (all fields as seen by firrtl must match exactly) + * `a <= b` + * + * 2. Strict Bi-Connect (implemented as being field-blasted because we know all firrtl fields would not match exactly) + * `a.foo <= b.foo, b.bar <= a.bar` + * + * 3. Not-Strict Bi-Connect (firrtl will allow fields to not match exactly) + * `a <- b` + * + * 4. Mixed Semantic Bi-Connect (some fields need to be handled differently) + * `a.foo <= b.foo` (case 2), `b.bar <- a.bar` (case 3) + * + * - The decision on 1 vs 2 is based on structural type -- if same type once emitted to firrtl, emit 1, otherwise emit 2 + * - 1/2 vs 3 is based on CompileOptions at connection point e.g. at `<>` , emit 3 if `emitStrictConnects = false` for either side + * - 4 is a special case of 2 turning into 3 for some subfields, when either side's subfield at `extends Bundle/Record` has `emitStrictConnects = false` */ def connect( sourceInfo: SourceInfo, @@ -140,8 +158,8 @@ private[chisel3] object BiConnect { // Handle Records defined in Chisel._ code by emitting a FIRRTL bulk // connect when possible and a partial connect otherwise case pair @ (left_r: Record, right_r: Record) => - val notStrict = - Seq(left_r.compileOptions, right_r.compileOptions).contains(ExplicitCompileOptions.NotStrict) + val emitStrictConnects: Boolean = + left_r.compileOptions.emitStrictConnects && right_r.compileOptions.emitStrictConnects // chisel3 <> is commutative but FIRRTL <- is not val flipConnection = @@ -161,40 +179,38 @@ private[chisel3] object BiConnect { ) ) { pushCommand(Connect(sourceInfo, leftReified.get.lref, rightReified.get.lref)) - } else if (notStrict) { - newLeft.bulkConnect(newRight)(sourceInfo, ExplicitCompileOptions.NotStrict) + } else if (!emitStrictConnects) { + newLeft.legacyConnect(newRight)(sourceInfo) } else { recordConnect(sourceInfo, connectCompileOptions, left_r, right_r, context_mod) } - // Handle Records connected to DontCare (change to NotStrict) + // Handle Records connected to DontCare case (left_r: Record, DontCare) => - left_r.compileOptions match { - case ExplicitCompileOptions.NotStrict => - left.bulkConnect(right)(sourceInfo, ExplicitCompileOptions.NotStrict) - case _ => - // For each field in left, descend with right - for ((field, left_sub) <- left_r.elements) { - try { - connect(sourceInfo, connectCompileOptions, left_sub, right, context_mod) - } catch { - case BiConnectException(message) => throw BiConnectException(s".$field$message") - } + if (!left_r.compileOptions.emitStrictConnects) { + left.legacyConnect(right)(sourceInfo) + } else { + // For each field in left, descend with right + for ((field, left_sub) <- left_r.elements) { + try { + connect(sourceInfo, connectCompileOptions, left_sub, right, context_mod) + } catch { + case BiConnectException(message) => throw BiConnectException(s".$field$message") } + } } case (DontCare, right_r: Record) => - right_r.compileOptions match { - case ExplicitCompileOptions.NotStrict => - left.bulkConnect(right)(sourceInfo, ExplicitCompileOptions.NotStrict) - case _ => - // For each field in left, descend with right - for ((field, right_sub) <- right_r.elements) { - try { - connect(sourceInfo, connectCompileOptions, left, right_sub, context_mod) - } catch { - case BiConnectException(message) => throw BiConnectException(s".$field$message") - } + if (!right_r.compileOptions.emitStrictConnects) { + left.legacyConnect(right)(sourceInfo) + } else { + // For each field in left, descend with right + for ((field, right_sub) <- right_r.elements) { + try { + connect(sourceInfo, connectCompileOptions, left, right_sub, context_mod) + } catch { + case BiConnectException(message) => throw BiConnectException(s".$field$message") } + } } // Left and right are different subtypes of Data so fail -- cgit v1.2.3 From dbffb8779efca6bea8699ed80a04b1d47d657d93 Mon Sep 17 00:00:00 2001 From: mergify[bot] Date: Wed, 13 Jul 2022 20:39:44 +0000 Subject: New enhanced API for specifying Chisel to Firrtl Annotations (#2628) (#2631) (cherry picked from commit 4b10cf7a276e90b280c1fd57070566acac3d80d3) Co-authored-by: Girish Pai --- core/src/main/scala/chisel3/internal/Builder.scala | 13 +++++--- .../main/scala/chisel3/internal/firrtl/IR.scala | 37 ++++++++++++++++++++-- 2 files changed, 44 insertions(+), 6 deletions(-) (limited to 'core/src/main/scala/chisel3/internal') diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala index 35dd01ab..61f94f8f 100644 --- a/core/src/main/scala/chisel3/internal/Builder.scala +++ b/core/src/main/scala/chisel3/internal/Builder.scala @@ -404,6 +404,7 @@ private[chisel3] class DynamicContext( val components = ArrayBuffer[Component]() val annotations = ArrayBuffer[ChiselAnnotation]() + val newAnnotations = ArrayBuffer[ChiselMultiAnnotation]() var currentModule: Option[BaseModule] = None /** Contains a mapping from a elaborated module to their aspect @@ -466,9 +467,13 @@ private[chisel3] object Builder extends LazyLogging { def idGen: IdGen = chiselContext.get.idGen - def globalNamespace: Namespace = dynamicContext.globalNamespace - def components: ArrayBuffer[Component] = dynamicContext.components - def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations + def globalNamespace: Namespace = dynamicContext.globalNamespace + def components: ArrayBuffer[Component] = dynamicContext.components + def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations + + // TODO : Unify this with annotations in the future - done this way for backward compatability + def newAnnotations: ArrayBuffer[ChiselMultiAnnotation] = dynamicContext.newAnnotations + def annotationSeq: AnnotationSeq = dynamicContext.annotationSeq def namingStack: NamingStack = dynamicContext.namingStack def importDefinitionMap: Map[String, String] = dynamicContext.importDefinitionMap @@ -770,7 +775,7 @@ private[chisel3] object Builder extends LazyLogging { errors.checkpoint(logger) logger.info("Done elaborating.") - (Circuit(components.last.name, components.toSeq, annotations.toSeq, makeViewRenameMap), mod) + (Circuit(components.last.name, components.toSeq, annotations.toSeq, makeViewRenameMap, newAnnotations.toSeq), mod) } } initializeSingletons() diff --git a/core/src/main/scala/chisel3/internal/firrtl/IR.scala b/core/src/main/scala/chisel3/internal/firrtl/IR.scala index 9327c29e..dc9ab027 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -861,7 +861,40 @@ case class DefBlackBox( params: Map[String, Param]) extends Component -case class Circuit(name: String, components: Seq[Component], annotations: Seq[ChiselAnnotation], renames: RenameMap) { - def firrtlAnnotations: Iterable[Annotation] = annotations.flatMap(_.toFirrtl.update(renames)) +case class Circuit( + name: String, + components: Seq[Component], + @deprecated("Do not use annotations val of Circuit directly - use firrtlAnnotations instead. Will be removed in a future release", + "Chisel 3.5") + annotations: Seq[ChiselAnnotation], + renames: RenameMap, + @deprecated("Do not use newAnnotations val of Circuit directly - use firrtlAnnotations instead. Will be removed in a future release", + "Chisel 3.5") + + newAnnotations: Seq[ChiselMultiAnnotation]) { + + def this(name: String, components: Seq[Component], annotations: Seq[ChiselAnnotation], renames: RenameMap) = + this(name, components, annotations, renames, Seq.empty) + + def firrtlAnnotations: Iterable[Annotation] = + annotations.flatMap(_.toFirrtl.update(renames)) ++ newAnnotations.flatMap( + _.toFirrtl.flatMap(_.update(renames)) + ) + + def copy( + name: String = name, + components: Seq[Component] = components, + annotations: Seq[ChiselAnnotation] = annotations, + renames: RenameMap = renames + ) = Circuit(name, components, annotations, renames, newAnnotations) + +} +object Circuit + extends scala.runtime.AbstractFunction4[String, Seq[Component], Seq[ChiselAnnotation], RenameMap, Circuit] { + def unapply(c: Circuit): Option[(String, Seq[Component], Seq[ChiselAnnotation], RenameMap)] = { + Some((c.name, c.components, c.annotations, c.renames)) + } + def apply(name: String, components: Seq[Component], annotations: Seq[ChiselAnnotation], renames: RenameMap): Circuit = + new Circuit(name, components, annotations, renames) } -- cgit v1.2.3