-# 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
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>
#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)
include = ""
for path in include_paths:
include += "-I"+path+" "
-
content = """\
SRC_DIR = {}
INC_DIR = {}
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')
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"
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