Add register dump to isolation data

Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: I02dc9ff21e538a8d6d66663bc0ecd07362a5332b
diff --git a/src/hei_isolation_data.hpp b/src/hei_isolation_data.hpp
index 93ec5b8..65cf37b 100644
--- a/src/hei_isolation_data.hpp
+++ b/src/hei_isolation_data.hpp
@@ -1,7 +1,10 @@
 #pragma once
 
+#include <hei_bit_string.hpp>
 #include <hei_signature.hpp>
 
+#include <map>
+#include <memory>
 #include <vector>
 
 namespace libhei
@@ -28,11 +31,32 @@
     /** @brief Assignment operator. */
     IsolationData& operator=(const IsolationData&) = default;
 
+  public:
+    /** The data stored in each entry of the register dump. */
+    struct RegDumpEntry
+    {
+        RegDumpEntry(RegisterId_t i_regId, Instance_t i_regInst,
+                     std::shared_ptr<BitStringBuffer> i_data) :
+            regId(i_regId),
+            regInst(i_regInst), data(i_data)
+        {}
+
+        RegisterId_t regId;                    ///< 3-byte register ID
+        Instance_t regInst;                    ///< 1-byte register instance
+        std::shared_ptr<BitStringBuffer> data; ///< register data
+    };
+
   private: // Instance variables
     /** A list of all signatures found during isolation. */
     std::vector<Signature> iv_sigLists;
 
-    // TODO: add register dump.
+    /**
+     * This intended to be a snapshot of the register values read from hardware
+     * as the isolator iterates the isolation tree. Therefore, it cannot share
+     * the values stored in the hardware register cache. Instead, it must be a
+     * copy of the data.
+     */
+    std::map<Chip, std::vector<RegDumpEntry>> iv_regDump;
 
   public: // Member functions
     /**
@@ -44,16 +68,46 @@
         iv_sigLists.push_back(i_signature);
     }
 
+    /**
+     * @brief Adds the contents of a register to the register dump.
+     * @param i_chip    The chip associated with this register.
+     * @param i_regId   The register ID.
+     * @param i_regInst The register instance.
+     * @param i_data    A BitString containing the contents of the register.
+     *                  Note that this function will make a copy of the data,
+     *                  which will be stored separately from the hardware
+     *                  register cache.
+     */
+    void addRegister(const Chip& i_chip, RegisterId_t i_regId,
+                     Instance_t i_regInst, const BitString* i_data)
+    {
+        if (!i_data->isZero()) // Only add non-zero values to save space.
+        {
+            // Make a copy of the register value.
+            auto data = std::make_shared<BitStringBuffer>(*i_data);
+
+            // Add to the list.
+            iv_regDump[i_chip].emplace_back(i_regId, i_regInst, data);
+        }
+    }
+
     /** @brief Allows access to the signature list. */
     const std::vector<Signature>& getSignatureList() const
     {
         return iv_sigLists;
     }
 
+    /** @brief Allows access to the register dump. */
+    const std::map<Chip, std::vector<RegDumpEntry>>& getRegisterDump() const
+    {
+        return iv_regDump;
+    }
+
     /** @brief Flushes the data to ensure a clean slate for isolation. */
     void flush()
     {
         iv_sigLists.clear();
+        iv_regDump.clear();
     }
 
 }; // end class IsolationData
diff --git a/src/isolator/hei_isolation_node.cpp b/src/isolator/hei_isolation_node.cpp
index 15bf5cf..51e3ee0 100644
--- a/src/isolator/hei_isolation_node.cpp
+++ b/src/isolator/hei_isolation_node.cpp
@@ -20,6 +20,7 @@
         // Read the register (adds BitString to register cache).
         if (hwReg->read(i_chip))
         {
+            // The register read failed.
             // TODO: Would be nice to add SCOM errors to the log just in case
             //       traces are not available.
             // TODO: This trace could be redundant with the user application,
@@ -30,13 +31,12 @@
             //         "address=0x%0" PRIx64,
             //         i_chip.getType(), hwReg->getAddress());
         }
-
-        // TODO: Add this register to io_isoData.
-        // TODO: getBitString() does read hardware if read() has not been called
-        //       and there is nothing in the register cache. However, it does
-        //       not does not indicate if the read was successful. Not sure if
-        //       this is intentional. Will need to investigate.
-        // auto bs = hwReg->getBitString();
+        else
+        {
+            // Add to the FFDC.
+            io_isoData.addRegister(i_chip, hwReg->getId(), hwReg->getInstance(),
+                                   hwReg->getBitString(i_chip));
+        }
     }
 
     // A rule for i_attnType must exist.
diff --git a/test/simulator/simulator.cpp b/test/simulator/simulator.cpp
index e9bd2aa..32eb31b 100644
--- a/test/simulator/simulator.cpp
+++ b/test/simulator/simulator.cpp
@@ -1,5 +1,7 @@
 #include "simulator.hpp"
 
+#include <util/hei_includes.hpp>
+
 #include <fstream> // std::ifstream
 
 namespace libhei
@@ -77,6 +79,20 @@
     IsolationData isoData{};
     isolate(iv_chipList, isoData);
 
+    /* TODO: Currently used for debug. Eventually, we want this and the
+     *       signature list written to file.
+    for (const auto& e : isoData.getRegisterDump())
+    {
+        HEI_INF("Chip: %s", (const char*)e.first.getChip());
+
+        for (const auto& r : e.second)
+        {
+            HEI_INF("  Reg: 0x%06x  %d  0x%016" PRIx64, r.regId, r.regInst,
+                    r.data->getFieldRight(0, 64));
+        }
+    }
+    */
+
     // Get the list of signatures found in isolation.
     std::vector<Signature> givenSigList = isoData.getSignatureList();