arch-arm: Initialize some cases of destReg
[gem5.git] / src / mem / ruby / network / garnet2.0 / GarnetNetwork.cc
1 /*
2 * Copyright (c) 2020 Advanced Micro Devices, Inc.
3 * Copyright (c) 2008 Princeton University
4 * Copyright (c) 2016 Georgia Institute of Technology
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met: redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer;
11 * redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution;
14 * neither the name of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31
32 #include "mem/ruby/network/garnet2.0/GarnetNetwork.hh"
33
34 #include <cassert>
35
36 #include "base/cast.hh"
37 #include "debug/RubyNetwork.hh"
38 #include "mem/ruby/common/NetDest.hh"
39 #include "mem/ruby/network/MessageBuffer.hh"
40 #include "mem/ruby/network/garnet2.0/CommonTypes.hh"
41 #include "mem/ruby/network/garnet2.0/CreditLink.hh"
42 #include "mem/ruby/network/garnet2.0/GarnetLink.hh"
43 #include "mem/ruby/network/garnet2.0/NetworkInterface.hh"
44 #include "mem/ruby/network/garnet2.0/NetworkLink.hh"
45 #include "mem/ruby/network/garnet2.0/Router.hh"
46 #include "mem/ruby/system/RubySystem.hh"
47
48 using namespace std;
49
50 /*
51 * GarnetNetwork sets up the routers and links and collects stats.
52 * Default parameters (GarnetNetwork.py) can be overwritten from command line
53 * (see configs/network/Network.py)
54 */
55
56 GarnetNetwork::GarnetNetwork(const Params *p)
57 : Network(p)
58 {
59 m_num_rows = p->num_rows;
60 m_ni_flit_size = p->ni_flit_size;
61 m_max_vcs_per_vnet = 0;
62 m_buffers_per_data_vc = p->buffers_per_data_vc;
63 m_buffers_per_ctrl_vc = p->buffers_per_ctrl_vc;
64 m_routing_algorithm = p->routing_algorithm;
65
66 m_enable_fault_model = p->enable_fault_model;
67 if (m_enable_fault_model)
68 fault_model = p->fault_model;
69
70 m_vnet_type.resize(m_virtual_networks);
71
72 for (int i = 0 ; i < m_virtual_networks ; i++) {
73 if (m_vnet_type_names[i] == "response")
74 m_vnet_type[i] = DATA_VNET_; // carries data (and ctrl) packets
75 else
76 m_vnet_type[i] = CTRL_VNET_; // carries only ctrl packets
77 }
78
79 // record the routers
80 for (vector<BasicRouter*>::const_iterator i = p->routers.begin();
81 i != p->routers.end(); ++i) {
82 Router* router = safe_cast<Router*>(*i);
83 m_routers.push_back(router);
84
85 // initialize the router's network pointers
86 router->init_net_ptr(this);
87 }
88
89 // record the network interfaces
90 for (vector<ClockedObject*>::const_iterator i = p->netifs.begin();
91 i != p->netifs.end(); ++i) {
92 NetworkInterface *ni = safe_cast<NetworkInterface *>(*i);
93 m_nis.push_back(ni);
94 ni->init_net_ptr(this);
95 }
96 }
97
98 void
99 GarnetNetwork::init()
100 {
101 Network::init();
102
103 for (int i=0; i < m_nodes; i++) {
104 m_nis[i]->addNode(m_toNetQueues[i], m_fromNetQueues[i]);
105 }
106
107 // The topology pointer should have already been initialized in the
108 // parent network constructor
109 assert(m_topology_ptr != NULL);
110 m_topology_ptr->createLinks(this);
111
112 // Initialize topology specific parameters
113 if (getNumRows() > 0) {
114 // Only for Mesh topology
115 // m_num_rows and m_num_cols are only used for
116 // implementing XY or custom routing in RoutingUnit.cc
117 m_num_rows = getNumRows();
118 m_num_cols = m_routers.size() / m_num_rows;
119 assert(m_num_rows * m_num_cols == m_routers.size());
120 } else {
121 m_num_rows = -1;
122 m_num_cols = -1;
123 }
124
125 // FaultModel: declare each router to the fault model
126 if (isFaultModelEnabled()) {
127 for (vector<Router*>::const_iterator i= m_routers.begin();
128 i != m_routers.end(); ++i) {
129 Router* router = safe_cast<Router*>(*i);
130 int router_id M5_VAR_USED =
131 fault_model->declare_router(router->get_num_inports(),
132 router->get_num_outports(),
133 router->get_vc_per_vnet(),
134 getBuffersPerDataVC(),
135 getBuffersPerCtrlVC());
136 assert(router_id == router->get_id());
137 router->printAggregateFaultProbability(cout);
138 router->printFaultVector(cout);
139 }
140 }
141 }
142
143 /*
144 * This function creates a link from the Network Interface (NI)
145 * into the Network.
146 * It creates a Network Link from the NI to a Router and a Credit Link from
147 * the Router to the NI
148 */
149
150 void
151 GarnetNetwork::makeExtInLink(NodeID global_src, SwitchID dest, BasicLink* link,
152 std::vector<NetDest>& routing_table_entry)
153 {
154 NodeID local_src = getLocalNodeID(global_src);
155 assert(local_src < m_nodes);
156
157 GarnetExtLink* garnet_link = safe_cast<GarnetExtLink*>(link);
158
159 // GarnetExtLink is bi-directional
160 NetworkLink* net_link = garnet_link->m_network_links[LinkDirection_In];
161 net_link->setType(EXT_IN_);
162 CreditLink* credit_link = garnet_link->m_credit_links[LinkDirection_In];
163
164 m_networklinks.push_back(net_link);
165 m_creditlinks.push_back(credit_link);
166
167 PortDirection dst_inport_dirn = "Local";
168
169 m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
170 m_routers[dest]->get_vc_per_vnet());
171
172 /*
173 * We check if a bridge was enabled at any end of the link.
174 * The bridge is enabled if either of clock domain
175 * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
176 * enabled for the link at each end. The bridge encapsulates
177 * the functionality for both CDC and SerDes and is a Consumer
178 * object similiar to a NetworkLink.
179 *
180 * If a bridge was enabled we connect the NI and Routers to
181 * bridge before connecting the link. Example, if an external
182 * bridge is enabled, we would connect:
183 * NI--->NetworkBridge--->GarnetExtLink---->Router
184 */
185 if (garnet_link->extBridgeEn) {
186 DPRINTF(RubyNetwork, "Enable external bridge for %s\n",
187 garnet_link->name());
188 m_nis[local_src]->
189 addOutPort(garnet_link->extNetBridge[LinkDirection_In],
190 garnet_link->extCredBridge[LinkDirection_In],
191 dest, m_routers[dest]->get_vc_per_vnet());
192 } else {
193 m_nis[local_src]->addOutPort(net_link, credit_link, dest,
194 m_routers[dest]->get_vc_per_vnet());
195 }
196
197 if (garnet_link->intBridgeEn) {
198 DPRINTF(RubyNetwork, "Enable internal bridge for %s\n",
199 garnet_link->name());
200 m_routers[dest]->
201 addInPort(dst_inport_dirn,
202 garnet_link->intNetBridge[LinkDirection_In],
203 garnet_link->intCredBridge[LinkDirection_In]);
204 } else {
205 m_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
206 }
207
208 }
209
210 /*
211 * This function creates a link from the Network to a NI.
212 * It creates a Network Link from a Router to the NI and
213 * a Credit Link from NI to the Router
214 */
215
216 void
217 GarnetNetwork::makeExtOutLink(SwitchID src, NodeID global_dest,
218 BasicLink* link,
219 std::vector<NetDest>& routing_table_entry)
220 {
221 NodeID local_dest = getLocalNodeID(global_dest);
222 assert(local_dest < m_nodes);
223 assert(src < m_routers.size());
224 assert(m_routers[src] != NULL);
225
226 GarnetExtLink* garnet_link = safe_cast<GarnetExtLink*>(link);
227
228 // GarnetExtLink is bi-directional
229 NetworkLink* net_link = garnet_link->m_network_links[LinkDirection_Out];
230 net_link->setType(EXT_OUT_);
231 CreditLink* credit_link = garnet_link->m_credit_links[LinkDirection_Out];
232
233 m_networklinks.push_back(net_link);
234 m_creditlinks.push_back(credit_link);
235
236 PortDirection src_outport_dirn = "Local";
237
238 m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
239 m_routers[src]->get_vc_per_vnet());
240
241 /*
242 * We check if a bridge was enabled at any end of the link.
243 * The bridge is enabled if either of clock domain
244 * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
245 * enabled for the link at each end. The bridge encapsulates
246 * the functionality for both CDC and SerDes and is a Consumer
247 * object similiar to a NetworkLink.
248 *
249 * If a bridge was enabled we connect the NI and Routers to
250 * bridge before connecting the link. Example, if an external
251 * bridge is enabled, we would connect:
252 * NI<---NetworkBridge<---GarnetExtLink<----Router
253 */
254 if (garnet_link->extBridgeEn) {
255 DPRINTF(RubyNetwork, "Enable external bridge for %s\n",
256 garnet_link->name());
257 m_nis[local_dest]->
258 addInPort(garnet_link->extNetBridge[LinkDirection_Out],
259 garnet_link->extCredBridge[LinkDirection_Out]);
260 } else {
261 m_nis[local_dest]->addInPort(net_link, credit_link);
262 }
263
264 if (garnet_link->intBridgeEn) {
265 DPRINTF(RubyNetwork, "Enable internal bridge for %s\n",
266 garnet_link->name());
267 m_routers[src]->
268 addOutPort(src_outport_dirn,
269 garnet_link->intNetBridge[LinkDirection_Out],
270 routing_table_entry, link->m_weight,
271 garnet_link->intCredBridge[LinkDirection_Out],
272 m_routers[src]->get_vc_per_vnet());
273 } else {
274 m_routers[src]->
275 addOutPort(src_outport_dirn, net_link,
276 routing_table_entry,
277 link->m_weight, credit_link,
278 m_routers[src]->get_vc_per_vnet());
279 }
280 }
281
282 /*
283 * This function creates an internal network link between two routers.
284 * It adds both the network link and an opposite credit link.
285 */
286
287 void
288 GarnetNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
289 std::vector<NetDest>& routing_table_entry,
290 PortDirection src_outport_dirn,
291 PortDirection dst_inport_dirn)
292 {
293 GarnetIntLink* garnet_link = safe_cast<GarnetIntLink*>(link);
294
295 // GarnetIntLink is unidirectional
296 NetworkLink* net_link = garnet_link->m_network_link;
297 net_link->setType(INT_);
298 CreditLink* credit_link = garnet_link->m_credit_link;
299
300 m_networklinks.push_back(net_link);
301 m_creditlinks.push_back(credit_link);
302
303 m_max_vcs_per_vnet = std::max(m_max_vcs_per_vnet,
304 std::max(m_routers[dest]->get_vc_per_vnet(),
305 m_routers[src]->get_vc_per_vnet()));
306
307 /*
308 * We check if a bridge was enabled at any end of the link.
309 * The bridge is enabled if either of clock domain
310 * crossing (CDC) or Serializer-Deserializer(SerDes) unit is
311 * enabled for the link at each end. The bridge encapsulates
312 * the functionality for both CDC and SerDes and is a Consumer
313 * object similiar to a NetworkLink.
314 *
315 * If a bridge was enabled we connect the NI and Routers to
316 * bridge before connecting the link. Example, if a source
317 * bridge is enabled, we would connect:
318 * Router--->NetworkBridge--->GarnetIntLink---->Router
319 */
320 if (garnet_link->dstBridgeEn) {
321 DPRINTF(RubyNetwork, "Enable destination bridge for %s\n",
322 garnet_link->name());
323 m_routers[dest]->addInPort(dst_inport_dirn,
324 garnet_link->dstNetBridge, garnet_link->dstCredBridge);
325 } else {
326 m_routers[dest]->addInPort(dst_inport_dirn, net_link, credit_link);
327 }
328
329 if (garnet_link->srcBridgeEn) {
330 DPRINTF(RubyNetwork, "Enable source bridge for %s\n",
331 garnet_link->name());
332 m_routers[src]->
333 addOutPort(src_outport_dirn, garnet_link->srcNetBridge,
334 routing_table_entry,
335 link->m_weight, garnet_link->srcCredBridge,
336 m_routers[dest]->get_vc_per_vnet());
337 } else {
338 m_routers[src]->addOutPort(src_outport_dirn, net_link,
339 routing_table_entry,
340 link->m_weight, credit_link,
341 m_routers[dest]->get_vc_per_vnet());
342 }
343 }
344
345 // Total routers in the network
346 int
347 GarnetNetwork::getNumRouters()
348 {
349 return m_routers.size();
350 }
351
352 // Get ID of router connected to a NI.
353 int
354 GarnetNetwork::get_router_id(int global_ni, int vnet)
355 {
356 NodeID local_ni = getLocalNodeID(global_ni);
357
358 return m_nis[local_ni]->get_router_id(vnet);
359 }
360
361 void
362 GarnetNetwork::regStats()
363 {
364 Network::regStats();
365
366 // Packets
367 m_packets_received
368 .init(m_virtual_networks)
369 .name(name() + ".packets_received")
370 .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
371 ;
372
373 m_packets_injected
374 .init(m_virtual_networks)
375 .name(name() + ".packets_injected")
376 .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
377 ;
378
379 m_packet_network_latency
380 .init(m_virtual_networks)
381 .name(name() + ".packet_network_latency")
382 .flags(Stats::oneline)
383 ;
384
385 m_packet_queueing_latency
386 .init(m_virtual_networks)
387 .name(name() + ".packet_queueing_latency")
388 .flags(Stats::oneline)
389 ;
390
391 for (int i = 0; i < m_virtual_networks; i++) {
392 m_packets_received.subname(i, csprintf("vnet-%i", i));
393 m_packets_injected.subname(i, csprintf("vnet-%i", i));
394 m_packet_network_latency.subname(i, csprintf("vnet-%i", i));
395 m_packet_queueing_latency.subname(i, csprintf("vnet-%i", i));
396 }
397
398 m_avg_packet_vnet_latency
399 .name(name() + ".average_packet_vnet_latency")
400 .flags(Stats::oneline);
401 m_avg_packet_vnet_latency =
402 m_packet_network_latency / m_packets_received;
403
404 m_avg_packet_vqueue_latency
405 .name(name() + ".average_packet_vqueue_latency")
406 .flags(Stats::oneline);
407 m_avg_packet_vqueue_latency =
408 m_packet_queueing_latency / m_packets_received;
409
410 m_avg_packet_network_latency
411 .name(name() + ".average_packet_network_latency");
412 m_avg_packet_network_latency =
413 sum(m_packet_network_latency) / sum(m_packets_received);
414
415 m_avg_packet_queueing_latency
416 .name(name() + ".average_packet_queueing_latency");
417 m_avg_packet_queueing_latency
418 = sum(m_packet_queueing_latency) / sum(m_packets_received);
419
420 m_avg_packet_latency
421 .name(name() + ".average_packet_latency");
422 m_avg_packet_latency
423 = m_avg_packet_network_latency + m_avg_packet_queueing_latency;
424
425 // Flits
426 m_flits_received
427 .init(m_virtual_networks)
428 .name(name() + ".flits_received")
429 .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
430 ;
431
432 m_flits_injected
433 .init(m_virtual_networks)
434 .name(name() + ".flits_injected")
435 .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
436 ;
437
438 m_flit_network_latency
439 .init(m_virtual_networks)
440 .name(name() + ".flit_network_latency")
441 .flags(Stats::oneline)
442 ;
443
444 m_flit_queueing_latency
445 .init(m_virtual_networks)
446 .name(name() + ".flit_queueing_latency")
447 .flags(Stats::oneline)
448 ;
449
450 for (int i = 0; i < m_virtual_networks; i++) {
451 m_flits_received.subname(i, csprintf("vnet-%i", i));
452 m_flits_injected.subname(i, csprintf("vnet-%i", i));
453 m_flit_network_latency.subname(i, csprintf("vnet-%i", i));
454 m_flit_queueing_latency.subname(i, csprintf("vnet-%i", i));
455 }
456
457 m_avg_flit_vnet_latency
458 .name(name() + ".average_flit_vnet_latency")
459 .flags(Stats::oneline);
460 m_avg_flit_vnet_latency = m_flit_network_latency / m_flits_received;
461
462 m_avg_flit_vqueue_latency
463 .name(name() + ".average_flit_vqueue_latency")
464 .flags(Stats::oneline);
465 m_avg_flit_vqueue_latency =
466 m_flit_queueing_latency / m_flits_received;
467
468 m_avg_flit_network_latency
469 .name(name() + ".average_flit_network_latency");
470 m_avg_flit_network_latency =
471 sum(m_flit_network_latency) / sum(m_flits_received);
472
473 m_avg_flit_queueing_latency
474 .name(name() + ".average_flit_queueing_latency");
475 m_avg_flit_queueing_latency =
476 sum(m_flit_queueing_latency) / sum(m_flits_received);
477
478 m_avg_flit_latency
479 .name(name() + ".average_flit_latency");
480 m_avg_flit_latency =
481 m_avg_flit_network_latency + m_avg_flit_queueing_latency;
482
483
484 // Hops
485 m_avg_hops.name(name() + ".average_hops");
486 m_avg_hops = m_total_hops / sum(m_flits_received);
487
488 // Links
489 m_total_ext_in_link_utilization
490 .name(name() + ".ext_in_link_utilization");
491 m_total_ext_out_link_utilization
492 .name(name() + ".ext_out_link_utilization");
493 m_total_int_link_utilization
494 .name(name() + ".int_link_utilization");
495 m_average_link_utilization
496 .name(name() + ".avg_link_utilization");
497 m_average_vc_load
498 .init(m_virtual_networks * m_max_vcs_per_vnet)
499 .name(name() + ".avg_vc_load")
500 .flags(Stats::pdf | Stats::total | Stats::nozero | Stats::oneline)
501 ;
502 }
503
504 void
505 GarnetNetwork::collateStats()
506 {
507 RubySystem *rs = params()->ruby_system;
508 double time_delta = double(curCycle() - rs->getStartCycle());
509
510 for (int i = 0; i < m_networklinks.size(); i++) {
511 link_type type = m_networklinks[i]->getType();
512 int activity = m_networklinks[i]->getLinkUtilization();
513
514 if (type == EXT_IN_)
515 m_total_ext_in_link_utilization += activity;
516 else if (type == EXT_OUT_)
517 m_total_ext_out_link_utilization += activity;
518 else if (type == INT_)
519 m_total_int_link_utilization += activity;
520
521 m_average_link_utilization +=
522 (double(activity) / time_delta);
523
524 vector<unsigned int> vc_load = m_networklinks[i]->getVcLoad();
525 for (int j = 0; j < vc_load.size(); j++) {
526 m_average_vc_load[j] += ((double)vc_load[j] / time_delta);
527 }
528 }
529
530 // Ask the routers to collate their statistics
531 for (int i = 0; i < m_routers.size(); i++) {
532 m_routers[i]->collateStats();
533 }
534 }
535
536 void
537 GarnetNetwork::resetStats()
538 {
539 for (int i = 0; i < m_routers.size(); i++) {
540 m_routers[i]->resetStats();
541 }
542 for (int i = 0; i < m_networklinks.size(); i++) {
543 m_networklinks[i]->resetStats();
544 }
545 for (int i = 0; i < m_creditlinks.size(); i++) {
546 m_creditlinks[i]->resetStats();
547 }
548 }
549
550 void
551 GarnetNetwork::print(ostream& out) const
552 {
553 out << "[GarnetNetwork]";
554 }
555
556 GarnetNetwork *
557 GarnetNetworkParams::create()
558 {
559 return new GarnetNetwork(this);
560 }
561
562 uint32_t
563 GarnetNetwork::functionalWrite(Packet *pkt)
564 {
565 uint32_t num_functional_writes = 0;
566
567 for (unsigned int i = 0; i < m_routers.size(); i++) {
568 num_functional_writes += m_routers[i]->functionalWrite(pkt);
569 }
570
571 for (unsigned int i = 0; i < m_nis.size(); ++i) {
572 num_functional_writes += m_nis[i]->functionalWrite(pkt);
573 }
574
575 for (unsigned int i = 0; i < m_networklinks.size(); ++i) {
576 num_functional_writes += m_networklinks[i]->functionalWrite(pkt);
577 }
578
579 return num_functional_writes;
580 }