Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add feature to select simulator programatically #805

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def create_tempdir(path: Path = None):
"""

if path is None:
path = Path(__file__).parent / ("tempdir_%i" % random.randint(0, 2**64 - 1))
path = Path(__file__).parent / ("tempdir_%i" % random.randint(0, 2 ** 64 - 1))

if path.exists():
shutil.rmtree(path)
Expand Down
10 changes: 10 additions & 0 deletions tests/unit/test_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,16 @@ def test_get_simulator_name(self):
ui = self._create_ui()
self.assertEqual(ui.get_simulator_name(), "mock")

def test_set_simulator(self):
ui = self._create_ui()
prefix = ui.get_simulator_prefix()
# Just change it
prefix = Path("mock")
ui.set_simulator("modelsim", "modelsim_2021_2", prefix)
self.assertEqual(ui.get_simulator_name(), "modelsim")
self.assertEqual(ui.get_simulator_id(), "modelsim_2021_2")
self.assertEqual(ui.get_simulator_prefix(), prefix)

def _create_ui(self, *args):
"""Create an instance of the VUnit public interface class"""
with mock.patch(
Expand Down
22 changes: 22 additions & 0 deletions vunit/sim_if/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class SimulatorInterface(object): # pylint: disable=too-many-public-methods
def __init__(self, output_path, gui):
self._output_path = output_path
self._gui = gui
self.id = None
self.prefix = None

@property
def output_path(self):
Expand Down Expand Up @@ -310,6 +312,26 @@ def get_env():
Allows inheriting classes to overload this to modify environment variables. Return None for default environment
"""

def set_id(self, id):
"""
Sets id of simulator, used for unique separate output directories for multiple versions of a class
param: id: The id to use
"""
if id is None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patterns like this can be simplified as

self.id = id or self.name

self.id = self.name
else:
self.id = id

def set_prefix(self, prefix):
"""
Sets prefix of simulator, if set overrides PATH searching
param: prefix: The prefix to use
"""
if prefix is None:
self.prefix = self.__class__.find_prefix()
else:
self.prefix = prefix


