SST  11.1.0
StructuralSimulationToolkit
simulation_impl.h
1 // -*- c++ -*-
2 
3 // Copyright 2009-2021 NTESS. Under the terms
4 // of Contract DE-NA0003525 with NTESS, the U.S.
5 // Government retains certain rights in this software.
6 //
7 // Copyright (c) 2009-2021, NTESS
8 // All rights reserved.
9 //
10 // This file is part of the SST software package. For license
11 // information, see the LICENSE file in the top level directory of the
12 // distribution.
13 
14 #ifndef SST_CORE_SIMULATION_IMPL_H
15 #define SST_CORE_SIMULATION_IMPL_H
16 
17 #include "sst/core/clock.h"
18 #include "sst/core/componentInfo.h"
19 #include "sst/core/oneshot.h"
20 #include "sst/core/output.h"
21 #include "sst/core/rankInfo.h"
22 #include "sst/core/simulation.h"
23 #include "sst/core/sst_types.h"
24 #include "sst/core/unitAlgebra.h"
25 
26 #include <atomic>
27 #include <iostream>
28 #include <signal.h>
29 #include <thread>
30 #include <unordered_map>
31 
32 /* Forward declare for Friendship */
33 extern int main(int argc, char** argv);
34 
35 namespace SST {
36 
37 #define _SIM_DBG(fmt, args...) __DBG(DBG_SIM, Sim, fmt, ##args)
38 #define STATALLFLAG "--ALLSTATS--"
39 
40 class Activity;
41 class Component;
42 class Config;
43 class ConfigGraph;
44 class Exit;
45 class Factory;
46 class SimulatorHeartbeat;
47 class Link;
48 class LinkMap;
49 class Params;
50 class SharedRegionManager;
51 class SimulatorHeartbeat;
52 class SyncBase;
53 class SyncManager;
54 class ThreadSync;
55 class TimeConverter;
56 class TimeLord;
57 class TimeVortex;
58 class UnitAlgebra;
59 class SharedRegionManager;
60 namespace Statistics {
61 class StatisticOutput;
62 class StatisticProcessingEngine;
63 } // namespace Statistics
64 
65 namespace Statistics {
66 class StatisticOutput;
67 class StatisticProcessingEngine;
68 } // namespace Statistics
69 
70 /**
71  * Main control class for a SST Simulation.
72  * Provides base features for managing the simulation
73  */
75 {
76 
77 public:
78  /******** Public API inherited from Simulation ********/
79  /** Get the run mode of the simulation (e.g. init, run, both etc) */
80  Mode_t getSimulationMode() const override { return runMode; };
81 
82  /** Return the current simulation time as a cycle count*/
83  SimTime_t getCurrentSimCycle() const override;
84 
85  /** Return the end simulation time as a cycle count*/
86  SimTime_t getEndSimCycle() const override;
87 
88  /** Return the current priority */
89  int getCurrentPriority() const override;
90 
91  /** Return the elapsed simulation time as a time */
92  UnitAlgebra getElapsedSimTime() const override;
93 
94  /** Return the end simulation time as a time */
95  UnitAlgebra getFinalSimTime() const override;
96 
97  /** Get this instance's parallel rank */
98  RankInfo getRank() const override { return my_rank; }
99 
100  /** Get the number of parallel ranks in the simulation */
101  RankInfo getNumRanks() const override { return num_ranks; }
102 
103  /**
104  Returns the output directory of the simulation
105  @return Directory in which simulation outputs are placed
106  */
107  std::string& getOutputDirectory() override { return output_directory; }
108 
109  /** Signifies that an event type is required for this simulation
110  * Causes the Factory to verify that the required event type can be found.
111  * @param name fully qualified libraryName.EventName
112  */
113  virtual void requireEvent(const std::string& name) override;
114 
115  /** Causes the current status of the simulation to be printed to stderr.
116  * @param fullStatus - if true, call printStatus() on all components as well
117  * as print the base Simulation's status
118  */
119  virtual void printStatus(bool fullStatus) override;
120 
121  virtual double getRunPhaseElapsedRealTime() const override;
122  virtual double getInitPhaseElapsedRealTime() const override;
123  virtual double getCompletePhaseElapsedRealTime() const override;
124 
125  /******** End Public API from Simulation ********/
126 
127  typedef std::map<std::pair<SimTime_t, int>, Clock*> clockMap_t; /*!< Map of times to clocks */
128  typedef std::map<std::pair<SimTime_t, int>, OneShot*> oneShotMap_t; /*!< Map of times to OneShots */
129 
130  ~Simulation_impl();
131 
132  /********* Static Core-only Functions *********/
133 
134  /** Return a pointer to the singleton instance of the Simulation */
135  static Simulation_impl* getSimulation() { return instanceMap.at(std::this_thread::get_id()); }
136 
137  /** Return the TimeLord associated with this Simulation */
138  static TimeLord* getTimeLord(void) { return &timeLord; }
139 
140  /** Return the base simulation Output class instance */
141  static Output& getSimulationOutput() { return sim_output; }
142 
143  /** Create new simulation
144  * @param config - Configuration of the simulation
145  * @param my_rank - Parallel Rank of this simulation object
146  * @param num_ranks - How many Ranks are in the simulation
147  */
148  static Simulation_impl* createSimulation(Config* config, RankInfo my_rank, RankInfo num_ranks);
149 
150  /**
151  * Used to signify the end of simulation. Cleans up any existing Simulation Objects
152  */
153  static void shutdown();
154 
155  /** Sets an internal flag for signaling the simulation. Used internally */
156  static void setSignal(int signal);
157 
158  /** Insert an activity to fire at a specified time */
159  void insertActivity(SimTime_t time, Activity* ev);
160 
161  /** Return the exit event */
162  Exit* getExit() const { return m_exit; }
163 
164  /******** Core only API *************/
165 
166  /** Processes the ConfigGraph to pull out any need information
167  * about relationships among the threads
168  */
169  void processGraphInfo(ConfigGraph& graph, const RankInfo& myRank, SimTime_t min_part);
170 
171  int prepareLinks(ConfigGraph& graph, const RankInfo& myRank, SimTime_t min_part);
172  int performWireUp(ConfigGraph& graph, const RankInfo& myRank, SimTime_t min_part);
173 
174  /** Set cycle count, which, if reached, will cause the simulation to halt. */
175  void setStopAtCycle(Config* cfg);
176 
177  /** Perform the init() phase of simulation */
178  void initialize();
179 
180  /** Perform the complete() phase of simulation */
181  void complete();
182 
183  /** Perform the setup() and run phases of the simulation. */
184  void setup();
185 
186  void run();
187 
188  void finish();
189 
190  bool isIndependentThread() { return independent; }
191 
192  /** Register a OneShot event to be called after a time delay
193  Note: OneShot cannot be canceled, and will always callback after
194  the timedelay.
195  */
196  TimeConverter* registerOneShot(const std::string& timeDelay, OneShot::HandlerBase* handler, int priority);
197 
198  TimeConverter* registerOneShot(const UnitAlgebra& timeDelay, OneShot::HandlerBase* handler, int priority);
199 
200  const std::vector<SimTime_t>& getInterThreadLatencies() const { return interThreadLatencies; }
201 
202  SimTime_t getInterThreadMinLatency() const { return interThreadMinLatency; }
203 
204  static TimeConverter* getMinPartTC() { return minPartTC; }
205 
206  LinkMap* getComponentLinkMap(ComponentId_t id) const
207  {
208  ComponentInfo* info = compInfoMap.getByID(id);
209  if ( nullptr == info ) { return nullptr; }
210  else {
211  return info->getLinkMap();
212  }
213  }
214 
215  /** Returns reference to the Component Info Map */
216  const ComponentInfoMap& getComponentInfoMap(void) { return compInfoMap; }
217 
218  /** returns the component with the given ID */
219  BaseComponent* getComponent(const ComponentId_t& id) const
220  {
221  ComponentInfo* i = compInfoMap.getByID(id);
222  // CompInfoMap_t::const_iterator i = compInfoMap.find(id);
223  if ( nullptr != i ) { return i->getComponent(); }
224  else {
225  printf("Simulation::getComponent() couldn't find component with id = %" PRIu64 "\n", id);
226  exit(1);
227  }
228  }
229 
230  /** returns the ComponentInfo object for the given ID */
231  ComponentInfo* getComponentInfo(const ComponentId_t& id) const
232  {
233  ComponentInfo* i = compInfoMap.getByID(id);
234  // CompInfoMap_t::const_iterator i = compInfoMap.find(id);
235  if ( nullptr != i ) { return i; }
236  else {
237  printf("Simulation::getComponentInfo() couldn't find component with id = %" PRIu64 "\n", id);
238  exit(1);
239  }
240  }
241 
242  /**
243  Set the output directory for this simulation
244  @param outDir Path of directory to place simulation outputs in
245  */
246  void setOutputDirectory(const std::string& outDir) { output_directory = outDir; }
247 
248  /**
249  * Gets the minimum next activity time across all TimeVortices in
250  * the Rank
251  */
252  static SimTime_t getLocalMinimumNextActivityTime();
253 
254  /**
255  * Returns true when the Wireup is finished.
256  */
257  bool isWireUpFinished() { return wireUpFinished; }
258 
259  uint64_t getTimeVortexMaxDepth() const;
260 
261  uint64_t getTimeVortexCurrentDepth() const;
262 
263  uint64_t getSyncQueueDataSize() const;
264 
265  /******** API provided through BaseComponent only ***********/
266 
267  /** Register a handler to be called on a set frequency */
268  TimeConverter* registerClock(const std::string& freq, Clock::HandlerBase* handler, int priority);
269 
270  TimeConverter* registerClock(const UnitAlgebra& freq, Clock::HandlerBase* handler, int priority);
271 
272  TimeConverter* registerClock(TimeConverter* tcFreq, Clock::HandlerBase* handler, int priority);
273 
274  /** Remove a clock handler from the list of active clock handlers */
275  void unregisterClock(TimeConverter* tc, Clock::HandlerBase* handler, int priority);
276 
277  /** Reactivate an existing clock and handler.
278  * @return time when handler will next fire
279  */
280  Cycle_t reregisterClock(TimeConverter* tc, Clock::HandlerBase* handler, int priority);
281 
282  /** Returns the next Cycle that the TImeConverter would fire. */
283  Cycle_t getNextClockCycle(TimeConverter* tc, int priority = CLOCKPRIORITY);
284 
285  /** Return the Statistic Processing Engine associated with this Simulation */
287 
288  // private:
289 
290  friend class Link;
291  friend class Action;
292  friend class Output;
293  // To enable main to set up globals
294  friend int ::main(int argc, char** argv);
295 
296  // Simulation_impl() {}
297  Simulation_impl(Config* config, RankInfo my_rank, RankInfo num_ranks);
298  Simulation_impl(Simulation_impl const&); // Don't Implement
299  void operator=(Simulation_impl const&); // Don't implement
300 
301  /** Get a handle to a TimeConverter
302  * @param cycles Frequency which is the base of the TimeConverter
303  */
304  TimeConverter* minPartToTC(SimTime_t cycles) const;
305 
306  /** Factory used to generate the simulation components */
307  static Factory* factory;
308 
309  static void resizeBarriers(uint32_t nthr);
310  static Core::ThreadSafe::Barrier initBarrier;
311  static Core::ThreadSafe::Barrier completeBarrier;
312  static Core::ThreadSafe::Barrier setupBarrier;
313  static Core::ThreadSafe::Barrier runBarrier;
314  static Core::ThreadSafe::Barrier exitBarrier;
315  static Core::ThreadSafe::Barrier finishBarrier;
316  static std::mutex simulationMutex;
317 
318  static std::map<LinkId_t, Link*> cross_thread_links;
319  bool direct_interthread;
320 
321  Component* createComponent(ComponentId_t id, const std::string& name, Params& params);
322 
323  TimeVortex* getTimeVortex() const { return timeVortex; }
324 
325  /** Emergency Shutdown
326  * Called when a SIGINT or SIGTERM has been seen
327  */
328  static void emergencyShutdown();
329  /** Normal Shutdown
330  */
331  void endSimulation(void);
332  void endSimulation(SimTime_t end);
333 
334  typedef enum {
335  SHUTDOWN_CLEAN, /* Normal shutdown */
336  SHUTDOWN_SIGNAL, /* SIGINT or SIGTERM received */
337  SHUTDOWN_EMERGENCY, /* emergencyShutdown() called */
338  } ShutdownMode_t;
339 
340  friend class SyncManager;
341 
342  TimeVortex* timeVortex;
343  TimeConverter* threadMinPartTC;
344  Activity* current_activity;
345  static SimTime_t minPart;
346  static TimeConverter* minPartTC;
347  std::vector<SimTime_t> interThreadLatencies;
348  SimTime_t interThreadMinLatency;
349  SyncManager* syncManager;
350  // ThreadSync* threadSync;
351  ComponentInfoMap compInfoMap;
352  clockMap_t clockMap;
353  oneShotMap_t oneShotMap;
354  static Exit* m_exit;
355  SimulatorHeartbeat* m_heartbeat;
356  bool endSim;
357  bool independent; // true if no links leave thread (i.e. no syncs required)
358  static std::atomic<int> untimed_msg_count;
359  unsigned int untimed_phase;
360  volatile sig_atomic_t lastRecvdSignal;
361  ShutdownMode_t shutdown_mode;
362  bool wireUpFinished;
363 
364  /** TimeLord of the simulation */
366  /** Output */
368 
369  Mode_t runMode;
370  SimTime_t currentSimCycle;
371  SimTime_t endSimCycle;
372  int currentPriority;
373  RankInfo my_rank;
374  RankInfo num_ranks;
375 
376  std::string output_directory;
377  static SharedRegionManager* sharedRegionManager;
378 
379  double run_phase_start_time;
380  double run_phase_total_time;
381  double init_phase_start_time;
382  double init_phase_total_time;
383  double complete_phase_start_time;
384  double complete_phase_total_time;
385 
386  static std::unordered_map<std::thread::id, Simulation_impl*> instanceMap;
387  static std::vector<Simulation_impl*> instanceVec;
388 
389  friend void wait_my_turn_start();
390  friend void wait_my_turn_end();
391 
392 private:
393  /**
394  * Returns the time of the next item to be executed
395  * that is in the TImeVortex of the Simulation
396  */
397  SimTime_t getNextActivityTime() const;
398 };
399 
400 // Function to allow for easy serialization of threads while debugging
401 // code. Can only be used when you can guarantee all threads will be
402 // taking the same code path. If you can't guarantee that, then use a
403 // spinlock to make sure only one person is in a given region at a
404 // time. ONLY FOR DEBUG USE.
405 void wait_my_turn_start(Core::ThreadSafe::Barrier& barrier, int thread, int total_threads);
406 
407 void wait_my_turn_end(Core::ThreadSafe::Barrier& barrier, int thread, int total_threads);
408 
409 } // namespace SST
410 
411 #endif // SST_CORE_SIMULATION_IMPL_H
Output object provides consistent method for outputting data to stdout, stderr and/or sst debug file...
Definition: output.h:51
An Action is a schedulable Activity which is not an Event.
Definition: action.h:26
Definition: ssthandler.h:100
SimTime_t getCurrentSimCycle() const override
Return the current simulation time as a cycle count.
Definition: simulation.cc:77
virtual double getCompletePhaseElapsedRealTime() const override
Get the amount of real-time spent executing the complete phase of the simulation. ...
Definition: simulation.cc:817
ComponentInfo * getComponentInfo(const ComponentId_t &id) const
returns the ComponentInfo object for the given ID
Definition: simulation_impl.h:231
Main control class for a SST Simulation.
Definition: simulation.h:35
Base class for all Activities in the SST Event Queue.
Definition: activity.h:48
Mode_t getSimulationMode() const override
Get the run mode of the simulation (e.g.
Definition: simulation_impl.h:80
Class to contain SST Simulation Configuration variables.
Definition: config.h:29
TimeConverter * registerOneShot(const std::string &timeDelay, OneShot::HandlerBase *handler, int priority)
Register a OneShot event to be called after a time delay Note: OneShot cannot be canceled, and will always callback after the timedelay.
Definition: simulation.cc:889
void insertActivity(SimTime_t time, Activity *ev)
Insert an activity to fire at a specified time.
Definition: simulation.cc:915
A class to convert between a component&#39;s view of time and the core&#39;s view of time.
Definition: timeConverter.h:26
RankInfo getRank() const override
Get this instance&#39;s parallel rank.
Definition: simulation_impl.h:98
Main component object for the simulation.
Definition: component.h:30
A Configuration Graph A graph representing Components and Links.
Definition: configGraph.h:375
Primary Event Queue.
Definition: timeVortex.h:25
static Output sim_output
Output.
Definition: simulation_impl.h:367
bool isWireUpFinished()
Returns true when the Wireup is finished.
Definition: simulation_impl.h:257
void setOutputDirectory(const std::string &outDir)
Set the output directory for this simulation.
Definition: simulation_impl.h:246
static Output & getSimulationOutput()
Return the base simulation Output class instance.
Definition: simulation_impl.h:141
void setup()
Perform the setup() and run phases of the simulation.
Definition: simulation.cc:602
SSTHandlerBaseNoArgs< void, false > HandlerBase
Base handler for OneShot callbacks.
Definition: oneshot.h:38
const ComponentInfoMap & getComponentInfoMap(void)
Returns reference to the Component Info Map.
Definition: simulation_impl.h:216
void initialize()
Perform the init() phase of simulation.
Definition: simulation.cc:511
Exit Event Action.
Definition: exit.h:33
Definition: componentInfo.h:249
Exit * getExit() const
Return the exit event.
Definition: simulation_impl.h:162
BaseComponent * getComponent(const ComponentId_t &id) const
returns the component with the given ID
Definition: simulation_impl.h:219
virtual void printStatus(bool fullStatus) override
Causes the current status of the simulation to be printed to stderr.
Definition: simulation.cc:782
int getCurrentPriority() const override
Return the current priority.
Definition: simulation.cc:89
static Simulation_impl * createSimulation(Config *config, RankInfo my_rank, RankInfo num_ranks)
Create new simulation.
Definition: simulation.cc:159
A Clock class.
Definition: clock.h:32
static void setSignal(int signal)
Sets an internal flag for signaling the simulation.
Definition: simulation.cc:775
Cycle_t reregisterClock(TimeConverter *tc, Clock::HandlerBase *handler, int priority)
Reactivate an existing clock and handler.
Definition: simulation.cc:855
RankInfo getNumRanks() const override
Get the number of parallel ranks in the simulation.
Definition: simulation_impl.h:101
Statistics::StatisticProcessingEngine * getStatisticsProcessingEngine(void) const
Return the Statistic Processing Engine associated with this Simulation.
Definition: simulation.cc:940
static TimeLord * getTimeLord(void)
Return the TimeLord associated with this Simulation.
Definition: simulation_impl.h:138
virtual double getInitPhaseElapsedRealTime() const override
Get the amount of real-time spent executing the init phase of the simulation.
Definition: simulation.cc:807
std::map< std::pair< SimTime_t, int >, OneShot * > oneShotMap_t
Definition: simulation_impl.h:128
virtual double getRunPhaseElapsedRealTime() const override
Get the amount of real-time spent executing the run phase of the simulation.
Definition: simulation.cc:797
static SimTime_t getLocalMinimumNextActivityTime()
Gets the minimum next activity time across all TimeVortices in the Rank.
Definition: simulation.cc:251
void unregisterClock(TimeConverter *tc, Clock::HandlerBase *handler, int priority)
Remove a clock handler from the list of active clock handlers.
Definition: simulation.cc:879
Main control class for a SST Simulation.
Definition: simulation_impl.h:74
Definition: rankInfo.h:21
TimeConverter * minPartToTC(SimTime_t cycles) const
Get a handle to a TimeConverter.
Definition: simulation.cc:111
Main component object for the simulation.
Definition: baseComponent.h:51
static Simulation_impl * getSimulation()
Return a pointer to the singleton instance of the Simulation.
Definition: simulation_impl.h:135
UnitAlgebra getElapsedSimTime() const override
Return the elapsed simulation time as a time.
Definition: simulation.cc:95
void complete()
Perform the complete() phase of simulation.
Definition: simulation.cc:566
static Factory * factory
Factory used to generate the simulation components.
Definition: simulation_impl.h:307
std::string & getOutputDirectory() override
Returns the output directory of the simulation.
Definition: simulation_impl.h:107
Cycle_t getNextClockCycle(TimeConverter *tc, int priority=CLOCKPRIORITY)
Returns the next Cycle that the TImeConverter would fire.
Definition: simulation.cc:867
A OneShot Event class.
Definition: oneshot.h:32
static void emergencyShutdown()
Emergency Shutdown Called when a SIGINT or SIGTERM has been seen.
Definition: simulation.cc:706
static TimeLord timeLord
TimeLord of the simulation.
Definition: simulation_impl.h:365
Parameter store.
Definition: params.h:43
void endSimulation(void)
Normal Shutdown.
Definition: simulation.cc:724
void setStopAtCycle(Config *cfg)
Set cycle count, which, if reached, will cause the simulation to halt.
Definition: simulation.cc:222
Class for creating and managing TimeConverter objects.
Definition: timeLord.h:37
Class for instantiating Components, Links and the like out of element libraries.
Definition: factory.h:42
TimeConverter * registerClock(const std::string &freq, Clock::HandlerBase *handler, int priority)
Register a handler to be called on a set frequency.
Definition: simulation.cc:827
virtual void requireEvent(const std::string &name) override
Signifies that an event type is required for this simulation Causes the Factory to verify that the re...
Definition: simulation.cc:239
Definition: componentInfo.h:39
void processGraphInfo(ConfigGraph &graph, const RankInfo &myRank, SimTime_t min_part)
Processes the ConfigGraph to pull out any need information about relationships among the threads...
Definition: simulation.cc:262
An SST core component that handles timing and event processing informing all registered Statistics to...
Definition: statengine.h:51
Mode_t
Type of Run Modes.
Definition: simulation.h:39
UnitAlgebra getFinalSimTime() const override
Return the end simulation time as a time.
Definition: simulation.cc:101
std::map< std::pair< SimTime_t, int >, Clock * > clockMap_t
Definition: simulation_impl.h:127
SimTime_t getEndSimCycle() const override
Return the end simulation time as a cycle count.
Definition: simulation.cc:83
Performs Unit math in full precision.
Definition: unitAlgebra.h:106
Definition: threadsafe.h:47
static void shutdown()
Used to signify the end of simulation.
Definition: simulation.cc:172
Definition: sharedRegion.h:63