How to emit vcd file when using chisel3.simulator
for testing?
#3957
-
I'm using chisel version // TopTest.scala
package test
import Serial.Top
import chisel3._
import chisel3.simulator.EphemeralSimulator._
import org.scalatest.flatspec.AnyFlatSpec
class TopSpec extends AnyFlatSpec {
behavior of "Top"
it should "do something" in {
simulate(new Top) { top =>
top.clock.step(1)
top.io.rxWire.poke(true.B)
top.clock.step(1)
top.io.rxWire.poke(false.B)
top.clock.step(1)
}
}
} But I cannot find any vcd file generated when Is there anything I am missing? I guess it is related with #3952? |
Beta Was this translation helpful? Give feedback.
Replies: 7 comments 1 reply
-
I was also looking for an answer and here is what I have found: Currently it is not possible to dump vcd files without extending the existing simulator. Existing one is EphemeralSimulator object which uses a DefaultSimulator class which extends SingleBackendSimulator with a verilator.Backend. In the DefaultSimulator class, the backendSpecificCompilationSettings is set to verilator.Backend.CompilationSettings(), which is the default settings. To enable VCD generation, you would need to modify these settings to include:
However, the DefaultSimulator class is private and its settings are not exposed for modification. Therefore, you might need to create your own simulator class that extends SingleBackendSimulator and allows you to specify your own backendSpecificCompilationSettings. It is unfortunate that chisel-template is using svsim. Mostly new users use the template and they do not know anything about chisel test frameworks. I also assume most users expect at least a traditional testing framework that supports waveforms. So, offering a half-done simulator with a subpar functionality is doing more bad than good for the adoption of Chisel. |
Beta Was this translation helpful? Give feedback.
-
I also find a demo here: https://github.com/rameloni/tywaves-chisel-demo |
Beta Was this translation helpful? Give feedback.
-
The missing thing is an object like |
Beta Was this translation helpful? Give feedback.
-
I recently updated For general usage you can make use of While |
Beta Was this translation helpful? Give feedback.
-
Adding a solution for vanilla Chisel 6.5 if we want to avoid importing any additional libraries beyond just Chisel. |
Beta Was this translation helpful? Give feedback.
-
Does Chisel 6.x provide a way to dump a VCD file like chiseltest does? Should we import ParametricSimulator or TywavesSimulator, or continue using the hacked EphemeralSimulator? |
Beta Was this translation helpful? Give feedback.
-
There was a software architecture mistake in the design of Chiselsim in Chisel 6 which offloads this onto the user. This is fixed in the soon-to-be-relased Chisel 7. The software architecture mistake was that Chiselsim was more about providing the pieces to build a simulator as opposed to actually providing that simulator. The expectation was that different users had different testing needs and anybody using this would write their own custom simulator in their
Note 1: This approach has a lot of problems. A default simulator isn't that hard to write, so why not just put it in upstream? The wrangling of different options, environments, etc. isn't that hard, it just needs some thought. Chisel 6 ExampleIf you want to do this on Chisel 6, you can do it with a simulator like the one defined below. I'll also accept any PR that adds something like this to the Chisel 6.x branch and the Chisel //> using scala "2.13.16"
//> using repository sonatype-s01:snapshots
//> using dep "org.chipsalliance::chisel::6.7.0"
//> using plugin "org.chipsalliance:::chisel-plugin::6.7.0"
//> using options "-unchecked", "-deprecation", "-language:reflectiveCalls", "-feature", "-Xcheckinit", "-Xfatal-warnings", "-Ywarn-dead-code", "-Ywarn-unused", "-Ymacro-annotations"
import chisel3._
import chisel3.simulator.{PeekPokeAPI, SingleBackendSimulator}
import chisel3.util.Counter
import svsim.{CommonCompilationSettings, verilator}
class Foo extends Module {
val (count, done) = Counter(true.B, 8)
when(done) {
stop()
}
printf("%d\n", count)
}
object DefaultSimulator extends PeekPokeAPI {
def simulate[T <: RawModule](
module: => T,
buildDir: String,
enableWaves: Boolean = false
)(body: (T) => Unit): Unit = {
makeSimulator(buildDir, enableWaves)
.simulate(module) { module =>
module.controller.setTraceEnabled(enableWaves)
body(module.wrapped)
}
.result
}
private class DefaultSimulator(
val workspacePath: String,
enableWaves: Boolean = false
) extends SingleBackendSimulator[verilator.Backend] {
val backend = verilator.Backend.initializeFromProcessEnvironment()
val tag = "default"
val commonCompilationSettings = CommonCompilationSettings()
val backendSpecificCompilationSettings = {
val settings = verilator.Backend.CompilationSettings()
if (enableWaves) {
settings.copy(
traceStyle = Some(verilator.Backend.CompilationSettings.TraceStyle.Vcd(traceUnderscore = false))
)
} else {
settings
}
}
}
private def makeSimulator(
buildDir: String,
enableWaves: Boolean
): DefaultSimulator = {
new DefaultSimulator(buildDir, enableWaves)
}
}
import DefaultSimulator._
object Main extends App {
simulate(new Foo, buildDir = "build", enableWaves = true) { dut =>
dut.clock.step(10)
}
} If you run this, you get the following output and directory structure:
Note 2: you get both test directory permanence and a Note 3: The simulation doesn't actually terminate. This is a longstanding bug in ChiselSim that was not understood at the time. A simulation is supposed to terminate when it hits a Note 4: You don't need any external libraries or hacks to Chisel internals to do this. Chisel 7Using a recent snapshot release you can use the following: //> using scala "2.13.16"
//> using repository sonatype-s01:snapshots
//> using dep "org.chipsalliance::chisel::7.0.0-M2+588-cf353ccf-SNAPSHOT"
//> using plugin "org.chipsalliance:::chisel-plugin::7.0.0-M2+588-cf353ccf-SNAPSHOT"
//> using options "-unchecked", "-deprecation", "-language:reflectiveCalls", "-feature", "-Xcheckinit", "-Xfatal-warnings", "-Ywarn-dead-code", "-Ywarn-unused", "-Ymacro-annotations"
import chisel3._
import chisel3.simulator.ChiselSim
import chisel3.simulator.HasSimulator
import chisel3.simulator.stimulus.{ResetProcedure, RunUntilFinished}
import chisel3.util.Counter
class Foo extends Module {
val (count, done) = Counter(true.B, 8)
when(done) {
stop()
}
printf("%d\n", count)
}
object Main extends App with ChiselSim {
implicit val verilator: HasSimulator = HasSimulator.simulators
.verilator(verilatorSettings =
svsim.verilator.Backend.CompilationSettings(
traceStyle = Some(
svsim.verilator.Backend.CompilationSettings.TraceStyle
.Vcd(traceUnderscore = true, "trace.vcd")
)
)
)
simulateRaw(new Foo) { dut =>
enableWaves()
ResetProcedure.module()(dut)
RunUntilFinished(10)(dut)
}
} If you run this you get the output below and the following directory structure:
Note 5: This is using one of two Note 6: The simulation actually terminates correctly on a If you are working in the Scalatest-specific version of behavior of "Foo"
it should "finish before 10 cycles" in {
simulate(new Foo) { dut =>
RunUntilFinished(10)(dut)
}
} Then, if there was a failure, a user would run Note 7: The difference between Note 8: It's safe to use a snapshot version of Chisel and bump more frequently. We always use snapshot releases in order to get the newest features. As long as you can deal with less API stability (e.g., things which have not made it into a publicly released API may break while they are under heavy development), this may be a good option for you. We are aiming to get onto a faster release cycle for Chisel 7+ so that major releases come out more frequently. |
Beta Was this translation helpful? Give feedback.
I was also looking for an answer and here is what I have found:
Currently it is not possible to dump vcd files without extending the existing simulator. Existing one is EphemeralSimulator object which uses a DefaultSimulator class which extends SingleBackendSimulator with a verilator.Backend.
https://github.com/chipsalliance/chisel/blob/ce05462c239deec8aee0704efbd3a71e8b64ec49/src/main/scala/chisel3/simulator/EphemeralSimulator.scala
In the DefaultSimulator class, the backendSpecificCompilationSettings is set to verilator.Backend.CompilationSettings(), which is the default settings. To enable VCD generation, you would need to modify these settings to include: