Skip to content

Commit

Permalink
FIX INLINING OF WRITE CALLS WITH Os ENABLED
Browse files Browse the repository at this point in the history
The inlining issue was due to a bad template design in the access policies
implementations: the MMIO_t type from the field was used (which is a volatile
type) for all arguments in the write implementation.
The new implementation relies on two template types (one for the register memory
device and another one for the value to be written). This fixes inlining and was
checked on godbolt.
  • Loading branch information
sendyne-nicocvn committed Feb 22, 2018
1 parent d7404ab commit 5cf8a85
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 66 deletions.
34 changes: 21 additions & 13 deletions policies/AccessPolicy.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ namespace cppreg {

//! Read access implementation.
/**
* @tparam MMIO_t Register memory device type.
* @tparam T Field data type.
* @param mmio_device Pointer to register mapped memory.
* @param mask Field mask.
* @param offset Field offset.
* @return The value at the field location.
*/
template <typename T>
inline static T read(const T* const mmio_device,
template <typename MMIO_t, typename T>
inline static T read(const MMIO_t* const mmio_device,
const T mask,
const Offset_t offset) noexcept {
return static_cast<T>((*mmio_device & mask) >> offset);
Expand All @@ -46,14 +47,15 @@ namespace cppreg {

//! Write access implementation.
/**
* @tparam MMIO_t Register memory device type.
* @tparam T Field data type.
* @param mmio_device Pointer to register mapped memory.
* @param mask Field mask.
* @param offset Field offset.
* @param value Value to be written at the field location.
*/
template <typename T>
inline static void write(T* const mmio_device,
template <typename MMIO_t, typename T>
inline static void write(MMIO_t* const mmio_device,
const T mask,
const Offset_t offset,
const T value) noexcept {
Expand All @@ -67,31 +69,36 @@ namespace cppreg {
* @param mmio_device Pointer to register mapped memory.
* @param mask Field mask.
*/
template <typename T>
inline static void set(T* const mmio_device, const T mask) noexcept {
template <typename MMIO_t, typename T>
inline static void set(MMIO_t* const mmio_device, const T mask)
noexcept {
*mmio_device = static_cast<T>((*mmio_device) | mask);
};

//! Clear field implementation.
/**
* @tparam MMIO_t Register memory device type.
* @tparam T Field data type.
* @param mmio_device Pointer to register mapped memory.
* @param mask Field mask.
*/
template <typename T>
inline static void clear(T* const mmio_device, const T mask) noexcept {
template <typename MMIO_t, typename T>
inline static void clear(MMIO_t* const mmio_device, const T mask)
noexcept {
*mmio_device = static_cast<T>((*mmio_device) & ~mask);
};

//! Toggle field implementation.
/**
* @tparam MMIO_t Register memory device type.
* @tparam T Field data type.
* @param mmio_device Pointer to register mapped memory.
* @param mask Field mask.
*/
template <typename T>
inline static void toggle(T* const mmio_device, const T mask) noexcept {
*mmio_device ^= mask;
template <typename MMIO_t, typename T>
inline static void toggle(MMIO_t* const mmio_device, const T mask)
noexcept {
*mmio_device = static_cast<T>((*mmio_device) ^ mask);
};

};
Expand All @@ -102,14 +109,15 @@ namespace cppreg {

//! Write access implementation.
/**
* @tparam MMIO_t Register memory device type.
* @tparam T Field data type.
* @param mmio_device Pointer to register mapped memory.
* @param mask Field mask.
* @param offset Field offset
* @param value Value to be written at the field location.
*/
template <typename T>
inline static void write(T* const mmio_device,
template <typename MMIO_t, typename T>
inline static void write(MMIO_t* const mmio_device,
const T mask,
const Offset_t offset,
const T value) noexcept {
Expand Down
34 changes: 14 additions & 20 deletions register/Field.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,9 @@ namespace cppreg {
*/
inline static type read() noexcept {
return
AccessPolicy
::template read<MMIO_t>(parent_register::ro_mem_pointer(),
mask,
offset);
AccessPolicy::read(parent_register::ro_mem_pointer(),
mask,
offset);
};

//! Field write method (shadow value disabled).
Expand All @@ -113,11 +112,10 @@ namespace cppreg {
write(const typename std::enable_if<
!parent_register::shadow::use_shadow, T
>::type value) noexcept {
AccessPolicy
::template write<MMIO_t>(parent_register::rw_mem_pointer(),
mask,
offset,
value);
AccessPolicy::write(parent_register::rw_mem_pointer(),
mask,
offset,
value);
};

//! Field write method (shadow value enabled).
Expand Down Expand Up @@ -147,11 +145,10 @@ namespace cppreg {

// Write as a block to the register, that is, we do not use the
// mask and offset.
AccessPolicy
::template write<MMIO_t>(parent_register::rw_mem_pointer(),
~(0u),
0u,
parent_register::shadow::value);
AccessPolicy::write(parent_register::rw_mem_pointer(),
~(0u),
0u,
parent_register::shadow::value);

};

Expand Down Expand Up @@ -205,26 +202,23 @@ namespace cppreg {
* This method will set all bits in the field.
*/
inline static void set() noexcept {
AccessPolicy
::template set<MMIO_t>(parent_register::rw_mem_pointer(), mask);
AccessPolicy::set(parent_register::rw_mem_pointer(), mask);
};

//! Field clear method.
/**
* This method will clear all bits in the field.
*/
inline static void clear() noexcept {
AccessPolicy
::template clear<MMIO_t>(parent_register::rw_mem_pointer(), mask);
AccessPolicy::clear(parent_register::rw_mem_pointer(), mask);
};

//! Field toggle method.
/**
* This method will toggle all bits in the field.
*/
inline static void toggle() noexcept {
AccessPolicy
::template toggle<MMIO_t>(parent_register::rw_mem_pointer(), mask);
AccessPolicy::toggle(parent_register::rw_mem_pointer(), mask);
};

//! Is field set bool method.
Expand Down
63 changes: 30 additions & 33 deletions single/cppreg-all.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,38 +24,41 @@ namespace cppreg {
#define CPPREG_ACCESSPOLICY_H
namespace cppreg {
struct read_only {
template <typename T>
inline static T read(const T* const mmio_device,
template <typename MMIO_t, typename T>
inline static T read(const MMIO_t* const mmio_device,
const T mask,
const Offset_t offset) noexcept {
return static_cast<T>((*mmio_device & mask) >> offset);
};
};
struct read_write : read_only {
template <typename T>
inline static void write(T* const mmio_device,
template <typename MMIO_t, typename T>
inline static void write(MMIO_t* const mmio_device,
const T mask,
const Offset_t offset,
const T value) noexcept {
*mmio_device = static_cast<T>((*mmio_device & ~mask) |
((value << offset) & mask));
};
template <typename T>
inline static void set(T* const mmio_device, const T mask) noexcept {
template <typename MMIO_t, typename T>
inline static void set(MMIO_t* const mmio_device, const T mask)
noexcept {
*mmio_device = static_cast<T>((*mmio_device) | mask);
};
template <typename T>
inline static void clear(T* const mmio_device, const T mask) noexcept {
template <typename MMIO_t, typename T>
inline static void clear(MMIO_t* const mmio_device, const T mask)
noexcept {
*mmio_device = static_cast<T>((*mmio_device) & ~mask);
};
template <typename T>
inline static void toggle(T* const mmio_device, const T mask) noexcept {
*mmio_device ^= mask;
template <typename MMIO_t, typename T>
inline static void toggle(MMIO_t* const mmio_device, const T mask)
noexcept {
*mmio_device = static_cast<T>((*mmio_device) ^ mask);
};
};
struct write_only {
template <typename T>
inline static void write(T* const mmio_device,
template <typename MMIO_t, typename T>
inline static void write(MMIO_t* const mmio_device,
const T mask,
const Offset_t offset,
const T value) noexcept {
Expand Down Expand Up @@ -287,21 +290,19 @@ namespace cppreg {
};
inline static type read() noexcept {
return
AccessPolicy
::template read<MMIO_t>(parent_register::ro_mem_pointer(),
mask,
offset);
AccessPolicy::read(parent_register::ro_mem_pointer(),
mask,
offset);
};
template <typename T = type>
inline static void
write(const typename std::enable_if<
!parent_register::shadow::use_shadow, T
>::type value) noexcept {
AccessPolicy
::template write<MMIO_t>(parent_register::rw_mem_pointer(),
mask,
offset,
value);
AccessPolicy::write(parent_register::rw_mem_pointer(),
mask,
offset,
value);
};
template <typename T = type>
inline static void
Expand All @@ -311,11 +312,10 @@ namespace cppreg {
parent_register::shadow::value =
(parent_register::shadow::value & ~mask) |
((value << offset) & mask);
AccessPolicy
::template write<MMIO_t>(parent_register::rw_mem_pointer(),
~(0u),
0u,
parent_register::shadow::value);
AccessPolicy::write(parent_register::rw_mem_pointer(),
~(0u),
0u,
parent_register::shadow::value);
};
template <type value, typename T = void>
inline static
Expand All @@ -340,16 +340,13 @@ namespace cppreg {
write(value);
};
inline static void set() noexcept {
AccessPolicy
::template set<MMIO_t>(parent_register::rw_mem_pointer(), mask);
AccessPolicy::set(parent_register::rw_mem_pointer(), mask);
};
inline static void clear() noexcept {
AccessPolicy
::template clear<MMIO_t>(parent_register::rw_mem_pointer(), mask);
AccessPolicy::clear(parent_register::rw_mem_pointer(), mask);
};
inline static void toggle() noexcept {
AccessPolicy
::template toggle<MMIO_t>(parent_register::rw_mem_pointer(), mask);
AccessPolicy::toggle(parent_register::rw_mem_pointer(), mask);
};
template <typename T = bool>
inline static typename std::enable_if<FieldWidth == 1, T>::type
Expand Down

0 comments on commit 5cf8a85

Please sign in to comment.