Skip to content

lethalbit/wegistew-cc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 

Repository files navigation

wegistew - Compile-time register grokking

wegistew is a single C++ header that allows for you to interact with hardware registers on embedded platforms in a near zero-cost way.

With wegistew, everything but the actual register access is done in the type system at compile time, meaning that only the actual calls to get or set the register are actually generated as machine code, the rest of it is seamlessly optimized away.

Installing

Because wegistew is a single header library, to install it you can either just download a copy and drop it in your source tree.

Alternatively use it as a meson subproject, it exports a wegistew_dep dependency you can just plop into your target.

Lastly, you can install it system-wide by using meson:

meson build
ninja -C build install

The default location is /usr/local/include but this can be changed by setting the environment variable DESTDIR to the prefix prior to running the ninja -C build install command.

Examples

The following examples so some uses for wegistew.

All of which are on compiler explorer (https://godbolt.org/z/8EbfeGcxh) for you to play with.

Defining a Register

To define a register with wegistew, you simply define a wegistew_t type templated with the register intrinsic, the address, and the fields for the register.

#include <wegistew.hh>

using wegistew::wegistew_t;
using wegistew::bit_t;
using wegistew::bitspan_t;

using par_el1 = wegistew_t<
	/* Register base type, dictates width */
	std::uint64_t,
	/* Register address */
	0xFEEDACA7DEADBEEF,
	/* Register fields */
	bit_t<0>,
	bitspan_t<1, 6>,
	bitspan_t<7, 8>,
	bit_t<9>,
	bit_t<10>,
	bit_t<22>,
	bitspan_t<12, 47>,
	bitspan_t<48, 51>,
	bitspan_t<52, 55>,
	bitspan_t<56, 63>
>;

There are two types you can use as a field in wegistew, the first is a bitspan_t<lsb, msb> which takes the start and stop bit indices, the second is a bit_t<idx> which takes a single offset into the register.

The bit_t<idx> type is just a type alias for bitspan_t<idx, idx>, which is a bit span with the the start and stop bits set to be identical.

Accessing Fields

To access a field of a register, you have two options, access it via the type system, or access it via an object instance.

To get / set a field without an instance of the register one would do the following:

/* Get the contents of the 6th field of the register */
auto pa = par_el1::field<6>::get();

/* Set the contents of the 3rd field of the register */
par_el1::field<3>::set(0b10);

To do the same, but with an instance of the register one would do the following:

/* Create an instance of the register */
auto reg = par_el1{};

/* Get the contents of the 6th field of the register */
auto pa = reg.get<6>();

/* Set the contents of the 3rd field of the register */
reg.set<3>(0b10);

Tips and Tricks

Here are some tips and tricks that you can use to make working with wegistew easier.

Field Naming

Rather than defining a constant to name your register fields for access, simply create a new type with the name of that field.

/* Alias the type */
using attr = typename par_el1::field<9>;

/* Do things with it */
auto current_attr = attr::get();
attr::set(0b11110000);

Use an Enum to name Values

You can use an enum class to define named values for passing to set and retrieving from get.

/* Let's alias the field for ease of use */
using sh = typename par_el1::field<3>;

/* Define named values */
enum class shareability : std::uint8_t {
	non_shareable   = 0b00,
	outer_shareable = 0b10,
	inner_shareable = 0b01,
};
/* Set it! */
sh::set(shareability::outer_shareable);

License

wegistew is licensed under the BSD-3-Clause and can be found in LICENSE.

About

Compile-time register grokking

Resources

License

Stars

Watchers

Forks

Contributors 2

  •  
  •