Skip to content

Commit bc063c0

Browse files
committed
[ChiselSim] Add inline layer control
Extend ChiselSim with the ability to control inline layers. This requires untangling some of the way that compilation settings are passed into a `Simulator` because these options need to be added to after Chisel elaboration. E.g., to enable all inline layers, this requires knowing all the layers that were created. This didn't come up previously with extract layers as all layer files could be blindly included for this case. In susbequent commits, I will cleanup the way that extract layers work to use the same code that is introduced here. Signed-off-by: Schuyler Eldridge <[email protected]>
1 parent 71239a4 commit bc063c0

File tree

4 files changed

+93
-33
lines changed

4 files changed

+93
-33
lines changed

src/main/scala-2/chisel3/simulator/EphemeralSimulator.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ object EphemeralSimulator extends PeekPokeAPI {
2323
layerControl: LayerControl.Type = LayerControl.EnableAll
2424
)(body: (T) => Unit
2525
): Unit = {
26-
makeSimulator(layerControl).simulate(module)({ module => body(module.wrapped) }).result
26+
makeSimulator(layerControl).simulate(module, layerControl)({ module => body(module.wrapped) }).result
2727
}
2828

2929
private class DefaultSimulator(val workspacePath: String, layerControl: LayerControl.Type)

src/main/scala-2/chisel3/simulator/Simulator.scala

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,16 @@ trait Simulator {
9999
def customSimulationWorkingDirectory: Option[String] = None
100100
def verbose: Boolean = false
101101
def firtoolArgs: Seq[String] = Seq()
102+
def commonCompilationSettings: CommonCompilationSettings
102103

103-
private[simulator] def processBackends(processor: Simulator.BackendProcessor): Unit
104+
private[simulator] def processBackends(
105+
processor: Simulator.BackendProcessor,
106+
commonCompilationSettings: CommonCompilationSettings
107+
): Unit
104108
private[simulator] def _simulate[T <: RawModule, U](
105-
module: => T
106-
)(body: (SimulatedModule[T]) => U
109+
module: => T,
110+
layerControl: LayerControl.Type
111+
)(body: (SimulatedModule[T]) => U
107112
): Seq[Simulator.BackendInvocationDigest[U]] = {
108113
val workspace = new Workspace(path = workspacePath, workingDirectoryPrefix = workingDirectoryPrefix)
109114
workspace.reset()
@@ -120,7 +125,13 @@ trait Simulator {
120125
outcome
121126
}
122127
)
123-
processBackends(compiler)
128+
129+
processBackends(
130+
compiler,
131+
commonCompilationSettings.copy(verilogPreprocessorDefines =
132+
commonCompilationSettings.verilogPreprocessorDefines ++ layerControl.preprocessorDefines(elaboratedModule)
133+
)
134+
)
124135
compiler.results.toSeq
125136
}
126137
}
@@ -129,10 +140,11 @@ trait MultiBackendSimulator extends Simulator {
129140
def processBackends(processor: Simulator.BackendProcessor): Unit
130141

131142
def simulate[T <: RawModule, U](
132-
module: => T
133-
)(body: (SimulatedModule[T]) => U
143+
module: => T,
144+
layerControl: LayerControl.Type = LayerControl.EnableAll
145+
)(body: (SimulatedModule[T]) => U
134146
): Seq[Simulator.BackendInvocationDigest[U]] = {
135-
_simulate(module)(body)
147+
_simulate(module, layerControl)(body)
136148
}
137149
}
138150

@@ -142,15 +154,19 @@ trait SingleBackendSimulator[T <: Backend] extends Simulator {
142154
def commonCompilationSettings: CommonCompilationSettings
143155
def backendSpecificCompilationSettings: backend.CompilationSettings
144156

145-
final def processBackends(processor: Simulator.BackendProcessor): Unit = {
157+
final def processBackends(
158+
processor: Simulator.BackendProcessor,
159+
commonCompilationSettings: CommonCompilationSettings
160+
): Unit = {
146161
processor.process(backend)(tag, commonCompilationSettings, backendSpecificCompilationSettings)
147162
}
148163

149164
def simulate[T <: RawModule, U](
150-
module: => T
151-
)(body: (SimulatedModule[T]) => U
165+
module: => T,
166+
layerControl: LayerControl.Type = LayerControl.EnableAll
167+
)(body: (SimulatedModule[T]) => U
152168
): Simulator.BackendInvocationDigest[U] = {
153-
_simulate(module)(body).head
169+
_simulate(module, layerControl)(body).head
154170
}
155171

156172
}

src/test/scala/chiselTests/ChiselSpec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ trait ChiselRunners extends Assertions {
6161
VerilogPreprocessorDefine("ASSERT_VERBOSE_COND", s"!${Workspace.testbenchModuleName}.reset"),
6262
VerilogPreprocessorDefine("PRINTF_COND", s"!${Workspace.testbenchModuleName}.reset"),
6363
VerilogPreprocessorDefine("STOP_COND", s"!${Workspace.testbenchModuleName}.reset")
64-
),
64+
) ++ layerControl.preprocessorDefines(elaboratedModule),
6565
includeDirs = Some(Seq(workspace.primarySourcesPath)),
6666
fileFilter = layerControl.filter
6767
)

