garnet: separate data and ctrl VCs
[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 m_vnet_type.resize(m_virtual_networks);
112 for (int i = 0; i < m_vnet_type.size(); i++) {
113 m_vnet_type[i] = CTRL_VNET_;
114 // DATA_VNET_ updated later based on traffic
115 }
116 }
117
118 GarnetNetwork_d::~GarnetNetwork_d()
119 {
120 for (int i = 0; i < m_nodes; i++) {
121 deletePointers(m_toNetQueues[i]);
122 deletePointers(m_fromNetQueues[i]);
123 }
124 deletePointers(m_router_ptr_vector);
125 deletePointers(m_ni_ptr_vector);
126 deletePointers(m_link_ptr_vector);
127 deletePointers(m_creditlink_ptr_vector);
128 delete m_topology_ptr;
129 }
130
131 void
132 GarnetNetwork_d::reset()
133 {
134 for (int node = 0; node < m_nodes; node++) {
135 for (int j = 0; j < m_virtual_networks; j++) {
136 m_toNetQueues[node][j]->clear();
137 m_fromNetQueues[node][j]->clear();
138 }
139 }
140 }
141
142 /*
143 * This function creates a link from the Network Interface (NI)
144 * into the Network.
145 * It creates a Network Link from the NI to a Router and a Credit Link from
146 * the Router to the NI
147 */
148
149 void
150 GarnetNetwork_d::makeInLink(NodeID src, SwitchID dest,
151 const NetDest& routing_table_entry, int link_latency, int bw_multiplier,
152 bool isReconfiguration)
153 {
154 assert(src < m_nodes);
155
156 if (!isReconfiguration) {
157 NetworkLink_d *net_link = new NetworkLink_d
158 (m_link_ptr_vector.size(), link_latency, this);
159 CreditLink_d *credit_link = new CreditLink_d
160 (m_creditlink_ptr_vector.size(), link_latency, this);
161 m_link_ptr_vector.push_back(net_link);
162 m_creditlink_ptr_vector.push_back(credit_link);
163
164 m_router_ptr_vector[dest]->addInPort(net_link, credit_link);
165 m_ni_ptr_vector[src]->addOutPort(net_link, credit_link);
166 } else {
167 panic("Fatal Error:: Reconfiguration not allowed here");
168 // do nothing
169 }
170 }
171
172 /*
173 * This function creates a link from the Network to a NI.
174 * It creates a Network Link from a Router to the NI and
175 * a Credit Link from NI to the Router
176 */
177
178 void
179 GarnetNetwork_d::makeOutLink(SwitchID src, NodeID dest,
180 const NetDest& routing_table_entry, int link_latency, int link_weight,
181 int bw_multiplier, bool isReconfiguration)
182 {
183 assert(dest < m_nodes);
184 assert(src < m_router_ptr_vector.size());
185 assert(m_router_ptr_vector[src] != NULL);
186
187 if (!isReconfiguration) {
188 NetworkLink_d *net_link = new NetworkLink_d
189 (m_link_ptr_vector.size(), link_latency, this);
190 CreditLink_d *credit_link = new CreditLink_d
191 (m_creditlink_ptr_vector.size(), link_latency, this);
192 m_link_ptr_vector.push_back(net_link);
193 m_creditlink_ptr_vector.push_back(credit_link);
194
195 m_router_ptr_vector[src]->addOutPort(net_link, routing_table_entry,
196 link_weight, credit_link);
197 m_ni_ptr_vector[dest]->addInPort(net_link, credit_link);
198 } else {
199 fatal("Fatal Error:: Reconfiguration not allowed here");
200 // do nothing
201 }
202 }
203
204 /*
205 * This function creates an internal network link
206 */
207
208 void
209 GarnetNetwork_d::makeInternalLink(SwitchID src, SwitchID dest,
210 const NetDest& routing_table_entry, int link_latency, int link_weight,
211 int bw_multiplier, bool isReconfiguration)
212 {
213 if (!isReconfiguration) {
214 NetworkLink_d *net_link = new NetworkLink_d
215 (m_link_ptr_vector.size(), link_latency, this);
216 CreditLink_d *credit_link = new CreditLink_d
217 (m_creditlink_ptr_vector.size(), link_latency, this);
218 m_link_ptr_vector.push_back(net_link);
219 m_creditlink_ptr_vector.push_back(credit_link);
220
221 m_router_ptr_vector[dest]->addInPort(net_link, credit_link);
222 m_router_ptr_vector[src]->addOutPort(net_link, routing_table_entry,
223 link_weight, credit_link);
224 } else {
225 fatal("Fatal Error:: Reconfiguration not allowed here");
226 // do nothing
227 }
228 }
229
230 void
231 GarnetNetwork_d::checkNetworkAllocation(NodeID id, bool ordered,
232 int network_num)
233 {
234 assert(id < m_nodes);
235 assert(network_num < m_virtual_networks);
236
237 if (ordered) {
238 m_ordered[network_num] = true;
239 }
240 m_in_use[network_num] = true;
241 }
242
243 MessageBuffer*
244 GarnetNetwork_d::getToNetQueue(NodeID id, bool ordered, int network_num)
245 {
246 checkNetworkAllocation(id, ordered, network_num);
247 return m_toNetQueues[id][network_num];
248 }
249
250 MessageBuffer*
251 GarnetNetwork_d::getFromNetQueue(NodeID id, bool ordered, int network_num)
252 {
253 checkNetworkAllocation(id, ordered, network_num);
254 return m_fromNetQueues[id][network_num];
255 }
256
257 void
258 GarnetNetwork_d::clearStats()
259 {
260 m_ruby_start = g_eventQueue_ptr->getTime();
261 }
262
263 Time
264 GarnetNetwork_d::getRubyStartTime()
265 {
266 return m_ruby_start;
267 }
268
269 void
270 GarnetNetwork_d::printStats(ostream& out) const
271 {
272 double average_link_utilization = 0;
273 vector<double> average_vc_load;
274 average_vc_load.resize(m_virtual_networks*m_vcs_per_class);
275
276 for (int i = 0; i < m_virtual_networks*m_vcs_per_class; i++)
277 {
278 average_vc_load[i] = 0;
279 }
280
281 out << endl;
282 out << "Network Stats" << endl;
283 out << "-------------" << endl;
284 out << endl;
285 for (int i = 0; i < m_link_ptr_vector.size(); i++) {
286 average_link_utilization +=
287 (double(m_link_ptr_vector[i]->getLinkUtilization())) /
288 (double(g_eventQueue_ptr->getTime()-m_ruby_start));
289
290 vector<int> vc_load = m_link_ptr_vector[i]->getVcLoad();
291 for (int j = 0; j < vc_load.size(); j++) {
292 assert(vc_load.size() == m_vcs_per_class*m_virtual_networks);
293 average_vc_load[j] += vc_load[j];
294 }
295 }
296 average_link_utilization =
297 average_link_utilization/m_link_ptr_vector.size();
298 out << "Average Link Utilization :: " << average_link_utilization
299 << " flits/cycle" << endl;
300 out << "-------------" << endl;
301
302 for (int i = 0; i < m_vcs_per_class*m_virtual_networks; i++) {
303 average_vc_load[i] = (double(average_vc_load[i]) /
304 (double(g_eventQueue_ptr->getTime()) - m_ruby_start));
305 out << "Average VC Load [" << i << "] = " << average_vc_load[i]
306 << " flits/cycle " << endl;
307 }
308 out << "-------------" << endl;
309
310 // out << "Total flits injected = " << m_flits_injected << endl;
311 // out << "Total flits received = " << m_flits_received << endl;
312 out << "Average network latency = "
313 << ((double) m_network_latency/ (double) m_flits_received)<< endl;
314 // out << "Average queueing latency = "
315 // << ((double) m_queueing_latency/ (double) m_flits_received)<< endl;
316 // out << "Average latency = "
317 // << ((double) (m_queueing_latency + m_network_latency) /
318 // (double) m_flits_received)<< endl;
319 out << "-------------" << endl;
320
321 double m_total_link_power = 0.0;
322 double m_total_router_power = 0.0;
323
324 for (int i = 0; i < m_link_ptr_vector.size(); i++) {
325 m_total_link_power += m_link_ptr_vector[i]->calculate_power();
326 }
327
328 for (int i = 0; i < m_router_ptr_vector.size(); i++) {
329 m_total_router_power += m_router_ptr_vector[i]->calculate_power();
330 }
331 out << "Total Link Power = " << m_total_link_power << " W " << endl;
332 out << "Total Router Power = " << m_total_router_power << " W " <<endl;
333 out << "-------------" << endl;
334 m_topology_ptr->printStats(out);
335 }
336
337 void
338 GarnetNetwork_d::printConfig(ostream& out) const
339 {
340 out << endl;
341 out << "Network Configuration" << endl;
342 out << "---------------------" << endl;
343 out << "network: GarnetNetwork_d" << endl;
344 out << "topology: " << m_topology_ptr->getName() << endl;
345 out << endl;
346
347 for (int i = 0; i < m_virtual_networks; i++) {
348 out << "virtual_net_" << i << ": ";
349 if (m_in_use[i]) {
350 out << "active, ";
351 if (m_ordered[i]) {
352 out << "ordered" << endl;
353 } else {
354 out << "unordered" << endl;
355 }
356 } else {
357 out << "inactive" << endl;
358 }
359 }
360 out << endl;
361
362 for (int i = 0; i < m_ni_ptr_vector.size(); i++) {
363 m_ni_ptr_vector[i]->printConfig(out);
364 }
365 for (int i = 0; i < m_router_ptr_vector.size(); i++) {
366 m_router_ptr_vector[i]->printConfig(out);
367 }
368 m_topology_ptr->printConfig(out);
369 }
370
371 void
372 GarnetNetwork_d::print(ostream& out) const
373 {
374 out << "[GarnetNetwork_d]";
375 }
376
377 GarnetNetwork_d *
378 GarnetNetwork_dParams::create()
379 {
380 return new GarnetNetwork_d(this);
381 }