Create SCOM and ID SCOM register classes

SCOM and ID SCOM registers are specialized register that will exist
under the HardwareRegister abstract class.

Change-Id: I40c39536ca7321c9ef36347cef2320cf7fc4da49
Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
diff --git a/src/isolator/hei_isolator.cpp b/src/isolator/hei_isolator.cpp
index 0b3f88f..87eea30 100644
--- a/src/isolator/hei_isolator.cpp
+++ b/src/isolator/hei_isolator.cpp
@@ -1,6 +1,6 @@
 
 #include <isolator/hei_isolator.hpp>
-#include <register/hei_hardware_register.hpp>
+#include <register/hei_scom_register.hpp>
 #include <util/hei_flyweight.hpp>
 
 namespace libhei
@@ -15,7 +15,20 @@
     HEI_INF( "Isolator::initialize(%p,%lu,%d)", i_buffer, i_bufferSize,
              i_forceInit );
 
-    Flyweight<HardwareRegister>::getSingleton().get( HardwareRegister {} );
+    Flyweight<ScomRegister>   & sfw = Flyweight<ScomRegister>::getSingleton();
+    Flyweight<IdScomRegister> & ifw = Flyweight<IdScomRegister>::getSingleton();
+
+    sfw.get( ScomRegister { CHIP_TYPE_INVALID, REG_ID_INVALID,
+                            REG_INST_DEFAULT, REG_ACCESS_RW, 0x01234567 } );
+    sfw.get( ScomRegister { CHIP_TYPE_INVALID, REG_ID_INVALID,
+                            REG_INST_DEFAULT, REG_ACCESS_RW, 0x00112233 } );
+
+    ifw.get( IdScomRegister { CHIP_TYPE_INVALID, REG_ID_INVALID,
+                              REG_INST_DEFAULT, REG_ACCESS_RW,
+                              0x0123456789abcdef } );
+    ifw.get( IdScomRegister { CHIP_TYPE_INVALID, REG_ID_INVALID,
+                              REG_INST_DEFAULT, REG_ACCESS_RW,
+                              0x0011223344556677 } );
     // END temporary code
 
     return rc;
@@ -32,7 +45,8 @@
     // END temporary code
 
     // Remove all of the isolation objects stored in the flyweights.
