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

34 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-10 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 

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

24 Handle Vivado simlib with a commercial simulator. 

25 """ 

26 

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

28 

29 _tcl = ( 

30 "set_param general.maxthreads 8\n" 

31 "compile_simlib " 

32 "-simulator {simulator_name} " 

33 "-simulator_exec_path {{{simulator_folder}}} " 

34 "-directory {{{output_path}}} " 

35 "-force " 

36 "-family all " 

37 "-language all " 

38 "-library all " 

39 "-no_ip_compile " 

40 "-no_systemc_compile " 

41 ) 

42 

43 def __init__( 

44 self, 

45 vivado_path: Optional[Path], 

46 output_path: Path, 

47 vunit_proj: Any, 

48 simulator_interface: Any, 

49 ): 

50 """ 

51 Arguments: 

52 output_path: The compiled simlib will be placed here. 

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

54 simulator_interface: A VUnit SimulatorInterface object. 

55 vivado_path: Path to Vivado executable. 

56 """ 

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

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

59 

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

61 

62 self._vunit_proj = vunit_proj 

63 

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

65 """ 

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

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

68 

69 Arguments: 

70 simulator_interface: A VUnit SimulatorInterface object. 

71 

72 Return: 

73 str: The simulator name preferred by Vivado. 

74 """ 

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

76 if simulator_interface.name == "rivierapro": 

77 return "riviera" 

78 

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

80 # See discussion in 

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

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

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

84 # regular ModelSim. 

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

86 return "questasim" 

87 

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

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

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

91 

92 def _compile(self) -> None: 

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

94 tcl = self._tcl.format( 

95 simulator_name=self._simulator_name, 

96 simulator_folder=to_tcl_path(self._simulator_folder), 

97 output_path=to_tcl_path(self.output_path), 

98 ) 

99 create_file(tcl_file, tcl) 

100 compile_ok = run_vivado_tcl(self._vivado_path, tcl_file) 

101 

102 if not compile_ok: 

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

104 

105 def _get_simulator_tag(self) -> str: 

106 """ 

107 Return e.g. modelsim_modeltech_pe_10_6c or riviera_riviera_pro_2018_10_x64. 

108 """ 

109 simulator_version = self._simulator_folder.parent.name 

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

111 

112 def _add_to_vunit_project(self) -> None: 

113 """ 

114 Add the compiled simlib to your VUnit project. 

115 """ 

116 for library_name in self.library_names: 

117 library_path = self.output_path / library_name 

118 assert library_path.exists(), library_path 

119 

120 self._vunit_proj.add_external_library(library_name, library_path)