Skip to content

Commit

Permalink
Merge branch 'SpinalHDL:dev' into fix-verilator-v5x-win
Browse files Browse the repository at this point in the history
  • Loading branch information
du33169 authored Dec 10, 2024
2 parents 0af12b1 26d9f88 commit 7ed4035
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 62 deletions.
36 changes: 24 additions & 12 deletions core/src/main/scala/spinal/core/sim/SimBootstraps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 173,8 @@ class SpinalVpiBackendConfig[T <: Component](val rtl : SpinalRepor
val usePluginsCache : Boolean,
val pluginsCachePath : String,
val enableLogging : Boolean,
val timePrecision : TimeNumber)
val timePrecision : TimeNumber,
val testPath : String)


case class SpinalIVerilogBackendConfig[T <: Component](override val rtl : SpinalReport[T],
Expand All @@ -189,7 190,8 @@ case class SpinalIVerilogBackendConfig[T <: Component](override val rtl : Spinal
override val usePluginsCache : Boolean = true,
override val pluginsCachePath : String = "./simWorkspace/.pluginsCachePath",
override val enableLogging : Boolean = false,
override val timePrecision : TimeNumber = null) extends
override val timePrecision : TimeNumber = null,
override val testPath : String = null) extends
SpinalVpiBackendConfig[T](rtl,
waveFormat,
workspacePath,
Expand All @@ -203,7 205,8 @@ case class SpinalIVerilogBackendConfig[T <: Component](override val rtl : Spinal
usePluginsCache,
pluginsCachePath,
enableLogging,
timePrecision)
timePrecision,
testPath)


case class SpinalVCSBackendConfig[T <: Component](override val rtl : SpinalReport[T],
Expand All @@ -226,7 229,8 @@ case class SpinalVCSBackendConfig[T <: Component](override val rtl : SpinalRepor
val compileFlags : ArrayBuffer[String] = ArrayBuffer[String](),
val elaborateFlags : ArrayBuffer[String] = ArrayBuffer[String](),
val vcsCC : Option[String] = None,
val vcsLd : Option[String] = None) extends
val vcsLd : Option[String] = None,
override val testPath : String = null) extends
SpinalVpiBackendConfig[T](rtl,
waveFormat,
workspacePath,
Expand All @@ -240,7 244,8 @@ case class SpinalVCSBackendConfig[T <: Component](override val rtl : SpinalRepor
usePluginsCache,
pluginsCachePath,
enableLogging,
timePrecision)
timePrecision,
testPath)

