Coverage for tsfpga/vivado/simlib_commercial.py: 79%
39 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-21 20:51 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-21 20:51 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the tsfpga project, a project platform for modern FPGA development.
5# https://tsfpga.com
6# https://github.com/tsfpga/tsfpga
7# --------------------------------------------------------------------------------------------------
9from __future__ import annotations
11from pathlib import Path
12from typing import TYPE_CHECKING, ClassVar
14from tsfpga.system_utils import create_file
16from .common import run_vivado_tcl, to_tcl_path
17from .simlib_common import VivadoSimlibCommon
19if TYPE_CHECKING:
20 from vunit.sim_if import SimulatorInterface
21 from vunit.ui import VUnit
24class VivadoSimlibCommercial(VivadoSimlibCommon):
25 """
26 Handle Vivado simlib with a commercial simulator.
27 """
29 library_names: ClassVar = ["unisim", "secureip", "unimacro", "unifast", "xpm"]
31 _tcl = (
32 "set_param general.maxthreads 8\n"
33 "compile_simlib "
34 "-simulator {simulator_name} "
35 "-simulator_exec_path {{{simulator_folder}}} "
36 "-directory {{{output_path}}} "
37 "-force "
38 "-family all "
39 "-language all "
40 "-library all "
41 "-no_ip_compile "
42 "-no_systemc_compile "
43 )
45 def __init__(
46 self,
47 vivado_path: Path | None,
48 output_path: Path,
49 vunit_proj: VUnit,
50 simulator_interface: SimulatorInterface,
51 ) -> None:
52 """
53 Arguments:
54 output_path: The compiled simlib will be placed here.
55 vunit_proj: The VUnit project that is used to run simulation.
56 simulator_interface: A VUnit SimulatorInterface object.
57 vivado_path: Path to Vivado executable.
58 """
59 self._simulator_folder = Path(simulator_interface.find_prefix())
60 self._simulator_name = self._get_simulator_name(simulator_interface=simulator_interface)
62 super().__init__(vivado_path=vivado_path, output_path=output_path)
64 self._vunit_proj = vunit_proj
66 def _get_simulator_name(self, simulator_interface: SimulatorInterface) -> str:
67 """
68 Used to get the "-simulator" argument to the Vivado "compile_simlib" function.
69 In some cases Vivado needs a different simulator name than what is used in VUnit.
71 Arguments:
72 simulator_interface: A VUnit SimulatorInterface object.
74 Return:
75 str: The simulator name preferred by Vivado.
76 """
77 # Aldec Riviera-PRO is called "rivierapro" in VUnit but Vivado needs the name "riviera"
78 if simulator_interface.name == "rivierapro":
79 return "riviera"
81 # Siemens Questa is called "modelsim" in VUnit but Vivado needs the name "questasim".
82 # See discussion in
83 # https://github.com/VUnit/vunit/issues/834
84 # Use the simulator installation path to decode whether we are running Questa or
85 # regular ModelSim.
86 if "questa" in str(self._simulator_folder).lower():
87 return "questasim"
89 # In other cases Vivado uses the same name as VUnit.
90 # We do not do typing of the 'simulator_interface', but we know that '.name' is a string.
91 return simulator_interface.name
93 def _compile(self) -> None:
94 tcl_file = self.output_path / "compile_simlib.tcl"
95 tcl = self._tcl.format(
96 simulator_name=self._simulator_name,
97 simulator_folder=to_tcl_path(self._simulator_folder),
98 output_path=to_tcl_path(self.output_path),
99 )
100 create_file(tcl_file, tcl)
101 compile_ok = run_vivado_tcl(self._vivado_path, tcl_file)
103 if not compile_ok:
104 raise RuntimeError("Vivado simlib compile call failed!")
106 def _get_simulator_tag(self) -> str:
107 """
108 Return e.g. modelsim_modeltech_pe_10_6c or riviera_riviera_pro_2018_10_x64.
109 """
110 simulator_version = self._simulator_folder.parent.name
111 return self._format_version(f"{self._simulator_name}_{simulator_version}")
113 def _add_to_vunit_project(self) -> None:
114 """
115 Add the compiled simlib to your VUnit project.
116 """
117 for library_name in self.library_names:
118 library_path = self.output_path / library_name
119 if not library_path.exists():
120 raise FileNotFoundError(f"Library path not found: {library_path}")
122 self._vunit_proj.add_external_library(library_name, library_path)