Skip to content

Commit 0070570

Browse files
Fix ModuleChoice under D/I (#4569)
* Use FileCheck in ModuleChoice tests; add a test * DRY out module definitions in ModuleChoiceSpec * Add a ModuleChoice test using Definition * Ensure Groups are propagated to parent builder under D/I
1 parent bd64d80 commit 0070570

File tree

2 files changed

+71
-62
lines changed

2 files changed

+71
-62
lines changed

core/src/main/scala/chisel3/experimental/hierarchy/core/Definition.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ object Definition extends SourceInfoDoc {
126126
Builder.components ++= ir.components
127127
Builder.annotations ++= ir.annotations: @nowarn // this will go away when firrtl is merged
128128
Builder.layers ++= dynamicContext.layers
129+
Builder.options ++= dynamicContext.options
129130
module._circuit = Builder.currentModule
130131
module.toDefinition
131132
}

src/test/scala/chiselTests/ModuleChoiceSpec.scala

Lines changed: 70 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package chiselTests
55
import chisel3._
66
import chisel3.choice.{Case, Group, ModuleChoice}
77
import chiselTests.{ChiselFlatSpec, MatchesAndOmits, Utils}
8+
import chisel3.experimental.hierarchy.Definition
89
import _root_.circt.stage.ChiselStage
910

1011
object Platform extends Group {
@@ -17,54 +18,69 @@ class TargetIO(width: Int) extends Bundle {
1718
val out = UInt(width.W)
1819
}
1920

20-
class FPGATarget extends FixedIOExtModule[TargetIO](new TargetIO(8))
21+
class FPGATarget extends FixedIORawModule[TargetIO](new TargetIO(8)) {
22+
io.out := io.in
23+
}
2124

2225
class ASICTarget extends FixedIOExtModule[TargetIO](new TargetIO(8))
2326

24-
class VerifTarget extends FixedIORawModule[TargetIO](new TargetIO(8))
27+
class VerifTarget extends FixedIORawModule[TargetIO](new TargetIO(8)) {
28+
io.out := io.in
29+
}
2530

26-
class ModuleChoiceSpec extends ChiselFlatSpec with Utils with MatchesAndOmits {
27-
it should "emit options and cases" in {
28-
class ModuleWithChoice extends Module {
29-
val out = IO(UInt(8.W))
31+
class ModuleWithChoice[T <: Data](
32+
default: => FixedIOBaseModule[T]
33+
)(alternateImpls: Seq[(Case, () => FixedIOBaseModule[T])])
34+
extends Module {
35+
val inst = ModuleChoice(default)(alternateImpls)
36+
val io = IO(inst.cloneType)
37+
io <> inst
38+
}
3039

31-
val inst =
32-
ModuleChoice(new VerifTarget)(Seq(Platform.FPGA -> new FPGATarget, Platform.ASIC -> new ASICTarget))
40+
class ModuleChoiceSpec extends ChiselFlatSpec with Utils with FileCheck {
41+
it should "emit options and cases" in {
42+
class ModuleWithValidChoices
43+
extends ModuleWithChoice(new VerifTarget)(Seq(Platform.FPGA -> new FPGATarget, Platform.ASIC -> new ASICTarget))
44+
45+
generateFirrtlAndFileCheck(new ModuleWithValidChoices)(
46+
"""|CHECK: option Platform :
47+
|CHECK-NEXT: FPGA
48+
|CHECK-NEXT: ASIC
49+
|CHECK: instchoice inst of VerifTarget, Platform :
50+
|CHECK-NEXT: FPGA => FPGATarget
51+
|CHECK-NEXT: ASIC => ASICTarget""".stripMargin
52+
)
53+
}
3354

34-
inst.in := 42.U(8.W)
35-
out := inst.out
55+
it should "emit options and cases for Modules including definitions" in {
56+
class ModuleWithValidChoices
57+
extends ModuleWithChoice(new VerifTarget)(Seq(Platform.FPGA -> new FPGATarget, Platform.ASIC -> new ASICTarget))
58+
class TopWithDefinition extends Module {
59+
val definitionWithChoice = Definition(new ModuleWithValidChoices)
3660
}
3761

38-
val chirrtl = ChiselStage.emitCHIRRTL(new ModuleWithChoice, Array("--full-stacktrace"))
39-
40-
info("CHIRRTL emission looks correct")
41-
matchesAndOmits(chirrtl)(
42-
"option Platform :",
43-
"FPGA",
44-
"ASIC",
45-
"instchoice inst of VerifTarget, Platform :",
46-
"FPGA => FPGATarget",
47-
"ASIC => ASICTarget"
48-
)()
62+
generateFirrtlAndFileCheck(new TopWithDefinition)(
63+
"""|CHECK: option Platform :
64+
|CHECK-NEXT: FPGA
65+
|CHECK-NEXT: ASIC
66+
|CHECK: instchoice inst of VerifTarget, Platform :
67+
|CHECK-NEXT: FPGA => FPGATarget
68+
|CHECK-NEXT: ASIC => ASICTarget""".stripMargin
69+
)
4970
}
5071

5172
it should "require that all cases are part of the same option" in {
5273

53-
class MixedOptions extends Module {
54-
object Performance extends Group {
55-
object Fast extends Case
56-
object Small extends Case
57-
}
58-
59-
val out = IO(UInt(8.W))
60-
61-
val inst =
62-
ModuleChoice(new VerifTarget)(Seq(Platform.FPGA -> new FPGATarget, Performance.Fast -> new ASICTarget))
63-
64-
inst.in := 42.U(8.W)
65-
out := inst.out
74+
object Performance extends Group {
75+
object Fast extends Case
76+
object Small extends Case
6677
}
6778

79+
class MixedOptions
80+
extends ModuleWithChoice(new VerifTarget)(
81+
Seq(Platform.FPGA -> new FPGATarget, Performance.Fast -> new ASICTarget)
82+
)
83+
6884
intercept[IllegalArgumentException] { ChiselStage.emitCHIRRTL(new MixedOptions) }.getMessage() should include(
6985
"cannot mix choices from different groups: Platform, Performance"
7086
)
@@ -73,33 +89,33 @@ class ModuleChoiceSpec extends ChiselFlatSpec with Utils with MatchesAndOmits {
7389

7490
it should "require that at least one alternative is present" in {
7591

76-
class MixedOptions extends Module {
77-
val out = IO(UInt(8.W))
78-
79-
val inst =
80-
ModuleChoice(new VerifTarget)(Seq())
92+
class NoAlternatives extends ModuleWithChoice(new VerifTarget)(Seq())
8193

82-
inst.in := 42.U(8.W)
83-
out := inst.out
84-
}
85-
86-
intercept[IllegalArgumentException] { ChiselStage.emitCHIRRTL(new MixedOptions) }.getMessage() should include(
94+
intercept[IllegalArgumentException] { ChiselStage.emitCHIRRTL(new NoAlternatives) }.getMessage() should include(
8795
"at least one alternative must be specified"
8896
)
8997

9098
}
9199

92-
it should "require that all cases are distinct" in {
100+
it should "allow a subset of options to be provided" in {
101+
102+
class SubsetOptions extends ModuleWithChoice(new VerifTarget)(Seq(Platform.FPGA -> new FPGATarget))
93103

94-
class MixedOptions extends Module {
95-
val out = IO(UInt(8.W))
104+
// Note, because of a quirk in how [[Case]]s are registered, only those referenced
105+
// in the Module here are going to be captured. This will be fixed in a forthcoming PR
106+
// that implements an [[addLayer]] like feature for [[Group]]s
107+
generateFirrtlAndFileCheck(new SubsetOptions)(
108+
"""|CHECK: option Platform :
109+
|CHECK-NEXT: FPGA
110+
|CHECK: instchoice inst of VerifTarget, Platform :
111+
|CHECK-NEXT: FPGA => FPGATarget""".stripMargin
112+
)
113+
}
96114

97-
val inst =
98-
ModuleChoice(new VerifTarget)(Seq(Platform.FPGA -> new FPGATarget, Platform.FPGA -> new ASICTarget))
115+
it should "require that all cases are distinct" in {
99116

100-
inst.in := 42.U(8.W)
101-
out := inst.out
102-
}
117+
class MixedOptions
118+
extends ModuleWithChoice(new VerifTarget)(Seq(Platform.FPGA -> new FPGATarget, Platform.FPGA -> new ASICTarget))
103119

104120
intercept[IllegalArgumentException] { ChiselStage.emitCHIRRTL(new MixedOptions) }.getMessage() should include(
105121
"duplicate case 'FPGA'"
@@ -109,17 +125,9 @@ class ModuleChoiceSpec extends ChiselFlatSpec with Utils with MatchesAndOmits {
109125

110126
it should "require that all IO bundles are type equivalent" in {
111127

112-
class MixedIO extends Module {
113-
val out = IO(UInt(8.W))
128+
class Target16 extends FixedIOExtModule[TargetIO](new TargetIO(16))
114129

115-
class Target16 extends FixedIOExtModule[TargetIO](new TargetIO(16))
116-
117-
val inst =
118-
ModuleChoice(new VerifTarget)(Seq(Platform.FPGA -> new Target16))
119-
120-
inst.in := 42.U(8.W)
121-
out := inst.out
122-
}
130+
class MixedIO extends ModuleWithChoice(new VerifTarget)(Seq(Platform.FPGA -> new Target16))
123131

124132
intercept[ChiselException] { ChiselStage.emitCHIRRTL(new MixedIO, Array("--throw-on-first-error")) }
125133
.getMessage() should include(

0 commit comments

Comments
 (0)