mmio: provide basic verbosity

The verbosity must be enabled at two levels: at compile time
via an enum that switches the availability of verbosity code
and via two members of 'Mmio' named '_read_verbose' and
'_write_verbose'. The latter are initialized to 0 (change this to
enable verbosity globally) and can be used to locally enable
(or disable) verbosity in deriving classes.

Ref #753
This commit is contained in:
Martin Stein 2013-05-29 20:12:29 +02:00 committed by Stefan Kalkowski
parent e23f24505b
commit 0c7c285079
2 changed files with 102 additions and 40 deletions

View File

@ -29,21 +29,67 @@ namespace Genode
*/
class Mmio
{
/*
* If set 0 verbosity isn't needed at all and the enum enables the
* compiler to remove all verbosity code. If set 1 verbosity code
* gets compiled and is then switched via '*_verbose' member variables.
*/
enum { VERBOSITY_AVAILABLE = 0 };
/**
* Proclaim a MMIO access
*
* \param _ACCESS_T integer type of access
* \param dst access destination
* \param v access value
* \param w 1: write access 0: read access
*/
template <typename _ACCESS_T>
inline void _access_verbosity(addr_t const dst, _ACCESS_T const v,
bool const w) const
{
if (!VERBOSITY_AVAILABLE) return;
if (!_write_verbose) return;
printf("mmio %s 0x%p: 0x", w ? "write" : "read ", (void *)dst);
Trait::Uint_type<_ACCESS_T>::print_hex(v);
printf("\n");
}
/**
* Write '_ACCESS_T' typed 'value' to MMIO base + 'o'
*/
template <typename _ACCESS_T>
inline void _write(off_t const o, _ACCESS_T const value)
{
addr_t const dst = (addr_t)base + o;
_access_verbosity<_ACCESS_T>(dst, value, 1);
*(_ACCESS_T volatile *)dst = value;
}
/**
* Read '_ACCESS_T' typed from MMIO base + 'o'
*/
template <typename _ACCESS_T>
inline _ACCESS_T _read(off_t const o) const
{
addr_t const dst = (addr_t)base + o;
_ACCESS_T const value = *(_ACCESS_T volatile *)dst;
_access_verbosity<_ACCESS_T>(dst, value, 0);
return value;
}
protected:
/**
* Write typed 'value' to MMIO base + 'o'
/*
* If VERBOSITY_AVAILABLE is set MMIO isn't verbose by default.
* Instead it causes this switches to be asked everytime MMIO
* could be verbose. This way the user can either enable verbosity
* locally by overwriting them in a deriving class or change their
* initialization temporarily to enable verbosity globally and
* then supress it locally by overwriting it.
*/
template <typename _ACCESS_T>
inline void _write(off_t const o, _ACCESS_T const value)
{ *(_ACCESS_T volatile *)((addr_t)base + o) = value; }
/**
* Read typed from MMIO base + 'o'
*/
template <typename _ACCESS_T>
inline _ACCESS_T _read(off_t const o) const
{ return *(_ACCESS_T volatile *)((addr_t)base + o); }
bool _write_verbose;
bool _read_verbose;
public:
@ -151,7 +197,7 @@ namespace Genode
struct Register_array : public Register<_OFFSET, _ACCESS_WIDTH,
_STRICT_WRITE>
{
typedef typename Trait::Uint_type<_ACCESS_WIDTH>::
typedef typename Trait::Uint_width<_ACCESS_WIDTH>::
template Divisor<_ITEM_WIDTH> Item;
enum {
@ -240,7 +286,8 @@ namespace Genode
*
* \param mmio_base base address of targeted MMIO region
*/
inline Mmio(addr_t mmio_base) : base(mmio_base) { }
inline Mmio(addr_t mmio_base)
: _write_verbose(0), _read_verbose(0), base(mmio_base) { }
/*************************

View File

@ -16,6 +16,7 @@
/* Genode includes */
#include <base/stdint.h>
#include <base/printf.h>
namespace Genode
{
@ -24,61 +25,76 @@ namespace Genode
/**
* Properties of integer types with a given bitwidth
*/
template <unsigned long _WIDTH> struct Uint_type;
template <unsigned long _WIDTH> struct Uint_width;
/***************************************************************
** Provide the integer type and the width as exponent to the **
** base of 2 for all supported widths in 'Uint_type' **
***************************************************************/
template <> struct Uint_type<1>
template <> struct Uint_width<1>
{
typedef bool Type;
enum { WIDTH_LOG2 = 0 };
/**
* Access widths, wich are dividers to the compound type width
* Access widths wich are dividers to the compound type width
*/
template <unsigned long _DIVISOR_WIDTH> struct Divisor;
static inline void print_hex(bool const v) {
printf("%01x", v); }
};
template <> struct Uint_type<8> : Uint_type<1>
template <> struct Uint_width<8> : Uint_width<1>
{
typedef uint8_t Type;
enum { WIDTH_LOG2 = 3 };
static inline void print_hex(uint8_t const v) {
printf("%02x", v); }
};
template <> struct Uint_type<16> : Uint_type<8>
template <> struct Uint_width<16> : Uint_width<8>
{
typedef uint16_t Type;
enum { WIDTH_LOG2 = 4 };
static inline void print_hex(uint16_t const v) {
printf("%04x", v); }
};
template <> struct Uint_type<32> : Uint_type<16>
template <> struct Uint_width<32> : Uint_width<16>
{
typedef uint32_t Type;
enum { WIDTH_LOG2 = 5 };
static inline void print_hex (uint32_t const v) {
printf("%08x", v); }
};
template <> struct Uint_type<64> : Uint_type<32>
template <> struct Uint_width<64> : Uint_width<32>
{
typedef uint64_t Type;
enum { WIDTH_LOG2 = 6 };
static inline void print_hex(uint64_t const v) {
printf("%016llx", v); }
};
template <> struct Uint_width<1>::Divisor<1> { enum { WIDTH_LOG2 = 0 }; };
template <> struct Uint_width<8>::Divisor<2> { enum { WIDTH_LOG2 = 1 }; };
template <> struct Uint_width<8>::Divisor<4> { enum { WIDTH_LOG2 = 2 }; };
template <> struct Uint_width<8>::Divisor<8> { enum { WIDTH_LOG2 = 3 }; };
template <> struct Uint_width<16>::Divisor<16> { enum { WIDTH_LOG2 = 4 }; };
template <> struct Uint_width<32>::Divisor<32> { enum { WIDTH_LOG2 = 5 }; };
template <> struct Uint_width<64>::Divisor<64> { enum { WIDTH_LOG2 = 6 }; };
/********************************************************************
** Provide widths as exponents to the base of 2 for all supported **
** access widths in 'Uint_type::Divisor' **
********************************************************************/
/**
* Reference 'Uint_width' through typenames
*/
template <typename _TYPE> struct Uint_type;
template <> struct Uint_type<1>::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 }; };
template <> struct Uint_type<bool> : Uint_width<1> { };
template <> struct Uint_type<uint8_t> : Uint_width<8> { };
template <> struct Uint_type<uint16_t> : Uint_width<16> { };
template <> struct Uint_type<uint32_t> : Uint_width<32> { };
template <> struct Uint_type<uint64_t> : Uint_width<64> { };
}
/**
@ -96,11 +112,10 @@ namespace Genode
{
enum {
ACCESS_WIDTH = _ACCESS_WIDTH,
ACCESS_WIDTH_LOG2 = Trait::Uint_type<ACCESS_WIDTH>::WIDTH_LOG2,
ACCESS_WIDTH_LOG2 = Trait::Uint_width<ACCESS_WIDTH>::WIDTH_LOG2,
};
typedef typename Trait::Uint_type<ACCESS_WIDTH>::Type access_t;
typedef typename Trait::Uint_width<ACCESS_WIDTH>::Type access_t;
/**
* A bitregion within a register