Skip to content

Commit

Permalink
sim_if/modelsim: use vmap to find modelsim.ini
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
bjornfor committed Nov 7, 2023
1 parent cdfa6da commit 250d9c2
Showing 1 changed file with 33 additions and 6 deletions.
39 changes: 33 additions & 6 deletions vunit/sim_if/modelsim.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from pathlib import Path
import os
import re
import logging
from configparser import RawConfigParser
from ..exceptions import CompileError
Expand Down Expand Up @@ -65,11 +66,7 @@ def find_prefix_from_path(cls):
"""
Find first valid modelsim toolchain prefix
"""

def has_modelsim_ini(path):
return os.path.isfile(str(Path(path).parent / "modelsim.ini"))

return cls.find_toolchain(["vsim"], constraints=[has_modelsim_ini])
return cls.find_toolchain(["vsim"])

@classmethod
def supports_vhdl_package_generics(cls):
Expand Down Expand Up @@ -98,6 +95,32 @@ def __init__(self, prefix, output_path, persistent=False, gui=False):
assert not (persistent and gui)
self._create_modelsim_ini()

def _get_modelsim_ini_path_from_vmap(self):
"""
Get the path to modelsim.ini, as used by vmap.
This means it listens to the MODELSIM environment variable, allowing
both vunit and other code/scripts to use the same modelsim.ini.
"""
vmap_output = []
proc = Process([str(Path(self._prefix) / "vmap")])
try:
proc.consume_output(callback=lambda line: vmap_output.append(line))
except Process.NonZeroExitCode:
# The responsibility of this code is only detecting where
# modelsim.ini is, not to check that all libraries defined in it
# exist. So suppress non-zero exit codes.
pass
for line in vmap_output:
m = re.match("Reading (.*modelsim\.ini)", line)
if m is None:
continue
modelsim_ini = Path(m.group(1)).resolve()
if not modelsim_ini.exists():
raise FileNotFoundError(modelsim_ini)
return modelsim_ini
raise Exception("Failed to get the path to modelsim.ini from vmap")

def _create_modelsim_ini(self):
"""
Create the modelsim.ini file
Expand All @@ -106,7 +129,11 @@ 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"))
# Try vunit specific environment variable first, then query vmap, which
# reads the MODELSIM environment variable if it exists, then checks the
# current working directory and eventually falls back to modelsim.ini
# bundled with ModelSim.
original_modelsim_ini = os.environ.get("VUNIT_MODELSIM_INI", self._get_modelsim_ini_path_from_vmap())
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

0 comments on commit 250d9c2

Please sign in to comment.