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

27 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-27 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 

9from __future__ import annotations 

10 

11import re 

12from pathlib import Path 

13from typing import TYPE_CHECKING 

14 

15from tsfpga.system_utils import run_command 

16 

17from .simlib_open_source import VivadoSimlibOpenSource 

18 

19if TYPE_CHECKING: 

20 from vunit.sim_if import SimulatorInterface 

21 from vunit.ui import VUnit 

22 

23 

24class VivadoSimlibGhdl(VivadoSimlibOpenSource): 

25 """ 

26 Handle Vivado simlib with GHDL. 

27 

28 Do not instantiate this class directly. 

29 Use factory class :class:`.VivadoSimlib` instead. 

30 """ 

31 

32 # GHDL compilation crashes if its 'workdir' folder does not exist as the analyze command 

33 # is executed. 

34 _create_library_folder_before_compile = True 

35 

36 def __init__( 

37 self, 

38 vivado_path: Path | None, 

39 output_path: Path, 

40 vunit_proj: VUnit, 

41 simulator_interface: SimulatorInterface, 

42 ) -> None: 

43 """ 

44 See superclass :class:`.VivadoSimlibCommon` constructor for details. 

45 """ 

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

47 

48 super().__init__( 

49 vivado_path=vivado_path, 

50 output_path=output_path, 

51 vunit_proj=vunit_proj, 

52 simulator_interface=simulator_interface, 

53 ) 

54 

55 def _execute_compile(self, output_path: Path, library_name: str, vhd_files: list[str]) -> None: 

56 cmd = [ 

57 str(self.ghdl_binary), 

58 "-a", 

59 "--ieee=synopsys", 

60 "--std=08", 

61 f"--workdir={output_path}", 

62 f"-P{self.output_path / 'unisim'}", 

63 "-fexplicit", 

64 "-frelaxed-rules", 

65 "--no-vital-checks", 

66 "--warn-binding", 

67 "--mb-comments", 

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

69 *vhd_files, 

70 ] 

71 

72 run_command(cmd, cwd=self.output_path) 

73 

74 def _get_simulator_tag(self) -> str: 

75 """ 

76 Return simulator version tag as a string. 

77 """ 

78 cmd = [str(self.ghdl_binary), "--version"] 

79 output = run_command(cmd, capture_output=True).stdout 

80 

81 match_develop = re.search(pattern=r"^GHDL (\S+) \((\S+)\).*", string=output) 

82 if match_develop is not None: 

83 return self._format_version(f"ghdl_{match_develop.group(1)}_{match_develop.group(2)}") 

84 

85 match_release = re.search(pattern=r"^GHDL (\S+).*", string=output) 

86 if match_release is not None: 

87 return self._format_version(f"ghdl_{match_release.group(1)}") 

88 

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