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