SST/macro
topology.h
Go to the documentation of this file.
1 /*
2  * This file is part of SST/macroscale:
3  * The macroscale architecture simulator from the SST suite.
4  * Copyright (c) 2009 Sandia Corporation.
5  * This software is distributed under the BSD License.
6  * Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7  * the U.S. Government retains certain rights in this software.
8  * For more information, see the LICENSE file in the top
9  * SST/macroscale directory.
10  */
11 
12 #ifndef SSTMAC_HARDWARE_NETWORK_SWITCHES_SWITCHTOPOLOGY_H_INCLUDED
13 #define SSTMAC_HARDWARE_NETWORK_SWITCHES_SWITCHTOPOLOGY_H_INCLUDED
14 
15 #include <sstmac/common/rng.h>
25 #include <sprockit/debug.h>
27 #include <sprockit/unordered.h>
28 
30 
31 #define top_debug(...) \
32  debug_printf(sprockit::dbg::topology, __VA_ARGS__)
33 
34 namespace sstmac {
35 namespace hw {
36 
37  template <class InputMap, class OutputMap>
38  void
39  copy_map(InputMap& input, OutputMap& output){
40  typedef typename InputMap::mapped_type input_cls_type;
41  typedef typename OutputMap::mapped_type output_cls_type;
42 
43  typename InputMap::iterator it, end = input.end();
44  for (it = input.begin(); it != end; ++it) {
45  output[it->first] = dynamic_cast<output_cls_type>(it->second);
46  }
47  }
48 
49 class topology :
50  virtual public sprockit::factory_type
51 {
52  public:
53  static const int eject;
54 
55  public:
56  typedef spkt_unordered_map<switch_id, connectable*> internal_connectable_map;
57  typedef spkt_unordered_map<node_id, connectable*> end_point_connectable_map;
58 
59  public:
60  virtual ~topology();
61 
62  virtual std::string
63  to_string() const = 0;
64 
65  virtual void
66  init_factory_params(sprockit::sim_parameters* params);
67 
68  virtual void
69  finalize_init();
70 
71  /**** BEGIN PURE VIRTUAL INTERFACE *****/
72  /**
73  * Given a switch address, return number of nodes connected to it
74  */
75  virtual int
76  endpoints_per_switch(switch_id addr) const = 0;
77 
78  int
79  concentration(switch_id addr) const {
80  return num_nodes_per_netlink_ * endpoints_per_switch(addr);
81  }
82 
83  /**
84  For indirect networks, this includes all switches -
85  those connected directly to nodes and internal
86  switches that are only a part of the network
87  @return The total number of switches
88  */
89  virtual int
90  num_switches() const = 0;
91 
92  virtual int
93  num_endpoints() const = 0;
94 
95  /**
96  @return The total number of nodes
97  */
98  virtual int
99  num_nodes() const = 0;
100 
101  /**
102  * @brief Given a set of connectables, connect them appropriately
103  * @param objects The set of objects to connect
104  * @param cloner If in parallel mode, not all objects may exist.
105  * The factory creates missing objects.
106  * @throws value_error If invalid switchid is passed to cloner
107  */
108  virtual void
109  connect_objects(internal_connectable_map& objects) = 0;
110 
111  virtual void
112  connect_end_point_objects(internal_connectable_map& internal,
113  end_point_connectable_map& end_points);
114 
115  /**
116  For a given node, determine the injection switch
117  All messages from this node inject into the network
118  through this switch
119  @param nodeaddr The node to inject to
120  @param switch_port [inout] The port on the switch the node injects on
121  @return The switch that injects from the node
122  */
123  virtual switch_id
124  endpoint_to_injection_switch(node_id nodeaddr, int& switch_port) const = 0;
125 
126  /**
127  For a given node, determine the ejection switch
128  All messages to this node eject into the network
129  through this switch
130  @param nodeaddr The node to eject from
131  @param switch_port [inout] The port on the switch the node ejects on
132  @return The switch that ejects into the node
133  */
134  virtual switch_id
135  endpoint_to_ejection_switch(node_id nodeaddr, int& switch_port) const = 0;
136 
137  virtual void
138  configure_vc_routing(std::map<routing::algorithm_t, int>& m) const = 0;
139 
140  /**
141  For a given node, determine the ejection switch
142  All messages to this node eject into the network
143  through this switch
144  @param nodeaddr The node to eject from
145  @param switch_port [inout] The port on the switch the node ejects on
146  @return The switch that ejects into the node
147  */
148  virtual int
149  endpoint_to_injection_port(node_id nodeaddr) const = 0;
150 
151  /**
152  For a given node, determine the ejection switch
153  All messages to this node eject into the network
154  through this switch
155  @param nodeaddr The node to eject from
156  @param switch_port [inout] The port on the switch the node ejects on
157  @return The switch that ejects into the node
158  */
159  virtual int
160  endpoint_to_ejection_port(node_id nodeaddr) const = 0;
161 
162  /**
163  For a given input switch, return all nodes connected to it.
164  This return vector might be empty if the
165  switch is an internal switch not connected to any nodes
166  @throw value_error If invalid switch id is given
167  @return The nodes connected to switch
168  */
169  virtual std::vector<node_id>
170  nodes_connected_to_injection_switch(switch_id swid) const = 0;
171 
172  virtual std::vector<node_id>
173  nodes_connected_to_ejection_switch(switch_id swid) const = 0;
174 
175  virtual void
176  create_partition(
177  int* switches_per_lp,
178  int *switch_to_lp,
179  int *switch_to_thread,
180  int& local_num_switches,
181  int me,
182  int nproc,
183  int nthread,
184  int noccupied);
185 
186  /**
187  @param dim The dimension (e.g. x, y, or z) that should be routed on next.
188  Integer value has different meaning depending on type of
189  router (torus/dragonfly/etc)
190  @param dir The direction (e.g. +/-) that should be routed on.
191  Integer value has different physical meaning depending on type
192  of router (torus/dragonly/etc)
193  @return The port number on a switch that the message should be routed through
194  for a given dim/dir
195  */
196  virtual int
197  convert_to_port(int dim, int dir) const = 0;
198 
199  /**
200  Given the current location and a destination,
201  compute the minimal path to the destination.
202  The path generally consists of a dimension,
203  a direction or branch along that dimension,
204  a port number for that dim/dir combination,
205  and a virtual channel along the dim/dir
206  appropriate for avoiding deadlock.
207  @param current_sw_addr The addr of the current switch
208  @param dest_sw_addr The addr of the destination switch
209  @param path [inout] A complete path descriptor to the destination switch
210  */
211  virtual void
212  minimal_route_to_switch(
213  switch_id current_sw_addr,
214  switch_id dest_sw_addr,
215  structured_routable::path& path) const = 0;
216 
217  /**
218  Given a traffic pattern (e.g. bit-complement),
219  return the partner nodes a given source node needs to
220  send messages to for the given traffic pattern
221  @param ty The desired traffic pattern
222  @param src_node The source node that sends messages
223  @param partners [inout] The list of partner nodes to send to
224  */
225  virtual void
226  send_partners(
228  node_id src_node,
229  std::vector<node_id>& partners) const = 0;
230 
231  static topology*
232  global() {
233  return main_top_;
234  }
235 
236  /**
237  Given a traffic pattern (e.g. bit-complement),
238  return the partner nodes a given destination node needs to
239  receive messages to for the given traffic pattern
240  @param ty The desired traffic pattern
241  @param src_node The source node that sends messages
242  @param partners [inout] The list of partner nodes to send to
243  */
244  virtual void
245  recv_partners(
247  node_id src_node,
248  std::vector<node_id>& partners) const = 0;
249 
250  /**
251  Figure out how many hops we have to go from a source node
252  to a destination node
253  @param src The source node address
254  @param dst The destination node address
255  @return The number of hops to destination
256  */
257  virtual int
258  num_hops_to_node(node_id src, node_id dst) const = 0;
259  /**** END PURE VIRTUAL INTERFACE *****/
260 
261  /**
262  Generate a path that is considered the cheapest, given the statistics of the inteconnect.
263  The 3 argument version should be a pure virtual function, but for now, will just return an empty path.
264 
265  @param src The source node address
266  @param dst The destination node address
267  @param stats A pointer to the statistics data; Type will change once established
268  @return The path chosen by the topology
269  */
270  virtual std::vector <std::pair <switch_id, int> >
271  cheapest_path(const node_id src, const node_id dst, void * stats) const {
272  return {};
273  }
274 
275  virtual std::vector <std::pair <switch_id, int> >
276  cheapest_path(const std::pair <node_id, node_id> & sd, void * stats) const {
277  return cheapest_path(sd.first, sd.second, stats);
278  }
279 
280  /**
281  Template utility function for allowing any specific map type
282  to be connected. This creates an equivalent map of connectables that
283  then calls the actual #connect_objects function
284  @param objects A map of connectable* types (map might hold more specific type like networkswitch)
285  */
286  template <class MapTypeInternal, class MapTypeEndPoint>
287  void
288  connect_end_points(MapTypeInternal& internal_nodes, MapTypeEndPoint& end_points) {
289  internal_connectable_map internal_clone_map;
290  end_point_connectable_map end_clone_map;
291  copy_map(internal_nodes, internal_clone_map);
292  copy_map(end_points, end_clone_map);
293  connect_end_point_objects(internal_clone_map, end_clone_map);
294  }
295 
296  /**
297  Template utility function for allowing any specific map type
298  to be connected. This creates an equivalent map of connectables that
299  then calls the actual #connect_objects function
300  @param objects A map of connectable* types (map might hold more specific type like networkswitch)
301  */
302  template <class MapType>
303  void
304  connect_topology(MapType& objects) {
305  typedef typename MapType::mapped_type cls_type;
306  typedef typename MapType::value_type val_type;
307  internal_connectable_map clone_map;
308  copy_map(objects, clone_map);
309  connect_objects(clone_map);
310  }
311 
312  virtual coordinates
313  switch_coords(switch_id swid) const;
314 
315  /**
316  Get a random switch from the topoology.
317  This is most often used in things like valiant routing.
318  The input parameter avoids accidentally returning
319  the exact same switch you are currently on.
320  @param current_sw The current location switch
321  @return A random switch different from current_sw
322  */
323  virtual switch_id
324  random_intermediate_switch(switch_id current_sw,
325  switch_id dest_sw = switch_id(-1));
326 
327  /**
328  For a given node, determine the injection switch
329  All messages from this node inject into the network
330  through this switch
331  @param nodeaddr The node to inject to
332  @return The switch that injects from the node
333  */
334  switch_id
335  endpoint_to_injection_switch(node_id nodeaddr) const {
336  int ignore;
337  return endpoint_to_injection_switch(nodeaddr, ignore);
338  }
339 
340  virtual switch_id
341  endpoint_to_injection_switch(
342  node_id nodeaddr, int ports[], int& num_ports) const {
343  num_ports = 1;
344  return endpoint_to_injection_switch(nodeaddr, ports[0]);
345  }
346 
347  switch_id
348  node_to_ejection_switch(node_id addr) const {
349  node_id netid(addr / num_nodes_per_netlink_);
350  return endpoint_to_ejection_switch(netid);
351  }
352 
353  /**
354  For a given node, determine the ejection switch
355  All messages to this node eject into the network
356  through this switch
357  @param nodeaddr The node to eject from
358  @return The switch that ejects into the node
359  */
360  switch_id
361  endpoint_to_ejection_switch(node_id nodeaddr) const {
362  int ignore;
363  return endpoint_to_ejection_switch(nodeaddr, ignore);
364  }
365 
366  virtual switch_id
367  endpoint_to_ejection_switch(
368  node_id nodeaddr, int ports[], int& num_ports) const {
369  num_ports = 1;
370  return endpoint_to_ejection_switch(nodeaddr, ports[0]);
371  }
372 
373  int
374  max_num_ports() const {
375  return max_ports_injection_ + max_ports_intra_network_;
376  }
377 
378  int
379  max_ports_injection() const {
380  return max_ports_injection_;
381  }
382 
383  int
384  max_ports_intra_network() const {
385  return max_ports_intra_network_;
386  }
387 
388  bool
389  is_injection_port(int port) const {
390  return port >= max_ports_intra_network_;
391  }
392 
393  /**
394  * @brief Return the port number for the ith injection/ejection node
395  * @param ith The injection/ejection index
396  * @return
397  */
398  int
399  eject_port(int ith) const {
400  return max_ports_intra_network() + ith;
401  }
402 
403  virtual void
404  sanity_check();
405 
406  virtual std::string
407  label(node_id nid) const;
408 
409  virtual std::string
410  label(switch_id sid) const;
411 
412  std::string
413  label(event_loc_id id) const;
414 
415  std::string
416  endpoint_label(node_id nid) const;
417 
418  /**
419  Given the current location and a destination,
420  compute the minimal path to the destination.
421  In most cases, this function first computes
422  the destination switch attached to the node
423  and then calls #minimal_route_to_switch.
424  The path generally consists of a dimension,
425  a direction or branch along that dimension,
426  a port number for that dim/dir combination,
427  and a virtual channel along the dim/dir
428  appropriate for avoiding deadlock.
429  @param current_sw_addr The addr of the current switch
430  @param dest_sw_addr The addr of the destination switch
431  @param path [inout] A complete path descriptor to the destination node
432  */
433  virtual void
434  minimal_route_to_node(
435  switch_id current_sw_addr,
436  node_id dest_node_addr,
437  structured_routable::path& path) const;
438 
439  /**
440  Informs topology that a new routing stage has begun, allowing any
441  topology specific state to be modified.
442  @param rinfo Routing info object
443  */
444  virtual void
445  new_routing_stage(structured_routable* rtbl) { }
446 
447  int
448  num_nodes_per_netlink() const {
449  return num_nodes_per_netlink_;
450  }
451 
452  bool
453  netlink_endpoints() const {
454  return netlink_endpoints_;
455  }
456 
457  virtual void
458  build_internal_connectables(
459  internal_connectable_map& connectables,
461  partition *part,
462  int my_rank,
463  sprockit::sim_parameters *params,
464  connectable* dummy) = 0;
465 
466  virtual void
467  build_endpoint_connectables(
468  end_point_connectable_map& connectables,
470  partition *part,
471  int my_rank,
472  sprockit::sim_parameters *params) = 0;
473 
474  virtual void
475  build_interface_connectables(
476  int conc,
477  end_point_connectable_map& connectables,
478  sprockit::factory2<connectable>* nic_factory,
479  partition *part,
480  int my_rank,
481  sprockit::sim_parameters* params,
482  sprockit::factory_type* interconnect) = 0;
483 
484  static topology*
485  static_topology(sprockit::sim_parameters* params);
486 
487  void
488  set_interconnect(interconnect * ic){
489  interconnect_ = ic;
490  }
491 
492  interconnect *
493  get_interconnect() const {
494  return interconnect_;
495  }
496 
497  protected:
498  topology();
499 
500  uint32_t random_number(uint32_t max, uint32_t attempt) const;
501 
502  protected:
503 
504  /**
505  Nodes per switch. The number of nodes connected to a leaf switch.
506  In many topologies, there is a 1-1 correspondence. For others,
507  you might have many compute nodes connected to a single injection/ejection switch.
508  */
509  int endpoints_per_switch_;
510 
511  bool netlink_endpoints_;
512 
513  bool outputgraph_;
514 
515  RNG::rngint_t seed_;
516 
517  bool debug_seed_;
518 
519  RNG::MWC* rng_;
520 
521  std::string name_;
522 
523  int num_nodes_per_netlink_;
524 
525  int max_ports_intra_network_;
526 
527  int max_ports_injection_;
528 
529  static topology* main_top_;
530 
531  interconnect * interconnect_;
532 
533  private:
534  static topology* static_topology_;
535 
536 };
537 
539 }
540 }
541 
542 #endif
DeclareFactory(node)
DeclareDebugSlot(topology) namespace sstmac
Definition: topology.h:29
The multiple-with-carry random number generator by George Marsaglia (1999; internet posting)...
Definition: rng.h:95
topology_id switch_id
Definition: node_address.h:23
SUMI = Simulator unified messagine interface It is also the name for a solid ink in Japanese - i...
uint32_t rngint_t
Definition: rng.h:22
endpoint_id node_id
Definition: node_address.h:20