Skip to content

Commit

Permalink
Merge pull request #31 from rameloni/improve-parametricSimulator
Browse files Browse the repository at this point in the history
Improve parametric and tywaves simulator
  • Loading branch information
rameloni authored Jul 11, 2024
2 parents e418da6 + f6fa338 commit b56b519
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 55 deletions.
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,16 @@ simulate(
A simulation can be customized by passing some settings to the simulator. The following options can be specified
for `ParametricSimulator` and / or `TywavesSimulator` classes using the following syntax:

| Setting | Description | Simulator |
|:------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
| `VcdTrace` | Enable the VCD output optimizing out signals starting with an underscore (_) in the final verilog | `ParametricSimulator` and `TywavesSimulator` |
| `VcdTraceWithUnderscore` | Enable the VCD output (including "underscored" signals) | `ParametricSimulator` and `TywavesSimulator` |
| `SaveWorkdir` | Save the workdir of `svsim` | `ParametricSimulator` and `TywavesSimulator` |
| `SaveWorkdirFile(name: String)` | Save the workdir with a specific name | `ParametricSimulator` and `TywavesSimulator` |
| `NameTrace(name: String)` | Give a name to the VCD trace | `ParametricSimulator` and `TywavesSimulator` |
| `WithFirtoolArgs(args: Seq[String])` | Pass arguments to `firtool` under the simulation | `ParametricSimulator` and `TywavesSimulator` |
| `WithTywavesWaveforms(runWaves: Boolean)` | Enable the generation of extra debug information (to fully exploit the tywaves project) and (optionally `runWaves=true`) launch the waveform viewer directly once the simulation has been completed | `ParametricSimulator` and `TywavesSimulator` |
| Setting | Description | Simulator |
|:--------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|
| `VcdTrace` | Enable the VCD output optimizing out signals starting with an underscore (_) in the final verilog | `ParametricSimulator` and `TywavesSimulator` |
| `VcdTraceWithUnderscore` | Enable the VCD output (including "underscored" signals) | `ParametricSimulator` and `TywavesSimulator` |
| `SaveWorkdir` | Save the workdir of `svsim` | `ParametricSimulator` and `TywavesSimulator` |
| `SaveWorkdirFile(name: String)` | Save the workdir with a specific name | `ParametricSimulator` and `TywavesSimulator` |
| `NameTrace(name: String)` | Give a name to the VCD trace | `ParametricSimulator` and `TywavesSimulator` |
| `WithFirtoolArgs(args: Seq[String])` | Pass arguments to `firtool` under the simulation | `ParametricSimulator` and `TywavesSimulator` |
| `WithTywavesWaveforms(runWaves: Boolean)` | Enable the generation of extra debug information (to fully exploit the tywaves project) and (optionally `runWaves=true`) launch the waveform viewer directly once the simulation has been completed | `ParametricSimulator` and `TywavesSimulator` |
| `WithTywavesWaveformsGo(runWaves: Boolean)` | Same as `WithTywavesWaveforms` but without blocking sbt if `runWaves` is `true` | `ParametricSimulator` and `TywavesSimulator` |

> **Note**: open an issue/PR to request new settings.
Expand Down Expand Up @@ -227,7 +228,7 @@ The following list shows a summary of the features added by the Tywaves project
- [x] Selectable signal value rendering (with type information attached)
- [ ] Automatic/custom signal value rendering
- [ ] For loops code generation
- [ ] Temporary values (also inside `when` and `otherwise` blocks)
- [x] Temporary values (also inside `when` and `otherwise` blocks)

# Versioning and tools ([ref](https://github.com/rameloni/tywaves-chisel-demo/wiki/Tywaves-internals#tywaves-software-architecture))

Expand Down
2 changes: 1 addition & 1 deletion example/gcd.test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
//> using dep "org.scalatest::scalatest:3.2.18"

// DO NOT EDIT THE ORTHER OF THESE IMPORTS (it will be solved in future versions)
import chisel3._
import tywaves.simulator._
import tywaves.simulator.ParametricSimulator._
import tywaves.simulator.simulatorSettings._
import chisel3._
import circt.stage.ChiselStage
// _root_ disambiguates from package chisel3.util.circt if user imports chisel3.util._
//import _root_.circt.stage.ChiselStage
Expand Down
6 changes: 6 additions & 0 deletions example/myfsm.test.scala
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,15 @@ class MyFSMTest extends AnyFunSpec with Matchers {
circt.stage.FirtoolOption("--emit-hgldd"),
),
)
simulate(new MyFSM(), Seq(VcdTrace, WithTywavesWaveformsGo(true)), simName = "runs_MYFSM_correctly_launch_tywaves_and_go") {
fsm =>
fsm.clock.step(10)
fsm.clock.step(10)
}
simulate(new MyFSM(), Seq(VcdTrace, WithTywavesWaveforms(true)), simName = "runs_MYFSM_correctly_launch_tywaves") {
fsm =>
fsm.clock.step(10)
fsm.io.inputState.poke(MyFSMStates.StateA)
fsm.clock.step(10)
}
}
Expand Down
22 changes: 2 additions & 20 deletions src/main/scala/tywaves/simulator/ParametricSimulator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,13 @@ import java.time.{LocalDateTime, format}
*/
object ParametricSimulator extends PeekPokeAPI {

private var simulator = new ParametricSimulator

/** If true, the simulator will be reset before running each simulation */
private var _resetSimulationBeforeRun = false

/** Use this method to run a simulations */
def simulate[T <: RawModule](
module: => T,
settings: Seq[SimulatorSettings] = Seq(),
simName: String = "defaultSimulation",
)(body: T => Unit): Unit = {
if (_resetSimulationBeforeRun)
reset()
simulator.simulate(module, settings, simName)(body)
}

/**
* Use this method to manually reset the simulator and run multiple
* independent simulations
*/
def reset(): Unit =
simulator = new ParametricSimulator

def resetBeforeEachRun(): Unit =
_resetSimulationBeforeRun = true
)(body: T => Unit): Unit =
(new ParametricSimulator).simulate(module, settings, simName)(body)
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/main/scala/tywaves/simulator/TywavesInterface.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ private[tywaves] object TywavesInterface {
hglddDirPath: Option[String],
extraScopes: Seq[String],
topModuleName: Option[String],
waitFor: Boolean = true,
): Unit = {
{
import scala.sys.process._
Expand All @@ -36,6 +37,8 @@ private[tywaves] object TywavesInterface {

// Execute and return to the caller
@unused val process = new ProcessBuilder(cmd: _*).inheritIO().start()
if (waitFor)
process.waitFor()
// No wait for the process to finish
}
}
30 changes: 13 additions & 17 deletions src/main/scala/tywaves/simulator/TywavesSimulator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import tywaves.circuitmapper.TypedConverter

object TywavesSimulator extends PeekPokeAPI {

private[simulator] case class Tywaves(runWaves: Boolean) extends SimulatorSettings
val WithTywavesWaveforms: Boolean => Tywaves = (runWaves: Boolean) => Tywaves(runWaves)
private[simulator] case class Tywaves(runWaves: Boolean, waitFor: Boolean) extends SimulatorSettings

private var simulator = new TywavesSimulator
/** Generate tywaves info and optionally run the waveform */
val WithTywavesWaveforms: Boolean => Tywaves = (runWaves: Boolean) => Tywaves(runWaves, waitFor = true)

/** If true, the simulator will be reset before running each simulation */
private var _resetSimulationBeforeRun = false
/**
* Generate tywaves info and optionally run the waveform without blocking sbt
*/
val WithTywavesWaveformsGo: Boolean => Tywaves = (runWaves: Boolean) => Tywaves(runWaves, waitFor = false)

/** Use this method to run a simulation */
def simulate[T <: RawModule](
Expand Down Expand Up @@ -44,28 +46,22 @@ object TywavesSimulator extends PeekPokeAPI {
TypedConverter.createDebugInfoHgldd(() => module, simulator.wantedWorkspacePath)

// Run tywaves viewer if the Tywaves waveform generation is enabled by Tywaves(true)
if (finalSettings.contains(Tywaves(true)))
val (runWaves, waitFor) =
if (finalSettings.contains(Tywaves(runWaves = true, waitFor = true))) { (true, true) }
else if (finalSettings.contains(Tywaves(runWaves = true, waitFor = false))) { (true, false) }
else { (false, false) }
if (runWaves)
TywavesInterface.run(
vcdPath = simulator.finalTracePath.get,
hglddDirPath = Some(TypedConverter.getDebugInfoDir(gOpt = true)),
extraScopes = extraScopes,
topModuleName = TypedConverter.getTopModuleName,
waitFor = waitFor,
)
} else if (containTywaves)
throw new Exception("Tywaves waveform generation requires a trace file. Please enable VcdTrace.")

}

/**
* Use this method to manually reset the simulator and run multiple
* independent simulations
*/
@deprecated
def reset(): Unit =
simulator = new TywavesSimulator

@deprecated
def resetBeforeEachRun(): Unit =
_resetSimulationBeforeRun = true
}
class TywavesSimulator extends ParametricSimulator
29 changes: 29 additions & 0 deletions src/test/scala/tywaves/simulator/ImportSimulatorReverseOrder.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package tywaves.simulator

import gcd.GCD
import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.must.Matchers

class ImportSimulatorReverseOrder extends AnyFunSpec with Matchers {
describe("Issue 27") {
it("Should import chisel before tywaves") {
import chisel3._
import tywaves.simulator.TywavesSimulator._
simulate(new GCD()) {
gcd =>
gcd.clock.step()
gcd.io.loadValues.poke(true.B)
}
}
it("Should import chisel after tywaves") {
import tywaves.simulator.TywavesSimulator._
import chisel3._
simulate(new GCD()) {
gcd =>
gcd.clock.step()
gcd.io.loadValues.poke(true.B)
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ class ParametricSimulatorSpec extends AnyFunSpec with Matchers {

describe("ParametricSimulator Runs") {

resetBeforeEachRun()

it("runs GCD correctly without settings") {
simulate(new GCD())(gcd => gcdTb(gcd))
}
Expand Down Expand Up @@ -90,7 +88,7 @@ class ParametricSimulatorSpec extends AnyFunSpec with Matchers {
}

describe("ParametricSimulator Exceptions") {
resetBeforeEachRun()

it("throws an exception when NameTrace is used without VcdTrace or VcdTraceWithUnderscore") {
intercept[Exception] {
simulate(new GCD(), Seq(NameTrace("")))(_ => gcdTb _)
Expand Down
4 changes: 0 additions & 4 deletions src/test/scala/tywaves/simulator/TywavesSimulatorSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ class TywavesSimulatorSpec extends AnyFunSpec with Matchers {
}

describe("New TywavesFunctionalities") {
resetBeforeEachRun()

it("runs GCD with waveform generation") {
simulate(new GCD(), Seq(VcdTrace, WithTywavesWaveforms(false)), simName = "runs_gcd_with_waveform_generation") {
Expand Down Expand Up @@ -66,8 +65,6 @@ class TywavesSimulatorSpec extends AnyFunSpec with Matchers {

describe("Tywaves with ParametricSimulator Functionalities") {

resetBeforeEachRun()

it("runs GCD correctly without settings") {
simulate(new GCD())(gcd => gcdTb(gcd))
}
Expand Down Expand Up @@ -131,7 +128,6 @@ class TywavesSimulatorSpec extends AnyFunSpec with Matchers {
}

describe("TywavesSimulator Exceptions") {
resetBeforeEachRun()
it("throws an exception when NameTrace is used without VcdTrace or VcdTraceWithUnderscore") {
intercept[Exception] {
simulate(new GCD(), Seq(NameTrace("")))(_ => gcdTb _)
Expand Down

0 comments on commit b56b519

Please sign in to comment.