diff options
| author | Adam Izraelevitz | 2021-09-05 12:11:32 -0700 |
|---|---|---|
| committer | GitHub | 2021-09-05 12:11:32 -0700 |
| commit | 9fa8da227569455a77596355aeb114f9c164510a (patch) | |
| tree | 3be3dd579fcc7ae83297d3c28020e97417a6b984 /macros/src/main/scala/chisel3/internal/InstantiableMacro.scala | |
| parent | 7fb2c1ebc23ca07e5de6416a284e1be1b62a48ac (diff) | |
Add Definition and Instance API (#2045)
This introduces a new experimental API for module instantiation that disentagles
elaborating the definition (or implementation) from instantiation of
a given module. This solves Chisel's longstanding reliance on
"Deduplication" for generating Verilog with multiple instances of the
same module.
The new API resides in package chisel3.experimental.hierarchy. Please
see the hierarchy ScalaDoc, documentation, and tests for examples of
use.
Co-authored-by: Jack Koenig <koenig@sifive.com>
Co-authored-by: Megan Wachs <megan@sifive.com>
Co-authored-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Diffstat (limited to 'macros/src/main/scala/chisel3/internal/InstantiableMacro.scala')
| -rw-r--r-- | macros/src/main/scala/chisel3/internal/InstantiableMacro.scala | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/macros/src/main/scala/chisel3/internal/InstantiableMacro.scala b/macros/src/main/scala/chisel3/internal/InstantiableMacro.scala new file mode 100644 index 00000000..1d374198 --- /dev/null +++ b/macros/src/main/scala/chisel3/internal/InstantiableMacro.scala @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.internal + +import scala.language.experimental.macros +import scala.annotation.StaticAnnotation +import scala.reflect.macros.whitebox + + +private[chisel3] object instantiableMacro { + + def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = { + import c.universe._ + def processBody(stats: Seq[Tree]): (Seq[Tree], Iterable[Tree]) = { + val extensions = scala.collection.mutable.ArrayBuffer.empty[Tree] + extensions += q"implicit val mg = new chisel3.internal.MacroGenerated{}" + val resultStats = stats.flatMap { + case x @ q"@public val $tpname: $tpe = $name" if tpname.toString() == name.toString() => + extensions += atPos(x.pos)(q"def $tpname = module._lookup(_.$tpname)") + Nil + case x @ q"@public val $tpname: $tpe = $_" => + extensions += atPos(x.pos)(q"def $tpname = module._lookup(_.$tpname)") + Seq(x) + case x @ q"@public lazy val $tpname: $tpe = $_" => + extensions += atPos(x.pos)(q"def $tpname = module._lookup(_.$tpname)") + Seq(x) + case other => Seq(other) + } + (resultStats, extensions) + } + val result = { + val (clz, objOpt) = annottees.map(_.tree).toList match { + case Seq(c, o) => (c, Some(o)) + case Seq(c) => (c, None) + } + val (newClz, implicitClzs, tpname) = clz match { + case q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }" => + val defname = TypeName(tpname + c.freshName()) + val instname = TypeName(tpname + c.freshName()) + val (newStats, extensions) = processBody(stats) + (q""" $mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents with chisel3.experimental.hierarchy.IsInstantiable { $self => ..$newStats } """, + Seq(q"""implicit class $defname(module: chisel3.experimental.hierarchy.Definition[$tpname]) { ..$extensions }""", + q"""implicit class $instname(module: chisel3.experimental.hierarchy.Instance[$tpname]) { ..$extensions } """), + tpname) + case q"$mods trait $tpname[..$tparams] extends { ..$earlydefns } with ..$parents { $self => ..$stats }" => + val defname = TypeName(tpname + c.freshName()) + val instname = TypeName(tpname + c.freshName()) + val (newStats, extensions) = processBody(stats) + (q"$mods trait $tpname[..$tparams] extends { ..$earlydefns } with ..$parents with chisel3.experimental.hierarchy.IsInstantiable { $self => ..$newStats }", + Seq(q"""implicit class $defname(module: chisel3.experimental.hierarchy.Definition[$tpname]) { ..$extensions }""", + q"""implicit class $instname(module: chisel3.experimental.hierarchy.Instance[$tpname]) { ..$extensions } """), + tpname) + } + val newObj = objOpt match { + case None => q"""object ${tpname.toTermName} { ..$implicitClzs } """ + case Some(obj @ q"$mods object $tname extends { ..$earlydefns } with ..$parents { $self => ..$body }") => + q""" + $mods object $tname extends { ..$earlydefns } with ..$parents { $self => + ..$implicitClzs + ..$body + } + """ + } + q""" + $newClz + + $newObj + """ + } + c.Expr[Any](result) + } +} + +private[chisel3] class instantiable extends StaticAnnotation { + def macroTransform(annottees: Any*): Any = macro instantiableMacro.impl +} +private[chisel3] class public extends StaticAnnotation |
