litex_sim: Rework Makefiles to put output files in gateware directory.
[litex.git] / litex / build / sim / verilator.py
index 608a2f62c7aa11f78f16bfc59c37b5cd3981924b..f068d08d1f899c08b0d03d4983973cfba2c1343c 100644 (file)
@@ -1,5 +1,5 @@
-# This file is Copyright (c) 2015-2016 Florent Kermarrec <florent@enjoy-digital.fr>
-#                            2017 Pierre-Olivier Vauboin <po@lambdaconcept.com>
+# This file is Copyright (c) 2015-2019 Florent Kermarrec <florent@enjoy-digital.fr>
+# This file is Copyright (c) 2017 Pierre-Olivier Vauboin <po@lambdaconcept>
 # License: BSD
 
 import os
@@ -60,7 +60,7 @@ def _generate_sim_cpp_struct(name, index, siglist):
     return content
 
 
-def _generate_sim_cpp(platform):
+def _generate_sim_cpp(platform, trace=False, trace_start=0, trace_end=-1):
     content = """\
 #include <stdio.h>
 #include <stdlib.h>
@@ -69,13 +69,28 @@ def _generate_sim_cpp(platform):
 #include <verilated.h>
 #include "dut_header.h"
 
-extern "C" void litex_sim_init(void **out)
+extern "C" void litex_sim_init_tracer(void *vdut, long start, long end);
+extern "C" void litex_sim_tracer_dump();
+
+extern "C" void litex_sim_dump()
 {
+"""
+    if trace:
+        content += """\
+    litex_sim_tracer_dump();
+"""
+    content  += """\
+}}
+
+extern "C" void litex_sim_init(void **out)
+{{
     Vdut *dut;
 
     dut = new Vdut;
 
-"""
+    litex_sim_init_tracer(dut, {}, {});
+
+""".format(trace_start, trace_end)
     for args in platform.sim_requested:
         content += _generate_sim_cpp_struct(*args)
 
@@ -90,7 +105,6 @@ def _generate_sim_variables(include_paths):
     include = ""
     for path in include_paths:
         include += "-I"+path+" "
-
     content = """\
 SRC_DIR = {}
 INC_DIR = {}
@@ -103,16 +117,26 @@ def _generate_sim_config(config):
     tools.write_to_file("sim_config.js", content)
 
 
-def _build_sim(platform, build_name, threads, verbose):
+def _build_sim(build_name, sources, threads, coverage, opt_level="O3", trace_fst=False):
     makefile = os.path.join(core_directory, 'Makefile')
+    cc_srcs = []
+    for filename, language, library in sources:
+        cc_srcs.append("--cc " + filename + " ")
     build_script_contents = """\
 rm -rf obj_dir/
-make -C . -f {} {}
-mkdir -p modules && cp obj_dir/*.so modules
-""".format(makefile, "THREADS={}".format(threads) if int(threads) > 1 else "")
+make -C . -f {} {} {} {} {} {}
+""".format(makefile,
+    "CC_SRCS=\"{}\"".format("".join(cc_srcs)),
+    "THREADS={}".format(threads) if int(threads) > 1 else "",
+    "COVERAGE=1" if coverage else "",
+    "OPT_LEVEL={}".format(opt_level),
+    "TRACE_FST=1" if trace_fst else "",
+    )
     build_script_file = "build_" + build_name + ".sh"
     tools.write_to_file(build_script_file, build_script_contents, force_unix=True)
 
+def _compile_sim(build_name, verbose):
+    build_script_file = "build_" + build_name + ".sh"
     p = subprocess.Popen(["bash", build_script_file], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
     output, _ = p.communicate()
     output = output.decode('utf-8')
@@ -125,7 +149,6 @@ mkdir -p modules && cp obj_dir/*.so modules
     if verbose:
         print(output)
 
-
 def _run_sim(build_name, as_root=False):
     run_script_contents = "sudo " if as_root else ""
     run_script_contents += "obj_dir/Vdut"
@@ -139,46 +162,58 @@ def _run_sim(build_name, as_root=False):
         if r != 0:
             raise OSError("Subprocess failed")
     except:
-        if sys.platform != "win32":
-            termios.tcsetattr(sys.stdin.fileno(), termios.TCSAFLUSH, termios_settings)
+        pass
+    if sys.platform != "win32":
+        termios.tcsetattr(sys.stdin.fileno(), termios.TCSAFLUSH, termios_settings)
 
 
 class SimVerilatorToolchain:
     def build(self, platform, fragment, build_dir="build", build_name="dut",
-            toolchain_path=None, serial="console", build=True, run=True, threads=1,
-            verbose=True, sim_config=None):
+            serial="console", build=True, run=True, threads=1,
+            verbose=True, sim_config=None, coverage=False, opt_level="O0",
+            trace=False, trace_fst=False, trace_start=0, trace_end=-1):
 
+        # create build directory
         os.makedirs(build_dir, exist_ok=True)
         os.chdir(build_dir)
 
         if build:
+            # finalize design
             if not isinstance(fragment, _Fragment):
                 fragment = fragment.get_fragment()
             platform.finalize(fragment)
 
-            v_output = platform.get_verilog(fragment,
+            # generate top module
+            top_output = platform.get_verilog(fragment,
                 name=build_name, dummy_signal=False, regular_comb=False, blocking_assign=True)
-            named_sc, named_pc = platform.resolve_signals(v_output.ns)
-            v_output.write(build_name + ".v")
-
-            include_paths = []
-            for source in platform.sources:
-                path = os.path.dirname(source[0]).replace("\\", "\/")
-                if path not in include_paths:
-                    include_paths.append(path)
-            include_paths += platform.verilog_include_paths
+            named_sc, named_pc = platform.resolve_signals(top_output.ns)
+            top_file = build_name + ".v"
+            top_output.write(top_file)
+            platform.add_source(top_file)
+
+            # generate cpp header/main/variables
             _generate_sim_h(platform)
-            _generate_sim_cpp(platform)
-            _generate_sim_variables(include_paths)
+            _generate_sim_cpp(platform, trace, trace_start, trace_end)
+            _generate_sim_variables(platform.verilog_include_paths)
+
+            # generate sim config
             if sim_config:
                 _generate_sim_config(sim_config)
 
-            _build_sim(platform, build_name, threads, verbose)
+            # build
+            _build_sim(build_name, platform.sources, threads, coverage, opt_level, trace_fst)
 
+        # run
         if run:
-            _run_sim(build_name, as_root=sim_config.has_module("ethernet"))
+            _compile_sim(build_name, verbose)
+            run_as_root = False
+            if sim_config.has_module("ethernet"):
+                run_as_root = True
+            if sim_config.has_module("xgmii_ethernet"):
+                run_as_root = True
+            _run_sim(build_name, as_root=run_as_root)
 
         os.chdir("../../")
 
         if build:
-            return v_output.ns
\ No newline at end of file
+            return top_output.ns