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
« 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# --------------------------------------------------------------------------------------------------
10# Standard libraries
11from pathlib import Path
12from typing import TYPE_CHECKING, Optional
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
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
27class CppGeneratorCommon(RegisterCodeGenerator):
28 """
29 Class with common methods for generating C++ code.
30 """
32 COMMENT_START = "//"
34 def __init__(self, register_list: RegisterList, output_folder: Path):
35 super().__init__(register_list=register_list, output_folder=output_folder)
37 self._class_name = self.to_pascal_case(snake_string=self.name)
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
47 def _constructor_signature(self) -> str:
48 return f"{self._class_name}(volatile uint8_t *base_address)"
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}."
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"
74 return result
76 if isinstance(field, Integer) and field.is_signed:
77 # Type that can represent negative values also.
78 return "int32_t"
80 # The default for most fields.
81 return "uint32_t"
83 @staticmethod
84 def _register_getter_function_name(
85 register: "Register", register_array: Optional["RegisterArray"]
86 ) -> str:
87 result = "get"
89 if register_array:
90 result += f"_{register_array.name}"
92 result += f"_{register.name}"
94 return result
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}("
107 if register_array:
108 indentation = self.get_indentation(indent=indent)
109 result += f"\n{indentation} size_t array_index\n{indentation}"
111 result += ")"
113 return result
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"
124 if register_array:
125 result += f"_{register_array.name}"
127 result += f"_{register.name}_{field.name}"
129 if from_value:
130 result += "_from_value"
132 return result
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)
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}("
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}"
157 result += ")"
159 return result
161 @staticmethod
162 def _register_setter_function_name(
163 register: "Register", register_array: Optional["RegisterArray"]
164 ) -> str:
165 result = "set"
167 if register_array:
168 result += f"_{register_array.name}"
170 result += f"_{register.name}"
172 return result
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)
182 function_name = self._register_setter_function_name(
183 register=register, register_array=register_array
184 )
185 result = f"{function_name}(\n"
187 if register_array:
188 result += f"{indentation} size_t array_index,\n"
190 result += f"{indentation} uint32_t register_value\n{indentation})"
192 return result
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"
203 if register_array:
204 result += f"_{register_array.name}"
206 result += f"_{register.name}_{field.name}"
208 if from_value:
209 result += "_from_value"
211 return result
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)
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"
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"
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})"
241 return result