case class SpinalGhdlBackendConfig[T <: Component](override val rtl : SpinalReport[T],
override val waveFormat : WaveFormat = WaveFormat.NONE,
Expand All @@ -256,7 261,8 @@ case class SpinalGhdlBackendConfig[T <: Component](override val rtl : SpinalRepo
override val pluginsCachePath : String = "./simWorkspace/.pluginsCachePath",
override val enableLogging : Boolean = false,
override val timePrecision : TimeNumber = null,
val ghdlFlags : GhdlFlags = GhdlFlags()
val ghdlFlags : GhdlFlags = GhdlFlags(),
override val testPath : String = null
) extends
SpinalVpiBackendConfig[T](rtl,
waveFormat,
Expand All @@ -271,7 277,8 @@ case class SpinalGhdlBackendConfig[T <: Component](override val rtl : SpinalRepo
usePluginsCache,
pluginsCachePath,
enableLogging,
timePrecision)
timePrecision,
testPath)


object SpinalGhdlBackend {
Expand All @@ -288,6 295,7 @@ object SpinalGhdlBackend {
}
vconfig.runFlags = config.runFlags.mkString(" ")
vconfig.logSimProcess = config.enableLogging
vconfig.testPath = config.testPath

val signalsCollector = SpinalVpiBackend(config, vconfig)

Expand All @@ -303,6 311,7 @@ object SpinalIVerilogBackend {
vconfig.analyzeFlags = config.simulatorFlags.mkString(" ")
vconfig.runFlags = config.simulatorFlags.mkString(" ")
vconfig.logSimProcess = config.enableLogging
vconfig.testPath = config.testPath
vconfig.timePrecision = config.timePrecision match {
case null => null
case t => t.decomposeString
Expand All @@ -328,6 337,7 @@ object SpinalVCSBackend {
vconfig.wavePrefix = config.wavePrefix
vconfig.simSetupFile = config.simSetupFile
vconfig.envSetup = config.envSetup
vconfig.testPath = config.testPath
vconfig.timePrecision = config.timePrecision match {
case null => null
case t => t.decomposeString
Expand Down Expand Up @@ -1090,14 1100,15 @@ case class SpinalSimConfig(
enableLogging = _withLogging,
usePluginsCache = !_disableCache,
timePrecision = _timePrecision,
ghdlFlags = _ghdlFlags
ghdlFlags = _ghdlFlags,
testPath = _testPath
)
val backend = SpinalGhdlBackend(vConfig)
val deltaTime = (System.nanoTime() - startAt) * 1e-6
println(f"[Progress] GHDL compilation done in $deltaTime%1.3f ms")
new SimCompiled(report, compiledPath, this){
override def newSimRaw(name: String, seed: Int): SimRaw = {
val raw = new SimVpi(backend)
val raw = new SimVpi(backend, name)
raw.userData = backend.signals
raw
}
Expand Down Expand Up @@ -1128,14 1139,15 @@ case class SpinalSimConfig(
simulatorFlags = _simulatorFlags additionalFlags,
enableLogging = _withLogging,
usePluginsCache = !_disableCache,
timePrecision = _timePrecision
timePrecision = _timePrecision,
testPath = _testPath
)
val backend = SpinalIVerilogBackend(vConfig)
val deltaTime = (System.nanoTime() - startAt) * 1e-6
println(f"[Progress] IVerilog compilation done in $deltaTime%1.3f ms")
new SimCompiled(report, compiledPath, this){
override def newSimRaw(name: String, seed: Int): SimRaw = {
val raw = new SimVpi(backend)
val raw = new SimVpi(backend, name)
raw.userData = backend.signals
raw
}
Expand Down Expand Up @@ -1164,7 1176,7 @@ case class SpinalSimConfig(
val backend = SpinalVCSBackend(vConfig)
new SimCompiled(report, compiledPath, this) {
override def newSimRaw(name: String, seed: Int): SimRaw = {
val raw = new SimVpi(backend)
val raw = new SimVpi(backend, name)
raw.userData = backend.signals
raw
}
Expand Down
28 changes: 17 additions & 11 deletions sim/src/main/scala/spinal/sim/GhdlBackend.scala
Original file line number Diff line number Diff line change
@@ -1,11 1,11 @@
package spinal.sim

import org.apache.commons.io.FileUtils
import spinal.sim.vpi.SharedMemIface

import java.io.{File, PrintWriter}
import java.nio.file.{Files, Paths}
import scala.sys.process._

import scala.collection.mutable

case class GhdlFlags(
Expand Down Expand Up @@ -37,15 37,6 @@ class GhdlBackend(config: GhdlBackendConfig) extends VpiBackend(config) {
WaveFormat.NONE
}

if (!(Array(WaveFormat.DEFAULT, WaveFormat.NONE) contains format)) {
val fixedPath = wavePath.split('.').init Seq(format.ext) mkString "."
if (format == WaveFormat.GHW) {
runFlags = " --wave=" fixedPath
} else {
runFlags = " --" format.ext "=" fixedPath
}
}

if (ghdlPath == null) ghdlPath = "ghdl"
var vpiModuleName = "vpi_ghdl.vpi"

Expand Down Expand Up @@ -97,7 88,7 @@ class GhdlBackend(config: GhdlBackendConfig) extends VpiBackend(config) {
)
}

def runSimulation(sharedMemIface: SharedMemIface): Thread = {
def runSimulation(sharedMemIface: SharedMemIface, testName: String): Thread = {
val vpiModulePath =
if (!isWindows) pluginsPath "/" vpiModuleName
else (pluginsPath "/" vpiModuleName).replaceAll("/C", raw"C:").replaceAll(raw"/", raw"\\")
Expand All @@ -112,6 103,20 @@ class GhdlBackend(config: GhdlBackendConfig) extends VpiBackend(config) {
val thread = new Thread(new Runnable {
val iface = sharedMemIface
def run(): Unit = {
val waveFileDir = Paths.get(System.getProperty("user.dir"), config.testPath.replace("$TEST",testName)).toAbsolutePath.normalize()
val waveFile = f"${waveFileDir}/wave.${config.waveFormat.ext}"
var waveArgString = ""
if (!(Array(WaveFormat.DEFAULT, WaveFormat.NONE) contains format)) {
if (format == WaveFormat.GHW) {
waveArgString = " --wave=" waveFile
} else {
waveArgString = " --" format.ext "=" waveFile
}
}
if (waveArgString != "") {
FileUtils.forceMkdirParent(new File(waveFileDir.toString, "."))
}

val retCode = Process(
Seq(
ghdlPath,
Expand All @@ -120,6 125,7 @@ class GhdlBackend(config: GhdlBackendConfig) extends VpiBackend(config) {
"-fsynopsys",
toplevelName,
s"--vpi=${pwd "/" vpiModulePath}",
waveArgString,
runFlags
).mkString(" "),
new File(workspacePath),
Expand Down
16 changes: 12 additions & 4 deletions sim/src/main/scala/spinal/sim/IVerilogBackend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 4,7 @@ import org.apache.commons.io.FileUtils
import spinal.sim.vpi.SharedMemIface

import java.io.{File, PrintWriter}
import java.nio.file.{Files, Paths}
import java.nio.file.{Files, Path, Paths}
import scala.sys.process.Process


Expand Down Expand Up @@ -105,9 105,12 @@ class IVerilogBackend(config: IVerilogBackendConfig) extends VpiBackend(config)
|`timescale $timeScale
|
|module __simulation_def;
|reg [255*8:0] wavefile; // "255 bytes are enough for every path"
|reg ign_res; // ignored result of $$value$$plusargs
|initial
| begin
| ${if (hasWave) "$dumpfile(\"" wavePath "\");" else ""}
| ign_res = $$value$$plusargs("wavefile=%s", wavefile); // read wave file name from wavefile=xxx.ext parameter passed at simulation runtime
| ${if (hasWave) "$dumpfile(wavefile);" else ""}
| ${if (hasWave) "$dumpvars(0," toplevelName ");" else ""}
| $$readmempath("./rtl/");
| end
Expand Down Expand Up @@ -146,18 149,23 @@ class IVerilogBackend(config: IVerilogBackendConfig) extends VpiBackend(config)
)
}

def runSimulation(sharedMemIface: SharedMemIface): Thread = {
def runSimulation(sharedMemIface: SharedMemIface, testName: String): Thread = {
val vpiModulePath =
if (!isWindows) pluginsPath "/" vpiModuleName
else (pluginsPath "/" vpiModuleName).replaceAll("/C", raw"C:").replaceAll(raw"/", raw"\\")

val pathStr = if (!isWindows) sys.env("PATH")
val waveFilePath = Paths.get(System.getProperty("user.dir"), config.testPath.replace("$TEST",testName)).toAbsolutePath.normalize()

val thread = new Thread(new Runnable {
val iface = sharedMemIface
def run(): Unit = {
val wavefilePathFlag = (if (config.waveFormat != WaveFormat.NONE) f" wavefile=${waveFilePath}/wave.${config.waveFormat.ext}" else "")
if (wavefilePathFlag != "") {
FileUtils.forceMkdirParent(new File(waveFilePath.toString, "."))
}
val retCode = Process(
Seq(vvpPath, "-M.", s"-m${pwd "/" vpiModulePath}", toplevelName ".vvp", runFlags).mkString(" "),
Seq(vvpPath, "-M.", s"-m${pwd "/" vpiModulePath}", toplevelName ".vvp", wavefilePathFlag, runFlags).mkString(" "),
new File(workspacePath)
).!(new LoggerPrint())
if (retCode != 0) {
Expand Down
4 changes: 2 additions & 2 deletions sim/src/main/scala/spinal/sim/SimVpi.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 8,11 @@ import scala.sys._

class VpiException(message: String) extends Exception(message)

class SimVpi(backend: VpiBackend) extends SimRaw {
class SimVpi(backend: VpiBackend, name: String) extends SimRaw {

val filledByte = 255.toByte
val zeroByte = 0.toByte
val (nativeIface, thread) = backend.instanciate()
val (nativeIface, thread) = backend.instanciate(name)
val handleMap: HashMap[Int, Long] = new HashMap()
val vectorInt8 = new VectorInt8()

Expand Down
2 changes: 1 addition & 1 deletion sim/src/main/scala/spinal/sim/VCSBackend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 353,7 @@ class VCSBackend(config: VCSBackendConfig) extends VpiBackend(config) {
override def buffer[T](f: => T) = f
}

def runSimulation(sharedMemIface: SharedMemIface): Thread = {
def runSimulation(sharedMemIface: SharedMemIface, testName: String): Thread = {
val thread = new Thread(new Runnable {
val iface = sharedMemIface
val logger = new LoggerPrintWithTerminationFilter()
Expand Down
17 changes: 9 additions & 8 deletions sim/src/main/scala/spinal/sim/VpiBackend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 32,8 @@ case class VpiBackendConfig(
var LDFLAGS: String = "-lpthread ",
var useCache: Boolean = false,
var logSimProcess: Boolean = false,
var timePrecision: String = null
var timePrecision: String = null,
var testPath: String = null
)

abstract class VpiBackend(val config: VpiBackendConfig) extends Backend {
Expand Down Expand Up @@ -169,9 170,9 @@ abstract class VpiBackend(val config: VpiBackendConfig) extends Backend {

def compileVPI() : Unit // Return the plugin name
def analyzeRTL() : Unit
def runSimulation(sharedMemIface: SharedMemIface) : Thread
def runSimulation(sharedMemIface: SharedMemIface, testName: String) : Thread

def instanciate_() : (SharedMemIface, Thread) = {
def instanciate_(name: String) : (SharedMemIface, Thread) = {
delayed_compilation
val shmemKey = Seq("SpinalHDL",
runIface.toString,
Expand All @@ -187,27 188,27 @@ abstract class VpiBackend(val config: VpiBackendConfig) extends Backend {
var shmemFile = new PrintWriter(new File(workspacePath "/shmem_name"))
shmemFile.write(shmemKey)
shmemFile.close
val thread = runSimulation(sharedMemIface)
val thread = runSimulation(sharedMemIface, name)
sharedMemIface.check_ready
(sharedMemIface, thread)
}

def instanciate(seed : Long) : (SharedMemIface, Thread) = {
def instanciate(name: String, seed : Long) : (SharedMemIface, Thread) = {
val ret = if(useCache) {
VpiBackend.synchronized {
instanciate_()
instanciate_(name)
}
} else {
this.synchronized {
instanciate_()
instanciate_(name)
}
}
ret._1.set_seed(seed)
ret._1.eval
ret
}

def instanciate() : (SharedMemIface, Thread) = instanciate(0x5EED5EED)
def instanciate(name: String) : (SharedMemIface, Thread) = instanciate(name, 0x5EED5EED)
}

object VpiBackend {}
Expand Down
2 changes: 1 addition & 1 deletion sim/src/test/scala/spinal/sim/Test2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 67,7 @@ object PlayGhdl extends App{
config.wavePath = "test.vcd"
config.waveFormat = WaveFormat.VCD

val (ghdlbackend, _) = new GhdlBackend(config).instanciate()
val (ghdlbackend, _) = new GhdlBackend(config).instanciate("test")
println(ghdlbackend.print_signals())
val nibble1 = ghdlbackend.get_signal_handle("adder.nibble1")
val nibble2 = ghdlbackend.get_signal_handle("adder.nibble2")
Expand Down
Loading

0 comments on commit 7ed4035

Please sign in to comment.