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

106 statements  

« prev     ^ index     » next       coverage.py v7.6.9, created at 2024-12-19 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# 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 ( 

49 f"{self._class_name}(volatile uint8_t *base_address, " 

50 "bool (*assertion_handler) (const std::string*))" 

51 ) 

52 

53 def _get_methods_description( 

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

55 ) -> str: 

56 register_description = self.register_description( 

57 register=register, register_array=register_array 

58 ) 

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

60 

61 def _field_value_type_name( 

62 self, 

63 register: "Register", 

64 register_array: Optional["RegisterArray"], 

65 field: "RegisterField", 

66 ) -> str: 

67 """ 

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

69 """ 

70 if isinstance(field, Enumeration): 

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

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

73 if register_array: 

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

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

76 

77 return result 

78 

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

80 # Type that can represent negative values also. 

81 return "int32_t" 

82 

83 # The default for most fields. 

84 return "uint32_t" 

85 

86 @staticmethod 

87 def _register_getter_function_name( 

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

89 ) -> str: 

90 result = "get" 

91 

92 if register_array: 

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

94 

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

96 

97 return result 

98 

99 def _register_getter_function_signature( 

100 self, 

101 register: "Register", 

102 register_array: Optional["RegisterArray"], 

103 indent: Optional[int] = None, 

104 ) -> str: 

105 function_name = self._register_getter_function_name( 

106 register=register, register_array=register_array 

107 ) 

108 result = f"{function_name}(" 

109 

110 if register_array: 

111 indentation = self.get_indentation(indent=indent) 

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

113 

114 result += ")" 

115 

116 return result 

117 

118 @staticmethod 

119 def _field_getter_function_name( 

120 register: "Register", 

121 register_array: Optional["RegisterArray"], 

122 field: "RegisterField", 

123 from_value: bool, 

124 ) -> str: 

125 result = "get" 

126 

127 if register_array: 

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

129 

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

131 

132 if from_value: 

133 result += "_from_value" 

134 

135 return result 

136 

137 def _field_getter_function_signature( 

138 self, 

139 register: "Register", 

140 register_array: Optional["RegisterArray"], 

141 field: "RegisterField", 

142 from_value: bool, 

143 indent: Optional[int] = None, 

144 ) -> str: 

145 indentation = self.get_indentation(indent=indent) 

146 

147 function_name = self._field_getter_function_name( 

148 register=register, register_array=register_array, field=field, from_value=from_value 

149 ) 

150 result = f"{function_name}(" 

151 

152 if from_value: 

153 # Value is supplied by user 

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

155 elif register_array: 

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

157 # is an array 

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

159 

160 result += ")" 

161 

162 return result 

163 

164 @staticmethod 

165 def _register_setter_function_name( 

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

167 ) -> str: 

168 result = "set" 

169 

170 if register_array: 

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

172 

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

174 

175 return result 

176 

177 def _register_setter_function_signature( 

178 self, 

179 register: "Register", 

180 register_array: Optional["RegisterArray"], 

181 indent: Optional[int] = None, 

182 ) -> str: 

183 indentation = self.get_indentation(indent=indent) 

184 

185 function_name = self._register_setter_function_name( 

186 register=register, register_array=register_array 

187 ) 

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

189 

190 if register_array: 

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

192 

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

194 

195 return result 

196 

197 @staticmethod 

198 def _field_setter_function_name( 

199 register: "Register", 

200 register_array: Optional["RegisterArray"], 

201 field: "RegisterField", 

202 from_value: bool, 

203 ) -> str: 

204 result = "set" 

205 

206 if register_array: 

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

208 

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

210 

211 if from_value: 

212 result += "_from_value" 

213 

214 return result 

215 

216 def _field_setter_function_signature( 

217 self, 

218 register: "Register", 

219 register_array: Optional["RegisterArray"], 

220 field: "RegisterField", 

221 from_value: bool, 

222 indent: Optional[int] = None, 

223 ) -> str: 

224 indentation = self.get_indentation(indent=indent) 

225 

226 function_name = self._field_setter_function_name( 

227 register=register, register_array=register_array, field=field, from_value=from_value 

228 ) 

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

230 

231 if from_value: 

232 # Current register value is supplied by user 

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

234 elif register_array: 

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

236 # index if this is an array 

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

238 

239 type_name = self._field_value_type_name( 

240 register=register, register_array=register_array, field=field 

241 ) 

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

243 

244 return result