22
33package chiseltest .simulator
44
5- import chiseltest .legacy .backends .verilator .CopyVerilatorHeaderFiles .getClass
65import chiseltest .legacy .backends .verilator .{VerilatorCFlags , VerilatorFlags }
76import chiseltest .simulator .ipc .{IPCSimulatorContext , VerilatorCppHarnessGenerator }
7+ import chiseltest .simulator .jni .{JNISimulatorContext , JNIUtils , VerilatorCppJNIHarnessGenerator }
88import firrtl ._
9+ import firrtl .annotations .{Annotation , NoTargetAnnotation }
910
1011import java .io .{File , IOException }
1112import java .nio .file .StandardCopyOption .REPLACE_EXISTING
1213import java .nio .file .{FileAlreadyExistsException , Files , Path , Paths }
1314import scala .sys .process ._
1415
16+ private [chiseltest] case object VerilatorUseJNI extends NoTargetAnnotation
17+
1518object VerilatorSimulator extends Simulator {
1619 override def name : String = " verilator"
1720
@@ -53,14 +56,16 @@ object VerilatorSimulator extends Simulator {
5356 val targetDir = chiseltest.dut.Compiler .requireTargetDir(state.annotations)
5457 val toplevel = TopmoduleInfo (state.circuit)
5558
59+ val useJNI = state.annotations.contains(VerilatorUseJNI )
60+
5661 // Create the header files that verilator needs + a custom harness
57- val cppHarness = generateHarness(targetDir, toplevel)
62+ val cppHarness = generateHarness(targetDir, toplevel, useJNI )
5863
5964 // compile low firrtl to System Verilog for verilator to use
6065 chiseltest.dut.Compiler .lowFirrtlToSystemVerilog(state, VerilatorCoverage .CoveragePasses )
6166
6267 // turn SystemVerilog into C++ simulation
63- val verilatedDir = runVerilator(state.circuit.main, targetDir, cppHarness, state.annotations)
68+ val verilatedDir = runVerilator(state.circuit.main, targetDir, cppHarness, state.annotations, useJNI )
6469
6570 // patch the coverage cpp provided with verilator only if Verilator is older than 4.202
6671 // Starting with Verilator 4.202, the whole patch coverage hack is no longer necessary
@@ -74,7 +79,11 @@ object VerilatorSimulator extends Simulator {
7479
7580 // the binary we created communicates using our standard IPC interface
7681 // TODO: waveform file + getCoverage!
77- new IPCSimulatorContext (List (simBin.toString()), toplevel, VerilatorSimulator )
82+ if (useJNI) {
83+ new JNISimulatorContext (List (simBin.toString()), toplevel, VerilatorSimulator )
84+ } else {
85+ new IPCSimulatorContext (List (simBin.toString()), toplevel, VerilatorSimulator )
86+ }
7887 }
7988
8089 private def compileSimulation (topName : String , verilatedDir : os.Path ): os.Path = {
@@ -88,12 +97,13 @@ object VerilatorSimulator extends Simulator {
8897 }
8998
9099 /** executes verilator in order to generate a C++ simulation */
91- private def runVerilator (topName : String , targetDir : String , cppHarness : String , annos : AnnotationSeq ): os.Path = {
100+ private def runVerilator (topName : String , targetDir : String , cppHarness : String , annos : AnnotationSeq , useJNI : Boolean ): os.Path = {
92101 val targetDirPath = os.pwd / os.RelPath (targetDir)
93102 val verilatedDir = targetDirPath / " verilated"
94103
95104 removeOldCode(verilatedDir)
96- val flags = generateFlags(topName, verilatedDir, annos)
105+ val flagAnnos : Seq [Annotation ] = if (useJNI) { VerilatorCFlags (JNIUtils .ccFlags) +: annos } else { annos }
106+ val flags = generateFlags(topName, verilatedDir, flagAnnos)
97107 val cmd = List (" verilator" , " --cc" , " --exe" , cppHarness) ++ flags ++ List (s " $topName.sv " )
98108 val ret = os.proc(cmd).call(cwd = targetDirPath)
99109
@@ -148,16 +158,19 @@ object VerilatorSimulator extends Simulator {
148158 flags
149159 }
150160
151- private def generateHarness (targetDir : String , toplevel : TopmoduleInfo ): String = {
161+ private def generateHarness (targetDir : String , toplevel : TopmoduleInfo , useJNI : Boolean ): String = {
152162 val targetDirPath = os.pwd / os.RelPath (targetDir)
153163 val topName = toplevel.name
154164
155165 // Create the header files that verilator needs + a custom harness
156166 CopyVerilatorHeaderFiles (targetDir)
157167 val cppHarnessFileName = s " ${topName}-harness.cpp "
158168 val vcdFile = new File (targetDir, s " $topName.vcd " )
159- val emittedStuff = VerilatorCppHarnessGenerator .codeGen(toplevel, vcdFile.toString, targetDir,
160- majorVersion = majorVersion, minorVersion = minorVersion)
169+ val emittedStuff = if (useJNI) {
170+ VerilatorCppJNIHarnessGenerator .codeGen(toplevel, vcdFile.toString, targetDir, majorVersion = majorVersion, minorVersion = minorVersion)
171+ } else {
172+ VerilatorCppHarnessGenerator .codeGen(toplevel, vcdFile.toString, targetDir, majorVersion = majorVersion, minorVersion = minorVersion)
173+ }
161174 os.write.over(targetDirPath / cppHarnessFileName, emittedStuff)
162175
163176 cppHarnessFileName
0 commit comments