Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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.system_utils import create_directory 

14from .common import get_vivado_path 

15from .simlib_common import VivadoSimlibCommon 

16 

17 

18class VivadoSimlibGhdl(VivadoSimlibCommon): 

19 

20 """ 

21 Handle Vivado simlib with GHDL. 

22 """ 

23 

24 _libraries = ["unisim", "secureip", "unimacro", "unifast"] 

25 

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

27 """ 

28 Arguments: 

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

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

31 simulator_interface: A VUnit SimulatorInterface class. 

32 vivado_path (`pathlib.Path`): Path to Vivado executable. 

33 """ 

34 self._vunit_proj = vunit_proj 

35 self._vivado_path = get_vivado_path(vivado_path) 

36 

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

38 

39 self._output_path = output_path / self._get_version_tag() 

40 

41 def _compile(self): 

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

43 

44 self._compile_unisim(vivado_libraries_path / "unisims") 

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

46 self._compile_unimacro(vivado_libraries_path / "unimacro") 

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

48 

49 def _compile_unisim(self, library_path): 

50 for vhd_file_base in [ 

51 "unisim_VPKG", 

52 "unisim_retarget_VCOMP", 

53 ]: 

54 vhd_file = library_path / (vhd_file_base + ".vhd") 

55 assert vhd_file.exists, vhd_file 

56 self._compile_ghdl_file(vhd_file, "unisim") 

57 

58 primitive_dir = library_path / "primitive" 

59 for vhd_file in self._iterate_compile_order(primitive_dir): 

60 self._compile_ghdl_file(vhd_file, "unisim") 

61 

62 retarget_dir = library_path / "retarget" 

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

64 self._compile_ghdl_file(vhd_file, "unisim") 

65 

66 def _compile_secureip(self, library_path): 

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

68 self._compile_ghdl_file(vhd_file, "secureip") 

69 

70 def _compile_unimacro(self, library_path): 

71 vhd_file = library_path / "unimacro_VCOMP.vhd" 

72 assert vhd_file.exists, vhd_file 

73 self._compile_ghdl_file(vhd_file, "unimacro") 

74 

75 for vhd_file in self._iterate_compile_order(library_path): 

76 self._compile_ghdl_file(vhd_file, "unimacro") 

77 

78 def _compile_unifast(self, library_path): 

79 for vhd_file in self._iterate_compile_order(library_path): 

80 self._compile_ghdl_file(vhd_file, "unifast") 

81 

82 @staticmethod 

83 def _iterate_compile_order(library_path): 

84 with (library_path / "vhdl_analyze_order").open() as file_handle: 

85 for vhd_file_base in file_handle.readlines(): 

86 vhd_file = library_path / vhd_file_base.strip() 

87 assert vhd_file.exists(), vhd_file 

88 yield vhd_file 

89 

90 def _compile_ghdl_file(self, vhd_file, library_name): 

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

92 workdir = self._output_path / library_name / "v08" 

93 create_directory(workdir, empty=False) 

94 cmd = [ 

95 self.ghdl_binary, 

96 "-a", 

97 "--ieee=synopsys", 

98 "--std=08", 

99 "--workdir=" + str(workdir.resolve()), 

100 "-P" + str(self._output_path), 

101 "-fexplicit", 

102 "-frelaxed-rules", 

103 "--no-vital-checks", 

104 "--warn-binding", 

105 "--mb-comments", 

106 "--work=" + library_name, 

107 str(vhd_file.resolve()), 

108 ] 

109 subprocess.check_call(cmd, cwd=self._output_path) 

110 

111 def _get_simulator_tag(self): 

112 """ 

113 Return simulator version tag 

114 """ 

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

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

117 

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

119 match = regexp_with_tag.search(output) 

120 if match is not None: 

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

122 

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

124 match = regexp_without_tag.search(output) 

125 if match is not None: 

126 return self._format_version("ghdl_" + match.group(1)) 

127 

128 raise ValueError("Could not find GHDL version string: " + output) 

129 

130 def _add_to_vunit_project(self): 

131 """ 

132 Add the compiled simlib to your VUnit project. 

133 """ 

134 for library in self._libraries: 

135 library_path = self._output_path / library / "v08" 

136 assert library_path.exists(), library_path 

137 self._vunit_proj.add_external_library(library, library_path)