Add register cache support in HardwareRegister class

Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: Ic671a099fdcd98d1f0158289ef321b968f1908ca
diff --git a/src/register/hei_hardware_register.cpp b/src/register/hei_hardware_register.cpp
index 5663f3b..58106bf 100755
--- a/src/register/hei_hardware_register.cpp
+++ b/src/register/hei_hardware_register.cpp
@@ -18,7 +18,6 @@
 #include <iipchip.h>
 #include <prdfMain.H>
 #include <prdfRasServices.H>
-#include <prdfRegisterCache.H>
 #include <prdfPlatServices.H>
 #include <prdfExtensibleChip.H>
 
@@ -69,14 +68,16 @@
     // Calling Read() will ensure that an entry exists in the cache and the
     // entry has at been synched with hardware at least once. Note that we
     // cannot read hardware for write-only registers. In this case, an entry
-    // will be created in the cache, if it does not exist, when readCache() is
-    // called below.
+    // will be created in the cache, if it does not exist, when the cache is
+    // read below.
+
     if ( ( ACCESS_NONE != iv_operationType ) &&
-            ( ACCESS_WO != iv_operationType ) )
+         ( ACCESS_WO   != iv_operationType ) )
     {
         Read();
     }
-    return &(readCache());
+
+    return &( accessCache() );
 }
 
 //------------------------------------------------------------------------------
@@ -86,15 +87,16 @@
     // Calling Read() will ensure that an entry exists in the cache and the
     // entry has at been synched with hardware at least once. Note that we
     // cannot read hardware for write-only registers. In this case, an entry
-    // will be created in the cache, if it does not exist, when readCache() is
-    // called below.
+    // will be created in the cache, if it does not exist, when the cache is
+    // read below.
+
     if ( ( ACCESS_NONE != iv_operationType ) &&
-            ( ACCESS_WO != iv_operationType ) )
+         ( ACCESS_WO   != iv_operationType ) )
     {
         Read();
     }
 
-    return readCache();
+    return accessCache();
 }
 #endif
 
@@ -104,17 +106,17 @@
 {
     ReturnCode rc;
 
-#if 0
     // Read from hardware only if the read is forced or the entry for this
     // instance does not exist in the cache.
     if ( i_force || !queryCache() )
     {
+#if 0
         // This register must be readable.
         HEI_ASSERT( ( ACCESS_NONE != iv_operationType ) &&
                     ( ACCESS_WO   != iv_operationType ) );
 
         // Get the buffer from the register cache.
-        BitString & bs = readCache();
+        BitString & bs = accessCache();
 
         // Get the byte size of the buffer.
         size_t sz_buffer = BitString::getMinBytes( bs.getBitLen() );
@@ -122,20 +124,22 @@
         // Read this register from hardware.
         rc = registerRead( getAccessorChip().getChip(), bs.getBufAddr(),
                            sz_buffer, getRegisterType(), getAddress() );
+#endif
         if ( RC_SUCCESS != rc )
         {
             // The read failed and we can't trust what was put in the register
             // cache. So remove this instance's entry from the cache.
-            flushCache( getAccessorChip() );
+            cv_cache.flush( getAccessorChip(), this );
         }
+#if 0
         else
         {
             // Sanity check. The returned size of the data written to the buffer
             // should match the register size.
             HEI_ASSERT( getSize() == sz_buffer );
         }
-    }
 #endif
+    }
 
     return rc;
 }
@@ -157,7 +161,7 @@
     HEI_ASSERT( queryCache() );
 
     // Get the buffer from the register cache.
-    BitString & bs = readCache();
+    BitString & bs = accessCache();
 
     // Get the byte size of the buffer.
     size_t sz_buffer = BitString::getMinBytes( bs.getBitLen() );
@@ -182,38 +186,6 @@
 #if 0
 //------------------------------------------------------------------------------
 
