Coverage for tsfpga/vivado/simlib_ghdl.py: 47%

73 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-11-29 20:01 +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://gitlab.com/tsfpga/tsfpga 

7# -------------------------------------------------------------------------------------------------- 

8 

9# Standard libraries 

10import re 

11import subprocess 

12from pathlib import Path 

13 

14# First party libraries 

15from tsfpga import DEFAULT_FILE_ENCODING 

16from tsfpga.system_utils import create_directory 

17 

18# Local folder libraries 

19from .common import get_vivado_path 

20from .simlib_common import VivadoSimlibCommon 

21 

22 

23class VivadoSimlibGhdl(VivadoSimlibCommon): 

24 

25 """ 

26 Handle Vivado simlib with GHDL. 

27 """ 

28 

29 library_names = ["unisim", "secureip", "unimacro", "unifast"] 

30 

31 def __init__(self, output_path, vunit_proj, simulator_interface, vivado_path): 

32 """ 

33 Arguments: 

34 output_path (pathlib.Path): The compiled simlib will be placed here. 

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

36 simulator_interface: A VUnit SimulatorInterface class. 

37 vivado_path (pathlib.Path): Path to Vivado executable. 

38 """ 

39 self._vunit_proj = vunit_proj 

40 self._vivado_path = get_vivado_path(vivado_path) 

41 

42 self.ghdl_binary = Path(simulator_interface.find_prefix()) / "ghdl" 

43 

44 self.output_path = output_path / self._get_version_tag() 

45 

46 def _compile(self): 

47 vivado_libraries_path = self._vivado_path.parent.parent / "data" / "vhdl" / "src" 

48 

49 self._compile_unisim(vivado_libraries_path / "unisims") 

50 self._compile_secureip(vivado_libraries_path / "unisims" / "secureip") 

51 self._compile_unimacro(vivado_libraries_path / "unimacro") 

52 self._compile_unifast(vivado_libraries_path / "unifast" / "primitive") 

53 

54 def _compile_unisim(self, library_path): 

55 for vhd_file_base in [ 

56 "unisim_VPKG", 

57 "unisim_retarget_VCOMP", 

58 ]: 

59 vhd_file = library_path / f"{vhd_file_base}.vhd" 

60 assert vhd_file.exists, vhd_file 

61 self._compile_ghdl_file(vhd_file, "unisim") 

62 

63 primitive_dir = library_path / "primitive" 

64 for vhd_file in self._iterate_compile_order(primitive_dir): 

65 self._compile_ghdl_file(vhd_file, "unisim") 

66 

67 retarget_dir = library_path / "retarget" 

68 for vhd_file in retarget_dir.glob("*.vhd"): 

69 self._compile_ghdl_file(vhd_file, "unisim") 

70 

71 def _compile_secureip(self, library_path): 

72 for vhd_file in library_path.glob("*.vhd"): 

73 self._compile_ghdl_file(vhd_file, "secureip") 

74 

75 def _compile_unimacro(self, library_path): 

76 vhd_file = library_path / "unimacro_VCOMP.vhd" 

77 assert vhd_file.exists, vhd_file 

78 self._compile_ghdl_file(vhd_file, "unimacro") 

79 

80 for vhd_file in self._iterate_compile_order(library_path): 

81 self._compile_ghdl_file(vhd_file, "unimacro") 

82 

83 def _compile_unifast(self, library_path): 

84 for vhd_file in self._iterate_compile_order(library_path): 

85 self._compile_ghdl_file(vhd_file, "unifast") 

86 

87 @staticmethod 

88 def _iterate_compile_order(library_path): 

89 with open( 

90 library_path / "vhdl_analyze_order", encoding=DEFAULT_FILE_ENCODING 

91 ) as file_handle: 

92 for vhd_file_base in file_handle.readlines(): 

93 vhd_file = library_path / vhd_file_base.strip() 

94 assert vhd_file.exists(), vhd_file 

95 yield vhd_file 

96 

97 def _compile_ghdl_file(self, vhd_file, library_name): 

98 print(f"Compiling {vhd_file} into {library_name}") 

99 

100 workdir = self.output_path / library_name 

101 create_directory(workdir, empty=False) 

102 

103 cmd = [ 

104 self.ghdl_binary, 

105 "-a", 

106 "--ieee=synopsys", 

107 "--std=08", 

108 f"--workdir={str(workdir.resolve())}", 

109 f"-P{str(self.output_path / 'unisim')}", 

110 "-fexplicit", 

111 "-frelaxed-rules", 

112 "--no-vital-checks", 

113 "--warn-binding", 

114 "--mb-comments", 

115 f"--work={library_name}", 

116 str(vhd_file.resolve()), 

117 ] 

118 subprocess.check_call(cmd, cwd=self.output_path) 

119 

120 def _get_simulator_tag(self): 

121 """ 

122 Return simulator version tag 

123 """ 

124 cmd = [self.ghdl_binary, "--version"] 

125 output = subprocess.check_output(cmd).decode() 

126 

127 regexp_with_tag = re.compile(r"^GHDL (\S+) \((\S+)\).*") 

128 match = regexp_with_tag.search(output) 

129 if match is not None: 

130 return self._format_version(f"ghdl_{match.group(1)}_{match.group(2)}") 

131 

132 regexp_without_tag = re.compile(r"^GHDL (\S+).*") 

133 match = regexp_without_tag.search(output) 

134 if match is not None: 

135 return self._format_version(f"ghdl_{match.group(1)}") 

136 

137 raise ValueError(f"Could not find GHDL version string: {output}") 

138 

139 def _add_to_vunit_project(self): 

140 """ 

141 Add the compiled simlib to your VUnit project. 

142 """ 

143 for library_name in self.library_names: 

144 library_path = self.output_path / library_name 

145 assert library_path.exists(), library_path 

146 self._vunit_proj.add_external_library(library_name, library_path)