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