Coverage for tsfpga/vivado/simlib_commercial.py: 91%

32 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-27 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 Do not instantiate this class directly. 

29 Use factory class :class:`.VivadoSimlib` instead. 

30 """ 

31 

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

33 

34 _tcl = ( 

35 "set_param general.maxthreads 8\n" 

36 "compile_simlib " 

37 "-simulator {simulator_name} " 

38 "-simulator_exec_path {{{simulator_folder}}} " 

39 "-directory {{{output_path}}} " 

40 "-force " 

41 "-family all " 

42 "-language all " 

43 "-library all " 

44 "-no_ip_compile " 

45 "-no_systemc_compile " 

46 ) 

47 

48 def __init__( 

49 self, 

50 vivado_path: Path | None, 

51 output_path: Path, 

52 vunit_proj: VUnit, 

53 simulator_interface: SimulatorInterface, 

54 ) -> None: 

55 """ 

56 See superclass :class:`.VivadoSimlibCommon` constructor for details. 

57 """ 

58 self._simulator_folder = Path(simulator_interface.find_prefix()) 

59 self._simulator_name = self._get_simulator_name(simulator_interface=simulator_interface) 

60 

61 super().__init__( 

62 vivado_path=vivado_path, 

63 output_path=output_path, 

64 vunit_proj=vunit_proj, 

65 simulator_interface=simulator_interface, 

66 ) 

67 

68 def _get_simulator_name(self, simulator_interface: SimulatorInterface) -> str: 

69 """ 

70 Used to get the "-simulator" argument to the Vivado "compile_simlib" function. 

71 In some cases Vivado needs a different simulator name than what is used in VUnit. 

72 

73 Arguments: 

74 simulator_interface: A VUnit SimulatorInterface object. 

75 

76 Return: 

77 str: The simulator name preferred by Vivado. 

78 """ 

79 # Aldec Riviera-PRO is called "rivierapro" in VUnit but Vivado needs the name "riviera" 

80 if simulator_interface.name == "rivierapro": 

81 return "riviera" 

82 

83 # Siemens Questa is called "modelsim" in VUnit but Vivado needs the name "questasim". 

84 # See discussion in 

85 # https://github.com/VUnit/vunit/issues/834 

86 # Use the simulator installation path to decode whether we are running Questa or 

87 # regular ModelSim. 

88 if "questa" in str(self._simulator_folder).lower(): 

89 return "questasim" 

90 

91 # In other cases Vivado uses the same name as VUnit. 

92 # We do not do typing of the 'simulator_interface', but we know that '.name' is a string. 

93 return simulator_interface.name 

94 

95 def _compile(self) -> None: 

96 tcl_file = self.output_path / "compile_simlib.tcl" 

97 tcl = self._tcl.format( 

98 simulator_name=self._simulator_name, 

99 simulator_folder=to_tcl_path(self._simulator_folder), 

100 output_path=to_tcl_path(self.output_path), 

101 ) 

102 create_file(tcl_file, tcl) 

103 compile_ok = run_vivado_tcl(self._vivado_path, tcl_file) 

104 

105 if not compile_ok: 

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

107 

108 def _get_simulator_tag(self) -> str: 

109 """ 

110 Return e.g. modelsim_modeltech_pe_10_6c or riviera_riviera_pro_2018_10_x64. 

111 """ 

112 simulator_version = self._simulator_folder.parent.name 

113 return self._format_version(f"{self._simulator_name}_{simulator_version}")