SST  15.1.0
StructuralSimulationToolkit
elibase.h
1 // Copyright 2009-2025 NTESS. Under the terms
2 // of Contract DE-NA0003525 with NTESS, the U.S.
3 // Government retains certain rights in this software.
4 //
5 // Copyright (c) 2009-2025, NTESS
6 // All rights reserved.
7 //
8 // This file is part of the SST software package. For license
9 // information, see the LICENSE file in the top level directory of the
10 // distribution.
11 
12 #ifndef SST_CORE_ELI_ELIBASE_H
13 #define SST_CORE_ELI_ELIBASE_H
14 
15 #include "sst/core/sst_types.h"
16 
17 #include <algorithm>
18 #include <cstdint>
19 #include <cstring>
20 #include <deque>
21 #include <map>
22 #include <memory>
23 #include <string>
24 #include <type_traits>
25 #include <vector>
26 
27 // Component Category Definitions
28 #define COMPONENT_CATEGORY_UNCATEGORIZED 0x00
29 #define COMPONENT_CATEGORY_PROCESSOR 0x01
30 #define COMPONENT_CATEGORY_MEMORY 0x02
31 #define COMPONENT_CATEGORY_NETWORK 0x04
32 #define COMPONENT_CATEGORY_SYSTEM 0x08
33 
34 namespace SST {
35 
36 /** Describes Statistics used by a Component.
37  */
39 {
40  const char* name; /*!< Name of the Statistic to be Enabled */
41  const char* description; /*!< Brief description of the Statistic */
42  const char* units; /*!< Units associated with this Statistic value */
43  const uint8_t enable_level; /*!< Level to meet to enable statistic 0 = disabled */
44 };
45 
46 /** Describes Parameters to a Component.
47  */
49 {
50  const char* name; /*!< Name of the parameter */
51  const char* description; /*!< Brief description of the parameter (ie, what it controls) */
52  const char* defaultValue; /*!< Default value (if any) nullptr == required parameter with no default, "" == optional
53  parameter, blank default, "foo" == default value */
54 };
55 
56 /** Describes Ports that the Component can use
57  */
59 {
60  const char* name; /*!< Name of the port. Can contain %d for a dynamic port, also %(xxx)d for dynamic port with xxx
61  being the controlling component parameter */
62  const char* description; /*!< Brief description of the port (ie, what it is used for) */
63  const std::vector<std::string>
64  validEvents; /*!< List of fully-qualified event types that this Port expects to send or receive */
65 };
66 
68 {
69  const char* name;
70  const char* description;
71  const char* superclass;
72 };
73 
75 {
76  const char* name;
77  const char* description;
78  const char* superclass;
79 };
80 
82 {
83  const char* name;
84  const char* value;
85 };
86 
87 namespace ELI {
88 
89 // Function used to combine the parent and child ELI information.
90 // This function only works for items that have a 'name' and a
91 // 'description/value' field (which is all of them at time of function
92 // writing). You can delete a parent's info by adding an entry in the
93 // child with the same name and a nullptr in the description. Each
94 // info item should include a macro of the format SST_ELI_DELETE_* to
95 // make this easy for the element library writer.
96 //
97 // The function creates a new vector and the uses vector::swap because
98 // the ElementInfo* classes have const data members so deleting from
99 // the vector does not compile (copy constructor is deleted).
100 template <typename T>
101 void
102 combineEliInfo(std::vector<T>& base, const std::vector<T>& add)
103 {
104  std::vector<T> combined;
105  // Add in any item that isn't already defined
106  for ( auto& x : add ) {
107  if ( std::none_of(base.begin(), base.end(), [&](auto& y) { return !strcmp(x.name, y.name); }) )
108  combined.emplace_back(x);
109  }
110 
111  // Now add all the locals. We will skip any one that has nullptr
112  // in the description field
113  for ( auto& x : base ) {
114  if constexpr ( std::is_same_v<T, ElementInfoAttribute> ) {
115  if ( x.value != nullptr ) combined.emplace_back(x);
116  }
117  else {
118  if ( x.description != nullptr ) combined.emplace_back(x);
119  }
120  }
121  base.swap(combined);
122 }
123 
125 {
126  virtual void load() = 0;
127  virtual ~LibraryLoader() = default;
128 };
129 
131 {
132 public:
133  using InfoMap = std::map<std::string, std::deque<std::shared_ptr<LibraryLoader>>>;
134  using LibraryMap = std::map<std::string, InfoMap>;
135 
136  static bool isLoaded(const std::string& name) { return getLoaders().count(name) != 0; }
137 
138  // @return A boolean indicated successfully added
139  static bool addLoader(
140  const std::string& lib, const std::string& name, const std::string& alias, LibraryLoader* loader);
141 
142  static LibraryMap& getLoaders()
143  {
144  static LibraryMap loaders;
145  return loaders;
146  }
147 };
148 
149 // Template used to get aliases. Needed because the ELI_getAlias()
150 // function may not exist.
151 template <typename, typename = void>
152 struct GetAlias
153 {
154  static std::string get() { return ""; }
155 };
156 
157 template <typename T>
158 struct GetAlias<T, std::void_t<decltype(T::ELI_getAlias())>>
159 {
160  static std::string get() { return T::ELI_getAlias(); }
161 };
162 
163 
164 } // namespace ELI
165 } // namespace SST
166 
167 #define ELI_FORWARD_AS_ONE(...) __VA_ARGS__
168 
169 // This is the macro used to declare a class that will become the base
170 // class for classes that are to be loaded through the ELI.
171 
172 // The __EliBaseLevel and __EliDerivedLevel are used to determine the
173 // ELI parent API. If __EliDerivedLevel is greater than
174 // __EliBaseLevel, then the parent API type is stored in
175 // __LocalEliBase. If not, then the parent API is __ParentEliBase.
176 // In other words, the parent API is __LocalEliBase if, and only if,
177 // the class is a derived class (i.e., calls SST_ELI_REGISTER_DERIVED
178 // either directly or indirectly) and has not called
179 // SST_ELI_DECLARE_BASE or SST_ELI_DECLARE_NEW_BASE. If the class has
180 // called either of the *_BASE macros, then they are APIs and if you
181 // derive a class from it, then you need to use that class also as the
182 // ELI parent.
183 #define SST_ELI_DECLARE_BASE(Base) \
184  using __LocalEliBase = Base; \
185  using __ParentEliBase = void; \
186  static constexpr int __EliBaseLevel = 0; \
187  static constexpr int __EliDerivedLevel = 0; \
188  static const char* ELI_baseName() \
189  { \
190  return #Base; \
191  }
192 
193 #define SST_ELI_DECLARE_INFO_COMMON() \
194  using InfoLibrary = ::SST::ELI::InfoLibrary<__LocalEliBase>; \
195  template <class __TT> \
196  static bool addDerivedInfo(const std::string& lib, const std::string& elem) \
197  { \
198  using BuilderInfo = typename __LocalEliBase::BuilderInfo; \
199  return addInfo(lib, elem, new BuilderInfo(lib, elem, (__TT*)nullptr)); \
200  }
201 
202 // This macro can be used to declare a new base class that inherits
203 // from another base class. The ELI information will also be
204 // inherited (added to whatever the child class declares). Items in
205 // the child will overwrite items in the parent. See comment for
206 // combineEliInfo() for information about deleting items from the
207 // parent API.
208 #define SST_ELI_DECLARE_NEW_BASE(OldBase, NewBase) \
209  using __LocalEliBase = NewBase; \
210  using __ParentEliBase = OldBase; \
211  static constexpr int __EliBaseLevel = OldBase::__EliBaseLevel + 2; \
212  SST_ELI_DECLARE_INFO_COMMON() \
213  static const char* ELI_baseName() \
214  { \
215  return #NewBase; \
216  } \
217  template <class InfoImpl> \
218  static bool addInfo(const std::string& elemlib, const std::string& elem, InfoImpl* info) \
219  { \
220  return OldBase::addInfo(elemlib, elem, info) && \
221  ::SST::ELI::InfoDatabase::getLibrary<NewBase>(elemlib)->addInfo(elem, info); \
222  }
223 
224 #endif // SST_CORE_ELI_ELIBASE_H
Definition: elibase.h:130
Definition: elibase.h:67
const char * defaultValue
Definition: elibase.h:52
const char * description
Definition: elibase.h:51
Definition: elibase.h:81
Definition: elibase.h:74
Definition: action.cc:18
Describes Statistics used by a Component.
Definition: elibase.h:38
Definition: elibase.h:124
const char * description
Definition: elibase.h:62
const char * name
Definition: elibase.h:50
const std::vector< std::string > validEvents
Definition: elibase.h:64
const char * name
Definition: elibase.h:40
Definition: elibase.h:152
Describes Parameters to a Component.
Definition: elibase.h:48
const char * description
Definition: elibase.h:41
const char * name
Definition: elibase.h:60
const uint8_t enable_level
Definition: elibase.h:43
Describes Ports that the Component can use.
Definition: elibase.h:58
const char * units
Definition: elibase.h:42