gem5  v20.1.0.0
Topology.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Advanced Micro Devices, Inc.
3  * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met: redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer;
10  * redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution;
13  * neither the name of the copyright holders nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
31 
32 #include <cassert>
33 
34 #include "base/trace.hh"
35 #include "debug/RubyNetwork.hh"
40 
41 using namespace std;
42 
43 const int INFINITE_LATENCY = 10000; // Yes, this is a big hack
44 
45 // Note: In this file, we use the first 2*m_nodes SwitchIDs to
46 // represent the input and output endpoint links. These really are
47 // not 'switches', as they will not have a Switch object allocated for
48 // them. The first m_nodes SwitchIDs are the links into the network,
49 // the second m_nodes set of SwitchIDs represent the the output queues
50 // of the network.
51 
52 Topology::Topology(uint32_t num_nodes, uint32_t num_routers,
53  uint32_t num_vnets,
54  const vector<BasicExtLink *> &ext_links,
55  const vector<BasicIntLink *> &int_links)
56  : m_nodes(MachineType_base_number(MachineType_NUM)),
57  m_number_of_switches(num_routers), m_vnets(num_vnets),
58  m_ext_link_vector(ext_links), m_int_link_vector(int_links)
59 {
60  // Total nodes/controllers in network
61  assert(m_nodes > 1);
62 
63  // analyze both the internal and external links, create data structures.
64  // The python created external links are bi-directional,
65  // and the python created internal links are uni-directional.
66  // The networks and topology utilize uni-directional links.
67  // Thus each external link is converted to two calls to addLink,
68  // one for each direction.
69  //
70  // External Links
71  for (vector<BasicExtLink*>::const_iterator i = ext_links.begin();
72  i != ext_links.end(); ++i) {
73  BasicExtLink *ext_link = (*i);
74  AbstractController *abs_cntrl = ext_link->params()->ext_node;
75  BasicRouter *router = ext_link->params()->int_node;
76 
77  int machine_base_idx = MachineType_base_number(abs_cntrl->getType());
78  int ext_idx1 = machine_base_idx + abs_cntrl->getVersion();
79  int ext_idx2 = ext_idx1 + m_nodes;
80  int int_idx = router->params()->router_id + 2*m_nodes;
81 
82  // create the internal uni-directional links in both directions
83  // ext to int
84  addLink(ext_idx1, int_idx, ext_link);
85  // int to ext
86  addLink(int_idx, ext_idx2, ext_link);
87  }
88 
89  // Internal Links
90  for (vector<BasicIntLink*>::const_iterator i = int_links.begin();
91  i != int_links.end(); ++i) {
92  BasicIntLink *int_link = (*i);
93  BasicRouter *router_src = int_link->params()->src_node;
94  BasicRouter *router_dst = int_link->params()->dst_node;
95 
96  PortDirection src_outport = int_link->params()->src_outport;
97  PortDirection dst_inport = int_link->params()->dst_inport;
98 
99  // Store the IntLink pointers for later
100  m_int_link_vector.push_back(int_link);
101 
102  int src = router_src->params()->router_id + 2*m_nodes;
103  int dst = router_dst->params()->router_id + 2*m_nodes;
104 
105  // create the internal uni-directional link from src to dst
106  addLink(src, dst, int_link, src_outport, dst_inport);
107  }
108 }
109 
110 void
112 {
113  // Find maximum switchID
114  SwitchID max_switch_id = 0;
115  for (LinkMap::const_iterator i = m_link_map.begin();
116  i != m_link_map.end(); ++i) {
117  std::pair<SwitchID, SwitchID> src_dest = (*i).first;
118  max_switch_id = max(max_switch_id, src_dest.first);
119  max_switch_id = max(max_switch_id, src_dest.second);
120  }
121 
122  // Initialize weight, latency, and inter switched vectors
123  int num_switches = max_switch_id+1;
124  Matrix topology_weights(m_vnets,
125  vector<vector<int>>(num_switches,
126  vector<int>(num_switches, INFINITE_LATENCY)));
127  Matrix component_latencies(num_switches,
128  vector<vector<int>>(num_switches,
129  vector<int>(m_vnets, -1)));
130  Matrix component_inter_switches(num_switches,
131  vector<vector<int>>(num_switches,
132  vector<int>(m_vnets, 0)));
133 
134  // Set identity weights to zero
135  for (int i = 0; i < topology_weights[0].size(); i++) {
136  for (int v = 0; v < m_vnets; v++) {
137  topology_weights[v][i][i] = 0;
138  }
139  }
140 
141  // Fill in the topology weights and bandwidth multipliers
142  for (auto link_group : m_link_map) {
143  std::pair<int, int> src_dest = link_group.first;
144  vector<bool> vnet_done(m_vnets, 0);
145  int src = src_dest.first;
146  int dst = src_dest.second;
147 
148  // Iterate over all links for this source and destination
149  std::vector<LinkEntry> link_entries = link_group.second;
150  for (int l = 0; l < link_entries.size(); l++) {
151  BasicLink* link = link_entries[l].link;
152  if (link->mVnets.size() == 0) {
153  for (int v = 0; v < m_vnets; v++) {
154  // Two links connecting same src and destination
155  // cannot carry same vnets.
156  fatal_if(vnet_done[v], "Two links connecting same src"
157  " and destination cannot support same vnets");
158 
159  component_latencies[src][dst][v] = link->m_latency;
160  topology_weights[v][src][dst] = link->m_weight;
161  vnet_done[v] = true;
162  }
163  } else {
164  for (int v = 0; v < link->mVnets.size(); v++) {
165  int vnet = link->mVnets[v];
166  fatal_if(vnet >= m_vnets, "Not enough virtual networks "
167  "(setting latency and weight for vnet %d)", vnet);
168  // Two links connecting same src and destination
169  // cannot carry same vnets.
170  fatal_if(vnet_done[vnet], "Two links connecting same src"
171  " and destination cannot support same vnets");
172 
173  component_latencies[src][dst][vnet] = link->m_latency;
174  topology_weights[vnet][src][dst] = link->m_weight;
175  vnet_done[vnet] = true;
176  }
177  }
178  }
179  }
180 
181  // Walk topology and hookup the links
182  Matrix dist = shortest_path(topology_weights, component_latencies,
183  component_inter_switches);
184 
185  for (int i = 0; i < topology_weights[0].size(); i++) {
186  for (int j = 0; j < topology_weights[0][i].size(); j++) {
187  std::vector<NetDest> routingMap;
188  routingMap.resize(m_vnets);
189 
190  // Not all sources and destinations are connected
191  // by direct links. We only construct the links
192  // which have been configured in topology.
193  bool realLink = false;
194 
195  for (int v = 0; v < m_vnets; v++) {
196  int weight = topology_weights[v][i][j];
197  if (weight > 0 && weight != INFINITE_LATENCY) {
198  realLink = true;
199  routingMap[v] =
200  shortest_path_to_node(i, j, topology_weights, dist, v);
201  }
202  }
203  // Make one link for each set of vnets between
204  // a given source and destination. We do not
205  // want to create one link for each vnet.
206  if (realLink) {
207  makeLink(net, i, j, routingMap);
208  }
209  }
210  }
211 }
212 
213 void
215  PortDirection src_outport_dirn,
216  PortDirection dst_inport_dirn)
217 {
218  assert(src <= m_number_of_switches+m_nodes+m_nodes);
219  assert(dest <= m_number_of_switches+m_nodes+m_nodes);
220 
221  std::pair<int, int> src_dest_pair;
222  src_dest_pair.first = src;
223  src_dest_pair.second = dest;
224  LinkEntry link_entry;
225 
226  link_entry.link = link;
227  link_entry.src_outport_dirn = src_outport_dirn;
228  link_entry.dst_inport_dirn = dst_inport_dirn;
229 
230  auto lit = m_link_map.find(src_dest_pair);
231  if (lit != m_link_map.end()) {
232  // HeteroGarnet allows multiple links between
233  // same source-destination pair supporting
234  // different vnets. If there is a link already
235  // between a given pair of source and destination
236  // add this new link to it.
237  lit->second.push_back(link_entry);
238  } else {
240  links.push_back(link_entry);
241  m_link_map[src_dest_pair] = links;
242  }
243 }
244 
245 void
247  std::vector<NetDest>& routing_table_entry)
248 {
249  // Make sure we're not trying to connect two end-point nodes
250  // directly together
251  assert(src >= 2 * m_nodes || dest >= 2 * m_nodes);
252 
253  std::pair<int, int> src_dest;
254  LinkEntry link_entry;
255 
256  if (src < m_nodes) {
257  src_dest.first = src;
258  src_dest.second = dest;
259  std::vector<LinkEntry> links = m_link_map[src_dest];
260  for (int l = 0; l < links.size(); l++) {
261  link_entry = links[l];
262  std::vector<NetDest> linkRoute;
263  linkRoute.resize(m_vnets);
264  BasicLink *link = link_entry.link;
265  if (link->mVnets.size() == 0) {
266  net->makeExtInLink(src, dest - (2 * m_nodes), link,
267  routing_table_entry);
268  } else {
269  for (int v = 0; v< link->mVnets.size(); v++) {
270  int vnet = link->mVnets[v];
271  linkRoute[vnet] = routing_table_entry[vnet];
272  }
273  net->makeExtInLink(src, dest - (2 * m_nodes), link,
274  linkRoute);
275  }
276  }
277  } else if (dest < 2*m_nodes) {
278  assert(dest >= m_nodes);
279  NodeID node = dest - m_nodes;
280  src_dest.first = src;
281  src_dest.second = dest;
282  std::vector<LinkEntry> links = m_link_map[src_dest];
283  for (int l = 0; l < links.size(); l++) {
284  link_entry = links[l];
285  std::vector<NetDest> linkRoute;
286  linkRoute.resize(m_vnets);
287  BasicLink *link = link_entry.link;
288  if (link->mVnets.size() == 0) {
289  net->makeExtOutLink(src - (2 * m_nodes), node, link,
290  routing_table_entry);
291  } else {
292  for (int v = 0; v< link->mVnets.size(); v++) {
293  int vnet = link->mVnets[v];
294  linkRoute[vnet] = routing_table_entry[vnet];
295  }
296  net->makeExtOutLink(src - (2 * m_nodes), node, link,
297  linkRoute);
298  }
299  }
300  } else {
301  assert((src >= 2 * m_nodes) && (dest >= 2 * m_nodes));
302  src_dest.first = src;
303  src_dest.second = dest;
304  std::vector<LinkEntry> links = m_link_map[src_dest];
305  for (int l = 0; l < links.size(); l++) {
306  link_entry = links[l];
307  std::vector<NetDest> linkRoute;
308  linkRoute.resize(m_vnets);
309  BasicLink *link = link_entry.link;
310  if (link->mVnets.size() == 0) {
311  net->makeInternalLink(src - (2 * m_nodes),
312  dest - (2 * m_nodes), link, routing_table_entry,
313  link_entry.src_outport_dirn,
314  link_entry.dst_inport_dirn);
315  } else {
316  for (int v = 0; v< link->mVnets.size(); v++) {
317  int vnet = link->mVnets[v];
318  linkRoute[vnet] = routing_table_entry[vnet];
319  }
320  net->makeInternalLink(src - (2 * m_nodes),
321  dest - (2 * m_nodes), link, linkRoute,
322  link_entry.src_outport_dirn,
323  link_entry.dst_inport_dirn);
324  }
325  }
326  }
327 }
328 
329 // The following all-pairs shortest path algorithm is based on the
330 // discussion from Cormen et al., Chapter 26.1.
331 void
332 Topology::extend_shortest_path(Matrix &current_dist, Matrix &latencies,
333  Matrix &inter_switches)
334 {
335  int nodes = current_dist[0].size();
336 
337  // We find the shortest path for each vnet for a given pair of
338  // source and destinations. This is done simply by traversing via
339  // all other nodes and finding the minimum distance.
340  for (int v = 0; v < m_vnets; v++) {
341  // There is a different topology for each vnet. Here we try to
342  // build a topology by finding the minimum number of intermediate
343  // switches needed to reach the destination
344  bool change = true;
345  while (change) {
346  change = false;
347  for (int i = 0; i < nodes; i++) {
348  for (int j = 0; j < nodes; j++) {
349  // We follow an iterative process to build the shortest
350  // path tree:
351  // 1. Start from the direct connection (if there is one,
352  // otherwise assume a hypothetical infinite weight link).
353  // 2. Then we iterate through all other nodes considering
354  // new potential intermediate switches. If we find any
355  // lesser weight combination, we set(update) that as the
356  // new weight between the source and destination.
357  // 3. Repeat for all pairs of nodes.
358  // 4. Go to step 1 if there was any new update done in
359  // Step 2.
360  int minimum = current_dist[v][i][j];
361  int previous_minimum = minimum;
362  int intermediate_switch = -1;
363  for (int k = 0; k < nodes; k++) {
364  minimum = min(minimum,
365  current_dist[v][i][k] + current_dist[v][k][j]);
366  if (previous_minimum != minimum) {
367  intermediate_switch = k;
368  inter_switches[i][j][v] =
369  inter_switches[i][k][v] +
370  inter_switches[k][j][v] + 1;
371  }
372  previous_minimum = minimum;
373  }
374  if (current_dist[v][i][j] != minimum) {
375  change = true;
376  current_dist[v][i][j] = minimum;
377  assert(intermediate_switch >= 0);
378  assert(intermediate_switch < latencies[i].size());
379  latencies[i][j][v] =
380  latencies[i][intermediate_switch][v] +
381  latencies[intermediate_switch][j][v];
382  }
383  }
384  }
385  }
386  }
387 }
388 
389 Matrix
390 Topology::shortest_path(const Matrix &weights, Matrix &latencies,
391  Matrix &inter_switches)
392 {
393  Matrix dist = weights;
394  extend_shortest_path(dist, latencies, inter_switches);
395  return dist;
396 }
397 
398 bool
400  SwitchID final, const Matrix &weights,
401  const Matrix &dist, int vnet)
402 {
403  return weights[vnet][src][next] + dist[vnet][next][final] ==
404  dist[vnet][src][final];
405 }
406 
407 NetDest
409  const Matrix &weights, const Matrix &dist,
410  int vnet)
411 {
412  NetDest result;
413  int d = 0;
414  int machines;
415  int max_machines;
416 
417  machines = MachineType_NUM;
418  max_machines = MachineType_base_number(MachineType_NUM);
419 
420  for (int m = 0; m < machines; m++) {
421  for (NodeID i = 0; i < MachineType_base_count((MachineType)m); i++) {
422  // we use "d+max_machines" below since the "destination"
423  // switches for the machines are numbered
424  // [MachineType_base_number(MachineType_NUM)...
425  // 2*MachineType_base_number(MachineType_NUM)-1] for the
426  // component network
427  if (link_is_shortest_path_to_node(src, next, d + max_machines,
428  weights, dist, vnet)) {
429  MachineID mach = {(MachineType)m, i};
430  result.add(mach);
431  }
432  d++;
433  }
434  }
435 
436  DPRINTF(RubyNetwork, "Returning shortest path\n"
437  "(src-(2*max_machines)): %d, (next-(2*max_machines)): %d, "
438  "src: %d, next: %d, vnet:%d result: %s\n",
439  (src-(2*max_machines)), (next-(2*max_machines)),
440  src, next, vnet, result);
441 
442  return result;
443 }
NetDest::add
void add(MachineID newElement)
Definition: NetDest.cc:39
Topology::makeLink
void makeLink(Network *net, SwitchID src, SwitchID dest, std::vector< NetDest > &routing_table_entry)
Definition: Topology.cc:246
AbstractController::getVersion
NodeID getVersion() const
Definition: AbstractController.hh:82
LinkEntry::link
BasicLink * link
Definition: Topology.hh:66
BasicRouter::params
const Params * params() const
Definition: BasicRouter.hh:44
Topology::extend_shortest_path
void extend_shortest_path(Matrix &current_dist, Matrix &latencies, Matrix &inter_switches)
Definition: Topology.cc:332
Topology::m_nodes
const uint32_t m_nodes
Definition: Topology.hh:107
ArmISA::i
Bitfield< 7 > i
Definition: miscregs_types.hh:63
Network::makeExtOutLink
virtual void makeExtOutLink(SwitchID src, NodeID dest, BasicLink *link, std::vector< NetDest > &routing_table_entry)=0
AbstractController.hh
std::vector< BasicExtLink * >
AbstractController
Definition: AbstractController.hh:74
MachineID
Definition: MachineID.hh:38
LinkEntry::dst_inport_dirn
PortDirection dst_inport_dirn
Definition: Topology.hh:68
Topology::m_vnets
int m_vnets
Definition: Topology.hh:109
ArmISA::j
Bitfield< 24 > j
Definition: miscregs_types.hh:54
Network::makeExtInLink
virtual void makeExtInLink(NodeID src, SwitchID dest, BasicLink *link, std::vector< NetDest > &routing_table_entry)=0
MipsISA::k
Bitfield< 23 > k
Definition: dt_constants.hh:78
DPRINTF
#define DPRINTF(x,...)
Definition: trace.hh:234
ArmISA::d
Bitfield< 9 > d
Definition: miscregs_types.hh:60
LinkEntry
Definition: Topology.hh:64
BasicRouter
Definition: BasicRouter.hh:39
Topology::m_number_of_switches
const uint32_t m_number_of_switches
Definition: Topology.hh:108
std::pair
STL pair class.
Definition: stl.hh:58
Topology::link_is_shortest_path_to_node
bool link_is_shortest_path_to_node(SwitchID src, SwitchID next, SwitchID final, const Matrix &weights, const Matrix &dist, int vnet)
Definition: Topology.cc:399
Network
Definition: Network.hh:76
Topology::m_link_map
LinkMap m_link_map
Definition: Topology.hh:114
Stats::dist
const FlagsType dist
Print the distribution.
Definition: info.hh:55
Topology.hh
Topology::shortest_path
Matrix shortest_path(const Matrix &weights, Matrix &latencies, Matrix &inter_switches)
Definition: Topology.cc:390
Network.hh
Network::makeInternalLink
virtual void makeInternalLink(SwitchID src, SwitchID dest, BasicLink *link, std::vector< NetDest > &routing_table_entry, PortDirection src_outport, PortDirection dst_inport)=0
INFINITE_LATENCY
const int INFINITE_LATENCY
Definition: Topology.cc:43
Topology::shortest_path_to_node
NetDest shortest_path_to_node(SwitchID src, SwitchID next, const Matrix &weights, const Matrix &dist, int vnet)
Definition: Topology.cc:408
std
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:587
AbstractController::getType
MachineType getType() const
Definition: AbstractController.hh:83
Topology::m_int_link_vector
std::vector< BasicIntLink * > m_int_link_vector
Definition: Topology.hh:112
Topology::createLinks
void createLinks(Network *net)
Definition: Topology.cc:111
LinkEntry::src_outport_dirn
PortDirection src_outport_dirn
Definition: Topology.hh:67
PortDirection
std::string PortDirection
Definition: Topology.hh:62
NodeID
unsigned int NodeID
Definition: TypeDefines.hh:34
Topology::Topology
Topology(uint32_t num_nodes, uint32_t num_routers, uint32_t num_vnets, const std::vector< BasicExtLink * > &ext_links, const std::vector< BasicIntLink * > &int_links)
Definition: Topology.cc:52
trace.hh
Topology::addLink
void addLink(SwitchID src, SwitchID dest, BasicLink *link, PortDirection src_outport_dirn="", PortDirection dest_inport_dirn="")
Definition: Topology.cc:214
fatal_if
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:219
MipsISA::l
Bitfield< 5 > l
Definition: pra_constants.hh:320
NetDest
Definition: NetDest.hh:39
ArmISA::v
Bitfield< 28 > v
Definition: miscregs_types.hh:51
NetDest.hh
SwitchID
unsigned int SwitchID
Definition: TypeDefines.hh:35
ArmISA::m
Bitfield< 0 > m
Definition: miscregs_types.hh:389

Generated on Wed Sep 30 2020 14:02:13 for gem5 by doxygen 1.8.17