support to parse RAS data signatures and actions
Change-Id: I114e62f11f962fa9f5b1d7cf52219984e5800f86
Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
diff --git a/analyzer/ras-data/ras-data-definition.md b/analyzer/ras-data/ras-data-definition.md
index b55886e..6603494 100644
--- a/analyzer/ras-data/ras-data-definition.md
+++ b/analyzer/ras-data/ras-data-definition.md
@@ -160,7 +160,6 @@
| name | The `<bus_name>` as defined by the `buses` keyword. |
| rx_priority | Optional priority of the receiving side endpoint |
| tx_priority | Optional priority of the transfer side endpoint |
-| name | The `<bus_name>` as defined by the `buses` keyword. |
| guard | See `guard` table above. |
#### 5.1.6) action type `callout_clock`
diff --git a/analyzer/ras-data/ras-data-parser.cpp b/analyzer/ras-data/ras-data-parser.cpp
index d1315dc..6386b6b 100644
--- a/analyzer/ras-data/ras-data-parser.cpp
+++ b/analyzer/ras-data/ras-data-parser.cpp
@@ -14,11 +14,13 @@
//------------------------------------------------------------------------------
std::shared_ptr<Resolution>
- RasDataParser::getResolution(const libhei::Signature&)
+ RasDataParser::getResolution(const libhei::Signature& i_signature)
{
- // TODO: Default to level 2 support callout until fully implemented.
- return std::make_shared<ProcedureCalloutResolution>(
- ProcedureCallout::NEXTLVL, Callout::HIGH);
+ const auto data = iv_dataFiles.at(i_signature.getChip().getType());
+
+ const auto action = parseSignature(data, i_signature);
+
+ return parseAction(data, action);
}
//------------------------------------------------------------------------------
@@ -96,4 +98,161 @@
//------------------------------------------------------------------------------
+std::string RasDataParser::parseSignature(const nlohmann::json& i_data,
+ const libhei::Signature& i_signature)
+{
+ // Get the signature keys. All are hex (lower case) with no prefix.
+ char buf[5];
+ sprintf(buf, "%04x", i_signature.getId());
+ std::string id{buf};
+
+ sprintf(buf, "%02x", i_signature.getBit());
+ std::string bit{buf};
+
+ sprintf(buf, "%02x", i_signature.getInstance());
+ std::string inst{buf};
+
+ // Return the action.
+ return i_data.at("signatures").at(id).at(bit).at(inst).get<std::string>();
+}
+
+//------------------------------------------------------------------------------
+
+std::shared_ptr<Resolution>
+ RasDataParser::parseAction(const nlohmann::json& i_data,
+ const std::string& i_action)
+{
+ auto o_list = std::make_shared<ResolutionList>();
+
+ // This function will be called recursively and we want to prevent cyclic
+ // recursion.
+ static std::vector<std::string> stack;
+ assert(stack.end() == std::find(stack.begin(), stack.end(), i_action));
+ stack.push_back(i_action);
+
+ // Iterate the action list and apply the changes.
+ for (const auto& a : i_data.at("actions").at(i_action))
+ {
+ auto type = a.at("type").get<std::string>();
+
+ if ("action" == type)
+ {
+ auto name = a.at("name").get<std::string>();
+
+ o_list->push(parseAction(i_data, name));
+ }
+ else if ("callout_self" == type)
+ {
+ auto priority = a.at("priority").get<std::string>();
+ auto guard = a.at("guard").get<bool>();
+
+ // TODO
+ trace::inf("callout_self: priority=%s guard=%c", priority.c_str(),
+ guard ? 'T' : 'F');
+ }
+ else if ("callout_unit" == type)
+ {
+ auto name = a.at("name").get<std::string>();
+ auto priority = a.at("priority").get<std::string>();
+ auto guard = a.at("guard").get<bool>();
+
+ // TODO
+ trace::inf("callout_unit: name=%s priority=%s guard=%c",
+ name.c_str(), priority.c_str(), guard ? 'T' : 'F');
+ }
+ else if ("callout_connected" == type)
+ {
+ auto name = a.at("name").get<std::string>();
+ auto priority = a.at("priority").get<std::string>();
+ auto guard = a.at("guard").get<bool>();
+
+ // TODO
+ trace::inf("callout_connected: name=%s priority=%s guard=%c",
+ name.c_str(), priority.c_str(), guard ? 'T' : 'F');
+ }
+ else if ("callout_bus" == type)
+ {
+ auto name = a.at("name").get<std::string>();
+ // auto rx_priority = a.at("rx_priority").get<std::string>();
+ // auto tx_priority = a.at("tx_priority").get<std::string>();
+ auto guard = a.at("guard").get<bool>();
+
+ // TODO
+ trace::inf("callout_bus: name=%s guard=%c", name.c_str(),
+ guard ? 'T' : 'F');
+ }
+ else if ("callout_clock" == type)
+ {
+ auto position = a.at("position").get<unsigned int>();
+ auto priority = a.at("priority").get<std::string>();
+ auto guard = a.at("guard").get<bool>();
+
+ // TODO
+ trace::inf("callout_clock: position=%u priority=%s guard=%c",
+ position, priority.c_str(), guard ? 'T' : 'F');
+ }
+ else if ("callout_procedure" == type)
+ {
+ auto name = a.at("name").get<std::string>();
+ auto priority = a.at("priority").get<std::string>();
+
+ // clang-format off
+ static const std::map<std::string, ProcedureCallout::Type> m =
+ {
+ {"LEVEL2", ProcedureCallout::NEXTLVL},
+ };
+ // clang-format on
+
+ o_list->push(std::make_shared<ProcedureCalloutResolution>(
+ m.at(name), getPriority(priority)));
+ }
+ else if ("callout_part" == type)
+ {
+ auto name = a.at("name").get<std::string>();
+ auto priority = a.at("priority").get<std::string>();
+
+ // TODO
+ trace::inf("callout_part: name=%s priority=%s", name.c_str(),
+ priority.c_str());
+ }
+ else if ("plugin" == type)
+ {
+ auto name = a.at("name").get<std::string>();
+
+ // TODO
+ trace::inf("plugin: name=%s", name.c_str());
+ }
+ else
+ {
+ throw std::logic_error("Unsupported action type: " + type);
+ }
+ }
+
+ // Done with this action pop it off the stack.
+ stack.pop_back();
+
+ return o_list;
+}
+
+//------------------------------------------------------------------------------
+
+Callout::Priority RasDataParser::getPriority(const std::string& i_priority)
+{
+ // clang-format off
+ static const std::map<std::string, Callout::Priority> m =
+ {
+ {"HIGH", Callout::HIGH},
+ {"MED", Callout::MED},
+ {"MED_A", Callout::MED_A},
+ {"MED_B", Callout::MED_B},
+ {"MED_C", Callout::MED_C},
+ {"LOW", Callout::LOW},
+ };
+ // clang-format on
+
+ return m.at(i_priority);
+}
+
+//------------------------------------------------------------------------------
+
} // namespace analyzer
diff --git a/analyzer/ras-data/ras-data-parser.hpp b/analyzer/ras-data/ras-data-parser.hpp
index e484167..6d45ad2 100644
--- a/analyzer/ras-data/ras-data-parser.hpp
+++ b/analyzer/ras-data/ras-data-parser.hpp
@@ -41,6 +41,40 @@
* the associated schema.
*/
void initDataFiles();
+
+ /**
+ * @brief Parses a signature in the given data file and returns a string
+ * representing the target action for the signature.
+ * @param i_data The parsed RAS data file associated with the
+ * signature's chip type.
+ * @param i_signature The target signature.
+ * @return A string representing the target action for the signature.
+ */
+ std::string parseSignature(const nlohmann::json& i_data,
+ const libhei::Signature& i_signature);
+
+ /**
+ * @brief Parses an action in the given data file and returns the
+ * corresponding resolution.
+ * @param i_data The parsed RAS data file associated with the signature's
+ * chip type.
+ * @param i_action The target action to parse from the given RAS data.
+ * @return A resolution (or nested resolutions) representing the given
+ * action.
+ * @note This function is called recursively because an action could
+ * reference another action. This function will maintain a stack of
+ * parsed actions and will assert that the same action cannot be
+ * parsed more than once in the recursion stack.
+ */
+ std::shared_ptr<Resolution> parseAction(const nlohmann::json& i_data,
+ const std::string& i_action);
+
+ /**
+ * @brief Returns a callout priority enum value for the given string.
+ * @param i_priority The priority string.
+ * @return A callout priority enum value.
+ */
+ Callout::Priority getPriority(const std::string& i_priority);
};
} // namespace analyzer