1 #pragma once 2 3 #include <string.h> 4 5 #include <analyzer/service_data.hpp> 6 #include <hei_chip.hpp> 7 8 #include <functional> 9 #include <map> 10 11 namespace analyzer 12 { 13 14 // A plugin is special function called by the RAS data files specifically for 15 // service actions that cannot be characterized by the RAS data files. 16 // 17 // IMPORTANT: 18 // Use of these plugins should be limited to avoid maintaining chip specific 19 // functionality in this repository. 20 // 21 // Each plugin must be defined in a specific form. See PluginFunction below. 22 // Then the plugin must registered in the PluginMap using the PLUGIN_DEFINE or 23 // PLUGIN_DEFINE_NS macros below. 24 25 // All plugins will have the following parameters: 26 // - The plugin instance for plugins that may be defined for a chip that has 27 // multiple instance of a unit/register. 28 // - The chip containing the root cause attention. 29 // - The service data object containing service actions and FFDC for the root 30 // cause attention. 31 using PluginFunction = 32 std::function<void(unsigned int, const libhei::Chip&, ServiceData&)>; 33 34 // These are provided as know chip types for plugin definitions. 35 constexpr libhei::ChipType_t EXPLORER_11 = 0x60d20011; 36 constexpr libhei::ChipType_t EXPLORER_20 = 0x60d20020; 37 constexpr libhei::ChipType_t P10_10 = 0x20da0010; 38 constexpr libhei::ChipType_t P10_20 = 0x20da0020; 39 40 /** 41 * @brief This is simply a global container for all of the registered plugins. 42 * 43 * @note This class cannot be instantiated. Instead, use the getSingleton() 44 * function to access. 45 */ 46 class PluginMap 47 { 48 private: 49 /** @brief Default constructor. */ 50 PluginMap() = default; 51 52 /** @brief Destructor. */ 53 ~PluginMap() = default; 54 55 /** @brief Copy constructor. */ 56 PluginMap(const PluginMap&) = delete; 57 58 /** @brief Assignment operator. */ 59 PluginMap& operator=(const PluginMap&) = delete; 60 61 public: 62 /** @brief Provides access to a singleton instance of this object. */ 63 static PluginMap& getSingleton() 64 { 65 static PluginMap thePluginMap; 66 return thePluginMap; 67 } 68 69 private: 70 /** A nested map that contains the function for each chip type and plugin 71 * name. */ 72 std::map<libhei::ChipType_t, std::map<std::string, PluginFunction>> iv_map; 73 74 public: 75 /** 76 * @brief Registers a plugin with the plugin map. 77 * 78 * @param i_type The chip type associated with the plugin. 79 * @param i_name The name of the plugin. 80 * @param i_plugin The plugin function. 81 * 82 * @throw std::logic_error if a plugin is defined more than once. 83 */ 84 void add(libhei::ChipType_t i_type, const std::string& i_name, 85 PluginFunction i_plugin) 86 { 87 auto itr = iv_map.find(i_type); 88 if (iv_map.end() == itr || 89 itr->second.end() == itr->second.find(i_name)) 90 { 91 iv_map[i_type][i_name] = i_plugin; 92 } 93 else 94 { 95 throw std::logic_error("Duplicate plugin found"); 96 } 97 } 98 99 /** 100 * @return The plugin function for the target plugin. 101 * 102 * @param i_type The chip type associated with the plugin. 103 * @param i_name The name of the plugin. 104 * 105 * @throw std::out_of_range if the target plugin does not exist. 106 */ 107 PluginFunction get(libhei::ChipType_t i_type, 108 const std::string& i_name) const 109 { 110 return iv_map.at(i_type).at(i_name); 111 } 112 }; 113 114 // These defines a unique class and a global variable for each plugin. Because 115 // the variables are defined in the global scope, they will be initialized with 116 // the default constructor before execution of the program. This allows all of 117 // the plugins to be registered in the plugin map before execution. 118 119 #define __PLUGIN_MAKE(X, Y, Z) X##Y##Z 120 121 #define __PLUGIN_DEFINE(CHIP, NAME, FUNC) \ 122 class __PLUGIN_MAKE(Plugin_, CHIP, NAME) \ 123 { \ 124 public: \ 125 __PLUGIN_MAKE(Plugin_, CHIP, NAME) \ 126 () \ 127 { \ 128 PluginMap::getSingleton().add(CHIP, #NAME, &FUNC); \ 129 } \ 130 }; \ 131 __PLUGIN_MAKE(Plugin_, CHIP, NAME) __PLUGIN_MAKE(g_Plugin_, CHIP, NAME) 132 133 #define PLUGIN_DEFINE(CHIP, NAME) __PLUGIN_DEFINE(CHIP, NAME, CHIP::NAME) 134 135 #define PLUGIN_DEFINE_NS(CHIP, NS, NAME) __PLUGIN_DEFINE(CHIP, NAME, NS::NAME) 136 137 // Regarding the use of PLUGIN_DEFINE_NS. This is provided for cases where the 138 // same plugin needs to be defined differently for different chips. Example: 139 // 140 // namespace A 141 // { 142 // void foo(...) { /* definition for chip A */ } 143 // }; 144 // 145 // namespace B 146 // { 147 // void foo(...) { /* definition for chip B */ } 148 // }; 149 // 150 // PLUGIN_DEFINE_NS(CHIP_A, A, foo); 151 // PLUGIN_DEFINE_NS(CHIP_B, B, foo); 152 // 153 // Also, it is important that the plugin definitions should be declared outside 154 // of the function namespaces (see the example above). This helps find 155 // duplicate plugin definitions at compile time. Otherwise, if you do something 156 // like this: 157 // 158 // namespace A 159 // { 160 // void foo(...) { /* definition for chip A */ } 161 // PLUGIN_DEFINE_NS(CHIP_A, A, foo); 162 // }; 163 // 164 // namespace B 165 // { 166 // void foo(...) { /* definition again for chip A */ } 167 // PLUGIN_DEFINE_NS(CHIP_A, B, foo); 168 // }; 169 // 170 // The compiler will not find the duplicate and instead it will be found during 171 // program execution, which will result in an exception. 172 173 } // namespace analyzer 174