Boost logo

Boost :

Subject: [boost] Interest in hardware abstraction layer library
From: Szymon Gutaj (gutajszymon_at_[hidden])
Date: 2011-12-01 06:31:42


Hi Everyone,

please share your comments/interest in a library that would ease writing
hardware abstraction layers (HAL's) for complex devices (like large
ASIC/FPGA).

Here's the description:

1. Let's assume that we've got a memory mapped IO device, controlled via
its registers. Each register is divided into few bitfields. Each bitfield
controls separate functionality and has its properties, like:
read/write/special access, numeral/enumerated value type, value
signedness, valid value range(s) etc.

All these are typically listed in device's specification:

+----------------+--------------+
|Register offset |Register name |
+----------------+--------------+
|0x12FE |CONTROL_REG1 |
+----------------+--------------+

+--------------+--------------+-------+-----------+------------+
|Bits occupied |Bitfield name |Access |Signedness |Value range |
+--------------+--------------+-------+-----------+------------+
|31:25 |TEMPERATURE |RA |SIGNED |- |
+--------------+--------------+-------+-----------+------------+
|24:1 |FAN_RPM |WA |UNSIGNED |0:6000 |
+--------------+--------------+-------+-----------+------------+
|0:0 |ENABLE |RWA |UNSIGNED |0:1 |
+--------------+--------------+-------+-----------+------------+

Note: RA: Read Access, WA: Write Access, RWA: Read/Write Access

2. Let's assume that there's a whole family of these ASICs (subsequent
generations/revisions). Each new revision differs from previous one only
in few details. The point is that we may have few thousand bitfields per
ASIC plus revision changes. Coding such amount of information "by hand" is
obviously error-prone. Using text processing (perl/python) to translate
the specification to code may obfuscate it's nice tabular format (and may
miss features/optimisation offered by metaprogramming).

3. Our goal is to create an abstract interface (HAL). Its implementations
would "talk to" corresponding bitfields via inner (intermediate) interface.

The purpose of that intermediate code would be to:
- present bitfield's name exactly "as is in specification",
- extract bitfield's value from its register in a typed, endiannes-correct
manner,
- enforce correct usage (like forbidding writing read-only fields),
- provide value validation,
- provide value conversion (enumeration-to-numeral etc.),
- provide array-style access if needed,
- provide debugging features,
- and few more cherries on top.

The key point is to have most of this code generated from the
specification using only simple regexp (to the form required by proposed
library).

4. Code snippet (using specification from point 1) - simple and simplified:

Let's create an interface with one member function "operate".
Implementation of this function will "talk to" bitfields of CONTROL_REG1
through get<BITFIELD> and set<BITFIELD> functions. These functions (and
few other utilities) are being generated by the proposed library, using
provided metadata.

// Definition of HAL interface ---------------------------

namespace some_subsystem { namespace driver {

class some_controller
{
public:
     virtual bool operate() = 0;
};

}}

// Definition of bitfields (metadata) --------------------

// Concrete device definition enclosed in a dedicated namespace

namespace some_subsystem { namespace driver { namespace asic_ver_123 {

// Legend:
// BOOST_HAL_DEF_REGISTER_BEG(REGISTER_OFFSET, REGISTER_NAME)
// BOOST_HAL_DEF_FIELD(MSBIT, LSBIT, BITFIELD_NAME, ACCESS,
SIGNEDNESS, VALIDATOR)
// BOOST_HAL_DEF_REGISTER_END()

BOOST_HAL_DEF_REGISTER_BEG(0x12FE, CONTROL_REG1) // Register definition
     BOOST_HAL_DEF_FIELD(30, 25, TEMPERATURE, RA, SIGNED,
CTP_ESC(no_check)) // CTP_ESC meant for commas escaping
     BOOST_HAL_DEF_FIELD(24, 1, FAN_RPM, WA, UNSIGNED, CTP_ESC(range<0,
6000>))
     BOOST_HAL_DEF_FIELD(0, 0, ENABLE, WA, UNSIGNED, CTP_ESC(range<0, 1>))
BOOST_HAL_DEF_REGISTER_END()

}}}

// Definition of HAL implementation ----------------------
namespace some_subsystem { namespace driver { namespace asic_ver_123 {

class some_controller_impl :
     public some_controller
{
public:
     virtual bool operate()
     {
        bool result = false;

         // Suitable bitfield type is deduced from its definition (but can
be manually overridden)
         // In this case it will be signed char or bigger
(CONTROL_REG1::TEMPERATURE = 6 bits)
         suitable<CONTROL_REG1::TEMPERATURE>::type temperature = 0;

         // Library automatically generates the bitfield's getter
         // which reads the register, masks & shifts unrelated bits,
         // performs (optional) value conversion and (mandatory) cast.
         // Debugging/logging also possible

         result = get<CONTROL_REG1::TEMPERATURE>(temperature); // Pass
"temperature" by reference

         // This would not compile, CONTROL_REG1::TEMPERATURE is read-only
         // result |= set<CONTROL_REG1::TEMPERATURE>(temperature); //
Compile error

         if(true == result && temperature > 20)
         {
             // Library automatically generates the bitfield's setter
             // which performs read-modify-write with value validation

             result |= set<CONTROL_REG1::FAN_RPM>(1000);
             result |= set<CONTROL_REG1::ENABLE>(true);

             // This would return "false" (7000 is an invalid value for
FAN_RPM)
             // result |= set<CONTROL_REG1::FAN_RPM>(7000);
         }
         else
         {
             result |= set<CONTROL_REG1::FAN_RPM>(0);
             result |= set<CONTROL_REG1::ENABLE>(false);
         }

         return result;
     }
};

}}}

// End of snippet ----------------------------------------------

This snippet shows the very basic functionality, anyway please share your
opinions if the idea is catchy and suitable for boost!

Best regards,

--
Szymon Gutaj

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk