Skip to content

Commit 250d9c2

Browse files
committed
sim_if/modelsim: use vmap to find modelsim.ini
* This creates a single source of truth for finding modelsim.ini. It is now possible to use MODELSIM=/path/to/custom/modelsim.ini and both ModelSim and vunit will use that. (The VUNIT_MODELSIM_INI environment variable can still be used to override modelsim.ini only for vunit.) * This fixes detecting modelsim.ini in the quartus-prime-lite package from https://github.com/nixos/nixpkgs, which exposes binaries at $prefix/bin, but not $prefix/modelsim.ini, because the latter is an FHS violation.
1 parent cdfa6da commit 250d9c2

File tree

1 file changed

+33
-6
lines changed

1 file changed

+33
-6
lines changed

vunit/sim_if/modelsim.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from pathlib import Path
1212
import os
13+
import re
1314
import logging
1415
from configparser import RawConfigParser
1516
from ..exceptions import CompileError
@@ -65,11 +66,7 @@ def find_prefix_from_path(cls):
6566
"""
6667
Find first valid modelsim toolchain prefix
6768
"""
68-
69-
def has_modelsim_ini(path):
70-
return os.path.isfile(str(Path(path).parent / "modelsim.ini"))
71-
72-
return cls.find_toolchain(["vsim"], constraints=[has_modelsim_ini])
69+
return cls.find_toolchain(["vsim"])
7370

7471
@classmethod
7572
def supports_vhdl_package_generics(cls):
@@ -98,6 +95,32 @@ def __init__(self, prefix, output_path, persistent=False, gui=False):
9895
assert not (persistent and gui)
9996
self._create_modelsim_ini()
10097

98+
def _get_modelsim_ini_path_from_vmap(self):
99+
"""
100+
Get the path to modelsim.ini, as used by vmap.
101+
102+
This means it listens to the MODELSIM environment variable, allowing
103+
both vunit and other code/scripts to use the same modelsim.ini.
104+
"""
105+
vmap_output = []
106+
proc = Process([str(Path(self._prefix) / "vmap")])
107+
try:
108+
proc.consume_output(callback=lambda line: vmap_output.append(line))
109+
except Process.NonZeroExitCode:
110+
# The responsibility of this code is only detecting where
111+
# modelsim.ini is, not to check that all libraries defined in it
112+
# exist. So suppress non-zero exit codes.
113+
pass
114+
for line in vmap_output:
115+
m = re.match("Reading (.*modelsim\.ini)", line)
116+
if m is None:
117+
continue
118+
modelsim_ini = Path(m.group(1)).resolve()
119+
if not modelsim_ini.exists():
120+
raise FileNotFoundError(modelsim_ini)
121+
return modelsim_ini
122+
raise Exception("Failed to get the path to modelsim.ini from vmap")
123+
101124
def _create_modelsim_ini(self):
102125
"""
103126
Create the modelsim.ini file
@@ -106,7 +129,11 @@ def _create_modelsim_ini(self):
106129
if not file_exists(parent):
107130
os.makedirs(parent)
108131

109-
original_modelsim_ini = os.environ.get("VUNIT_MODELSIM_INI", str(Path(self._prefix).parent / "modelsim.ini"))
132+
# Try vunit specific environment variable first, then query vmap, which
133+
# reads the MODELSIM environment variable if it exists, then checks the
134+
# current working directory and eventually falls back to modelsim.ini
135+
# bundled with ModelSim.
136+
original_modelsim_ini = os.environ.get("VUNIT_MODELSIM_INI", self._get_modelsim_ini_path_from_vmap())
110137
with Path(original_modelsim_ini).open("rb") as fread:
111138
with Path(self._sim_cfg_file_name).open("wb") as fwrite:
112139
fwrite.write(fread.read())

0 commit comments

Comments
 (0)