OpenMPTL
C++ Microprocessor Template Library
register_access.hpp
Go to the documentation of this file.
1 /*
2  * OpenMPTL - C++ Microprocessor Template Library
3  *
4  * Copyright (C) 2012-2017 Axel Burri <axel@tty0.ch>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef REGISTER_ACCESS_HPP_INCLUDED
22 #define REGISTER_ACCESS_HPP_INCLUDED
23 
24 #include <compiler.h>
25 #include <register_type.hpp>
26 #include <arch/bitband.hpp>
27 
28 #ifdef OPENMPTL_SIMULATION
29 # include <register_sim.hpp>
30 #endif
31 
32 namespace mptl {
33 
34 #ifndef OPENMPTL_SIMULATION
35 
36 template<
37  typename Tp,
38  reg_addr_t _addr,
39  reg_perm _permission,
40  Tp reset_value
41  >
42 struct reg_access
43 {
44  static_assert(std::is_integral<Tp>::value, "Tp is not an integral type");
45  static_assert(std::is_unsigned<Tp>::value, "Tp is not an unsigned type");
46  static_assert(!std::is_volatile<Tp>::value, "Tp is a volatile-qualified type (why would you want this?)");
47 
48  /** Integral type used for register access. */
49  using value_type = Tp;
50 
51  static constexpr reg_addr_t addr = _addr;
52  static constexpr reg_perm permission = _permission;
53 
54  static constexpr bool bitop_enabled = bitband_periph::covered(addr);
55 
56  /** Load (read) register value. */
57  static __always_inline Tp load(void) {
58  static_assert(permission != wo, "read access to a write-only register");
59  return *reinterpret_cast<volatile Tp *>(addr);
60  }
61 
62  /** Store (write) a register value. */
63  static __always_inline void store(Tp const value) {
64  static_assert(permission != ro, "write access to a read-only register");
65  *reinterpret_cast<volatile Tp *>(addr) = value;
66  }
67 
68  /** Set a single bit using bitband_periph::bitset<> */
69  template<unsigned bit_no>
70  static __always_inline void bitset() {
71  static_assert(permission != ro, "write access to a read-only register");
72  bitband_periph::bitset<addr, bit_no>();
73  }
74 
75  /** Clear a single bit using bitband_periph::bitclear<> */
76  template<unsigned bit_no>
77  static __always_inline void bitclear() {
78  static_assert(permission != ro, "write access to a read-only register");
79  bitband_periph::bitclear<addr, bit_no>();
80  }
81 
82  /** Returns the value of a single bit using bitband_periph::bittest<> */
83  template<unsigned bit_no>
84  static __always_inline bool bittest() {
85  static_assert(permission != wo, "read access to a write-only register");
86  return bitband_periph::bittest<addr, bit_no>();
87  }
88 };
89 
90 
91 #else //////////////////// OPENMPTL_SIMULATION ////////////////////
92 
93 
94 template<
95  typename Tp,
96  reg_addr_t _addr,
97  reg_perm _permission,
98  Tp reset_value
99  >
100 class reg_access
101 {
102  static void store_impl(Tp const value) {
103  static_assert(permission != ro, "write access to a read-only register");
104 
105 #ifdef CONFIG_REGISTER_REACTION
106  sim::reg_reaction reaction(addr, reg_value);
107 #endif
108  reg_value = value;
109 #ifdef CONFIG_REGISTER_REACTION
111  reaction.react();
113 #endif
114  }
115 
116 public:
117  using value_type = Tp;
118  static Tp reg_value;
119 
120  static constexpr reg_addr_t addr = _addr;
121  static constexpr reg_perm permission = _permission;
122 
123  static constexpr bool bitop_enabled = bitband_periph::covered(addr);
124 
125 #ifdef CONFIG_DUMP_REGISTER_ACCESS
126  using dumper = sim::reg_dumper<Tp, addr>;
127 #endif
128 
129  static Tp load() {
130  static_assert(permission != wo, "read access to a write-only register");
131 #ifdef CONFIG_DUMP_REGISTER_ACCESS
132  dumper::dump_register_load(reg_value);
133 #endif // CONFIG_DUMP_REGISTER_ACCESS
134  return reg_value;
135  }
136 
137  static void store(Tp const value) {
138 #ifdef CONFIG_DUMP_REGISTER_ACCESS
139  dumper::dump_register_store(reg_value, value);
140 #endif
141  store_impl(value);
142  }
143 
144  template<unsigned bit_no>
145  static __always_inline void bitset() {
146  value_type value = reg_value | (1 << bit_no);
147 #ifdef CONFIG_DUMP_REGISTER_ACCESS
148  dumper::dump_register_bitset(reg_value, bit_no);
149 #endif
150  store_impl(value);
151  }
152 
153  template<unsigned bit_no>
154  static __always_inline void bitclear() {
155  value_type value = reg_value & ~(1 << bit_no);
156 #ifdef CONFIG_DUMP_REGISTER_ACCESS
157  dumper::dump_register_bitclear(reg_value, bit_no);
158 #endif
159  store_impl(value);
160  }
161 
162  template<unsigned bit_no>
163  static __always_inline bool bittest() {
164  static_assert(permission != wo, "read access to a write-only register");
165  value_type value = reg_value & (1 << bit_no);
166 #ifdef CONFIG_DUMP_REGISTER_ACCESS
167  dumper::dump_register_bittest(reg_value, bit_no);
168 #endif
169  return value;
170  }
171 };
172 
173 /* initialize reg_value to the reset value */
174 template<
175  typename Tp,
178  Tp reset_value
179  >
181 
182 #endif // OPENMPTL_SIMULATION
183 
184 } // namespace mptl
185 
186 #endif // REGISTER_ACCESS_HPP_INCLUDED
static __always_inline void bitset()
Set a single bit using bitband_periph::bitset<>
Definition: register_access.hpp:70
Definition: register_type.hpp:29
static constexpr reg_addr_t addr
Definition: register_access.hpp:51
uintptr_t reg_addr_t
Register address type (uintptr_t: unsigned integer type capable of holding a pointer) ...
Definition: register_type.hpp:33
#define __always_inline
Definition: compiler.h:8
Definition: register_access.hpp:42
Tp value_type
Integral type used for register access.
Definition: register_access.hpp:49
Definition: register_type.hpp:29
thread_local int regdump_reaction_running
void react()
Reaction function, must be implemented per-project.
Definition: register_sim.hpp:57
static __always_inline Tp load(void)
Load (read) register value.
Definition: register_access.hpp:57
Definition: register_sim.hpp:95
static constexpr reg_perm permission
Definition: register_access.hpp:52
static constexpr bool bitop_enabled
Definition: register_access.hpp:54
reg_perm
Register access permission.
Definition: register_type.hpp:29
Definition: fifo.hpp:26
static __always_inline bool bittest()
Returns the value of a single bit using bitband_periph::bittest<>
Definition: register_access.hpp:84
static __always_inline void store(Tp const value)
Store (write) a register value.
Definition: register_access.hpp:63
static __always_inline void bitclear()
Clear a single bit using bitband_periph::bitclear<>
Definition: register_access.hpp:77