-bool HardwareRegister::queryCache() const
-{
-    RegDataCache & cache = RegDataCache::getCachedRegisters();
-    BitString * bs = cache.queryCache( getAccessorChip(), this );
-    return ( nullptr != bs );
-}
-
-//------------------------------------------------------------------------------
-
-BitString & HardwareRegister::readCache() const
-{
-    RegDataCache & cache = RegDataCache::getCachedRegisters();
-    return cache.read( getAccessorChip(), this );
-}
-
-//------------------------------------------------------------------------------
-
-void HardwareRegister::flushCache( ExtensibleChip *i_pChip ) const
-{
-     RegDataCache & regDump = RegDataCache::getCachedRegisters();
-    if( nullptr == i_pChip )
-    {
-        regDump.flush();
-    }
-    else
-    {
-        regDump.flush( i_pChip ,this );
-    }
-}
-
-//-----------------------------------------------------------------------------
-
 bool HardwareRegister::operator == ( const HardwareRegister & i_rightRegister ) const
 {
     if( iv_scomAddress == i_rightRegister.GetAddress() )
@@ -254,5 +226,95 @@
 
 //------------------------------------------------------------------------------
 
+HardwareRegister::Cache HardwareRegister::cv_cache {};
+
+//------------------------------------------------------------------------------
+
+bool HardwareRegister::Cache::query( const Chip & i_chip,
+                                     const HardwareRegister * i_hwReg ) const
+{
+    // Does i_chip exist in the cache?
+    auto chipPairItr = iv_cache.find( i_chip );
+    if ( iv_cache.end() != chipPairItr )
+    {
+        auto & hwRegMap = chipPairItr->second; // for ease of use
+
+        // Does i_hwReg exist in the cache?
+        auto hwRegPairItr = hwRegMap.find( i_hwReg );
+        if ( hwRegMap.end() != hwRegPairItr )
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+//------------------------------------------------------------------------------
+
+BitString & HardwareRegister::Cache::access( const Chip & i_chip,
+                                             const HardwareRegister * i_hwReg )
+{
+    // If the entry does not exist, create a new entry.
+    if ( !query(i_chip, i_hwReg) )
+    {
+        BitString * bs = new BitStringBuffer { i_hwReg->getByteSize() * 8 };
+        iv_cache[i_chip][i_hwReg] = bs;
+    }
+
+    // Return a reference to the target entry.
+    return *(iv_cache[i_chip][i_hwReg]);
+}
+
+//------------------------------------------------------------------------------
+
+void HardwareRegister::Cache::flush()
+{
+    // Delete all of the BitStrings.
+    for ( auto & chipPair : iv_cache )
+    {
+        for ( auto & hwRegPair : chipPair.second )
+        {
+            delete hwRegPair.second;
+        }
+    }
+
+    // !!! Do not delete the HardwareRegisters !!!
+    // Those are deleted when the main uninitialize() API is called.
+
+    // Flush the rest of the cache.
+    iv_cache.clear();
+}
+
+//------------------------------------------------------------------------------
+
+void HardwareRegister::Cache::flush( const Chip & i_chip,
+                                     const HardwareRegister * i_hwReg )
+{
+    // Does i_chip exist in the cache?
+    auto chipPairItr = iv_cache.find( i_chip );
+    if ( iv_cache.end() != chipPairItr )
+    {
+        auto & hwRegMap = chipPairItr->second; // for ease of use
+
+        // Does i_hwReg exist in the cache?
+        auto hwRegPairItr = hwRegMap.find( i_hwReg );
+        if ( hwRegMap.end() != hwRegPairItr )
+        {
+            delete hwRegPairItr->second; // delete the BitString
+            hwRegMap.erase(i_hwReg);     // remove the entry for this register
+        }
+
+        // If i_hwReg was the only entry for i_chip, we can remove i_chip from
+        // the cache.
+        if ( hwRegMap.empty() )
+        {
+            iv_cache.erase(i_chip);
+        }
+    }
+}
+
+//------------------------------------------------------------------------------
+
 } // end namespace libhei