Skip to content

Commit 78ba535

Browse files
authored
[svsim] Add -j, --build-jobs, and --verilate-jobs (#5051)
Add Verilator compilation-time options to the Verilator svsim backend. This is added to workaround an issue observed internally where Verilator can crash when running with full parallelism, i.e., the default `-j 0` that was previously hard-coded in the Verilator backend. The default behavior is preserved, but users can now set `-j` OR `--build-jobs`/`--verilate-jobs` individually. Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
1 parent dd5ca2a commit 78ba535

File tree

9 files changed

+289
-26
lines changed

9 files changed

+289
-26
lines changed

src/main/scala/chisel3/simulator/HasSimulator.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ object HasSimulator {
4242
/** A [[HasSimulator]] implementation for a Verilator simulator. */
4343
def verilator(
4444
compilationSettings: svsim.CommonCompilationSettings = svsim.CommonCompilationSettings(),
45-
verilatorSettings: svsim.verilator.Backend.CompilationSettings = svsim.verilator.Backend.CompilationSettings()
45+
verilatorSettings: svsim.verilator.Backend.CompilationSettings =
46+
svsim.verilator.Backend.CompilationSettings.default
4647
): HasSimulator = new HasSimulator {
4748
override def getSimulator(implicit testingDirectory: HasTestingDirectory): Simulator[svsim.verilator.Backend] =
4849
new Simulator[svsim.verilator.Backend] {

src/main/scala/chisel3/simulator/scalatest/Cli.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ object Cli {
129129
traceSettings = options.traceSettings.copy(enableVcd = true)
130130
)
131131
case options: svsim.verilator.Backend.CompilationSettings =>
132-
options.copy(
133-
traceStyle = options.traceStyle match {
132+
options.withTraceStyle(
133+
options.traceStyle match {
134134
case None =>
135135
Some(
136136
svsim.verilator.Backend.CompilationSettings

src/test/scala-2/chiselTests/MultiClockSpec.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,9 @@ class MultiClockSpec extends AnyFlatSpec with Matchers with LogUtils with Chisel
125125

126126
it should "scope ports of memories" in {
127127
implicit val verilator = simulators
128-
.verilator(verilatorSettings = svsim.verilator.Backend.CompilationSettings(disabledWarnings = Seq("MULTIDRIVEN")))
128+
.verilator(verilatorSettings =
129+
svsim.verilator.Backend.CompilationSettings.default.withDisabledWarnings(Seq("MULTIDRIVEN"))
130+
)
129131
simulate(new MultiClockMemTest)(RunUntilFinished(21))
130132
}
131133

src/test/scala-2/chiselTests/simulator/HasSimulatorSpec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class HasSimulatorSpec extends AnyFunSpec with Matchers {
2828
override val backend = svsim.verilator.Backend.initializeFromProcessEnvironment()
2929
override val tag = "still-verilator"
3030
override val commonCompilationSettings = svsim.CommonCompilationSettings()
31-
override val backendSpecificCompilationSettings = svsim.verilator.Backend.CompilationSettings()
31+
override val backendSpecificCompilationSettings = svsim.verilator.Backend.CompilationSettings.default
3232
override val workspacePath = ""
3333
}
3434
}

src/test/scala-2/chiselTests/simulator/SimulatorSpec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class VerilatorSimulator(val workspacePath: String) extends Simulator[verilator.
1414
val backend = verilator.Backend.initializeFromProcessEnvironment()
1515
val tag = "verilator"
1616
val commonCompilationSettings = CommonCompilationSettings()
17-
val backendSpecificCompilationSettings = verilator.Backend.CompilationSettings()
17+
val backendSpecificCompilationSettings = verilator.Backend.CompilationSettings.default
1818
}
1919

2020
class SimulatorSpec extends AnyFunSpec with Matchers {

src/test/scala-2/chiselTests/simulator/scalatest/ChiselSimSpec.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ class ChiselSimSpec extends AnyFunSpec with Matchers with ChiselSim with FileChe
212212
// Return a Verilator `HasSimulator` that will dump waves to `trace.vcd`.
213213
def verilatorWithVcd = HasSimulator.simulators
214214
.verilator(verilatorSettings =
215-
svsim.verilator.Backend.CompilationSettings(
216-
traceStyle = Some(
215+
svsim.verilator.Backend.CompilationSettings.default.withTraceStyle(
216+
Some(
217217
svsim.verilator.Backend.CompilationSettings
218218
.TraceStyle(
219219
svsim.verilator.Backend.CompilationSettings.TraceKind.Vcd,
@@ -229,8 +229,8 @@ class ChiselSimSpec extends AnyFunSpec with Matchers with ChiselSim with FileChe
229229
// Return a Verilator `HasSimulator` that will dump waves to `trace.fst`.
230230
def verilatorWithFst = HasSimulator.simulators
231231
.verilator(verilatorSettings =
232-
svsim.verilator.Backend.CompilationSettings(
233-
traceStyle = Some(
232+
svsim.verilator.Backend.CompilationSettings.default.withTraceStyle(
233+
Some(
234234
svsim.verilator.Backend.CompilationSettings
235235
.TraceStyle(
236236
svsim.verilator.Backend.CompilationSettings.TraceKind.Fst(Some(2)),

svsim/src/main/scala/verilator/Backend.scala

Lines changed: 215 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ object Backend {
2222
}
2323

2424
/** FST tracing
25-
*
25+
*
2626
* @param traceThreads Enable FST waveform creation using `traceThreads` separate threads
2727
*/
2828
case class Fst(traceThreads: Option[Int] = None) extends Type {
@@ -66,17 +66,217 @@ object Backend {
6666
case object TimingEnabled extends Type
6767
case object TimingDisabled extends Type
6868
}
69+
70+
/** Control job parallelism in verilator */
71+
object Parallelism {
72+
sealed trait Type {
73+
def toCompileFlags: Seq[String]
74+
}
75+
76+
/** Apply uniform parallelism to Verilation. This maps to `-j`. */
77+
class Uniform private (num: Int) extends Type {
78+
override def toCompileFlags = Seq("-j", num.toString)
79+
80+
private def copy(num: Int): Uniform = new Uniform(num = num)
81+
82+
def withNum(num: Int): Uniform = copy(num = num)
83+
}
84+
85+
object Uniform {
86+
def default: Uniform = new Uniform(num = 0)
87+
}
88+
89+
/** Apply non-uniform parallelism to Verilation. This allows control of
90+
* `--build-jobs` and `--verilate-jobs` separately.
91+
*/
92+
class Different private (build: Option[Int], verilate: Option[Int]) extends Type {
93+
override def toCompileFlags: Seq[String] = {
94+
val buildJobs: Seq[String] = build.map(num => Seq("--build-jobs", num.toString)).toSeq.flatten
95+
val verilateJobs: Seq[String] = verilate.map(num => Seq("--verilate-jobs", num.toString)).toSeq.flatten
96+
buildJobs ++ verilateJobs
97+
}
98+
99+
private def copy(build: Option[Int] = this.build, verilate: Option[Int] = this.verilate): Different =
100+
new Different(
101+
build = build,
102+
verilate = verilate
103+
)
104+
105+
def withBuild(build: Option[Int]): Different = copy(build = build)
106+
107+
def withVerilate(verilate: Option[Int]): Different = copy(verilate = verilate)
108+
}
109+
110+
object Different {
111+
def default = new Different(build = None, verilate = None)
112+
}
113+
}
114+
115+
@deprecated("use 'CompilationSettings.default' and 'with<name>' helpers", "Chisel 7.1.0")
116+
def apply(
117+
traceStyle: Option[CompilationSettings.TraceStyle] = None,
118+
outputSplit: Option[Int] = None,
119+
outputSplitCFuncs: Option[Int] = None,
120+
disabledWarnings: Seq[String] = Seq(),
121+
disableFatalExitOnWarnings: Boolean = false,
122+
enableAllAssertions: Boolean = false,
123+
timing: Option[CompilationSettings.Timing.Type] = None
124+
): CompilationSettings = CompilationSettings(
125+
traceStyle,
126+
outputSplit,
127+
outputSplitCFuncs,
128+
disabledWarnings,
129+
disableFatalExitOnWarnings,
130+
enableAllAssertions,
131+
timing,
132+
Some(CompilationSettings.Parallelism.Uniform.default)
133+
)
134+
135+
@deprecated("avoid use of unapply", "Chisel 7.1.0")
136+
def unapply(compilationSettings: CompilationSettings): Option[
137+
(
138+
Option[CompilationSettings.TraceStyle],
139+
Option[Int],
140+
Option[Int],
141+
Seq[String],
142+
Boolean,
143+
Boolean,
144+
Option[CompilationSettings.Timing.Type]
145+
)
146+
] = Some(
147+
(
148+
compilationSettings.traceStyle,
149+
compilationSettings.outputSplit,
150+
compilationSettings.outputSplitCFuncs,
151+
compilationSettings.disabledWarnings,
152+
compilationSettings.disableFatalExitOnWarnings,
153+
compilationSettings.enableAllAssertions,
154+
compilationSettings.timing
155+
)
156+
)
157+
158+
def default: CompilationSettings = new CompilationSettings(
159+
traceStyle = None,
160+
outputSplit = None,
161+
outputSplitCFuncs = None,
162+
disabledWarnings = Seq(),
163+
disableFatalExitOnWarnings = false,
164+
enableAllAssertions = false,
165+
timing = None,
166+
parallelism = Some(CompilationSettings.Parallelism.Uniform.default)
167+
)
168+
69169
}
70170

71-
case class CompilationSettings(
72-
traceStyle: Option[CompilationSettings.TraceStyle] = None,
73-
outputSplit: Option[Int] = None,
74-
outputSplitCFuncs: Option[Int] = None,
75-
disabledWarnings: Seq[String] = Seq(),
76-
disableFatalExitOnWarnings: Boolean = false,
77-
enableAllAssertions: Boolean = false,
78-
timing: Option[CompilationSettings.Timing.Type] = None
79-
) extends svsim.Backend.Settings
171+
case class CompilationSettings private (
172+
traceStyle: Option[CompilationSettings.TraceStyle],
173+
outputSplit: Option[Int],
174+
outputSplitCFuncs: Option[Int],
175+
disabledWarnings: Seq[String],
176+
disableFatalExitOnWarnings: Boolean,
177+
enableAllAssertions: Boolean,
178+
timing: Option[CompilationSettings.Timing.Type],
179+
parallelism: Option[CompilationSettings.Parallelism.Type]
180+
) extends svsim.Backend.Settings {
181+
182+
@deprecated("use 'CompilationSettings.default' and 'with<name>' helpers", "Chisel 7.1.0")
183+
def this(
184+
traceStyle: Option[CompilationSettings.TraceStyle] = None,
185+
outputSplit: Option[Int] = None,
186+
outputSplitCFuncs: Option[Int] = None,
187+
disabledWarnings: Seq[String] = Seq(),
188+
disableFatalExitOnWarnings: Boolean = false,
189+
enableAllAssertions: Boolean = false,
190+
timing: Option[CompilationSettings.Timing.Type] = None
191+
) = this(
192+
traceStyle,
193+
outputSplit,
194+
outputSplitCFuncs,
195+
disabledWarnings,
196+
disableFatalExitOnWarnings,
197+
enableAllAssertions,
198+
timing,
199+
Some(CompilationSettings.Parallelism.Uniform.default)
200+
)
201+
202+
def _copy(
203+
traceStyle: Option[CompilationSettings.TraceStyle] = this.traceStyle,
204+
outputSplit: Option[Int] = this.outputSplit,
205+
outputSplitCFuncs: Option[Int] = this.outputSplitCFuncs,
206+
disabledWarnings: Seq[String] = this.disabledWarnings,
207+
disableFatalExitOnWarnings: Boolean = this.disableFatalExitOnWarnings,
208+
enableAllAssertions: Boolean = this.enableAllAssertions,
209+
timing: Option[CompilationSettings.Timing.Type] = this.timing,
210+
parallelism: Option[CompilationSettings.Parallelism.Type] = this.parallelism
211+
): CompilationSettings = CompilationSettings(
212+
traceStyle = traceStyle,
213+
outputSplit = outputSplit,
214+
outputSplitCFuncs = outputSplitCFuncs,
215+
disabledWarnings = disabledWarnings,
216+
disableFatalExitOnWarnings = disableFatalExitOnWarnings,
217+
enableAllAssertions = enableAllAssertions,
218+
timing = timing,
219+
parallelism = parallelism
220+
)
221+
222+
@deprecated("don't use the copy method, use 'with<name>' single setters", "Chisel 7.1.0")
223+
def copy(
224+
traceStyle: Option[CompilationSettings.TraceStyle] = this.traceStyle,
225+
outputSplit: Option[Int] = this.outputSplit,
226+
outputSplitCFuncs: Option[Int] = this.outputSplitCFuncs,
227+
disabledWarnings: Seq[String] = this.disabledWarnings,
228+
disableFatalExitOnWarnings: Boolean = this.disableFatalExitOnWarnings,
229+
enableAllAssertions: Boolean = this.enableAllAssertions,
230+
timing: Option[CompilationSettings.Timing.Type] = this.timing
231+
): CompilationSettings = _copy(
232+
traceStyle = traceStyle,
233+
outputSplit = outputSplit,
234+
outputSplitCFuncs = outputSplitCFuncs,
235+
disabledWarnings = disabledWarnings,
236+
disableFatalExitOnWarnings = disableFatalExitOnWarnings,
237+
enableAllAssertions = enableAllAssertions,
238+
timing = timing,
239+
parallelism = this.parallelism
240+
)
241+
242+
// Suppress generation of private copy with default arguments by Scala 3
243+
private def copy(
244+
traceStyle: Option[CompilationSettings.TraceStyle],
245+
outputSplit: Option[Int],
246+
outputSplitCFuncs: Option[Int],
247+
disabledWarnings: Seq[String],
248+
disableFatalExitOnWarnings: Boolean,
249+
enableAllAssertions: Boolean,
250+
timing: Option[CompilationSettings.Timing.Type],
251+
parallelism: Option[CompilationSettings.Parallelism.Type]
252+
): CompilationSettings = _copy(
253+
traceStyle = traceStyle,
254+
outputSplit = outputSplit,
255+
outputSplitCFuncs = outputSplitCFuncs,
256+
disabledWarnings = disabledWarnings,
257+
disableFatalExitOnWarnings = disableFatalExitOnWarnings,
258+
enableAllAssertions = enableAllAssertions,
259+
timing = timing,
260+
parallelism = Some(CompilationSettings.Parallelism.Uniform.default)
261+
)
262+
263+
def withTraceStyle(traceStyle: Option[CompilationSettings.TraceStyle]) = _copy(traceStyle = traceStyle)
264+
265+
def withOutputSplit(outputSplit: Option[Int]) = _copy(outputSplit = outputSplit)
266+
267+
def withOutputSplitCFuncs(outputSplitCFuncs: Option[Int]) = _copy(outputSplitCFuncs = outputSplitCFuncs)
268+
269+
def withDisabledWarnings(disabledWarnings: Seq[String]) = _copy(disabledWarnings = disabledWarnings)
270+
271+
def withDisableFatalExitOnWarnings(disableFatalExitOnWarnings: Boolean) =
272+
_copy(disableFatalExitOnWarnings = disableFatalExitOnWarnings)
273+
274+
def withEnableAllAssertions(enableAllAssertions: Boolean) = _copy(enableAllAssertions = enableAllAssertions)
275+
276+
def withTiming(timing: Option[CompilationSettings.Timing.Type]) = _copy(timing = timing)
277+
278+
def withParallelism(parallelism: Option[CompilationSettings.Parallelism.Type]) = _copy(parallelism = parallelism)
279+
}
80280

81281
def initializeFromProcessEnvironment() = {
82282
val output = mutable.ArrayBuffer.empty[String]
@@ -114,13 +314,17 @@ final class Backend(executablePath: String) extends svsim.Backend {
114314
"--cc",
115315
"--exe",
116316
"--build",
117-
"-j", "0",
118317
"-o", s"../$outputBinaryName",
119318
"--top-module", topModuleName,
120319
"--Mdir", "verilated-sources",
121320
"--assert"
122321
))
123322

323+
backendSpecificSettings.parallelism match {
324+
case Some(parallelism) => addArg(parallelism.toCompileFlags)
325+
case None => ()
326+
}
327+
124328
commonSettings.libraryExtensions.foreach { extensions =>
125329
addArg(Seq((Seq("+libext") ++ extensions).mkString("+")))
126330
}

svsim/src/test/scala/BackendSpec.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ class VerilatorSpec extends BackendSpec {
155155

156156
import verilator.Backend.CompilationSettings._
157157
val backend = CustomVerilatorBackend(verilator.Backend.initializeFromProcessEnvironment())
158-
val compilationSettings = verilator.Backend.CompilationSettings(
159-
traceStyle = Some(TraceStyle(TraceKind.Vcd, traceUnderscore = false))
158+
val compilationSettings = verilator.Backend.CompilationSettings.default.withTraceStyle(
159+
Some(TraceStyle(TraceKind.Vcd, traceUnderscore = false))
160160
)
161161
test("verilator", backend)(compilationSettings)
162162

@@ -174,7 +174,7 @@ class VerilatorSpec extends BackendSpec {
174174
)(
175175
workingDirectoryTag = "verilator",
176176
commonSettings = CommonCompilationSettings(),
177-
backendSpecificSettings = compilationSettings.copy(traceStyle = None),
177+
backendSpecificSettings = compilationSettings.withTraceStyle(None),
178178
customSimulationWorkingDirectory = None,
179179
verbose = false
180180
)
@@ -197,8 +197,8 @@ class VerilatorFstTraceSpec extends BackendSpec {
197197

198198
import verilator.Backend.CompilationSettings._
199199
val backend = CustomVerilatorBackend(verilator.Backend.initializeFromProcessEnvironment())
200-
val compilationSettings = verilator.Backend.CompilationSettings(
201-
traceStyle = Some(TraceStyle(TraceKind.Fst(), traceUnderscore = true))
200+
val compilationSettings = verilator.Backend.CompilationSettings.default.withTraceStyle(
201+
Some(TraceStyle(TraceKind.Fst(), traceUnderscore = true))
202202
)
203203
test("verilator", backend)(compilationSettings)
204204

0 commit comments

Comments
 (0)