SST  9.1.0
StructuralSimulationToolkit
baseComponent.h
1 // Copyright 2009-2019 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-2019, 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_BASECOMPONENT_H
13 #define SST_CORE_BASECOMPONENT_H
14 
15 #include <sst/core/sst_types.h>
16 #include <sst/core/warnmacros.h>
17 
18 #include <map>
19 #include <string>
20 
21 #include <sst/core/statapi/statengine.h>
22 #include <sst/core/statapi/statbase.h>
23 #include <sst/core/event.h>
24 #include <sst/core/clock.h>
25 #include <sst/core/oneshot.h>
26 #include <sst/core/componentInfo.h>
27 #include <sst/core/simulation.h>
28 #include <sst/core/eli/elementinfo.h>
29 
30 using namespace SST::Statistics;
31 
32 namespace SST {
33 
34 class Clock;
35 class Link;
36 class LinkMap;
37 class Module;
38 class Params;
39 class SubComponent;
40 class TimeConverter;
41 class UnitAlgebra;
42 class SharedRegion;
43 class SharedRegionMerger;
44 class Component;
45 class ComponentExtension;
46 class SubComponent;
47 class SubComponentSlotInfo;
48 
49 /**
50  * Main component object for the simulation.
51  */
53 
54  friend class SubComponentSlotInfo;
55  friend class SubComponent;
56  friend class ComponentInfo;
57  friend class ComponentExtension;
58 
59 public:
60 
61  BaseComponent(ComponentId_t id);
62  BaseComponent() {}
63  virtual ~BaseComponent();
64 
65  /** Returns a pointer to the parent BaseComponent */
66  BaseComponent* getParent() const __attribute__ ((deprecated("getParent() will be removed in SST version 10.0. With the new subcomponent structure, direct access to your parent is not allowed.")))
67  { return my_info->parent_info->component; }
68 
69  const std::string& getType() const { return my_info->getType(); }
70 
71  /** Returns unique component ID */
72  inline ComponentId_t getId() const { return my_info->id; }
73 
74  /** Called when SIGINT or SIGTERM has been seen.
75  * Allows components opportunity to clean up external state.
76  */
77  virtual void emergencyShutdown(void) {}
78 
79 
80  /** Returns component Name */
81  /* inline const std::string& getName() const { return name; } */
82  inline const std::string& getName() const { return my_info->getName(); }
83 
84 
85  /** Used during the init phase. The method will be called each phase of initialization.
86  Initialization ends when no components have sent any data. */
87  virtual void init(unsigned int UNUSED(phase)) {}
88  /** Used during the init phase. The method will be called each phase of initialization.
89  Initialization ends when no components have sent any data. */
90  virtual void complete(unsigned int UNUSED(phase)) {}
91  /** Called after all components have been constructed and initialization has
92  completed, but before simulation time has begun. */
93  virtual void setup( ) { }
94  /** Called after simulation completes, but before objects are
95  destroyed. A good place to print out statistics. */
96  virtual void finish( ) { }
97 
98  /** Currently unused function */
99  virtual bool Status( ) { return 0; }
100 
101  /**
102  * Called by the Simulation to request that the component
103  * print it's current status. Useful for debugging.
104  * @param out The Output class which should be used to print component status.
105  */
106  virtual void printStatus(Output &UNUSED(out)) { return; }
107 
108  /** Determine if a port name is connected to any links */
109  bool isPortConnected(const std::string &name) const;
110 
111  /** Configure a Link
112  * @param name - Port Name on which the link to configure is attached.
113  * @param time_base - Time Base of the link. If NULL is passed in, then it
114  * will use the Component defaultTimeBase
115  * @param handler - Optional Handler to be called when an Event is received
116  * @return A pointer to the configured link, or NULL if an error occured.
117  */
118  Link* configureLink( std::string name, TimeConverter* time_base, Event::HandlerBase* handler = NULL);
119  /** Configure a Link
120  * @param name - Port Name on which the link to configure is attached.
121  * @param time_base - Time Base of the link as a string
122  * @param handler - Optional Handler to be called when an Event is received
123  * @return A pointer to the configured link, or NULL if an error occured.
124  */
125  Link* configureLink( std::string name, std::string time_base, Event::HandlerBase* handler = NULL);
126  /** Configure a Link
127  * @param name - Port Name on which the link to configure is attached.
128  * @param handler - Optional Handler to be called when an Event is received
129  * @return A pointer to the configured link, or NULL if an error occured.
130  */
131  Link* configureLink( std::string name, Event::HandlerBase* handler = NULL);
132 
133  /** Configure a SelfLink (Loopback link)
134  * @param name - Name of the self-link port
135  * @param time_base - Time Base of the link. If NULL is passed in, then it
136  * will use the Component defaultTimeBase
137  * @param handler - Optional Handler to be called when an Event is received
138  * @return A pointer to the configured link, or NULL if an error occured.
139  */
140  Link* configureSelfLink( std::string name, TimeConverter* time_base, Event::HandlerBase* handler = NULL);
141  /** Configure a SelfLink (Loopback link)
142  * @param name - Name of the self-link port
143  * @param time_base - Time Base of the link
144  * @param handler - Optional Handler to be called when an Event is received
145  * @return A pointer to the configured link, or NULL if an error occured.
146  */
147  Link* configureSelfLink( std::string name, std::string time_base, Event::HandlerBase* handler = NULL);
148  /** Configure a SelfLink (Loopback link)
149  * @param name - Name of the self-link port
150  * @param handler - Optional Handler to be called when an Event is received
151  * @return A pointer to the configured link, or NULL if an error occured.
152  */
153  Link* configureSelfLink( std::string name, Event::HandlerBase* handler = NULL);
154 
155  /** Registers a clock for this component.
156  @param freq Frequency for the clock in SI units
157  @param handler Pointer to Clock::HandlerBase which is to be invoked
158  at the specified interval
159  @param regAll Should this clock period be used as the default
160  time base for all of the links connected to this component
161  */
162  TimeConverter* registerClock( std::string freq, Clock::HandlerBase* handler,
163  bool regAll = true);
164  TimeConverter* registerClock( const UnitAlgebra& freq, Clock::HandlerBase* handler,
165  bool regAll = true);
166  /** Removes a clock handler from the component */
167  void unregisterClock(TimeConverter *tc, Clock::HandlerBase* handler);
168 
169  /** Reactivates an existing Clock and Handler
170  * @return time of next time clock handler will fire
171  */
172  Cycle_t reregisterClock(TimeConverter *freq, Clock::HandlerBase* handler);
173  /** Returns the next Cycle that the TimeConverter would fire */
174  Cycle_t getNextClockCycle(TimeConverter *freq);
175 
176  /** Registers a OneShot event for this component.
177  Note: OneShot cannot be canceled, and will always callback after
178  the timedelay.
179  @param timeDelay Time delay for the OneShot in SI units
180  @param handler Pointer to OneShot::HandlerBase which is to be invoked
181  at the specified interval
182  */
183  TimeConverter* registerOneShot( std::string timeDelay, OneShot::HandlerBase* handler);
184  TimeConverter* registerOneShot( const UnitAlgebra& timeDelay, OneShot::HandlerBase* handler);
185 
186  /** Registers a default time base for the component and optionally
187  sets the the component's links to that timebase. Useful for
188  components which do not have a clock, but would like a default
189  timebase.
190  @param base Frequency for the clock in SI units
191  @param regAll Should this clock period be used as the default
192  time base for all of the links connected to this component
193  */
194  TimeConverter* registerTimeBase( std::string base, bool regAll = true);
195 
196  TimeConverter* getTimeConverter( const std::string& base );
197  TimeConverter* getTimeConverter( const UnitAlgebra& base );
198 
199  /** return the time since the simulation began in units specified by
200  the parameter.
201  @param tc TimeConverter specifying the units */
202  SimTime_t getCurrentSimTime(TimeConverter *tc) const;
203  /** return the time since the simulation began in the default timebase */
204  inline SimTime_t getCurrentSimTime() const{
205  return getCurrentSimTime(my_info->defaultTimeBase);
206  }
207  /** return the time since the simulation began in timebase specified
208  @param base Timebase frequency in SI Units */
209  SimTime_t getCurrentSimTime(std::string base);
210 
211  /** Utility function to return the time since the simulation began in nanoseconds */
212  SimTime_t getCurrentSimTimeNano() const;
213  /** Utility function to return the time since the simulation began in microseconds */
214  SimTime_t getCurrentSimTimeMicro() const;
215  /** Utility function to return the time since the simulation began in milliseconds */
216  SimTime_t getCurrentSimTimeMilli() const;
217 
218  bool isStatisticShared(const std::string& statName, bool include_me = false) {
219  if ( include_me ) {
220  if ( doesComponentInfoStatisticExist(statName)) {
221  return true;
222  }
223  }
224  if ( my_info->sharesStatistics() ) {
225  return my_info->parent_info->component->isStatisticShared(statName, true);
226  }
227  else {
228  return false;
229  }
230  }
231 
232 
233  /** Registers a statistic.
234  If Statistic is allowed to run (controlled by Python runtime parameters),
235  then a statistic will be created and returned. If not allowed to run,
236  then a NullStatistic will be returned. In either case, the returned
237  value should be used for all future Statistic calls. The type of
238  Statistic and the Collection Rate is set by Python runtime parameters.
239  If no type is defined, then an Accumulator Statistic will be provided
240  by default. If rate set to 0 or not provided, then the statistic will
241  output results only at end of sim (if output is enabled).
242  @param statName Primary name of the statistic. This name must match the
243  defined ElementInfoStatistic in the component, and must also
244  be enabled in the Python input file.
245  @param statSubId An additional sub name for the statistic
246  @return Either a created statistic of desired type or a NullStatistic
247  depending upon runtime settings.
248  */
249  template <typename T>
250  Statistic<T>* registerStatistic(SST::Params& params, const std::string& statName, const std::string& statSubId = "")
251  {
252  // Verify here that name of the stat is one of the registered
253  // names of the component's ElementInfoStatistic.
254  if (false == doesComponentInfoStatisticExist(statName)) {
255  // I don't define this statistic, so it must be inherited (or non-existant)
256  if ( my_info->sharesStatistics() ) {
257  return my_info->parent_info->component->registerStatistic<T>(params, statName, statSubId);
258  }
259  else {
260  printf("Error: Statistic %s name %s is not found in ElementInfoStatistic, exiting...\n",
261  StatisticBase::buildStatisticFullName(getName().c_str(), statName, statSubId).c_str(),
262  statName.c_str());
263  exit(1);
264  }
265  }
266  // Check to see if the Statistic is previously registered with the Statistics Engine
267  auto* engine = StatisticProcessingEngine::getInstance();
268  StatisticBase* stat = engine->isStatisticRegisteredWithEngine(getName(), my_info->getID(), statName, statSubId, StatisticFieldType<T>::id());
269 
270  if (!stat){
271  //stat does not exist yet
272  auto makeInstance = [=](const std::string& type, BaseComponent* comp,
273  const std::string& name, const std::string& subName,
274  SST::Params& params) -> StatisticBase* {
275  return engine->createStatistic<T>(comp, type, name, subName, params);
276  };
277  stat = registerStatisticCore(params, statName, statSubId, StatisticFieldType<T>::id(),
278  std::move(makeInstance));
279  }
280  return dynamic_cast<Statistic<T>*>(stat);
281  }
282 
283  template <typename T>
284  Statistic<T>* registerStatistic(const std::string& statName, const std::string& statSubId = "")
285  {
286  SST::Params empty{};
287  return registerStatistic<T>(empty, statName, statSubId);
288  }
289 
290  template <typename... Args>
291  Statistic<std::tuple<Args...>>* registerMultiStatistic(const std::string& statName, const std::string& statSubId = "")
292  {
293  SST::Params empty{};
294  return registerStatistic<std::tuple<Args...>>(empty, statName, statSubId);
295  }
296 
297  template <typename... Args>
298  Statistic<std::tuple<Args...>>* registerMultiStatistic(SST::Params& params, const std::string& statName,
299  const std::string& statSubId = "")
300  {
301  return registerStatistic<std::tuple<Args...>>(params, statName, statSubId);
302  }
303 
304  template <typename T>
305  Statistic<T>* registerStatistic(const char* statName, const char* statSubId = "")
306  {
307  return registerStatistic<T>(std::string(statName), std::string(statSubId));
308  }
309 
310 
311  /** Loads a module from an element Library
312  * @param type Fully Qualified library.moduleName
313  * @param params Parameters the module should use for configuration
314  * @return handle to new instance of module, or NULL on failure.
315  */
316  Module* loadModule(std::string type, Params& params);
317 
318  /** Loads a module from an element Library
319  * @param type Fully Qualified library.moduleName
320  * @param comp Pointer to component to pass to Module's constructor
321  * @param params Parameters the module should use for configuration
322  * @return handle to new instance of module, or NULL on failure.
323  */
324  Module* loadModuleWithComponent(std::string type, Component* comp, Params& params) __attribute__ ((deprecated("loadModuleWithComponent will be removed in SST version 10.0. If the module needs access to the parent component, please use SubComponents instead of Modules.")));
325 
326 
327  /** Loads a module from an element Library
328  * @param type Fully Qualified library.moduleName
329  * @param params Parameters the module should use for configuration
330  * @return handle to new instance of module, or NULL on failure.
331  */
332  template <class T, class... ARGS>
333  T* loadModule(std::string type, Params& params, ARGS... args) {
334 
335  // Check to see if this can be loaded with new API or if we have to fallback to old
336  return Factory::getFactory()->Create<T>(type, params, params, args...);
337  }
338 
339 
340 
341  /** Loads a SubComponent from an element Library
342  * @param type Fully Qualified library.moduleName
343  * @param comp Pointer to component to pass to SuBaseComponent's constructor
344  * @param params Parameters the module should use for configuration
345  * @return handle to new instance of SubComponent, or NULL on failure.
346  */
347  SubComponent* loadSubComponent(std::string type, Component* comp, Params& params) __attribute__ ((deprecated("This version of loadSubComponent will be removed in SST version 10.0. Please switch to new user defined API (LoadUserSubComponent(std::string, int, ARGS...)).")));
348 
349  /* New ELI style */
350  SubComponent* loadNamedSubComponent(std::string name) __attribute__ ((deprecated("This version of loadNamedSubComponent will be removed in SST version 10.0. Please switch to new user defined API (LoadUserSubComponent(std::string, int, ARGS...)).")));
351  SubComponent* loadNamedSubComponent(std::string name, Params& params) __attribute__ ((deprecated("This version of loadNamedSubComponent will be removed in SST version 10.0. Please switch to new user defined API (LoadUserSubComponent(std::string, int, ARGS...)).")));
352 
353 
354 protected:
355  // When you direct load, the ComponentExtension does not need any
356  // ELI information and if it has any, it will be ignored. The
357  // extension will be loaded as if it were part of the part
358  // BaseComponent and will share all that components ELI
359  // information.
360  template <class T, class... ARGS>
361  T* loadComponentExtension(ARGS... args) {
362  ComponentExtension* ret = new T(my_info->id, args...);
363  return static_cast<T*>(ret);
364  }
365 
366  /**
367  Check to see if a given element type is loadable with a particular API
368  @param name - Name of element to check in lib.name format
369  @return True if loadable as the API specified as the template parameter
370  */
371  template <class T>
372  bool isSubComponentLoadableUsingAPI(std::string type) {
373  return Factory::getFactory()->isSubComponentLoadableUsingAPI<T>(type);
374  }
375 
376  /**
377  Loads an anonymous subcomponent (not defined in input file to
378  SST run).
379 
380  @param type tyupe of subcomponent to load in lib.name format
381  @param slot_name name of the slot to load subcomponent into
382  @param slot_num index of the slot to load subcomponent into
383  @param share_flags Share flags to be used by subcomponent
384  @param params Params object to be passed to subcomponent
385  @param args Arguments to be passed to constructor. This
386  signature is defined in the API definition
387 
388  For ease in backward compatibility to old API, this call will
389  try to load using new API and will fallback to old if
390  unsuccessful.
391  */
392  template <class T, class... ARGS>
393  T* loadAnonymousSubComponent(std::string type, std::string slot_name, int slot_num, uint64_t share_flags, Params& params, ARGS... args) {
394 
395  share_flags = share_flags & ComponentInfo::USER_FLAGS;
396  ComponentId_t cid = my_info->addAnonymousSubComponent(my_info, type, slot_name, slot_num, share_flags);
397  ComponentInfo* sub_info = my_info->findSubComponent(cid);
398 
399  //This shouldn't happen since we just put it in, but just in case
400  if ( sub_info == NULL ) return NULL;
401 
402  // Check to see if this can be loaded with new API or if we have to fallback to old
403  if ( isSubComponentLoadableUsingAPI<T>(type) ) {
404  auto ret = Factory::getFactory()->Create<T>(type, params, sub_info->id, params, args...);
405  return ret;
406  }
407  else {
408  SubComponent* ret = loadLegacySubComponentPrivate(cid,type,params);
409  return dynamic_cast<T*>(ret);
410  }
411  }
412 
413 
414  /**
415  Loads a user defined subcomponent (defined in input file to SST
416  run). This version does not allow share flags (set to
417  SHARE_NONE) or constructor arguments.
418 
419  @param slot_name name of the slot to load subcomponent into
420 
421  For ease in backward compatibility to old API, this call will
422  try to load using new API and will fallback to old if
423  unsuccessful.
424  */
425  template <class T>
426  T* loadUserSubComponent(std::string slot_name) {
427  return loadUserSubComponent<T>(slot_name, ComponentInfo::SHARE_NONE);
428  }
429 
430  /**
431  Loads a user defined subcomponent (defined in input file to SST
432  run).
433 
434  @param slot_name name of the slot to load subcomponent into
435  @param share_flags Share flags to be used by subcomponent
436  @param args Arguments to be passed to constructor. This
437  signature is defined in the API definition
438 
439  For ease in backward compatibility to old API, this call will
440  try to load using new API and will fallback to old if
441  unsuccessful.
442  */
443  template <class T, class... ARGS>
444  T* loadUserSubComponent(std::string slot_name, uint64_t share_flags, ARGS... args) {
445 
446  // Get list of ComponentInfo objects and make sure that there is
447  // only one SubComponent put into this slot
448  // const std::vector<ComponentInfo>& subcomps = my_info->getSubComponents();
449  const std::map<ComponentId_t,ComponentInfo>& subcomps = my_info->getSubComponents();
450  int sub_count = 0;
451  int index = -1;
452  for ( auto &ci : subcomps ) {
453  if ( ci.second.getSlotName() == slot_name ) {
454  index = ci.second.getSlotNum();
455  sub_count++;
456  }
457  }
458 
459  if ( sub_count > 1 ) {
460  SST::Output outXX("SubComponentSlotWarning: ", 0, 0, Output::STDERR);
461  outXX.fatal(CALL_INFO, 1, "Error: ComponentSlot \"%s\" in component \"%s\" only allows for one SubComponent, %d provided.\n",
462  slot_name.c_str(), my_info->getType().c_str(), sub_count);
463  }
464 
465  return loadUserSubComponentByIndex<T,ARGS...>(slot_name, index, share_flags, args...);
466  }
467 
468 private:
469 
470  SubComponent* loadNamedSubComponent(std::string name, int slot_num);
471  SubComponent* loadNamedSubComponent(std::string name, int slot_num, Params& params);
472 
473  SubComponent* loadNamedSubComponentLegacyPrivate(ComponentInfo* sub_info, Params& params);
474 
475 
476  SubComponent* loadLegacySubComponentPrivate(ComponentId_t cid, const std::string& type, Params& params);
477 
478 
479  // These two functions are only need for backward compatibility
480  // for anonymous subcomponents.
481  void setDefaultTimeBaseForParentLinks(TimeConverter* tc);
482  void setDefaultTimeBaseForChildLinks(TimeConverter* tc);
483 
484  void setDefaultTimeBaseForLinks(TimeConverter* tc);
485 
486  void pushValidParams(Params& params, const std::string& type);
487 
488  template <class T, class... ARGS>
489  T* loadUserSubComponentByIndex(std::string slot_name, int slot_num, int share_flags, ARGS... args) {
490 
491  share_flags = share_flags & ComponentInfo::USER_FLAGS;
492 
493  // Check to see if the slot exists
494  ComponentInfo* sub_info = my_info->findSubComponent(slot_name,slot_num);
495  if ( sub_info == NULL ) return NULL;
496  sub_info->share_flags = share_flags;
497  sub_info->parent_info = my_info;
498 
499  // Check to see if this is documented, and if so, try to load it through the ElementBuilder
500  Params myParams;
501  if ( sub_info->getParams() != NULL ) {
502  myParams.insert(*sub_info->getParams());
503  }
504 
505  if ( isSubComponentLoadableUsingAPI<T>(sub_info->type) ) {
506  auto ret = Factory::getFactory()->Create<T>(sub_info->type, myParams, sub_info->id, myParams, args...);
507  return ret;
508  }
509  else {
510  SubComponent* ret = loadNamedSubComponentLegacyPrivate(sub_info,myParams);
511  return dynamic_cast<T*>(ret);
512  }
513 
514  // return nullptr;
515  }
516 
517  ComponentInfo* getCurrentlyLoadingSubComponentInfo() { return currentlyLoadingSubComponent; }
518  ComponentId_t getCurrentlyLoadingSubComponentID() { return currentlyLoadingSubComponentID; }
519 
520 
521 public:
522  SubComponentSlotInfo* getSubComponentSlotInfo(std::string name, bool fatalOnEmptyIndex = false);
523 
524  /** Retrieve the X,Y,Z coordinates of this component */
525  const std::vector<double>& getCoordinates() const {
526  return my_info->coordinates;
527  }
528 
529 protected:
531 
532  bool isAnonymous() {
533  return my_info->isAnonymous();
534  }
535 
536  bool isUser() {
537  return my_info->isUser();
538  }
539 
540  /** Manually set the default detaulTimeBase */
542  my_info->defaultTimeBase = tc;
543  }
544 
545  TimeConverter* getDefaultTimeBase() {
546  return my_info->defaultTimeBase;
547  }
548 
549  bool doesSubComponentExist(std::string type);
550 
551 
552  /** Find a lookup table */
553  SharedRegion* getLocalSharedRegion(const std::string &key, size_t size);
554  SharedRegion* getGlobalSharedRegion(const std::string &key, size_t size, SharedRegionMerger *merger = NULL);
555 
556  /* Get the Simulation */
557  Simulation* getSimulation() const { return sim; }
558 
559  // Does the statisticName exist in the ElementInfoStatistic
560  virtual bool doesComponentInfoStatisticExist(const std::string &statisticName) const;
561  // Return the EnableLevel for the statisticName from the ElementInfoStatistic
562  uint8_t getComponentInfoStatisticEnableLevel(const std::string &statisticName) const;
563  // Return the Units for the statisticName from the ElementInfoStatistic
564  // std::string getComponentInfoStatisticUnits(const std::string &statisticName) const;
565 
566 
567  Component* getTrueComponent() const __attribute__ ((deprecated("getTrueParent will be removed in SST version 10.0. With the new subcomponent structure, direct access to your parent component is not allowed.")));
568 
569 
570 protected:
571  Simulation *sim;
572 
573 
574 private:
575 
576  // Only need temporarily to help with backward compatibility
577  // implementation in elements.
578  bool loadedWithLegacyAPI;
579 
580 public:
581 
582  /**
583  Temporary function to help provide backward compatibility to
584  old SubComponent API.
585 
586  @return true if subcomponent loaded with old API, false if
587  loaded with new
588  */
589  bool wasLoadedWithLegacyAPI() const {
590  return loadedWithLegacyAPI;
591  }
592 
593 private:
594 
595  ComponentInfo* my_info;
596  ComponentInfo* currentlyLoadingSubComponent;
597  ComponentId_t currentlyLoadingSubComponentID;
598  bool isExtension;
599 
600  void addSelfLink(std::string name);
601  Link* getLinkFromParentSharedPort(const std::string& port);
602 
603  using CreateFxn = std::function<StatisticBase*(const std::string&,
604  BaseComponent*,const std::string&, const std::string&, SST::Params&)>;
605 
606  StatisticBase* registerStatisticCore(SST::Params& params,
607  const std::string& statName, const std::string& statSubId,
608  fieldType_t fieldType, CreateFxn&& fxn);
609 
610  Component* getTrueComponentPrivate() const;
611 
612 };
613 
614 
615 /**
616  Used to load SubComponents when multiple SubComponents are loaded
617  into a single slot (will also also work when a single SubComponent
618  is loaded).
619  */
621 
622  BaseComponent* comp;
623  std::string slot_name;
624  int max_slot_index;
625 
626 protected:
627 
628  SubComponent* protected_create(int slot_num, Params& params) const {
629  if ( slot_num > max_slot_index ) return NULL;
630 
631  return comp->loadNamedSubComponent(slot_name, slot_num, params);
632  }
633 
634 
635 
636 
637 public:
639 
640 
641  SubComponentSlotInfo(BaseComponent* comp, std::string slot_name) :
642  comp(comp),
643  slot_name(slot_name)
644  {
645  const std::map<ComponentId_t,ComponentInfo>& subcomps = comp->my_info->getSubComponents();
646 
647  // Look for all subcomponents with the right slot name
648  max_slot_index = -1;
649  for ( auto &ci : subcomps ) {
650  if ( ci.second.getSlotName() == slot_name ) {
651  if ( ci.second.getSlotNum() > static_cast<int>(max_slot_index) ) {
652  max_slot_index = ci.second.getSlotNum();
653  }
654  }
655  }
656  }
657 
658  const std::string& getSlotName() const {
659  return slot_name;
660  };
661 
662  bool isPopulated(int slot_num) const {
663  if ( slot_num > max_slot_index ) return false;
664  if ( comp->my_info->findSubComponent(slot_name,slot_num) == NULL ) return false;
665  return true;
666  }
667 
668  bool isAllPopulated() const {
669  for ( int i = 0; i < max_slot_index; ++i ) {
670  if ( comp->my_info->findSubComponent(slot_name,i) == NULL ) return false;
671  }
672  return true;
673  }
674 
675  int getMaxPopulatedSlotNumber() const {
676  return max_slot_index;
677  }
678 
679 
680  // Create functions that support the legacy API
681 
682  template <typename T>
683  __attribute__ ((deprecated("This version of create will be removed in SST version 10.0. Please switch to the new user defined API, which includes the share flags.")))
684  T* create(int slot_num, Params& params) const
685  {
686  return private_create<T>(slot_num,params);
687  }
688 
689  template <typename T>
690  __attribute__ ((deprecated("This version of createAll will be removed in SST version 10.0. Please switch to the new user defined API, which includes the share flags and optional constructor arguments.")))
691  void createAll(Params& params, std::vector<T*>& vec, bool insertNulls = true) const
692  {
693  return private_createAll<T>(params, vec, insertNulls);
694  }
695 
696  template <typename T>
697  __attribute__ ((deprecated("This version of createAll will be removed in SST version 10.0. Please switch to the new user defined API, which includes the share flags and optional constructor arguments.")))
698  void createAll(std::vector<T*>& vec, bool insertNulls = true) const
699  {
700  Params empty;
701  return private_createAll<T>(empty, vec, insertNulls);
702  }
703 
704 
705  // Create functions that support the new API
706 
707  /**
708  Create a user defined subcomponent (defined in input file to
709  SST run). This call will pass SHARE_NONE to the new
710  subcomponent and will not take constructor arguments. If
711  constructor arguments are needed for the API that is being
712  loaded, the full call to create will need to be used
713  create(slot_num, share_flags, args...).
714 
715  @param slot_num Slot index from which to load subcomponent
716 
717  This function supports the new API, but is identical to an
718  existing API call. It will try to load using new API and will
719  fallback to old if unsuccessful.
720  */
721  template <typename T>
722  T* create(int slot_num) const
723  {
724  Params empty;
725  return comp->loadUserSubComponentByIndex<T>(slot_name, slot_num, ComponentInfo::SHARE_NONE);
726  // return private_create<T>(slot_num, empty);
727  }
728 
729 
730  /**
731  Create a user defined subcomponent (defined in input file to SST
732  run).
733 
734  @param slot_num Slot index from which to load subcomponent
735  @param share_flags Share flags to be used by subcomponent
736  @param args Arguments to be passed to constructor. This
737  signature is defined in the API definition
738 
739  For ease in backward compatibility to old API, this call will
740  try to load using new API and will fallback to old if
741  unsuccessful.
742  */
743  template <class T, class... ARGS>
744  T* create(int slot_num, uint64_t share_flags, ARGS... args) const {
745  return comp->loadUserSubComponentByIndex<T,ARGS...>(slot_name,slot_num, share_flags, args...);
746  }
747 
748 
749  /**
750  Create all user defined subcomponents (defined in input file to SST
751  run) for the slot.
752 
753  @param vec Vector of T* that will hold the pointers to the new
754  subcomponents. If an index is not occupied, a nullptr will be
755  put in it's place. All components will be added to the end of
756  the vector, so index N will be at vec.length() + N, where
757  vec.length() is the length of the vector when it is passed to
758  the call.
759  @param share_flags Share flags to be used by subcomponent
760  @param args Arguments to be passed to constructor. This
761  signature is defined in the API definition
762 
763  For ease in backward compatibility to old API, this call will
764  try to load using new API and will fallback to old if
765  unsuccessful.
766  */
767  template <typename T, class... ARGS>
768  void createAll(std::vector<T*>& vec, uint64_t share_flags, ARGS... args) const {
769  for ( int i = 0; i <= getMaxPopulatedSlotNumber(); ++i ) {
770  T* sub = create<T>(i, share_flags, args...);
771  vec.push_back(sub);
772  }
773  }
774 
775  /**
776  Create all user defined subcomponents (defined in input file to SST
777  run) for the slot.
778 
779  @param vec Vector of pair<int,T*> that will hold the pointers
780  to the new subcomponents. The int will hold the index from
781  which the subcomponent wass loaded. Unoccupied indexes will be
782  skipped. All components will be added to the end of the
783  vector.
784  @param share_flags Share flags to be used by subcomponent
785  @param args Arguments to be passed to constructor. This
786  signature is defined in the API definition
787 
788  For ease in backward compatibility to old API, this call will
789  try to load using new API and will fallback to old if
790  unsuccessful.
791  */
792  template <typename T, class... ARGS>
793  void createAllSparse(std::vector<std::pair<int,T*> >& vec, uint64_t share_flags, ARGS... args) const {
794  for ( int i = 0; i <= getMaxPopulatedSlotNumber(); ++i ) {
795  T* sub = create<T>(i, share_flags, args...);
796  if ( sub != nullptr ) vec.push_back(i,sub);
797  }
798  }
799 
800  /**
801  Create all user defined subcomponents (defined in input file to SST
802  run) for the slot.
803 
804  @param vec Vector of T* that will hold the pointers
805  to the new subcomponents. Unoccupied indexes will be
806  skipped. All components will be added to the end of the
807  vector.
808  @param share_flags Share flags to be used by subcomponent
809  @param args Arguments to be passed to constructor. This
810  signature is defined in the API definition
811 
812  For ease in backward compatibility to old API, this call will
813  try to load using new API and will fallback to old if
814  unsuccessful.
815  */
816  template <typename T, class... ARGS>
817  void createAllSparse(std::vector<T*>& vec, uint64_t share_flags, ARGS... args) const {
818  for ( int i = 0; i <= getMaxPopulatedSlotNumber(); ++i ) {
819  T* sub = create<T>(i, share_flags, args...);
820  if ( sub != nullptr ) vec.push_back(sub);
821  }
822  }
823 
824 private:
825 
826  // Extra versions of the calls supporting the legacy API to avoid
827  // deprecation warnings in every file that include this file
828  template <typename T>
829  T* private_create(int slot_num, Params& params) const
830  {
831  SubComponent* sub = protected_create(slot_num, params);
832  if ( sub == NULL ) {
833  // Nothing populated at this index, simply return NULL
834  return NULL;
835  }
836  T* cast_sub = dynamic_cast<T*>(sub);
837  if ( cast_sub == NULL ) {
838  // SubComponent not castable to the correct class,
839  // fatal
840  Simulation::getSimulationOutput().fatal(CALL_INFO,1,"Attempt to load SubComponent into slot "
841  "%s, index %d, which is not castable to correct time\n",
842  getSlotName().c_str(),slot_num);
843  }
844  return cast_sub;
845  }
846 
847  template <typename T>
848  void private_createAll(Params& params, std::vector<T*>& vec, bool insertNulls = true) const
849  {
850  for ( int i = 0; i <= getMaxPopulatedSlotNumber(); ++i ) {
851  T* sub = create<T>(i, params);
852  if ( sub != NULL || insertNulls ) vec.push_back(sub);
853  }
854  }
855 
856 };
857 
858 
859 
860 } //namespace SST
861 
862 #endif // SST_CORE_BASECOMPONENT_H
Output object provides consistent method for outputting data to stdout, stderr and/or sst debug file...
Definition: output.h:54
virtual void complete(unsigned int UNUSED(phase))
Used during the init phase.
Definition: baseComponent.h:90
BaseComponent * getParent() const
Returns a pointer to the parent BaseComponent.
Definition: baseComponent.h:66
virtual void printStatus(Output &UNUSED(out))
Called by the Simulation to request that the component print it&#39;s current status. ...
Definition: baseComponent.h:106
ComponentId_t getId() const
Returns unique component ID.
Definition: baseComponent.h:72
T * create(int slot_num, uint64_t share_flags, ARGS...args) const
Create a user defined subcomponent (defined in input file to SST run).
Definition: baseComponent.h:744
A class to convert between a component&#39;s view of time and the core&#39;s view of time.
Definition: timeConverter.h:25
void createAllSparse(std::vector< T * > &vec, uint64_t share_flags, ARGS...args) const
Create all user defined subcomponents (defined in input file to SST run) for the slot.
Definition: baseComponent.h:817
Main component object for the simulation.
Definition: component.h:32
void createAll(std::vector< T * > &vec, uint64_t share_flags, ARGS...args) const
Create all user defined subcomponents (defined in input file to SST run) for the slot.
Definition: baseComponent.h:768
void insert(std::string key, std::string value, bool overwrite=true)
Add a key value pair into the param object.
Definition: params.cc:99
virtual void finish()
Called after simulation completes, but before objects are destroyed.
Definition: baseComponent.h:96
Forms the base class for statistics gathering within SST.
Definition: statbase.h:63
ComponentExtension is a class that can be loaded using loadComponentExtension&lt;T&gt;(...).
Definition: componentExtension.h:29
virtual void emergencyShutdown(void)
Called when SIGINT or SIGTERM has been seen.
Definition: baseComponent.h:77
T * loadAnonymousSubComponent(std::string type, std::string slot_name, int slot_num, uint64_t share_flags, Params &params, ARGS...args)
Loads an anonymous subcomponent (not defined in input file to SST run).
Definition: baseComponent.h:393
Forms the template defined base class for statistics gathering within SST.
Definition: elementinfo.h:43
const std::vector< double > & getCoordinates() const
Retrieve the X,Y,Z coordinates of this component.
Definition: baseComponent.h:525
static Output & getSimulationOutput()
Return the base simulation Output class instance.
Definition: simulation.h:178
virtual void setup()
Called after all components have been constructed and initialization has completed, but before simulation time has begun.
Definition: baseComponent.h:93
T * loadUserSubComponent(std::string slot_name, uint64_t share_flags, ARGS...args)
Loads a user defined subcomponent (defined in input file to SST run).
Definition: baseComponent.h:444
void fatal(uint32_t line, const char *file, const char *func, int exit_code, const char *format,...) const
Output the fatal message with formatting as specified by the format parameter.
Definition: output.cc:155
void createAllSparse(std::vector< std::pair< int, T * > > &vec, uint64_t share_flags, ARGS...args) const
Create all user defined subcomponents (defined in input file to SST run) for the slot.
Definition: baseComponent.h:793
Functor classes for Clock handling.
Definition: clock.h:44
Main component object for the simulation.
Definition: baseComponent.h:52
Definition: output.h:62
virtual bool Status()
Currently unused function.
Definition: baseComponent.h:99
Parameter store.
Definition: params.h:45
Statistic< T > * registerStatistic(SST::Params &params, const std::string &statName, const std::string &statSubId="")
Registers a statistic.
Definition: baseComponent.h:250
Functor classes for Event handling.
Definition: event.h:86
bool isSubComponentLoadableUsingAPI(std::string type)
Check to see if a given element type is loadable with a particular API.
Definition: baseComponent.h:372
Definition: componentInfo.h:36
Used to load SubComponents when multiple SubComponents are loaded into a single slot (will also also ...
Definition: baseComponent.h:620
Definition: statfieldinfo.h:51
T * create(int slot_num) const
Create a user defined subcomponent (defined in input file to SST run).
Definition: baseComponent.h:722
An SST core component that handles timing and event processing informing all registered Statistics to...
Definition: statengine.h:52
const std::string & getName() const
Returns component Name.
Definition: baseComponent.h:82
Performs Unit math in full precision.
Definition: unitAlgebra.h:104
void setDefaultTimeBase(TimeConverter *tc)
Manually set the default detaulTimeBase.
Definition: baseComponent.h:541
SubComponent is a class loadable through the factory which allows dynamic functionality to be added t...
Definition: subcomponent.h:30
SimTime_t getCurrentSimTime() const
return the time since the simulation began in the default timebase
Definition: baseComponent.h:204
T * loadModule(std::string type, Params &params, ARGS...args)
Loads a module from an element Library.
Definition: baseComponent.h:333
T * loadUserSubComponent(std::string slot_name)
Loads a user defined subcomponent (defined in input file to SST run).
Definition: baseComponent.h:426
virtual void init(unsigned int UNUSED(phase))
Used during the init phase.
Definition: baseComponent.h:87
Functor classes for OneShot handling.
Definition: oneshot.h:39