#pragma once #include #include #include #include #include #include namespace analyzer { // A plugin is special function called by the RAS data files specifically for // service actions that cannot be characterized by the RAS data files. // // IMPORTANT: // Use of these plugins should be limited to avoid maintaining chip specific // functionality in this repository. // // Each plugin must be defined in a specific form. See PluginFunction below. // Then the plugin must registered in the PluginMap using the PLUGIN_DEFINE or // PLUGIN_DEFINE_NS macros below. // All plugins will have the following parameters: // - The plugin instance for plugins that may be defined for a chip that has // multiple instance of a unit/register. // - The chip containing the root cause attention. // - The service data object containing service actions and FFDC for the root // cause attention. using PluginFunction = std::function; // These are provided as know chip types for plugin definitions. constexpr libhei::ChipType_t EXPLORER_11 = 0x60d20011; constexpr libhei::ChipType_t EXPLORER_20 = 0x60d20020; constexpr libhei::ChipType_t ODYSSEY_10 = 0x60c00010; constexpr libhei::ChipType_t P10_10 = 0x20da0010; constexpr libhei::ChipType_t P10_20 = 0x20da0020; /** * @brief This is simply a global container for all of the registered plugins. * * @note This class cannot be instantiated. Instead, use the getSingleton() * function to access. */ class PluginMap { private: /** @brief Default constructor. */ PluginMap() = default; /** @brief Destructor. */ ~PluginMap() = default; /** @brief Copy constructor. */ PluginMap(const PluginMap&) = delete; /** @brief Assignment operator. */ PluginMap& operator=(const PluginMap&) = delete; public: /** @brief Provides access to a singleton instance of this object. */ static PluginMap& getSingleton() { static PluginMap thePluginMap; return thePluginMap; } private: /** A nested map that contains the function for each chip type and plugin * name. */ std::map> iv_map; public: /** * @brief Registers a plugin with the plugin map. * * @param i_type The chip type associated with the plugin. * @param i_name The name of the plugin. * @param i_plugin The plugin function. * * @throw std::logic_error if a plugin is defined more than once. */ void add(libhei::ChipType_t i_type, const std::string& i_name, PluginFunction i_plugin) { auto itr = iv_map.find(i_type); if (iv_map.end() == itr || itr->second.end() == itr->second.find(i_name)) { iv_map[i_type][i_name] = i_plugin; } else { throw std::logic_error("Duplicate plugin found"); } } /** * @return The plugin function for the target plugin. * * @param i_type The chip type associated with the plugin. * @param i_name The name of the plugin. * * @throw std::out_of_range if the target plugin does not exist. */ PluginFunction get(libhei::ChipType_t i_type, const std::string& i_name) const { PluginFunction func; try { func = iv_map.at(i_type).at(i_name); } catch (const std::out_of_range& e) { trace::err("Plugin not defined: i_type=0x%08x i_name=%s", i_type, i_name.c_str()); throw; // caught later downstream } return func; } }; // These defines a unique class and a global variable for each plugin. Because // the variables are defined in the global scope, they will be initialized with // the default constructor before execution of the program. This allows all of // the plugins to be registered in the plugin map before execution. #define __PLUGIN_MAKE(X, Y, Z) X##Y##Z #define __PLUGIN_DEFINE(CHIP, NAME, FUNC) \ class __PLUGIN_MAKE(Plugin_, CHIP, NAME) \ { \ public: \ __PLUGIN_MAKE(Plugin_, CHIP, NAME) \ () \ { \ PluginMap::getSingleton().add(CHIP, #NAME, &FUNC); \ } \ }; \ __PLUGIN_MAKE(Plugin_, CHIP, NAME) __PLUGIN_MAKE(g_Plugin_, CHIP, NAME) #define PLUGIN_DEFINE(CHIP, NAME) __PLUGIN_DEFINE(CHIP, NAME, CHIP::NAME) #define PLUGIN_DEFINE_NS(CHIP, NS, NAME) __PLUGIN_DEFINE(CHIP, NAME, NS::NAME) // Regarding the use of PLUGIN_DEFINE_NS. This is provided for cases where the // same plugin needs to be defined differently for different chips. Example: // // namespace A // { // void foo(...) { /* definition for chip A */ } // }; // // namespace B // { // void foo(...) { /* definition for chip B */ } // }; // // PLUGIN_DEFINE_NS(CHIP_A, A, foo); // PLUGIN_DEFINE_NS(CHIP_B, B, foo); // // Also, it is important that the plugin definitions should be declared outside // of the function namespaces (see the example above). This helps find // duplicate plugin definitions at compile time. Otherwise, if you do something // like this: // // namespace A // { // void foo(...) { /* definition for chip A */ } // PLUGIN_DEFINE_NS(CHIP_A, A, foo); // }; // // namespace B // { // void foo(...) { /* definition again for chip A */ } // PLUGIN_DEFINE_NS(CHIP_A, B, foo); // }; // // The compiler will not find the duplicate and instead it will be found during // program execution, which will result in an exception. } // namespace analyzer