a88263c62e17b149b2e8ad882aaecba14f13c210
[gem5.git] / src / mem / ruby / network / garnet / flexible-pipeline / GarnetNetwork.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 "mem/ruby/network/garnet/flexible-pipeline/GarnetNetwork.hh"
32 #include "mem/protocol/MachineType.hh"
33 #include "mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.hh"
34 #include "mem/ruby/buffers/MessageBuffer.hh"
35 #include "mem/ruby/network/garnet/flexible-pipeline/Router.hh"
36 #include "mem/ruby/network/simple/Topology.hh"
37 #include "mem/ruby/network/simple/SimpleNetwork.hh"
38 #include "mem/ruby/network/garnet/fixed-pipeline/GarnetNetwork_d.hh"
39 #include "mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh"
40 #include "mem/ruby/common/NetDest.hh"
41
42 GarnetNetwork::GarnetNetwork(const string & name)
43 : Network(name)
44 {
45 }
46
47 void GarnetNetwork::init()
48 {
49 // printf("hello\n");
50 Network::init(argv);
51 //added by SS
52 // assert (m_topology_ptr!=NULL);
53
54 m_network_config_ptr = new NetworkConfig;
55
56 m_network_config_ptr->init(argv);
57
58 m_ruby_start = 0;
59
60 // Allocate to and from queues
61 m_toNetQueues.setSize(m_nodes); // Queues that are getting messages from protocol
62 m_fromNetQueues.setSize(m_nodes); // Queues that are feeding the protocol
63 m_in_use.setSize(m_virtual_networks);
64 m_ordered.setSize(m_virtual_networks);
65 for (int i = 0; i < m_virtual_networks; i++)
66 {
67 m_in_use[i] = false;
68 m_ordered[i] = false;
69 }
70
71 for (int node = 0; node < m_nodes; node++)
72 {
73 //Setting how many vitual message buffers will there be per Network Queue
74 m_toNetQueues[node].setSize(m_virtual_networks);
75 m_fromNetQueues[node].setSize(m_virtual_networks);
76
77 for (int j = 0; j < m_virtual_networks; j++)
78 {
79 m_toNetQueues[node][j] = new MessageBuffer(); // Instantiating the Message Buffers that interact with the coherence protocol
80 m_fromNetQueues[node][j] = new MessageBuffer();
81 }
82 }
83
84 // Setup the network switches
85 assert (m_topology_ptr!=NULL);
86 m_topology_ptr->makeTopology();
87
88 int number_of_routers = m_topology_ptr->numSwitches();
89 for (int i=0; i<number_of_routers; i++) {
90 m_router_ptr_vector.insertAtBottom(new Router(i, this));
91 }
92
93 for (int i=0; i < m_nodes; i++) {
94 NetworkInterface *ni = new NetworkInterface(i, m_virtual_networks, this);
95 ni->addNode(m_toNetQueues[i], m_fromNetQueues[i]);
96 m_ni_ptr_vector.insertAtBottom(ni);
97 }
98 m_topology_ptr->createLinks(this, false); // false because this isn't a reconfiguration
99 }
100
101 GarnetNetwork::~GarnetNetwork()
102 {
103 for (int i = 0; i < m_nodes; i++)
104 {
105 m_toNetQueues[i].deletePointers();
106 m_fromNetQueues[i].deletePointers();
107 }
108 m_router_ptr_vector.deletePointers();
109 m_ni_ptr_vector.deletePointers();
110 m_link_ptr_vector.deletePointers();
111 delete m_topology_ptr;
112 }
113
114 void GarnetNetwork::reset()
115 {
116 for (int node = 0; node < m_nodes; node++)
117 {
118 for (int j = 0; j < m_virtual_networks; j++)
119 {
120 m_toNetQueues[node][j]->clear();
121 m_fromNetQueues[node][j]->clear();
122 }
123 }
124 }
125
126 void GarnetNetwork::makeInLink(NodeID src, SwitchID dest, const NetDest& routing_table_entry, int link_latency, int bw_multiplier, bool isReconfiguration)
127 {
128 assert(src < m_nodes);
129
130 if(!isReconfiguration)
131 {
132 NetworkLink *net_link = new NetworkLink(m_link_ptr_vector.size(), link_latency, this);
133 m_link_ptr_vector.insertAtBottom(net_link);
134 m_router_ptr_vector[dest]->addInPort(net_link);
135 m_ni_ptr_vector[src]->addOutPort(net_link);
136 }
137 else
138 {
139 ERROR_MSG("Fatal Error:: Reconfiguration not allowed here");
140 // do nothing
141 }
142 }
143
144 void GarnetNetwork::makeOutLink(SwitchID src, NodeID dest, const NetDest& routing_table_entry, int link_latency, int link_weight, int bw_multiplier, bool isReconfiguration)
145 {
146 assert(dest < m_nodes);
147 assert(src < m_router_ptr_vector.size());
148 assert(m_router_ptr_vector[src] != NULL);
149
150 if(!isReconfiguration)
151 {
152 NetworkLink *net_link = new NetworkLink(m_link_ptr_vector.size(), link_latency, this);
153 m_link_ptr_vector.insertAtBottom(net_link);
154 m_router_ptr_vector[src]->addOutPort(net_link, routing_table_entry, link_weight);
155 m_ni_ptr_vector[dest]->addInPort(net_link);
156 }
157 else
158 {
159 ERROR_MSG("Fatal Error:: Reconfiguration not allowed here");
160 //do nothing
161 }
162 }
163
164 void GarnetNetwork::makeInternalLink(SwitchID src, SwitchID dest, const NetDest& routing_table_entry, int link_latency, int link_weight, int bw_multiplier, bool isReconfiguration)
165 {
166 if(!isReconfiguration)
167 {
168 NetworkLink *net_link = new NetworkLink(m_link_ptr_vector.size(), link_latency, this);
169 m_link_ptr_vector.insertAtBottom(net_link);
170 m_router_ptr_vector[dest]->addInPort(net_link);
171 m_router_ptr_vector[src]->addOutPort(net_link, routing_table_entry, link_weight);
172 }
173 else
174 {
175 ERROR_MSG("Fatal Error:: Reconfiguration not allowed here");
176 // do nothing
177 }
178
179 }
180
181 void GarnetNetwork::checkNetworkAllocation(NodeID id, bool ordered, int network_num)
182 {
183 printf ("id = %i, m_nodes = %i \n", id, m_nodes);
184 ASSERT(id < m_nodes);
185 ASSERT(network_num < m_virtual_networks);
186
187 if (ordered)
188 {
189 m_ordered[network_num] = true;
190 }
191 m_in_use[network_num] = true;
192 }
193
194 MessageBuffer* GarnetNetwork::getToNetQueue(NodeID id, bool ordered, int network_num)
195 {
196 checkNetworkAllocation(id, ordered, network_num);
197 return m_toNetQueues[id][network_num];
198 }
199
200 MessageBuffer* GarnetNetwork::getFromNetQueue(NodeID id, bool ordered, int network_num)
201 {
202 checkNetworkAllocation(id, ordered, network_num);
203 return m_fromNetQueues[id][network_num];
204 }
205
206 void GarnetNetwork::clearStats()
207 {
208 m_ruby_start = g_eventQueue_ptr->getTime();
209 }
210
211 Time GarnetNetwork::getRubyStartTime()
212 {
213 return m_ruby_start;
214 }
215
216 void GarnetNetwork::printStats(ostream& out) const
217 { double average_link_utilization = 0;
218 Vector<double > average_vc_load;
219 average_vc_load.setSize(m_virtual_networks*m_network_config_ptr->getVCsPerClass());
220
221 for(int i = 0; i < m_virtual_networks*m_network_config_ptr->getVCsPerClass(); i++)
222 {
223 average_vc_load[i] = 0;
224 }
225
226 out << endl;
227 out << "Network Stats" << endl;
228 out << "-------------" << endl;
229 out << endl;
230 for(int i = 0; i < m_link_ptr_vector.size(); i++)
231 {
232 average_link_utilization += m_link_ptr_vector[i]->getLinkUtilization();
233 Vector<int > vc_load = m_link_ptr_vector[i]->getVcLoad();
234 for(int j = 0; j < vc_load.size(); j++)
235 {
236 assert(vc_load.size() == m_network_config_ptr->getVCsPerClass()*m_virtual_networks);
237 average_vc_load[j] += vc_load[j];
238 }
239 }
240 average_link_utilization = average_link_utilization/m_link_ptr_vector.size();
241 out << "Average Link Utilization :: " << average_link_utilization << " flits/cycle" <<endl;
242 out << "-------------" << endl;
243
244 for(int i = 0; i < m_network_config_ptr->getVCsPerClass()*m_virtual_networks; i++)
245 {
246 average_vc_load[i] = (double(average_vc_load[i]) / (double(g_eventQueue_ptr->getTime()) - m_ruby_start));
247 out << "Average VC Load [" << i << "] = " << average_vc_load[i] << " flits/cycle" << endl;
248 }
249 out << "-------------" << endl;
250 }
251
252 void GarnetNetwork::printConfig(ostream& out) const
253 {
254 out << endl;
255 out << "Network Configuration" << endl;
256 out << "---------------------" << endl;
257 out << "network: GARNET_NETWORK" << endl;
258 out << "topology: " << m_topology_ptr->getName() << endl;
259 out << endl;
260
261 for (int i = 0; i < m_virtual_networks; i++)
262 {
263 out << "virtual_net_" << i << ": ";
264 if (m_in_use[i])
265 {
266 out << "active, ";
267 if (m_ordered[i])
268 {
269 out << "ordered" << endl;
270 }
271 else
272 {
273 out << "unordered" << endl;
274 }
275 }
276 else
277 {
278 out << "inactive" << endl;
279 }
280 }
281 out << endl;
282
283 for(int i = 0; i < m_ni_ptr_vector.size(); i++)
284 {
285 m_ni_ptr_vector[i]->printConfig(out);
286 }
287 for(int i = 0; i < m_router_ptr_vector.size(); i++)
288 {
289 m_router_ptr_vector[i]->printConfig(out);
290 }
291 m_topology_ptr->printConfig(out);
292 }
293
294 void GarnetNetwork::print(ostream& out) const
295 {
296 out << "[GarnetNetwork]";
297 }