Initial support to parse a Chip Data File

Change-Id: Ib5a7d8344922f8288c23f5bedd304e282dcfaada
Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
diff --git a/meson.build b/meson.build
index db4e378..9453bbc 100644
--- a/meson.build
+++ b/meson.build
@@ -9,10 +9,14 @@
 
 incdir = include_directories('src')
 
-libhei_src = ['src/isolator/hei_isolator.cpp',
-              'src/isolator/hei_isolation_node.cpp',
-              'src/register/hei_hardware_register.cpp',
-              'src/util/hei_bit_string.cpp']
+libhei_src = [
+    'src/chip_data/hei_chip_data.cpp',
+    'src/isolator/hei_isolator.cpp',
+    'src/isolator/hei_isolation_chip.cpp',
+    'src/isolator/hei_isolation_node.cpp',
+    'src/register/hei_hardware_register.cpp',
+    'src/util/hei_bit_string.cpp',
+]
 
 libhei_dep = declare_dependency(include_directories : incdir,
                                 sources : libhei_src)
diff --git a/src/chip_data/hei_chip_data.cpp b/src/chip_data/hei_chip_data.cpp
new file mode 100644
index 0000000..f10589d
--- /dev/null
+++ b/src/chip_data/hei_chip_data.cpp
@@ -0,0 +1,54 @@
+#include <chip_data/hei_chip_data.hpp>
+#include <chip_data/hei_chip_data_stream.hpp>
+
+namespace libhei
+{
+
+//------------------------------------------------------------------------------
+
+using FileKeyword_t = uint64_t;
+
+constexpr FileKeyword_t KW_CHIPDATA = 0x4348495044415441; // "CHIPDATA" ASCII
+
+using SectionKeyword_t = uint32_t;
+
+constexpr SectionKeyword_t KW_REGS = 0x43484950; // "REGS" ASCII
+constexpr SectionKeyword_t KW_NODE = 0x4e4f4445; // "NODE" ASCII
+constexpr SectionKeyword_t KW_ROOT = 0x524f4f54; // "ROOT" ASCII
+
+using Version_t = uint8_t;
+
+constexpr Version_t VERSION_1 = 0x01;
+
+//------------------------------------------------------------------------------
+
+void parseChipDataFile(void* i_buffer, size_t i_bufferSize,
+                       IsolationChipMap& io_isoChips)
+{
+    ChipDataStream stream{i_buffer, i_bufferSize};
+
+    // Read the file metadata.
+    FileKeyword_t file_kw = 0;
+    ChipType_t chipType   = 0;
+    Version_t version     = 0;
+    stream >> file_kw >> chipType >> version;
+
+    // Check the file ID.
+    HEI_ASSERT(KW_CHIPDATA == file_kw);
+
+    // This chip type should not already exist.
+    HEI_ASSERT(io_isoChips.end() == io_isoChips.find(chipType));
+
+    // Allocate memory for the new isolation chip.
+    auto isoChip = std::make_unique<IsolationChip>(chipType);
+
+    // TODO
+
+    // Add this isolation chip to the collective list of isolation chips.
+    auto ret = io_isoChips.emplace(chipType, std::move(isoChip));
+    HEI_ASSERT(ret.second); // Just in case.
+}
+
+//------------------------------------------------------------------------------
+
+} // namespace libhei
diff --git a/src/chip_data/hei_chip_data.hpp b/src/chip_data/hei_chip_data.hpp
index 26cfb75..f35cdc1 100644
--- a/src/chip_data/hei_chip_data.hpp
+++ b/src/chip_data/hei_chip_data.hpp
@@ -1,6 +1,25 @@
 #pragma once
 
-#include <hei_includes.hpp>
+#include <isolator/hei_isolation_chip.hpp>
 
 namespace libhei
-{} // end namespace libhei
+{
+
+/**
+ * @brief Parses a buffer containing a Chip Data File and builds the necessary
+ *        objects.
+ *
+ * This function will assert:
+ *   - The buffer is a properly formated Chip Data File and contains valid data.
+ *   - An IsolationChip object has not already been created for the chip type
+ *     associated with the given buffer.
+ *
+ * @param i_buffer     First address of the Chip Data File buffer.
+ * @param i_bufferSize Size of the Chip Data File buffer.
+ * @param io_isoChips  This map will contain all current IsolationChip objects
+ *                     for each of the user applications chip types.
+ */
+void parseChipDataFile(void* i_buffer, size_t i_bufferSize,
+                       IsolationChipMap& io_isoChips);
+
+} // end namespace libhei
diff --git a/src/hei_includes.hpp b/src/hei_includes.hpp
index 40bdfc7..71abb4c 100644
--- a/src/hei_includes.hpp
+++ b/src/hei_includes.hpp
@@ -12,6 +12,7 @@
 #include <stdlib.h>
 
 #include <map>
+#include <memory>
 #include <vector>
 
 // Library includes
