SST  15.1.0
StructuralSimulationToolkit
link.h
1 // Copyright 2009-2025 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-2025, 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_LINK_H
13 #define SST_CORE_LINK_H
14 
15 #include "sst/core/event.h"
16 #include "sst/core/rankInfo.h"
17 #include "sst/core/serialization/serialize_impl_fwd.h"
18 #include "sst/core/sst_types.h"
19 #include "sst/core/timeConverter.h"
20 
21 #include <cstdint>
22 #include <string>
23 #include <vector>
24 
25 namespace SST {
26 
27 #define _LINK_DBG(fmt, args...) __DBG(DBG_LINK, Link, fmt, ##args)
28 
29 class ActivityQueue;
30 class BaseComponent;
31 class TimeConverter;
32 class LinkPair;
33 class Simulation_impl;
34 
35 class UnitAlgebra;
36 
37 namespace Profile {
38 class EventHandlerProfileTool;
39 }
40 
41 class Link;
42 
43 template <>
45 {
46  // Function implemented in link.cc
47  void operator()(Link*& s, SST::Core::Serialization::serializer& ser, ser_opt_t options);
48  void serialize_events(
49  SST::Core::Serialization::serializer& ser, uintptr_t delivery_info, ActivityQueue* queue = nullptr);
50 
51  SST_FRIEND_SERIALIZE();
52 };
53 
54 
55 /** Link between two components. Carries events */
56 class alignas(64) Link
57 {
58  enum Type_t : uint16_t { POLL, HANDLER, SYNC, UNINITIALIZED };
59  enum Mode_t : uint16_t { INIT, RUN, COMPLETE };
60 
62 
63 public:
64  /**
65  Attach point for inspecting, modifying or dropping events
66  sent on the Link.
67 
68  NOTE: Using the Link::AttachPoint will noticeably affect the
69  performance of sending events on Links and it is recommended
70  that, if possible, Event::HandlerBase::AttachPoint or
71  Event::HandlerBase::InterceptPoint be used instead.
72  */
74  {
75  public:
76  /**
77  Function that will be called when an attach point is
78  registered with the tool implementing the attach point.
79  The metadata passed in will be dependent on what type of
80  tool this is attached to. The uintptr_t returned from this
81  function will be passed into the eventSent() function.
82 
83  @param mdata Metadata to be passed into the tool
84 
85  @return Opaque key that will be passed back into
86  eventSent() to identify the source of the call
87  */
88  virtual uintptr_t registerLinkAttachTool(const AttachPointMetaData& mdata) = 0;
89 
90  /**
91  Function that will be called when an event is sent on a
92  link with registered attach points. If ev is set to
93  nullptr, then the event will not be delivered and the tool
94  should delete the original event.
95 
96  @param key Opaque key returned from registerLinkAttachTool()
97  */
98  virtual void eventSent(uintptr_t key, Event*& ev) = 0;
99 
100  /**
101  Function that will be called to handle the key returned
102  from registerLinkAttachTool, if the AttachPoint tool is
103  serializable. This is needed because the key is opaque to
104  the Link, so it doesn't know how to handle it during
105  serialization. During SIZE and PACK phases of
106  serialization, the tool needs to store out any information
107  that will be needed to recreate data that is reliant on the
108  key. On UNPACK, the function needs to recreate any state
109  and reinitialize the passed in key reference to the proper
110  state to continue to make valid calls to eventSent().
111 
112  Since not all tools will be serializable, there is a
113  default, empty implementation.
114 
115  @param ser Serializer to use for serialization
116 
117  @param key Key that would be passed into the eventSent() function.
118  */
119  virtual void serializeEventAttachPointKey(SST::Core::Serialization::serializer& ser, uintptr_t& key);
120 
121  virtual ~AttachPoint() = default;
122  };
123 
124  friend class LinkPair;
125  friend class RankSync;
126  friend class ThreadSync;
127  friend class Simulation_impl;
128  friend class SyncManager;
129  friend class ComponentInfo;
130 
131  ~Link();
132 
133  /** Set additional Latency to be added to events being sent out of this link
134  * @param cycles Number of Cycles to be added
135  * @param timebase Base Units of cycles
136  */
137  void addSendLatency(int cycles, const std::string& timebase);
138 
139  /** Set additional Latency to be added to events being sent out of this link
140  * @param cycles Number of Cycles to be added
141  * @param timebase Base Units of cycles
142  */
143  [[deprecated("Use of shared TimeConverter objects is deprecated. Use 'addSendLatency(SimTime_t cycles, "
144  "TimeConverter timebase)' (i.e., no pointer) instead.")]]
145  void addSendLatency(SimTime_t cycles, TimeConverter* timebase);
146  void addSendLatency(SimTime_t cycles, TimeConverter timebase);
147 
148  /** Set additional Latency to be added on to events coming in on this link.
149  * @param cycles Number of Cycles to be added
150  * @param timebase Base Units of cycles
151  */
152  void addRecvLatency(int cycles, const std::string& timebase);
153 
154  /** Set additional Latency to be added on to events coming in on this link.
155  * @param cycles Number of Cycles to be added
156  * @param timebase Base Units of cycles
157  */
158  [[deprecated("Use of shared TimeConverter objects is deprecated. Use 'addRecvLatency(SimTime_t cycles, "
159  "TimeConverter timebase)' (i.e., no pointer) instead.")]]
160  void addRecvLatency(SimTime_t cycles, TimeConverter* timebase);
161  void addRecvLatency(SimTime_t cycles, TimeConverter timebase);
162 
163  /** Set the callback function to be called when a message is
164  * delivered. Not available for Polling links.
165  * @param functor Functor to call when message is delivered
166  */
167  void setFunctor(Event::HandlerBase* functor);
168 
169  /** Replace the callback function to be called when a message is
170  * delivered. Any previous handler will be deleted.
171  * Not available for Polling links.
172  * @param functor Functor to call when message is delivered
173  */
174  void replaceFunctor(Event::HandlerBase* functor);
175 
176  /** Get the callback function to be called when a message is
177  * delivered. Polling links will return nullptr.
178  */
180 
181  /** Send an event over the link with additional delay. Sends an event
182  * over a link with an additional delay specified with a
183  * TimeConverter. I.e. the total delay is the link's delay + the
184  * additional specified delay.
185  * @param delay - additional delay
186  * @param tc - time converter to specify units for the additional delay
187  * @param event - the Event to send
188  */
189  [[deprecated(
190  "Use of shared TimeConverter objects is deprecated. Use 'send(SimTime_t delay, const TimeConverter& tc, "
191  "Event* event)' instead.")]]
192  inline void send(SimTime_t delay, TimeConverter* tc, Event* event)
193  {
194  send(delay, *tc, event);
195  }
196 
197  /** Send an event over the link with additional delay. Sends an event
198  * over a link with an additional delay specified with a
199  * TimeConverter. I.e. the total delay is the link's delay + the
200  * additional specified delay.
201  * @param delay - additional delay
202  * @param tc - time converter to specify units for the additional delay
203  * @param event - the Event to send
204  */
205  inline void send(SimTime_t delay, TimeConverter tc, Event* event) { send_impl(tc.convertToCoreTime(delay), event); }
206 
207 
208  /** Send an event with additional delay. Sends an event over a link
209  * with additional delay specified by the Link's default
210  * timebase.
211  * @param delay The additional delay, in units of the default Link timebase
212  * @param event The event to send
213  */
214  inline void send(SimTime_t delay, Event* event) { send_impl(delay * defaultTimeBase, event); }
215 
216  /** Send an event with the Link's default delay
217  * @param event The event to send
218  */
219  inline void send(Event* event) { send_impl(0, event); }
220 
221 
222  /** Retrieve a pending event from the Link. For links which do not
223  * have a set event handler, they can be polled with this function.
224  * Returns nullptr if there is no pending event.
225  * Not available for HANDLER-type links.
226  * @return Event if one is available
227  * @return nullptr if no Event is available
228  */
229  Event* recv();
230 
231  /** Manually set the default defaultTimeBase
232  * @param tc TimeConverter object for the timebase
233  */
234  [[deprecated("Use of shared TimeConverter objects is deprecated. Use 'setDefaultTimeBase(TimeConverter tc)', "
235  "(i.e., no pointer) instead.")]]
237 
238  /** Manually set the default defaultTimeBase
239  * @param tc TimeConverter object for the timebase
240  */
242 
243  /** Return the default Time Base for this link
244  * @return the default Time Base for this link
245  */
247 
248  /** Return the default Time Base for this link
249  * @return the default Time Base for this link
250  */
251  const TimeConverter* getDefaultTimeBase() const;
252 
253  /** Return the ID of this link
254  * @return the unique ID for this link
255  */
256  LinkId_t getId() { return tag; }
257 
258  /** Send data during the init() or complete() phase.
259  * @param data event to send
260  */
261  void sendUntimedData(Event* data);
262 
263  /** Receive an event (if any) during the init() or complete() phase.
264  * @return Event if one is available
265  * @return nullptr if no Event is available
266  */
268 
269  /** Return whether link has been configured
270  * @return whether link is configured
271  */
272  bool isConfigured() { return type != UNINITIALIZED; }
273 
274 #ifdef __SST_DEBUG_EVENT_TRACKING__
275  void setSendingComponentInfo(const std::string& comp_in, const std::string& type_in, const std::string& port_in)
276  {
277  comp = comp_in;
278  ctype = type_in;
279  port = port_in;
280  }
281 
282  const std::string& getSendingComponentName() { return comp; }
283  const std::string& getSendingComponentType() { return ctype; }
284  const std::string& getSendingPort() { return port; }
285 
286 #endif
287 
288 protected:
289  Link();
290 
291  void setAsSyncLink() { type = SYNC; }
292 
293  /**
294  Set the delivery_info for the link
295  */
296  void setDeliveryInfo(uintptr_t info) { delivery_info = info; }
297 
298  /** Send an event over the link with additional delay. Sends an event
299  * over a link with an additional delay specified with a
300  * TimeConverter. I.e. the total delay is the link's delay + the
301  * additional specified delay.
302  * @param delay - additional total delay to add
303  * @param event - the Event to send
304  */
305  void send_impl(SimTime_t delay, Event* event);
306 
307  /**
308  Updates the delivery info in an event. This is used during a
309  restart and is implemented here because Link is a friend of
310  event.
311 
312  @param event - Event to update
313 
314  @param delivery_info New delivery info (pointer to handler cast
315  as uintptr_t)
316  */
317  static void updateEventDeliveryInfo(Event* event, uintptr_t delivery_info)
318  {
319  event->updateDeliveryInfo(delivery_info);
320  }
321 
322  // Since Links are found in pairs, I will keep all the information
323  // needed for me to send and deliver an event to the other side of
324  // the link. That means, that I mostly keep my pair's
325  // information. The one consequence, is that polling links will
326  // have to pull the data from the pair, but since this is a less
327  // common case, that's okay (this decision makes the common case
328  // faster and the less common case slower).
329 
330  /** Queue of events to be received by the owning component */
332 
333  /** Holds the delivery information. This is stored as a
334  uintptr_t, but is actually a pointer converted using
335  reinterpret_cast. For links connected to a
336  Component/SubComponent, this holds a pointer to the delivery
337  functor. For links connected to a Sync object, this holds a
338  pointer to the remote link to send the event on after
339  synchronization.
340  */
341  uintptr_t delivery_info;
342 
343  /** Timebase used if no other timebase is specified. Used to specify
344  the units for added delays when sending, such as in
345  Link::send(). Often set by the Component::registerClock()
346  function if the regAll argument is true.
347  */
348  SimTime_t defaultTimeBase;
349 
350  /** Latency of the link. It is used by the partitioner as the
351  weight. This latency is added to the delay put on the event by
352  the component.
353  */
354  SimTime_t latency;
355 
356  /** Pointer to the opposite side of this link */
358 
359 private:
360  friend class BaseComponent;
361 
362  SimTime_t& current_time;
363  Type_t type;
364  Mode_t mode;
365  LinkId_t tag;
366 
367  /** Create a new link with a given tag
368 
369  The tag is used for two different things depending on where
370  this link sends data:
371 
372  If it sends it to a Sync object, then it represents the
373  remote_tag used to lookup the correct link on the other side.
374 
375  If it sends to a TimeVortex (or DirectLinkQueue), it is the
376  value used for enforce_link_order (if that feature is
377  enabled).
378  */
379  explicit Link(LinkId_t tag);
380 
381  Link(const Link& l);
382 
383  /** Specifies that this link has no callback, and is poll-based only */
384  void setPolling();
385 
386  /** Causes an event to be delivered to the registered callback */
387  inline void deliverEvent(Event* event) const { (*reinterpret_cast<Event::HandlerBase*>(delivery_info))(event); }
388 
389  /** Set minimum link latency */
390  void setLatency(Cycle_t lat);
391 
392  void sendUntimedData_sync(Event* data);
393  void finalizeConfiguration();
394  void prepareForComplete();
395 
396  std::string createUniqueGlobalLinkName(
397  RankInfo local_rank, uintptr_t local_ptr, RankInfo remote_rank, uintptr_t remote_ptr);
398 
399 
400  void attachTool(AttachPoint* tool, const AttachPointMetaData& mdata);
401  void detachTool(AttachPoint* tool);
402 
403 
404  using ToolList = std::vector<std::pair<AttachPoint*, uintptr_t>>;
405  ToolList* attached_tools;
406 
407  /** Manually set the default time base
408  * @param factor SimTime_T defining the timebase factor
409  */
410  void setDefaultTimeBase(SimTime_t factor) { defaultTimeBase = factor; }
411 
412  /** Set the default time base fo uninitialized */
413  void resetDefaultTimeBase() { defaultTimeBase = 0; }
414 
415 
416 #ifdef __SST_DEBUG_EVENT_TRACKING__
417  std::string comp;
418  std::string ctype;
419  std::string port;
420 #endif
421 };
422 
423 /** Self Links are links from a component to itself */
424 class SelfLink : public Link
425 {
426 public:
427  SelfLink() :
428  Link()
429  {
430  pair_link = this;
431  latency = 0;
432  }
433 };
434 
435 
436 } // namespace SST
437 
438 #endif // SST_CORE_LINK_H
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:42
Definition: syncManager.h:137
Base template for handlers which take a class defined argument.
Definition: ssthandler.h:109
A class to convert between a component&#39;s view of time and the core&#39;s view of time.
Definition: timeConverter.h:27
Definition: syncManager.h:42
Base serialize class.
Definition: serialize.h:113
Definition: action.cc:18
Definition: syncManager.h:94
Main control class for a SST Simulation.
Definition: simulation_impl.h:122
Definition: rankInfo.h:23
Main component object for the simulation.
Definition: baseComponent.h:64
Defines a pair of links (to define a connected link)
Definition: linkPair.h:23
SimTime_t convertToCoreTime(SimTime_t time) const
Converts from the component&#39;s view to the core&#39;s view of time.
Definition: timeConverter.h:62
Definition: componentInfo.h:44
Struct used as a base class for all AttachPoint metadata passed to registration functions.
Definition: sst_types.h:80
Base Class for a queue of Activities.
Definition: activityQueue.h:21
Base class for Events - Items sent across links to communicate between components.
Definition: event.h:40