SST 16.0.0
Structural Simulation Toolkit
baseComponent.h
1// Copyright 2009-2026 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-2026, 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/clock.h"
16#include "sst/core/componentInfo.h"
17#include "sst/core/eli/elementinfo.h"
18#include "sst/core/event.h"
19#include "sst/core/factory.h"
20#include "sst/core/portModule.h"
21#include "sst/core/profile/componentProfileTool.h"
22#include "sst/core/serialization/serializable_base.h"
23#include "sst/core/serialization/serialize.h"
24#include "sst/core/sst_types.h"
25#include "sst/core/statapi/statbase.h"
26#include "sst/core/statapi/statengine.h"
27#include "sst/core/timeConverter.h"
28#include "sst/core/warnmacros.h"
29
30#include <cstdarg>
31#include <cstdint>
32#include <functional>
33#include <map>
34#include <set>
35#include <string>
36#include <type_traits>
37#include <utility>
38#include <vector>
39
40using namespace SST::Statistics;
41
42namespace SST {
43
44class Component;
46class Clock;
47class Link;
48class LinkMap;
49class Module;
50class Params;
51class Simulation;
52class Simulation;
53class SubComponent;
55class TimeConverter;
56class UnitAlgebra;
57class WatchPoint;
58
59namespace Core::Serialization::pvt {
61}
62
63/**
64 * Main component object for the simulation.
65 */
67{
68
69 friend class Component;
70 friend class ComponentExtension;
71 friend class ComponentInfo;
72 friend class SubComponent;
73 friend class SubComponentSlotInfo;
74 friend class PortModule;
75
76protected:
77 using StatCreateFunction = std::function<Statistics::StatisticBase*(BaseComponent*,
78 Statistics::StatisticProcessingEngine*, const std::string& /*name*/, const std::string& /*sub_id*/, Params&)>;
79
80 BaseComponent() = default; // For serialization only
81
82public:
83 explicit BaseComponent(ComponentId_t id);
84 virtual ~BaseComponent();
85
86 BaseComponent(const BaseComponent&) = delete;
87 BaseComponent& operator=(const BaseComponent&) = delete;
88
89 /**
90 Gets the ELI type for this BaseComponent
91
92 @return ELI type as a string
93 */
94 const std::string& getType() const { return my_info_->getType(); }
95
96 /**
97 Get the unique component ID
98
99 @return ID of BaseComponent
100 */
101 inline ComponentId_t getId() const { return my_info_->id_; }
102
103 /**
104 Get the BaseComponent Statistic load level
105
106 @return Statistic load level of BaseComponent
107 */
108 inline uint8_t getStatisticLoadLevel() const { return my_info_->statLoadLevel; }
109
110 /**
111 Called when SIGINT or SIGTERM has been seen. Allows components opportunity to clean up external state.
112 */
113 virtual void emergencyShutdown() {}
114
115 /**
116 Get the name of the BaseComponent
117
118 @return BaseComponent's name
119 */
120 inline const std::string& getName() const { return my_info_->getName(); }
121
122 /**
123 Get the name of the parent Component for the Component tree. If called on a Component, returns the name of that
124 Component.
125
126 @return The name of the parent Component for the Component tree.
127 */
128 inline const std::string& getParentComponentName() const { return my_info_->getParentComponentName(); }
129
130 /**
131 Used during the init phase. The method will be called each phase of initialization. Initialization ends when no
132 components have sent any data.
133
134 @param phase Current phase number
135 */
136 virtual void init(unsigned int UNUSED(phase)) {}
137
138 /**
139 Used during the complete phase after the end of simulation. The method will be called each phase of
140 complete. Complete phase ends when no components have sent any data.
141
142 @param phase Current phase number
143 */
144 virtual void complete(unsigned int UNUSED(phase)) {}
145
146 /**
147 Called after all components have been constructed and initialization has completed, but before simulation time
148 has begun.
149 */
150 virtual void setup() {}
151
152 /**
153 Called after complete phase, but before objects are destroyed. A good place to print out statistics.
154 */
155 virtual void finish() {}
156
157 /** Currently unused function */
158 virtual bool Status() { return 0; }
159
160 /**
161 Called by the Simulation to request that the component print its current status. Useful for debugging.
162
163 @param out The Output class which should be used to print component status.
164 */
165 virtual void printStatus(Output& UNUSED(out)) {}
166
167 /**
168 Get the core timebase
169
170 @return Core timebase set at the beginning of the simulation. Returned as a UnitAlgebra
171 */
173
174 /**
175 Get the current simulation time as a cycle count
176
177 @return Current simulation cycle for the simulation
178 */
179 SimTime_t getCurrentSimCycle() const;
180
181 /**
182 Get the current priority
183
184 @return Current priority for the simulation
185 */
186 int getCurrentPriority() const;
187
188 /**
189 get the elapsed simulation time as a UnitAlgebra
190
191 @return Time in seconds as a UnitAlgebra
192 */
194
195 /**
196 Get the end simulation time as a cycle count
197
198 @return End simulation time as cycle count
199 */
200 SimTime_t getEndSimCycle() const;
201
202 /**
203 Get the end simulation time as a UnitAlgebra
204
205 @return End time in seconds as a UnitAlgebra
206 */
208
209 /**
210 Get this instance's parallel rank
211
212 @return Get the rank for this objects partition
213 */
214 RankInfo getRank() const;
215
216 /**
217 Get the number of parallel ranks in the simulation
218
219 @return Number of ranks in simulation
220 */
221 RankInfo getNumRanks() const;
222
223 /**
224 Get the default simulation Output class instance. Elements do not have to use this Output object and can create
225 their own to use instead.
226
227 @return Default Output object for this partition
228 */
229 static Output& getSimulationOutput();
230
231 /**
232 Return the simulated time since the simulation began in the default timebase
233
234 @return Current simulation time in units of the default timebase for the object
235 */
236 inline SimTime_t getCurrentSimTime() const { return getCurrentSimTime(my_info_->defaultTimeBase); }
237
238 /**
239 Get the simulated time since the simulation began in units specified by
240 the parameter.
241
242 @param tc TimeConverter specifying the units
243
244 @return Current time as a cycle count based on the provided timebase
245 */
246 SimTime_t getCurrentSimTime(TimeConverter base) const;
247
248 /**
249 Return the simulated time since the simulation began in the specified timebase.
250
251 NOTE: This version of getCurrentSimTime() can accept a timebase that is not normally representable because it is
252 smaller than the global timebase set by the user. If this happens, the underlying code will use UnitAlgebra to
253 compute the cycle count. Because UnitAlgebra is computationally intense, it is best to avoid this case during
254 the run loop of the simulation.
255
256 @param base Timebase frequency in SI Units
257
258 @return Current time as a cycle count based on the provided timebase
259
260 */
261 SimTime_t getCurrentSimTime(const std::string& base) const;
262
263 /**
264 Return the simulated time since the simulation began in the specified timebase
265
266 NOTE: This version of getCurrentSimTime() exists because both std::string and TimeConverter can be implicitly
267 created with a const char*. Having this implementation removes ambiguity and ensures that a const char* is
268 passed through the std::string version, which can accept timebases that are not representable with TimeConverter
269 due to being smaller than the global timebase.
270
271 @param base Timebase frequency in SI Units
272
273 @return Current time as a cycle count based on the provided timebase
274 */
275 SimTime_t getCurrentSimTime(const char* base) const { return getCurrentSimTime(std::string(base)); }
276
277 /**
278 Utility function to return the time since the simulation began in nanoseconds
279
280 @return Current time as a count of nanoseconds expired in the simulation
281 */
282 SimTime_t getCurrentSimTimeNano() const;
283
284 /**
285 Utility function to return the time since the simulation began in microseconds
286
287 @return Current time as a count of microseconds expired in the simulation
288 */
289 SimTime_t getCurrentSimTimeMicro() const;
290
291 /**
292 Utility function to return the time since the simulation began in milliseconds
293
294 @return Current time as a count of milliseconds expired in the simulation
295 */
296 SimTime_t getCurrentSimTimeMilli() const;
297
298 /**
299 Get the amount of real-time spent executing the run phase of the simulation.
300
301 @return Real time in seconds spent executing the run phase
302 */
303 double getRunPhaseElapsedRealTime() const;
304
305 /**
306 Get the amount of real-time spent executing the init phase of the simulation.
307
308 @return Real time in seconds spent executing the init phase
309 */
310 double getInitPhaseElapsedRealTime() const;
311
312 /**
313 Get the amount of real-time spent executing the complete phase of the simulation.
314
315 @return Real time in seconds spent executing the complete phase
316 */
317 double getCompletePhaseElapsedRealTime() const;
318
319
320 /**
321 Add a watch point to all handlers in the Component Tree
322 */
323 void addWatchPoint(WatchPoint* pt);
324
325 /**
326 Remove a watch point from all handlers in the Component Tree
327 */
329
330
331private:
332 /**
333 Recursively add Watch point to myself and all my children
334 */
335 void addWatchPointRecursive(WatchPoint* pt);
336
337 /**
338 Recursively removes a Watch point from myself and all my children
339 */
340 void removeWatchPointRecursive(WatchPoint* pt);
341
342protected:
343 /**
344 Check to see if the run mode was set to INIT
345
346 @return True if simulation run mode is set to INIT
347 */
348 bool isSimulationRunModeInit() const;
349
350 /**
351 Check to see if the run mode was set to RUN
352
353 @return True if simulation run mode is set to RUN
354 */
355 bool isSimulationRunModeRun() const;
356
357 /**
358 Check to see if the run mode was set to BOTH
359
360 @return True if simulation run mode is set to BOTH
361 */
362 bool isSimulationRunModeBoth() const;
363
364 /**
365 Returns the output directory of the simulation
366
367 @return Directory in which simulation outputs should be placed. Returns empty string if output directory not
368 set by user.
369 */
370 std::string& getOutputDirectory() const;
371
372 /**
373 Signifies that a library is required for this simulation. Causes the Factory to verify that the required library
374 is loaded.
375
376 NOTE: This function should rarely be required, as most dependencies are automatically detected in the simulator
377 core. However, if the component uses an event from another library that is not wholly defined in a header file,
378 this call may be required to ensure that all the code from the event is loaded. Similarly, if you use a class
379 from another library that does not have ELI information, this call may also be required to make sure all
380 dependencies are loaded.
381
382 @param name Name of library this BaseComponent depends on
383 */
384 void requireLibrary(const std::string& name);
385
386
387 /**
388 Determine if a port name is connected to any links
389
390 @param name Name of the port
391
392 @return True if port is connected, false otherwise
393 */
394 bool isPortConnected(const std::string& name) const;
395
396 /**
397 Configure a Link
398
399 @param name Port Name on which the link to configure is attached.
400
401 @param timebase Timebase of the link provided as either a std::string, SST::UnitAlgebra, or
402 SST::TimeConverter
403
404 @param handler Optional Handler to be called when an Event is received
405
406 @return A pointer to the configured link, or nullptr if an error occurred.
407 */
408 Link* configureLink(const std::string& name, TimeConverter timebase, Event::HandlerBase* handler = nullptr)
409 {
410 return configureLink_impl(name, timebase.getFactor(), handler);
411 }
412
413 /**
414 Configure a Link
415
416 @param name Port Name on which the link to configure is attached.
417
418 @param handler Optional Handler to be called when an Event is received
419
420 @return A pointer to the configured link, or nullptr if an error occurred.
421 */
422 Link* configureLink(const std::string& name, Event::HandlerBase* handler = nullptr);
423
424 /**
425 Configure a SelfLink (Loopback link)
426
427 @param name Name of the self-link port
428
429 @param timebase Timebase of the link. Timebase can be a std::string, SST::UnitAlgebra or SST::TimeConverter
430
431 @param handler Optional Handler to be called when an Event is received
432
433 @return A pointer to the configured link, or nullptr if an error occurred.
434 */
435 Link* configureSelfLink(const std::string& name, TimeConverter timebase, Event::HandlerBase* handler = nullptr)
436 {
437 addSelfLink(name);
438 return configureLink(name, timebase, handler);
439 }
440
441
442 /**
443 Configure a SelfLink (Loopback link) that uses the (Sub)Component's defaultTimeBase
444
445 @param name Name of the self-link port
446
447 @param handler Optional Handler to be called when an Event is received
448
449 @return A pointer to the configured link, or nullptr if an error occurred.
450 */
451 Link* configureSelfLink(const std::string& name, Event::HandlerBase* handler = nullptr);
452
453
454 /**
455 Registers a clock for this component.
456
457 @param tc TimeConverter object specifying the clock frequency. May be specified as a TimeConverter, std::string
458 or UnitAlgebra
459
460 @param handler Pointer to Clock::HandlerBase which is to be invoked at the specified interval
461
462 @param reg_all Should this clock period be used as the default timebase for all of the links connected to this
463 component
464
465 @return The TimeConverter object representing the clock frequency
466 */
467 TimeConverter registerClock(TimeConverter tc, Clock::HandlerBase* handler, bool reg_all = true);
468
469 /**
470 Removes a clock handler from the component
471
472 NOTE: This operation needs to search the list until it finds the specified handler, which can be a slow operation
473 for long lists. Consider using the return value from the clock handler to control whether a handler is removed
474 from the list or not.
475
476 @param tc TimeConverter representing the period of the clock
477
478 @param handler Handler to remove from the list
479 */
481
482 /**
483 Reactivates an existing Clock and Handler
484
485 @return Time of next time clock handler will fire
486
487 Note: If called after the simulation run loop (e.g., in finish() or complete()), will return the next time of the
488 clock past when the simulation ended. There can be a small lag between simulation end and detection of simulation
489 end during which clocks can run a few extra cycles. As a result, the return value just prior to simulation end
490 may be greater than the value returned after simulation end.
491 */
492 Cycle_t reregisterClock(TimeConverter freq, Clock::HandlerBase* handler);
493
494 /**
495 Returns the next Cycle that the TimeConverter would fire. If called prior to the simulation run loop, next Cycle
496 is 0. If called after the simulation run loop completes (e.g., during complete() or finish()), next Cycle is one
497 past the end time of the simulation. See Note in reregisterClock() for additional guidance when calling this
498 function after simulation ends.
499
500 @param freq Frequency of the clock
501
502 @return Cycle count that will be passed into the next call to this clock's handler functions
503 */
504 Cycle_t getNextClockCycle(TimeConverter freq);
505
506 /**
507 Registers a default timebase for the component and optionally
508 sets the the component's links to that timebase. Useful for
509 components which do not have a clock, but would like a default
510 timebase.
511
512 @param base Frequency for the clock in SI units
513
514 @param reg_all Should this clock period be used as the default timebase for all of the links connected to this
515 component
516 */
517 TimeConverter registerTimeBase(const std::string& base, bool reg_all = true);
518
519 TimeConverter getTimeConverter(const std::string& base) const;
520 TimeConverter getTimeConverter(const UnitAlgebra& base) const;
521
522 bool isStatisticShared(const std::string& stat_name, bool include_me = false)
523 {
524 if ( include_me ) {
525 if ( getStatisticValidityAndLevel(stat_name) != 255 ) {
526 return true;
527 }
528 }
529 if ( my_info_->sharesStatistics() ) {
530 return my_info_->parent_info->component->isStatisticShared(stat_name, true);
531 }
532 else {
533 return false;
534 }
535 }
536
537 /**
538 Tell the simulation object to initiate interactive mode (if currently turned on)
539
540 @param msg Message to print when interactive mode is entered
541 */
542 void initiateInteractive(const std::string& msg);
543
544private:
545 ImplementSerializable(SST::BaseComponent)
546 void serialize_order(SST::Core::Serialization::serializer& ser) override;
547
548
549 /**
550 Handles the profile points, default timebase, handler tracking and checkpointing.
551
552 @param tc TimeConverter representing the period of the clock
553
554 @param handler Handler to add to the list
555
556 @param reg_all Should this clock period be used as the default timebase for all of the links connected to this
557 component
558 */
559 void registerClock_impl(TimeConverter tc, Clock::HandlerBase* handler, bool reg_all);
560
561 /**
562 Handles default timebase setup
563
564 @param name Name of the port on which to configure the link
565
566 @param timebase Default timebase for the Link
567
568 @param handler Handler to call on event delivery. If no handler is provided, this will be a polling link
569 */
570 Link* configureLink_impl(const std::string& name, SimTime_t timebase, Event::HandlerBase* handler = nullptr);
571
572 /**
573 Helper function used to create an enabled statistic. For explicitly-enabled statistics, this must be called on
574 the parent component. For enable-all, it can be called on the enabling component.
575
576 @param cpp_params Any parameters given in C++ specific to this statistic
577
578 @param name The name (different from type) for this statistic
579
580 @param stat_sub_id An optional sub ID for this statistic to differentiate instances of the same stat
581
582 @return The statistic created
583 */
584 template <typename T>
585 Statistics::Statistic<T>* createStatistic(
586 SST::Params& params, StatisticId_t id, const std::string& name, const std::string& stat_sub_id)
587 {
588 /* I would prefer to avoid this std::function with dynamic cast,
589 * but the code is just a lot cleaner and avoids many unnecessary template instantiations
590 * doing it this way. At some point in the future, we would need to clean up
591 * the rule around enabling all statistics to make this better
592 *
593 * Even if we moved the logic around, we'd still have to dyncast anything coming out of
594 * the stat data structures.
595 */
596 StatCreateFunction create = [=](BaseComponent* comp, Statistics::StatisticProcessingEngine* engine,
597 const std::string& name, const std::string& sub_id,
598 SST::Params& params) -> Statistics::StatisticBase* {
599 return engine->createStatistic<T>(comp, name, sub_id, params);
600 };
601
602 // We follow two distinct paths depending on if it is enable all, versus explicitly enabled
603 // Enable all is "scoped" to the (sub)component
604 // Explicitly enabled stats are assigned component-unique IDs and can be shared across subcomponents
605 // so creation and management happens in the parent component
606 Statistics::StatisticBase* base_stat =
607 id == STATALL_ID ? createEnabledAllStatistic(params, name, stat_sub_id, std::move(create))
608 : getParentComponent()->createExplicitlyEnabledStatistic(
609 params, id, name, stat_sub_id, std::move(create));
610
611 // Ugh, dynamic casts hurt my eyes, but I must do this
612 auto* statistic = dynamic_cast<Statistics::Statistic<T>*>(base_stat);
613 if ( statistic ) {
614 return statistic;
615 }
616 else {
617 fatal(__LINE__, __FILE__, "createStatistic", 1, "failed to cast created statistic '%s' to expected type",
618 name.c_str());
619 }
620 }
621
622 /**
623 Internal registration function for statistics. Determines if a statistic is enabled or not.
624 It first locates the component that should "own" the stat based on both ELI and statistic enable parameters.
625 If enabled, it calls createStatistic<T> on the owning component.
626 If disabled, it returns a disabled statistic from the statistic engine.
627 */
628 template <typename T>
629 Statistics::Statistic<T>* registerStatistic_impl(
630 SST::Params& params, const std::string& stat_name, const std::string& stat_sub_id, uint8_t level = 255)
631 {
632 if ( level == 255 ) { // Stat has not yet been found in ELI, search this component's ELI
633 level = getStatisticValidityAndLevel(stat_name);
634 }
635
636 if ( level == 255 ) {
637 // If level is still 255, stat has not been found in any ELI yet, need to check if parent shares their ELI
638 if ( my_info_->parent_info && my_info_->sharesStatistics() ) {
639 return my_info_->parent_info->component->registerStatistic_impl<T>(params, stat_name, stat_sub_id);
640 }
641 else {
642 // not a valid stat and I won't be able to share my parent's statistic
643 fatal(__LINE__, __FILE__, "registerStatistic", 1,
644 "attempting to register a statistic '%s' that is not found in ELI", stat_name.c_str());
645 }
646 }
647
648 // Path 1: Explicitly enabled statistic
649 if ( my_info_->enabled_stat_names_ ) {
650 auto iter = my_info_->enabled_stat_names_->find(stat_name);
651 if ( iter != my_info_->enabled_stat_names_->end() ) {
652 // valid, enabled statistic
653 // During initialization, the component should have assigned a mapping between
654 // the local name and globally unique stat ID
655 StatisticId_t id = iter->second;
656 return getParentComponent()->createStatistic<T>(params, id, stat_name, stat_sub_id);
657 }
658 }
659
660 // Path 2: Enabled all statistic
661 if ( my_info_->enabled_all_stats_ ) { // I enabled this stat and it is valid
662 if ( level > getStatisticLoadLevel() ) {
663 return getStatEngine()->createDisabledStatistic<T>();
664 }
665 return createStatistic<T>(params, STATALL_ID, stat_name, stat_sub_id);
666 }
667 else if ( my_info_->parent_info && my_info_->canInsertStatistics() ) {
668 // I did not enable all but my parent may have and will accept my statistics
669 return my_info_->parent_info->component->registerStatistic_impl<T>(params, stat_name, stat_sub_id, level);
670 }
671 else {
672 // Not enabled
673 return getStatEngine()->createDisabledStatistic<T>();
674 }
675 }
676
677protected:
678 /**
679 Registers a statistic.
680
681 If Statistic is allowed to run (controlled by Python runtime parameters), then a statistic will be created and
682 returned. If not allowed to run, then a NullStatistic will be returned. In either case, the returned value
683 should be used for all future Statistic calls. The type of Statistic and the Collection Rate is set by Python
684 runtime parameters. If no type is defined, then an Accumulator Statistic will be provided by default. If rate
685 set to 0 or not provided, then the statistic will output results only at end of sim (if output is enabled).
686
687 @param params Parameter set to be passed to the statistic constructor.
688
689 @param stat_name Primary name of the statistic. This name must match the defined ElementInfoStatistic in the
690 component, and must also be enabled in the Python input file.
691
692 @param stat_sub_id An additional sub name for the statistic
693
694 @return Either a created statistic of desired type or a NullStatistic depending upon runtime settings.
695 */
696 template <typename T>
698 SST::Params& params, const std::string& stat_name, const std::string& stat_sub_id = "")
699 {
700 return registerStatistic_impl<T>(params, stat_name, stat_sub_id);
701 }
702
703 template <typename T>
704 Statistics::Statistic<T>* registerStatistic(const std::string& stat_name, const std::string& stat_sub_id = "")
705 {
706 SST::Params empty {};
707 return registerStatistic_impl<T>(empty, stat_name, stat_sub_id);
708 }
709
710 template <typename... Args>
711 Statistics::Statistic<std::tuple<Args...>>* registerMultiStatistic(
712 const std::string& stat_name, const std::string& stat_sub_id = "")
713 {
714 SST::Params empty {};
715 return registerStatistic_impl<std::tuple<Args...>>(empty, stat_name, stat_sub_id);
716 }
717
718 template <typename... Args>
719 Statistics::Statistic<std::tuple<Args...>>* registerMultiStatistic(
720 SST::Params& params, const std::string& stat_name, const std::string& stat_sub_id = "")
721 {
722 return registerStatistic_impl<std::tuple<Args...>>(params, stat_name, stat_sub_id);
723 }
724
725 template <typename T>
726 Statistics::Statistic<T>* registerStatistic(const char* stat_name, const char* stat_sub_id = "")
727 {
728 return registerStatistic<T>(std::string(stat_name), std::string(stat_sub_id));
729 }
730
731 /**
732 Called by the Components and Subcomponent to perform a statistic Output.
733
734 @param stat Pointer to the statistic.
735 */
736 void performStatisticOutput(Statistics::StatisticBase* stat);
737
738 /**
739 Performs a global statistic Output.
740
741 This routine will force ALL Components and Subcomponents to output their statistic information. This may lead to
742 unexpected results if the statistic counts or data is reset on output.
743
744 NOTE: Currently, this function will only output statistics that are on the same rank.
745 */
747
748 /**
749 Registers a profiling point.
750
751 This function will register a profiling point.
752
753 @param point_name Name of point to register
754
755 @return Either a pointer to a created T::ProfilePoint or nullptr if not enabled.
756 */
757 template <typename T>
758 typename T::ProfilePoint* registerProfilePoint(const std::string& point_name)
759 {
760 std::string full_point_name = getType() + "." + point_name;
761 auto tools = getComponentProfileTools(full_point_name);
762 if ( tools.size() == 0 ) return nullptr;
763
764 typename T::ProfilePoint* ret = new typename T::ProfilePoint();
765 for ( auto* x : tools ) {
766 T* tool = dynamic_cast<T*>(x);
767 if ( nullptr == tool ) {
768 // Not the right type, fatal
769 fatal(CALL_INFO_LONG, 1, "ERROR: wrong type of profiling tool for profiling point %s)\n",
770 point_name.c_str());
771 }
772 ret->registerProfilePoint(tool, point_name, getId(), getName(), getType());
773 }
774 return ret;
775 }
776
777 /**
778 Loads a module from an element Library
779
780 @param type Fully Qualified library.moduleName
781
782 @param params Parameters the module should use for configuration
783
784 @return Handle to new instance of module, or nullptr on failure.
785 */
786 template <class T, class... ARGS>
787 T* loadModule(const std::string& type, Params& params, ARGS... args)
788 {
789 // Check to see if this can be loaded with new API or if we have to fallback to old
790 return Factory::getFactory()->CreateWithParams<T>(type, params, params, args...);
791 }
792
793protected:
794 // When you direct load, the ComponentExtension does not need any
795 // ELI information and if it has any, it will be ignored. The
796 // extension will be loaded as if it were part of the parent
797 // BaseComponent and will share all that components ELI
798 // information.
799 template <class T, class... ARGS>
800 T* loadComponentExtension(ARGS... args)
801 {
802 ComponentExtension* ret = new T(my_info_->id_, args...);
803 return static_cast<T*>(ret);
804 }
805
806 /**
807 Check to see if a given element type is loadable with a particular API
808
809 @param name Name of element to check in lib.name format
810
811 @return True if loadable as the API specified as the template parameter
812 */
813 template <class T>
814 bool isSubComponentLoadableUsingAPI(const std::string& type)
815 {
816 return Factory::getFactory()->isSubComponentLoadableUsingAPI<T>(type);
817 }
818
819 /**
820 Check to see if the element type loaded by the user into the.
821 specified slot is loadable with a particular API. This will
822 only check slot index 0. If you need to check other slots,
823 please use the SubComponentSlotInfo.
824
825 @param slot_name Name of slot to check
826
827 @return True if loadable as the API specified as the template parameter
828 */
829 template <class T>
830 bool isUserSubComponentLoadableUsingAPI(const std::string& slot_name)
831 {
832 // Get list of ComponentInfo objects and make sure that there is
833 // only one SubComponent put into this slot
834 // const std::vector<ComponentInfo>& subcomps = my_info_->getSubComponents();
835 const std::map<ComponentId_t, ComponentInfo>& subcomps = my_info_->getSubComponents();
836 int sub_count = 0;
837 int index = -1;
838 for ( auto& ci : subcomps ) {
839 if ( ci.second.getSlotName() == slot_name ) {
840 index = ci.second.getSlotNum();
841 sub_count++;
842 }
843 }
844
845 if ( sub_count > 1 ) {
846 SST::Output outXX("SubComponentSlotWarning: ", 0, 0, Output::STDERR);
847 outXX.fatal(CALL_INFO, 1,
848 "Error: ComponentSlot \"%s\" in component \"%s\" only allows for one SubComponent, %d provided.\n",
849 slot_name.c_str(), my_info_->getType().c_str(), sub_count);
850 }
851
852 return isUserSubComponentLoadableUsingAPIByIndex<T>(slot_name, index);
853 }
854
855 /**
856 Loads an anonymous subcomponent (not defined in input file to SST run).
857
858 @param type type of subcomponent to load in lib.name format
859
860 @param slot_name name of the slot to load subcomponent into
861
862 @param slot_num index of the slot to load subcomponent into
863
864 @param share_flags Share flags to be used by subcomponent
865
866 @param params Params object to be passed to subcomponent
867
868 @param args Arguments to be passed to constructor. This signature is defined in the API definition
869
870 For ease in backward compatibility to old API, this call will try to load using new API and will fallback to old
871 if unsuccessful.
872 */
873 template <class T, class... ARGS>
874 T* loadAnonymousSubComponent(const std::string& type, const std::string& slot_name, int slot_num,
875 uint64_t share_flags, Params& params, ARGS... args)
876 {
877
878 share_flags = share_flags & ComponentInfo::USER_FLAGS;
879 ComponentId_t cid = my_info_->addAnonymousSubComponent(my_info_, type, slot_name, slot_num, share_flags);
880 ComponentInfo* sub_info = my_info_->findSubComponent(cid);
881
882 // This shouldn't happen since we just put it in, but just in case
883 if ( sub_info == nullptr ) return nullptr;
884
885 // Check to see if this can be loaded with new API or if we have to fallback to old
887 auto ret = Factory::getFactory()->CreateWithParams<T>(type, params, sub_info->id_, params, args...);
888 return ret;
889 }
890 return nullptr;
891 }
892
893 /**
894 Loads a user defined subcomponent (defined in input file to SST run). This version does not allow share flags
895 (set to SHARE_NONE) or constructor arguments.
896
897 @param slot_name name of the slot to load subcomponent into
898
899 For ease in backward compatibility to old API, this call will try to load using new API and will fallback to old
900 if unsuccessful.
901 */
902 template <class T>
903 T* loadUserSubComponent(const std::string& slot_name)
904 {
905 return loadUserSubComponent<T>(slot_name, ComponentInfo::SHARE_NONE);
906 }
907
908 /**
909 Loads a user defined subcomponent (defined in input file to SST
910 run).
911
912 @param slot_name name of the slot to load subcomponent into
913
914 @param share_flags Share flags to be used by subcomponent
915
916 @param args Arguments to be passed to constructor. This signature is defined in the API definition
917
918 For ease in backward compatibility to old API, this call will try to load using new API and will fallback to old
919 if unsuccessful.
920 */
921 template <class T, class... ARGS>
922 T* loadUserSubComponent(const std::string& slot_name, uint64_t share_flags, ARGS... args)
923 {
924
925 // Get list of ComponentInfo objects and make sure that there is
926 // only one SubComponent put into this slot
927 // const std::vector<ComponentInfo>& subcomps = my_info_->getSubComponents();
928 const std::map<ComponentId_t, ComponentInfo>& subcomps = my_info_->getSubComponents();
929 int sub_count = 0;
930 int index = -1;
931 for ( auto& ci : subcomps ) {
932 if ( ci.second.getSlotName() == slot_name ) {
933 index = ci.second.getSlotNum();
934 sub_count++;
935 }
936 }
937
938 if ( sub_count > 1 ) {
939 SST::Output outXX("SubComponentSlotWarning: ", 0, 0, Output::STDERR);
940 outXX.fatal(CALL_INFO, 1,
941 "Error: ComponentSlot \"%s\" in component \"%s\" only allows for one SubComponent, %d provided.\n",
942 slot_name.c_str(), my_info_->getType().c_str(), sub_count);
943 }
944
945 return loadUserSubComponentByIndex<T, ARGS...>(slot_name, index, share_flags, args...);
946 }
947
948 /**
949 Convenience function for reporting fatal conditions. The function will create a new Output object and call
950 fatal() using the supplied parameters. Before calling Output::fatal(), the function will also print other
951 information about the (sub)component that called fatal and about the simulation state.
952
953 From Output::fatal: Message will be sent to the output location and to stderr. The output will be prepended with
954 the expanded prefix set in the object.
955
956 NOTE: fatal() will call MPI_Abort(exit_code) to terminate simulation.
957
958 @param line Line number of calling function (use CALL_INFO macro)
959
960 @param file File name calling function (use CALL_INFO macro)
961
962 @param func Function name calling function (use CALL_INFO macro)
963
964 @param exit_code The exit code used for termination of simulation. will be passed to MPI_Abort()
965
966 @param format Format string. All valid formats for printf are available.
967
968 @param ... Arguments for format.
969 */
970 [[noreturn]]
971 void fatal(uint32_t line, const char* file, const char* func, int exit_code, const char* format, ...) const
972 __attribute__((format(printf, 6, 7)));
973
974 /**
975 Convenience function for testing for and reporting fatal conditions. If the condition holds, fatal() will be
976 called, otherwise, the function will return. The function will create a new Output object and call fatal() using
977 the supplied parameters. Before calling Output::fatal(), the function will also print other information about
978 the (sub)component that called fatal and about the simulation state.
979
980 From Output::fatal: Message will be sent to the output location and to stderr. The output will be prepended with
981 the expanded prefix set in the object. NOTE: fatal() will call MPI_Abort(exit_code) to terminate simulation.
982
983
984 @param condition on which to call fatal(); fatal() is called if the bool is false.
985
986 @param line Line number of calling function (use CALL_INFO macro)
987
988 @param file File name calling function (use CALL_INFO macro)
989
990 @param func Function name calling function (use CALL_INFO macro)
991
992 @param exit_code The exit code used for termination of simulation. will be passed to MPI_Abort()
993
994 @param format Format string. All valid formats for printf are available.
995
996 @param ... Arguments for format.
997 */
998 void sst_assert(bool condition, uint32_t line, const char* file, const char* func, int exit_code,
999 const char* format, ...) const __attribute__((format(printf, 7, 8)));
1000
1001private:
1002 SimTime_t processCurrentTimeWithUnderflowedBase(const std::string& base) const;
1003
1004 /**
1005 findExplicitlyEnabledStatistic
1006
1007 @param params
1008
1009 @param id
1010
1011 @param name
1012
1013 @param stat_sub_id
1014
1015 @return That matching stat if the stat already was created for the given ID, otherwise nullptr
1016 */
1017 Statistics::StatisticBase* createExplicitlyEnabledStatistic(SST::Params& params, StatisticId_t id,
1018 const std::string& name, const std::string& stat_sub_id, StatCreateFunction create);
1019
1020 Statistics::StatisticBase* createEnabledAllStatistic(
1021 SST::Params& params, const std::string& name, const std::string& stat_sub_id, StatCreateFunction create);
1022
1023 void setDefaultTimeBaseForLinks(TimeConverter tc);
1024
1025 void pushValidParams(Params& params, const std::string& type);
1026
1027 template <class T, class... ARGS>
1028 T* loadUserSubComponentByIndex(const std::string& slot_name, int slot_num, int share_flags, ARGS... args)
1029 {
1030
1031 share_flags = share_flags & ComponentInfo::USER_FLAGS;
1032
1033 // Check to see if the slot exists
1034 ComponentInfo* sub_info = my_info_->findSubComponent(slot_name, slot_num);
1035 if ( sub_info == nullptr ) return nullptr;
1036 sub_info->share_flags = share_flags;
1037 sub_info->parent_info = my_info_;
1038
1039 if ( isSubComponentLoadableUsingAPI<T>(sub_info->type) ) {
1040 auto ret = Factory::getFactory()->CreateWithParams<T>(
1041 sub_info->type, *sub_info->params, sub_info->id_, *sub_info->params, args...);
1042 return ret;
1043 }
1044 return nullptr;
1045 }
1046
1047 template <class T>
1048 bool isUserSubComponentLoadableUsingAPIByIndex(const std::string& slot_name, int slot_num)
1049 {
1050 // Check to see if the slot exists
1051 ComponentInfo* sub_info = my_info_->findSubComponent(slot_name, slot_num);
1052 if ( sub_info == nullptr ) return false;
1053
1054 return isSubComponentLoadableUsingAPI<T>(sub_info->type);
1055 }
1056
1057 // Utility function used by fatal and sst_assert
1058 [[noreturn]]
1059 void vfatal(uint32_t line, const char* file, const char* func, int exit_code, const char* format, va_list arg) const
1060 __attribute__((format(printf, 6, 0)));
1061
1062 // Get the statengine from Simulation
1063 StatisticProcessingEngine* getStatEngine();
1064
1065public:
1066 SubComponentSlotInfo* getSubComponentSlotInfo(const std::string& name, bool fatalOnEmptyIndex = false);
1067
1068 /**
1069 Retrieve the X,Y,Z coordinates of this component
1070 */
1071 const std::vector<double>& getCoordinates() const { return my_info_->coordinates; }
1072
1073protected:
1075 friend class SST::Statistics::StatisticBase;
1076
1077 bool isAnonymous() { return my_info_->isAnonymous(); }
1078
1079 bool isUser() { return my_info_->isUser(); }
1080
1081 /**
1082 Manually set the default defaultTimeBase
1083 */
1084 void setDefaultTimeBase(TimeConverter tc) { my_info_->defaultTimeBase = tc; }
1085
1086 TimeConverter getDefaultTimeBase() { return my_info_->defaultTimeBase; }
1087 const TimeConverter getDefaultTimeBase() const { return my_info_->defaultTimeBase; }
1088
1089 bool doesSubComponentExist(const std::string& type);
1090
1091 // Does the statisticName exist in the ElementInfoStatistic and if so, what is its enable level
1092 uint8_t getStatisticValidityAndLevel(const std::string& statisticName) const;
1093
1094 std::vector<Profile::ComponentProfileTool*> getComponentProfileTools(const std::string& point);
1095
1096 /**** Primary Component API ****/
1097
1098 /**
1099 Register as a primary component, which allows the component to specify when it is and is not OK to end
1100 simulation. The simulator will not end simulation through use of the Exit object while any primary component has
1101 specified primaryComponentDoNotEndSim(). However, it is still possible for Actions other than Exit to end
1102 simulation. Once all primary components have specified primaryComponentOKToEndSim(), the Exit object will
1103 trigger and end simulation.
1104
1105 This must be called during simulation wireup (i.e during the constructor for the component), or a fatal error
1106 will occur.
1107
1108 If no component registers as a primary component, then the Exit object will not be used for that simulation and
1109 simulation termination must be accomplished through some other mechanism (e.g. --stopAt flag, or some other
1110 Action object).
1111
1112 @sa BaseComponent::primaryComponentDoNotEndSim()
1113 @sa BaseComponent::primaryComponentOKToEndSim()
1114 */
1116
1117 /**
1118 Tells the simulation that it should not exit. The component will remain in this state until a call to
1119 primaryComponentOKToEndSim(). A component may reenter the DoNotEndSime state by calling this function after
1120 calling primaryComponentOKToEndSim(), in which case, another call to primaryComponentOKToEndSim() will need to be
1121 called to end the simulation.
1122
1123 Calls to this function when already in the DoNotEndSime state, will be functionally ignored, but will generate a
1124 warning if verbose is turned on.
1125
1126 Calls to this function on non-primary components will be ignored and will generate a warning if verbose is turned
1127 on.
1128
1129 @sa BaseComponent::registerAsPrimaryComponent()
1130 @sa BaseComponent::primaryComponentOKToEndSim()
1131 */
1133
1134 /**
1135 Tells the simulation that it is now OK to end simulation. Simulation will not end until all primary components
1136 that have called primaryComponentDoNotEndSim() have called this function.
1137
1138 Calls to this function when already in the OKToEndSim state, will be functionally ignored, but will generate a
1139 warning if verbose is turned on.
1140
1141 Calls to this function on non-primary components will be ignored and will generate a warning if verbose is turned
1142 on.
1143
1144 @sa BaseComponent::registerAsPrimaryComponent()
1145 @sa BaseComponent::primaryComponentDoNotEndSim()
1146 */
1148
1149
1150private:
1151 enum class ComponentState : uint8_t {
1152 // Primary States
1153 None = 0,
1154 Primary = 1 << 0,
1155 DoNotEndSim = 1 << 1,
1156 OKToEndSim = 1 << 2,
1157
1158 // Whether this is an extension
1159 Extension = 1 << 3,
1160 };
1161
1162 /**
1163 Check for Primary state
1164
1165 @return True if component_state_ includes Primary, false otherwise
1166 */
1167 bool isStatePrimary()
1168 {
1169 return static_cast<uint8_t>(component_state_) & static_cast<uint8_t>(ComponentState::Primary);
1170 }
1171
1172 /**
1173 Check for DoNotEndSim state. This state is mutually exclusive with OKToEndSim
1174
1175 @return True if component_state_ includes DoNotEndSim, false otherwise
1176 */
1177 bool isStateDoNotEndSim()
1178 {
1179 return static_cast<uint8_t>(component_state_) & static_cast<uint8_t>(ComponentState::DoNotEndSim);
1180 }
1181
1182 /**
1183 Check for OKToEndSim state. This state is mutually exclusive with DoNotEndSim
1184
1185 @return True if component_state_ includes OKToEndSim
1186 */
1187 bool isStateOKToEndSim()
1188 {
1189 return static_cast<uint8_t>(component_state_) & static_cast<uint8_t>(ComponentState::OKToEndSim);
1190 }
1191
1192 /**
1193 Check for Extension state
1194
1195 @return True if component_state_ includes Extension, false otherwise
1196 */
1197 bool isExtension()
1198 {
1199 return static_cast<uint8_t>(component_state_) & static_cast<uint8_t>(ComponentState::Extension);
1200 }
1201
1202
1203 /**
1204 Adds Primary to the component_state_
1205
1206 NOTE: This function does not check to see if the component is in the proper stage of simulation, that check
1207 should be done before calling this function.
1208 */
1209 void setStateAsPrimary()
1210 {
1211 component_state_ = static_cast<ComponentState>(
1212 static_cast<uint8_t>(component_state_) | static_cast<uint8_t>(ComponentState::Primary));
1213 }
1214
1215 /**
1216 Adds DoNotEndSim and removes OKToEndSim to/from the component_state_
1217
1218 NOTE: This function does not check to see if registerAsPrimaryComponent() has been properly called, that check
1219 should be done before calling this function.
1220 */
1221 void setStateDoNotEndSim()
1222 {
1223 component_state_ = static_cast<ComponentState>(
1224 static_cast<uint8_t>(component_state_) | static_cast<uint8_t>(ComponentState::DoNotEndSim));
1225 component_state_ = static_cast<ComponentState>(
1226 static_cast<uint8_t>(component_state_) & ~static_cast<uint8_t>(ComponentState::OKToEndSim));
1227 }
1228
1229 /**
1230 Adds OKToEndSim and removes DoNotEndSim to/from the component_state_
1231
1232 NOTE: This function does not check to see if registerAsPrimaryComponent() has been properly called, that check
1233 should be done before calling this function.
1234 */
1235 void setStateOKToEndSim()
1236 {
1237 component_state_ = static_cast<ComponentState>(
1238 static_cast<uint8_t>(component_state_) | static_cast<uint8_t>(ComponentState::OKToEndSim));
1239 component_state_ = static_cast<ComponentState>(
1240 static_cast<uint8_t>(component_state_) & ~static_cast<uint8_t>(ComponentState::DoNotEndSim));
1241 }
1242
1243 /**
1244 Adds Extension to the component_state_
1245 */
1246 void setAsExtension()
1247 {
1248 component_state_ = static_cast<ComponentState>(
1249 static_cast<uint8_t>(component_state_) | static_cast<uint8_t>(ComponentState::Extension));
1250 }
1251
1252
1253 friend class Core::Serialization::pvt::SerializeBaseComponentHelper;
1254
1255
1256 ComponentInfo* my_info_ = nullptr;
1257 Simulation* sim_ = nullptr;
1258
1259 // component_state_ is initialized as NotPrimary and !Extension
1260 ComponentState component_state_ = ComponentState::None;
1261 // bool isExtension = false;
1262
1263 // Need to track clock handlers for checkpointing. We need to
1264 // know what clock handlers we have registered with the core
1265 std::vector<Clock::HandlerBase*> clock_handlers_;
1266 std::set<SimTime_t> registered_clocks_;
1267
1268 void addSelfLink(const std::string& name);
1269 Link* getLinkFromParentSharedPort(const std::string& port, std::vector<ConfigPortModule>& port_modules);
1270
1271 using StatNameMap = std::map<std::string, std::map<std::string, Statistics::StatisticBase*>>;
1272
1273 ConfigPortModule& getPortModuleConfig(PortModuleId_t);
1274
1275 static thread_local std::pair<ComponentId_t, PortModuleId_t> port_module_id_;
1276
1277 std::vector<PortModule*> port_modules_;
1278
1279 std::map<StatisticId_t, Statistics::StatisticBase*>
1280 explicitly_enabled_shared_stats_; // Lookup structure to determine if an explicitly enabled shared stat has
1281 // already been registered. In this context, a shared stat is one that has
1282 // been piped to a different user-defined name in the config.
1283 std::map<StatisticId_t, StatNameMap>
1284 explicitly_enabled_unique_stats_; // Lookup structure to determine if an explicitly enabled non-shared stat has
1285 // been registered.
1286 StatNameMap enabled_all_stats_;
1287
1288 /**
1289 Get the ultimate parent Component for this BaseComponent. Will return this is caller is a Component
1290 */
1291 BaseComponent* getParentComponent()
1292 {
1293 ComponentInfo* base_info = my_info_;
1294 while ( base_info->parent_info ) {
1295 base_info = base_info->parent_info;
1296 }
1297 return base_info->component;
1298 }
1299};
1300
1301/**
1302 Used to load SubComponents when multiple SubComponents are loaded into a single slot (will also also work when a
1303 single SubComponent is loaded).
1304 */
1305class SubComponentSlotInfo
1306{
1307
1308 BaseComponent* comp;
1309 std::string slot_name;
1310 int max_slot_index;
1311
1312public:
1313 ~SubComponentSlotInfo() {}
1314
1315 SubComponentSlotInfo(BaseComponent* comp, const std::string& slot_name) :
1316 comp(comp),
1317 slot_name(slot_name)
1318 {
1319 const std::map<ComponentId_t, ComponentInfo>& subcomps = comp->my_info_->getSubComponents();
1320
1321 // Look for all subcomponents with the right slot name
1322 max_slot_index = -1;
1323 for ( auto& ci : subcomps ) {
1324 if ( ci.second.getSlotName() == slot_name ) {
1325 if ( ci.second.getSlotNum() > static_cast<int>(max_slot_index) ) {
1326 max_slot_index = ci.second.getSlotNum();
1327 }
1328 }
1329 }
1330 }
1331
1332 const std::string& getSlotName() const { return slot_name; };
1333
1334 bool isPopulated(int slot_num) const
1335 {
1336 if ( slot_num > max_slot_index ) return false;
1337 if ( comp->my_info_->findSubComponent(slot_name, slot_num) == nullptr ) return false;
1338 return true;
1339 }
1340
1341 bool isAllPopulated() const
1342 {
1343 for ( int i = 0; i < max_slot_index; ++i ) {
1344 if ( comp->my_info_->findSubComponent(slot_name, i) == nullptr ) return false;
1345 }
1346 return true;
1347 }
1348
1349 int getMaxPopulatedSlotNumber() const { return max_slot_index; }
1350
1351 /**
1352 Check to see if the element type loaded by the user into the specified slot index is loadable with a particular
1353 API.
1354
1355 @param slot_num Slot index to check
1356
1357 @return True if loadable as the API specified as the template parameter
1358 */
1359 template <class T>
1360 bool isLoadableUsingAPI(int slot_num)
1361 {
1362 return comp->isUserSubComponentLoadableUsingAPIByIndex<T>(slot_name, slot_num);
1363 }
1364
1365 // Create functions that support the new API
1366
1367 /**
1368 Create a user defined subcomponent (defined in input file to SST run). This call will pass SHARE_NONE to the new
1369 subcomponent and will not take constructor arguments. If constructor arguments are needed for the API that is
1370 being loaded, the full call to create will need to be used create(slot_num, share_flags, args...).
1371
1372 @param slot_num Slot index from which to load subcomponent
1373
1374 This function supports the new API, but is identical to an existing API call. It will try to load using new API
1375 and will fallback to old if unsuccessful.
1376 */
1377 template <typename T>
1378 T* create(int slot_num) const
1379 {
1380 Params empty;
1381 return comp->loadUserSubComponentByIndex<T>(slot_name, slot_num, ComponentInfo::SHARE_NONE);
1382 }
1383
1384 /**
1385 Create a user defined subcomponent (defined in input file to SST run).
1386
1387 @param slot_num Slot index from which to load subcomponent
1388
1389 @param share_flags Share flags to be used by subcomponent
1390
1391 @param args Arguments to be passed to constructor. This signature is defined in the API definition
1392
1393 For ease in backward compatibility to old API, this call will try to load using new API and will fallback to old
1394 if unsuccessful.
1395 */
1396 template <class T, class... ARGS>
1397 T* create(int slot_num, uint64_t share_flags, ARGS... args) const
1398 {
1399 return comp->loadUserSubComponentByIndex<T, ARGS...>(slot_name, slot_num, share_flags, args...);
1400 }
1401
1402 /**
1403 Create all user defined subcomponents (defined in input file to SST run) for the slot.
1404
1405 @param vec Vector of T* that will hold the pointers to the new subcomponents. If an index is not occupied, a
1406 nullptr will be put in its place. All components will be added to the end of the vector, so index N will be at
1407 vec.length() + N, where vec.length() is the length of the vector when it is passed to the call.
1408
1409 @param share_flags Share flags to be used by subcomponent
1410
1411 @param args Arguments to be passed to constructor. This signature is defined in the API definition
1412
1413 For ease in backward compatibility to old API, this call will try to load using new API and will fallback to old
1414 if unsuccessful.
1415 */
1416 template <typename T, class... ARGS>
1417 void createAll(std::vector<T*>& vec, uint64_t share_flags, ARGS... args) const
1418 {
1419 for ( int i = 0; i <= getMaxPopulatedSlotNumber(); ++i ) {
1420 T* sub = create<T>(i, share_flags, args...);
1421 vec.push_back(sub);
1422 }
1423 }
1424
1425 /**
1426 Create all user defined subcomponents (defined in input file to SST
1427 run) for the slot.
1428
1429 @param vec Vector of pair<int,T*> that will hold the pointers to the new subcomponents. The int will hold the
1430 index from which the subcomponent was loaded. Unoccupied indexes will be skipped. All components will be added
1431 to the end of the vector.
1432
1433 @param share_flags Share flags to be used by subcomponent
1434
1435 @param args Arguments to be passed to constructor. This signature is defined in the API definition
1436
1437 For ease in backward compatibility to old API, this call will try to load using new API and will fallback to old
1438 if unsuccessful.
1439 */
1440 template <typename T, class... ARGS>
1441 void createAllSparse(std::vector<std::pair<int, T*>>& vec, uint64_t share_flags, ARGS... args) const
1442 {
1443 for ( int i = 0; i <= getMaxPopulatedSlotNumber(); ++i ) {
1444 T* sub = create<T>(i, share_flags, args...);
1445 if ( sub != nullptr ) vec.push_back(i, sub);
1446 }
1447 }
1448
1449 /**
1450 Create all user defined subcomponents (defined in input file to SST run) for the slot.
1451
1452 @param vec Vector of T* that will hold the pointers to the new subcomponents. Unoccupied indexes will be
1453 skipped. All components will be added to the end of the vector.
1454
1455 @param share_flags Share flags to be used by subcomponent
1456
1457 @param args Arguments to be passed to constructor. This signature is defined in the API definition
1458
1459 For ease in backward compatibility to old API, this call will try to load using new API and will fallback to old
1460 if unsuccessful.
1461 */
1462 template <typename T, class... ARGS>
1463 void createAllSparse(std::vector<T*>& vec, uint64_t share_flags, ARGS... args) const
1464 {
1465 for ( int i = 0; i <= getMaxPopulatedSlotNumber(); ++i ) {
1466 T* sub = create<T>(i, share_flags, args...);
1467 if ( sub != nullptr ) vec.push_back(sub);
1468 }
1469 }
1470};
1471
1472namespace Core::Serialization {
1473
1474namespace pvt {
1476{
1477public:
1478 static void size_basecomponent(serializable_base* s, serializer& ser);
1479
1480 static void pack_basecomponent(serializable_base* s, serializer& ser);
1481
1482 static void unpack_basecomponent(serializable_base*& s, serializer& ser);
1483
1484 static void map_basecomponent(serializable_base*& s, serializer& ser, const std::string& name);
1485};
1486
1487} // namespace pvt
1488
1489
1490template <class T>
1491class serialize_impl<T*, std::enable_if_t<std::is_base_of_v<SST::BaseComponent, T>>>
1492{
1493 void operator()(T*& s, serializer& ser, ser_opt_t UNUSED(options))
1494 {
1495 serializable_base* sp = static_cast<serializable_base*>(s);
1496 switch ( ser.mode() ) {
1497 case serializer::SIZER:
1498 pvt::SerializeBaseComponentHelper::size_basecomponent(sp, ser);
1499 break;
1500 case serializer::PACK:
1501 pvt::SerializeBaseComponentHelper::pack_basecomponent(sp, ser);
1502 break;
1503 case serializer::UNPACK:
1504 pvt::SerializeBaseComponentHelper::unpack_basecomponent(sp, ser);
1505 break;
1506 case serializer::MAP:
1507 pvt::SerializeBaseComponentHelper::map_basecomponent(sp, ser, ser.getMapName());
1508 break;
1509 }
1510 s = static_cast<T*>(sp);
1511 }
1512
1513 SST_FRIEND_SERIALIZE();
1514};
1515
1516} // namespace Core::Serialization
1517
1518} // namespace SST
1519
1520#endif // SST_CORE_BASECOMPONENT_H
Main component object for the simulation.
Definition baseComponent.h:67
bool isSimulationRunModeInit() const
Check to see if the run mode was set to INIT.
Definition baseComponent.cc:330
SimTime_t getCurrentSimTimeMilli() const
Utility function to return the time since the simulation began in milliseconds.
Definition baseComponent.cc:211
virtual void complete(unsigned int UNUSED(phase))
Used during the complete phase after the end of simulation.
Definition baseComponent.h:144
void requireLibrary(const std::string &name)
Signifies that a library is required for this simulation.
Definition baseComponent.cc:354
bool isSimulationRunModeRun() const
Check to see if the run mode was set to RUN.
Definition baseComponent.cc:336
void setDefaultTimeBase(TimeConverter tc)
Manually set the default defaultTimeBase.
Definition baseComponent.h:1084
bool isPortConnected(const std::string &name) const
Determine if a port name is connected to any links.
Definition baseComponent.cc:361
void fatal(uint32_t line, const char *file, const char *func, int exit_code, const char *format,...) const
Convenience function for reporting fatal conditions.
Definition baseComponent.cc:660
double getRunPhaseElapsedRealTime() const
Get the amount of real-time spent executing the run phase of the simulation.
Definition baseComponent.cc:220
void removeWatchPoint(WatchPoint *pt)
Remove a watch point from all handlers in the Component Tree.
Definition baseComponent.cc:252
T * loadUserSubComponent(const std::string &slot_name)
Loads a user defined subcomponent (defined in input file to SST run).
Definition baseComponent.h:903
const std::string & getName() const
Get the name of the BaseComponent.
Definition baseComponent.h:120
TimeConverter registerTimeBase(const std::string &base, bool reg_all=true)
Registers a default timebase for the component and optionally sets the the component's links to that ...
Definition baseComponent.cc:410
void registerAsPrimaryComponent()
Register as a primary component, which allows the component to specify when it is and is not OK to en...
Definition baseComponent.cc:870
TimeConverter registerClock(TimeConverter tc, Clock::HandlerBase *handler, bool reg_all=true)
Registers a clock for this component.
Definition baseComponent.cc:382
virtual void setup()
Called after all components have been constructed and initialization has completed,...
Definition baseComponent.h:150
uint8_t getStatisticLoadLevel() const
Get the BaseComponent Statistic load level.
Definition baseComponent.h:108
UnitAlgebra getCoreTimeBase() const
Get the core timebase.
Definition baseComponent.cc:118
Cycle_t reregisterClock(TimeConverter freq, Clock::HandlerBase *handler)
Reactivates an existing Clock and Handler.
Definition baseComponent.cc:396
void initiateInteractive(const std::string &msg)
Tell the simulation object to initiate interactive mode (if currently turned on).
Definition baseComponent.cc:437
std::string & getOutputDirectory() const
Returns the output directory of the simulation.
Definition baseComponent.cc:348
double getCompletePhaseElapsedRealTime() const
Get the amount of real-time spent executing the complete phase of the simulation.
Definition baseComponent.cc:232
void performStatisticOutput(Statistics::StatisticBase *stat)
Called by the Components and Subcomponent to perform a statistic Output.
Definition baseComponent.cc:647
int getCurrentPriority() const
Get the current priority.
Definition baseComponent.cc:130
double getInitPhaseElapsedRealTime() const
Get the amount of real-time spent executing the init phase of the simulation.
Definition baseComponent.cc:226
Link * configureSelfLink(const std::string &name, TimeConverter timebase, Event::HandlerBase *handler=nullptr)
Configure a SelfLink (Loopback link).
Definition baseComponent.h:435
void performGlobalStatisticOutput()
Performs a global statistic Output.
Definition baseComponent.cc:653
bool isSubComponentLoadableUsingAPI(const std::string &type)
Check to see if a given element type is loadable with a particular API.
Definition baseComponent.h:814
const std::vector< double > & getCoordinates() const
Retrieve the X,Y,Z coordinates of this component.
Definition baseComponent.h:1071
const std::string & getParentComponentName() const
Get the name of the parent Component for the Component tree.
Definition baseComponent.h:128
virtual void init(unsigned int UNUSED(phase))
Used during the init phase.
Definition baseComponent.h:136
SimTime_t getCurrentSimTime() const
Return the simulated time since the simulation began in the default timebase.
Definition baseComponent.h:236
UnitAlgebra getElapsedSimTime() const
get the elapsed simulation time as a UnitAlgebra
Definition baseComponent.cc:136
SimTime_t getCurrentSimTimeMicro() const
Utility function to return the time since the simulation began in microseconds.
Definition baseComponent.cc:203
void addWatchPoint(WatchPoint *pt)
Add a watch point to all handlers in the Component Tree.
Definition baseComponent.cc:239
static Output & getSimulationOutput()
Get the default simulation Output class instance.
Definition baseComponent.cc:166
RankInfo getNumRanks() const
Get the number of parallel ranks in the simulation.
Definition baseComponent.cc:160
UnitAlgebra getEndSimTime() const
Get the end simulation time as a UnitAlgebra.
Definition baseComponent.cc:148
void sst_assert(bool condition, uint32_t line, const char *file, const char *func, int exit_code, const char *format,...) const
Convenience function for testing for and reporting fatal conditions.
Definition baseComponent.cc:669
T::ProfilePoint * registerProfilePoint(const std::string &point_name)
Registers a profiling point.
Definition baseComponent.h:758
bool isSimulationRunModeBoth() const
Check to see if the run mode was set to BOTH.
Definition baseComponent.cc:342
RankInfo getRank() const
Get this instance's parallel rank.
Definition baseComponent.cc:154
virtual void emergencyShutdown()
Called when SIGINT or SIGTERM has been seen.
Definition baseComponent.h:113
SimTime_t getCurrentSimTime(const char *base) const
Return the simulated time since the simulation began in the specified timebase.
Definition baseComponent.h:275
void primaryComponentOKToEndSim()
Tells the simulation that it is now OK to end simulation.
Definition baseComponent.cc:909
Statistics::Statistic< T > * registerStatistic(SST::Params &params, const std::string &stat_name, const std::string &stat_sub_id="")
Registers a statistic.
Definition baseComponent.h:697
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:922
const std::string & getType() const
Gets the ELI type for this BaseComponent.
Definition baseComponent.h:94
SimTime_t getCurrentSimTimeNano() const
Utility function to return the time since the simulation began in nanoseconds.
Definition baseComponent.cc:195
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:874
Cycle_t getNextClockCycle(TimeConverter freq)
Returns the next Cycle that the TimeConverter would fire.
Definition baseComponent.cc:403
void primaryComponentDoNotEndSim()
Tells the simulation that it should not exit.
Definition baseComponent.cc:889
ComponentId_t getId() const
Get the unique component ID.
Definition baseComponent.h:101
void unregisterClock(TimeConverter tc, Clock::HandlerBase *handler)
Removes a clock handler from the component.
Definition baseComponent.cc:390
bool isUserSubComponentLoadableUsingAPI(const std::string &slot_name)
Check to see if the element type loaded by the user into the.
Definition baseComponent.h:830
Link * configureLink(const std::string &name, TimeConverter timebase, Event::HandlerBase *handler=nullptr)
Configure a Link.
Definition baseComponent.h:408
virtual void finish()
Called after complete phase, but before objects are destroyed.
Definition baseComponent.h:155
SimTime_t getEndSimCycle() const
Get the end simulation time as a cycle count.
Definition baseComponent.cc:142
virtual bool Status()
Currently unused function.
Definition baseComponent.h:158
SimTime_t getCurrentSimCycle() const
Get the current simulation time as a cycle count.
Definition baseComponent.cc:124
virtual void printStatus(Output &UNUSED(out))
Called by the Simulation to request that the component print its current status.
Definition baseComponent.h:165
T * loadModule(const std::string &type, Params &params, ARGS... args)
Loads a module from an element Library.
Definition baseComponent.h:787
A Clock class.
Definition clock.h:35
SSTHandlerBase< bool, Cycle_t > HandlerBase
Base handler for clock functions.
Definition clock.h:44
ComponentExtension is a class that can be loaded using loadComponentExtension<T>(....
Definition componentExtension.h:29
Definition componentInfo.h:45
Main component object for the simulation.
Definition component.h:32
Definition serializable_base.h:121
Base serialize class.
Definition serialize.h:132
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition serializer.h:43
SSTHandlerBase< void, Event * > HandlerBase
Base handler for event delivery.
Definition event.h:48
Maps port names to the Links that are connected to it.
Definition linkMap.h:30
Module is a tag class used with the loadModule function.
Definition module.h:26
Output object provides consistent method for outputting data to stdout, stderr and/or sst debug file.
Definition output.h:58
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:156
@ STDERR
Definition output.h:65
Parameter store.
Definition params.h:65
Definition rankInfo.h:24
Main control class for a SST Simulation.
Definition simulation.h:121
Forms the base class for statistics gathering within SST.
Definition statbase.h:51
An SST core component that handles timing and event processing informing all registered Statistics to...
Definition statengine.h:55
Forms the template defined base class for statistics gathering within SST.
Definition statbase.h:369
Used to load SubComponents when multiple SubComponents are loaded into a single slot (will also also ...
Definition baseComponent.h:1306
T * create(int slot_num) const
Create a user defined subcomponent (defined in input file to SST run).
Definition baseComponent.h:1378
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:1441
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:1360
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:1417
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:1397
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:1463
SubComponent is a class loadable through the factory which allows dynamic functionality to be added t...
Definition subcomponent.h:29
A class to convert between a component's view of time and the core's view of time.
Definition timeConverter.h:31
SimTime_t getFactor() const
Definition timeConverter.h:91
Performs Unit math in full precision.
Definition unitAlgebra.h:107
Class that can attach to Clock and Event Handlers to monitor the state of variables.
Definition watchPoint.h:28