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

73 statements  

« prev     ^ index     » next       coverage.py v6.4, created at 2022-05-28 04:01 +0000

1# -------------------------------------------------------------------------------------------------- 

2# Copyright (c) Lukas Vik. All rights reserved. 

3# 

4# This file is part of the tsfpga project. 

5# https://tsfpga.com 

6# https://gitlab.com/tsfpga/tsfpga 

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

8 

9import re 

10import subprocess 

11from pathlib import Path 

12 

13from tsfpga import DEFAULT_FILE_ENCODING 

14from tsfpga.system_utils import create_directory 

15from .common import get_vivado_path 

16from .simlib_common import VivadoSimlibCommon 

17 

18 

19class VivadoSimlibGhdl(VivadoSimlibCommon): 

20 

21 """ 

22 Handle Vivado simlib with GHDL. 

23 """ 

24 

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

26 

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

28 """ 

29 Arguments: 

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

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

32 simulator_interface: A VUnit SimulatorInterface class. 

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

34 """ 

35 self._vunit_proj = vunit_proj 

36 self._vivado_path = get_vivado_path(vivado_path) 

37 

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

39 

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

41 

42 def _compile(self): 

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

44 

45 self._compile_unisim(vivado_libraries_path / "unisims") 

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

47 self._compile_unimacro(vivado_libraries_path / "unimacro") 

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

49 

50 def _compile_unisim(self, library_path): 

51 for vhd_file_base in [ 

52 "unisim_VPKG", 

53 "unisim_retarget_VCOMP", 

54 ]: 

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

56 assert vhd_file.exists, vhd_file 

57 self._compile_ghdl_file(vhd_file, "unisim") 

58 

59 primitive_dir = library_path / "primitive" 

60 for vhd_file in self._iterate_compile_order(primitive_dir): 

61 self._compile_ghdl_file(vhd_file, "unisim") 

62 

63 retarget_dir = library_path / "retarget" 

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

65 self._compile_ghdl_file(vhd_file, "unisim") 

66 

67 def _compile_secureip(self, library_path): 

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

69 self._compile_ghdl_file(vhd_file, "secureip") 

70 

71 def _compile_unimacro(self, library_path): 

72 vhd_file = library_path / "unimacro_VCOMP.vhd" 

73 assert vhd_file.exists, vhd_file 

74 self._compile_ghdl_file(vhd_file, "unimacro") 

75 

76 for vhd_file in self._iterate_compile_order(library_path): 

77 self._compile_ghdl_file(vhd_file, "unimacro") 

78 

79 def _compile_unifast(self, library_path): 

80 for vhd_file in self._iterate_compile_order(library_path): 

81 self._compile_ghdl_file(vhd_file, "unifast") 

82 

83 @staticmethod 

84 def _iterate_compile_order(library_path): 

85 with open( 

86 library_path / "vhdl_analyze_order", encoding=DEFAULT_FILE_ENCODING 

87 ) as file_handle: 

88 for vhd_file_base in file_handle.readlines(): 

89 vhd_file = library_path / vhd_file_base.strip() 

90 assert vhd_file.exists(), vhd_file 

91 yield vhd_file 

92 

93 def _compile_ghdl_file(self, vhd_file, library_name): 

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

95 

96 workdir = self.output_path / library_name 

97 create_directory(workdir, empty=False) 

98 

99 cmd = [ 

100 self.ghdl_binary, 

101 "-a", 

102 "--ieee=synopsys", 

103 "--std=08", 

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

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

106 "-fexplicit", 

107 "-frelaxed-rules", 

108 "--no-vital-checks", 

109 "--warn-binding", 

110 "--mb-comments", 

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

112 str(vhd_file.resolve()), 

113 ] 

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

115 

116 def _get_simulator_tag(self): 

117 """ 

118 Return simulator version tag 

119 """ 

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

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

122 

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

124 match = regexp_with_tag.search(output) 

125 if match is not None: 

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

127 

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

129 match = regexp_without_tag.search(output) 

130 if match is not None: 

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

132 

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

134 

135 def _add_to_vunit_project(self): 

136 """ 

137 Add the compiled simlib to your VUnit project. 

138 """ 

139 for library_name in self.library_names: 

140 library_path = self.output_path / library_name 

141 assert library_path.exists(), library_path 

142 self._vunit_proj.add_external_library(library_name, library_path)