Coverage for hdl_registers/generator/cpp/header.py: 100%
38 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 11:11 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-03-12 11:11 +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# --------------------------------------------------------------------------------------------------
10from pathlib import Path
11from typing import Any
13from .cpp_generator_common import CppGeneratorCommon
16class CppHeaderGenerator(CppGeneratorCommon):
17 """
18 Generate a C++ class header.
19 See the :ref:`generator_cpp` article for usage details.
21 The class header will contain:
23 * for each register, signature of getter and setter methods for reading/writing the register as
24 an ``uint``.
26 * for each field in each register, signature of getter and setter methods for reading/writing
27 the field as its native type (enumeration, positive/negative int, etc.).
29 * The setter will read-modify-write the register to update only the specified field,
30 depending on the mode of the register.
31 """
33 __version__ = "1.0.0"
35 SHORT_DESCRIPTION = "C++ header"
37 DEFAULT_INDENTATION_LEVEL = 4
39 @property
40 def output_file(self) -> Path:
41 """
42 Result will be placed in this file.
43 """
44 return self.output_folder / f"{self.name}.h"
46 def get_code(
47 self,
48 **kwargs: Any, # noqa: ANN401, ARG002
49 ) -> str:
50 """
51 Get a complete C++ class header with methods for accessing registers and fields.
52 """
53 cpp_code = f"""\
54 class {self._class_name} : public I{self._class_name}
55 {
56 private:
57 volatile uint32_t *m_registers;
58 bool (*m_assertion_handler) (const std::string*);
60 public:
61 /**
62 * Class constructor.
63 * @param base_address Byte address where these registers are memory mapped.
64 * Can be e.g. '0x43C00000' in bare metal, or e.g.
65 * 'reinterpret_cast<uintptr_t>(mmap(...))' in Linux.
66 * When using an operating system, care must be taken to pass the
67 * virtual address, not the physical address.
68 * When using bare metal, these are the same.
69 * @param assertion_handler Function to call when an assertion fails.
70 * Function takes a string pointer as an argument and must return a
71 * boolean 'true'.
72 */
73 {self._constructor_signature()};
75 virtual ~{self._class_name}() { }
76"""
78 def function(return_type_name: str, signature: str) -> str:
79 return f" virtual {return_type_name} {signature} const override;\n"
81 for register, register_array in self.iterate_registers():
82 cpp_code += f"\n{self.get_separator_line()}"
84 description = self._get_methods_description(
85 register=register, register_array=register_array
86 )
87 cpp_code += self.comment_block(
88 text=[description, "See interface header for documentation."]
89 )
91 if register.mode.software_can_read:
92 signature = self._register_getter_function_signature(
93 register=register, register_array=register_array
94 )
95 cpp_code += function(return_type_name="uint32_t", signature=signature)
97 for field in register.fields:
98 field_type_name = self._field_value_type_name(
99 register=register, register_array=register_array, field=field
100 )
102 signature = self._field_getter_function_signature(
103 register=register,
104 register_array=register_array,
105 field=field,
106 from_value=False,
107 )
108 cpp_code += function(return_type_name=field_type_name, signature=signature)
110 signature = self._field_getter_function_signature(
111 register=register,
112 register_array=register_array,
113 field=field,
114 from_value=True,
115 )
116 cpp_code += function(return_type_name=field_type_name, signature=signature)
118 if register.mode.software_can_write:
119 signature = self._register_setter_function_signature(
120 register=register, register_array=register_array
121 )
123 cpp_code += function(return_type_name="void", signature=signature)
125 for field in register.fields:
126 signature = self._field_setter_function_signature(
127 register=register,
128 register_array=register_array,
129 field=field,
130 from_value=False,
131 )
132 cpp_code += function(return_type_name="void", signature=signature)
134 signature = self._field_setter_function_signature(
135 register=register,
136 register_array=register_array,
137 field=field,
138 from_value=True,
139 )
140 cpp_code += function(return_type_name="uint32_t", signature=signature)
142 cpp_code += " };\n"
144 cpp_code_top = f"""\
145#pragma once
147#include "i_{self.name}.h"
149"""
150 return cpp_code_top + self._with_namespace(cpp_code)