mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
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:
parent
e23f24505b
commit
0c7c285079
@ -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) { }
|
||||
|
||||
|
||||
/*************************
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user