Simplify interface of the MMIO framework, ref #69

Parameterize register and bitfield templates to always take their
bitwidth instead of the according types or width exponents as arguments.
This commit is contained in:
Martin Stein 2012-01-17 18:55:24 +01:00 committed by Norman Feske
parent 7044b264e6
commit 70ae53fe3c
3 changed files with 198 additions and 120 deletions

View File

@ -15,8 +15,6 @@
#define _BASE__INCLUDE__UTIL__MMIO_H_ #define _BASE__INCLUDE__UTIL__MMIO_H_
#include <util/register.h> #include <util/register.h>
#include <base/printf.h>
namespace Genode namespace Genode
{ {
@ -30,110 +28,119 @@ namespace Genode
/** /**
* Write typed 'value' to MMIO base + 'o' * Write typed 'value' to MMIO base + 'o'
*/ */
template <typename STORAGE_T> template <typename _ACCESS_T>
inline void _write(off_t const o, STORAGE_T const value); inline void _write(off_t const o, _ACCESS_T const value);
/** /**
* Read typed from MMIO base + 'o' * Read typed from MMIO base + 'o'
*/ */
template <typename STORAGE_T> template <typename _ACCESS_T>
inline STORAGE_T _read(off_t const o) const; inline _ACCESS_T _read(off_t const o) const;
public: public:
enum { BYTE_WIDTH_LOG2 = 3, BYTE_WIDTH = 1 << BYTE_WIDTH_LOG2 }; enum { BYTE_WIDTH_LOG2 = 3, BYTE_WIDTH = 1 << BYTE_WIDTH_LOG2 };
/** /**
* A POD-like region at offset 'MMIO_OFFSET' within a MMIO region * An integer like region within a MMIO region.
* *
* \detail The register can contain multiple bitfields. Bitfields * \param _OFFSET Offset of the region relative to the base
* that are partially out of the register range are read and * of the compound MMIO.
* written also partially. Bitfields that are completely out * \param _ACCESS_WIDTH Bit width of the region.
* of the register range are read as '0' and trying to *
* overwrite them has no effect * \detail See 'Genode::Register'
*/ */
template <off_t MMIO_OFFSET, typename STORAGE_T> template <off_t _OFFSET, unsigned long _ACCESS_WIDTH>
struct Register : public Genode::Register<STORAGE_T> struct Register : public Genode::Register<_ACCESS_WIDTH>
{ {
enum { OFFSET = MMIO_OFFSET }; enum {
OFFSET = _OFFSET,
ACCESS_WIDTH = _ACCESS_WIDTH,
};
/** /**
* A bitregion within a register * A region within a register
* *
* \detail Bitfields are read and written according to their range, * \param _SHIFT Bit shift of the first bit within the compound register
* so if we have a 'Bitfield<2,3>' and write '0b11101' to it * \param _WIDTH Bit width of the region
* only '0b101' (shiftet by 2 bits) is written *
* \detail See 'Genode::Register::Bitfield'
*/ */
template <unsigned long BIT_SHIFT, unsigned long BIT_SIZE> template <unsigned long _SHIFT, unsigned long _WIDTH>
struct Bitfield : public Genode::Register<STORAGE_T>::template Bitfield<BIT_SHIFT, BIT_SIZE> struct Bitfield : public Genode::Register<ACCESS_WIDTH>::template Bitfield<_SHIFT, _WIDTH>
{ {
/** /**
* Back reference to containing register * Back reference to containing register
*/ */
typedef Register<OFFSET, STORAGE_T> Compound_reg; typedef Register<OFFSET, ACCESS_WIDTH> Compound_reg;
}; };
}; };
/** /**
* An array of successive similar items * An array of successive equally structured regions
* *
* \detail 'STORAGE_T' width must be a power of 2. The array * \param _OFFSET Offset of the first region relative to the base
* takes all bitfields that are covered by an item width and * of the compound MMIO.
* iterates them successive 'ITEMS' times. Thus bitfields out of * \param _ACCESS_WIDTH Bit width of a single access, must be at least
* the range of the first item are not accessible in any item. * the item width.
* Furthermore the maximum item width is the width of 'STORAGE_T'. * \param _ITEMS How many times the region gets iterated successive
* The array is not limited to one 'STORAGE_T' instance, * \param _ITEM_WIDTH Bit width of a region
* it uses as much successive instances as needed. *
* \detail The array takes all inner structures, wich are covered by an item
* width and iterates them successive. Such structures that are partially
* exceed an item range are read and written also partially. Structures that are
* completely out of the item range are read as '0' and trying to overwrite
* them has no effect. The array is not limited to its access width, it extends to
* the memory region of its successive items. Trying to read out read with an item
* index out of the array range returns '0', trying to write to such indices
* has no effect
*/ */
template <off_t MMIO_OFFSET, typename STORAGE_T, unsigned long ITEMS, unsigned long _ITEM_WIDTH_LOG2> template <off_t _OFFSET, unsigned long _ACCESS_WIDTH, unsigned long _ITEMS, unsigned long _ITEM_WIDTH>
struct Register_array : public Register<MMIO_OFFSET, STORAGE_T> struct Register_array : public Register<_OFFSET, _ACCESS_WIDTH>
{ {
enum { typedef typename Trait::Uint_type<_ACCESS_WIDTH>::template Divisor<_ITEM_WIDTH> Item;
MAX_INDEX = ITEMS - 1,
ITEM_WIDTH_LOG2 = _ITEM_WIDTH_LOG2,
ITEM_WIDTH = 1 << ITEM_WIDTH_LOG2,
ITEM_MASK = (1 << ITEM_WIDTH) - 1,
ITEMS_PER_REG = (sizeof(STORAGE_T) << BYTE_WIDTH_LOG2) >> ITEM_WIDTH_LOG2,
ITEM_IS_REG = ITEMS_PER_REG == 1,
STORAGE_WIDTH = BYTE_WIDTH * sizeof(STORAGE_T),
/** enum {
* Static sanity check OFFSET = _OFFSET,
*/ ACCESS_WIDTH = _ACCESS_WIDTH,
ERROR_ITEMS_OVERSIZED = ITEMS_PER_REG / ITEMS_PER_REG, ITEMS = _ITEMS,
ITEM_WIDTH = _ITEM_WIDTH,
ITEM_WIDTH_LOG2 = Item::WIDTH_LOG2,
MAX_INDEX = ITEMS - 1,
ITEM_MASK = (1 << ITEM_WIDTH) - 1,
}; };
typedef typename Register<OFFSET, ACCESS_WIDTH>::access_t access_t;
/** /**
* A bitregion within a register array * A bitregion within a register array item
* *
* \detail Bitfields are only written and read as far as the * \param _SHIFT Bit shift of the first bit within an item
* item width reaches, i.e. assume a 'Register_array<0,uint8_t,6,2>' * \param _WIDTH Bit width of the region
* that contains a 'Bitfield<1,5>' and we write '0b01101' to it, then *
* only '0b101' is written and read in consequence. Bitfields that are * \detail See 'Genode::Register::Bitfield'
* completely out of the item range ar read as '0' and trying to overwrite
* them has no effect.
*/ */
template <unsigned long BIT_SHIFT, unsigned long BIT_SIZE> template <unsigned long _SHIFT, unsigned long _SIZE>
struct Bitfield : public Register<MMIO_OFFSET, STORAGE_T>::template Bitfield<BIT_SHIFT, BIT_SIZE> struct Bitfield : public Register<OFFSET, ACCESS_WIDTH>::template Bitfield<_SHIFT, _SIZE>
{ {
/** /**
* Back reference to containing register array * Back reference to containing register array
*/ */
typedef Register_array<MMIO_OFFSET, STORAGE_T, ITEMS, ITEM_WIDTH_LOG2> Compound_array; typedef Register_array<OFFSET, ACCESS_WIDTH, ITEMS, ITEM_WIDTH> Compound_array;
}; };
/** /**
* Calculate the MMIO-relative offset 'offset' and shift 'shift' * Calculate the MMIO-relative offset 'offset' and shift 'shift'
* within the according 'storage_t' instance to access this bitfield * within the according 'access_t' instance to access item 'index'
* from item 'index'
*/ */
static inline void access_dest(off_t & offset, unsigned long & shift, static inline void access_dest(off_t & offset, unsigned long & shift,
unsigned long const index) unsigned long const index)
{ {
unsigned long const bit_off = index << ITEM_WIDTH_LOG2; unsigned long const bit_off = index << ITEM_WIDTH_LOG2;
offset = (off_t) ((bit_off >> BYTE_WIDTH_LOG2) & ~(sizeof(STORAGE_T)-1) ); offset = (off_t) ((bit_off >> BYTE_WIDTH_LOG2) & ~(sizeof(access_t)-1) );
shift = bit_off - ( offset << BYTE_WIDTH_LOG2 ); shift = bit_off - ( offset << BYTE_WIDTH_LOG2 );
offset += MMIO_OFFSET; offset += OFFSET;
} }
}; };
@ -153,19 +160,19 @@ namespace Genode
* Typed address of register 'REGISTER' * Typed address of register 'REGISTER'
*/ */
template <typename REGISTER> template <typename REGISTER>
inline typename REGISTER::storage_t volatile * typed_addr() const; inline typename REGISTER::access_t volatile * typed_addr() const;
/** /**
* Read the whole register 'REGISTER' * Read the whole register 'REGISTER'
*/ */
template <typename REGISTER> template <typename REGISTER>
inline typename REGISTER::storage_t read() const; inline typename REGISTER::access_t read() const;
/** /**
* Write 'value' to the register 'REGISTER' * Write 'value' to the register 'REGISTER'
*/ */
template <typename REGISTER> template <typename REGISTER>
inline void write(typename REGISTER::storage_t const value); inline void write(typename REGISTER::access_t const value);
/****************************************** /******************************************
@ -176,13 +183,13 @@ namespace Genode
* Read the bitfield 'BITFIELD' * Read the bitfield 'BITFIELD'
*/ */
template <typename BITFIELD> template <typename BITFIELD>
inline typename BITFIELD::Compound_reg::storage_t read() const; inline typename BITFIELD::Compound_reg::access_t read() const;
/** /**
* Write value to the bitfield 'BITFIELD' * Write value to the bitfield 'BITFIELD'
*/ */
template <typename BITFIELD> template <typename BITFIELD>
inline void write(typename BITFIELD::Compound_reg::storage_t const value); inline void write(typename BITFIELD::Compound_reg::access_t const value);
/******************************* /*******************************
@ -193,13 +200,13 @@ namespace Genode
* Read the whole item 'index' of the array 'REGISTER_ARRAY' * Read the whole item 'index' of the array 'REGISTER_ARRAY'
*/ */
template <typename REGISTER_ARRAY> template <typename REGISTER_ARRAY>
inline typename REGISTER_ARRAY::storage_t read(unsigned long const index) const; inline typename REGISTER_ARRAY::access_t read(unsigned long const index) const;
/** /**
* Write 'value' to item 'index' of the array 'REGISTER_ARRAY' * Write 'value' to item 'index' of the array 'REGISTER_ARRAY'
*/ */
template <typename REGISTER_ARRAY> template <typename REGISTER_ARRAY>
inline void write(typename REGISTER_ARRAY::storage_t const value, inline void write(typename REGISTER_ARRAY::access_t const value,
unsigned long const index); unsigned long const index);
@ -211,28 +218,28 @@ namespace Genode
* Read the bitfield 'ARRAY_BITFIELD' of item 'index' of the compound reg array * Read the bitfield 'ARRAY_BITFIELD' of item 'index' of the compound reg array
*/ */
template <typename ARRAY_BITFIELD> template <typename ARRAY_BITFIELD>
inline typename ARRAY_BITFIELD::Compound_array::storage_t read(unsigned long const index) const; inline typename ARRAY_BITFIELD::Compound_array::access_t read(unsigned long const index) const;
/** /**
* Write 'value' to bitfield 'ARRAY_BITFIELD' of item 'index' of the compound reg array * Write 'value' to bitfield 'ARRAY_BITFIELD' of item 'index' of the compound reg array
*/ */
template <typename ARRAY_BITFIELD> template <typename ARRAY_BITFIELD>
inline void write(typename ARRAY_BITFIELD::Compound_array::storage_t const value, long unsigned const index); inline void write(typename ARRAY_BITFIELD::Compound_array::access_t const value, long unsigned const index);
}; };
} }
template <typename STORAGE_T> template <typename ACCESS_T>
void Genode::Mmio::_write(off_t const o, STORAGE_T const value) void Genode::Mmio::_write(off_t const o, ACCESS_T const value)
{ {
*(STORAGE_T volatile *)((addr_t)base + o) = value; *(ACCESS_T volatile *)((addr_t)base + o) = value;
} }
template <typename STORAGE_T> template <typename ACCESS_T>
STORAGE_T Genode::Mmio::_read(off_t const o) const ACCESS_T Genode::Mmio::_read(off_t const o) const
{ {
return *(STORAGE_T volatile *)((addr_t)base + o); return *(ACCESS_T volatile *)((addr_t)base + o);
} }
@ -242,23 +249,23 @@ STORAGE_T Genode::Mmio::_read(off_t const o) const
template <typename REGISTER> template <typename REGISTER>
typename REGISTER::storage_t volatile * Genode::Mmio::typed_addr() const typename REGISTER::access_t volatile * Genode::Mmio::typed_addr() const
{ {
return (typename REGISTER::storage_t volatile *)base + REGISTER::OFFSET; return (typename REGISTER::access_t volatile *)base + REGISTER::OFFSET;
} }
template <typename REGISTER> template <typename REGISTER>
typename REGISTER::storage_t Genode::Mmio::read() const typename REGISTER::access_t Genode::Mmio::read() const
{ {
return _read<typename REGISTER::storage_t>(REGISTER::OFFSET); return _read<typename REGISTER::access_t>(REGISTER::OFFSET);
} }
template <typename REGISTER> template <typename REGISTER>
void Genode::Mmio::write(typename REGISTER::storage_t const value) void Genode::Mmio::write(typename REGISTER::access_t const value)
{ {
_write<typename REGISTER::storage_t>(REGISTER::OFFSET, value); _write<typename REGISTER::access_t>(REGISTER::OFFSET, value);
} }
@ -268,22 +275,22 @@ void Genode::Mmio::write(typename REGISTER::storage_t const value)
template <typename BITFIELD> template <typename BITFIELD>
typename BITFIELD::Compound_reg::storage_t Genode::Mmio::read() const typename BITFIELD::Compound_reg::access_t Genode::Mmio::read() const
{ {
typedef typename BITFIELD::Compound_reg Register; typedef typename BITFIELD::Compound_reg Register;
typedef typename Register::storage_t storage_t; typedef typename Register::access_t access_t;
return BITFIELD::get(_read<storage_t>(Register::OFFSET)); return BITFIELD::get(_read<access_t>(Register::OFFSET));
} }
template <typename BITFIELD> template <typename BITFIELD>
void Genode::Mmio::write(typename BITFIELD::Compound_reg::storage_t const value) void Genode::Mmio::write(typename BITFIELD::Compound_reg::access_t const value)
{ {
typedef typename BITFIELD::Compound_reg Register; typedef typename BITFIELD::Compound_reg Register;
typedef typename Register::storage_t storage_t; typedef typename Register::access_t access_t;
storage_t new_reg = read<Register>(); access_t new_reg = read<Register>();
BITFIELD::clear(new_reg); BITFIELD::clear(new_reg);
BITFIELD::set(new_reg, value); BITFIELD::set(new_reg, value);
@ -297,7 +304,7 @@ void Genode::Mmio::write(typename BITFIELD::Compound_reg::storage_t const value)
template <typename REGISTER_ARRAY> template <typename REGISTER_ARRAY>
typename REGISTER_ARRAY::storage_t Genode::Mmio::read(unsigned long const index) const typename REGISTER_ARRAY::access_t Genode::Mmio::read(unsigned long const index) const
{ {
/** /**
* Handle array overflow * Handle array overflow
@ -307,25 +314,25 @@ typename REGISTER_ARRAY::storage_t Genode::Mmio::read(unsigned long const index)
off_t offset; off_t offset;
/** /**
* Optimize access if item width equals storage type width * Optimize access if item width equals access width
*/ */
if (REGISTER_ARRAY::ITEM_IS_REG) { if (REGISTER_ARRAY::ITEM_WIDTH == REGISTER_ARRAY::ACCESS_WIDTH) {
offset = REGISTER_ARRAY::OFFSET + (index << REGISTER_ARRAY::ITEM_WIDTH_LOG2); offset = REGISTER_ARRAY::OFFSET + (index << REGISTER_ARRAY::ITEM_WIDTH_LOG2);
return _read<typename REGISTER_ARRAY::storage_t>(offset); return _read<typename REGISTER_ARRAY::access_t>(offset);
} else { } else {
long unsigned shift; long unsigned shift;
REGISTER_ARRAY::access_dest(offset, shift, index); REGISTER_ARRAY::access_dest(offset, shift, index);
return (_read<typename REGISTER_ARRAY::storage_t>(offset) >> shift) & REGISTER_ARRAY::ITEM_MASK; return (_read<typename REGISTER_ARRAY::access_t>(offset) >> shift) & REGISTER_ARRAY::ITEM_MASK;
} }
} }
template <typename REGISTER_ARRAY> template <typename REGISTER_ARRAY>
void Genode::Mmio::write(typename REGISTER_ARRAY::storage_t const value, void Genode::Mmio::write(typename REGISTER_ARRAY::access_t const value,
unsigned long const index) unsigned long const index)
{ {
/** /**
@ -336,12 +343,12 @@ void Genode::Mmio::write(typename REGISTER_ARRAY::storage_t const value,
off_t offset; off_t offset;
/** /**
* Optimize access if item width equals storage type width * Optimize access if item width equals access width
*/ */
if (REGISTER_ARRAY::ITEM_IS_REG) { if (REGISTER_ARRAY::ITEM_WIDTH == REGISTER_ARRAY::ACCESS_WIDTH) {
offset = REGISTER_ARRAY::OFFSET + (index << REGISTER_ARRAY::ITEM_WIDTH_LOG2); offset = REGISTER_ARRAY::OFFSET + (index << REGISTER_ARRAY::ITEM_WIDTH_LOG2);
_write<typename REGISTER_ARRAY::storage_t>(offset, value); _write<typename REGISTER_ARRAY::access_t>(offset, value);
} else { } else {
@ -351,11 +358,11 @@ void Genode::Mmio::write(typename REGISTER_ARRAY::storage_t const value,
/** /**
* Insert new value into old register value * Insert new value into old register value
*/ */
typename REGISTER_ARRAY::storage_t new_reg = _read<typename REGISTER_ARRAY::storage_t>(offset); typename REGISTER_ARRAY::access_t new_reg = _read<typename REGISTER_ARRAY::access_t>(offset);
new_reg &= ~(REGISTER_ARRAY::ITEM_MASK << shift); new_reg &= ~(REGISTER_ARRAY::ITEM_MASK << shift);
new_reg |= (value & REGISTER_ARRAY::ITEM_MASK) << shift; new_reg |= (value & REGISTER_ARRAY::ITEM_MASK) << shift;
_write<typename REGISTER_ARRAY::storage_t>(offset, new_reg); _write<typename REGISTER_ARRAY::access_t>(offset, new_reg);
} }
} }
@ -366,12 +373,12 @@ void Genode::Mmio::write(typename REGISTER_ARRAY::storage_t const value,
template <typename ARRAY_BITFIELD> template <typename ARRAY_BITFIELD>
void Genode::Mmio::write(typename ARRAY_BITFIELD::Compound_array::storage_t const value, void Genode::Mmio::write(typename ARRAY_BITFIELD::Compound_array::access_t const value,
long unsigned const index) long unsigned const index)
{ {
typedef typename ARRAY_BITFIELD::Compound_array Register_array; typedef typename ARRAY_BITFIELD::Compound_array Register_array;
typename Register_array::storage_t new_reg = read<Register_array>(index); typename Register_array::access_t new_reg = read<Register_array>(index);
ARRAY_BITFIELD::clear(new_reg); ARRAY_BITFIELD::clear(new_reg);
ARRAY_BITFIELD::set(new_reg, value); ARRAY_BITFIELD::set(new_reg, value);
@ -380,10 +387,10 @@ void Genode::Mmio::write(typename ARRAY_BITFIELD::Compound_array::storage_t cons
template <typename ARRAY_BITFIELD> template <typename ARRAY_BITFIELD>
typename ARRAY_BITFIELD::Compound_array::storage_t Genode::Mmio::read(long unsigned const index) const typename ARRAY_BITFIELD::Compound_array::access_t Genode::Mmio::read(long unsigned const index) const
{ {
typedef typename ARRAY_BITFIELD::Compound_array Array; typedef typename ARRAY_BITFIELD::Compound_array Array;
typedef typename Array::storage_t storage_t; typedef typename Array::access_t access_t;
return ARRAY_BITFIELD::get(read<Array>(index)); return ARRAY_BITFIELD::get(read<Array>(index));
} }

View File

@ -18,23 +18,94 @@
namespace Genode namespace Genode
{ {
namespace Trait {
/**
* Get unsigned integer type for a given access width
*/
template <unsigned long _WIDTH> struct Uint_type;
template <> struct Uint_type<8>
{
typedef uint8_t Type;
enum { WIDTH_LOG2 = 3 };
/**
* Declare dividers of the compound type width
*/
template <unsigned long _DIVISOR_WIDTH> struct Divisor;
};
template <> struct Uint_type<16> : Uint_type<8>
{
typedef uint16_t Type;
enum { WIDTH_LOG2 = 4 };
};
template <> struct Uint_type<32> : Uint_type<16>
{
typedef uint32_t Type;
enum { WIDTH_LOG2 = 5 };
};
template <> struct Uint_type<64> : Uint_type<32>
{
typedef uint32_t Type;
enum { WIDTH_LOG2 = 6 };
};
template <> struct Uint_type<8>::Divisor<1> { enum { WIDTH_LOG2 = 0 }; };
template <> struct Uint_type<8>::Divisor<2> { enum { WIDTH_LOG2 = 1 }; };
template <> struct Uint_type<8>::Divisor<4> { enum { WIDTH_LOG2 = 2 }; };
template <> struct Uint_type<8>::Divisor<8> { enum { WIDTH_LOG2 = 3 }; };
template <> struct Uint_type<16>::Divisor<16> { enum { WIDTH_LOG2 = 4 }; };
template <> struct Uint_type<32>::Divisor<32> { enum { WIDTH_LOG2 = 5 }; };
template <> struct Uint_type<64>::Divisor<64> { enum { WIDTH_LOG2 = 6 }; };
}
/** /**
* A POD-like highly structured memory region * An integer like highly structured memory region
*
* \param _ACCESS_WIDTH Bit width of the region
*
* \detail The register can contain multiple bitfields. Bitfields
* that are partially exceed the register range are read and
* written also partially. Bitfields that are completely out
* of the register range are read as '0' and trying to
* overwrite them has no effect.
*/ */
template <typename STORAGE_T> template <unsigned long _ACCESS_WIDTH>
struct Register struct Register
{ {
typedef STORAGE_T storage_t; enum {
ACCESS_WIDTH = _ACCESS_WIDTH,
ACCESS_WIDTH_LOG2 = Trait::Uint_type<ACCESS_WIDTH>::WIDTH_LOG2,
};
typedef typename Trait::Uint_type<ACCESS_WIDTH>::Type access_t;
/** /**
* A bitregion within a register * A bitregion within a register
*
* \param _SHIFT Bit shift of the first bit within the compound register
* \param _WIDTH Bit width of the region
*
* \detail Bitfields are read and written according to their range,
* so if we have a 'Bitfield<2,3>' and write '0b11101' to it
* only '0b101' (shiftet by 2 bits) is written
*/ */
template <unsigned long BIT_SHIFT, unsigned long BIT_SIZE> template <unsigned long _SHIFT, unsigned long _WIDTH>
struct Bitfield struct Bitfield
{ {
enum { enum {
SHIFT = BIT_SHIFT,
WIDTH = BIT_SIZE, /**
* Fetch template parameters
*/
SHIFT = _SHIFT,
WIDTH = _WIDTH,
MASK = (1 << WIDTH) - 1, MASK = (1 << WIDTH) - 1,
REG_MASK = MASK << SHIFT, REG_MASK = MASK << SHIFT,
CLEAR_MASK = ~REG_MASK, CLEAR_MASK = ~REG_MASK,
@ -43,7 +114,7 @@ namespace Genode
/** /**
* Back reference to containing register * Back reference to containing register
*/ */
typedef Register<storage_t> Compound_reg; typedef Register<ACCESS_WIDTH> Compound_reg;
/** /**
* Get a register value with this bitfield set to 'value' and the rest left zero * Get a register value with this bitfield set to 'value' and the rest left zero
@ -51,22 +122,22 @@ namespace Genode
* \detail Useful to combine successive access to multiple bitfields * \detail Useful to combine successive access to multiple bitfields
* into one operation * into one operation
*/ */
static inline storage_t bits(storage_t const value) { return (value & MASK) << SHIFT; } static inline access_t bits(access_t const value) { return (value & MASK) << SHIFT; }
/** /**
* Get value of this bitfield from 'reg' * Get value of this bitfield from 'reg'
*/ */
static inline storage_t get(storage_t const reg) { return (reg >> SHIFT) & MASK; } static inline access_t get(access_t const reg) { return (reg >> SHIFT) & MASK; }
/** /**
* Get registervalue 'reg' with this bitfield set to zero * Get registervalue 'reg' with this bitfield set to zero
*/ */
static inline void clear(storage_t & reg) { reg &= CLEAR_MASK; } static inline void clear(access_t & reg) { reg &= CLEAR_MASK; }
/** /**
* Get registervalue 'reg' with this bitfield set to 'value' * Get registervalue 'reg' with this bitfield set to 'value'
*/ */
static inline void set(storage_t & reg, storage_t const value = ~0) static inline void set(access_t & reg, access_t const value = ~0)
{ {
clear(reg); clear(reg);
reg |= (value & MASK) << SHIFT; reg |= (value & MASK) << SHIFT;

View File

@ -31,7 +31,7 @@ static uint8_t mmio_mem[MMIO_SIZE];
/** /**
* Exemplary highly structured type for accessing 'cpu_state' * Exemplary highly structured type for accessing 'cpu_state'
*/ */
struct Cpu_state : Register<uint16_t> struct Cpu_state : Register<16>
{ {
struct Mode : Bitfield<0,4> struct Mode : Bitfield<0,4>
{ {
@ -49,9 +49,9 @@ struct Cpu_state : Register<uint16_t>
struct Invalid_bit : Bitfield<18,1> { }; struct Invalid_bit : Bitfield<18,1> { };
struct Invalid_area : Bitfield<15,4> { }; struct Invalid_area : Bitfield<15,4> { };
inline static storage_t read() { return cpu_state; } inline static access_t read() { return cpu_state; }
inline static void write(storage_t & v) { cpu_state = v; } inline static void write(access_t & v) { cpu_state = v; }
}; };
struct A : public Mmio { struct A : public Mmio {
@ -67,15 +67,15 @@ struct Test_mmio : public Mmio
{ {
Test_mmio(addr_t const base) : Mmio(base) { } Test_mmio(addr_t const base) : Mmio(base) { }
struct Reg : Register<0x04, uint8_t> struct Reg : Register<0x04, 8>
{ {
struct Bit_1 : Bitfield<0,1> { }; struct Bit_1 : Bitfield<0,1> { };
struct Area : Bitfield<1,3> struct Area : Bitfield<1,3>
{ {
enum { enum {
VALUE_1 = 3, VALUE_1 = 3,
VALUE_2 = 4, VALUE_2 = 4,
VALUE_3 = 5, VALUE_3 = 5,
}; };
}; };
struct Bit_2 : Bitfield<4,1> { }; struct Bit_2 : Bitfield<4,1> { };
@ -84,7 +84,7 @@ struct Test_mmio : public Mmio
struct Overlapping_area : Bitfield<0,6> { }; struct Overlapping_area : Bitfield<0,6> { };
}; };
struct Array : Register_array<0x2, uint16_t, 10, 2> struct Array : Register_array<0x2, 16, 10, 4>
{ {
struct A : Bitfield<0,1> { }; struct A : Bitfield<0,1> { };
struct B : Bitfield<1,2> { }; struct B : Bitfield<1,2> { };
@ -251,7 +251,7 @@ int main()
/** /**
* Test 9, read/write bitfields appropriately, overflowing and out of range * Test 9, read/write bitfields appropriately, overflowing and out of range
*/ */
Cpu_state::storage_t state = Cpu_state::read(); Cpu_state::access_t state = Cpu_state::read();
Cpu_state::Mode::set(state, Cpu_state::Mode::MONITOR); Cpu_state::Mode::set(state, Cpu_state::Mode::MONITOR);
Cpu_state::A::set(state, 1); Cpu_state::A::set(state, 1);
Cpu_state::B::set(state); Cpu_state::B::set(state);