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.hpp b/src/register/hei_hardware_register.hpp
index 066f6db..7588a6c 100755
--- a/src/register/hei_hardware_register.hpp
+++ b/src/register/hei_hardware_register.hpp
@@ -17,13 +17,6 @@
namespace libhei
{
-#if 0
-// Forward References
-class CHIP_CLASS;
-class MopsRegisterAccess;
-class ExtensibleChip;
-#endif
-
/**
* @brief Stores information (e.g. address, type, length, etc.) for an actual
* hardware register.
@@ -40,6 +33,20 @@
* - Perform all necessary hardware accesses to that chip.
* - Call HardwareRegister::clearAccessor() to remove the chip access. This
* helps ensure we don't try to access the wrong chip.
+ *
+ * Register cache:
+ *
+ * In order to save memory space, each instance of this class does not store
+ * the contents of the target hardware register. Instead, that data is stored
+ * in a register cache, which a static variable defined in this class. This
+ * allows us to store only what we need. The cache can also be thought of as a
+ * snapshot of the registers at the time of isolation, which can be useful if
+ * the hardware is still running and register values could change.
+ *
+ * In order to ensure stale data isn't used from the cache, call
+ * HardwareRegister::flushAll() before beginning isolation on a new attention.
+ * Also, HardwareRegister::flushAll() should be called when the isolator is
+ * uninitialized before the rest of the isolation objects are deleted.
*/
class HardwareRegister : public Register
{
@@ -95,6 +102,7 @@
*/
uint32_t GetBitLength(void) const { return iv_bitLength ;}
#endif
+ size_t getByteSize() const { return 8; } // TODO
/**
* @brief Reads a register from hardware via the user interface APIs.
@@ -196,22 +204,6 @@
friend class CaptureData;
- /** @return TRUE if entry for this register exist in this cache. */
- bool queryCache() const;
-
- /**
- * @brief Reads register contents from cache.
- * @return Reference to bit string buffer maintained in cache.
- */
- BitString & readCache() const;
-
- /**
- * @brief Deletes one or all entry in the cache
- * @param RuleChip pointer associated with register
- * @return Nil
- */
- void flushCache( ExtensibleChip *i_pChip = nullptr ) const;
-
private: // Data
uint32_t iv_bitLength; // bit length of scom
@@ -305,6 +297,103 @@
return cv_accessor->getChip();
}
+
+ private: // Register cache class variable
+
+ /**
+ * @brief Caches the contents of registers read from hardware.
+ *
+ * The goal is to create a snapshot of the hardware register contents as
+ * close to the reported attention as possible. This snapshot is then used
+ * for additional analysis/debug when needed.
+ */
+ class Cache
+ {
+ public:
+
+ /** @brief Default constructor. */
+ Cache() = default;
+
+ /** @brief Destructor. */
+ ~Cache() = default;
+
+ /** @brief Copy constructor. */
+ Cache( const Cache & ) = delete;
+
+ /** @brief Assignment operator. */
+ Cache & operator=( const Cache & ) = delete;
+
+ /**
+ * @brief Queries if a specific entry exists in the cache.
+ * @param i_chip The target chip.
+ * @param i_hwReg The target register.
+ * @return True if the entry exists, false otherwise.
+ */
+ bool query( const Chip & i_chip,
+ const HardwareRegister * i_hwReg ) const;
+
+ /**
+ * @brief Returns the data buffer for the given chip and register.
+ * @param i_chip The target chip.
+ * @param i_hwReg The target register.
+ * @return A reference to the BitString containing the register data.
+ * @note If an entry does not exist in the cache, an entry will be
+ * created and the BitString will be initialized to 0.
+ */
+ BitString & access( const Chip & i_chip,
+ const HardwareRegister * i_hwReg );
+
+ /** @brief Flushes entire contents from cache. */
+ void flush();
+
+ /**
+ * @brief Removes a single register from the cache.
+ * @param i_chip The target chip.
+ * @param i_hwReg The target register.
+ */
+ void flush( const Chip & i_chip, const HardwareRegister * i_hwReg );
+
+ private:
+
+ /**
+ * @brief Stores a BitStringBuffer for each HardwareRegister per Chip.
+ *
+ * The HardwareRegister keys will just be pointers to the isolation
+ * objects created in the main initialize() API. Those should exist
+ * until the main uninitialize() API is called. It is important that the
+ * cache is flushed at the beginning of the uninitialize() API before
+ * the rest of the isolation objects are deleted.
+ *
+ * The Chip keys are copies of the objects passed to the isolator
+ * because the user application is responsible for storage of the
+ * objects passed to the isolator. We don't want to chance a Chip was
+ * created as a local variable that goes out of scope, or other similar
+ * situations.
+ */
+ std::map<Chip, std::map<const HardwareRegister*, BitString*>> iv_cache;
+ };
+
+ /** This allows all HardwareRegister objects access to the cache. */
+ static Cache cv_cache;
+
+ public: // Register cache management functions.
+
+ /** @brief Flushes the entire register cache. */
+ static void flushAll() { cv_cache.flush(); }
+
+ private: // Register cache management functions.
+
+ /** @return True if an entry for this register exist in this cache. */
+ bool queryCache() const
+ {
+ return cv_cache.query( getAccessorChip(), this );
+ }
+
+ /** @return A reference to this register's BitString in cache. */
+ BitString & accessCache() const
+ {
+ return cv_cache.access( getAccessorChip(), this );
+ }
};
} // end namespace libhei