-    Flyweight<HardwareRegister>::getSingleton().clear();
+    Flyweight<ScomRegister>::getSingleton().clear();
+    Flyweight<IdScomRegister>::getSingleton().clear();
 }
 
 ReturnCode Isolator::isolate( const std::vector<Chip> & i_chipList,
diff --git a/src/register/hei_hardware_register.cpp b/src/register/hei_hardware_register.cpp
index e007eca..0c1e871 100755
--- a/src/register/hei_hardware_register.cpp
+++ b/src/register/hei_hardware_register.cpp
@@ -51,9 +51,13 @@
 namespace libhei
 {
 
-#if 0
-// ---------------------------------------------------------------------
+//------------------------------------------------------------------------------
 
+HardwareRegister::~HardwareRegister() {}
+
+//------------------------------------------------------------------------------
+
+#if 0
 void HardwareRegister::SetBitString( const BitString *bs )
 {
     BitString & l_string  = AccessBitString();
diff --git a/src/register/hei_hardware_register.hpp b/src/register/hei_hardware_register.hpp
index 255cf5a..3d2f974 100755
--- a/src/register/hei_hardware_register.hpp
+++ b/src/register/hei_hardware_register.hpp
@@ -18,8 +18,8 @@
 {
 
 /**
- * @brief Stores information (e.g. address, type, length, etc.) for an actual
- *        hardware register.
+ * @brief An abstract class containing information (e.g. address, type, length,
+ *        etc.) for an actual hardware register.
  *
  * Hardware access:
  *
@@ -52,6 +52,69 @@
 {
   public:
 
+    /** @brief Pure virtual destructor. */
+    virtual ~HardwareRegister() = 0;
+
+  protected:
+
+    /**
+     * @brief Constructor from components.
+     * @param i_chipType    Type of chip associated with this register.
+     * @param i_id          Unique ID for this register.
+     * @param i_instance    Instance of this register
+     * @param i_accessLevel Hardware access level for this register.
+     */
+    HardwareRegister( ChipType_t i_chipType, RegisterId_t i_id,
+                      RegisterInstance_t i_instance,
+                      RegisterAccessLevel_t i_accessLevel ) :
+        Register(), iv_chipType( i_chipType ), iv_id( i_id ),
+        iv_instance( i_instance ), iv_accessLevel( i_accessLevel )
+    {}
+
+  private: // Instance variables
+
+    /** The type of chip associated with register. */
+    const ChipType_t iv_chipType;
+
+    /** The unique ID for this register. */
+    const RegisterId_t iv_id;
+
+    /** A register may have multiple instances. All of which will have the same
+     *  ID. This variable is used to distinguish between each instance of the
+     *  register. */
+    const RegisterInstance_t iv_instance;
+
+    /** The hardware access level of this register (read/write, read-only,
+     *  write-only, etc.). */
+    const RegisterAccessLevel_t iv_accessLevel;
+
+  public: // Accessor functions
+
+    /** @return The type of chip associated with this register. */
+    ChipType_t getChipType() const { return iv_chipType; }
+
+    /* @return The unique ID for this register. */
+    RegisterId_t getId() const { return iv_id; }
+
+    /* @return The instance of this register. */
+    RegisterInstance_t getInstance() const { return iv_instance; }
+
+    /** @return The hardware access level of this register. */
+    RegisterAccessLevel_t getAccessLevel() const { return iv_accessLevel; }
+
+    // NOTE: The following are determined by child classes.
+
+    /** @return This register's type. */
+    virtual RegisterType_t getRegisterType() const = 0;
+
+    /** @return The address of this register. */
+    virtual RegisterAddress_t getAddress() const = 0;
+
+    /** @return The size (in bytes) of this register. */
+    virtual size_t getSize() const = 0;
+
+  public:
+
 #if 0
     /**
      * @brief     constructor
diff --git a/src/register/hei_scom_register.hpp b/src/register/hei_scom_register.hpp
new file mode 100644
index 0000000..b781694
--- /dev/null
+++ b/src/register/hei_scom_register.hpp
@@ -0,0 +1,188 @@
+#pragma once
+
+#include <register/hei_hardware_register.hpp>
+
+namespace libhei
+{
+
+/**
+ * @brief A Power Systems SCOM register.
+ *
+ * Address width:   4 bytes
+ * Register width:  8 bytes
+ * Bit order:       Ascending (0-63 left to right)
+ */
+class ScomRegister : public HardwareRegister
+{
+  public: // Constructor, destructors, assignment, etc.
+
+    /**
+     * @brief Constructor from components.
+     * @param i_chipType    Type of chip associated with this register.
+     * @param i_id          Unique ID for this register.
+     * @param i_instance    Instance of this register
+     * @param i_accessLevel Hardware access level for this register.
+     * @param i_address     A 4-byte address for this SCOM register.
+     */
+    ScomRegister( ChipType_t i_chipType, RegisterId_t i_id,
+                  RegisterInstance_t i_instance,
+                  RegisterAccessLevel_t i_accessLevel, uint32_t i_address ) :
+        HardwareRegister( i_chipType, i_id, i_instance, i_accessLevel ),
+        iv_address( i_address )
+    {}
+
+    /** @brief Destructor. */
+    ~ScomRegister() = default;
+
+    /**
+     * @brief Copy constructor.
+     *
+     * Would prefer to delete this to prevent implicit copy assignments, but it
+     * is needed by the Flyweight class.
+     */
+    ScomRegister( const ScomRegister & ) = default;
+
+    /**
+     * @brief Explicitly disables assignment operator.
+     *
+     * This is redundant since the compilier will implicitly delete this because
+     * of the constant instance variables, but helps communicate it is not
+     * allowed.
+     */
+    ScomRegister & operator=( const ScomRegister & ) = delete;
+
+  public: // Accessor functions
+
+    /** Function overloaded from parent HardwareRegister class. */
+    RegisterType_t getRegisterType() const { return REG_TYPE_SCOM; }
+
+    /** Function overloaded from parent HardwareRegister class. */
+    RegisterAddress_t getAddress() const
+    {
+        return static_cast<RegisterAddress_t>( iv_address );
+    }
+
+    /** Function overloaded from parent HardwareRegister class. */
+    size_t getSize() const { return 8; }
+
+  public: // Operators
+
+    /** @brief Equals operator. */
+    bool operator==( const ScomRegister & i_r ) const
+    {
+        // Comparing address and chip type should be sufficient.
+        return ( getAddress()  == i_r.getAddress()  ) &&
+               ( getChipType() == i_r.getChipType() );
+    }
+
+    /** @brief Less than operator. */
+    bool operator<( const ScomRegister & i_r ) const
+    {
+        // Comparing address and chip type should be sufficient.
+        return (   getAddress()  <  i_r.getAddress()       ) ||
+               ( ( getAddress()  == i_r.getAddress()  ) &&
+                 ( getChipType() <  i_r.getChipType() )    );
+    }
+
+  private: // Instance variables
+
+    /** This register's address. */
+    const uint32_t iv_address;
+
+}; // end class ScomRegister
+
+/**
+ * @brief A Power Systems Indirect SCOM register.
+ *
+ * Address width:   8 bytes
+ * Register width:  2* bytes (see note below)
+ * Bit order:       Ascending (0-63 left to right)
+ *
+ * IMPORTANT NOTE:
+ *   Technically, only two bytes of data are actually used. However, the bit
+ *   definition of these registers put the two bytes at the end of the returned
+ *   value (bit 48-63). Therefore, this class will be made to look like the
+ *   width is 8 bytes in order to make the bit indexing work in the returned
+ *   BitString.
+ */
+class IdScomRegister : public HardwareRegister
+{
+  public: // Constructor, destructors, assignment, etc.
+
+    /**
+     * @brief Constructor from components.
+     * @param i_chipType    Type of chip associated with this register.
+     * @param i_id          Unique ID for this register.
+     * @param i_instance    Instance of this register
+     * @param i_accessLevel Hardware access level for this register.
+     * @param i_address     An 8-byte address for this Indirect SCOM register.
+     */
+    IdScomRegister( ChipType_t i_chipType, RegisterId_t i_id,
+                    RegisterInstance_t i_instance,
+                    RegisterAccessLevel_t i_accessLevel, uint64_t i_address ) :
+        HardwareRegister( i_chipType, i_id, i_instance, i_accessLevel ),
+        iv_address( i_address )
+    {}
+
+    /** @brief Destructor. */
+    ~IdScomRegister() = default;
+
+    /**
+     * @brief Copy constructor.
+     *
+     * Would prefer to delete this to prevent implicit copy assignments, but it
+     * is needed by the Flyweight class.
+     */
+    IdScomRegister( const IdScomRegister & ) = default;
+
+    /**
+     * @brief Explicitly disables assignment operator.
+     *
+     * This is redundant since the compilier will implicitly delete this because
+     * of the constant instance variables, but helps communicate it is not
+     * allowed.
+     */
+    IdScomRegister & operator=( const IdScomRegister & ) = delete;
+
+  public: // Accessor functions
+
+    /** Function overloaded from parent HardwareRegister class. */
+    RegisterType_t getRegisterType() const { return REG_TYPE_ID_SCOM; }
+
+    /** Function overloaded from parent HardwareRegister class. */
+    RegisterAddress_t getAddress() const
+    {
+        return static_cast<RegisterAddress_t>( iv_address );
+    }
+
+    /** Function overloaded from parent HardwareRegister class. */
+    size_t getSize() const { return 8; } // See note in class documentation.
+
+  public: // Operators
+
+    /** @brief Equals operator. */
+    bool operator==( const IdScomRegister & i_r ) const
+    {
+        // Comparing address and chip type should be sufficient.
+        return ( getAddress()  == i_r.getAddress()  ) &&
+               ( getChipType() == i_r.getChipType() );
+    }
+
+    /** @brief Less than operator. */
+    bool operator<( const IdScomRegister & i_r ) const
+    {
+        // Comparing address and chip type should be sufficient.
+        return (   getAddress()  <  i_r.getAddress()       ) ||
+               ( ( getAddress()  == i_r.getAddress()  ) &&
+                 ( getChipType() <  i_r.getChipType() )    );
+    }
+
+  private: // Instance variables
+
+    /** This register's address. */
+    const uint64_t iv_address;
+
+}; // end class IdScomRegister
+
+} // end namespace libhei
+