00001 // Copyright 2009-2015 Sandia Corporation. Under the terms 00002 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. 00003 // Government retains certain rights in this software. 00004 // 00005 // Copyright (c) 2009-2015, Sandia Corporation 00006 // All rights reserved. 00007 // 00008 // This file is part of the SST software package. For license 00009 // information, see the LICENSE file in the top level directory of the 00010 // distribution. 00011 00012 #ifndef SST_CORE_COMPONENT_H 00013 #define SST_CORE_COMPONENT_H 00014 00015 #include <sst/core/sst_types.h> 00016 #include <sst/core/serialization.h> 00017 00018 #include <map> 00019 #include <string> 00020 00021 #include <sst/core/clock.h> 00022 #include <sst/core/oneshot.h> 00023 #include <sst/core/event.h> 00024 //#include <sst/core/params.h> 00025 //#include <sst/core/link.h> 00026 //#include <sst/core/timeConverter.h> 00027 #include "sst/core/simulation.h" 00028 #include "sst/core/unitAlgebra.h" 00029 #include "sst/core/statapi/statbase.h" 00030 00031 using namespace SST::Statistics; 00032 00033 namespace SST { 00034 00035 class Link; 00036 class LinkMap; 00037 class Module; 00038 class Params; 00039 class SubComponent; 00040 class TimeConverter; 00041 class UnitAlgebra; 00042 class SharedRegion; 00043 class SharedRegionMerger; 00044 00045 #define _COMP_DBG( fmt, args...) __DBG( DBG_COMP, Component, fmt, ## args ) 00046 00047 /** 00048 * Main component object for the simulation. 00049 * All models inherit from this. 00050 */ 00051 class Component { 00052 public: 00053 00054 static bool isPortValidForComponent(const std::string& comp_name, const std::string& port_name); 00055 00056 /* Deprecated typedef */ 00057 // typedef Params Params_t; 00058 00059 /** Constructor. Generally only called by the factory class. 00060 @param id Unique component ID 00061 */ 00062 Component( ComponentId_t id ); 00063 virtual ~Component(); 00064 00065 /** Called when SIGINT or SIGTERM has been seen. 00066 * Allows components opportunity to clean up external state. 00067 */ 00068 virtual void emergencyShutdown(void) {} 00069 00070 /** Returns unique component ID */ 00071 inline ComponentId_t getId() const { return id; } 00072 00073 /** Returns component Name */ 00074 /* inline const std::string& getName() const { return name; } */ 00075 inline const std::string& getName() const { return my_info->getName(); } 00076 00077 00078 /** Component's type, set by the factory when the object is created. 00079 It is identical to the configuration string used to create the 00080 component. I.e. the XML "<component id="aFoo"><foo>..." would 00081 set component::type to "foo" */ 00082 /* std::string type; */ 00083 00084 /** Used during the init phase. The method will be called each phase of initialization. 00085 Initialization ends when no components have sent any data. */ 00086 virtual void init(unsigned int phase) {} 00087 /** Called after all components have been constructed and inialization has 00088 completed, but before simulation time has begun. */ 00089 virtual void setup( ) { } 00090 /** Called after simulation completes, but before objects are 00091 destroyed. A good place to print out statistics. */ 00092 virtual void finish( ) { } 00093 00094 /** Currently unused function */ 00095 virtual bool Status( ) { return 0; } 00096 00097 /** 00098 * Called by the Simulation to request that the component 00099 * print it's current status. Useful for debugging. 00100 * @param out The Output class which should be used to print component status. 00101 */ 00102 virtual void printStatus(Output &out) { return; } 00103 00104 /** Determine if a port name is connected to any links */ 00105 bool isPortConnected(const std::string &name) const; 00106 00107 /** Configure a Link 00108 * @param name - Port Name on which the link to configure is attached. 00109 * @param time_base - Time Base of the link 00110 * @param handler - Optional Handler to be called when an Event is received 00111 * @return A pointer to the configured link, or NULL if an error occured. 00112 */ 00113 Link* configureLink( std::string name, TimeConverter* time_base, Event::HandlerBase* handler = NULL); 00114 /** Configure a Link 00115 * @param name - Port Name on which the link to configure is attached. 00116 * @param time_base - Time Base of the link 00117 * @param handler - Optional Handler to be called when an Event is received 00118 * @return A pointer to the configured link, or NULL if an error occured. 00119 */ 00120 Link* configureLink( std::string name, std::string time_base, Event::HandlerBase* handler = NULL); 00121 /** Configure a Link 00122 * @param name - Port Name on which the link to configure is attached. 00123 * @param handler - Optional Handler to be called when an Event is received 00124 * @return A pointer to the configured link, or NULL if an error occured. 00125 */ 00126 Link* configureLink( std::string name, Event::HandlerBase* handler = NULL); 00127 00128 /** Configure a SelfLink (Loopback link) 00129 * @param name - Name of the self-link port 00130 * @param time_base - Time Base of the link 00131 * @param handler - Optional Handler to be called when an Event is received 00132 * @return A pointer to the configured link, or NULL if an error occured. 00133 */ 00134 Link* configureSelfLink( std::string name, TimeConverter* time_base, Event::HandlerBase* handler = NULL); 00135 /** Configure a SelfLink (Loopback link) 00136 * @param name - Name of the self-link port 00137 * @param time_base - Time Base of the link 00138 * @param handler - Optional Handler to be called when an Event is received 00139 * @return A pointer to the configured link, or NULL if an error occured. 00140 */ 00141 Link* configureSelfLink( std::string name, std::string time_base, Event::HandlerBase* handler = NULL); 00142 /** Configure a SelfLink (Loopback link) 00143 * @param name - Name of the self-link port 00144 * @param handler - Optional Handler to be called when an Event is received 00145 * @return A pointer to the configured link, or NULL if an error occured. 00146 */ 00147 Link* configureSelfLink( std::string name, Event::HandlerBase* handler = NULL); 00148 00149 /** Registers a clock for this component. 00150 @param freq Frequency for the clock in SI units 00151 @param handler Pointer to Clock::HandlerBase which is to be invoked 00152 at the specified interval 00153 @param regAll Should this clock perioud be used as the default 00154 time base for all of the links connected to this component 00155 */ 00156 TimeConverter* registerClock( std::string freq, Clock::HandlerBase* handler, 00157 bool regAll = true); 00158 TimeConverter* registerClock( const UnitAlgebra& freq, Clock::HandlerBase* handler, 00159 bool regAll = true); 00160 /** Removes a clock handler from the component */ 00161 void unregisterClock(TimeConverter *tc, Clock::HandlerBase* handler); 00162 00163 /** Reactivates an existing Clock and Handler 00164 * @return time of next time clock handler will fire 00165 */ 00166 Cycle_t reregisterClock(TimeConverter *freq, Clock::HandlerBase* handler); 00167 /** Returns the next Cycle that the TimeConverter would fire */ 00168 Cycle_t getNextClockCycle(TimeConverter *freq); 00169 00170 /** Registers a OneShot event for this component. 00171 Note: OneShot cannot be canceled, and will always callback after 00172 the timedelay. 00173 @param timeDelay Time delay for the OneShot in SI units 00174 @param handler Pointer to OneShot::HandlerBase which is to be invoked 00175 at the specified interval 00176 */ 00177 TimeConverter* registerOneShot( std::string timeDelay, OneShot::HandlerBase* handler); 00178 TimeConverter* registerOneShot( const UnitAlgebra& timeDelay, OneShot::HandlerBase* handler); 00179 00180 /** Registers a default time base for the component and optionally 00181 sets the the component's links to that timebase. Useful for 00182 components which do not have a clock, but would like a default 00183 timebase. 00184 @param base Frequency for the clock in SI units 00185 @param regAll Should this clock perioud be used as the default 00186 time base for all of the links connected to this component 00187 */ 00188 TimeConverter* registerTimeBase( std::string base, bool regAll = true); 00189 00190 TimeConverter* getTimeConverter( const std::string& base ); 00191 TimeConverter* getTimeConverter( const UnitAlgebra& base ); 00192 00193 /** return the time since the simulation began in units specified by 00194 the parameter. 00195 @param tc TimeConverter specificing the units */ 00196 SimTime_t getCurrentSimTime(TimeConverter *tc) const; 00197 /** return the time since the simulation began in the default timebase */ 00198 inline SimTime_t getCurrentSimTime() const{ 00199 return getCurrentSimTime(defaultTimeBase); 00200 } 00201 /** return the time since the simulation began in timebase specified 00202 @param base Timebase frequency in SI Units */ 00203 SimTime_t getCurrentSimTime(std::string base); 00204 00205 /** Utility function to return the time since the simulation began in nanoseconds */ 00206 SimTime_t getCurrentSimTimeNano() const; 00207 /** Utility function to return the time since the simulation began in microseconds */ 00208 SimTime_t getCurrentSimTimeMicro() const; 00209 /** Utility function to return the time since the simulation began in milliseconds */ 00210 SimTime_t getCurrentSimTimeMilli() const; 00211 00212 /** Registers a statistic. 00213 If Statistic is allowed to run (controlled by Python runtime parameters), 00214 then a statistic will be created and returned. If not allowed to run, 00215 then a NullStatistic will be returned. In either case, the returned 00216 value should be used for all future Statistic calls. The type of 00217 Statistic and the Collection Rate is set by Python runtime parameters. 00218 If no type is defined, then an Accumulator Statistic will be provided 00219 by default. If rate set to 0 or not provided, then the statistic will 00220 output results only at end of sim (if output is enabled). 00221 @param statName Primary name of the statistic. This name must match the 00222 defined ElementInfoStatistic in the component, and must also 00223 be enabled in the Python input file. 00224 @param statSubId An additional sub name for the statistic 00225 @return Either a created statistic of desired type or a NullStatistic 00226 depending upon runtime settings. 00227 */ 00228 template <typename T> 00229 Statistic<T>* registerStatisticCore(std::string statName, std::string statSubId = "") 00230 { 00231 // NOTE: Templated Code for implementation of Statistic Registration 00232 // is in the componentregisterstat_impl.h file. This was done 00233 // to avoid code bloat in the .h file. 00234 #include "sst/core/statapi/componentregisterstat_impl.h" 00235 } 00236 00237 template <typename T> 00238 Statistic<T>* registerStatistic(std::string statName, std::string statSubId = "") 00239 { 00240 // // NOTE: Templated Code for implementation of Statistic Registration 00241 // // is in the componentregisterstat_impl.h file. This was done 00242 // // to avoid code bloat in the .h file. 00243 // #include "sst/core/statapi/componentregisterstat_impl.h" 00244 00245 // Verify here that name of the stat is one of the registered 00246 // names of the component's ElementInfoStatistic. 00247 if (false == doesComponentInfoStatisticExist(statName)) { 00248 printf("Error: Statistic %s name %s is not found in ElementInfoStatistic, exiting...\n", 00249 StatisticBase::buildStatisticFullName(getName().c_str(), statName, statSubId).c_str(), 00250 statName.c_str()); 00251 exit(1); 00252 } 00253 return registerStatisticCore<T>(statName, statSubId); 00254 } 00255 00256 template <typename T> 00257 Statistic<T>* registerStatistic(const char* statName, const char* statSubId = "") 00258 { 00259 return registerStatistic<T>(std::string(statName), std::string(statSubId)); 00260 } 00261 00262 /** Register that the simulation should not end until this 00263 component says it is OK to. Calling this function (generally 00264 done in Component::setup() or in component constructor) 00265 increments a global counter. Calls to 00266 Component::unregisterExit() decrements the counter. The 00267 simulation cannot end unless this counter reaches zero, or the 00268 simulation time limit is reached. This counter is synchonized 00269 periodically with the other nodes. 00270 00271 @sa Component::unregisterExit() 00272 */ 00273 bool registerExit(); 00274 00275 /** Indicate permission for the simulation to end. This function is 00276 the mirror of Component::registerExit(). It decrements the 00277 global counter, which, upon reaching zero, indicates that the 00278 simulation can terminate. @sa Component::registerExit() */ 00279 bool unregisterExit(); 00280 00281 /** Register as a primary component, which allows the component to 00282 specifiy when it is and is not OK to end simulation. The 00283 simulator will not end simulation natuarally (through use of 00284 the Exit object) while any primary component has specified 00285 primaryComponentDoNotEndSim(). However, it is still possible 00286 for Actions other than Exit to end simulation. Once all 00287 primary components have specified 00288 primaryComponentOKToEndSim(), the Exit object will trigger and 00289 end simulation. 00290 00291 This must be called during simulation wireup (i.e during the 00292 constructor for the component). By default, the state of the 00293 primary component is set to OKToEndSim. 00294 00295 If no component registers as a primary component, then the 00296 Exit object will not be used for that simulation and 00297 simulation termination must be accomplished through some other 00298 mechanism (e.g. --stopAt flag, or some other Action object). 00299 00300 @sa Component::primaryComponentDoNotEndSim() 00301 @sa Component::primaryComponentOKToEndSim() 00302 */ 00303 void registerAsPrimaryComponent(); 00304 00305 /** Tells the simulation that it should not exit. The component 00306 will remain in this state until a call to 00307 primaryComponentOKToEndSim(). 00308 00309 @sa Component::registerAsPrimaryComponent() 00310 @sa Component::primaryComponentOKToEndSim() 00311 */ 00312 void primaryComponentDoNotEndSim(); 00313 00314 /** Tells the simulation that it is now OK to end simulation. 00315 Simulation will not end until all primary components have 00316 called this function. 00317 00318 @sa Component::registerAsPrimaryComponent() 00319 @sa Component::primaryComponentDoNotEndSim() 00320 */ 00321 void primaryComponentOKToEndSim(); 00322 00323 /** Loads a module from an element Library 00324 * @param type Fully Qualified library.moduleName 00325 * @param params Parameters the module should use for configuration 00326 * @return handle to new instance of module, or NULL on failure. 00327 */ 00328 Module* loadModule(std::string type, Params& params); 00329 00330 /** Loads a module from an element Library 00331 * @param type Fully Qualified library.moduleName 00332 * @param comp Pointer to component to pass to Module's constructor 00333 * @param params Parameters the module should use for configuration 00334 * @return handle to new instance of module, or NULL on failure. 00335 */ 00336 Module* loadModuleWithComponent(std::string type, Component* comp, Params& params); 00337 00338 /** Loads a SubComponent from an element Library 00339 * @param type Fully Qualified library.moduleName 00340 * @param comp Pointer to component to pass to SuComponent's constructor 00341 * @param params Parameters the module should use for configuration 00342 * @return handle to new instance of SubComponent, or NULL on failure. 00343 */ 00344 SubComponent* loadSubComponent(std::string type, Component* comp, Params& params); 00345 00346 protected: 00347 Component(); // For serialization only 00348 00349 /** Manually set the default detaulTimeBase */ 00350 void setDefaultTimeBase(TimeConverter *tc) { 00351 defaultTimeBase = tc; 00352 } 00353 00354 /** Timebase used if no other timebase is specified for calls like 00355 Component::getCurrentSimTime(). Often set by Component::registerClock() 00356 function */ 00357 TimeConverter* defaultTimeBase; 00358 00359 /** Creates a new selfLink */ 00360 Link* selfLink( std::string name, Event::HandlerBase* handler = NULL ); 00361 00362 00363 /** Find a lookup table */ 00364 SharedRegion* getLocalSharedRegion(const std::string &key, size_t size); 00365 SharedRegion* getGlobalSharedRegion(const std::string &key, size_t size, SharedRegionMerger *merger = NULL); 00366 00367 private: 00368 00369 friend class SubComponent; 00370 00371 void addSelfLink(std::string name); 00372 00373 // Does the statisticName exist in the ElementInfoStatistic 00374 bool doesComponentInfoStatisticExist(std::string statisticName); 00375 // Return the EnableLevel for the statisticName from the ElementInfoStatistic 00376 uint8_t getComponentInfoStatisticEnableLevel(std::string statisticName); 00377 // Return the Units for the statisticName from the ElementInfoStatistic 00378 std::string getComponentInfoStatisticUnits(std::string statisticName); 00379 00380 /** Unique ID */ 00381 ComponentId_t id; 00382 /* std::string name; */ 00383 ComponentInfo* my_info; 00384 00385 // LinkMap* myLinks; 00386 std::string currentlyLoadingSubComponent; 00387 00388 friend class boost::serialization::access; 00389 template<class Archive> 00390 void serialize(Archive& ar, const unsigned int version); 00391 }; 00392 00393 } //namespace SST 00394 00395 BOOST_CLASS_EXPORT_KEY(SST::Component) 00396 00397 #endif // SST_CORE_COMPONENT_H