ruby: get rid of ruby's Debug.hh
[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 <cassert>
32
33 #include "base/stl_helpers.hh"
34 #include "mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.hh"
35 #include "mem/protocol/MachineType.hh"
36 #include "mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.hh"
37 #include "mem/ruby/buffers/MessageBuffer.hh"
38 #include "mem/ruby/network/garnet/fixed-pipeline/Router_d.hh"
39 #include "mem/ruby/network/simple/Topology.hh"
40 #include "mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.hh"
41 #include "mem/ruby/network/garnet/fixed-pipeline/CreditLink_d.hh"
42 #include "mem/ruby/common/NetDest.hh"
43
44 using namespace std;
45 using m5::stl_helpers::deletePointers;
46
47 GarnetNetwork_d::GarnetNetwork_d(const Params *p)
48 : BaseGarnetNetwork(p)
49 {
50 m_ruby_start = 0;
51 m_flits_received = 0;
52 m_flits_injected = 0;
53 m_network_latency = 0.0;
54 m_queueing_latency = 0.0;
55
56 m_router_ptr_vector.clear();
57
58 // Queues that are getting messages from protocol
59 m_toNetQueues.resize(m_nodes);
60
61 // Queues that are feeding the protocol
62 m_fromNetQueues.resize(m_nodes);
63 m_in_use.resize(m_virtual_networks);
64 m_ordered.resize(m_virtual_networks);
65 for (int i = 0; i < m_virtual_networks; i++) {
66 m_in_use[i] = false;
67 m_ordered[i] = false;
68 }
69
70 for (int node = 0; node < m_nodes; node++) {
71 // Setting how many vitual message buffers
72 // will there be per Network Queue
73 m_toNetQueues[node].resize(m_virtual_networks);
74 m_fromNetQueues[node].resize(m_virtual_networks);
75
76 // Instantiating the Message Buffers
77 // that interact with the coherence protocol
78 for (int j = 0; j < m_virtual_networks; j++) {
79 m_toNetQueues[node][j] = new MessageBuffer();
80 m_fromNetQueues[node][j] = new MessageBuffer();
81 }
82 }
83 }
84
85 void
86 GarnetNetwork_d::init()
87 {
88 BaseGarnetNetwork::init();
89
90 // The topology pointer should have already been initialized in the
91 // parent network constructor
92 assert(m_topology_ptr != NULL);
93
94 int number_of_routers = m_topology_ptr->numSwitches();
95 for (int i=0; i<number_of_routers; i++) {
96 m_router_ptr_vector.push_back(new Router_d(i, this));
97 }
98
99 for (int i=0; i < m_nodes; i++) {
100 NetworkInterface_d *ni = new NetworkInterface_d(i, m_virtual_networks,
101 this);
102 ni->addNode(m_toNetQueues[i], m_fromNetQueues[i]);
103 m_ni_ptr_vector.push_back(ni);
104 }
105 // false because this isn't a reconfiguration
106 m_topology_ptr->createLinks(this, false);
107 for (int i = 0; i < m_router_ptr_vector.size(); i++) {
108 m_router_ptr_vector[i]->init();
109 }
110 }
111
112 GarnetNetwork_d::~GarnetNetwork_d()
113 {
114 for (int i = 0; i < m_nodes; i++) {
115 deletePointers(m_toNetQueues[i]);
116 deletePointers(m_fromNetQueues[i]);
117 }
118 deletePointers(m_router_ptr_vector);
119 deletePointers(m_ni_ptr_vector);
120 deletePointers(m_link_ptr_vector);
121 deletePointers(m_creditlink_ptr_vector);
122 delete m_topology_ptr;
123 }
124
125 void
126 GarnetNetwork_d::reset()
127 {
128 for (int node = 0; node < m_nodes; node++) {
129 for (int j = 0; j < m_virtual_networks; j++) {
130 m_toNetQueues[node][j]->clear();
131 m_fromNetQueues[node][j]->clear();
132 }
133 }
134 }
135
136 /*
137 * This function creates a link from the Network Interface (NI)
138 * into the Network.
139 * It creates a Network Link from the NI to a Router and a Credit Link from
140 * the Router to the NI
141 */
142
143 void
144 GarnetNetwork_d::makeInLink(NodeID src, SwitchID dest,
145 const NetDest& routing_table_entry, int link_latency, int bw_multiplier,
146 bool isReconfiguration)
147 {
148 assert(src < m_nodes);
149
150 if (!isReconfiguration) {
151 NetworkLink_d *net_link = new NetworkLink_d
152 (m_link_ptr_vector.size(), link_latency, this);
153 CreditLink_d *credit_link = new CreditLink_d
154 (m_creditlink_ptr_vector.size(), link_latency, this);
155 m_link_ptr_vector.push_back(net_link);
156 m_creditlink_ptr_vector.push_back(credit_link);
157
158 m_router_ptr_vector[dest]->addInPort(net_link, credit_link);
159 m_ni_ptr_vector[src]->addOutPort(net_link, credit_link);
160 } else {
161 panic("Fatal Error:: Reconfiguration not allowed here");
162 // do nothing
163 }
164 }
165
166 /*
167 * This function creates a link from the Network to a NI.
168 * It creates a Network Link from a Router to the NI and
169 * a Credit Link from NI to the Router
170 */
171
172 void
173 GarnetNetwork_d::makeOutLink(SwitchID src, NodeID dest,
174 const NetDest& routing_table_entry, int link_latency, int link_weight,
175 int bw_multiplier, bool isReconfiguration)
176 {
177 assert(dest < m_nodes);
178 assert(src < m_router_ptr_vector.size());
179 assert(m_router_ptr_vector[src] != NULL);
180
181 if (!isReconfiguration) {
182 NetworkLink_d *net_link = new NetworkLink_d
183 (m_link_ptr_vector.size(), link_latency, this);
184 CreditLink_d *credit_link = new CreditLink_d
185 (m_creditlink_ptr_vector.size(), link_latency, this);
186 m_link_ptr_vector.push_back(net_link);
187 m_creditlink_ptr_vector.push_back(credit_link);
188
189 m_router_ptr_vector[src]->addOutPort(net_link, routing_table_entry,
190 link_weight, credit_link);
191 m_ni_ptr_vector[dest]->addInPort(net_link, credit_link);
192 } else {
193 fatal("Fatal Error:: Reconfiguration not allowed here");
194 // do nothing
195 }
196 }
197
198 /*
199 * This function creates an internal network link
200 */
201
202 void
203 GarnetNetwork_d::makeInternalLink(SwitchID src, SwitchID dest,
204 const NetDest& routing_table_entry, int link_latency, int link_weight,
205 int bw_multiplier, bool isReconfiguration)
206 {
207 if (!isReconfiguration) {
208 NetworkLink_d *net_link = new NetworkLink_d
209 (m_link_ptr_vector.size(), link_latency, this);
210 CreditLink_d *credit_link = new CreditLink_d
211 (m_creditlink_ptr_vector.size(), link_latency, this);
212 m_link_ptr_vector.push_back(net_link);
213 m_creditlink_ptr_vector.push_back(credit_link);
214
215 m_router_ptr_vector[dest]->addInPort(net_link, credit_link);
216 m_router_ptr_vector[src]->addOutPort(net_link, routing_table_entry,
217 link_weight, credit_link);
218 } else {
219 fatal("Fatal Error:: Reconfiguration not allowed here");
220 // do nothing
221 }
222 }
223
224 void
225 GarnetNetwork_d::checkNetworkAllocation(NodeID id, bool ordered,
226 int network_num)
227 {
228 assert(id < m_nodes);
229 assert(network_num < m_virtual_networks);
230
231 if (ordered) {
232 m_ordered[network_num] = true;
233 }
234 m_in_use[network_num] = true;
235 }
236
237 MessageBuffer*
238 GarnetNetwork_d::getToNetQueue(NodeID id, bool ordered, int network_num)
239 {
240 checkNetworkAllocation(id, ordered, network_num);
241 return m_toNetQueues[id][network_num];
242 }
243
244 MessageBuffer*
245 GarnetNetwork_d::getFromNetQueue(NodeID id, bool ordered, int network_num)
246 {
247 checkNetworkAllocation(id, ordered, network_num);
248 return m_fromNetQueues[id][network_num];
249 }
250
251 void
252 GarnetNetwork_d::clearStats()
253 {
254 m_ruby_start = g_eventQueue_ptr->getTime();
255 }
256
257 Time
258 GarnetNetwork_d::getRubyStartTime()
259 {
260 return m_ruby_start;
261 }
262
263 void
264 GarnetNetwork_d::printStats(ostream& out) const
265 {
266 double average_link_utilization = 0;
267 vector<double> average_vc_load;
268 average_vc_load.resize(m_virtual_networks*m_vcs_per_class);
269
270 for (int i = 0; i < m_virtual_networks*m_vcs_per_class; i++)
271 {
272 average_vc_load[i] = 0;
273 }
274
275 out << endl;
276 out << "Network Stats" << endl;
277 out << "-------------" << endl;
278 out << endl;
279 for (int i = 0; i < m_link_ptr_vector.size(); i++) {
280 average_link_utilization +=
281 (double(m_link_ptr_vector[i]->getLinkUtilization())) /
282 (double(g_eventQueue_ptr->getTime()-m_ruby_start));
283
284 vector<int> vc_load = m_link_ptr_vector[i]->getVcLoad();
285 for (int j = 0; j < vc_load.size(); j++) {
286 assert(vc_load.size() == m_vcs_per_class*m_virtual_networks);
287 average_vc_load[j] += vc_load[j];
288 }
289 }
290 average_link_utilization =
291 average_link_utilization/m_link_ptr_vector.size();
292 out << "Average Link Utilization :: " << average_link_utilization
293 << " flits/cycle" << endl;
294 out << "-------------" << endl;
295
296 for (int i = 0; i < m_vcs_per_class*m_virtual_networks; i++) {
297 average_vc_load[i] = (double(average_vc_load[i]) /
298 (double(g_eventQueue_ptr->getTime()) - m_ruby_start));
299 out << "Average VC Load [" << i << "] = " << average_vc_load[i]
300 << " flits/cycle " << endl;
301 }
302 out << "-------------" << endl;
303
304 // out << "Total flits injected = " << m_flits_injected << endl;
305 // out << "Total flits received = " << m_flits_received << endl;
306 out << "Average network latency = "
307 << ((double) m_network_latency/ (double) m_flits_received)<< endl;
308 // out << "Average queueing latency = "
309 // << ((double) m_queueing_latency/ (double) m_flits_received)<< endl;
310 // out << "Average latency = "
311 // << ((double) (m_queueing_latency + m_network_latency) /
312 // (double) m_flits_received)<< endl;
313 out << "-------------" << endl;
314
315 double m_total_link_power = 0.0;
316 double m_total_router_power = 0.0;
317
318 for (int i = 0; i < m_link_ptr_vector.size(); i++) {
319 m_total_link_power += m_link_ptr_vector[i]->calculate_power();
320 }
321
322 for (int i = 0; i < m_router_ptr_vector.size(); i++) {
323 m_total_router_power += m_router_ptr_vector[i]->calculate_power();
324 }
325 out << "Total Link Power = " << m_total_link_power << " W " << endl;
326 out << "Total Router Power = " << m_total_router_power << " W " <<endl;
327 out << "-------------" << endl;
328 m_topology_ptr->printStats(out);
329 }
330
331 void
332 GarnetNetwork_d::printConfig(ostream& out) const
333 {
334 out << endl;
335 out << "Network Configuration" << endl;
336 out << "---------------------" << endl;
337 out << "network: GarnetNetwork_d" << endl;
338 out << "topology: " << m_topology_ptr->getName() << endl;
339 out << endl;
340
341 for (int i = 0; i < m_virtual_networks; i++) {
342 out << "virtual_net_" << i << ": ";
343 if (m_in_use[i]) {
344 out << "active, ";
345 if (m_ordered[i]) {
346 out << "ordered" << endl;
347 } else {
348 out << "unordered" << endl;
349 }
350 } else {
351 out << "inactive" << endl;
352 }
353 }
354 out << endl;
355
356 for (int i = 0; i < m_ni_ptr_vector.size(); i++) {
357 m_ni_ptr_vector[i]->printConfig(out);
358 }
359 for (int i = 0; i < m_router_ptr_vector.size(); i++) {
360 m_router_ptr_vector[i]->printConfig(out);
361 }
362 m_topology_ptr->printConfig(out);
363 }
364
365 void
366 GarnetNetwork_d::print(ostream& out) const
367 {
368 out << "[GarnetNetwork_d]";
369 }
370
371 GarnetNetwork_d *
372 GarnetNetwork_dParams::create()
373 {
374 return new GarnetNetwork_d(this);
375 }