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