summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/src/main/scala/chisel3/internal/Builder.scala15
-rw-r--r--plugin/README.md99
-rw-r--r--plugin/src/main/resources/scalac-plugin.xml4
-rw-r--r--plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala281
-rw-r--r--plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala242
-rw-r--r--plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala81
-rw-r--r--src/main/scala/chisel3/stage/ChiselAnnotations.scala2
-rw-r--r--src/main/scala/chisel3/stage/phases/Convert.scala2
-rw-r--r--src/main/scala/chisel3/util/Bitwise.scala12
-rw-r--r--src/main/scala/chisel3/util/Cat.scala4
-rw-r--r--src/main/scala/chisel3/util/experimental/ForceNames.scala10
-rw-r--r--src/main/scala/chisel3/util/experimental/Inline.scala4
-rw-r--r--src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala2
-rw-r--r--src/main/scala/chisel3/util/experimental/group.scala2
-rw-r--r--src/main/scala/chisel3/verilog.scala1
15 files changed, 20 insertions, 741 deletions
diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala
index d62f2934..5a6cd3a7 100644
--- a/core/src/main/scala/chisel3/internal/Builder.scala
+++ b/core/src/main/scala/chisel3/internal/Builder.scala
@@ -725,20 +725,6 @@ private[chisel3] object Builder extends LazyLogging {
throwException(m)
}
- def getScalaMajorVersion: Int = {
- val "2" :: major :: _ :: Nil = chisel3.BuildInfo.scalaVersion.split("\\.").toList: @unchecked
- major.toInt
- }
-
- def checkScalaVersion(): Unit = {
- if (getScalaMajorVersion == 11) {
- val url = _root_.firrtl.stage.transforms.CheckScalaVersion.migrationDocumentLink
- val msg = s"Chisel 3.4 is the last version that will support Scala 2.11. " +
- s"Please upgrade to Scala 2.12. See $url"
- deprecated(msg, Some(""))
- }
- }
-
private[chisel3] def build[T <: BaseModule](
f: => T,
dynamicContext: DynamicContext,
@@ -746,7 +732,6 @@ private[chisel3] object Builder extends LazyLogging {
): (Circuit, T) = {
dynamicContextVar.withValue(Some(dynamicContext)) {
// in tiny designs/testcases that never access anything in chisel3.internal
- checkScalaVersion()
logger.info("Elaborating design...")
val mod = f
if (forceModName) { // This avoids definition name index skipping with D/I
diff --git a/plugin/README.md b/plugin/README.md
deleted file mode 100644
index 762f4822..00000000
--- a/plugin/README.md
+++ /dev/null
@@ -1,99 +0,0 @@
-# Notes on the Compiler Plug-in
-
-The Chisel plugin provides some operations that are too difficult, or not possbile,
-to implement through regular Scala code.
-
-# This documentation is for developers working on chisel internals.
-
-## Compiler plugin operations
-These are the two things that the compile plugin does.
-
-1. Automatically generates the `cloneType` methods of Bundle
-2. Changes the underlying mechanics of the `Bundle`s `elements` method in a way
-that does not require the use of **reflection**
-3. Future work: Make having a Seq[Data] in a bundle be a compiler error. See "Detecting Bundles with Seq[Data]" below.
-
-### 1. Generating `cloneType` method
-As of Mar 18, 2021, PR #1826, generating the `cloneType` method (1. above) is now the default behavior.
-The cloneType method used to be a tricky thing to write for chisel developers.
-For historical purposes, here is the flag was used to control that prior to full adoption.
-```
--P:chiselplugin:useBundlePlugin
-```
-
-### 2. Changing `Bundle#elements` method
-
-A `Bundle` has a default `elements` method that relies on **reflection**, which is slow and brittle, to access the list of
-*fields* the bundle contains.
-When enabled this second operation of the plugin examines
-the `Bundle`s AST in order to determine the fields and then re-writes the underlying code of `elements`.
-Technically, rewriting a lower level private method `_elementsImpl`.
-It is expected that the using this feature will shortly become the default.
-
->The plugin should not be enabled for the `main` chisel3 project because of internal considerations.
-> It is enabled for the `Test` section.
-
-In the meantime, advanced users can try using the feature by adding the following flag to the scalac options in their
-chisel projects.
-
-```
--P:chiselplugin:buildElementAccessor
-```
-
-For example in an `build.sbt` file adding the line
-```
-scalacOptions += "-P:chiselplugin:genBundleElements",
-```
-in the appropriate place.
-
-## Future work
-### Detecting Bundles with Seq[Data]
-Trying to have a `val Seq[Data]` (as opposed to a `val Vec[Data]` in a `Bundle` is a run time error.
-Here is a block of code that could be added to the plugin to detect this case at compile time (with some refinement in
-the detection mechanism):
-```scala
- if (member.isAccessor && typeIsSeqOfData(member.tpe) && !isIgnoreSeqInBundle(bundleSymbol)) {
- global.reporter.error(
- member.pos,
- s"Bundle.field ${bundleSymbol.name}.${member.name} cannot be a Seq[Data]. " +
- "Use Vec or MixedVec or mix in trait IgnoreSeqInBundle"
- )
- }
-```
-### Notes about working on the `_elementsImpl` generator for the plugin in `BundleComponent.scala`
-In general the easiest way to develop and debug new code in the plugin is to use `println` statements.
-Naively this can result in reams of text that can be very hard to look through.
-
-What I found to be useful was creating some wrappers for `println` that only printed when the `Bundles` had a particular name pattern.
-- Create a regular expression string in the `BundleComponent` class
-- Add a printf wrapper name `show` that checks the `Bundle`'s name against the regex
-- For recursive code in `getAllBundleFields` create a different wrapper `indentShow` that indents debug lines
-- Sprinkle calls to these wrappers as needed for debugging
-
-#### Bundle Regex
-```scala
- val bundleNameDebugRegex = "MyBundle.*"
-```
-#### Add `show` wrapper
-`show` should be inside `case bundle` block of the `transform` method in order to have access to the current `Bundle`
-
-```scala
-def show(string: => String): Unit = {
- if (bundle.symbol.name.toString.matches(bundleNameDebugRegex)) {
- println(string)
- }
-}
-```
-#### Add `indentShow` wrapper
-This method can be added into `BundleComponent.scala` in the `transform` method after `case Bundle`
-Inside of `getAllBundleFields` I added the following code that indented for each recursion up the current
-`Bundle`'s hierarchy.
-```scala
-def indentShow(s: => String): Unit = {
- val indentString = ("-" * depth) * 2 + "> "
- s.split("\n").foreach { line =>
- show(indentString + line)
- }
-}
-```
-
diff --git a/plugin/src/main/resources/scalac-plugin.xml b/plugin/src/main/resources/scalac-plugin.xml
deleted file mode 100644
index abe51d12..00000000
--- a/plugin/src/main/resources/scalac-plugin.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<plugin>
- <name>chiselplugin</name>
- <classname>chisel3.internal.plugin.ChiselPlugin</classname>
-</plugin>
diff --git a/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala b/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala
deleted file mode 100644
index f9452f5a..00000000
--- a/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala
+++ /dev/null
@@ -1,281 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-package chisel3.internal.plugin
-
-import scala.collection.mutable
-import scala.tools.nsc
-import scala.tools.nsc.{Global, Phase}
-import scala.tools.nsc.plugins.PluginComponent
-import scala.tools.nsc.symtab.Flags
-import scala.tools.nsc.transform.TypingTransformers
-
-/** Performs three operations
- * 1) Records that this plugin ran on a bundle by adding a method
- * `override protected def _usingPlugin: Boolean = true`
- * 2) Constructs a cloneType method
- * 3) Builds a `def elements` that is computed once in this plugin
- * Eliminates needing reflection to discover the hardware fields of a `Bundle`
- *
- * @param global the environment
- * @param arguments run time parameters to code
- */
-private[plugin] class BundleComponent(val global: Global, arguments: ChiselPluginArguments)
- extends PluginComponent
- with TypingTransformers {
- import global._
-
- val phaseName: String = "chiselbundlephase"
- val runsAfter: List[String] = "typer" :: Nil
- def newPhase(prev: Phase): Phase = new BundlePhase(prev)
-
- private class BundlePhase(prev: Phase) extends StdPhase(prev) {
- override def name: String = phaseName
- def apply(unit: CompilationUnit): Unit = {
- if (ChiselPlugin.runComponent(global, arguments)(unit)) {
- unit.body = new MyTypingTransformer(unit).transform(unit.body)
- }
- }
- }
-
- private class MyTypingTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
-
- def inferType(t: Tree): Type = localTyper.typed(t, nsc.Mode.TYPEmode).tpe
-
- val bundleTpe: Type = inferType(tq"chisel3.Bundle")
- val recordTpe: Type = inferType(tq"chisel3.Record")
- val autoCloneTpe: Type = inferType(tq"chisel3.experimental.AutoCloneType")
- val dataTpe: Type = inferType(tq"chisel3.Data")
- val ignoreSeqTpe: Type = inferType(tq"chisel3.IgnoreSeqInBundle")
- val seqOfDataTpe: Type = inferType(tq"scala.collection.Seq[chisel3.Data]")
- val someOfDataTpe: Type = inferType(tq"scala.Option[chisel3.Data]")
- val itStringAnyTpe: Type = inferType(tq"scala.collection.Iterable[(String,Any)]")
-
- // Not cached because it should only be run once per class (thus once per Type)
- def isABundle(sym: Symbol): Boolean = { sym.tpe <:< bundleTpe }
-
- def isARecord(sym: Symbol): Boolean = { sym.tpe <:< recordTpe }
-
- def isAnAutoCloneType(sym: Symbol): Boolean = { sym.tpe <:< autoCloneTpe }
-
- def isIgnoreSeqInBundle(sym: Symbol): Boolean = { sym.tpe <:< ignoreSeqTpe }
-
- def isSeqOfData(sym: Symbol): Boolean = {
- val tpe = sym.tpe
- tpe match {
- case NullaryMethodType(resultType) =>
- resultType <:< seqOfDataTpe
- case _ =>
- false
- }
- }
-
- def isOptionOfData(symbol: Symbol): Boolean = {
- val tpe = symbol.tpe
- tpe match {
- case NullaryMethodType(resultType) =>
- resultType <:< someOfDataTpe
- case _ =>
- false
- }
- }
- def isExactBundle(sym: Symbol): Boolean = { sym.tpe =:= bundleTpe }
-
- // Cached because this is run on every argument to every Bundle
- val isDataCache = new mutable.HashMap[Type, Boolean]
- def isData(sym: Symbol): Boolean = isDataCache.getOrElseUpdate(sym.tpe, sym.tpe <:< dataTpe)
-
- def cloneTypeFull(tree: Tree): Tree =
- localTyper.typed(q"chisel3.experimental.DataMirror.internal.chiselTypeClone[${tree.tpe}]($tree)")
-
- def isNullaryMethodNamed(name: String, defdef: DefDef): Boolean =
- defdef.name.decodedName.toString == name && defdef.tparams.isEmpty && defdef.vparamss.isEmpty
-
- def isVarArgs(sym: Symbol): Boolean = definitions.isRepeatedParamType(sym.tpe)
-
- def getConstructorAndParams(body: List[Tree], isBundle: Boolean): (Option[DefDef], Seq[Symbol]) = {
- val paramAccessors = mutable.ListBuffer[Symbol]()
- var primaryConstructor: Option[DefDef] = None
- body.foreach {
- case acc: ValDef if acc.symbol.isParamAccessor =>
- paramAccessors += acc.symbol
- case con: DefDef if con.symbol.isPrimaryConstructor =>
- primaryConstructor = Some(con)
- case d: DefDef if isNullaryMethodNamed("_cloneTypeImpl", d) =>
- val msg = "Users cannot override _cloneTypeImpl. Let the compiler plugin generate it."
- global.reporter.error(d.pos, msg)
- case d: DefDef if isNullaryMethodNamed("_elementsImpl", d) && isBundle =>
- val msg = "Users cannot override _elementsImpl. Let the compiler plugin generate it."
- global.reporter.error(d.pos, msg)
- case d: DefDef if isNullaryMethodNamed("_usingPlugin", d) && isBundle =>
- val msg = "Users cannot override _usingPlugin, it is for the compiler plugin's use only."
- global.reporter.error(d.pos, msg)
- case d: DefDef if isNullaryMethodNamed("cloneType", d) =>
- val prefix = if (isBundle) "Bundles" else "Records extending AutoCloneType"
- val msg = s"$prefix cannot override cloneType. Let the compiler plugin generate it."
- global.reporter.error(d.pos, msg)
- case _ =>
- }
- (primaryConstructor, paramAccessors.toList)
- }
-
- def warnOnCloneType(body: List[Tree]): Unit = {
- body.foreach {
- case d: DefDef if isNullaryMethodNamed("cloneType", d) =>
- val msg = "It is no longer necessary to implement cloneType. " +
- "Mix in chisel3.experimental.AutoCloneType to let the compiler plugin generate it. " +
- "This will become an error in Chisel 3.6."
- global.reporter.warning(d.pos, msg)
- case _ => // Do nothing
- }
- }
-
- def generateAutoCloneType(record: ClassDef, thiz: global.This, isBundle: Boolean): Option[Tree] = {
- val (con, params) = getConstructorAndParams(record.impl.body, isBundle)
- if (con.isEmpty) {
- global.reporter.warning(record.pos, "Unable to determine primary constructor!")
- return None
- }
-
- val constructor = con.get
-
- // The params have spaces after them (Scalac implementation detail)
- val paramLookup: String => Symbol = params.map(sym => sym.name.toString.trim -> sym).toMap
-
- // Create a this.<ref> for each field matching order of constructor arguments
- // List of Lists because we can have multiple parameter lists
- val conArgs: List[List[Tree]] =
- constructor.vparamss.map(_.map { vp =>
- val p = paramLookup(vp.name.toString)
- // Make this.<ref>
- val select = gen.mkAttributedSelect(thiz.asInstanceOf[Tree], p)
- // Clone any Data parameters to avoid field aliasing, need full clone to include direction
- val cloned = if (isData(vp.symbol)) cloneTypeFull(select.asInstanceOf[Tree]) else select
- // Need to splat varargs
- if (isVarArgs(vp.symbol)) q"$cloned: _*" else cloned
- })
-
- val tparamList = record.tparams.map { t => Ident(t.symbol) }
- val ttpe =
- if (tparamList.nonEmpty) AppliedTypeTree(Ident(record.symbol), tparamList) else Ident(record.symbol)
- val newUntyped = New(ttpe, conArgs)
- val neww = localTyper.typed(newUntyped)
-
- // Create the symbol for the method and have it be associated with the Record class
- val cloneTypeSym =
- record.symbol.newMethod(TermName("_cloneTypeImpl"), record.symbol.pos.focus, Flag.OVERRIDE | Flag.PROTECTED)
- // Handwritten cloneTypes don't have the Method flag set, unclear if it matters
- cloneTypeSym.resetFlag(Flags.METHOD)
-
- // Need to set the return type correctly for the override to work
- // For binary compatibility reasons in 3.5, Bundles have to return chisel3.Bundle
- val returnType = if (isBundle) bundleTpe else recordTpe
- cloneTypeSym.setInfo(NullaryMethodType(returnType))
-
- Some(localTyper.typed(DefDef(cloneTypeSym, neww)))
- }
-
- def generateElements(bundle: ClassDef, thiz: global.This): Tree = {
- /* extract the true fields from the super classes a given bundle
- * depth argument can be helpful for debugging
- */
- def getAllBundleFields(bundleSymbol: Symbol, depth: Int = 0): List[(String, Tree)] = {
-
- def isBundleField(member: Symbol): Boolean = {
- if (!member.isAccessor) {
- false
- } else if (isData(member.tpe.typeSymbol)) {
- true
- } else if (isOptionOfData(member)) {
- true
- } else if (isSeqOfData(member)) {
- // This field is passed along, even though it is illegal
- // An error for this will be generated in `Bundle.elements`
- // It would be possible here to check for Seq[Data] and make a compiler error, but
- // that would be a API error difference. See reference in docs/chisel-plugin.md
- // If Bundle is subclass of IgnoreSeqInBundle then don't pass this field along
-
- !isIgnoreSeqInBundle(bundleSymbol)
- } else {
- // none of the above
- false
- }
- }
-
- val currentFields = bundleSymbol.info.members.flatMap {
-
- case member if member.isPublic =>
- if (isBundleField(member)) {
- // The params have spaces after them (Scalac implementation detail)
- Some(member.name.toString.trim -> gen.mkAttributedSelect(thiz.asInstanceOf[Tree], member))
- } else {
- None
- }
-
- case _ => None
- }.toList
-
- val allParentFields = bundleSymbol.parentSymbols.flatMap { parentSymbol =>
- val fieldsFromParent = if (depth < 1 && !isExactBundle(bundleSymbol)) {
- val foundFields = getAllBundleFields(parentSymbol, depth + 1)
- foundFields
- } else {
- List()
- }
- fieldsFromParent
- }
- allParentFields ++ currentFields
- }
-
- val elementArgs = getAllBundleFields(bundle.symbol)
-
- val elementsImplSym =
- bundle.symbol.newMethod(TermName("_elementsImpl"), bundle.symbol.pos.focus, Flag.OVERRIDE | Flag.PROTECTED)
- elementsImplSym.resetFlag(Flags.METHOD)
- elementsImplSym.setInfo(NullaryMethodType(itStringAnyTpe))
-
- val elementsImpl = localTyper.typed(
- DefDef(elementsImplSym, q"scala.collection.immutable.Vector.apply[(String, Any)](..$elementArgs)")
- )
-
- elementsImpl
- }
-
- override def transform(tree: Tree): Tree = tree match {
-
- case record: ClassDef if isARecord(record.symbol) && !record.mods.hasFlag(Flag.ABSTRACT) =>
- val isBundle: Boolean = isABundle(record.symbol)
- val isAutoCloneType: Boolean = isAnAutoCloneType(record.symbol)
-
- if (!isAutoCloneType) {
- warnOnCloneType(record.impl.body)
- // Other than warning, there is nothing to do on Records that don't mixin AutoCloneType
- return super.transform(record)
- }
-
- val thiz: global.This = gen.mkAttributedThis(record.symbol)
-
- // ==================== Generate _cloneTypeImpl ====================
- val cloneTypeImplOpt = generateAutoCloneType(record, thiz, isBundle)
-
- // ==================== Generate val elements (Bundles only) ====================
- val elementsImplOpt =
- if (isBundle && arguments.genBundleElements) Some(generateElements(record, thiz)) else None
-
- // ==================== Generate _usingPlugin ====================
- val usingPluginOpt = if (isBundle) {
- // Unclear why quasiquotes work here but didn't for cloneTypeSym, maybe they could.
- Some(localTyper.typed(q"override protected def _usingPlugin: Boolean = true"))
- } else {
- None
- }
-
- val withMethods = deriveClassDef(record) { t =>
- deriveTemplate(t)(_ ++ cloneTypeImplOpt ++ usingPluginOpt ++ elementsImplOpt)
- }
-
- super.transform(localTyper.typed(withMethods))
-
- case _ => super.transform(tree)
- }
- }
-}
diff --git a/plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala b/plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala
deleted file mode 100644
index c0efb4ed..00000000
--- a/plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala
+++ /dev/null
@@ -1,242 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-package chisel3.internal.plugin
-
-import scala.collection.mutable
-import scala.reflect.internal.Flags
-import scala.tools.nsc
-import scala.tools.nsc.{Global, Phase}
-import scala.tools.nsc.plugins.PluginComponent
-import scala.tools.nsc.transform.TypingTransformers
-
-// The component of the chisel plugin. Not sure exactly what the difference is between
-// a Plugin and a PluginComponent.
-class ChiselComponent(val global: Global, arguments: ChiselPluginArguments)
- extends PluginComponent
- with TypingTransformers {
- import global._
- val runsAfter: List[String] = List[String]("typer")
- val phaseName: String = "chiselcomponent"
- def newPhase(_prev: Phase): ChiselComponentPhase = new ChiselComponentPhase(_prev)
- class ChiselComponentPhase(prev: Phase) extends StdPhase(prev) {
- override def name: String = phaseName
- def apply(unit: CompilationUnit): Unit = {
- if (ChiselPlugin.runComponent(global, arguments)(unit)) {
- unit.body = new MyTypingTransformer(unit).transform(unit.body)
- }
- }
- }
-
- class MyTypingTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
-
- private def shouldMatchGen(bases: Tree*): Type => Boolean = {
- val cache = mutable.HashMap.empty[Type, Boolean]
- val baseTypes = bases.map(inferType)
-
- // If subtype of one of the base types, it's a match!
- def terminate(t: Type): Boolean = baseTypes.exists(t <:< _)
-
- // Recurse through subtype hierarchy finding containers
- // Seen is only updated when we recurse into type parameters, thus it is typically small
- def recShouldMatch(s: Type, seen: Set[Type]): Boolean = {
- def outerMatches(t: Type): Boolean = {
- val str = t.toString
- str.startsWith("Option[") || str.startsWith("Iterable[")
- }
- if (terminate(s)) {
- true
- } else if (seen.contains(s)) {
- false
- } else if (outerMatches(s)) {
- // These are type parameters, loops *are* possible here
- recShouldMatch(s.typeArgs.head, seen + s)
- } else {
- // This is the standard inheritance hierarchy, Scalac catches loops here
- s.parents.exists(p => recShouldMatch(p, seen))
- }
- }
-
- // If doesn't match container pattern, exit early
- def earlyExit(t: Type): Boolean = {
- !(t.matchesPattern(inferType(tq"Iterable[_]")) || t.matchesPattern(inferType(tq"Option[_]")))
- }
-
- // Return function so that it captures the cache
- { q: Type =>
- cache.getOrElseUpdate(
- q, {
- // First check if a match, then check early exit, then recurse
- if (terminate(q)) {
- true
- } else if (earlyExit(q)) {
- false
- } else {
- recShouldMatch(q, Set.empty)
- }
- }
- )
- }
- }
-
- private val shouldMatchData: Type => Boolean = shouldMatchGen(tq"chisel3.Data")
- // Checking for all chisel3.internal.NamedComponents, but since it is internal, we instead have
- // to match the public subtypes
- private val shouldMatchNamedComp: Type => Boolean =
- shouldMatchGen(
- tq"chisel3.Data",
- tq"chisel3.MemBase[_]",
- tq"chisel3.VerificationStatement"
- )
- private val shouldMatchModule: Type => Boolean = shouldMatchGen(tq"chisel3.experimental.BaseModule")
- private val shouldMatchChiselPrefixed: Type => Boolean =
- shouldMatchGen(
- tq"chisel3.experimental.AffectsChiselPrefix"
- )
-
- // Given a type tree, infer the type and return it
- private def inferType(t: Tree): Type = localTyper.typed(t, nsc.Mode.TYPEmode).tpe
-
- // Indicates whether a ValDef is properly formed to get name
- private def okVal(dd: ValDef): Boolean = {
-
- // These were found through trial and error
- def okFlags(mods: Modifiers): Boolean = {
- val badFlags = Set(
- Flag.PARAM,
- Flag.SYNTHETIC,
- Flag.DEFERRED,
- Flags.TRIEDCOOKING,
- Flags.CASEACCESSOR,
- Flags.PARAMACCESSOR
- )
- badFlags.forall { x => !mods.hasFlag(x) }
- }
-
- // Ensure expression isn't null, as you can't call `null.autoName("myname")`
- val isNull = dd.rhs match {
- case Literal(Constant(null)) => true
- case _ => false
- }
-
- okFlags(dd.mods) && !isNull && dd.rhs != EmptyTree
- }
- // TODO Unify with okVal
- private def okUnapply(dd: ValDef): Boolean = {
-
- // These were found through trial and error
- def okFlags(mods: Modifiers): Boolean = {
- val badFlags = Set(
- Flag.PARAM,
- Flag.DEFERRED,
- Flags.TRIEDCOOKING,
- Flags.CASEACCESSOR,
- Flags.PARAMACCESSOR
- )
- val goodFlags = Set(
- Flag.SYNTHETIC,
- Flag.ARTIFACT
- )
- goodFlags.forall(f => mods.hasFlag(f)) && badFlags.forall(f => !mods.hasFlag(f))
- }
-
- // Ensure expression isn't null, as you can't call `null.autoName("myname")`
- val isNull = dd.rhs match {
- case Literal(Constant(null)) => true
- case _ => false
- }
- val tpe = inferType(dd.tpt)
- definitions.isTupleType(tpe) && okFlags(dd.mods) && !isNull && dd.rhs != EmptyTree
- }
-
- private def findUnapplyNames(tree: Tree): Option[List[String]] = {
- val applyArgs: Option[List[Tree]] = tree match {
- case Match(_, List(CaseDef(_, _, Apply(_, args)))) => Some(args)
- case _ => None
- }
- applyArgs.flatMap { args =>
- var ok = true
- val result = mutable.ListBuffer[String]()
- args.foreach {
- case Ident(TermName(name)) => result += name
- // Anything unexpected and we abort
- case _ => ok = false
- }
- if (ok) Some(result.toList) else None
- }
- }
-
- // Whether this val is directly enclosed by a Bundle type
- private def inBundle(dd: ValDef): Boolean = {
- dd.symbol.logicallyEnclosingMember.thisType <:< inferType(tq"chisel3.Bundle")
- }
-
- private def stringFromTermName(name: TermName): String =
- name.toString.trim() // Remove trailing space (Scalac implementation detail)
-
- // Method called by the compiler to modify source tree
- override def transform(tree: Tree): Tree = tree match {
- // Check if a subtree is a candidate
- case dd @ ValDef(mods, name, tpt, rhs) if okVal(dd) =>
- val tpe = inferType(tpt)
- val isData = shouldMatchData(tpe)
- val isNamedComp = isData || shouldMatchNamedComp(tpe)
- val isPrefixed = isNamedComp || shouldMatchChiselPrefixed(tpe)
-
- // If a Data and in a Bundle, just get the name but not a prefix
- if (isData && inBundle(dd)) {
- val str = stringFromTermName(name)
- val newRHS = transform(rhs) // chisel3.internal.plugin.autoNameRecursively
- val named = q"chisel3.internal.plugin.autoNameRecursively($str)($newRHS)"
- treeCopy.ValDef(dd, mods, name, tpt, localTyper.typed(named))
- }
- // If a Data or a Memory, get the name and a prefix
- else if (isData || isPrefixed) {
- val str = stringFromTermName(name)
- // Starting with '_' signifies a temporary, we ignore it for prefixing because we don't
- // want double "__" in names when the user is just specifying a temporary
- val prefix = if (str.head == '_') str.tail else str
- val newRHS = transform(rhs)
- val prefixed = q"chisel3.experimental.prefix.apply[$tpt](name=$prefix)(f=$newRHS)"
-
- val named =
- if (isNamedComp) {
- // Only name named components (not things that are merely prefixed)
- q"chisel3.internal.plugin.autoNameRecursively($str)($prefixed)"
- } else {
- prefixed
- }
-
- treeCopy.ValDef(dd, mods, name, tpt, localTyper.typed(named))
- }
- // If an instance, just get a name but no prefix
- else if (shouldMatchModule(tpe)) {
- val str = stringFromTermName(name)
- val newRHS = transform(rhs)
- val named = q"chisel3.internal.plugin.autoNameRecursively($str)($newRHS)"
- treeCopy.ValDef(dd, mods, name, tpt, localTyper.typed(named))
- } else {
- // Otherwise, continue
- super.transform(tree)
- }
- case dd @ ValDef(mods, name, tpt, rhs @ Match(_, _)) if okUnapply(dd) =>
- val tpe = inferType(tpt)
- val fieldsOfInterest: List[Boolean] = tpe.typeArgs.map(shouldMatchData)
- // Only transform if at least one field is of interest
- if (fieldsOfInterest.reduce(_ || _)) {
- findUnapplyNames(rhs) match {
- case Some(names) =>
- val onames: List[Option[String]] =
- fieldsOfInterest.zip(names).map { case (ok, name) => if (ok) Some(name) else None }
- val named = q"chisel3.internal.plugin.autoNameRecursivelyProduct($onames)($rhs)"
- treeCopy.ValDef(dd, mods, name, tpt, localTyper.typed(named))
- case None => // It's not clear how this could happen but we don't want to crash
- super.transform(tree)
- }
- } else {
- super.transform(tree)
- }
- // Otherwise, continue
- case _ => super.transform(tree)
- }
- }
-}
diff --git a/plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala b/plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala
deleted file mode 100644
index 9bf8c657..00000000
--- a/plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala
+++ /dev/null
@@ -1,81 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0
-
-package chisel3.internal.plugin
-
-import scala.tools.nsc
-import nsc.Global
-import nsc.plugins.{Plugin, PluginComponent}
-import scala.reflect.internal.util.NoPosition
-import scala.collection.mutable
-
-private[plugin] case class ChiselPluginArguments(
- val skipFiles: mutable.HashSet[String] = mutable.HashSet.empty,
- var genBundleElements: Boolean = false) {
- def useBundlePluginOpt = "useBundlePlugin"
- def useBundlePluginFullOpt = s"-P:${ChiselPlugin.name}:$useBundlePluginOpt"
- def genBundleElementsOpt = "genBundleElements"
- def genBundleElementsFullOpt = s"-P:${ChiselPlugin.name}:$genBundleElementsOpt"
- // Annoying because this shouldn't be used by users
- def skipFilePluginOpt = "INTERNALskipFile:"
- def skipFilePluginFullOpt = s"-P:${ChiselPlugin.name}:$skipFilePluginOpt"
-}
-
-object ChiselPlugin {
- val name = "chiselplugin"
-
- // Also logs why the component was not run
- private[plugin] def runComponent(
- global: Global,
- arguments: ChiselPluginArguments
- )(unit: global.CompilationUnit
- ): Boolean = {
- // This plugin doesn't work on Scala 2.11 nor Scala 3. Rather than complicate the sbt build flow,
- // instead we just check the version and if its an early Scala version, the plugin does nothing
- val scalaVersion = scala.util.Properties.versionNumberString.split('.')
- val scalaVersionOk = scalaVersion(0).toInt == 2 && scalaVersion(1).toInt >= 12
- val skipFile = arguments.skipFiles(unit.source.file.path)
- if (scalaVersionOk && !skipFile) {
- true
- } else {
- val reason = if (!scalaVersionOk) {
- s"invalid Scala version '${scala.util.Properties.versionNumberString}'"
- } else {
- s"file skipped via '${arguments.skipFilePluginFullOpt}'"
- }
- // Enable this with scalacOption '-Ylog:chiselbundlephase'
- global.log(s"Skipping BundleComponent on account of $reason.")
- false
- }
- }
-}
-
-// The plugin to be run by the Scala compiler during compilation of Chisel code
-class ChiselPlugin(val global: Global) extends Plugin {
- val name = ChiselPlugin.name
- val description = "Plugin for Chisel 3 Hardware Description Language"
- private val arguments = ChiselPluginArguments()
- val components: List[PluginComponent] = List[PluginComponent](
- new ChiselComponent(global, arguments),
- new BundleComponent(global, arguments)
- )
-
- override def init(options: List[String], error: String => Unit): Boolean = {
- for (option <- options) {
- if (option == arguments.useBundlePluginOpt) {
- val msg = s"'${arguments.useBundlePluginFullOpt}' is now default behavior, you can stop using the scalacOption."
- global.reporter.warning(NoPosition, msg)
- } else if (option.startsWith(arguments.skipFilePluginOpt)) {
- val filename = option.stripPrefix(arguments.skipFilePluginOpt)
- arguments.skipFiles += filename
- // Be annoying and warn because users are not supposed to use this
- val msg = s"Option -P:${ChiselPlugin.name}:$option should only be used for internal chisel3 compiler purposes!"
- global.reporter.warning(NoPosition, msg)
- } else if (option == arguments.genBundleElementsOpt) {
- arguments.genBundleElements = true
- } else {
- error(s"Option not understood: '$option'")
- }
- }
- true
- }
-}
diff --git a/src/main/scala/chisel3/stage/ChiselAnnotations.scala b/src/main/scala/chisel3/stage/ChiselAnnotations.scala
index 318945c8..8972310b 100644
--- a/src/main/scala/chisel3/stage/ChiselAnnotations.scala
+++ b/src/main/scala/chisel3/stage/ChiselAnnotations.scala
@@ -135,7 +135,7 @@ object ChiselGeneratorAnnotation extends HasShellOptions {
def apply(name: String): ChiselGeneratorAnnotation = {
val gen = () =>
try {
- Class.forName(name).asInstanceOf[Class[_ <: RawModule]].newInstance()
+ Class.forName(name).asInstanceOf[Class[? <: RawModule]].newInstance()
} catch {
case e: ClassNotFoundException =>
throw new OptionsException(s"Unable to locate module '$name'! (Did you misspell it?)", e)
diff --git a/src/main/scala/chisel3/stage/phases/Convert.scala b/src/main/scala/chisel3/stage/phases/Convert.scala
index aeeff246..41ee8226 100644
--- a/src/main/scala/chisel3/stage/phases/Convert.scala
+++ b/src/main/scala/chisel3/stage/phases/Convert.scala
@@ -31,7 +31,7 @@ class Convert extends Phase {
a.circuit.firrtlAnnotations ++
a.circuit.annotations.collect {
case anno: RunFirrtlTransform => anno.transformClass
- }.distinct.map { c: Class[_ <: Transform] => RunFirrtlTransformAnnotation(c.newInstance()) }
+ }.distinct.map { (c: Class[? <: Transform]) => RunFirrtlTransformAnnotation(c.newInstance()) }
case a => Some(a)
}
diff --git a/src/main/scala/chisel3/util/Bitwise.scala b/src/main/scala/chisel3/util/Bitwise.scala
index 4fc4d78c..5a1af691 100644
--- a/src/main/scala/chisel3/util/Bitwise.scala
+++ b/src/main/scala/chisel3/util/Bitwise.scala
@@ -24,14 +24,14 @@ object FillInterleaved {
*
* Output data-equivalent to in(size(in)-1) (n times) ## ... ## in(1) (n times) ## in(0) (n times)
*/
- def apply(@deprecatedName('n, "Chisel 3.5") n: Int, @deprecatedName('in, "Chisel 3.5") in: UInt): UInt =
+ def apply(@deprecatedName(Symbol("n"), "Chisel 3.5") n: Int, @deprecatedName(Symbol("in"), "Chisel 3.5") in: UInt): UInt =
apply(n, in.asBools)
/** Creates n repetitions of each bit of x in order.
*
* Output data-equivalent to in(size(in)-1) (n times) ## ... ## in(1) (n times) ## in(0) (n times)
*/
- def apply(@deprecatedName('n, "Chisel 3.5") n: Int, @deprecatedName('in, "Chisel 3.5") in: Seq[Bool]): UInt = Cat(
+ def apply(@deprecatedName(Symbol("n"), "Chisel 3.5") n: Int, @deprecatedName(Symbol("in"), "Chisel 3.5") in: Seq[Bool]): UInt = Cat(
in.map(Fill(n, _)).reverse
)
}
@@ -48,9 +48,9 @@ object FillInterleaved {
* }}}
*/
object PopCount {
- def apply(@deprecatedName('in, "Chisel 3.5") in: Iterable[Bool]): UInt = SeqUtils.count(in.toSeq)
+ def apply(@deprecatedName(Symbol("in"), "Chisel 3.5") in: Iterable[Bool]): UInt = SeqUtils.count(in.toSeq)
- def apply(@deprecatedName('in, "Chisel 3.5") in: Bits): UInt = apply((0 until in.getWidth).map(in(_)))
+ def apply(@deprecatedName(Symbol("in"), "Chisel 3.5") in: Bits): UInt = apply((0 until in.getWidth).map(in(_)))
}
/** Create repetitions of the input using a tree fanout topology.
@@ -68,7 +68,7 @@ object Fill {
* Output data-equivalent to x ## x ## ... ## x (n repetitions).
* @throws java.lang.IllegalArgumentException if `n` is less than zero
*/
- def apply(@deprecatedName('n, "Chisel 3.5") n: Int, @deprecatedName('x, "Chisel 3.5") x: UInt): UInt = {
+ def apply(@deprecatedName(Symbol("n"), "Chisel 3.5") n: Int, @deprecatedName(Symbol("x"), "Chisel 3.5") x: UInt): UInt = {
n match {
case _ if n < 0 => throw new IllegalArgumentException(s"n (=$n) must be nonnegative integer.")
case 0 => UInt(0.W)
@@ -114,5 +114,5 @@ object Reverse {
Cat(doit(in(half - 1, 0), half), doit(in(length - 1, half), length - half))
}
- def apply(@deprecatedName('in, "Chisel 3.5") in: UInt): UInt = doit(in, in.getWidth)
+ def apply(@deprecatedName(Symbol("in"), "Chisel 3.5") in: UInt): UInt = doit(in, in.getWidth)
}
diff --git a/src/main/scala/chisel3/util/Cat.scala b/src/main/scala/chisel3/util/Cat.scala
index 3224ec03..4f4c87ca 100644
--- a/src/main/scala/chisel3/util/Cat.scala
+++ b/src/main/scala/chisel3/util/Cat.scala
@@ -19,7 +19,7 @@ object Cat {
/** Concatenates the argument data elements, in argument order, together. The first argument
* forms the most significant bits, while the last argument forms the least significant bits.
*/
- def apply[T <: Bits](@deprecatedName('a, "Chisel 3.5") a: T, @deprecatedName('r, "Chisel 3.5") r: T*): UInt = apply(
+ def apply[T <: Bits](@deprecatedName(Symbol("a"), "Chisel 3.5") a: T, @deprecatedName(Symbol("r"), "Chisel 3.5") r: T*): UInt = apply(
a :: r.toList
)
@@ -30,5 +30,5 @@ object Cat {
* Equivalent to r(0) ## r(1) ## ... ## r(n-1).
* @note This returns a `0.U` if applied to a zero-element `Vec`.
*/
- def apply[T <: Bits](@deprecatedName('r, "Chisel 3.5") r: Seq[T]): UInt = SeqUtils.asUInt(r.reverse)
+ def apply[T <: Bits](@deprecatedName(Symbol("r"), "Chisel 3.5") r: Seq[T]): UInt = SeqUtils.asUInt(r.reverse)
}
diff --git a/src/main/scala/chisel3/util/experimental/ForceNames.scala b/src/main/scala/chisel3/util/experimental/ForceNames.scala
index 3070a210..39517e02 100644
--- a/src/main/scala/chisel3/util/experimental/ForceNames.scala
+++ b/src/main/scala/chisel3/util/experimental/ForceNames.scala
@@ -28,7 +28,7 @@ object forceName {
if (!signal.isSynthesizable) Builder.deprecated(s"Using forceName '$name' on non-hardware value $signal")
annotate(new ChiselAnnotation with RunFirrtlTransform {
def toFirrtl = ForceNameAnnotation(signal.toTarget, name)
- override def transformClass: Class[_ <: Transform] = classOf[ForceNamesTransform]
+ override def transformClass: Class[? <: Transform] = classOf[ForceNamesTransform]
})
signal
}
@@ -42,7 +42,7 @@ object forceName {
if (!signal.isSynthesizable) Builder.deprecated(s"Using forceName on non-hardware value $signal")
annotate(new ChiselAnnotation with RunFirrtlTransform {
def toFirrtl = ForceNameAnnotation(signal.toTarget, signal.toTarget.ref)
- override def transformClass: Class[_ <: Transform] = classOf[ForceNamesTransform]
+ override def transformClass: Class[? <: Transform] = classOf[ForceNamesTransform]
})
signal
}
@@ -57,7 +57,7 @@ object forceName {
val t = instance.toAbsoluteTarget
ForceNameAnnotation(t, name)
}
- override def transformClass: Class[_ <: Transform] = classOf[ForceNamesTransform]
+ override def transformClass: Class[? <: Transform] = classOf[ForceNamesTransform]
})
}
@@ -72,7 +72,7 @@ object forceName {
val t = instance.toAbsoluteTarget
ForceNameAnnotation(t, instance.instanceName)
}
- override def transformClass: Class[_ <: Transform] = classOf[ForceNamesTransform]
+ override def transformClass: Class[? <: Transform] = classOf[ForceNamesTransform]
})
}
}
@@ -132,7 +132,7 @@ private object ForceNamesTransform {
.view
.map(_.map(_.toTokens).toList)
.toList
- allInstancePaths(lookup) _
+ allInstancePaths(lookup)
}
/** Returns a function which returns all instance paths to a given IsModule
diff --git a/src/main/scala/chisel3/util/experimental/Inline.scala b/src/main/scala/chisel3/util/experimental/Inline.scala
index fd5c6aa5..e9b2cec1 100644
--- a/src/main/scala/chisel3/util/experimental/Inline.scala
+++ b/src/main/scala/chisel3/util/experimental/Inline.scala
@@ -43,7 +43,7 @@ trait InlineInstance { self: BaseModule =>
Seq(
new ChiselAnnotation with RunFirrtlTransform {
def toFirrtl: Annotation = InlineAnnotation(self.toNamed)
- def transformClass: Class[_ <: Transform] = classOf[InlineInstances]
+ def transformClass: Class[? <: Transform] = classOf[InlineInstances]
},
new ChiselAnnotation {
def toFirrtl: Annotation = NoDedupAnnotation(self.toNamed)
@@ -82,7 +82,7 @@ trait FlattenInstance { self: BaseModule =>
Seq(
new ChiselAnnotation with RunFirrtlTransform {
def toFirrtl: Annotation = FlattenAnnotation(self.toNamed)
- def transformClass: Class[_ <: Transform] = classOf[Flatten]
+ def transformClass: Class[? <: Transform] = classOf[Flatten]
},
new ChiselAnnotation {
def toFirrtl: Annotation = NoDedupAnnotation(self.toNamed)
diff --git a/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala b/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala
index 26a072f1..9004ef28 100644
--- a/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala
+++ b/src/main/scala/chisel3/util/experimental/decode/QMCMinimizer.scala
@@ -264,7 +264,7 @@ object QMCMinimizer extends Minimizer {
implicants.foreach(_.isPrime = true)
val cols = (0 to n).reverse.map(b => implicants.filter(b == _.bp.mask.bitCount))
- val mergeTable = cols.map(c => (0 to n).map(b => collection.mutable.Set(c.filter(b == _.bp.value.bitCount): _*)))
+ val mergeTable = cols.map(c => (0 to n).map(b => collection.mutable.Set(c.filter(b == _.bp.value.bitCount)*)))
// O(n ^ 3)
for (i <- 0 to n) {
diff --git a/src/main/scala/chisel3/util/experimental/group.scala b/src/main/scala/chisel3/util/experimental/group.scala
index ac687da7..faa086f1 100644
--- a/src/main/scala/chisel3/util/experimental/group.scala
+++ b/src/main/scala/chisel3/util/experimental/group.scala
@@ -58,7 +58,7 @@ object group {
annotate(new ChiselAnnotation with RunFirrtlTransform {
def toFirrtl = GroupAnnotation(components.map(_.toNamed), newModule, newInstance, outputSuffix, inputSuffix)
- override def transformClass: Class[_ <: Transform] = classOf[GroupComponents]
+ override def transformClass: Class[? <: Transform] = classOf[GroupComponents]
})
}
}
diff --git a/src/main/scala/chisel3/verilog.scala b/src/main/scala/chisel3/verilog.scala
index c301ff98..a29dd0c5 100644
--- a/src/main/scala/chisel3/verilog.scala
+++ b/src/main/scala/chisel3/verilog.scala
@@ -2,6 +2,7 @@ package chisel3
import chisel3.stage.ChiselStage
import firrtl.AnnotationSeq
+import firrtl.seqToAnnoSeq
object getVerilogString {