src/test/scala/chiselTests/simulator/EphemeraSimulatorSpec.scala

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,37 +24,81 @@ class EphemeralSimulatorSpec extends AnyFunSpec with Matchers {
2424
}
2525
}
2626
describe("layer control functionality") {
27-
object A extends Layer(LayerConfig.Extract())
28-
class Foo extends Module {
29-
block(A) {
30-
chisel3.assert(false.B)
27+
describe("for extract layers") {
28+
object A extends Layer(LayerConfig.Extract())
29+
class Foo extends Module {
30+
block(A) {
31+
chisel3.assert(false.B)
32+
}
3133
}
32-
}
33-
it("should enable all layers by default") {
34-
intercept[svsim.Simulation.UnexpectedEndOfMessages.type] {
35-
simulate(new Foo) { dut =>
36-
dut.clock.step()
34+
it("should enable all layers by default") {
35+
intercept[svsim.Simulation.UnexpectedEndOfMessages.type] {
36+
simulate(new Foo) { dut =>
37+
dut.clock.step()
38+
}
3739
}
3840
}
39-
}
40-
it("should enable all layers when provied with EnableAll") {
41-
intercept[svsim.Simulation.UnexpectedEndOfMessages.type] {
42-
simulate(new Foo, layerControl = LayerControl.EnableAll) { dut =>
41+
it("should enable all layers when provied with EnableAll") {
42+
intercept[svsim.Simulation.UnexpectedEndOfMessages.type] {
43+
simulate(new Foo, layerControl = LayerControl.EnableAll) { dut =>
44+
dut.clock.step()
45+
}
46+
}
47+
}
48+
it("should disable all layers when provided with Enable()") {
49+
simulate(new Foo, layerControl = LayerControl.Enable()) { dut =>
4350
dut.clock.step()
4451
}
4552
}
46-
}
47-
it("should disable all layers when provided with Enable()") {
48-
simulate(new Foo, layerControl = LayerControl.Enable()) { dut =>
49-
dut.clock.step()
53+
it("should enable specific layers with Enable") {
54+
intercept[svsim.Simulation.UnexpectedEndOfMessages.type] {
55+
simulate(new Foo, layerControl = LayerControl.Enable(A)) { dut =>
56+
dut.clock.step()
57+
}
58+
}
5059
}
5160
}
52-
it("should enable specific layers with Enable") {
53-
intercept[svsim.Simulation.UnexpectedEndOfMessages.type] {
54-
simulate(new Foo, layerControl = LayerControl.Enable(A)) { dut =>
61+
describe("for inline layers") {
62+
object A extends Layer(LayerConfig.Inline)
63+
object B extends Layer(LayerConfig.Inline)
64+
class Foo extends Module {
65+
block(A) {
66+
chisel3.assert(false.B)
67+
}
68+
}
69+
it("should enable all layers by default") {
70+
intercept[svsim.Simulation.UnexpectedEndOfMessages.type] {
71+
simulate(new Foo) { dut =>
72+
dut.clock.step()
73+
}
74+
}
75+
}
76+
it("should enable all layers when provied with EnableAll") {
77+
intercept[svsim.Simulation.UnexpectedEndOfMessages.type] {
78+
simulate(new Foo, layerControl = LayerControl.EnableAll) { dut =>
79+
dut.clock.step()
80+
}
81+
}
82+
}
83+
it("should disable all layers when provided with Enable()") {
84+
simulate(new Foo, layerControl = LayerControl.Enable()) { dut =>
5585
dut.clock.step()
5686
}
5787
}
88+
it("should enable specific layers with Enable") {
89+
intercept[svsim.Simulation.UnexpectedEndOfMessages.type] {
90+
simulate(new Foo, layerControl = LayerControl.Enable(A)) { dut =>
91+
dut.clock.step()
92+
}
93+
}
94+
}
95+
it("should error if an enabled layer does not exist") {
96+
intercept[IllegalArgumentException] {
97+
simulate(new Foo, layerControl = LayerControl.Enable(B)) { dut =>
98+
dut.clock.step()
99+
}
100+
}.getMessage() must include("cannot enable layer 'B' as it is not one of the defined layers")
101+
}
58102
}
59103
}
60104
}

0 commit comments

Comments
 (0)