Skip to content

Commit 7a3226b

Browse files
authored
Fix @public constructor vals in Scala 2 (#5485)
1 parent fa7b9f6 commit 7a3226b

2 files changed

Lines changed: 31 additions & 10 deletions

File tree

‎macros/src/main/scala-2/chisel3/internal/InstantiableMacro.scala‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,17 @@ private[chisel3] object instantiableMacro {
1010

1111
def impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
1212
import c.universe._
13-
def processBody(stats: Seq[Tree]): (Seq[Tree], Iterable[Tree]) = {
13+
def processBody(stats: Seq[Tree], paramss: List[List[ValDef]]): (Seq[Tree], Iterable[Tree]) = {
1414
val extensions = scala.collection.mutable.ArrayBuffer.empty[Tree]
1515
extensions += q"implicit val mg: chisel3.internal.MacroGenerated = new chisel3.internal.MacroGenerated {}"
16+
paramss.flatten.foreach { param =>
17+
if (
18+
param.mods.hasFlag(c.universe.Flag.PARAMACCESSOR) &&
19+
param.mods.annotations.toString.contains("new public()")
20+
) {
21+
extensions += atPos(param.pos)(q"def ${param.name} = ___module._lookup(_.${param.name})")
22+
}
23+
}
1624
// Note the triple `_` prefixing `module` is to avoid conflicts if a user marks a 'val module'
1725
// with @public; in this case, the lookup code is ambiguous between the generated `def module`
1826
// function and the argument to the generated implicit class.
@@ -60,7 +68,7 @@ private[chisel3] object instantiableMacro {
6068
case q"$mods class $tpname[..$tparams] $ctorMods(...$paramss) extends { ..$earlydefns } with ..$parents { $self => ..$stats }" =>
6169
val defname = TypeName(tpname.toString + c.freshName())
6270
val instname = TypeName(tpname.toString + c.freshName())
63-
val (newStats, extensions) = processBody(stats)
71+
val (newStats, extensions) = processBody(stats, paramss)
6472
val argTParams = tparams.map(_.name)
6573
val allParents =
6674
if (hasIsInstantiable(parents)) parents
@@ -76,7 +84,7 @@ private[chisel3] object instantiableMacro {
7684
case q"$mods trait $tpname[..$tparams] extends { ..$earlydefns } with ..$parents { $self => ..$stats }" =>
7785
val defname = TypeName(tpname.toString + c.freshName())
7886
val instname = TypeName(tpname.toString + c.freshName())
79-
val (newStats, extensions) = processBody(stats)
87+
val (newStats, extensions) = processBody(stats, Nil)
8088
val argTParams = tparams.map(_.name)
8189
val allParents =
8290
if (hasIsInstantiable(parents)) parents

‎src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala‎

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,20 @@ class DefinitionSpec extends AnyFunSpec with Matchers with FileCheck {
549549
|""".stripMargin
550550
)
551551
}
552-
it("(3.k): should work on unimplemented vals in abstract classes/traits") {
552+
it("(3.k): should expose public constructor vals") {
553+
@instantiable
554+
class Foo(@public val x: Int, @public val y: Int = 0) extends Module
555+
class Top extends Module {
556+
val definition = Definition(new Foo(1))
557+
definition.x should be(1)
558+
definition.y should be(0)
559+
val instance = Instance(definition)
560+
instance.x should be(1)
561+
instance.y should be(0)
562+
}
563+
ChiselStage.emitCHIRRTL(new Top) should include("module Foo :")
564+
}
565+
it("(3.l): should work on unimplemented vals in abstract classes/traits") {
553566
class Top() extends Module {
554567
val i = Definition(new ConcreteHasBlah())
555568
def f(d: Definition[HasBlah]): Unit = {
@@ -566,7 +579,7 @@ class DefinitionSpec extends AnyFunSpec with Matchers with FileCheck {
566579
|""".stripMargin
567580
)
568581
}
569-
it("(3.l): should work on eithers") {
582+
it("(3.m): should work on eithers") {
570583
class Top() extends Module {
571584
val i = Definition(new HasEither())
572585
i.x.map(x => mark(x, "xright")).left.map(x => mark(x, "xleft"))
@@ -584,7 +597,7 @@ class DefinitionSpec extends AnyFunSpec with Matchers with FileCheck {
584597
|""".stripMargin
585598
)
586599
}
587-
it("(3.m): should work on tuple2") {
600+
it("(3.n): should work on tuple2") {
588601
class Top() extends Module {
589602
val i = Definition(new HasTuple2())
590603
mark(i.xy._1, "x")
@@ -602,7 +615,7 @@ class DefinitionSpec extends AnyFunSpec with Matchers with FileCheck {
602615
|""".stripMargin
603616
)
604617
}
605-
it("(3.n): should work on Mems/SyncReadMems") {
618+
it("(3.o): should work on Mems/SyncReadMems") {
606619
class Top() extends Module {
607620
val i = Definition(new HasMems())
608621
mark(i.mem, "Mem")
@@ -620,7 +633,7 @@ class DefinitionSpec extends AnyFunSpec with Matchers with FileCheck {
620633
|""".stripMargin
621634
)
622635
}
623-
it("(3.o): should not create memory ports") {
636+
it("(3.p): should not create memory ports") {
624637
class Top() extends Module {
625638
val i = Definition(new HasMems())
626639
i.mem(0) := 100.U // should be illegal!
@@ -631,7 +644,7 @@ class DefinitionSpec extends AnyFunSpec with Matchers with FileCheck {
631644
"Cannot create a memory port in a different module (Top) than where the memory is (HasMems)."
632645
)
633646
}
634-
it("(3.p): should work on HasTarget") {
647+
it("(3.q): should work on HasTarget") {
635648
class Top() extends Module {
636649
val i = Definition(new HasHasTarget)
637650
mark(i.x, "x")
@@ -645,7 +658,7 @@ class DefinitionSpec extends AnyFunSpec with Matchers with FileCheck {
645658
|""".stripMargin
646659
)
647660
}
648-
it("(3.q): should work on Tuple5 with a Module in it") {
661+
it("(3.r): should work on Tuple5 with a Module in it") {
649662
class Top() extends Module {
650663
val defn = Definition(new HasTuple5())
651664
val (3, w: UInt, "hi", inst: Instance[AddOne], l) = defn.tup

0 commit comments

Comments
 (0)