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

34 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-18 20:52 +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 

9# Standard libraries 

10from pathlib import Path 

11from typing import Any, Optional 

12 

13# First party libraries 

14from tsfpga.system_utils import create_file 

15 

16# Local folder libraries 

17from .common import run_vivado_tcl, to_tcl_path 

18from .simlib_common import VivadoSimlibCommon 

19 

20 

21class VivadoSimlibCommercial(VivadoSimlibCommon): 

22 """ 

23 Handle Vivado simlib with a commercial simulator. 

24 """ 

25 

26 library_names = ["unisim", "secureip", "unimacro", "unifast", "xpm"] 

27 

28 _tcl = ( 

29 "set_param general.maxthreads 8\n" 

30 "compile_simlib " 

31 "-simulator {simulator_name} " 

32 "-simulator_exec_path {{{simulator_folder}}} " 

33 "-directory {{{output_path}}} " 

34 "-force " 

35 "-family all " 

36 "-language all " 

37 "-library all " 

38 "-no_ip_compile " 

39 "-no_systemc_compile " 

40 ) 

41 

42 def __init__( 

43 self, 

44 vivado_path: Optional[Path], 

45 output_path: Path, 

46 vunit_proj: Any, 

47 simulator_interface: Any, 

48 ): 

49 """ 

50 Arguments: 

51 output_path: The compiled simlib will be placed here. 

52 vunit_proj: The VUnit project that is used to run simulation. 

53 simulator_interface: A VUnit SimulatorInterface object. 

54 vivado_path: Path to Vivado executable. 

55 """ 

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

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

58 

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

60 

61 self._vunit_proj = vunit_proj 

62 

63 def _get_simulator_name(self, simulator_interface: Any) -> str: 

64 """ 

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

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

67 

68 Arguments: 

69 simulator_interface: A VUnit SimulatorInterface object. 

70 

71 Return: 

72 str: The simulator name preferred by Vivado. 

73 """ 

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

75 if simulator_interface.name == "rivierapro": 

76 return "riviera" 

77 

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

79 # See discussion in 

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

81 # https://gitlab.com/tsfpga/tsfpga/-/issues/67 

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

83 # regular ModelSim. 

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

85 return "questasim" 

86 

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

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

89 return simulator_interface.name # type: ignore[no-any-return] 

90 

91 def _compile(self) -> None: 

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

93 tcl = self._tcl.format( 

94 simulator_name=self._simulator_name, 

95 simulator_folder=to_tcl_path(self._simulator_folder), 

96 output_path=to_tcl_path(self.output_path), 

97 ) 

98 create_file(tcl_file, tcl) 

99 compile_ok = run_vivado_tcl(self._vivado_path, tcl_file) 

100 

101 if not compile_ok: 

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

103 

104 def _get_simulator_tag(self) -> str: 

105 """ 

106 Return e.g. modelsim_modeltech_pe_10_6c or riviera_riviera_pro_2018_10_x64. 

107 """ 

108 simulator_version = self._simulator_folder.parent.name 

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

110 

111 def _add_to_vunit_project(self) -> None: 

112 """ 

113 Add the compiled simlib to your VUnit project. 

114 """ 

115 for library_name in self.library_names: 

116 library_path = self.output_path / library_name 

117 assert library_path.exists(), library_path 

118 

119 self._vunit_proj.add_external_library(library_name, library_path)