-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathRegister.h
More file actions
131 lines (104 loc) · 4.09 KB
/
Copy pathRegister.h
File metadata and controls
131 lines (104 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! Register type implementation.
/**
* @file Register.h
* @author Nicolas Clauvelin (nclauvelin@sendyne.com)
* @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved.
*
* This header provides the definitions related to register implementation.
*/
#ifndef CPPREG_REGISTER_H
#define CPPREG_REGISTER_H
#include "Memory.h"
#include "MergeWrite.h"
#include "ShadowValue.h"
namespace cppreg {
//! Register data structure.
/**
* @tparam reg_address Register address.
* @tparam reg_size Register size enum value.
* @tparam reset_value Register reset value (0x0 if unknown).
* @tparam use_shadow shadow Boolean flag to enable shadow value.
*
* This data structure will act as a container for fields and is
* therefore limited to a strict minimum. It only carries information
* about the register base address, size, and reset value.
* In practice, register are implemented by deriving from this class to
* create custom types.
*/
template <Address reg_address,
RegBitSize reg_size,
typename TypeTraits<reg_size>::type reset_value = 0x0,
bool use_shadow = false>
struct Register {
//! Register base type.
using type = typename TypeTraits<reg_size>::type; // NOLINT
//! MMIO pointer type.
using MMIO = volatile type;
//! Boolean flag for shadow value management.
using shadow = Shadow<Register, use_shadow>; // NOLINT
//! Register base address.
constexpr static auto base_address = reg_address;
//! Register size in bits.
constexpr static auto size = TypeTraits<reg_size>::bit_size;
//! Register reset value.
constexpr static auto reset = reset_value;
//! Register pack for memory device.
using pack = RegisterPack<base_address, size / one_byte>; // NOLINT
//! Memory modifier.
/**
* @return A reference to the writable register memory.
*/
static MMIO& rw_mem_device() {
using MemDevice = typename RegisterMemoryDevice<pack>::mem_device;
return MemDevice::template rw_memory<reg_size, 0>();
}
//! Memory accessor.
/**
* @return A reference to the read-only register memory.
*/
static const MMIO& ro_mem_device() {
using MemDevice = typename RegisterMemoryDevice<pack>::mem_device;
return MemDevice::template ro_memory<reg_size, 0>();
}
//! Merge write start function.
/**
* @tparam F Field on which to perform the first write operation.
* @param value Value to be written to the field.
* @return A merge write data structure to chain further writes.
*/
template <typename F>
static MergeWrite<typename F::parent_register, F::mask> merge_write(
const typename F::type value) noexcept {
const auto lhs = static_cast<type>(value << F::offset);
return MergeWrite<typename F::parent_register, F::mask>::create(
static_cast<type>(lhs & F::mask));
}
//! Merge write start function for constant value.
/**
* @tparam F Field on which to perform the first write operation.
* @tparam value Value to be written to the field.
* @return A merge write data structure to chain further writes.
*/
template <typename F,
type value,
typename T = MergeWrite_tmpl<typename F::parent_register,
F::mask,
F::offset,
value>>
static T merge_write() noexcept {
// Check overflow.
static_assert(
internals::check_overflow<type, value, (F::mask >> F::offset)>::
value,
"Register::merge_write<value>:: value too large for the field");
return T::create();
}
// Sanity check.
static_assert(size != 0, "Register:: register definition with zero size");
// Enforce alignment.
static_assert(internals::is_aligned<reg_address,
TypeTraits<reg_size>::byte_size>::value,
"Register:: address is mis-aligned for register type");
};
} // namespace cppreg
#endif // CPPREG_REGISTER_H