diff --git a/cppreg.h b/cppreg.h index fbf3058..0e16e50 100644 --- a/cppreg.h +++ b/cppreg.h @@ -2,7 +2,7 @@ /** * @file cppreg.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved. */ diff --git a/cppreg_Defines.h b/cppreg_Defines.h index 4feccb9..daacc94 100644 --- a/cppreg_Defines.h +++ b/cppreg_Defines.h @@ -2,7 +2,7 @@ /** * @file cppreg_Defines.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved. * * This header mostly defines data types used across the project. These data * types have been defined with 32-bits address space hardware in mind. It @@ -32,10 +32,14 @@ using Address = std::uintptr_t; * This is used to enforce the supported register sizes. */ enum class RegBitSize : std::uint8_t { - b8, //!< 8-bit register. - b16, //!< 16-bit register. - b32, //!< 32-bit register. - b64 //!< 64-bit register. + //! 8-bit register. + b8, // NOLINT + //! 16-bit register. + b16, // NOLINT + //! 32-bit register. + b32, // NOLINT + //! 64-bit register. + b64 // NOLINT }; @@ -54,11 +58,15 @@ using FieldOffset = std::uint8_t; * This is used to define register masks. */ template -struct type_mask { +struct type_mask { // NOLINT constexpr static const T value = std::numeric_limits::max(); }; +//! Global constant to convert bits to bytes. +constexpr static const auto one_byte = std::size_t{8}; + + } // namespace cppreg diff --git a/cppreg_Includes.h b/cppreg_Includes.h index 494b23c..5a820d3 100644 --- a/cppreg_Includes.h +++ b/cppreg_Includes.h @@ -2,7 +2,7 @@ /** * @file cppreg_Defines.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved. */ diff --git a/policies/AccessPolicy.h b/policies/AccessPolicy.h index 4cabdbb..e12e4a1 100644 --- a/policies/AccessPolicy.h +++ b/policies/AccessPolicy.h @@ -2,7 +2,7 @@ /** * @file AccessPolicy.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved. * * Access policies are used to describe if register fields are read-write, * read-only or write-only. @@ -39,7 +39,7 @@ namespace cppreg { * @tparam offset Offset for the read operation. */ template -struct is_trivial_rw +struct is_trivial_rw // NOLINT : std::integral_constant::value) && (offset == FieldOffset{0})> {}; @@ -52,7 +52,7 @@ struct is_trivial_rw * @tparam U Enabled type if trivial. */ template -using is_trivial = +using is_trivial = // NOLINT typename std::enable_if::value, U>::type; //! Non-trivial read/write enable_if helper. @@ -63,7 +63,7 @@ using is_trivial = * @tparam U Enabled type if non-trivial. */ template -using is_not_trivial = +using is_not_trivial = // NOLINT typename std::enable_if::value, U>::type; //!@} @@ -85,9 +85,10 @@ struct RegisterRead { * @return The content of the register field. */ template - static T read(const MMIO& mmio_device, + static T read(const MMIO& mmio_device, // NOLINTNEXTLINE is_not_trivial* = nullptr) noexcept { - return static_cast((mmio_device & mask) >> offset); + const auto lhs = static_cast(mmio_device & mask); + return static_cast(lhs >> offset); } //! Trivial read implementation. @@ -96,7 +97,7 @@ struct RegisterRead { * @return The content of the register field. */ template - static T read(const MMIO& mmio_device, + static T read(const MMIO& mmio_device, // NOLINTNEXTLINE is_trivial* = nullptr) noexcept { return static_cast(mmio_device); } @@ -120,10 +121,12 @@ struct RegisterWrite { */ template static void write(MMIO& mmio_device, - T value, + T value, // NOLINTNEXTLINE is_not_trivial* = nullptr) noexcept { - mmio_device = - static_cast((mmio_device & ~mask) | ((value << offset) & mask)); + const auto shifted_value = static_cast(value << offset); + const auto lhs = static_cast(mmio_device & static_cast(~mask)); + const auto rhs = static_cast(shifted_value & mask); + mmio_device = static_cast(lhs | rhs); } //! Trivial write implementation. @@ -133,7 +136,7 @@ struct RegisterWrite { */ template static void write(MMIO& mmio_device, - T value, + T value, // NOLINTNEXTLINE is_trivial* = nullptr) noexcept { mmio_device = value; } @@ -156,10 +159,12 @@ struct RegisterWriteConstant { * @param mmio_device Pointer to the register memory device. */ template - static void write(MMIO& mmio_device, + static void write(MMIO& mmio_device, // NOLINTNEXTLINE is_not_trivial* = nullptr) noexcept { - mmio_device = - static_cast((mmio_device & ~mask) | ((value << offset) & mask)); + constexpr auto shifted_value = static_cast(value << offset); + const auto lhs = static_cast(mmio_device & static_cast(~mask)); + constexpr auto rhs = static_cast(shifted_value & mask); + mmio_device = static_cast(lhs | rhs); } //! Trivial write implementation. @@ -167,7 +172,7 @@ struct RegisterWriteConstant { * @param mmio_device Pointer to the register memory device. */ template - static void write(MMIO& mmio_device, + static void write(MMIO& mmio_device, // NOLINTNEXTLINE is_trivial* = nullptr) noexcept { mmio_device = value; } @@ -175,7 +180,7 @@ struct RegisterWriteConstant { //! Read-only access policy. -struct read_only { +struct read_only { // NOLINT //! Read access implementation. /** @@ -194,7 +199,7 @@ struct read_only { //! Read-write access policy. -struct read_write : read_only { +struct read_write : read_only { // NOLINT //! Write access implementation. /** @@ -267,7 +272,7 @@ struct read_write : read_only { //! Write-only access policy. -struct write_only { +struct write_only { // NOLINT //! Write access implementation. /** diff --git a/register/Field.h b/register/Field.h index 76e8849..b2a13c8 100644 --- a/register/Field.h +++ b/register/Field.h @@ -2,7 +2,7 @@ /** * @file Field.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved. * * This header provides the definitions related to register field * implementation. Strictly speaking a field is defined as a region of a @@ -43,16 +43,16 @@ template - using if_no_shadow = + using if_no_shadow = // NOLINT typename std::enable_if::type; template - using if_shadow = + using if_shadow = // NOLINT typename std::enable_if::type; //!@} @@ -118,7 +118,7 @@ struct Field { * field and uses the constant write implementation. */ template - static void write(if_no_shadow* = nullptr) noexcept { + static void write(if_no_shadow* = nullptr) noexcept { // NOLINT policy::template write( parent_register::rw_mem_device()); @@ -136,7 +136,7 @@ struct Field { * field and uses the constant write implementation. */ template - static void write(if_shadow* = nullptr) noexcept { + static void write(if_shadow* = nullptr) noexcept { // NOLINT // For this one we simply forward to the non-constant // implementation because the shadow value needs to be updated. write(value); diff --git a/register/Internals.h b/register/Internals.h index c8d5fe2..85f2ed4 100644 --- a/register/Internals.h +++ b/register/Internals.h @@ -2,7 +2,7 @@ /** * @file Internals.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 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. @@ -31,7 +31,8 @@ namespace internals { * There is overflow if value if strictly larger than limit. */ template -struct check_overflow : std::integral_constant {}; +struct check_overflow // NOLINT + : std::integral_constant {}; //! is_aligned implementation. @@ -42,8 +43,10 @@ struct check_overflow : std::integral_constant {}; * This will only derived from std::true_type if the address is aligned. */ template
-struct is_aligned - : std::integral_constant {}; +struct is_aligned // NOLINT + : std::integral_constant< + bool, + (static_cast(address) & (alignment - 1)) == 0> {}; } // namespace internals diff --git a/register/Mask.h b/register/Mask.h index 40d9a66..5eca25a 100644 --- a/register/Mask.h +++ b/register/Mask.h @@ -2,7 +2,7 @@ /** * @file Mask.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved. * * The implementation is designed to compute masks prior to runtime by * relying on constexpr function. This will work as intended if the function @@ -28,9 +28,13 @@ namespace cppreg { */ template constexpr Mask make_mask(const FieldWidth width) noexcept { - return width == 0 ? static_cast(0u) - : static_cast( - (make_mask(FieldWidth(width - 1)) << 1) | 1); + return width == 0U + ? static_cast(0U) + : static_cast( + static_cast(make_mask(FieldWidth( + static_cast(width - 1U))) + << 1U) + | 1U); } diff --git a/register/Memory.h b/register/Memory.h index 9a13bf0..0ff582b 100644 --- a/register/Memory.h +++ b/register/Memory.h @@ -2,7 +2,7 @@ /** * @file Memory.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved. */ @@ -10,6 +10,7 @@ #define CPPREG_DEV_MEMORY_H +#include "Internals.h" #include "Traits.h" #include @@ -43,10 +44,10 @@ template
struct MemoryDevice { //! Storage type. - using memory_storage = std::array; + using MemStorage = std::array; //! Memory device storage. - static memory_storage& _mem_storage; + static MemStorage& _mem_storage; // NOLINT //! Accessor. template @@ -59,7 +60,7 @@ struct MemoryDevice { reg_size>::type>::value>::value, "MemoryDevice:: ro request not aligned"); - return *(reinterpret_cast::type*>( &_mem_storage[byte_offset])); } @@ -75,16 +76,17 @@ struct MemoryDevice { reg_size>::type>::value>::value, "MemoryDevice:: rw request not aligned"); - return *( + return *( // NOLINTNEXTLINE reinterpret_cast::type*>( &_mem_storage[byte_offset])); } }; //! Static reference definition. -template
-typename MemoryDevice::memory_storage& MemoryDevice::_mem_storage = - *(reinterpret_cast::memory_storage*>(a)); +template
// NOLINTNEXTLINE +typename MemoryDevice::MemStorage& MemoryDevice::_mem_storage = + // NOLINTNEXTLINE + *(reinterpret_cast::MemStorage*>(a)); //! Register memory device for register pack. @@ -95,7 +97,7 @@ typename MemoryDevice::memory_storage& MemoryDevice::_mem_storage = */ template struct RegisterMemoryDevice { - using mem_device = + using mem_device = // NOLINT MemoryDevice; }; diff --git a/register/MergeWrite.h b/register/MergeWrite.h index 5ac1077..73f5a3d 100644 --- a/register/MergeWrite.h +++ b/register/MergeWrite.h @@ -2,7 +2,7 @@ /** * @file MergeWrite.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved. * * The "merge write" implementation is designed to make it possible to merge * write operations on different fields into a single one. @@ -45,26 +45,27 @@ template -class MergeWrite_tmpl { +class MergeWrite_tmpl { // NOLINT private: // Type alias to register base type. - using base_type = typename Register::type; + using base_type = typename Register::type; // NOLINT // Accumulated value. - constexpr static auto _accumulated_value = + constexpr static auto _accumulated_value = // NOLINT base_type{(value << offset) & mask}; // Combined mask. - constexpr static auto _combined_mask = mask; + constexpr static auto _combined_mask = mask; // NOLINT // Type helper. template - using propagated = + using propagated = // NOLINT MergeWrite_tmpl(~F::mask)) | ((new_value << F::offset) & F::mask)>; // Default constructor. @@ -80,12 +81,17 @@ public: return {}; } - //!@{ Non-copyable and non-moveable. + //! Destructor. + ~MergeWrite_tmpl() = default; + + //! Move constructor. + MergeWrite_tmpl(MergeWrite_tmpl&&) noexcept = default; + + //!@{ Non-copyable and non-assignable. MergeWrite_tmpl(const MergeWrite_tmpl&) = delete; MergeWrite_tmpl& operator=(const MergeWrite_tmpl&) = delete; MergeWrite_tmpl& operator=(MergeWrite_tmpl&&) = delete; MergeWrite_tmpl operator=(MergeWrite_tmpl) = delete; - MergeWrite_tmpl(MergeWrite_tmpl&&) = delete; //!@} //! Closure method. @@ -114,7 +120,7 @@ public: * @return A merge write instance with accumulated data. */ template - propagated&& with() const&& noexcept { + propagated with() const&& noexcept { // Check that the field belongs to the register. static_assert( @@ -129,7 +135,7 @@ public: static_assert(no_overflow, "MergeWrite_tmpl:: field overflow in with() call"); - return std::move(propagated{}); + return propagated{}; } }; @@ -147,17 +153,18 @@ class MergeWrite { private: // Type alias to register base type. - using base_type = typename Register::type; + using base_type = typename Register::type; // NOLINT // Accumulated value. - base_type _accumulated_value; + base_type _accumulated_value; // NOLINT // Combined mask. - constexpr static auto _combined_mask = mask; + constexpr static auto _combined_mask = mask; // NOLINT // Type helper. template - using propagated = MergeWrite; + using propagated = // NOLINT + MergeWrite; // Private default constructor. constexpr MergeWrite() : _accumulated_value{0} {}; @@ -173,11 +180,14 @@ public: return MergeWrite(value); } + //! Destructor. + ~MergeWrite() = default; + //!@ Move constructor. MergeWrite(MergeWrite&& mw) noexcept : _accumulated_value{mw._accumulated_value} {}; - //!@{ Non-copyable. + //!@{ Non-copyable and non-assignable. MergeWrite(const MergeWrite&) = delete; MergeWrite& operator=(const MergeWrite&) = delete; MergeWrite& operator=(MergeWrite&&) = delete; @@ -216,10 +226,11 @@ public: "field is not from the same register in merge_write"); // Update accumulated value. - const auto new_value = static_cast( - (_accumulated_value & ~F::mask) | ((value << F::offset) & F::mask)); - - return std::move(propagated::create(new_value)); + constexpr auto neg_mask = static_cast(~F::mask); + const auto shifted_value = static_cast(value << F::offset); + const auto lhs = static_cast(_accumulated_value & neg_mask); + const auto rhs = static_cast(shifted_value & F::mask); + return propagated::create(static_cast(lhs | rhs)); } }; diff --git a/register/Register.h b/register/Register.h index 0fe68e5..46f299c 100644 --- a/register/Register.h +++ b/register/Register.h @@ -2,7 +2,7 @@ /** * @file Register.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved. * * This header provides the definitions related to register implementation. */ @@ -40,13 +40,13 @@ template
::type; + using type = typename TypeTraits::type; // NOLINT //! MMIO pointer type. using MMIO = volatile type; //! Boolean flag for shadow value management. - using shadow = Shadow; + using shadow = Shadow; // NOLINT //! Register base address. constexpr static auto base_address = reg_address; @@ -58,15 +58,15 @@ struct Register { constexpr static auto reset = reset_value; //! Register pack for memory device. - using pack = RegisterPack; + using pack = RegisterPack; // NOLINT //! Memory modifier. /** * @return A reference to the writable register memory. */ static MMIO& rw_mem_device() { - using mem_device = typename RegisterMemoryDevice::mem_device; - return mem_device::template rw_memory(); + using MemDevice = typename RegisterMemoryDevice::mem_device; + return MemDevice::template rw_memory(); } //! Memory accessor. @@ -74,8 +74,8 @@ struct Register { * @return A reference to the read-only register memory. */ static const MMIO& ro_mem_device() { - using mem_device = typename RegisterMemoryDevice::mem_device; - return mem_device::template ro_memory(); + using MemDevice = typename RegisterMemoryDevice::mem_device; + return MemDevice::template ro_memory(); } //! Merge write start function. @@ -87,8 +87,9 @@ struct Register { template static MergeWrite merge_write( const typename F::type value) noexcept { + const auto lhs = static_cast(value << F::offset); return MergeWrite::create( - static_cast((value << F::offset) & F::mask)); + static_cast(lhs & F::mask)); } //! Merge write start function for constant value. @@ -103,7 +104,7 @@ struct Register { F::mask, F::offset, value>> - static T&& merge_write() noexcept { + static T merge_write() noexcept { // Check overflow. static_assert( @@ -111,11 +112,11 @@ struct Register { value, "Register::merge_write:: value too large for the field"); - return std::move(T::create()); + return T::create(); } // Sanity check. - static_assert(size != 0u, "Register:: register definition with zero size"); + static_assert(size != 0, "Register:: register definition with zero size"); // Enforce alignment. static_assert(internals::is_aligned::type reset_value = 0x0, bool use_shadow = false> -struct PackedRegister : Register { +struct PackedRegister + : Register { //! Register pack. - using pack = RegisterPack; + using pack = RegisterPack; // NOLINT //! Register type. - using base_reg = Register; + using base_reg = // NOLINT + Register; //! Memory modifier. /** * @return A reference to the writable register memory. */ static typename base_reg::MMIO& rw_mem_device() noexcept { - using mem_device = + using MemDevice = typename RegisterMemoryDevice::mem_device; - return mem_device::template rw_memory(); + return MemDevice::template rw_memory(); } //! Memory accessor. @@ -66,13 +69,14 @@ struct PackedRegister : Register::mem_device; - return mem_device::template ro_memory(); + return MemDevice::template ro_memory(); } // Safety check to detect if are overflowing the pack. - static_assert(TypeTraits::byte_size + (bit_offset / 8u) + static_assert(TypeTraits::byte_size + (bit_offset / one_byte) <= RegisterPack::size_in_bytes, "PackRegister:: packed register is overflowing the pack"); @@ -84,7 +88,7 @@ struct PackedRegister : Register::byte_size>::value, "PackedRegister:: pack base address is mis-aligned for register type"); static_assert( - internals::is_aligned::byte_size>::value, "PackedRegister:: offset address is mis-aligned for register type"); }; @@ -102,15 +106,15 @@ template struct PackIndexing { //! Tuple type. - using tuple_t = typename std::tuple; + using tuple_t = typename std::tuple; // NOLINT //! Number of elements. constexpr static const std::size_t n_elems = std::tuple_size::value; //! Element accessor. - template - using elem = typename std::tuple_element::type; + template + using elem = typename std::tuple_element::type; // NOLINT }; @@ -120,7 +124,7 @@ struct PackIndexing { * @tparam end End index value. */ template -struct for_loop { +struct for_loop { // NOLINT //! Loop method. /** @@ -131,8 +135,9 @@ struct for_loop { template static void apply() noexcept { Func().template operator()(); - if (start < end) - for_loop::template apply(); + if (start < end) { + for_loop::template apply(); + } } #if __cplusplus >= 201402L @@ -150,7 +155,7 @@ struct for_loop { static void apply(Op&& f) noexcept { if (start < end) { f(std::integral_constant{}); - for_loop::apply(std::forward(f)); + for_loop::apply(std::forward(f)); }; } #endif // __cplusplus 201402L @@ -161,8 +166,8 @@ struct for_loop { static void apply() noexcept {} #if __cplusplus >= 201402L template - static void apply(Op&& f) noexcept {} -#endif // __cplusplus 201402L + static void apply(Op&&) noexcept {} // NOLINT +#endif // __cplusplus 201402L }; @@ -171,7 +176,7 @@ struct for_loop { * @tparam IndexedPack Indexed pack type. */ template -struct pack_loop : for_loop<0, IndexedPack::n_elems> {}; +struct pack_loop : for_loop<0, IndexedPack::n_elems> {}; // NOLINT } // namespace cppreg diff --git a/register/ShadowValue.h b/register/ShadowValue.h index 9c15fc3..33f78e4 100644 --- a/register/ShadowValue.h +++ b/register/ShadowValue.h @@ -2,7 +2,7 @@ /** * @file ShadowValue.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved. */ diff --git a/register/Traits.h b/register/Traits.h index 68e41ab..f5550a7 100644 --- a/register/Traits.h +++ b/register/Traits.h @@ -2,7 +2,7 @@ /** * @file Traits.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved. * * This header provides some traits for register type instantiation. */ @@ -20,9 +20,9 @@ namespace cppreg { //! Register type traits based on size. /** - * @tparam S Register size in bits. + * @tparam size Register size in bits. */ -template +template struct TypeTraits {}; @@ -31,7 +31,7 @@ struct TypeTraits {}; //! 8-bit specialization. template <> struct TypeTraits { - using type = std::uint8_t; + using type = std::uint8_t; // NOLINT constexpr static auto bit_size = std::uint8_t{8}; constexpr static auto byte_size = std::uint8_t{bit_size / 8}; }; @@ -39,7 +39,7 @@ struct TypeTraits { //! 16-bit specialization. template <> struct TypeTraits { - using type = std::uint16_t; + using type = std::uint16_t; // NOLINT constexpr static auto bit_size = std::uint8_t{16}; constexpr static auto byte_size = std::uint8_t{bit_size / 8}; }; @@ -47,7 +47,7 @@ struct TypeTraits { //! 32-bit specialization. template <> struct TypeTraits { - using type = std::uint32_t; + using type = std::uint32_t; // NOLINT constexpr static auto bit_size = std::uint8_t{32}; constexpr static auto byte_size = std::uint8_t{bit_size / 8}; }; @@ -55,7 +55,7 @@ struct TypeTraits { //! 64-bit specialization. template <> struct TypeTraits { - using type = std::uint64_t; + using type = std::uint64_t; // NOLINT constexpr static auto bit_size = std::uint8_t{64}; constexpr static auto byte_size = std::uint8_t{bit_size / 8}; }; diff --git a/single/cppreg-all.h b/single/cppreg-all.h index ce670e3..5913bb6 100644 --- a/single/cppreg-all.h +++ b/single/cppreg-all.h @@ -1,14 +1,15 @@ +/* clang-format off */ //! cppreg library. /** * @file cppreg-all.h * @author Nicolas Clauvelin (nclauvelin@sendyne.com) - * @copyright Copyright 2010-2019 Sendyne Corp. All rights reserved. + * @copyright Copyright 2010-2022 Sendyne Corp. All rights reserved. */ #include -#include #include #include +#include // cppreg_Defines.h #ifndef CPPREG_CPPREG_DEFINES_H @@ -16,17 +17,18 @@ namespace cppreg { using Address = std::uintptr_t; enum class RegBitSize : std::uint8_t { - b8, - b16, - b32, - b64 + b8, // NOLINT + b16, // NOLINT + b32, // NOLINT + b64 // NOLINT }; using FieldWidth = std::uint8_t; using FieldOffset = std::uint8_t; template -struct type_mask { +struct type_mask { // NOLINT constexpr static const T value = std::numeric_limits::max(); }; +constexpr static const auto one_byte = std::size_t{8}; } #endif @@ -34,29 +36,29 @@ struct type_mask { #ifndef CPPREG_TRAITS_H #define CPPREG_TRAITS_H namespace cppreg { -template +template struct TypeTraits {}; template <> struct TypeTraits { - using type = std::uint8_t; + using type = std::uint8_t; // NOLINT constexpr static auto bit_size = std::uint8_t{8}; constexpr static auto byte_size = std::uint8_t{bit_size / 8}; }; template <> struct TypeTraits { - using type = std::uint16_t; + using type = std::uint16_t; // NOLINT constexpr static auto bit_size = std::uint8_t{16}; constexpr static auto byte_size = std::uint8_t{bit_size / 8}; }; template <> struct TypeTraits { - using type = std::uint32_t; + using type = std::uint32_t; // NOLINT constexpr static auto bit_size = std::uint8_t{32}; constexpr static auto byte_size = std::uint8_t{bit_size / 8}; }; template <> struct TypeTraits { - using type = std::uint64_t; + using type = std::uint64_t; // NOLINT constexpr static auto bit_size = std::uint8_t{64}; constexpr static auto byte_size = std::uint8_t{bit_size / 8}; }; @@ -69,10 +71,13 @@ struct TypeTraits { namespace cppreg { namespace internals { template -struct check_overflow : std::integral_constant {}; +struct check_overflow // NOLINT + : std::integral_constant {}; template
-struct is_aligned - : std::integral_constant {}; +struct is_aligned // NOLINT + : std::integral_constant< + bool, + (static_cast(address) & (alignment - 1)) == 0> {}; } } #endif @@ -88,8 +93,8 @@ struct RegisterPack { }; template
struct MemoryDevice { - using memory_storage = std::array; - static memory_storage& _mem_storage; + using MemStorage = std::array; + static MemStorage& _mem_storage; // NOLINT template static const volatile typename TypeTraits::type& ro_memory() { static_assert( @@ -97,7 +102,7 @@ struct MemoryDevice { std::alignment_of::type>::value>::value, "MemoryDevice:: ro request not aligned"); - return *(reinterpret_cast::type*>( &_mem_storage[byte_offset])); } @@ -108,17 +113,18 @@ struct MemoryDevice { std::alignment_of::type>::value>::value, "MemoryDevice:: rw request not aligned"); - return *( + return *( // NOLINTNEXTLINE reinterpret_cast::type*>( &_mem_storage[byte_offset])); } }; -template
-typename MemoryDevice::memory_storage& MemoryDevice::_mem_storage = - *(reinterpret_cast::memory_storage*>(a)); +template
// NOLINTNEXTLINE +typename MemoryDevice::MemStorage& MemoryDevice::_mem_storage = + // NOLINTNEXTLINE + *(reinterpret_cast::MemStorage*>(a)); template struct RegisterMemoryDevice { - using mem_device = + using mem_device = // NOLINT MemoryDevice; }; } @@ -129,25 +135,26 @@ struct RegisterMemoryDevice { #define CPPREG_ACCESSPOLICY_H namespace cppreg { template -struct is_trivial_rw +struct is_trivial_rw // NOLINT : std::integral_constant::value) && (offset == FieldOffset{0})> {}; template -using is_trivial = +using is_trivial = // NOLINT typename std::enable_if::value, U>::type; template -using is_not_trivial = +using is_not_trivial = // NOLINT typename std::enable_if::value, U>::type; template struct RegisterRead { template - static T read(const MMIO& mmio_device, + static T read(const MMIO& mmio_device, // NOLINTNEXTLINE is_not_trivial* = nullptr) noexcept { - return static_cast((mmio_device & mask) >> offset); + const auto lhs = static_cast(mmio_device & mask); + return static_cast(lhs >> offset); } template - static T read(const MMIO& mmio_device, + static T read(const MMIO& mmio_device, // NOLINTNEXTLINE is_trivial* = nullptr) noexcept { return static_cast(mmio_device); } @@ -156,14 +163,16 @@ template struct RegisterWrite { template static void write(MMIO& mmio_device, - T value, + T value, // NOLINTNEXTLINE is_not_trivial* = nullptr) noexcept { - mmio_device = - static_cast((mmio_device & ~mask) | ((value << offset) & mask)); + const auto shifted_value = static_cast(value << offset); + const auto lhs = static_cast(mmio_device & static_cast(~mask)); + const auto rhs = static_cast(shifted_value & mask); + mmio_device = static_cast(lhs | rhs); } template static void write(MMIO& mmio_device, - T value, + T value, // NOLINTNEXTLINE is_trivial* = nullptr) noexcept { mmio_device = value; } @@ -171,24 +180,26 @@ struct RegisterWrite { template struct RegisterWriteConstant { template - static void write(MMIO& mmio_device, + static void write(MMIO& mmio_device, // NOLINTNEXTLINE is_not_trivial* = nullptr) noexcept { - mmio_device = - static_cast((mmio_device & ~mask) | ((value << offset) & mask)); + constexpr auto shifted_value = static_cast(value << offset); + const auto lhs = static_cast(mmio_device & static_cast(~mask)); + constexpr auto rhs = static_cast(shifted_value & mask); + mmio_device = static_cast(lhs | rhs); } template - static void write(MMIO& mmio_device, + static void write(MMIO& mmio_device, // NOLINTNEXTLINE is_trivial* = nullptr) noexcept { mmio_device = value; } }; -struct read_only { +struct read_only { // NOLINT template static T read(const MMIO& mmio_device) noexcept { return RegisterRead::read(mmio_device); } }; -struct read_write : read_only { +struct read_write : read_only { // NOLINT template static void write(MMIO& mmio_device, const T value) noexcept { RegisterWrite::write(mmio_device, value); @@ -215,7 +226,7 @@ struct read_write : read_only { mmio_device = static_cast((mmio_device) ^ mask); } }; -struct write_only { +struct write_only { // NOLINT template static void write(MMIO& mmio_device, const T value) noexcept { RegisterWrite::value, FieldOffset{0}>::write( @@ -239,9 +250,13 @@ struct write_only { namespace cppreg { template constexpr Mask make_mask(const FieldWidth width) noexcept { - return width == 0 ? static_cast(0u) - : static_cast( - (make_mask(FieldWidth(width - 1)) << 1) | 1); + return width == 0U + ? static_cast(0U) + : static_cast( + static_cast(make_mask(FieldWidth( + static_cast(width - 1U))) + << 1U) + | 1U); } template constexpr Mask make_shifted_mask(const FieldWidth width, @@ -274,18 +289,19 @@ template -class MergeWrite_tmpl { +class MergeWrite_tmpl { // NOLINT private: - using base_type = typename Register::type; - constexpr static auto _accumulated_value = + using base_type = typename Register::type; // NOLINT + constexpr static auto _accumulated_value = // NOLINT base_type{(value << offset) & mask}; - constexpr static auto _combined_mask = mask; + constexpr static auto _combined_mask = mask; // NOLINT template - using propagated = + using propagated = // NOLINT MergeWrite_tmpl(~F::mask)) | ((new_value << F::offset) & F::mask)>; MergeWrite_tmpl() = default; static_assert(!Register::shadow::value, @@ -294,11 +310,12 @@ public: static MergeWrite_tmpl create() noexcept { return {}; } + ~MergeWrite_tmpl() = default; + MergeWrite_tmpl(MergeWrite_tmpl&&) noexcept = default; MergeWrite_tmpl(const MergeWrite_tmpl&) = delete; MergeWrite_tmpl& operator=(const MergeWrite_tmpl&) = delete; MergeWrite_tmpl& operator=(MergeWrite_tmpl&&) = delete; MergeWrite_tmpl operator=(MergeWrite_tmpl) = delete; - MergeWrite_tmpl(MergeWrite_tmpl&&) = delete; void done() const&& noexcept { typename Register::MMIO& mmio_device = Register::rw_mem_device(); RegisterWriteConstant::write(mmio_device); } template - propagated&& with() const&& noexcept { + propagated with() const&& noexcept { static_assert( std::is_same::value, "MergeWrite_tmpl:: field is not from the same register"); @@ -318,17 +335,18 @@ public: (F::mask >> F::offset)>::value; static_assert(no_overflow, "MergeWrite_tmpl:: field overflow in with() call"); - return std::move(propagated{}); + return propagated{}; } }; template class MergeWrite { private: - using base_type = typename Register::type; - base_type _accumulated_value; - constexpr static auto _combined_mask = mask; + using base_type = typename Register::type; // NOLINT + base_type _accumulated_value; // NOLINT + constexpr static auto _combined_mask = mask; // NOLINT template - using propagated = MergeWrite; + using propagated = // NOLINT + MergeWrite; constexpr MergeWrite() : _accumulated_value{0} {}; constexpr explicit MergeWrite(const base_type v) : _accumulated_value{v} {}; static_assert(!Register::shadow::value, @@ -337,6 +355,7 @@ public: constexpr static MergeWrite create(const base_type value) noexcept { return MergeWrite(value); } + ~MergeWrite() = default; MergeWrite(MergeWrite&& mw) noexcept : _accumulated_value{mw._accumulated_value} {}; MergeWrite(const MergeWrite&) = delete; @@ -354,9 +373,11 @@ public: static_assert( std::is_same::value, "field is not from the same register in merge_write"); - const auto new_value = static_cast( - (_accumulated_value & ~F::mask) | ((value << F::offset) & F::mask)); - return std::move(propagated::create(new_value)); + constexpr auto neg_mask = static_cast(~F::mask); + const auto shifted_value = static_cast(value << F::offset); + const auto lhs = static_cast(_accumulated_value & neg_mask); + const auto rhs = static_cast(shifted_value & F::mask); + return propagated::create(static_cast(lhs | rhs)); } }; } @@ -371,26 +392,27 @@ template
::type reset_value = 0x0, bool use_shadow = false> struct Register { - using type = typename TypeTraits::type; + using type = typename TypeTraits::type; // NOLINT using MMIO = volatile type; - using shadow = Shadow; + using shadow = Shadow; // NOLINT constexpr static auto base_address = reg_address; constexpr static auto size = TypeTraits::bit_size; constexpr static auto reset = reset_value; - using pack = RegisterPack; + using pack = RegisterPack; // NOLINT static MMIO& rw_mem_device() { - using mem_device = typename RegisterMemoryDevice::mem_device; - return mem_device::template rw_memory(); + using MemDevice = typename RegisterMemoryDevice::mem_device; + return MemDevice::template rw_memory(); } static const MMIO& ro_mem_device() { - using mem_device = typename RegisterMemoryDevice::mem_device; - return mem_device::template ro_memory(); + using MemDevice = typename RegisterMemoryDevice::mem_device; + return MemDevice::template ro_memory(); } template static MergeWrite merge_write( const typename F::type value) noexcept { + const auto lhs = static_cast(value << F::offset); return MergeWrite::create( - static_cast((value << F::offset) & F::mask)); + static_cast(lhs & F::mask)); } template > - static T&& merge_write() noexcept { + static T merge_write() noexcept { static_assert( internals::check_overflow> F::offset)>:: value, "Register::merge_write:: value too large for the field"); - return std::move(T::create()); + return T::create(); } - static_assert(size != 0u, "Register:: register definition with zero size"); + static_assert(size != 0, "Register:: register definition with zero size"); static_assert(internals::is_aligned::byte_size>::value, "Register:: address is mis-aligned for register type"); @@ -422,26 +444,30 @@ template ::type reset_value = 0x0, bool use_shadow = false> -struct PackedRegister : Register { - using pack = RegisterPack; - using base_reg = Register; +struct PackedRegister + : Register { + using pack = RegisterPack; // NOLINT + using base_reg = // NOLINT + Register; static typename base_reg::MMIO& rw_mem_device() noexcept { - using mem_device = + using MemDevice = typename RegisterMemoryDevice::mem_device; - return mem_device::template rw_memory(); + return MemDevice::template rw_memory(); } static const typename base_reg::MMIO& ro_mem_device() noexcept { - using mem_device = + using MemDevice = typename RegisterMemoryDevice::mem_device; - return mem_device::template ro_memory(); + return MemDevice::template ro_memory(); } - static_assert(TypeTraits::byte_size + (bit_offset / 8u) + static_assert(TypeTraits::byte_size + (bit_offset / one_byte) <= RegisterPack::size_in_bytes, "PackRegister:: packed register is overflowing the pack"); static_assert( @@ -449,32 +475,33 @@ struct PackedRegister : Register::byte_size>::value, "PackedRegister:: pack base address is mis-aligned for register type"); static_assert( - internals::is_aligned::byte_size>::value, "PackedRegister:: offset address is mis-aligned for register type"); }; template struct PackIndexing { - using tuple_t = typename std::tuple; + using tuple_t = typename std::tuple; // NOLINT constexpr static const std::size_t n_elems = std::tuple_size::value; - template - using elem = typename std::tuple_element::type; + template + using elem = typename std::tuple_element::type; // NOLINT }; template -struct for_loop { +struct for_loop { // NOLINT template static void apply() noexcept { Func().template operator()(); - if (start < end) - for_loop::template apply(); + if (start < end) { + for_loop::template apply(); + } } #if __cplusplus >= 201402L template static void apply(Op&& f) noexcept { if (start < end) { f(std::integral_constant{}); - for_loop::apply(std::forward(f)); + for_loop::apply(std::forward(f)); }; } #endif @@ -485,11 +512,11 @@ struct for_loop { static void apply() noexcept {} #if __cplusplus >= 201402L template - static void apply(Op&& f) noexcept {} -#endif + static void apply(Op&&) noexcept {} // NOLINT +#endif }; template -struct pack_loop : for_loop<0, IndexedPack::n_elems> {}; +struct pack_loop : for_loop<0, IndexedPack::n_elems> {}; // NOLINT } #endif @@ -502,18 +529,18 @@ template struct Field { - using parent_register = BaseRegister; - using type = typename parent_register::type; - using MMIO = typename parent_register::MMIO; - using policy = AccessPolicy; + using parent_register = BaseRegister; // NOLINT + using type = typename parent_register::type; // NOLINT + using MMIO = typename parent_register::MMIO; // NOLINT + using policy = AccessPolicy; // NOLINT constexpr static auto width = field_width; constexpr static auto offset = field_offset; constexpr static auto mask = make_shifted_mask(width, offset); template - using if_no_shadow = + using if_no_shadow = // NOLINT typename std::enable_if::type; template - using if_shadow = + using if_shadow = // NOLINT typename std::enable_if::type; static type read() noexcept { return policy::template read( @@ -534,7 +561,7 @@ struct Field { parent_register::shadow::shadow_value); } template - static void write(if_no_shadow* = nullptr) noexcept { + static void write(if_no_shadow* = nullptr) noexcept { // NOLINT policy::template write( parent_register::rw_mem_device()); static_assert( @@ -542,7 +569,7 @@ struct Field { "Field::write: value too large for the field"); } template - static void write(if_shadow* = nullptr) noexcept { + static void write(if_shadow* = nullptr) noexcept { // NOLINT write(value); static_assert( internals::check_overflow> offset)>::value, @@ -574,5 +601,6 @@ struct Field { "Field:: defining a Field type of zero width is not allowed"); }; } -#endif +#endif +/* clang-format on */