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 

10 

11from tsfpga.system_utils import read_file 

12from tsfpga.test.lint.test_copyright import CopyrightHeader 

13 

14 

15VHDL_COMMENT_SEPARATOR = "-- " + ("-" * (CopyrightHeader.separator_line_length - 3)) 

16 

17 

18class VhdlFileDocumentation: 

19 

20 """ 

21 Methods to extract documentation from a VHDL source file. 

22 """ 

23 

24 def __init__(self, vhd_file_path): 

25 """ 

26 Arguments: 

27 vhd_file_path (`pathlib.Path`): Path to the VHDL file which shall be documented. 

28 """ 

29 self._vhd_file_path = vhd_file_path 

30 

31 def get_header_rst(self): 

32 """ 

33 Get the contents of the VHDL file's header. This means everything that is in the comment 

34 block at the start of the file, after the copyright notice. 

35 

36 Return: 

37 str: File header content. 

38 """ 

39 file_contents = read_file(self._vhd_file_path) 

40 

41 documentation_header_regexp = re.compile( 

42 VHDL_COMMENT_SEPARATOR 

43 + r"\n(.+?)\n" 

44 + VHDL_COMMENT_SEPARATOR 

45 + r"\n(.+?)\n" 

46 + VHDL_COMMENT_SEPARATOR 

47 + r"\n\n", 

48 re.DOTALL, 

49 ) 

50 match = documentation_header_regexp.search(file_contents) 

51 if match is None: 

52 return None 

53 

54 # The first group will match the copyright header. Second group is documentation. 

55 lines = match.group(2).split("\n") 

56 text = "" 

57 for line in lines: 

58 if line == "--": 

59 text += "\n" 

60 else: 

61 # Remove initial "-- " from comments 

62 text += f"{line[3:]}\n" 

63 

64 return text 

65 

66 def get_symbolator_component(self): 

67 """ 

68 Return a string with a ``component`` declaration equivalent to the ``entity`` declaration 

69 within the file. (We use entity's but symbolator requires component's). 

70 

71 Default values and range declarations on ports are removed since symbolator does not seem 

72 to handle them. 

73 

74 Return: 

75 str: VHDL ``component`` declaration. ``None`` if file is a package, and hence contains 

76 no ``entity``. 

77 """ 

78 if self._vhd_file_path.name.endswith("_pkg.vhd"): 

79 # File is a package 

80 return None 

81 

82 entity_name = self._vhd_file_path.stem 

83 entity_regexp = re.compile( 

84 f"entity {entity_name} is" + r"\n(.+?)end entity;", re.IGNORECASE | re.DOTALL 

85 ) 

86 

87 file_contents = read_file(self._vhd_file_path) 

88 match = entity_regexp.search(file_contents) 

89 if match is None: 

90 return None 

91 

92 component = f"component {entity_name} is\n{match.group(1)}end component;" 

93 

94 # Remove default values. 

95 # Symbolator stops parsing if it encounters vector default values (others => ...). 

96 default_value_regexp = re.compile(r"\s+:=\s+[^;\n]+", re.IGNORECASE) 

97 component = default_value_regexp.sub("", component) 

98 

99 # Remove any vector range declarations in port list. 

100 # The lines become too long so they don't fit in the image. 

101 vector_regexp = re.compile(r"\([^;\n]+\)", re.IGNORECASE) 

102 component = vector_regexp.sub("", component) 

103 

104 return component