Coverage for hdl_registers/generator/cpp/cpp_generator_common.py: 97%

106 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 TYPE_CHECKING, Optional 

13 

14# First party libraries 

15from hdl_registers.field.enumeration import Enumeration 

16from hdl_registers.field.integer import Integer 

17from hdl_registers.generator.register_code_generator import RegisterCodeGenerator 

18from hdl_registers.register_list import RegisterList 

19 

20if TYPE_CHECKING: 

21 # First party libraries 

22 from hdl_registers.field.register_field import RegisterField 

23 from hdl_registers.register import Register 

24 from hdl_registers.register_array import RegisterArray 

25 

26 

27class CppGeneratorCommon(RegisterCodeGenerator): 

28 """ 

29 Class with common methods for generating C++ code. 

30 """ 

31 

32 COMMENT_START = "//" 

33 

34 def __init__(self, register_list: RegisterList, output_folder: Path): 

35 super().__init__(register_list=register_list, output_folder=output_folder) 

36 

37 self._class_name = self.to_pascal_case(snake_string=self.name) 

38 

39 @staticmethod 

40 def _with_namespace(cpp_code_body: str) -> str: 

41 cpp_code = "namespace fpga_regs\n" 

42 cpp_code += "{\n\n" 

43 cpp_code += f"{cpp_code_body}" 

44 cpp_code += "} /* namespace fpga_regs */\n" 

45 return cpp_code 

46 

47 def _constructor_signature(self) -> str: 

48 return f"{self._class_name}(volatile uint8_t *base_address)" 

49 

50 def _get_methods_description( 

51 self, register: "Register", register_array: Optional["RegisterArray"] 

52 ) -> str: 

53 register_description = self.register_description( 

54 register=register, register_array=register_array 

55 ) 

56 return f"Methods for the {register_description}." 

57 

58 def _field_value_type_name( 

59 self, 

60 register: "Register", 

61 register_array: Optional["RegisterArray"], 

62 field: "RegisterField", 

63 ) -> str: 

64 """ 

65 The name of the type used to represent the field. 

66 """ 

67 if isinstance(field, Enumeration): 

68 # The name of an enum available in this field's attributes. 

69 result = f"{self.name}::" 

70 if register_array: 

71 result += f"{register_array.name}::" 

72 result += f"{register.name}::{field.name}::Enumeration" 

73 

74 return result 

75 

76 if isinstance(field, Integer) and field.is_signed: 

77 # Type that can represent negative values also. 

78 return "int32_t" 

79 

80 # The default for most fields. 

81 return "uint32_t" 

82 

83 @staticmethod 

84 def _register_getter_function_name( 

85 register: "Register", register_array: Optional["RegisterArray"] 

86 ) -> str: 

87 result = "get" 

88 

89 if register_array: 

90 result += f"_{register_array.name}" 

91 

92 result += f"_{register.name}" 

93 

94 return result 

95 

96 def _register_getter_function_signature( 

97 self, 

98 register: "Register", 

99 register_array: Optional["RegisterArray"], 

100 indent: Optional[int] = None, 

101 ) -> str: 

102 function_name = self._register_getter_function_name( 

103 register=register, register_array=register_array 

104 ) 

105 result = f"{function_name}(" 

106 

107 if register_array: 

108 indentation = self.get_indentation(indent=indent) 

109 result += f"\n{indentation} size_t array_index\n{indentation}" 

110 

111 result += ")" 

112 

113 return result 

114 

115 @staticmethod 

116 def _field_getter_function_name( 

117 register: "Register", 

118 register_array: Optional["RegisterArray"], 

119 field: "RegisterField", 

120 from_value: bool, 

121 ) -> str: 

122 result = "get" 

123 

124 if register_array: 

125 result += f"_{register_array.name}" 

126 

127 result += f"_{register.name}_{field.name}" 

128 

129 if from_value: 

130 result += "_from_value" 

131 

132 return result 

133 

134 def _field_getter_function_signature( 

135 self, 

136 register: "Register", 

137 register_array: Optional["RegisterArray"], 

138 field: "RegisterField", 

139 from_value: bool, 

140 indent: Optional[int] = None, 

141 ) -> str: 

142 indentation = self.get_indentation(indent=indent) 

143 

144 function_name = self._field_getter_function_name( 

145 register=register, register_array=register_array, field=field, from_value=from_value 

146 ) 

147 result = f"{function_name}(" 

148 

149 if from_value: 

150 # Value is supplied by user 

151 result += f"\n{indentation} uint32_t register_value\n{indentation}" 

152 elif register_array: 

153 # Value shall be read from bus, in which case we need to know array index if this 

154 # is an array 

155 result += f"\n{indentation} size_t array_index\n{indentation}" 

156 

157 result += ")" 

158 

159 return result 

160 

161 @staticmethod 

162 def _register_setter_function_name( 

163 register: "Register", register_array: Optional["RegisterArray"] 

164 ) -> str: 

165 result = "set" 

166 

167 if register_array: 

168 result += f"_{register_array.name}" 

169 

170 result += f"_{register.name}" 

171 

172 return result 

173 

174 def _register_setter_function_signature( 

175 self, 

176 register: "Register", 

177 register_array: Optional["RegisterArray"], 

178 indent: Optional[int] = None, 

179 ) -> str: 

180 indentation = self.get_indentation(indent=indent) 

181 

182 function_name = self._register_setter_function_name( 

183 register=register, register_array=register_array 

184 ) 

185 result = f"{function_name}(\n" 

186 

187 if register_array: 

188 result += f"{indentation} size_t array_index,\n" 

189 

190 result += f"{indentation} uint32_t register_value\n{indentation})" 

191 

192 return result 

193 

194 @staticmethod 

195 def _field_setter_function_name( 

196 register: "Register", 

197 register_array: Optional["RegisterArray"], 

198 field: "RegisterField", 

199 from_value: bool, 

200 ) -> str: 

201 result = "set" 

202 

203 if register_array: 

204 result += f"_{register_array.name}" 

205 

206 result += f"_{register.name}_{field.name}" 

207 

208 if from_value: 

209 result += "_from_value" 

210 

211 return result 

212 

213 def _field_setter_function_signature( 

214 self, 

215 register: "Register", 

216 register_array: Optional["RegisterArray"], 

217 field: "RegisterField", 

218 from_value: bool, 

219 indent: Optional[int] = None, 

220 ) -> str: 

221 indentation = self.get_indentation(indent=indent) 

222 

223 function_name = self._field_setter_function_name( 

224 register=register, register_array=register_array, field=field, from_value=from_value 

225 ) 

226 result = f"{function_name}(\n" 

227 

228 if from_value: 

229 # Current register value is supplied by user 

230 result += f"{indentation} uint32_t register_value,\n" 

231 elif register_array: 

232 # Current register value shall be read from bus, in which case we need to know array 

233 # index if this is an array 

234 result += f"{indentation} size_t array_index,\n" 

235 

236 type_name = self._field_value_type_name( 

237 register=register, register_array=register_array, field=field 

238 ) 

239 result += f"{indentation} {type_name} field_value\n{indentation})" 

240 

241 return result