Coverage for hdl_registers/generator/vhdl/test/test_register_package.py: 100%

86 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-28 20:51 +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""" 

11Some limited unit tests that check the generated code. 

12Note that the generated VHDL code is also simulated in a functional test. 

13""" 

14 

15# Third party libraries 

16import pytest 

17from tsfpga.system_utils import read_file 

18 

19# First party libraries 

20from hdl_registers import HDL_REGISTERS_TESTS 

21from hdl_registers.field.numerical_interpretation import ( 

22 Signed, 

23 SignedFixedPoint, 

24 Unsigned, 

25 UnsignedFixedPoint, 

26) 

27from hdl_registers.generator.vhdl.register_package import VhdlRegisterPackageGenerator 

28from hdl_registers.parser.toml import from_toml 

29from hdl_registers.register_list import RegisterList 

30from hdl_registers.register_modes import REGISTER_MODES 

31 

32 

33def get_package(register_list, output_folder): 

34 return read_file(VhdlRegisterPackageGenerator(register_list, output_folder).create()) 

35 

36 

37class RegisterConfigurationTest: 

38 def __init__(self, name, source_toml_file): 

39 self.register_list = from_toml(name=name, toml_file=source_toml_file) 

40 

41 self.register_list.add_constant(name="boolean_constant", value=True, description="") 

42 self.register_list.add_constant(name="integer_constant", value=3, description="") 

43 self.register_list.add_constant(name="real_constant", value=3.14, description="") 

44 self.register_list.add_constant(name="real_big_constant", value=1e20, description="") 

45 self.register_list.add_constant(name="real_small_constant", value=4e-8, description="") 

46 self.register_list.add_constant(name="string_constant", value="apa", description="") 

47 

48 def test_vhdl_package(self, output_path, test_registers, test_constants): 

49 vhdl = get_package(register_list=self.register_list, output_folder=output_path) 

50 

51 if test_registers: 

52 assert "constant test_register_map : " in vhdl, vhdl 

53 else: 

54 assert "constant test_register_map : " not in vhdl, vhdl 

55 

56 if test_constants: 

57 assert "constant test_constant_boolean_constant : boolean := true;" in vhdl, vhdl 

58 assert "constant test_constant_integer_constant : integer := 3;" in vhdl, vhdl 

59 assert "constant test_constant_real_constant : real := 3.14;" in vhdl, vhdl 

60 assert "constant test_constant_real_big_constant : real := 1.0e+20;" in vhdl, vhdl 

61 assert "constant test_constant_real_small_constant : real := 4.0e-08;" in vhdl, vhdl 

62 assert 'constant test_constant_string_constant : string := "apa";' in vhdl, vhdl 

63 assert ( 

64 "constant test_constant_base_address_hex : " 

65 'unsigned(36 - 1 downto 0) := x"8_0000_0000";' in vhdl 

66 ), vhdl 

67 assert ( 

68 "constant test_constant_base_address_bin : " 

69 'unsigned(36 - 1 downto 0) := "100000000000000000000000000000000000";' in vhdl 

70 ), vhdl 

71 else: 

72 assert "boolean_constant" not in vhdl, vhdl 

73 assert "integer_constant" not in vhdl, vhdl 

74 assert "real_constant" not in vhdl, vhdl 

75 assert "string_constant" not in vhdl, vhdl 

76 

77 

78@pytest.fixture 

79def register_configuration(): 

80 return RegisterConfigurationTest("test", HDL_REGISTERS_TESTS / "regs_test.toml") 

81 

82 

83# False positive for pytest fixtures 

84# pylint: disable=redefined-outer-name 

85 

86 

87def test_vhdl_package_with_registers_and_constants(tmp_path, register_configuration): 

88 register_configuration.test_vhdl_package(tmp_path, test_registers=True, test_constants=True) 

89 

90 

91def test_vhdl_package_with_registers_and_no_constants(tmp_path, register_configuration): 

92 register_configuration.register_list.constants = [] 

93 register_configuration.test_vhdl_package(tmp_path, test_registers=True, test_constants=False) 

94 

95 

96def test_vhdl_package_with_constants_and_no_registers(tmp_path, register_configuration): 

97 register_configuration.register_list.register_objects = [] 

98 register_configuration.test_vhdl_package(tmp_path, test_registers=False, test_constants=True) 

99 

