Boot a simulation
Introduction
There is an example hardware definition + testbench :
//Your hardware toplevel
import spinal.core._
class TopLevel extends Component {
...
}
// Your toplevel tester
import spinal.sim._
import spinal.core.sim._
object DutTests {
def main(args: Array[String]): Unit = {
SimConfig.withWave.compile(new TopLevel).doSim{ dut =>
// Simulation code here
}
}
}
Configuration
SimConfig
will return a default simulation configuration instance on which you can call multiple functions to configure your simulation:
Syntax |
Description |
---|---|
|
Enable simulation wave capture (default format) |
|
Enable simulation wave capture (VCD text format) |
|
Enable simulation wave capture (FST binary format) |
|
Specify the |
|
Enable all the RTL compilation optimizations to reduce simulation time (will increase compilation time) |
|
Change the folder where the sim files are generated |
|
Use Verilator as simulation backend (default) |
|
Use GHDL as simulation backend |
|
Use Icarus Verilog as simulation backend |
|
Use Synopsys VCS as simulation backend |
Then you can call the compile(rtl)
function to compile the hardware and warm up the simulator.
This function will return a SimCompiled
instance.
On this SimCompiled
instance you can run your simulation with the following functions:
Syntax |
Description |
---|---|
|
Run the simulation until the main thread is done (doesn’t wait on forked threads) or until all threads are stuck |
|
Run the simulation until all threads are done or stuck |
For example :
val spinalConfig = SpinalConfig(defaultClockDomainFrequency = FixedFrequency(10 MHz))
SimConfig
.withConfig(spinalConfig)
.withWave
.allOptimisation
.workspacePath("~/tmp")
.compile(new TopLevel)
.doSim { dut =>
// Simulation code here
}
Note that by default, the simulation files will be placed into the simWorkspace/xxx
folders. You can override the simWorkspace location by setting the SPINALSIM_WORKSPACE
environnement variable.
Running multiple tests on the same hardware
val compiled = SimConfig.withWave.compile(new Dut)
compiled.doSim("testA") { dut =>
// Simulation code here
}
compiled.doSim("testB") { dut =>
// Simulation code here
}
Throw Success or Failure of the simulation from a thread
At any moment during a simulation you can call simSuccess
or simFailure
to end it.
It is possible to make a simulation fail when it is too long, for instance because the test-bench is waiting for a condition which never occurs. To do so, call SimTimeout(maxDuration)
where maxDuration
is the time (in simulation units of time) after the which the simulation should be considered to have failed.
For instance, to make the simulation fail after 1000 times the duration of a clock cycle:
val period = 10
dut.clockDomain.forkStimulus(period)
SimTimeout(1000 * period)