svsim is a low-level library for compiling and controlling SystemVerilog
simulations, currently targeting Verilator and VCS as backends.
In no particular order, here are some of the design considerations of svsim:
svsimdoes not know about Chisel. The inputs tosvsimare SystemVerilog files and theModuleInfoclass, which encodes all the informationsvsimneeds to generate a test harness for the suppliedSystemVerilog.svsimis not a testing framework, and is not opinionated about how a higher-level testing framework should be built.svsimshould enable SystemVerilog simulation for any testing framework and should not be tied to any particular technology (i.e. Scalatest).svsimprovides a backend-independent test harness. This means thatsvsim's generated sources are not impacted by the choice of backend and indeed can be shared between multiple backends. If backend-specific behavior is required, it is provided via a compile-time flag (such asSVSIM_BACKEND_SUPPORTS_DELAY_IN_PUBLIC_FUNCTIONS).svsimsimulations are also backend-independent, meaning that the same code launches and controls a simulation regardless of what backend it was compiled using.svsimbackends are declarative. This means a backend only controls which executable is invoked for compilation, and what arguments are provided to that executable (either via command line or environment variables). Backends may also provide arguments to the simulation, but may not have any other specialized logic.- Simulations are controlled using an ad-hoc protocol where commands are read
from
stdinand messages are written tostdout. This protocol is not meant to be an ABI, and can change freely between Chisel verisons. - Communication with the simulation is pipelined, so the Scala driver can send
multiple commands before processing responses from the simulation. This allows
svsimto effectively eliminate the overhead of communicating with the simulation without resorting to JNA or Scala-side caching. This optimization can, of course, be defeated if the driver code waits on every command, but we consider this an antipattern. svsimstrives to have the minimum amount of dependencies possible, so that it may be maximally portable.svsimdoes not provide syntactic sugar, and expects that higher level frameworks will implement whatever sugar they thing is appropriate. For example, if a framework likechiseltestwere to usesvsimunder the hood, it might choose to store theSimulation.Controllerin aDynamicValueto enable callingpeekandpokedirectly on a ChiselData, or pass information via annotations. Such specialization should stay in the higher-level framework and allsvsimAPIs should stay explicit.
We consider it a top priority to keep svsim's architecture and implementation
as simple as possible. In support of this effort, there are really only three
components to svsim:
The Workspace manages all interaction with the filesystem. Its API is mutable,
because the underlying representation (files on disk) is mutable. A Workspace
is represented on the filesystem as a folder. The reset() method will delete
any previous state and create the necessary folders. The elaborate() method
takes a ModuleInfo which describes the SystemVerilog module to be simulated.
The idea is that a higher-level framework will provide specialized elaborate
methods which emit SystemVerilog to primarySourcesPath, similar to what we do
with elaborateGCD() in src/test/scala/Resources.scala. For example, Chisel
can provide an elaborate[T <: RawModule](module: => T) method.
generateAdditionalSources() uses the ModuleInfo from elaborate and
generates the test harness. Finally, compile() uses a Backend to compile the
simulation. Because svsim's test harness is backend-independent, compile may
be called multiple times with different settings or different backends to create
multiple Simulations (a workingDirectoryTag is provided so that mutliple
simulations are output to separate directories).
The Workspace's compile method returns a Simulation instance. A
Simulation is launched using the run method, which passes a
Simulation.Controller instance to the provided closure. The
Simulation.Controller is used to explicitly control the Simulation, and
should not escape the body of the closure. Like most of svsim,
Simulation.Controller aims to be a low level API on which higher level APIs
can be built. For example, Simulation.Controller's get method does not
implicitly run the simulation to make the effects of previous set calls
visible, the way you would expect for a peek/poke test. To evaluate the
simulation state, the user must explicitly call controller.run(0). This, of
course, does not prevent a peek/poke style API from being built using these
building blocks in a higher-level framework.
svsim currently provides two Backends: verilator.Backend and
vcs.Backend. Settings which all svsim Backends must support (like
SystemVerilog preprocessor defines) live in CommonCompilationSettings, and each
backend has its own backend-specific CompilationSettings.
Because Backends are declarative, svsim is able to output a Makefile for
compiling the simulation. This Makefile can be re-invoked after the fact to
rebuild the simulation without re-running the Scala driver (make simulation).
Users are free to modify either the harness generated by svsim
(generated-sources), the SystemVerilog provided to svsim
(primary-sources), or even the arguments passed to the compiler
(workdir-$tag/Makefile) and these changes will be picked up when running make simulation.
svsim by default emits an execution-script.txt when running a Simulation.
This script captures all commands sent to the simulation, which enables svsim
to add a second target to the Makefile: make replay. make replay rebuilds
the simulation, picking up any changes as mentioned above, and then replays the
commands that were sent by Simulation.Controller verbatim. This allows
replaying most tests without having to re-run the Scala code, potentially with
manual modifications to either the SystemVerilog or the test harness (though
tests which modify their behavior based on values read from the Simulation may
not be replayed faithfully).