SST  9.0.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 SubComponent from an element Library
328  * @param type Fully Qualified library.moduleName
329  * @param comp Pointer to component to pass to SuBaseComponent's constructor
330  * @param params Parameters the module should use for configuration
331  * @return handle to new instance of SubComponent, or NULL on failure.
332  */
333  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...)).")));
334 
335  /* New ELI style */
336  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...)).")));
337  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...)).")));
338 
339 
340 protected:
341  // When you direct load, the ComponentExtension does not need any
342  // ELI information and if it has any, it will be ignored. The
343  // extension will be loaded as if it were part of the part
344  // BaseComponent and will share all that components ELI
345  // information.
346  template <class T, class... ARGS>
347  T* loadComponentExtension(ARGS... args) {
348  ComponentExtension* ret = new T(my_info->id, args...);
349  return static_cast<T*>(ret);
350  }
351 
352  /**
353  Check to see if a given element type is loadable with a particular API
354  @param name - Name of element to check in lib.name format
355  @return True if loadable as the API specified as the template parameter
356  */
357  template <class T>
358  bool isSubComponentLoadableUsingAPI(std::string type) {
359  return Factory::getFactory()->isSubComponentLoadableUsingAPI<T>(type);
360  }
361 
362  /**
363  Loads an anonymous subcomponent (not defined in input file to
364  SST run).
365 
366  @param type tyupe of subcomponent to load in lib.name format
367  @param slot_name name of the slot to load subcomponent into
368  @param slot_num index of the slot to load subcomponent into
369  @param share_flags Share flags to be used by subcomponent
370  @param params Params object to be passed to subcomponent
371  @param args Arguments to be passed to constructor. This
372  signature is defined in the API definition
373 
374  For ease in backward compatibility to old API, this call will
375  try to load using new API and will fallback to old if
376  unsuccessful.
377  */
378  template <class T, class... ARGS>
379  T* loadAnonymousSubComponent(std::string type, std::string slot_name, int slot_num, uint64_t share_flags, Params& params, ARGS... args) {
380 
381  share_flags = share_flags & ComponentInfo::USER_FLAGS;
382  ComponentId_t cid = my_info->addAnonymousSubComponent(my_info, type, slot_name, slot_num, share_flags);
383  ComponentInfo* sub_info = my_info->findSubComponent(cid);
384 
385  //This shouldn't happen since we just put it in, but just in case
386  if ( sub_info == NULL ) return NULL;
387 
388  // Check to see if this can be loaded with new API or if we have to fallback to old
389  if ( isSubComponentLoadableUsingAPI<T>(type) ) {
390  auto ret = Factory::getFactory()->Create<T>(type, params, sub_info->id, params, args...);
391  return ret;
392  }
393  else {
394  SubComponent* ret = loadLegacySubComponentPrivate(cid,type,params);
395  return dynamic_cast<T*>(ret);
396  }
397  }
398 
399 
400  /**
401  Loads a user defined subcomponent (defined in input file to SST
402  run). This version does not allow share flags (set to
403  SHARE_NONE) or constructor arguments.
404 
405  @param slot_name name of the slot to load subcomponent into
406 
407  For ease in backward compatibility to old API, this call will
408  try to load using new API and will fallback to old if
409  unsuccessful.
410  */
411  template <class T>
412  T* loadUserSubComponent(std::string slot_name) {
413  return loadUserSubComponent<T>(slot_name, ComponentInfo::SHARE_NONE);
414  }
415 
416  /**
417  Loads a user defined subcomponent (defined in input file to SST
418  run).
419 
420  @param slot_name name of the slot to load subcomponent into
421  @param share_flags Share flags to be used by subcomponent
422  @param args Arguments to be passed to constructor. This
423  signature is defined in the API definition
424 
425  For ease in backward compatibility to old API, this call will
426  try to load using new API and will fallback to old if
427  unsuccessful.
428  */
429  template <class T, class... ARGS>
430  T* loadUserSubComponent(std::string slot_name, uint64_t share_flags, ARGS... args) {
431 
432  // Get list of ComponentInfo objects and make sure that there is
433  // only one SubComponent put into this slot
434  // const std::vector<ComponentInfo>& subcomps = my_info->getSubComponents();
435  const std::map<ComponentId_t,ComponentInfo>& subcomps = my_info->getSubComponents();
436  int sub_count = 0;
437  int index = -1;
438  for ( auto &ci : subcomps ) {
439  if ( ci.second.getSlotName() == slot_name ) {
440  index = ci.second.getSlotNum();
441  sub_count++;
442  }
443  }
444 
445  if ( sub_count > 1 ) {
446  SST::Output outXX("SubComponentSlotWarning: ", 0, 0, Output::STDERR);
447  outXX.fatal(CALL_INFO, 1, "Error: ComponentSlot \"%s\" in component \"%s\" only allows for one SubComponent, %d provided.\n",
448  slot_name.c_str(), my_info->getType().c_str(), sub_count);
449  }
450 
451  return loadUserSubComponentByIndex<T,ARGS...>(slot_name, index, share_flags, args...);
452  }
453 
454 private:
455 
456  SubComponent* loadNamedSubComponent(std::string name, int slot_num);
457  SubComponent* loadNamedSubComponent(std::string name, int slot_num, Params& params);
458 
459  SubComponent* loadNamedSubComponentLegacyPrivate(ComponentInfo* sub_info, Params& params);
460 
461 
462  SubComponent* loadLegacySubComponentPrivate(ComponentId_t cid, const std::string& type, Params& params);
463 
464 
465  // These two functions are only need for backward compatibility
466  // for anonymous subcomponents.
467  void setDefaultTimeBaseForParentLinks(TimeConverter* tc);
468  void setDefaultTimeBaseForChildLinks(TimeConverter* tc);
469 
470  void setDefaultTimeBaseForLinks(TimeConverter* tc);
471 
472  void pushValidParams(Params& params, const std::string& type);
473 
474  template <class T, class... ARGS>
475  T* loadUserSubComponentByIndex(std::string slot_name, int slot_num, int share_flags, ARGS... args) {
476 
477  share_flags = share_flags & ComponentInfo::USER_FLAGS;
478 
479  // Check to see if the slot exists
480  ComponentInfo* sub_info = my_info->findSubComponent(slot_name,slot_num);
481  if ( sub_info == NULL ) return NULL;
482  sub_info->share_flags = share_flags;
483  sub_info->parent_info = my_info;
484 
485  // Check to see if this is documented, and if so, try to load it through the ElementBuilder
486  Params myParams;
487  if ( sub_info->getParams() != NULL ) {
488  myParams.insert(*sub_info->getParams());
489  }
490 
491  if ( isSubComponentLoadableUsingAPI<T>(sub_info->type) ) {
492  auto ret = Factory::getFactory()->Create<T>(sub_info->type, myParams, sub_info->id, myParams, args...);
493  return ret;
494  }
495  else {
496  SubComponent* ret = loadNamedSubComponentLegacyPrivate(sub_info,myParams);
497  return dynamic_cast<T*>(ret);
498  }
499 
500  // return nullptr;
501  }
502 
503  ComponentInfo* getCurrentlyLoadingSubComponentInfo() { return currentlyLoadingSubComponent; }
504  ComponentId_t getCurrentlyLoadingSubComponentID() { return currentlyLoadingSubComponentID; }
505 
506 
507 public:
508  SubComponentSlotInfo* getSubComponentSlotInfo(std::string name, bool fatalOnEmptyIndex = false);
509 
510  /** Retrieve the X,Y,Z coordinates of this component */
511  const std::vector<double>& getCoordinates() const {
512  return my_info->coordinates;
513  }
514 
515 protected:
517 
518  bool isAnonymous() {
519  return my_info->isAnonymous();
520  }
521 
522  bool isUser() {
523  return my_info->isUser();
524  }
525 
526  /** Manually set the default detaulTimeBase */
528  my_info->defaultTimeBase = tc;
529  }
530 
531  TimeConverter* getDefaultTimeBase() {
532  return my_info->defaultTimeBase;
533  }
534 
535  bool doesSubComponentExist(std::string type);
536 
537 
538  /** Find a lookup table */
539  SharedRegion* getLocalSharedRegion(const std::string &key, size_t size);
540  SharedRegion* getGlobalSharedRegion(const std::string &key, size_t size, SharedRegionMerger *merger = NULL);
541 
542  /* Get the Simulation */
543  Simulation* getSimulation() const { return sim; }
544 
545  // Does the statisticName exist in the ElementInfoStatistic
546  virtual bool doesComponentInfoStatisticExist(const std::string &statisticName) const;
547  // Return the EnableLevel for the statisticName from the ElementInfoStatistic
548  uint8_t getComponentInfoStatisticEnableLevel(const std::string &statisticName) const;
549  // Return the Units for the statisticName from the ElementInfoStatistic
550  // std::string getComponentInfoStatisticUnits(const std::string &statisticName) const;
551 
552 
553  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.")));
554 
555 
556 protected:
557  Simulation *sim;
558 
559 
560 private:
561 
562  // Only need temporarily to help with backward compatibility
563  // implementation in elements.
564  bool loadedWithLegacyAPI;
565 
566 public:
567 
568  /**
569  Temporary function to help provide backward compatibility to
570  old SubComponent API.
571 
572  @return true if subcomponent loaded with old API, false if
573  loaded with new
574  */
575  bool wasLoadedWithLegacyAPI() const {
576  return loadedWithLegacyAPI;
577  }
578 
579 private:
580 
581  ComponentInfo* my_info;
582  ComponentInfo* currentlyLoadingSubComponent;
583  ComponentId_t currentlyLoadingSubComponentID;
584  bool isExtension;
585 
586  void addSelfLink(std::string name);
587  Link* getLinkFromParentSharedPort(const std::string& port);
588 
589  using CreateFxn = std::function<StatisticBase*(const std::string&,
590  BaseComponent*,const std::string&, const std::string&, SST::Params&)>;
591 
592  StatisticBase* registerStatisticCore(SST::Params& params,
593  const std::string& statName, const std::string& statSubId,
594  fieldType_t fieldType, CreateFxn&& fxn);
595 
596  Component* getTrueComponentPrivate() const;
597 
598 };
599 
600 
601 /**
602  Used to load SubComponents when multiple SubComponents are loaded
603  into a single slot (will also also work when a single SubComponent
604  is loaded).
605  */
607 
608  BaseComponent* comp;
609  std::string slot_name;
610  int max_slot_index;
611 
612 protected:
613 
614  SubComponent* protected_create(int slot_num, Params& params) const {
615  if ( slot_num > max_slot_index ) return NULL;
616 
617  return comp->loadNamedSubComponent(slot_name, slot_num, params);
618  }
619 
620 
621 
622 
623 public:
625 
626 
627  SubComponentSlotInfo(BaseComponent* comp, std::string slot_name) :
628  comp(comp),
629  slot_name(slot_name)
630  {
631  const std::map<ComponentId_t,ComponentInfo>& subcomps = comp->my_info->getSubComponents();
632 
633  // Look for all subcomponents with the right slot name
634  max_slot_index = -1;
635  for ( auto &ci : subcomps ) {
636  if ( ci.second.getSlotName() == slot_name ) {
637  if ( ci.second.getSlotNum() > static_cast<int>(max_slot_index) ) {
638  max_slot_index = ci.second.getSlotNum();
639  }
640  }
641  }
642  }
643 
644  const std::string& getSlotName() const {
645  return slot_name;
646  };
647 
648  bool isPopulated(int slot_num) const {
649  if ( slot_num > max_slot_index ) return false;
650  if ( comp->my_info->findSubComponent(slot_name,slot_num) == NULL ) return false;
651  return true;
652  }
653 
654  bool isAllPopulated() const {
655  for ( int i = 0; i < max_slot_index; ++i ) {
656  if ( comp->my_info->findSubComponent(slot_name,i) == NULL ) return false;
657  }
658  return true;
659  }
660 
661  int getMaxPopulatedSlotNumber() const {
662  return max_slot_index;
663  }
664 
665 
666  // Create functions that support the legacy API
667 
668  template <typename T>
669  __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.")))
670  T* create(int slot_num, Params& params) const
671  {
672  return private_create<T>(slot_num,params);
673  }
674 
675  template <typename T>
676  __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.")))
677  void createAll(Params& params, std::vector<T*>& vec, bool insertNulls = true) const
678  {
679  return private_createAll<T>(params, vec, insertNulls);
680  }
681 
682  template <typename T>
683  __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.")))
684  void createAll(std::vector<T*>& vec, bool insertNulls = true) const
685  {
686  Params empty;
687  return private_createAll<T>(empty, vec, insertNulls);
688  }
689 
690 
691  // Create functions that support the new API
692 
693  /**
694  Create a user defined subcomponent (defined in input file to
695  SST run). This call will pass SHARE_NONE to the new
696  subcomponent and will not take constructor arguments. If
697  constructor arguments are needed for the API that is being
698  loaded, the full call to create will need to be used
699  create(slot_num, share_flags, args...).
700 
701  @param slot_num Slot index from which to load subcomponent
702 
703  This function supports the new API, but is identical to an
704  existing API call. It will try to load using new API and will
705  fallback to old if unsuccessful.
706  */
707  template <typename T>
708  T* create(int slot_num) const
709  {
710  Params empty;
711  return comp->loadUserSubComponentByIndex<T>(slot_name, slot_num, ComponentInfo::SHARE_NONE);
712  // return private_create<T>(slot_num, empty);
713  }
714 
715 
716  /**
717  Create a user defined subcomponent (defined in input file to SST
718  run).
719 
720  @param slot_num Slot index from which to load subcomponent
721  @param share_flags Share flags to be used by subcomponent
722  @param args Arguments to be passed to constructor. This
723  signature is defined in the API definition
724 
725  For ease in backward compatibility to old API, this call will
726  try to load using new API and will fallback to old if
727  unsuccessful.
728  */
729  template <class T, class... ARGS>
730  T* create(int slot_num, uint64_t share_flags, ARGS... args) const {
731  return comp->loadUserSubComponentByIndex<T,ARGS...>(slot_name,slot_num, share_flags, args...);
732  }
733 
734 
735  /**
736  Create all user defined subcomponents (defined in input file to SST
737  run) for the slot.
738 
739  @param vec Vector of T* that will hold the pointers to the new
740  subcomponents. If an index is not occupied, a nullptr will be
741  put in it's place. All components will be added to the end of
742  the vector, so index N will be at vec.length() + N, where
743  vec.length() is the length of the vector when it is passed to
744  the call.
745  @param share_flags Share flags to be used by subcomponent
746  @param args Arguments to be passed to constructor. This
747  signature is defined in the API definition
748 
749  For ease in backward compatibility to old API, this call will
750  try to load using new API and will fallback to old if
751  unsuccessful.
752  */
753  template <typename T, class... ARGS>
754  void createAll(std::vector<T*>& vec, uint64_t share_flags, ARGS... args) const {
755  for ( int i = 0; i <= getMaxPopulatedSlotNumber(); ++i ) {
756  T* sub = create<T>(i, share_flags, args...);
757  vec.push_back(sub);
758  }
759  }
760 
761  /**
762  Create all user defined subcomponents (defined in input file to SST
763  run) for the slot.
764 
765  @param vec Vector of pair<int,T*> that will hold the pointers
766  to the new subcomponents. The int will hold the index from
767  which the subcomponent wass loaded. Unoccupied indexes will be
768  skipped. All components will be added to the end of the
769  vector.
770  @param share_flags Share flags to be used by subcomponent
771  @param args Arguments to be passed to constructor. This
772  signature is defined in the API definition
773 
774  For ease in backward compatibility to old API, this call will
775  try to load using new API and will fallback to old if
776  unsuccessful.
777  */
778  template <typename T, class... ARGS>
779  void createAllSparse(std::vector<std::pair<int,T*> >& vec, uint64_t share_flags, ARGS... args) const {
780  for ( int i = 0; i <= getMaxPopulatedSlotNumber(); ++i ) {
781  T* sub = create<T>(i, share_flags, args...);
782  if ( sub != nullptr ) vec.push_back(i,sub);
783  }
784  }
785 
786  /**
787  Create all user defined subcomponents (defined in input file to SST
788  run) for the slot.
789 
790  @param vec Vector of T* that will hold the pointers
791  to the new subcomponents. Unoccupied indexes will be
792  skipped. All components will be added to the end of the
793  vector.
794  @param share_flags Share flags to be used by subcomponent
795  @param args Arguments to be passed to constructor. This
796  signature is defined in the API definition
797 
798  For ease in backward compatibility to old API, this call will
799  try to load using new API and will fallback to old if
800  unsuccessful.
801  */
802  template <typename T, class... ARGS>
803  void createAllSparse(std::vector<T*>& vec, uint64_t share_flags, ARGS... args) const {
804  for ( int i = 0; i <= getMaxPopulatedSlotNumber(); ++i ) {
805  T* sub = create<T>(i, share_flags, args...);
806  if ( sub != nullptr ) vec.push_back(sub);
807  }
808  }
809 
810 private:
811 
812  // Extra versions of the calls supporting the legacy API to avoid
813  // deprecation warnings in every file that include this file
814  template <typename T>
815  T* private_create(int slot_num, Params& params) const
816  {
817  SubComponent* sub = protected_create(slot_num, params);
818  if ( sub == NULL ) {
819  // Nothing populated at this index, simply return NULL
820  return NULL;
821  }
822  T* cast_sub = dynamic_cast<T*>(sub);
823  if ( cast_sub == NULL ) {
824  // SubComponent not castable to the correct class,
825  // fatal
826  Simulation::getSimulationOutput().fatal(CALL_INFO,1,"Attempt to load SubComponent into slot "
827  "%s, index %d, which is not castable to correct time\n",
828  getSlotName().c_str(),slot_num);
829  }
830  return cast_sub;
831  }
832 
833  template <typename T>
834  void private_createAll(Params& params, std::vector<T*>& vec, bool insertNulls = true) const
835  {
836  for ( int i = 0; i <= getMaxPopulatedSlotNumber(); ++i ) {
837  T* sub = create<T>(i, params);
838  if ( sub != NULL || insertNulls ) vec.push_back(sub);
839  }
840  }
841 
842 };
843 
844 
845 
846 } //namespace SST
847 
848 #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:730
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:803
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:754
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:379
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:511
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:430
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:779
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:358
Definition: componentInfo.h:36
Used to load SubComponents when multiple SubComponents are loaded into a single slot (will also also ...
Definition: baseComponent.h:606
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:708
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:527
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 * loadUserSubComponent(std::string slot_name)
Loads a user defined subcomponent (defined in input file to SST run).
Definition: baseComponent.h:412
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