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

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# -------------------------------------------------------------------------------------------------- 

8 

9from __future__ import annotations 

10 

11from pathlib import Path 

12from typing import TYPE_CHECKING, ClassVar 

13 

14from tsfpga.system_utils import create_file 

15 

16from .common import run_vivado_tcl, to_tcl_path 

17from .simlib_common import VivadoSimlibCommon 

18 

19if TYPE_CHECKING: 

20 from vunit.sim_if import SimulatorInterface 

21 from vunit.ui import VUnit 

22 

23 

24class VivadoSimlibCommercial(VivadoSimlibCommon): 

25 """ 

26 Handle Vivado simlib with a commercial simulator. 

27 """ 

28 

29 library_names: ClassVar = ["unisim", "secureip", "unimacro", "unifast", "xpm"] 

30 

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 ) 

44 

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) 

61 

62 super().__init__(vivado_path=vivado_path, output_path=output_path) 

63 

64 self._vunit_proj = vunit_proj 

65 

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. 

70 

71 Arguments: 

72 simulator_interface: A VUnit SimulatorInterface object. 

73 

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" 

80 

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" 

88 

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 

92 

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) 

102 

103 if not compile_ok: 

104 raise RuntimeError("Vivado simlib compile call failed!") 

105 

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}") 

112 

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}") 

121 

122 self._vunit_proj.add_external_library(library_name, library_path)