mirror of
https://github.com/sendyne/cppreg.git
synced 2025-05-09 15:14:05 +00:00
INTERNAL IMPLEMENTATIONS RELOCATED TO AN INTERNALS HEADER
The Internals.h contains the overflow, is_aligned and memory array implementations.
This commit is contained in:
parent
6085f47115
commit
5925c223c8
2
cppreg.h
2
cppreg.h
@ -10,7 +10,7 @@
|
||||
#define CPPREG_CPPREG_H
|
||||
|
||||
|
||||
#include "Overflow.h"
|
||||
#include "Internals.h"
|
||||
#include "MergeWrite.h"
|
||||
#include "Register.h"
|
||||
#include "RegisterPack.h"
|
||||
|
102
register/Internals.h
Normal file
102
register/Internals.h
Normal file
@ -0,0 +1,102 @@
|
||||
//! Internals implementation.
|
||||
/**
|
||||
* @file Internals.h
|
||||
* @author Nicolas Clauvelin (nclauvelin@sendyne.com)
|
||||
* @copyright Copyright 2010-2018 Sendyne Corp. All rights reserved.
|
||||
*
|
||||
* This header collects various implementations which are required for cppreg
|
||||
* implementation but not intended to be fully exposed to the user.
|
||||
*/
|
||||
|
||||
|
||||
#include "cppreg_Defines.h"
|
||||
#include "Traits.h"
|
||||
|
||||
|
||||
#ifndef CPPREG_INTERNALS_H
|
||||
#define CPPREG_INTERNALS_H
|
||||
|
||||
|
||||
//! cppreg::internals namespace.
|
||||
namespace cppreg {
|
||||
namespace internals {
|
||||
|
||||
|
||||
//! Overflow check implementation.
|
||||
/**
|
||||
* @tparam T Data type.
|
||||
* @tparam value Value to check.
|
||||
* @tparam limit Overflow limit value.
|
||||
*
|
||||
* This structure defines a type result set to std::true_type if there is
|
||||
* no overflow and set to std::false_type if there is overflow.
|
||||
* There is overflow if value if strictly larger than limit.
|
||||
*/
|
||||
template <
|
||||
typename T,
|
||||
T value,
|
||||
T limit
|
||||
>
|
||||
struct check_overflow : std::integral_constant<bool, value <= limit> {};
|
||||
|
||||
|
||||
//! is_aligned implementation.
|
||||
/**
|
||||
* @tparam address Address to be checked for alignment.
|
||||
* @tparam alignment Alignment boundary in bytes.
|
||||
*
|
||||
* This will only derived from std::true_type if the address is aligned.
|
||||
*/
|
||||
template <Address_t address, std::size_t alignment>
|
||||
struct is_aligned : std::integral_constant<
|
||||
bool,
|
||||
(address & (alignment - 1)) == 0
|
||||
> {
|
||||
};
|
||||
|
||||
|
||||
//! Memory map implementation for packed registers.
|
||||
/**
|
||||
* @tparam address Memory region base address.
|
||||
* @tparam n Memory size in bytes.
|
||||
* @tparam reg_size Register bit size enum value.
|
||||
*
|
||||
* This structure is used to map an array structure onto a memory region.
|
||||
* The size of the array elements is defined by the register size.
|
||||
*/
|
||||
template <Address_t address, std::uint32_t n, RegBitSize reg_size>
|
||||
struct memory_map {
|
||||
|
||||
//! Array type.
|
||||
using mem_array_t = std::array<
|
||||
volatile typename TypeTraits<reg_size>::type,
|
||||
n / sizeof(typename TypeTraits<reg_size>::type)
|
||||
>;
|
||||
|
||||
//! Static reference to memory array.
|
||||
static mem_array_t& array;
|
||||
|
||||
// Alignment check.
|
||||
static_assert(
|
||||
is_aligned<address, TypeTraits<reg_size>::byte_size>::value,
|
||||
"memory_map: base address is mis-aligned for register type"
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
//! Memory array reference definition.
|
||||
template <Address_t address, std::uint32_t n, RegBitSize reg_size>
|
||||
typename memory_map<address, n, reg_size>::mem_array_t&
|
||||
memory_map<address, n, reg_size>::array = *(
|
||||
reinterpret_cast<typename memory_map<address, n, reg_size>
|
||||
::mem_array_t*>(
|
||||
address
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // CPPREG_INTERNALS_H
|
@ -18,7 +18,7 @@
|
||||
#define CPPREG_MERGEWRITE_H
|
||||
|
||||
|
||||
#include "Overflow.h"
|
||||
#include "Internals.h"
|
||||
#include "AccessPolicy.h"
|
||||
#include <functional>
|
||||
|
||||
|
@ -1,44 +0,0 @@
|
||||
//! Overflow check implementation.
|
||||
/**
|
||||
* @file Overflow.h
|
||||
* @author Nicolas Clauvelin (nclauvelin@sendyne.com)
|
||||
* @copyright Copyright 2010-2018 Sendyne Corp. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CPPREG_OVERFLOW_H
|
||||
#define CPPREG_OVERFLOW_H
|
||||
|
||||
|
||||
#include "Traits.h"
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
//! cppreg::internals namespace.
|
||||
namespace cppreg {
|
||||
namespace internals {
|
||||
|
||||
|
||||
//! Overflow check implementation.
|
||||
/**
|
||||
* @tparam T Data type.
|
||||
* @tparam value Value to check.
|
||||
* @tparam limit Overflow limit value.
|
||||
*
|
||||
* This structure defines a type result set to std::true_type if there is
|
||||
* no overflow and set to std::false_type if there is overflow.
|
||||
* There is overflow if value if strictly larger than limit.
|
||||
*/
|
||||
template <
|
||||
typename T,
|
||||
T value,
|
||||
T limit
|
||||
>
|
||||
struct check_overflow : std::integral_constant<bool, value <= limit> {};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // CPPREG_OVERFLOW_H
|
@ -120,7 +120,14 @@ namespace cppreg {
|
||||
|
||||
// Sanity check.
|
||||
static_assert(size != 0u,
|
||||
"defining a Register type of zero size is not allowed");
|
||||
"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"
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
|
||||
#include "Register.h"
|
||||
#include "Internals.h"
|
||||
|
||||
|
||||
#ifndef CPPREG_REGISTERPACK_H
|
||||
@ -19,62 +20,6 @@
|
||||
namespace cppreg {
|
||||
|
||||
|
||||
//! cppreg::internals namespace.
|
||||
namespace internals {
|
||||
|
||||
//! Memory map implementation.
|
||||
/**
|
||||
* @tparam address Memory base address.
|
||||
* @tparam n Memory size in bytes.
|
||||
* @tparam reg_size Register bit size for the array elements.
|
||||
*
|
||||
* This structure is used to map an array structure onto a memory region.
|
||||
* The width parameter will correspond to the register size.
|
||||
*/
|
||||
template <Address_t address, std::uint32_t n, RegBitSize reg_size>
|
||||
struct memory_map {
|
||||
|
||||
//! Array type.
|
||||
using mem_array_t = std::array<
|
||||
volatile typename TypeTraits<reg_size>::type,
|
||||
n / sizeof(typename TypeTraits<reg_size>::type)
|
||||
>;
|
||||
|
||||
//! Static reference to memory array.
|
||||
/**
|
||||
* This is defined below.
|
||||
*/
|
||||
static mem_array_t& array;
|
||||
|
||||
};
|
||||
|
||||
//! Memory array reference definition.
|
||||
template <Address_t address, std::uint32_t n, RegBitSize reg_size>
|
||||
typename memory_map<address, n, reg_size>::mem_array_t&
|
||||
memory_map<address, n, reg_size>::array = *(
|
||||
reinterpret_cast<typename memory_map<address, n, reg_size>
|
||||
::mem_array_t*>(
|
||||
address
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
//! is_aligned implementation.
|
||||
/**
|
||||
* @tparam address Address to be checked for alignment.
|
||||
* @tparam alignment Alignment constraint.
|
||||
*/
|
||||
template <Address_t address, std::size_t alignment>
|
||||
struct is_aligned : std::integral_constant<
|
||||
bool,
|
||||
(address & (alignment - 1)) == 0
|
||||
> {
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! Register pack base implementation.
|
||||
/**
|
||||
* @tparam base_address Pack base address.
|
||||
@ -112,13 +57,12 @@ namespace internals {
|
||||
typename TypeTraits<reg_size>::type reset_value = 0x0,
|
||||
bool use_shadow = false
|
||||
>
|
||||
struct PackedRegister :
|
||||
Register<
|
||||
RegisterPack::pack_base + (bit_offset / 8u),
|
||||
reg_size,
|
||||
reset_value,
|
||||
use_shadow
|
||||
> {
|
||||
struct PackedRegister : Register<
|
||||
RegisterPack::pack_base + (bit_offset / 8u),
|
||||
reg_size,
|
||||
reset_value,
|
||||
use_shadow
|
||||
> {
|
||||
|
||||
//! Register type.
|
||||
using base_reg = Register<
|
||||
@ -139,7 +83,7 @@ namespace internals {
|
||||
/**
|
||||
* @return A reference to the writable register memory.
|
||||
*/
|
||||
static typename base_reg::MMIO_t& rw_mem_device() {
|
||||
inline static typename base_reg::MMIO_t& rw_mem_device() noexcept {
|
||||
return mem_map_t::array[bit_offset
|
||||
/ TypeTraits<reg_size>::bit_size];
|
||||
};
|
||||
@ -148,14 +92,17 @@ namespace internals {
|
||||
/**
|
||||
* @return A reference to the read-only register memory.
|
||||
*/
|
||||
static const typename base_reg::MMIO_t& ro_mem_device() {
|
||||
inline static const typename base_reg::MMIO_t& ro_mem_device() noexcept {
|
||||
return mem_map_t::array[bit_offset
|
||||
/ TypeTraits<reg_size>::bit_size];
|
||||
};
|
||||
|
||||
// Safety check to detect if are overflowing the pack.
|
||||
static_assert((bit_offset / 8u) <= RegisterPack::size_in_bytes,
|
||||
"packed register is overflowing the pack");
|
||||
static_assert(
|
||||
TypeTraits<reg_size>::byte_size + (bit_offset / 8u) <=
|
||||
RegisterPack::size_in_bytes,
|
||||
"PackRegister: packed register is overflowing the pack"
|
||||
);
|
||||
|
||||
// A packed register of width N bits requires:
|
||||
// - the pack address to be N-bits aligned (N/8 aligned),
|
||||
@ -164,13 +111,15 @@ namespace internals {
|
||||
internals::is_aligned<
|
||||
RegisterPack::pack_base,
|
||||
TypeTraits<reg_size>::byte_size
|
||||
>::value
|
||||
&&
|
||||
>::value,
|
||||
"PackedRegister: pack base address is mis-aligned for register type"
|
||||
);
|
||||
static_assert(
|
||||
internals::is_aligned<
|
||||
RegisterPack::pack_base + (bit_offset / 8),
|
||||
RegisterPack::pack_base + (bit_offset / 8u),
|
||||
TypeTraits<reg_size>::byte_size
|
||||
>::value,
|
||||
"register is mis-aligned in the pack"
|
||||
"PackedRegister: offset address is mis-aligned for register type"
|
||||
);
|
||||
|
||||
|
||||
@ -208,10 +157,10 @@ namespace internals {
|
||||
* This will call Op for the range [start, end).
|
||||
*/
|
||||
template <typename Func>
|
||||
inline static void loop() {
|
||||
inline static void loop() noexcept {
|
||||
Func().template operator()<start>();
|
||||
if (start < end)
|
||||
for_loop<start + 1, end>::template loop<Func>();
|
||||
for_loop<start + 1ul, end>::template loop<Func>();
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
@ -226,10 +175,10 @@ namespace internals {
|
||||
* use lambda [](auto index) { index.value will be the loop index};
|
||||
*/
|
||||
template <typename Op>
|
||||
inline static void apply(Op& f) {
|
||||
inline static void apply(Op& f) noexcept {
|
||||
if (start < end) {
|
||||
f(std::integral_constant<std::size_t, start>{});
|
||||
for_loop<start + 1, end>::apply(f);
|
||||
for_loop<start + 1ul, end>::apply(f);
|
||||
};
|
||||
};
|
||||
#endif // __cplusplus 201402L
|
||||
@ -238,10 +187,10 @@ namespace internals {
|
||||
template <std::size_t end>
|
||||
struct for_loop<end, end> {
|
||||
template <typename Func>
|
||||
inline static void loop() {};
|
||||
inline static void loop() noexcept {};
|
||||
#if __cplusplus >= 201402L
|
||||
template <typename Op>
|
||||
inline static void apply(Op& f) {};
|
||||
inline static void apply(Op& f) noexcept {};
|
||||
#endif // __cplusplus 201402L
|
||||
};
|
||||
|
||||
|
@ -32,33 +32,25 @@ namespace cppreg {
|
||||
template <> struct TypeTraits<RegBitSize::b8> {
|
||||
using type = std::uint8_t;
|
||||
constexpr static const std::uint8_t bit_size = 8u;
|
||||
constexpr static const std::uint8_t byte_size = 1u;
|
||||
constexpr static const std::uint8_t max_field_width = 8u;
|
||||
constexpr static const std::uint8_t max_field_offset = 8u;
|
||||
constexpr static const std::uint8_t byte_size = bit_size / 8u;
|
||||
};
|
||||
//! 16-bit specialization.
|
||||
template <> struct TypeTraits<RegBitSize::b16> {
|
||||
using type = std::uint16_t;
|
||||
constexpr static const std::uint8_t bit_size = 16u;
|
||||
constexpr static const std::uint8_t byte_size = 2u;
|
||||
constexpr static const std::uint8_t max_field_width = 16u;
|
||||
constexpr static const std::uint8_t max_field_offset = 16u;
|
||||
constexpr static const std::uint8_t byte_size = bit_size / 8u;
|
||||
};
|
||||
//! 32-bit specialization.
|
||||
template <> struct TypeTraits<RegBitSize::b32> {
|
||||
using type = std::uint32_t;
|
||||
constexpr static const std::uint8_t bit_size = 32u;
|
||||
constexpr static const std::uint8_t byte_size = 4u;
|
||||
constexpr static const std::uint8_t max_field_width = 32u;
|
||||
constexpr static const std::uint8_t max_field_offset = 32u;
|
||||
constexpr static const std::uint8_t byte_size = bit_size / 8u;
|
||||
};
|
||||
//! 64-bit specialization.
|
||||
template <> struct TypeTraits<RegBitSize::b64> {
|
||||
using type = std::uint64_t;
|
||||
constexpr static const std::uint8_t bit_size = 64u;
|
||||
constexpr static const std::uint8_t byte_size = 8u;
|
||||
constexpr static const std::uint8_t max_field_width = 64u;
|
||||
constexpr static const std::uint8_t max_field_offset = 64u;
|
||||
constexpr static const std::uint8_t byte_size = bit_size / 8u;
|
||||
};
|
||||
//!@}
|
||||
|
||||
|
@ -30,6 +30,76 @@ namespace cppreg {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Traits.h
|
||||
#ifndef CPPREG_TRAITS_H
|
||||
#define CPPREG_TRAITS_H
|
||||
namespace cppreg {
|
||||
template <RegBitSize S>
|
||||
struct TypeTraits;
|
||||
template <> struct TypeTraits<RegBitSize::b8> {
|
||||
using type = std::uint8_t;
|
||||
constexpr static const std::uint8_t bit_size = 8u;
|
||||
constexpr static const std::uint8_t byte_size = bit_size / 8u;
|
||||
};
|
||||
template <> struct TypeTraits<RegBitSize::b16> {
|
||||
using type = std::uint16_t;
|
||||
constexpr static const std::uint8_t bit_size = 16u;
|
||||
constexpr static const std::uint8_t byte_size = bit_size / 8u;
|
||||
};
|
||||
template <> struct TypeTraits<RegBitSize::b32> {
|
||||
using type = std::uint32_t;
|
||||
constexpr static const std::uint8_t bit_size = 32u;
|
||||
constexpr static const std::uint8_t byte_size = bit_size / 8u;
|
||||
};
|
||||
template <> struct TypeTraits<RegBitSize::b64> {
|
||||
using type = std::uint64_t;
|
||||
constexpr static const std::uint8_t bit_size = 64u;
|
||||
constexpr static const std::uint8_t byte_size = bit_size / 8u;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
// Internals.h
|
||||
#ifndef CPPREG_INTERNALS_H
|
||||
#define CPPREG_INTERNALS_H
|
||||
namespace cppreg {
|
||||
namespace internals {
|
||||
template <
|
||||
typename T,
|
||||
T value,
|
||||
T limit
|
||||
>
|
||||
struct check_overflow : std::integral_constant<bool, value <= limit> {};
|
||||
template <Address_t address, std::size_t alignment>
|
||||
struct is_aligned : std::integral_constant<
|
||||
bool,
|
||||
(address & (alignment - 1)) == 0
|
||||
> {
|
||||
};
|
||||
template <Address_t address, std::uint32_t n, RegBitSize reg_size>
|
||||
struct memory_map {
|
||||
using mem_array_t = std::array<
|
||||
volatile typename TypeTraits<reg_size>::type,
|
||||
n / sizeof(typename TypeTraits<reg_size>::type)
|
||||
>;
|
||||
static mem_array_t& array;
|
||||
static_assert(
|
||||
is_aligned<address, TypeTraits<reg_size>::byte_size>::value,
|
||||
"memory_map: base address is mis-aligned for register type"
|
||||
);
|
||||
};
|
||||
template <Address_t address, std::uint32_t n, RegBitSize reg_size>
|
||||
typename memory_map<address, n, reg_size>::mem_array_t&
|
||||
memory_map<address, n, reg_size>::array = *(
|
||||
reinterpret_cast<typename memory_map<address, n, reg_size>
|
||||
::mem_array_t*>(
|
||||
address
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// AccessPolicy.h
|
||||
#ifndef CPPREG_ACCESSPOLICY_H
|
||||
#define CPPREG_ACCESSPOLICY_H
|
||||
@ -157,58 +227,6 @@ namespace cppreg {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Traits.h
|
||||
#ifndef CPPREG_TRAITS_H
|
||||
#define CPPREG_TRAITS_H
|
||||
namespace cppreg {
|
||||
template <RegBitSize S>
|
||||
struct TypeTraits;
|
||||
template <> struct TypeTraits<RegBitSize::b8> {
|
||||
using type = std::uint8_t;
|
||||
constexpr static const std::uint8_t bit_size = 8u;
|
||||
constexpr static const std::uint8_t byte_size = 1u;
|
||||
constexpr static const std::uint8_t max_field_width = 8u;
|
||||
constexpr static const std::uint8_t max_field_offset = 8u;
|
||||
};
|
||||
template <> struct TypeTraits<RegBitSize::b16> {
|
||||
using type = std::uint16_t;
|
||||
constexpr static const std::uint8_t bit_size = 16u;
|
||||
constexpr static const std::uint8_t byte_size = 2u;
|
||||
constexpr static const std::uint8_t max_field_width = 16u;
|
||||
constexpr static const std::uint8_t max_field_offset = 16u;
|
||||
};
|
||||
template <> struct TypeTraits<RegBitSize::b32> {
|
||||
using type = std::uint32_t;
|
||||
constexpr static const std::uint8_t bit_size = 32u;
|
||||
constexpr static const std::uint8_t byte_size = 4u;
|
||||
constexpr static const std::uint8_t max_field_width = 32u;
|
||||
constexpr static const std::uint8_t max_field_offset = 32u;
|
||||
};
|
||||
template <> struct TypeTraits<RegBitSize::b64> {
|
||||
using type = std::uint64_t;
|
||||
constexpr static const std::uint8_t bit_size = 64u;
|
||||
constexpr static const std::uint8_t byte_size = 8u;
|
||||
constexpr static const std::uint8_t max_field_width = 64u;
|
||||
constexpr static const std::uint8_t max_field_offset = 64u;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
// Overflow.h
|
||||
#ifndef CPPREG_OVERFLOW_H
|
||||
#define CPPREG_OVERFLOW_H
|
||||
namespace cppreg {
|
||||
namespace internals {
|
||||
template <
|
||||
typename T,
|
||||
T value,
|
||||
T limit
|
||||
>
|
||||
struct check_overflow : std::integral_constant<bool, value <= limit> {};
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Mask.h
|
||||
#ifndef CPPREG_MASK_H
|
||||
#define CPPREG_MASK_H
|
||||
@ -419,7 +437,12 @@ namespace cppreg {
|
||||
return std::move(T::make());
|
||||
};
|
||||
static_assert(size != 0u,
|
||||
"defining a Register type of zero size is not allowed");
|
||||
"Register: register definition with zero size");
|
||||
static_assert(
|
||||
internals::is_aligned<reg_address, TypeTraits<reg_size>::byte_size>
|
||||
::value,
|
||||
"Register: address is mis-aligned for register type"
|
||||
);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@ -428,30 +451,6 @@ namespace cppreg {
|
||||
#ifndef CPPREG_REGISTERPACK_H
|
||||
#define CPPREG_REGISTERPACK_H
|
||||
namespace cppreg {
|
||||
namespace internals {
|
||||
template <Address_t address, std::uint32_t n, RegBitSize reg_size>
|
||||
struct memory_map {
|
||||
using mem_array_t = std::array<
|
||||
volatile typename TypeTraits<reg_size>::type,
|
||||
n / sizeof(typename TypeTraits<reg_size>::type)
|
||||
>;
|
||||
static mem_array_t& array;
|
||||
};
|
||||
template <Address_t address, std::uint32_t n, RegBitSize reg_size>
|
||||
typename memory_map<address, n, reg_size>::mem_array_t&
|
||||
memory_map<address, n, reg_size>::array = *(
|
||||
reinterpret_cast<typename memory_map<address, n, reg_size>
|
||||
::mem_array_t*>(
|
||||
address
|
||||
)
|
||||
);
|
||||
template <Address_t address, std::size_t alignment>
|
||||
struct is_aligned : std::integral_constant<
|
||||
bool,
|
||||
(address & (alignment - 1)) == 0
|
||||
> {
|
||||
};
|
||||
}
|
||||
template <
|
||||
Address_t base_address,
|
||||
std::uint32_t pack_byte_size
|
||||
@ -466,13 +465,12 @@ namespace internals {
|
||||
typename TypeTraits<reg_size>::type reset_value = 0x0,
|
||||
bool use_shadow = false
|
||||
>
|
||||
struct PackedRegister :
|
||||
Register<
|
||||
RegisterPack::pack_base + (bit_offset / 8u),
|
||||
reg_size,
|
||||
reset_value,
|
||||
use_shadow
|
||||
> {
|
||||
struct PackedRegister : Register<
|
||||
RegisterPack::pack_base + (bit_offset / 8u),
|
||||
reg_size,
|
||||
reset_value,
|
||||
use_shadow
|
||||
> {
|
||||
using base_reg = Register<
|
||||
RegisterPack::pack_base + (bit_offset / 8u),
|
||||
reg_size,
|
||||
@ -484,27 +482,32 @@ namespace internals {
|
||||
RegisterPack::size_in_bytes,
|
||||
reg_size
|
||||
>;
|
||||
static typename base_reg::MMIO_t& rw_mem_device() {
|
||||
inline static typename base_reg::MMIO_t& rw_mem_device() noexcept {
|
||||
return mem_map_t::array[bit_offset
|
||||
/ TypeTraits<reg_size>::bit_size];
|
||||
};
|
||||
static const typename base_reg::MMIO_t& ro_mem_device() {
|
||||
inline static const typename base_reg::MMIO_t& ro_mem_device() noexcept {
|
||||
return mem_map_t::array[bit_offset
|
||||
/ TypeTraits<reg_size>::bit_size];
|
||||
};
|
||||
static_assert((bit_offset / 8u) <= RegisterPack::size_in_bytes,
|
||||
"packed register is overflowing the pack");
|
||||
static_assert(
|
||||
TypeTraits<reg_size>::byte_size + (bit_offset / 8u) <=
|
||||
RegisterPack::size_in_bytes,
|
||||
"PackRegister: packed register is overflowing the pack"
|
||||
);
|
||||
static_assert(
|
||||
internals::is_aligned<
|
||||
RegisterPack::pack_base,
|
||||
TypeTraits<reg_size>::byte_size
|
||||
>::value
|
||||
&&
|
||||
>::value,
|
||||
"PackedRegister: pack base address is mis-aligned for register type"
|
||||
);
|
||||
static_assert(
|
||||
internals::is_aligned<
|
||||
RegisterPack::pack_base + (bit_offset / 8),
|
||||
RegisterPack::pack_base + (bit_offset / 8u),
|
||||
TypeTraits<reg_size>::byte_size
|
||||
>::value,
|
||||
"register is mis-aligned in the pack"
|
||||
"PackedRegister: offset address is mis-aligned for register type"
|
||||
);
|
||||
};
|
||||
template <typename... T>
|
||||
@ -516,17 +519,17 @@ namespace internals {
|
||||
template <std::size_t start, std::size_t end>
|
||||
struct for_loop {
|
||||
template <typename Func>
|
||||
inline static void loop() {
|
||||
inline static void loop() noexcept {
|
||||
Func().template operator()<start>();
|
||||
if (start < end)
|
||||
for_loop<start + 1, end>::template loop<Func>();
|
||||
for_loop<start + 1ul, end>::template loop<Func>();
|
||||
};
|
||||
#if __cplusplus >= 201402L
|
||||
template <typename Op>
|
||||
inline static void apply(Op& f) {
|
||||
inline static void apply(Op& f) noexcept {
|
||||
if (start < end) {
|
||||
f(std::integral_constant<std::size_t, start>{});
|
||||
for_loop<start + 1, end>::apply(f);
|
||||
for_loop<start + 1ul, end>::apply(f);
|
||||
};
|
||||
};
|
||||
#endif
|
||||
@ -534,10 +537,10 @@ namespace internals {
|
||||
template <std::size_t end>
|
||||
struct for_loop<end, end> {
|
||||
template <typename Func>
|
||||
inline static void loop() {};
|
||||
inline static void loop() noexcept {};
|
||||
#if __cplusplus >= 201402L
|
||||
template <typename Op>
|
||||
inline static void apply(Op& f) {};
|
||||
inline static void apply(Op& f) noexcept {};
|
||||
#endif
|
||||
};
|
||||
template <typename IndexedPack>
|
||||
|
Loading…
x
Reference in New Issue
Block a user