diff --git a/src/isolator/hei_isolation_chip.hpp b/src/isolator/hei_isolation_chip.hpp
index 6930955..d4acddf 100644
--- a/src/isolator/hei_isolation_chip.hpp
+++ b/src/isolator/hei_isolation_chip.hpp
@@ -30,10 +30,8 @@
 class IsolationChip
 {
   public: // Constructors, destructor, assignment
-    /** @brief Default constructor. */
-    IsolationChip(ChipType_t i_chipType, const RootNodeMap& i_rootNodes) :
-        iv_chipType(i_chipType), iv_rootNodes(i_rootNodes)
-    {}
+    /** @brief Constructor. */
+    explicit IsolationChip(ChipType_t i_chipType) : iv_chipType(i_chipType) {}
 
     /** @brief Destructor. */
     ~IsolationChip() = default;
@@ -49,7 +47,7 @@
     const ChipType_t iv_chipType;
 
     /** Root nodes for this chip type. */
-    const RootNodeMap iv_rootNodes;
+    RootNodeMap iv_rootNodes;
 
   public: // Member functions
     /**
@@ -68,6 +66,22 @@
     {
         return iv_chipType;
     }
+
+    /**
+     * @brief Adds a root node to this chip.
+     * @param i_attnType The target attention type. Will assert this type does
+     *                   not already exist in iv_rootNodes.
+     * @param i_node     The target isolation node for this attention type.
+     */
+    void addRootNode(AttentionType_t i_attnType, IsolationNodePtr i_node)
+    {
+        auto ret = iv_rootNodes.emplace(i_attnType, i_node);
+        HEI_ASSERT(ret.second); // Should have not already existed.
+    }
 };
 
+/** A simple map to ensure only one IsolationChip exists per chip type. */
+using IsolationChipMap =
+    std::map<ChipType_t, const std::unique_ptr<const IsolationChip>>;
+
 } // end namespace libhei
diff --git a/src/isolator/hei_isolation_node.hpp b/src/isolator/hei_isolation_node.hpp
index 90aaeb4..eedde91 100644
--- a/src/isolator/hei_isolation_node.hpp
+++ b/src/isolator/hei_isolation_node.hpp
@@ -181,7 +181,10 @@
     }
 };
 
+/** Pointer management for isolation nodes. */
+using IsolationNodePtr = std::shared_ptr<IsolationNode>;
+
 /** Simple map to ensure only one root IsolationNode per attention type. */
-using RootNodeMap = std::map<AttentionType_t, const IsolationNode*>;
+using RootNodeMap = std::map<AttentionType_t, const IsolationNodePtr>;
 
 } // end namespace libhei
diff --git a/src/isolator/hei_isolator.cpp b/src/isolator/hei_isolator.cpp
index dc4d09b..db5668e 100644
--- a/src/isolator/hei_isolator.cpp
+++ b/src/isolator/hei_isolator.cpp
@@ -2,14 +2,9 @@
 #include <hei_includes.hpp>
 #include <isolator/hei_isolation_node.hpp>
 #include <isolator/hei_isolator.hpp>
-#include <register/hei_hardware_register.hpp>
-#include <util/hei_flyweight.hpp>
-
-// BEGIN temporary code
-#include <isolator/hei_isolation_node.hpp>
 #include <register/hei_operator_register.hpp>
 #include <register/hei_scom_register.hpp>
-// END temporary code
+#include <util/hei_flyweight.hpp>
 
 namespace libhei
 {
@@ -35,13 +30,11 @@
 
 //------------------------------------------------------------------------------
 
-void Isolator::initialize(void* i_buffer, size_t i_bufferSize)
-{
-    // TODO
-}
-
 void Isolator::uninitialize()
 {
+    // Clear all of the IsolationChip objects.
+    iv_isoChips.clear();
+
     // Remove all of the IsolationNode objects stored in the flyweights. This
     // must be done before removing the HardwareRegister objects
     Flyweight<IsolationNode>::getSingleton().clear();
@@ -67,8 +60,12 @@
     // Analyze active error on each chip.
     for (const auto& chip : i_chipList)
     {
-        // TODO
-        HEI_INF("Isolator::isolate(%p,%u)", chip.getChip(), chip.getType());
+        // Isolation objects for this chip's type must exist.
+        const auto& itr = iv_isoChips.find(chip.getType());
+        HEI_ASSERT(iv_isoChips.end() != itr);
+
+        // Analyze this chip.
+        itr->second->analyze(chip, o_isoData);
     }
 }
 
diff --git a/src/isolator/hei_isolator.hpp b/src/isolator/hei_isolator.hpp
index f185007..25aaa50 100644
--- a/src/isolator/hei_isolator.hpp
+++ b/src/isolator/hei_isolator.hpp
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <hei_includes.hpp>
+#include <chip_data/hei_chip_data.hpp>
 #include <hei_isolation_data.hpp>
 #include <isolator/hei_isolation_node.hpp>
 
@@ -46,6 +46,10 @@
     /** @brief Assignment operator. */
     Isolator& operator=(const Isolator&) = delete;
 
+  private:
+    /** Keeps track of all chip types that have been initialized. */
+    IsolationChipMap iv_isoChips;
+
   public:
     /** @brief Provides access to a singleton instance of this object. */
     static Isolator& getSingleton()
@@ -55,7 +59,10 @@
     }
 
     /** @brief See API wrapper description in hei_main.hpp. */
-    void initialize(void* i_buffer, size_t i_bufferSize);
+    void initialize(void* i_buffer, size_t i_bufferSize)
+    {
+        parseChipDataFile(i_buffer, i_bufferSize, iv_isoChips);
+    }
 
     /**
      * @brief See API wrapper description in hei_main.hpp.