summaryrefslogtreecommitdiff
path: root/plugin/src/main
diff options
context:
space:
mode:
authorJack2022-01-12 04:27:19 +0000
committerJack2022-01-12 04:27:19 +0000
commit29df513e348cc809876893f650af8180f0190496 (patch)
tree06daaea954b4e5af7113f06e4bdbb78b33515cb3 /plugin/src/main
parent5242ce90659decb9058ee75db56e5c188029fbf9 (diff)
parent747d16311bdf185d2e98e452b14cb5d8ccca004c (diff)
Merge branch 'master' into 3.5-release
Diffstat (limited to 'plugin/src/main')
-rw-r--r--plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala23
-rw-r--r--plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala68
-rw-r--r--plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala50
3 files changed, 83 insertions, 58 deletions
diff --git a/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala b/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala
index 67d744fc..2d3a2cae 100644
--- a/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala
+++ b/plugin/src/main/scala/chisel3/internal/plugin/BundleComponent.scala
@@ -22,20 +22,8 @@ private[plugin] class BundleComponent(val global: Global, arguments: ChiselPlugi
private class BundlePhase(prev: Phase) extends StdPhase(prev) {
override def name: String = phaseName
def apply(unit: CompilationUnit): Unit = {
- // 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
- if (scalaVersionOk && arguments.useBundlePlugin) {
+ if (ChiselPlugin.runComponent(global, arguments)(unit)) {
unit.body = new MyTypingTransformer(unit).transform(unit.body)
- } else {
- val reason = if (!scalaVersionOk) {
- s"invalid Scala version '${scala.util.Properties.versionNumberString}'"
- } else {
- s"not enabled via '${arguments.useBundlePluginFullOpt}'"
- }
- // Enable this with scalacOption '-Ylog:chiselbundlephase'
- global.log(s"Skipping BundleComponent on account of $reason.")
}
}
}
@@ -82,11 +70,9 @@ private[plugin] class BundleComponent(val global: Global, arguments: ChiselPlugi
(primaryConstructor, paramAccessors.toList)
}
-
override def transform(tree: Tree): Tree = tree match {
case bundle: ClassDef if isBundle(bundle.symbol) && !bundle.mods.hasFlag(Flag.ABSTRACT) =>
-
// ==================== Generate _cloneTypeImpl ====================
val (con, params) = getConstructorAndParams(bundle.impl.body)
if (con.isEmpty) {
@@ -111,13 +97,14 @@ private[plugin] class BundleComponent(val global: Global, arguments: ChiselPlugi
if (isData(vp.symbol)) cloneTypeFull(select) else select
})
- val tparamList = bundle.tparams.map{ t => Ident(t.symbol) }
- val ttpe = if(tparamList.nonEmpty) AppliedTypeTree(Ident(bundle.symbol), tparamList) else Ident(bundle.symbol)
+ val tparamList = bundle.tparams.map { t => Ident(t.symbol) }
+ val ttpe = if (tparamList.nonEmpty) AppliedTypeTree(Ident(bundle.symbol), tparamList) else Ident(bundle.symbol)
val newUntyped = New(ttpe, conArgs)
val neww = localTyper.typed(newUntyped)
// Create the symbol for the method and have it be associated with the Bundle class
- val cloneTypeSym = bundle.symbol.newMethod(TermName("_cloneTypeImpl"), bundle.symbol.pos.focus, Flag.OVERRIDE | Flag.PROTECTED)
+ val cloneTypeSym =
+ bundle.symbol.newMethod(TermName("_cloneTypeImpl"), bundle.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 type to chisel3.Bundle for the override to work
diff --git a/plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala b/plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala
index af22e6a7..eced652b 100644
--- a/plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala
+++ b/plugin/src/main/scala/chisel3/internal/plugin/ChiselComponent.scala
@@ -11,7 +11,9 @@ 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) extends PluginComponent with TypingTransformers {
+class ChiselComponent(val global: Global, arguments: ChiselPluginArguments)
+ extends PluginComponent
+ with TypingTransformers {
import global._
val runsAfter: List[String] = List[String]("typer")
val phaseName: String = "chiselcomponent"
@@ -19,17 +21,13 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra
class ChiselComponentPhase(prev: Phase) extends StdPhase(prev) {
override def name: String = phaseName
def apply(unit: CompilationUnit): Unit = {
- // 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('.')
- if (scalaVersion(0).toInt == 2 && scalaVersion(1).toInt >= 12) {
+ if (ChiselPlugin.runComponent(global, arguments)(unit)) {
unit.body = new MyTypingTransformer(unit).transform(unit.body)
}
}
}
- class MyTypingTransformer(unit: CompilationUnit)
- extends TypingTransformer(unit) {
+ class MyTypingTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
private def shouldMatchGen(bases: Tree*): Type => Boolean = {
val cache = mutable.HashMap.empty[Type, Boolean]
@@ -54,7 +52,7 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra
recShouldMatch(s.typeArgs.head, seen + s)
} else {
// This is the standard inheritance hierarchy, Scalac catches loops here
- s.parents.exists( p => recShouldMatch(p, seen) )
+ s.parents.exists(p => recShouldMatch(p, seen))
}
}
@@ -65,24 +63,25 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra
// 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)
+ 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")
- private val shouldMatchDataOrMem : Type => Boolean = shouldMatchGen(tq"chisel3.Data", tq"chisel3.MemBase[_]")
- private val shouldMatchModule : Type => Boolean = shouldMatchGen(tq"chisel3.experimental.BaseModule")
- private val shouldMatchInstance : Type => Boolean = shouldMatchGen(tq"chisel3.experimental.hierarchy.Instance[_]")
+ private val shouldMatchData: Type => Boolean = shouldMatchGen(tq"chisel3.Data")
+ private val shouldMatchDataOrMem: Type => Boolean = shouldMatchGen(tq"chisel3.Data", tq"chisel3.MemBase[_]")
+ private val shouldMatchModule: Type => Boolean = shouldMatchGen(tq"chisel3.experimental.BaseModule")
+ private val shouldMatchInstance: Type => Boolean = shouldMatchGen(tq"chisel3.experimental.hierarchy.Instance[_]")
// Given a type tree, infer the type and return it
private def inferType(t: Tree): Type = localTyper.typed(t, nsc.Mode.TYPEmode).tpe
@@ -100,13 +99,13 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra
Flags.CASEACCESSOR,
Flags.PARAMACCESSOR
)
- badFlags.forall{ x => !mods.hasFlag(x)}
+ 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
+ case _ => false
}
okFlags(dd.mods) && !isNull && dd.rhs != EmptyTree
@@ -133,7 +132,7 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra
// 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
+ case _ => false
}
val tpe = inferType(dd.tpt)
definitions.isTupleType(tpe) && okFlags(dd.mods) && !isNull && dd.rhs != EmptyTree
@@ -142,7 +141,7 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra
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
+ case _ => None
}
applyArgs.flatMap { args =>
var ok = true
@@ -150,7 +149,7 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra
args.foreach {
case Ident(TermName(name)) => result += name
// Anything unexpected and we abort
- case _ => ok = false
+ case _ => ok = false
}
if (ok) Some(result.toList) else None
}
@@ -172,9 +171,9 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra
// If a Data and in a Bundle, just get the name but not a prefix
if (shouldMatchData(tpe) && inBundle(dd)) {
val str = stringFromTermName(name)
- val newRHS = transform(rhs) // chisel3.internal.plugin.autoNameRecursively
+ 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)
+ treeCopy.ValDef(dd, mods, name, tpt, localTyper.typed(named))
}
// If a Data or a Memory, get the name and a prefix
else if (shouldMatchDataOrMem(tpe)) {
@@ -182,18 +181,18 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra
val newRHS = transform(rhs)
val prefixed = q"chisel3.experimental.prefix.apply[$tpt](name=$str)(f=$newRHS)"
val named = q"chisel3.internal.plugin.autoNameRecursively($str)($prefixed)"
- treeCopy.ValDef(dd, mods, name, tpt, localTyper typed named)
+ 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)
+ treeCopy.ValDef(dd, mods, name, tpt, localTyper.typed(named))
} else if (shouldMatchInstance(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)
+ treeCopy.ValDef(dd, mods, name, tpt, localTyper.typed(named))
} else {
// Otherwise, continue
super.transform(tree)
@@ -205,9 +204,10 @@ class ChiselComponent(val global: Global) extends PluginComponent with TypingTra
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 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)
+ 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)
}
diff --git a/plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala b/plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala
index 23082329..bd02d50c 100644
--- a/plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala
+++ b/plugin/src/main/scala/chisel3/internal/plugin/ChiselPlugin.scala
@@ -6,19 +6,53 @@ 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(var useBundlePlugin: Boolean = true) {
+private[plugin] case class ChiselPluginArguments(val skipFiles: mutable.HashSet[String] = mutable.HashSet.empty) {
def useBundlePluginOpt = "useBundlePlugin"
- def useBundlePluginFullOpt = s"-P:chiselplugin:$useBundlePluginOpt"
+ def useBundlePluginFullOpt = s"-P:${ChiselPlugin.name}:$useBundlePluginOpt"
+
+ // 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 compoennt 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"
+ 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),
+ new ChiselComponent(global, arguments),
new BundleComponent(global, arguments)
)
@@ -27,6 +61,12 @@ class ChiselPlugin(val global: Global) extends Plugin {
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 {
error(s"Option not understood: '$option'")
}
@@ -34,6 +74,4 @@ class ChiselPlugin(val global: Global) extends Plugin {
true
}
-
}
-