def isfile(file_name):
"""
Expand Down
16 changes: 8 additions & 8 deletions vunit/sim_if/activehdl.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def supports_coverage():
def __init__(self, prefix, output_path, gui=False):
SimulatorInterface.__init__(self, output_path, gui)
self._library_cfg = str(Path(output_path) / "library.cfg")
self._prefix = prefix
self.prefix = prefix
self._create_library_cfg()
self._libraries = []
self._coverage_files = set()
Expand Down Expand Up @@ -120,7 +120,7 @@ def compile_vhdl_file_command(self, source_file):
"""
return (
[
str(Path(self._prefix) / "vcom"),
str(Path(self.prefix) / "vcom"),
"-quiet",
"-j",
str(Path(self._library_cfg).parent),
Expand All @@ -138,7 +138,7 @@ def compile_verilog_file_command(self, source_file):
"""
Returns the command to compile a Verilog file
"""
args = [str(Path(self._prefix) / "vlog"), "-quiet", "-lc", self._library_cfg]
args = [str(Path(self.prefix) / "vlog"), "-quiet", "-lc", self._library_cfg]
args += source_file.compile_options.get("activehdl.vlog_flags", [])
args += ["-work", source_file.library.name, source_file.name]
for library in self._libraries:
Expand All @@ -162,7 +162,7 @@ def create_library(self, library_name, path, mapped_libraries=None):

if not file_exists(path):
proc = Process(
[str(Path(self._prefix) / "vlib"), library_name, path],
[str(Path(self.prefix) / "vlib"), library_name, path],
cwd=str(Path(self._library_cfg).parent),
env=self.get_env(),
)
Expand All @@ -172,7 +172,7 @@ def create_library(self, library_name, path, mapped_libraries=None):
return

proc = Process(
[str(Path(self._prefix) / "vmap"), library_name, path],
[str(Path(self.prefix) / "vmap"), library_name, path],
cwd=str(Path(self._library_cfg).parent),
env=self.get_env(),
)
Expand All @@ -186,7 +186,7 @@ def _create_library_cfg(self):
return

with Path(self._library_cfg).open("w", encoding="utf-8") as ofile:
ofile.write(f'$INCLUDE = "{str(Path(self._prefix).parent / "vlib" / "library.cfg")}"\n')
ofile.write(f'$INCLUDE = "{str(Path(self.prefix).parent / "vlib" / "library.cfg")}"\n')

_library_re = re.compile(r'([a-zA-Z_]+)\s=\s"(.*)"')

Expand Down Expand Up @@ -324,7 +324,7 @@ def merge_coverage(self, file_name, args=None):
fptr.write(merge_command + "\n")

vcover_cmd = [
str(Path(self._prefix) / "vsimsa"),
str(Path(self.prefix) / "vsimsa"),
"-tcl",
str(fix_path(merge_script_name)),
]
Expand Down Expand Up @@ -393,7 +393,7 @@ def _run_batch_file(self, batch_file_name, gui, cwd):

try:
args = [
str(Path(self._prefix) / "vsim"),
str(Path(self.prefix) / "vsim"),
"-gui" if gui else "-c",
"-l",
str(Path(batch_file_name).parent / "transcript"),
Expand Down
13 changes: 13 additions & 0 deletions vunit/sim_if/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,19 @@ def select_simulator(self):

return simulator_class

def get_simulator(self, simulator):
"""
Get a simulator class by name
param: simulator: Name of a supported simulator
"""
supported_simulators = self.supported_simulators()
name_mapping = {simulator_class.name: simulator_class for simulator_class in self.supported_simulators()}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You declared supported_simulators on the previous line. I would either remove that and only use self.supported_simulators() everywhere or use that variable everywhere in here.

if simulator not in name_mapping:
raise ValueError(f"Unknown simulator {simulator}, expected one of {supported_simulators}")

simulator = name_mapping[simulator]
return simulator

def add_arguments(self, parser):
"""
Add command line arguments to parser
Expand Down
6 changes: 3 additions & 3 deletions vunit/sim_if/ghdl.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def __init__( # pylint: disable=too-many-arguments
backend="llvm",
):
SimulatorInterface.__init__(self, output_path, gui)
self._prefix = prefix
self.prefix = prefix
self._project = None

if gui and (not self.find_executable("gtkwave")):
Expand Down Expand Up @@ -237,7 +237,7 @@ def compile_vhdl_file_command(self, source_file):
Returns the command to compile a vhdl file
"""
cmd = [
str(Path(self._prefix) / self.executable),
str(Path(self.prefix) / self.executable),
"-a",
f"--workdir={source_file.library.directory!s}",
f"--work={source_file.library.name!s}",
Expand Down Expand Up @@ -269,7 +269,7 @@ def _get_command(self, config, output_path, elaborate_only, ghdl_e, wave_file):
"""
Return GHDL simulation command
"""
cmd = [str(Path(self._prefix) / self.executable)]
cmd = [str(Path(self.prefix) / self.executable)]

cmd += ["-e"] if ghdl_e else ["--elab-run"]

Expand Down
12 changes: 6 additions & 6 deletions vunit/sim_if/incisive.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def __init__( # pylint: disable=too-many-arguments
self, prefix, output_path, gui=False, log_level=None, cdslib=None, hdlvar=None
):
SimulatorInterface.__init__(self, output_path, gui)
self._prefix = prefix
self.prefix = prefix
self._libraries = []
self._log_level = log_level
if cdslib is None:
Expand All @@ -102,14 +102,14 @@ def find_cds_root_irun(self):
"""
Finds irun cds root
"""
return subprocess.check_output([str(Path(self._prefix) / "cds_root"), "irun"]).splitlines()[0]
return subprocess.check_output([str(Path(self.prefix) / "cds_root"), "irun"]).splitlines()[0]

def find_cds_root_virtuoso(self):
"""
Finds virtuoso cds root
"""
try:
return subprocess.check_output([str(Path(self._prefix) / "cds_root"), "virtuoso"]).splitlines()[0]
return subprocess.check_output([str(Path(self.prefix) / "cds_root"), "virtuoso"]).splitlines()[0]
except subprocess.CalledProcessError:
return None

Expand Down Expand Up @@ -182,7 +182,7 @@ def compile_vhdl_file_command(self, source_file):
"""
Returns command to compile a VHDL file
"""
cmd = str(Path(self._prefix) / "irun")
cmd = str(Path(self.prefix) / "irun")
args = []
args += ["-compile"]
args += ["-nocopyright"]
Expand Down Expand Up @@ -212,7 +212,7 @@ def compile_verilog_file_command(self, source_file):
"""
Returns commands to compile a Verilog file
"""
cmd = str(Path(self._prefix) / "irun")
cmd = str(Path(self.prefix) / "irun")
args = []
args += ["-compile"]
args += ["-nocopyright"]
Expand Down Expand Up @@ -291,7 +291,7 @@ def simulate(self, output_path, test_suite_name, config, elaborate_only=False):
steps = ["elaborate", "simulate"]

for step in steps:
cmd = str(Path(self._prefix) / "irun")
cmd = str(Path(self.prefix) / "irun")
args = []
if step == "elaborate":
args += ["-elaborate"]
Expand Down
10 changes: 5 additions & 5 deletions vunit/sim_if/modelsim.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def _create_modelsim_ini(self):
if not file_exists(parent):
os.makedirs(parent)

original_modelsim_ini = os.environ.get("VUNIT_MODELSIM_INI", str(Path(self._prefix).parent / "modelsim.ini"))
original_modelsim_ini = os.environ.get("VUNIT_MODELSIM_INI", str(Path(self.prefix).parent / "modelsim.ini"))
with Path(original_modelsim_ini).open("rb") as fread:
with Path(self._sim_cfg_file_name).open("wb") as fwrite:
fwrite.write(fread.read())
Expand Down Expand Up @@ -159,7 +159,7 @@ def compile_vhdl_file_command(self, source_file):
"""
return (
[
str(Path(self._prefix) / "vcom"),
str(Path(self.prefix) / "vcom"),
"-quiet",
"-modelsimini",
self._sim_cfg_file_name,
Expand All @@ -178,7 +178,7 @@ def compile_verilog_file_command(self, source_file):
Returns the command to compile a verilog file
"""
args = [
str(Path(self._prefix) / "vlog"),
str(Path(self.prefix) / "vlog"),
"-quiet",
"-modelsimini",
self._sim_cfg_file_name,
Expand Down Expand Up @@ -208,7 +208,7 @@ def create_library(self, library_name, path, mapped_libraries=None):
os.makedirs(apath)

if not file_exists(path):
proc = Process([str(Path(self._prefix) / "vlib"), "-unix", path], env=self.get_env())
proc = Process([str(Path(self.prefix) / "vlib"), "-unix", path], env=self.get_env())
proc.consume_output(callback=None)

if library_name in mapped_libraries and mapped_libraries[library_name] == path:
Expand Down Expand Up @@ -378,7 +378,7 @@ def merge_coverage(self, file_name, args=None):
args = []

coverage_files = str(Path(self._output_path) / "coverage_files.txt")
vcover_cmd = [str(Path(self._prefix) / "vcover"), "merge", "-inputs"] + [coverage_files] + args + [file_name]
vcover_cmd = [str(Path(self.prefix) / "vcover"), "merge", "-inputs"] + [coverage_files] + args + [file_name]
with Path(coverage_files).open("w", encoding="utf-8") as fptr:
for coverage_file in self._coverage_files:
if file_exists(coverage_file):
Expand Down
14 changes: 7 additions & 7 deletions vunit/sim_if/rivierapro.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ def compile_vhdl_file_command(self, source_file):

return (
[
str(Path(self._prefix) / "vcom"),
str(Path(self.prefix) / "vcom"),
"-quiet",
"-j",
str(Path(self._sim_cfg_file_name).parent),
Expand All @@ -192,7 +192,7 @@ def compile_verilog_file_command(self, source_file):
Returns the command to compile a Verilog file
"""
args = [
str(Path(self._prefix) / "vlog"),
str(Path(self.prefix) / "vlog"),
"-quiet",
"-lc",
self._sim_cfg_file_name,
Expand Down Expand Up @@ -224,7 +224,7 @@ def create_library(self, library_name, path, mapped_libraries=None):

if not file_exists(path):
proc = Process(
[str(Path(self._prefix) / "vlib"), library_name, path],
[str(Path(self.prefix) / "vlib"), library_name, path],
cwd=str(Path(self._sim_cfg_file_name).parent),
env=self.get_env(),
)
Expand All @@ -234,7 +234,7 @@ def create_library(self, library_name, path, mapped_libraries=None):
return

proc = Process(
[str(Path(self._prefix) / "vmap"), library_name, path],
[str(Path(self.prefix) / "vmap"), library_name, path],
cwd=str(Path(self._sim_cfg_file_name).parent),
env=self.get_env(),
)
Expand All @@ -252,7 +252,7 @@ def _create_library_cfg(self):

@property
def _builtin_library_cfg(self):
return str(Path(self._prefix).parent / "vlib" / "library.cfg")
return str(Path(self.prefix).parent / "vlib" / "library.cfg")

_library_re = re.compile(r"([a-zA-Z_0-9]+)\s=\s(.*)")

Expand All @@ -261,7 +261,7 @@ def _get_mapped_libraries(self, library_cfg_file):
Get mapped libraries by running vlist on the working directory
"""
lines = []
proc = Process([str(Path(self._prefix) / "vlist")], cwd=str(Path(library_cfg_file).parent))
proc = Process([str(Path(self.prefix) / "vlist")], cwd=str(Path(library_cfg_file).parent))
proc.consume_output(callback=lines.append)

libraries = {}
Expand Down Expand Up @@ -412,7 +412,7 @@ def merge_coverage(self, file_name, args=None):

mscript = str(merge_script_name).replace("\\", "/")
vcover_cmd = [
str(Path(self._prefix) / "vsim"),
str(Path(self.prefix) / "vsim"),
"-c",
"-do",
f"source {{{mscript}}}; quit;",
Expand Down
6 changes: 3 additions & 3 deletions vunit/sim_if/vsim_simulator_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ class VsimSimulatorMixin(object):
"""

def __init__(self, prefix, persistent, sim_cfg_file_name):
self._prefix = prefix
self.prefix = prefix
sim_cfg_file_name = str(Path(sim_cfg_file_name).resolve())
self._sim_cfg_file_name = sim_cfg_file_name

prefix = self._prefix # Avoid circular dependency inhibiting process destruction
prefix = self.prefix # Avoid circular dependency inhibiting process destruction
env = self.get_env()

def create_process(ident):
Expand Down Expand Up @@ -270,7 +270,7 @@ def _run_batch_file(self, batch_file_name, gui=False):

try:
args = [
str(Path(self._prefix) / "vsim"),
str(Path(self.prefix) / "vsim"),
"-gui" if gui else "-c",
"-l",
str(Path(batch_file_name).parent / "transcript"),
Expand Down