Coverage for hdl_registers/generator/python/test/accessor/conftest.py: 100%

56 statements  

« prev     ^ index     » next       coverage.py v7.6.8, created at 2024-12-01 20:50 +0000

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

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

3# 

4# This file is part of the hdl-registers project, an HDL register generator fast enough to run 

5# in real time. 

6# https://hdl-registers.com 

7# https://github.com/hdl-registers/hdl-registers 

8# -------------------------------------------------------------------------------------------------- 

9 

10# Standard libraries 

11from pathlib import Path 

12from typing import Union 

13 

14# Third party libraries 

15import pytest 

16from tsfpga.system_utils import load_python_module 

17 

18# First party libraries 

19from hdl_registers.field.numerical_interpretation import ( 

20 Signed, 

21 SignedFixedPoint, 

22 Unsigned, 

23 UnsignedFixedPoint, 

24) 

25from hdl_registers.generator.python.accessor import PythonAccessorGenerator 

26from hdl_registers.generator.python.pickle import PythonPickleGenerator 

27from hdl_registers.register_array import RegisterArray 

28from hdl_registers.register_list import RegisterList 

29from hdl_registers.register_mode import RegisterMode 

30from hdl_registers.register_modes import REGISTER_MODES 

31 

32# False positive for pytest fixtures 

33# pylint: disable=redefined-outer-name 

34 

35 

36@pytest.fixture(scope="session") 

37def tmp_session_path(tmp_path_factory: pytest.TempdirFactory) -> Path: 

38 """ 

39 tmp_path that is common for all test runs in this session. 

40 Unlike the default tmp_path fixture, which is function scoped. 

41 https://stackoverflow.com/questions/70779045 

42 https://docs.pytest.org/en/6.2.x/tmpdir.html#the-tmp-path-factory-fixture 

43 """ 

44 return tmp_path_factory.mktemp("temp") 

45 

46 

47@pytest.fixture(scope="session") 

48def generate_default_accessor(tmp_session_path): 

49 """ 

50 Since all the tests use the same register list, we can save a lot of time by generating the 

51 Python code artifact only once. 

52 We run a huge amount of tests for the accessor, and the file generation takes 0.5-1 second, 

53 so the gain is significant. 

54 """ 

55 register_list = RegisterList(name="test") 

56 

57 add_test_registers(register_list_or_array=register_list) 

58 add_empty_registers(register_list_or_array=register_list) 

59 add_single_field_registers(register_list_or_array=register_list) 

60 

61 register_array = register_list.append_register_array( 

62 name="reg_array_a", length=3, description="" 

63 ) 

64 add_test_registers(register_list_or_array=register_array) 

65 add_empty_registers(register_list_or_array=register_array) 

66 add_single_field_registers(register_list_or_array=register_array) 

67 

68 PythonPickleGenerator(register_list=register_list, output_folder=tmp_session_path).create() 

69 PythonAccessorGenerator(register_list=register_list, output_folder=tmp_session_path).create() 

70 

71 python_module = load_python_module(tmp_session_path / "test_accessor.py") 

72 

73 return tmp_session_path, python_module 

74 

75 

76def add_test_registers(register_list_or_array: Union[RegisterList, RegisterArray]) -> None: 

77 for mode in REGISTER_MODES.values(): 

78 setup_test_register(register_list_or_array=register_list_or_array, mode=mode) 

79 

80 

81def setup_test_register( 

82 register_list_or_array: Union[RegisterList, RegisterArray], mode: RegisterMode 

83) -> None: 

84 register = register_list_or_array.append_register( 

85 f"reg_{mode.shorthand}", mode=mode, description="" 

86 ) 

87 

88 register.append_bit(name="bit_aa0", description="", default_value="0") 

89 register.append_bit(name="bit_aa1", description="", default_value="1") 

90 

91 register.append_bit_vector( 

92 name="unsigned_aa", 

93 description="", 

94 width=4, 

95 default_value="0101", 

96 numerical_interpretation=Unsigned(bit_width=4), 

97 ) 

98 register.append_bit_vector( 

99 name="signed_aa", 

100 description="", 

101 width=4, 

102 default_value="1010", 

103 numerical_interpretation=Signed(bit_width=4), 

104 ) 

105 register.append_bit_vector( 

106 name="ufixed_aa", 

107 description="", 

108 width=4, 

109 default_value="0110", 

110 numerical_interpretation=UnsignedFixedPoint(1, -2), 

111 ) 

112 register.append_bit_vector( 

113 name="sfixed_aa", 

114 description="", 

115 width=4, 

116 default_value="1001", 

117 numerical_interpretation=SignedFixedPoint(0, -3), 

118 ) 

119 

120 register.append_enumeration( 

121 name="enumeration_aa", 

122 description="", 

123 elements=dict(element_aa0="", element_aa1="", element_aa2=""), 

124 default_value="element_aa1", 

125 ) 

126 

127 register.append_integer( 

128 name="uint_aa", description="", min_value=0, max_value=10, default_value=5 

129 ) 

130 register.append_integer( 

131 name="sint_aa", description="", min_value=-10, max_value=10, default_value=2 

132 ) 

133 

134 

135def add_empty_registers(register_list_or_array: Union[RegisterList, RegisterArray]) -> None: 

136 for mode in REGISTER_MODES.values(): 

137 register_list_or_array.append_register( 

138 name=f"empty_{mode.shorthand}", mode=mode, description="" 

139 ) 

140 

141 

142def add_single_field_registers(register_list_or_array: Union[RegisterList, RegisterArray]) -> None: 

143 register = register_list_or_array.append_register( 

144 "single_w_bit", mode=REGISTER_MODES["w"], description="" 

145 ) 

146 register.append_bit(name="bit_bb", description="", default_value="1") 

147 

148 register = register_list_or_array.append_register( 

149 "single_w_unsigned", mode=REGISTER_MODES["w"], description="" 

150 ) 

151 register.append_bit_vector( 

152 name="unsigned_bb", 

153 description="", 

154 width=4, 

155 default_value="1011", 

156 numerical_interpretation=Unsigned(bit_width=4), 

157 ) 

158 

159 register = register_list_or_array.append_register( 

160 "single_r_w_sfixed", mode=REGISTER_MODES["r_w"], description="" 

161 ) 

162 register.append_bit_vector( 

163 name="sfixed_bb", 

164 description="", 

165 width=4, 

166 default_value="1100", 

167 numerical_interpretation=SignedFixedPoint(1, -2), 

168 ) 

169 

170 register = register_list_or_array.append_register( 

171 "single_wpulse_enumeration", mode=REGISTER_MODES["wpulse"], description="" 

172 ) 

173 register.append_enumeration( 

174 name="enumeration_bb", 

175 description="", 

176 elements=dict(element_bb0="", element_bb1="", element_bb2=""), 

177 default_value="element_bb2", 

178 ) 

179 

180 register = register_list_or_array.append_register( 

181 "single_r_wpulse_uint", mode=REGISTER_MODES["r_wpulse"], description="" 

182 ) 

183 register.append_integer( 

184 name="uint_bb", description="", min_value=10, max_value=15, default_value=15 

185 )