garnet: Added topology print function to Garnet printStats
[gem5.git] / src / mem / ruby / network / garnet / fixed-pipeline / GarnetNetwork_d.cc
1 /*
2 * Copyright (c) 2008 Princeton University
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Niket Agarwal
29 */
30
31 #include "base/stl_helpers.hh"
32 #include "mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.hh"
33 #include "mem/protocol/MachineType.hh"
34 #include "mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.hh"
35 #include "mem/ruby/buffers/MessageBuffer.hh"
36 #include "mem/ruby/network/garnet/fixed-pipeline/Router_d.hh"
37 #include "mem/ruby/network/simple/Topology.hh"
38 #include "mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.hh"
39 #include "mem/ruby/network/garnet/fixed-pipeline/CreditLink_d.hh"
40 #include "mem/ruby/common/NetDest.hh"
41
42 using namespace std;
43 using m5::stl_helpers::deletePointers;
44
45 GarnetNetwork_d::GarnetNetwork_d(const Params *p)
46 : BaseGarnetNetwork(p)
47 {
48 m_ruby_start = 0;
49 m_flits_received = 0;
50 m_flits_injected = 0;
51 m_network_latency = 0.0;
52 m_queueing_latency = 0.0;
53
54 m_router_ptr_vector.clear();
55
56 // Queues that are getting messages from protocol
57 m_toNetQueues.resize(m_nodes);
58
59 // Queues that are feeding the protocol
60 m_fromNetQueues.resize(m_nodes);
61 m_in_use.resize(m_virtual_networks);
62 m_ordered.resize(m_virtual_networks);
63 for (int i = 0; i < m_virtual_networks; i++) {
64 m_in_use[i] = false;
65 m_ordered[i] = false;
66 }
67
68 for (int node = 0; node < m_nodes; node++) {
69 // Setting how many vitual message buffers
70 // will there be per Network Queue
71 m_toNetQueues[node].resize(m_virtual_networks);
72 m_fromNetQueues[node].resize(m_virtual_networks);
73
74 // Instantiating the Message Buffers
75 // that interact with the coherence protocol
76 for (int j = 0; j < m_virtual_networks; j++) {
77 m_toNetQueues[node][j] = new MessageBuffer();
78 m_fromNetQueues[node][j] = new MessageBuffer();
79 }
80 }
81 }
82
83 void
84 GarnetNetwork_d::init()
85 {
86 BaseGarnetNetwork::init();
87
88 // The topology pointer should have already been initialized in the
89 // parent network constructor
90 assert(m_topology_ptr != NULL);
91
92 int number_of_routers = m_topology_ptr->numSwitches();
93 for (int i=0; i<number_of_routers; i++) {
94 m_router_ptr_vector.push_back(new Router_d(i, this));
95 }
96
97 for (int i=0; i < m_nodes; i++) {
98 NetworkInterface_d *ni = new NetworkInterface_d(i, m_virtual_networks,
99 this);
100 ni->addNode(m_toNetQueues[i], m_fromNetQueues[i]);
101 m_ni_ptr_vector.push_back(ni);
102 }
103 // false because this isn't a reconfiguration
104 m_topology_ptr->createLinks(this, false);
105 for (int i = 0; i < m_router_ptr_vector.size(); i++) {
106 m_router_ptr_vector[i]->init();
107 }
108 }
109
110 GarnetNetwork_d::~GarnetNetwork_d()
111 {
112 for (int i = 0; i < m_nodes; i++) {
113 deletePointers(m_toNetQueues[i]);
114 deletePointers(m_fromNetQueues[i]);
115 }
116 deletePointers(m_router_ptr_vector);
117 deletePointers(m_ni_ptr_vector);
118 deletePointers(m_link_ptr_vector);
119 deletePointers(m_creditlink_ptr_vector);
120 delete m_topology_ptr;
121 }
122
123 void
124 GarnetNetwork_d::reset()
125 {
126 for (int node = 0; node < m_nodes; node++) {
127 for (int j = 0; j < m_virtual_networks; j++) {
128 m_toNetQueues[node][j]->clear();
129 m_fromNetQueues[node][j]->clear();
130 }
131 }
132 }
133
134 /*
135 * This function creates a link from the Network Interface (NI)
136 * into the Network.
137 * It creates a Network Link from the NI to a Router and a Credit Link from
138 * the Router to the NI
139 */
140
141 void
142 GarnetNetwork_d::makeInLink(NodeID src, SwitchID dest,
143 const NetDest& routing_table_entry, int link_latency, int bw_multiplier,
144 bool isReconfiguration)
145 {
146 assert(src < m_nodes);
147
148 if (!isReconfiguration) {
149 NetworkLink_d *net_link = new NetworkLink_d
150 (m_link_ptr_vector.size(), link_latency, this);
151 CreditLink_d *credit_link = new CreditLink_d
152 (m_creditlink_ptr_vector.size(), link_latency, this);
153 m_link_ptr_vector.push_back(net_link);
154 m_creditlink_ptr_vector.push_back(credit_link);
155
156 m_router_ptr_vector[dest]->addInPort(net_link, credit_link);
157 m_ni_ptr_vector[src]->addOutPort(net_link, credit_link);
158 } else {
159 ERROR_MSG("Fatal Error:: Reconfiguration not allowed here");
160 // do nothing
161 }
162 }
163
164 /*
165 * This function creates a link from the Network to a NI.
166 * It creates a Network Link from a Router to the NI and
167 * a Credit Link from NI to the Router
168 */
169
170 void
171 GarnetNetwork_d::makeOutLink(SwitchID src, NodeID dest,
172 const NetDest& routing_table_entry, int link_latency, int link_weight,
173 int bw_multiplier, bool isReconfiguration)
174 {
175 assert(dest < m_nodes);
176 assert(src < m_router_ptr_vector.size());
177 assert(m_router_ptr_vector[src] != NULL);
178
179 if (!isReconfiguration) {
180 NetworkLink_d *net_link = new NetworkLink_d
181 (m_link_ptr_vector.size(), link_latency, this);
182 CreditLink_d *credit_link = new CreditLink_d
183 (m_creditlink_ptr_vector.size(), link_latency, this);
184 m_link_ptr_vector.push_back(net_link);
185 m_creditlink_ptr_vector.push_back(credit_link);
186
187 m_router_ptr_vector[src]->addOutPort(net_link, routing_table_entry,
188 link_weight, credit_link);
189 m_ni_ptr_vector[dest]->addInPort(net_link, credit_link);
190 } else {
191 ERROR_MSG("Fatal Error:: Reconfiguration not allowed here");
192 // do nothing
193 }
194 }
195
196 /*
197 * This function creates an internal network link
198 */
199
200 void
201 GarnetNetwork_d::makeInternalLink(SwitchID src, SwitchID dest,
202 const NetDest& routing_table_entry, int link_latency, int link_weight,
203 int bw_multiplier, bool isReconfiguration)
204 {
205 if (!isReconfiguration) {
206 NetworkLink_d *net_link = new NetworkLink_d
207 (m_link_ptr_vector.size(), link_latency, this);
208 CreditLink_d *credit_link = new CreditLink_d
209 (m_creditlink_ptr_vector.size(), link_latency, this);
210 m_link_ptr_vector.push_back(net_link);
211 m_creditlink_ptr_vector.push_back(credit_link);
212
213 m_router_ptr_vector[dest]->addInPort(net_link, credit_link);
214 m_router_ptr_vector[src]->addOutPort(net_link, routing_table_entry,
215 link_weight, credit_link);
216 } else {
217 ERROR_MSG("Fatal Error:: Reconfiguration not allowed here");
218 // do nothing
219 }
220 }
221
222 void
223 GarnetNetwork_d::checkNetworkAllocation(NodeID id, bool ordered,
224 int network_num)
225 {
226 ASSERT(id < m_nodes);
227 ASSERT(network_num < m_virtual_networks);
228
229 if (ordered) {
230 m_ordered[network_num] = true;
231 }
232 m_in_use[network_num] = true;
233 }
234
235 MessageBuffer*
236 GarnetNetwork_d::getToNetQueue(NodeID id, bool ordered, int network_num)
237 {
238 checkNetworkAllocation(id, ordered, network_num);
239 return m_toNetQueues[id][network_num];
240 }
241
242 MessageBuffer*
243 GarnetNetwork_d::getFromNetQueue(NodeID id, bool ordered, int network_num)
244 {
245 checkNetworkAllocation(id, ordered, network_num);
246 return m_fromNetQueues[id][network_num];
247 }
248
249 void
250 GarnetNetwork_d::clearStats()
251 {
252 m_ruby_start = g_eventQueue_ptr->getTime();
253 }
254
255 Time
256 GarnetNetwork_d::getRubyStartTime()
257 {
258 return m_ruby_start;
259 }
260
261 void
262 GarnetNetwork_d::printStats(ostream& out) const
263 {
264 double average_link_utilization = 0;
265 vector<double> average_vc_load;
266 average_vc_load.resize(m_virtual_networks*m_vcs_per_class);
267
268 for (int i = 0; i < m_virtual_networks*m_vcs_per_class; i++)
269 {
270 average_vc_load[i] = 0;
271 }
272
273 out << endl;
274 out << "Network Stats" << endl;
275 out << "-------------" << endl;
276 out << endl;
277 for (int i = 0; i < m_link_ptr_vector.size(); i++) {
278 average_link_utilization +=
279 (double(m_link_ptr_vector[i]->getLinkUtilization())) /
280 (double(g_eventQueue_ptr->getTime()-m_ruby_start));
281
282 vector<int> vc_load = m_link_ptr_vector[i]->getVcLoad();
283 for (int j = 0; j < vc_load.size(); j++) {
284 assert(vc_load.size() == m_vcs_per_class*m_virtual_networks);
285 average_vc_load[j] += vc_load[j];
286 }
287 }
288 average_link_utilization =
289 average_link_utilization/m_link_ptr_vector.size();
290 out << "Average Link Utilization :: " << average_link_utilization
291 << " flits/cycle" << endl;
292 out << "-------------" << endl;
293
294 for (int i = 0; i < m_vcs_per_class*m_virtual_networks; i++) {
295 average_vc_load[i] = (double(average_vc_load[i]) /
296 (double(g_eventQueue_ptr->getTime()) - m_ruby_start));
297 out << "Average VC Load [" << i << "] = " << average_vc_load[i]
298 << " flits/cycle " << endl;
299 }
300 out << "-------------" << endl;
301
302 // out << "Total flits injected = " << m_flits_injected << endl;
303 // out << "Total flits received = " << m_flits_received << endl;
304 out << "Average network latency = "
305 << ((double) m_network_latency/ (double) m_flits_received)<< endl;
306 // out << "Average queueing latency = "
307 // << ((double) m_queueing_latency/ (double) m_flits_received)<< endl;
308 // out << "Average latency = "
309 // << ((double) (m_queueing_latency + m_network_latency) /
310 // (double) m_flits_received)<< endl;
311 out << "-------------" << endl;
312
313 double m_total_link_power = 0.0;
314 double m_total_router_power = 0.0;
315
316 for (int i = 0; i < m_link_ptr_vector.size(); i++) {
317 m_total_link_power += m_link_ptr_vector[i]->calculate_power();
318 }
319
320 for (int i = 0; i < m_router_ptr_vector.size(); i++) {
321 m_total_router_power += m_router_ptr_vector[i]->calculate_power();
322 }
323 out << "Total Link Power = " << m_total_link_power << " W " << endl;
324 out << "Total Router Power = " << m_total_router_power << " W " <<endl;
325 out << "-------------" << endl;
326 m_topology_ptr->printStats(out);
327 }
328
329 void
330 GarnetNetwork_d::printConfig(ostream& out) const
331 {
332 out << endl;
333 out << "Network Configuration" << endl;
334 out << "---------------------" << endl;
335 out << "network: GarnetNetwork_d" << endl;
336 out << "topology: " << m_topology_ptr->getName() << endl;
337 out << endl;
338
339 for (int i = 0; i < m_virtual_networks; i++) {
340 out << "virtual_net_" << i << ": ";
341 if (m_in_use[i]) {
342 out << "active, ";
343 if (m_ordered[i]) {
344 out << "ordered" << endl;
345 } else {
346 out << "unordered" << endl;
347 }
348 } else {
349 out << "inactive" << endl;
350 }
351 }
352 out << endl;
353
354 for (int i = 0; i < m_ni_ptr_vector.size(); i++) {
355 m_ni_ptr_vector[i]->printConfig(out);
356 }
357 for (int i = 0; i < m_router_ptr_vector.size(); i++) {
358 m_router_ptr_vector[i]->printConfig(out);
359 }
360 m_topology_ptr->printConfig(out);
361 }
362
363 void
364 GarnetNetwork_d::print(ostream& out) const
365 {
366 out << "[GarnetNetwork_d]";
367 }
368
369 GarnetNetwork_d *
370 GarnetNetwork_dParams::create()
371 {
372 return new GarnetNetwork_d(this);
373 }