100 

101def test_vhdl_package_with_only_one_register(tmp_path): 

102 """ 

103 Test that register_map constant has valid VHDL syntax even when there is only one register. 

104 """ 

105 register_list = RegisterList(name="apa", source_definition_file=None) 

106 register_list.append_register( 

107 name="hest", mode=REGISTER_MODES["r"], description="a single register" 

108 ) 

109 vhdl = read_file(VhdlRegisterPackageGenerator(register_list, tmp_path).create()) 

110 

111 expected = """ 

112 constant apa_register_map : register_definition_vec_t(apa_register_range) := ( 

113 0 => (index => apa_hest, mode => r, utilized_width => 32) 

114 ); 

115 

116 constant apa_regs_init : apa_regs_t := ( 

117 0 => "00000000000000000000000000000000" 

118 ); 

119""" 

120 assert expected in vhdl, vhdl 

121 

122 

123def test_vhdl_typedef(tmp_path): 

124 register_list = RegisterList(name="test", source_definition_file=None) 

125 register = register_list.append_register("number", REGISTER_MODES["r_w"], "") 

126 

127 register.append_bit_vector( 

128 name="u0", 

129 description="", 

130 width=2, 

131 default_value="11", 

132 numerical_interpretation=Unsigned(bit_width=2), 

133 ) 

134 

135 register.append_bit_vector( 

136 name="s0", 

137 description="", 

138 width=2, 

139 default_value="11", 

140 numerical_interpretation=Signed(bit_width=2), 

141 ) 

142 

143 register.append_bit_vector( 

144 name="ufixed0", 

145 description="", 

146 width=2, 

147 default_value="11", 

148 numerical_interpretation=UnsignedFixedPoint(-1, -2), 

149 ) 

150 register.append_bit_vector( 

151 name="ufixed1", 

152 description="", 

153 width=8, 

154 default_value="1" * 8, 

155 numerical_interpretation=UnsignedFixedPoint(5, -2), 

156 ) 

157 

158 register.append_bit_vector( 

159 name="sfixed0", 

160 description="", 

161 width=2, 

162 default_value="11", 

163 numerical_interpretation=SignedFixedPoint(-1, -2), 

164 ) 

165 register.append_bit_vector( 

166 name="sfixed1", 

167 description="", 

168 width=6, 

169 default_value="1" * 6, 

170 numerical_interpretation=SignedFixedPoint(5, 0), 

171 ) 

172 

173 register.append_integer( 

174 name="integer0", description="", min_value=1, max_value=3, default_value=2 

175 ) 

176 

177 vhdl = read_file(VhdlRegisterPackageGenerator(register_list, tmp_path).create()) 

178 

179 assert "subtype test_number_u0_t is u_unsigned(1 downto 0);" in vhdl, vhdl 

180 

181 assert "subtype test_number_s0_t is u_signed(1 downto 0);" in vhdl, vhdl 

182 

183 assert "subtype test_number_ufixed0_t is ufixed(-1 downto -2);" in vhdl, vhdl 

184 assert "subtype test_number_ufixed1_t is ufixed(5 downto -2);" in vhdl, vhdl 

185 

186 assert "subtype test_number_sfixed0_t is sfixed(-1 downto -2);" in vhdl, vhdl 

187 assert "subtype test_number_sfixed1_t is sfixed(5 downto 0);" in vhdl, vhdl 

188 

189 assert "subtype test_number_integer0_t is integer range 1 to 3;" in vhdl, vhdl 

190 

191 

192def test_address_width(tmp_path): 

193 register_list = RegisterList(name="apa", source_definition_file=None) 

194 constant_name = "apa_address_width" 

195 

196 def check(num_addressing_bits): 

197 assert f"{constant_name} : positive := {num_addressing_bits + 2}" in get_package( 

198 register_list, tmp_path 

199 ) 

200 

201 assert constant_name not in get_package(register_list, tmp_path) 

202 

203 register_list.append_register("a", REGISTER_MODES["r"], "") 

204 check(1) 

205 

206 register_list.append_register("b", REGISTER_MODES["r"], "") 

207 check(1) 

208 

209 register_list.append_register("c", REGISTER_MODES["r"], "") 

210 check(2) 

211 

212 register_list.append_register_array("d", 2, "").append_register("e", REGISTER_MODES["r"], "") 

213 check(3)