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 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: 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> bool _write_verbose;
inline void _write(off_t const o, _ACCESS_T const value) bool _read_verbose;
{ *(_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); }
public: public:
@ -151,7 +197,7 @@ namespace Genode
struct Register_array : public Register<_OFFSET, _ACCESS_WIDTH, struct Register_array : public Register<_OFFSET, _ACCESS_WIDTH,
_STRICT_WRITE> _STRICT_WRITE>
{ {
typedef typename Trait::Uint_type<_ACCESS_WIDTH>:: typedef typename Trait::Uint_width<_ACCESS_WIDTH>::
template Divisor<_ITEM_WIDTH> Item; template Divisor<_ITEM_WIDTH> Item;
enum { enum {
@ -240,7 +286,8 @@ namespace Genode
* *
* \param mmio_base base address of targeted MMIO region * \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 */ /* Genode includes */
#include <base/stdint.h> #include <base/stdint.h>
#include <base/printf.h>
namespace Genode namespace Genode
{ {
@ -24,61 +25,76 @@ namespace Genode
/** /**
* Properties of integer types with a given bitwidth * Properties of integer types with a given bitwidth
*/ */
template <unsigned long _WIDTH> struct Uint_type; template <unsigned long _WIDTH> struct Uint_width;
/*************************************************************** template <> struct Uint_width<1>
** 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>
{ {
typedef bool Type; typedef bool Type;
enum { WIDTH_LOG2 = 0 }; 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; 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; typedef uint8_t Type;
enum { WIDTH_LOG2 = 3 }; 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; typedef uint16_t Type;
enum { WIDTH_LOG2 = 4 }; 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; typedef uint32_t Type;
enum { WIDTH_LOG2 = 5 }; 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; typedef uint64_t Type;
enum { WIDTH_LOG2 = 6 }; 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 ** * Reference 'Uint_width' through typenames
** access widths in 'Uint_type::Divisor' ** */
********************************************************************/ template <typename _TYPE> struct Uint_type;
template <> struct Uint_type<1>::Divisor<1> { enum { WIDTH_LOG2 = 0 }; }; template <> struct Uint_type<bool> : Uint_width<1> { };
template <> struct Uint_type<8>::Divisor<2> { enum { WIDTH_LOG2 = 1 }; }; template <> struct Uint_type<uint8_t> : Uint_width<8> { };
template <> struct Uint_type<8>::Divisor<4> { enum { WIDTH_LOG2 = 2 }; }; template <> struct Uint_type<uint16_t> : Uint_width<16> { };
template <> struct Uint_type<8>::Divisor<8> { enum { WIDTH_LOG2 = 3 }; }; template <> struct Uint_type<uint32_t> : Uint_width<32> { };
template <> struct Uint_type<16>::Divisor<16> { enum { WIDTH_LOG2 = 4 }; }; template <> struct Uint_type<uint64_t> : Uint_width<64> { };
template <> struct Uint_type<32>::Divisor<32> { enum { WIDTH_LOG2 = 5 }; };
template <> struct Uint_type<64>::Divisor<64> { enum { WIDTH_LOG2 = 6 }; };
} }
/** /**
@ -96,11 +112,10 @@ namespace Genode
{ {
enum { enum {
ACCESS_WIDTH = _ACCESS_WIDTH, ACCESS_WIDTH = _ACCESS_WIDTH,
ACCESS_WIDTH_LOG2 = Trait::Uint_width<ACCESS_WIDTH>::WIDTH_LOG2,
ACCESS_WIDTH_LOG2 = Trait::Uint_type<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 * A bitregion within a register