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

86 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""" 

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# Standard libraries 

16from pathlib import Path 

17 

18# Third party libraries 

19from tsfpga.system_utils import read_file 

20 

21# First party libraries 

22from hdl_registers.generator.vhdl.axi_lite.wrapper import VhdlAxiLiteWrapperGenerator 

23from hdl_registers.generator.vhdl.record_package import VhdlRecordPackageGenerator 

24from hdl_registers.generator.vhdl.register_package import VhdlRegisterPackageGenerator 

25from hdl_registers.generator.vhdl.simulation.check_package import ( 

26 VhdlSimulationCheckPackageGenerator, 

27) 

28from hdl_registers.generator.vhdl.simulation.read_write_package import ( 

29 VhdlSimulationReadWritePackageGenerator, 

30) 

31from hdl_registers.generator.vhdl.simulation.wait_until_package import ( 

32 VhdlSimulationWaitUntilPackageGenerator, 

33) 

34from hdl_registers.register_list import RegisterList 

35from hdl_registers.register_modes import REGISTER_MODES 

36 

37 

38def generate_all_vhdl_artifacts(register_list: RegisterList, output_folder: Path) -> None: 

39 VhdlRegisterPackageGenerator( 

40 register_list=register_list, output_folder=output_folder 

41 ).create_if_needed() 

42 

43 VhdlRecordPackageGenerator( 

44 register_list=register_list, output_folder=output_folder 

45 ).create_if_needed() 

46 

47 VhdlAxiLiteWrapperGenerator( 

48 register_list=register_list, output_folder=output_folder 

49 ).create_if_needed() 

50 

51 VhdlSimulationReadWritePackageGenerator( 

52 register_list=register_list, output_folder=output_folder 

53 ).create_if_needed() 

54 

55 VhdlSimulationCheckPackageGenerator( 

56 register_list=register_list, output_folder=output_folder 

57 ).create_if_needed() 

58 

59 VhdlSimulationWaitUntilPackageGenerator( 

60 register_list=register_list, output_folder=output_folder 

61 ).create_if_needed() 

62 

63 

64def generate_strange_register_maps(output_path): 

65 """ 

66 Generate register VHDL artifacts for some strange niche cases. 

67 """ 

68 

69 def create_packages(direction, mode): 

70 def append_register(data, name): 

71 """ 

72 Append a register with some fields. 

73 """ 

74 register = data.append_register( 

75 name=f"{name}_{mode.shorthand}", mode=mode, description="" 

76 ) 

77 

78 register.append_integer( 

79 name="integer", description="", min_value=-10, max_value=10, default_value=3 

80 ) 

81 register.append_enumeration( 

82 name="enumeration", description="", elements=dict(a="", b=""), default_value="b" 

83 ) 

84 

85 def append_registers(data): 

86 """ 

87 Append some registers with some fields, either to a RegisterList or a RegisterArray. 

88 """ 

89 append_register(data=data, name="first") 

90 append_register(data=data, name="second") 

91 

92 # Some plain registers, in one direction only. 

93 register_list = RegisterList(name=f"plain_only_{direction}") 

94 append_registers(data=register_list) 

95 generate_all_vhdl_artifacts(register_list=register_list, output_folder=output_path) 

96 

97 # Some register arrays, in one direction only. 

98 register_list = RegisterList(name=f"array_only_{direction}") 

99 register_array = register_list.append_register_array(name="apa", length=5, description="") 

100 append_registers(data=register_array) 

101 register_array = register_list.append_register_array(name="hest", length=10, description="") 

102 append_registers(data=register_array) 

103 generate_all_vhdl_artifacts(register_list=register_list, output_folder=output_path) 

104 

105 # Plain registers and some register arrays, in one direction only. 

106 register_list = RegisterList(name=f"plain_and_array_only_{direction}") 

107 append_registers(data=register_list) 

108 register_array = register_list.append_register_array(name="apa", length=5, description="") 

109 append_registers(data=register_array) 

110 register_array = register_list.append_register_array(name="hest", length=10, description="") 

111 append_registers(data=register_array) 

112 generate_all_vhdl_artifacts(register_list=register_list, output_folder=output_path) 

113 

114 # Mode 'Read only' should give registers only in the 'up' direction' 

115 create_packages(direction="up", mode=REGISTER_MODES["r"]) 

116 # Mode 'Write only' should give registers only in the 'down' direction' 

117 create_packages(direction="down", mode=REGISTER_MODES["w"]) 

118 

119 register_list = RegisterList(name="only_constants") 

120 register_list.add_constant(name="first", value=123, description="") 

121 register_list.add_constant(name="second", value=True, description="") 

122 generate_all_vhdl_artifacts(register_list=register_list, output_folder=output_path) 

123 

124 register_list = RegisterList(name="empty") 

125 generate_all_vhdl_artifacts(register_list=register_list, output_folder=output_path) 

126 

127 

128def _get_register_arrays_record_string(direction): 

129 return ( 

130 f"records for the registers of each register array the are in the '{direction}' direction" 

131 ) 

132 

133 

134def test_registers_only_in_up_direction_should_give_no_down_type_or_port(tmp_path): 

135 generate_strange_register_maps(output_path=tmp_path) 

136 

137 for file_name in ["array_only_up", "plain_and_array_only_up", "plain_only_up"]: 

138 vhd = read_file(tmp_path / f"{file_name}_register_record_pkg.vhd") 

139 

140 assert f"{file_name}_regs_up_t" in vhd 

141 assert f"{file_name}_regs_down_t" not in vhd 

142 

143 # If there are no arrays there should be no records for arrays, and this comment shall not 

144 # be present. 

145 string = _get_register_arrays_record_string("up") 

146 if "array" in file_name: 

147 assert string in vhd 

148 else: 

149 assert string not in vhd 

150 

151 # The 'down' comment shall never be present since we have no 'down' registers. 

152 string = _get_register_arrays_record_string("down") 

153 assert string not in vhd 

154 

155 vhd = read_file(tmp_path / f"{file_name}_reg_file.vhd") 

156 

157 assert "regs_up : in" in vhd 

158 assert "regs_down : out" not in vhd 

159 

160 assert "reg_was_read : out" in vhd 

161 assert "reg_was_written : out" not in vhd 

162 

163 

164def test_registers_only_in_down_direction_should_give_no_down_type_or_port(tmp_path): 

165 generate_strange_register_maps(output_path=tmp_path) 

166 

167 for file_name in ["array_only_down", "plain_and_array_only_down", "plain_only_down"]: 

168 vhd = read_file(tmp_path / f"{file_name}_register_record_pkg.vhd") 

169 

170 assert f"{file_name}_regs_up_t" not in vhd 

171 assert f"{file_name}_regs_down_t" in vhd 

172 

173 # If there are no arrays there should be no records for arrays, and this comment shall not 

174 # be present. 

175 string = _get_register_arrays_record_string("down") 

176 if "array" in file_name: 

177 assert string in vhd 

178 else: 

179 assert string not in vhd 

180 

181 # The 'up' comment shall never be present since we have no 'up' registers. 

182 string = _get_register_arrays_record_string("up") 

183 assert string not in vhd 

184 

185 vhd = read_file(tmp_path / f"{file_name}_reg_file.vhd") 

186 

187 assert "regs_up : in" not in vhd 

188 assert "regs_down : out" in vhd 

189 

190 assert "reg_was_read : out" not in vhd 

191 assert "reg_was_written : out" in vhd