Coverage for tsfpga/vivado/simlib_nvc.py: 73%

30 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 VivadoSimlibNvc(VivadoSimlibOpenSource): 

25 """ 

26 Handle Vivado simlib with NVC. 

27 

28 Do not instantiate this class directly. 

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

30 """ 

31 

32 # NVC compilation gives a warning if the folder exist when the analyze command is executed. 

33 _create_library_folder_before_compile = False 

34 

35 def __init__( 

36 self, 

37 vivado_path: Path | None, 

38 output_path: Path, 

39 vunit_proj: VUnit, 

40 simulator_interface: SimulatorInterface, 

41 ) -> None: 

42 """ 

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

44 """ 

45 self.nvc_binary = Path(simulator_interface.find_prefix()) / "nvc" 

46 

47 super().__init__( 

48 vivado_path=vivado_path, 

49 output_path=output_path, 

50 vunit_proj=vunit_proj, 

51 simulator_interface=simulator_interface, 

52 ) 

53 

54 def _execute_compile( 

55 self, 

56 output_path: Path, # noqa: ARG002 

57 library_name: str, 

58 vhd_files: list[str], 

59 ) -> None: 

60 cmd = [ 

61 str(self.nvc_binary), 

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

63 "--std=2008", 

64 "-M", 

65 "64m", 

66 ] 

67 if library_name != "unisim": 

68 cmd.append( 

69 f"--map=unisim:{self.output_path / 'unisim'}", 

70 ) 

71 

72 cmd += ["-a", *vhd_files] 

73 

74 run_command(cmd, cwd=self.output_path) 

75 

76 def _get_simulator_tag(self) -> str: 

77 """ 

78 Return simulator version tag as a string. 

79 """ 

80 cmd = [str(self.nvc_binary), "--version"] 

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

82 

83 match_release = re.search(pattern=r"^nvc (\S+) \(Using.*", string=output) 

84 if match_release is not None: 

85 return self._format_version(f"nvc_{match_release.group(1)}") 

86 

87 match_develop = re.search(pattern=r"^nvc (\S+) \((\S+)\) \(Using.*", string=output) 

88 if match_develop is not None: 

89 return self._format_version(f"nvc_{match_develop.group(1)}_{match_develop.group(2)}") 

90 

91 raise ValueError(f"Could not find NVC version string: {output}")