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