gem5 v24.1.0.1
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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"
41
42namespace gem5
43{
44
45namespace ruby
46{
47
48const int INFINITE_LATENCY = 10000; // Yes, this is a big hack
49
50// Note: In this file, we use the first 2*m_nodes SwitchIDs to
51// represent the input and output endpoint links. These really are
52// not 'switches', as they will not have a Switch object allocated for
53// them. The first m_nodes SwitchIDs are the links into the network,
54// the second m_nodes set of SwitchIDs represent the the output queues
55// of the network.
56
57Topology::Topology(uint32_t num_nodes, uint32_t num_routers,
58 uint32_t num_vnets,
59 const std::vector<BasicExtLink *> &ext_links,
60 const std::vector<BasicIntLink *> &int_links,
61 RubySystem *ruby_system)
62 : m_nodes(ruby_system->MachineType_base_number(MachineType_NUM)),
63 m_number_of_switches(num_routers), m_vnets(num_vnets),
64 m_ext_link_vector(ext_links), m_int_link_vector(int_links),
65 m_ruby_system(ruby_system)
66{
67 // Total nodes/controllers in network
68 assert(m_nodes > 1);
69
70 // analyze both the internal and external links, create data structures.
71 // The python created external links are bi-directional,
72 // and the python created internal links are uni-directional.
73 // The networks and topology utilize uni-directional links.
74 // Thus each external link is converted to two calls to addLink,
75 // one for each direction.
76 //
77 // External Links
78 for (std::vector<BasicExtLink*>::const_iterator i = ext_links.begin();
79 i != ext_links.end(); ++i) {
80 BasicExtLink *ext_link = (*i);
81 AbstractController *abs_cntrl = ext_link->params().ext_node;
82 BasicRouter *router = ext_link->params().int_node;
83
84 int machine_base_idx =
85 ruby_system->MachineType_base_number(abs_cntrl->getType());
86 int ext_idx1 = machine_base_idx + abs_cntrl->getVersion();
87 int ext_idx2 = ext_idx1 + m_nodes;
88 int int_idx = router->params().router_id + 2*m_nodes;
89
90 // create the internal uni-directional links in both directions
91 // ext to int
92 addLink(ext_idx1, int_idx, ext_link);
93 // int to ext
94 addLink(int_idx, ext_idx2, ext_link);
95 }
96
97 // Internal Links
98 for (std::vector<BasicIntLink*>::const_iterator i = int_links.begin();
99 i != int_links.end(); ++i) {
100 BasicIntLink *int_link = (*i);
101 BasicRouter *router_src = int_link->params().src_node;
102 BasicRouter *router_dst = int_link->params().dst_node;
103
104 PortDirection src_outport = int_link->params().src_outport;
105 PortDirection dst_inport = int_link->params().dst_inport;
106
107 // Store the IntLink pointers for later
108 m_int_link_vector.push_back(int_link);
109
110 int src = router_src->params().router_id + 2*m_nodes;
111 int dst = router_dst->params().router_id + 2*m_nodes;
112
113 // create the internal uni-directional link from src to dst
114 addLink(src, dst, int_link, src_outport, dst_inport);
115 }
116}
117
118void
120{
121 // Find maximum switchID
122 SwitchID max_switch_id = 0;
123 for (LinkMap::const_iterator i = m_link_map.begin();
124 i != m_link_map.end(); ++i) {
125 std::pair<SwitchID, SwitchID> src_dest = (*i).first;
126 max_switch_id = std::max(max_switch_id, src_dest.first);
127 max_switch_id = std::max(max_switch_id, src_dest.second);
128 }
129
130 // Initialize weight, latency, and inter switched vectors
131 int num_switches = max_switch_id+1;
132 Matrix topology_weights(m_vnets,
133 std::vector<std::vector<int>>(num_switches,
134 std::vector<int>(num_switches, INFINITE_LATENCY)));
135 Matrix component_latencies(num_switches,
136 std::vector<std::vector<int>>(num_switches,
138 Matrix component_inter_switches(num_switches,
139 std::vector<std::vector<int>>(num_switches,
141
142 // Set identity weights to zero
143 for (int i = 0; i < topology_weights[0].size(); i++) {
144 for (int v = 0; v < m_vnets; v++) {
145 topology_weights[v][i][i] = 0;
146 }
147 }
148
149 // Fill in the topology weights and bandwidth multipliers
150 for (auto link_group : m_link_map) {
151 std::pair<int, int> src_dest = link_group.first;
152 std::vector<bool> vnet_done(m_vnets, 0);
153 int src = src_dest.first;
154 int dst = src_dest.second;
155
156 // Iterate over all links for this source and destination
157 std::vector<LinkEntry> link_entries = link_group.second;
158 for (int l = 0; l < link_entries.size(); l++) {
159 BasicLink* link = link_entries[l].link;
160 if (link->mVnets.size() == 0) {
161 for (int v = 0; v < m_vnets; v++) {
162 // Two links connecting same src and destination
163 // cannot carry same vnets.
164 fatal_if(vnet_done[v], "Two links connecting same src"
165 " and destination cannot support same vnets");
166
167 component_latencies[src][dst][v] = link->m_latency;
168 topology_weights[v][src][dst] = link->m_weight;
169 vnet_done[v] = true;
170 }
171 } else {
172 for (int v = 0; v < link->mVnets.size(); v++) {
173 int vnet = link->mVnets[v];
174 fatal_if(vnet >= m_vnets, "Not enough virtual networks "
175 "(setting latency and weight for vnet %d)", vnet);
176 // Two links connecting same src and destination
177 // cannot carry same vnets.
178 fatal_if(vnet_done[vnet], "Two links connecting same src"
179 " and destination cannot support same vnets");
180
181 component_latencies[src][dst][vnet] = link->m_latency;
182 topology_weights[vnet][src][dst] = link->m_weight;
183 vnet_done[vnet] = true;
184 }
185 }
186 }
187 }
188
189 // Walk topology and hookup the links
190 Matrix dist = shortest_path(topology_weights, component_latencies,
191 component_inter_switches);
192
193 for (int i = 0; i < topology_weights[0].size(); i++) {
194 for (int j = 0; j < topology_weights[0][i].size(); j++) {
195 std::vector<NetDest> routingMap;
196 routingMap.resize(m_vnets, m_ruby_system);
197
198 // Not all sources and destinations are connected
199 // by direct links. We only construct the links
200 // which have been configured in topology.
201 bool realLink = false;
202
203 for (int v = 0; v < m_vnets; v++) {
204 int weight = topology_weights[v][i][j];
205 if (weight > 0 && weight != INFINITE_LATENCY) {
206 realLink = true;
207 routingMap[v] =
208 shortest_path_to_node(i, j, topology_weights, dist, v);
209 }
210 }
211 // Make one link for each set of vnets between
212 // a given source and destination. We do not
213 // want to create one link for each vnet.
214 if (realLink) {
215 makeLink(net, i, j, routingMap);
216 }
217 }
218 }
219}
220
221void
223 PortDirection src_outport_dirn,
224 PortDirection dst_inport_dirn)
225{
226 assert(src <= m_number_of_switches+m_nodes+m_nodes);
227 assert(dest <= m_number_of_switches+m_nodes+m_nodes);
228
229 std::pair<int, int> src_dest_pair;
230 src_dest_pair.first = src;
231 src_dest_pair.second = dest;
232 LinkEntry link_entry;
233
234 link_entry.link = link;
235 link_entry.src_outport_dirn = src_outport_dirn;
236 link_entry.dst_inport_dirn = dst_inport_dirn;
237
238 auto lit = m_link_map.find(src_dest_pair);
239 if (lit != m_link_map.end()) {
240 // HeteroGarnet allows multiple links between
241 // same source-destination pair supporting
242 // different vnets. If there is a link already
243 // between a given pair of source and destination
244 // add this new link to it.
245 lit->second.push_back(link_entry);
246 } else {
248 links.push_back(link_entry);
249 m_link_map[src_dest_pair] = links;
250 }
251}
252
253void
255 std::vector<NetDest>& routing_table_entry)
256{
257 // Make sure we're not trying to connect two end-point nodes
258 // directly together
259 assert(src >= 2 * m_nodes || dest >= 2 * m_nodes);
260
261 std::pair<int, int> src_dest;
262 LinkEntry link_entry;
263
264 if (src < m_nodes) {
265 src_dest.first = src;
266 src_dest.second = dest;
267 std::vector<LinkEntry> links = m_link_map[src_dest];
268 for (int l = 0; l < links.size(); l++) {
269 link_entry = links[l];
270 std::vector<NetDest> linkRoute;
271 linkRoute.resize(m_vnets, m_ruby_system);
272 BasicLink *link = link_entry.link;
273 if (link->mVnets.size() == 0) {
274 net->makeExtInLink(src, dest - (2 * m_nodes), link,
275 routing_table_entry);
276 } else {
277 for (int v = 0; v< link->mVnets.size(); v++) {
278 int vnet = link->mVnets[v];
279 linkRoute[vnet] = routing_table_entry[vnet];
280 }
281 net->makeExtInLink(src, dest - (2 * m_nodes), link,
282 linkRoute);
283 }
284 }
285 } else if (dest < 2*m_nodes) {
286 assert(dest >= m_nodes);
287 NodeID node = dest - m_nodes;
288 src_dest.first = src;
289 src_dest.second = dest;
290 std::vector<LinkEntry> links = m_link_map[src_dest];
291 for (int l = 0; l < links.size(); l++) {
292 link_entry = links[l];
293 std::vector<NetDest> linkRoute;
294 linkRoute.resize(m_vnets, m_ruby_system);
295 BasicLink *link = link_entry.link;
296 if (link->mVnets.size() == 0) {
297 net->makeExtOutLink(src - (2 * m_nodes), node, link,
298 routing_table_entry);
299 } else {
300 for (int v = 0; v< link->mVnets.size(); v++) {
301 int vnet = link->mVnets[v];
302 linkRoute[vnet] = routing_table_entry[vnet];
303 }
304 net->makeExtOutLink(src - (2 * m_nodes), node, link,
305 linkRoute);
306 }
307 }
308 } else {
309 assert((src >= 2 * m_nodes) && (dest >= 2 * m_nodes));
310 src_dest.first = src;
311 src_dest.second = dest;
312 std::vector<LinkEntry> links = m_link_map[src_dest];
313 for (int l = 0; l < links.size(); l++) {
314 link_entry = links[l];
315 std::vector<NetDest> linkRoute;
316 linkRoute.resize(m_vnets, m_ruby_system);
317 BasicLink *link = link_entry.link;
318 if (link->mVnets.size() == 0) {
319 net->makeInternalLink(src - (2 * m_nodes),
320 dest - (2 * m_nodes), link, routing_table_entry,
321 link_entry.src_outport_dirn,
322 link_entry.dst_inport_dirn);
323 } else {
324 for (int v = 0; v< link->mVnets.size(); v++) {
325 int vnet = link->mVnets[v];
326 linkRoute[vnet] = routing_table_entry[vnet];
327 }
328 net->makeInternalLink(src - (2 * m_nodes),
329 dest - (2 * m_nodes), link, linkRoute,
330 link_entry.src_outport_dirn,
331 link_entry.dst_inport_dirn);
332 }
333 }
334 }
335}
336
337// The following all-pairs shortest path algorithm is based on the
338// discussion from Cormen et al., Chapter 26.1.
339void
341 Matrix &inter_switches)
342{
343 int nodes = current_dist[0].size();
344
345 // We find the shortest path for each vnet for a given pair of
346 // source and destinations. This is done simply by traversing via
347 // all other nodes and finding the minimum distance.
348 for (int v = 0; v < m_vnets; v++) {
349 // There is a different topology for each vnet. Here we try to
350 // build a topology by finding the minimum number of intermediate
351 // switches needed to reach the destination
352 bool change = true;
353 while (change) {
354 change = false;
355 for (int i = 0; i < nodes; i++) {
356 for (int j = 0; j < nodes; j++) {
357 // We follow an iterative process to build the shortest
358 // path tree:
359 // 1. Start from the direct connection (if there is one,
360 // otherwise assume a hypothetical infinite weight link).
361 // 2. Then we iterate through all other nodes considering
362 // new potential intermediate switches. If we find any
363 // lesser weight combination, we set(update) that as the
364 // new weight between the source and destination.
365 // 3. Repeat for all pairs of nodes.
366 // 4. Go to step 1 if there was any new update done in
367 // Step 2.
368 int minimum = current_dist[v][i][j];
369 int previous_minimum = minimum;
370 int intermediate_switch = -1;
371 for (int k = 0; k < nodes; k++) {
372 minimum = std::min(minimum,
373 current_dist[v][i][k] + current_dist[v][k][j]);
374 if (previous_minimum != minimum) {
375 intermediate_switch = k;
376 inter_switches[i][j][v] =
377 inter_switches[i][k][v] +
378 inter_switches[k][j][v] + 1;
379 }
380 previous_minimum = minimum;
381 }
382 if (current_dist[v][i][j] != minimum) {
383 change = true;
384 current_dist[v][i][j] = minimum;
385 assert(intermediate_switch >= 0);
386 assert(intermediate_switch < latencies[i].size());
387 latencies[i][j][v] =
388 latencies[i][intermediate_switch][v] +
389 latencies[intermediate_switch][j][v];
390 }
391 }
392 }
393 }
394 }
395}
396
397Matrix
398Topology::shortest_path(const Matrix &weights, Matrix &latencies,
399 Matrix &inter_switches)
400{
401 Matrix dist = weights;
402 extend_shortest_path(dist, latencies, inter_switches);
403 return dist;
404}
405
406bool
408 SwitchID final, const Matrix &weights,
409 const Matrix &dist, int vnet)
410{
411 return weights[vnet][src][next] + dist[vnet][next][final] ==
412 dist[vnet][src][final];
413}
414
417 const Matrix &weights, const Matrix &dist,
418 int vnet)
419{
420 NetDest result(m_ruby_system);
421 int d = 0;
422 int machines;
423 int max_machines;
424
425 machines = MachineType_NUM;
426 max_machines = m_ruby_system->MachineType_base_number(MachineType_NUM);
427
428 for (int m = 0; m < machines; m++) {
429 for (NodeID i = 0;
430 i < m_ruby_system->MachineType_base_count((MachineType)m); i++) {
431 // we use "d+max_machines" below since the "destination"
432 // switches for the machines are numbered
433 // [MachineType_base_number(MachineType_NUM)...
434 // 2*MachineType_base_number(MachineType_NUM)-1] for the
435 // component network
436 if (link_is_shortest_path_to_node(src, next, d + max_machines,
437 weights, dist, vnet)) {
438 MachineID mach = {(MachineType)m, i};
439 result.add(mach);
440 }
441 d++;
442 }
443 }
444
445 DPRINTF(RubyNetwork, "Returning shortest path\n"
446 "(src-(2*max_machines)): %d, (next-(2*max_machines)): %d, "
447 "src: %d, next: %d, vnet:%d result: %s\n",
448 (src-(2*max_machines)), (next-(2*max_machines)),
449 src, next, vnet, result);
450
451 return result;
452}
453
454} // namespace ruby
455} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:209
void add(MachineID newElement)
Definition NetDest.cc:52
virtual void makeInternalLink(SwitchID src, SwitchID dest, BasicLink *link, std::vector< NetDest > &routing_table_entry, PortDirection src_outport, PortDirection dst_inport)=0
virtual void makeExtOutLink(SwitchID src, NodeID dest, BasicLink *link, std::vector< NetDest > &routing_table_entry)=0
virtual void makeExtInLink(NodeID src, SwitchID dest, BasicLink *link, std::vector< NetDest > &routing_table_entry)=0
int MachineType_base_number(const MachineType &obj)
int MachineType_base_count(const MachineType &obj)
std::vector< BasicIntLink * > m_int_link_vector
Definition Topology.hh:117
void makeLink(Network *net, SwitchID src, SwitchID dest, std::vector< NetDest > &routing_table_entry)
Definition Topology.cc:254
RubySystem * m_ruby_system
Definition Topology.hh:121
void addLink(SwitchID src, SwitchID dest, BasicLink *link, PortDirection src_outport_dirn="", PortDirection dest_inport_dirn="")
Definition Topology.cc:222
const uint32_t m_number_of_switches
Definition Topology.hh:113
void createLinks(Network *net)
Definition Topology.cc:119
void extend_shortest_path(Matrix &current_dist, Matrix &latencies, Matrix &inter_switches)
Definition Topology.cc:340
bool link_is_shortest_path_to_node(SwitchID src, SwitchID next, SwitchID final, const Matrix &weights, const Matrix &dist, int vnet)
Definition Topology.cc:407
Matrix shortest_path(const Matrix &weights, Matrix &latencies, Matrix &inter_switches)
Definition Topology.cc:398
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, RubySystem *ruby_system)
Definition Topology.cc:57
NetDest shortest_path_to_node(SwitchID src, SwitchID next, const Matrix &weights, const Matrix &dist, int vnet)
Definition Topology.cc:416
STL pair class.
Definition stl.hh:58
STL vector class.
Definition stl.hh:37
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:236
const Params & params() const
Bitfield< 28 > v
Definition misc_types.hh:54
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 9 > d
Definition misc_types.hh:64
Bitfield< 0 > m
Bitfield< 5 > l
Bitfield< 23 > k
unsigned int SwitchID
std::string PortDirection
unsigned int NodeID
const int INFINITE_LATENCY
Definition Topology.cc:48
const FlagsType dist
Print the distribution.
Definition info.hh:65
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
PortDirection dst_inport_dirn
Definition Topology.hh:72
PortDirection src_outport_dirn
Definition Topology.hh:71

Generated on Mon Jan 13 2025 04:28:40 for gem5 by doxygen 1.9.8