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 ODYSSEY_10 = 0x60c00010; 39 constexpr libhei::ChipType_t P10_10 = 0x20da0010; 40 constexpr libhei::ChipType_t P10_20 = 0x20da0020; 41 42 /** 43 * @brief This is simply a global container for all of the registered plugins. 44 * 45 * @note This class cannot be instantiated. Instead, use the getSingleton() 46 * function to access. 47 */ 48 class PluginMap 49 { 50 private: 51 /** @brief Default constructor. */ 52 PluginMap() = default; 53 54 /** @brief Destructor. */ 55 ~PluginMap() = default; 56 57 /** @brief Copy constructor. */ 58 PluginMap(const PluginMap&) = delete; 59 60 /** @brief Assignment operator. */ 61 PluginMap& operator=(const PluginMap&) = delete; 62 63 public: 64 /** @brief Provides access to a singleton instance of this object. */ 65 static PluginMap& getSingleton() 66 { 67 static PluginMap thePluginMap; 68 return thePluginMap; 69 } 70 71 private: 72 /** A nested map that contains the function for each chip type and plugin 73 * name. */ 74 std::map<libhei::ChipType_t, std::map<std::string, PluginFunction>> iv_map; 75 76 public: 77 /** 78 * @brief Registers a plugin with the plugin map. 79 * 80 * @param i_type The chip type associated with the plugin. 81 * @param i_name The name of the plugin. 82 * @param i_plugin The plugin function. 83 * 84 * @throw std::logic_error if a plugin is defined more than once. 85 */ 86 void add(libhei::ChipType_t i_type, const std::string& i_name, 87 PluginFunction i_plugin) 88 { 89 auto itr = iv_map.find(i_type); 90 if (iv_map.end() == itr || 91 itr->second.end() == itr->second.find(i_name)) 92 { 93 iv_map[i_type][i_name] = i_plugin; 94 } 95 else 96 { 97 throw std::logic_error("Duplicate plugin found"); 98 } 99 } 100 101 /** 102 * @return The plugin function for the target plugin. 103 * 104 * @param i_type The chip type associated with the plugin. 105 * @param i_name The name of the plugin. 106 * 107 * @throw std::out_of_range if the target plugin does not exist. 108 */ 109 PluginFunction get(libhei::ChipType_t i_type, 110 const std::string& i_name) const 111 { 112 PluginFunction func; 113 114 try 115 { 116 func = iv_map.at(i_type).at(i_name); 117 } 118 catch (const std::out_of_range& e) 119 { 120 trace::err("Plugin not defined: i_type=0x%08x i_name=%s", i_type, 121 i_name.c_str()); 122 throw; // caught later downstream 123 } 124 125 return func; 126 } 127 }; 128 129 // These defines a unique class and a global variable for each plugin. Because 130 // the variables are defined in the global scope, they will be initialized with 131 // the default constructor before execution of the program. This allows all of 132 // the plugins to be registered in the plugin map before execution. 133 134 #define __PLUGIN_MAKE(X, Y, Z) X##Y##Z 135 136 #define __PLUGIN_DEFINE(CHIP, NAME, FUNC) \ 137 class __PLUGIN_MAKE(Plugin_, CHIP, NAME) \ 138 { \ 139 public: \ 140 __PLUGIN_MAKE(Plugin_, CHIP, NAME) \ 141 () \ 142 { \ 143 PluginMap::getSingleton().add(CHIP, #NAME, &FUNC); \ 144 } \ 145 }; \ 146 __PLUGIN_MAKE(Plugin_, CHIP, NAME) __PLUGIN_MAKE(g_Plugin_, CHIP, NAME) 147 148 #define PLUGIN_DEFINE(CHIP, NAME) __PLUGIN_DEFINE(CHIP, NAME, CHIP::NAME) 149 150 #define PLUGIN_DEFINE_NS(CHIP, NS, NAME) __PLUGIN_DEFINE(CHIP, NAME, NS::NAME) 151 152 // Regarding the use of PLUGIN_DEFINE_NS. This is provided for cases where the 153 // same plugin needs to be defined differently for different chips. Example: 154 // 155 // namespace A 156 // { 157 // void foo(...) { /* definition for chip A */ } 158 // }; 159 // 160 // namespace B 161 // { 162 // void foo(...) { /* definition for chip B */ } 163 // }; 164 // 165 // PLUGIN_DEFINE_NS(CHIP_A, A, foo); 166 // PLUGIN_DEFINE_NS(CHIP_B, B, foo); 167 // 168 // Also, it is important that the plugin definitions should be declared outside 169 // of the function namespaces (see the example above). This helps find 170 // duplicate plugin definitions at compile time. Otherwise, if you do something 171 // like this: 172 // 173 // namespace A 174 // { 175 // void foo(...) { /* definition for chip A */ } 176 // PLUGIN_DEFINE_NS(CHIP_A, A, foo); 177 // }; 178 // 179 // namespace B 180 // { 181 // void foo(...) { /* definition again for chip A */ } 182 // PLUGIN_DEFINE_NS(CHIP_A, B, foo); 183 // }; 184 // 185 // The compiler will not find the duplicate and instead it will be found during 186 // program execution, which will result in an exception. 187 188 } // namespace analyzer 189