SimpleNetwork.cc revision 8485:7a9a7f2a3d46
1/*
2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
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
29#include <cassert>
30#include <numeric>
31
32#include "base/stl_helpers.hh"
33#include "mem/protocol/MachineType.hh"
34#include "mem/protocol/TopologyType.hh"
35#include "mem/ruby/buffers/MessageBuffer.hh"
36#include "mem/ruby/common/NetDest.hh"
37#include "mem/ruby/network/BasicLink.hh"
38#include "mem/ruby/network/simple/SimpleLink.hh"
39#include "mem/ruby/network/simple/SimpleNetwork.hh"
40#include "mem/ruby/network/simple/Switch.hh"
41#include "mem/ruby/network/simple/Throttle.hh"
42#include "mem/ruby/network/Topology.hh"
43#include "mem/ruby/profiler/Profiler.hh"
44#include "mem/ruby/system/System.hh"
45
46using namespace std;
47using m5::stl_helpers::deletePointers;
48
49#if 0
50// ***BIG HACK*** - This is actually code that _should_ be in Network.cc
51
52// Note: Moved to Princeton Network
53// calls new to abstract away from the network
54Network*
55Network::createNetwork(int nodes)
56{
57    return new SimpleNetwork(nodes);
58}
59#endif
60
61SimpleNetwork::SimpleNetwork(const Params *p)
62    : Network(p)
63{
64    m_buffer_size = p->buffer_size;
65    m_endpoint_bandwidth = p->endpoint_bandwidth;
66    m_adaptive_routing = p->adaptive_routing;
67
68    // Note: the parent Network Object constructor is called before the
69    // SimpleNetwork child constructor.  Therefore, the member variables
70    // used below should already be initialized.
71
72    m_endpoint_switches.resize(m_nodes);
73
74    m_in_use.resize(m_virtual_networks);
75    m_ordered.resize(m_virtual_networks);
76    for (int i = 0; i < m_virtual_networks; i++) {
77        m_in_use[i] = false;
78        m_ordered[i] = false;
79    }
80
81    // Allocate to and from queues
82    m_toNetQueues.resize(m_nodes);
83    m_fromNetQueues.resize(m_nodes);
84    for (int node = 0; node < m_nodes; node++) {
85        m_toNetQueues[node].resize(m_virtual_networks);
86        m_fromNetQueues[node].resize(m_virtual_networks);
87        for (int j = 0; j < m_virtual_networks; j++) {
88            m_toNetQueues[node][j] =
89                new MessageBuffer(csprintf("toNet node %d j %d", node, j));
90            m_fromNetQueues[node][j] =
91                new MessageBuffer(csprintf("fromNet node %d j %d", node, j));
92        }
93    }
94}
95
96void
97SimpleNetwork::init()
98{
99    Network::init();
100
101    // The topology pointer should have already been initialized in
102    // the parent class network constructor.
103    assert(m_topology_ptr != NULL);
104    int number_of_switches = m_topology_ptr->numSwitches();
105    for (int i = 0; i < number_of_switches; i++) {
106        m_switch_ptr_vector.push_back(new Switch(i, this));
107    }
108
109    // false because this isn't a reconfiguration
110    m_topology_ptr->createLinks(this, false);
111}
112
113void
114SimpleNetwork::reset()
115{
116    for (int node = 0; node < m_nodes; node++) {
117        for (int j = 0; j < m_virtual_networks; j++) {
118            m_toNetQueues[node][j]->clear();
119            m_fromNetQueues[node][j]->clear();
120        }
121    }
122
123    for(int i = 0; i < m_switch_ptr_vector.size(); i++){
124        m_switch_ptr_vector[i]->clearBuffers();
125    }
126}
127
128SimpleNetwork::~SimpleNetwork()
129{
130    for (int i = 0; i < m_nodes; i++) {
131        deletePointers(m_toNetQueues[i]);
132        deletePointers(m_fromNetQueues[i]);
133    }
134    deletePointers(m_switch_ptr_vector);
135    deletePointers(m_buffers_to_free);
136    // delete m_topology_ptr;
137}
138
139// From a switch to an endpoint node
140void
141SimpleNetwork::makeOutLink(SwitchID src, NodeID dest, BasicLink* link,
142                           LinkDirection direction,
143                           const NetDest& routing_table_entry,
144                           bool isReconfiguration)
145{
146    assert(dest < m_nodes);
147    assert(src < m_switch_ptr_vector.size());
148    assert(m_switch_ptr_vector[src] != NULL);
149
150    if (isReconfiguration) {
151        m_switch_ptr_vector[src]->reconfigureOutPort(routing_table_entry);
152        return;
153    }
154
155    SimpleExtLink *simple_link = safe_cast<SimpleExtLink*>(link);
156
157    m_switch_ptr_vector[src]->addOutPort(m_fromNetQueues[dest],
158                                         routing_table_entry,
159                                         simple_link->m_latency,
160                                         simple_link->m_bw_multiplier);
161
162    m_endpoint_switches[dest] = m_switch_ptr_vector[src];
163}
164
165// From an endpoint node to a switch
166void
167SimpleNetwork::makeInLink(NodeID src, SwitchID dest, BasicLink* link,
168                          LinkDirection direction,
169                          const NetDest& routing_table_entry,
170                          bool isReconfiguration)
171{
172    assert(src < m_nodes);
173    if (isReconfiguration) {
174        // do nothing
175        return;
176    }
177
178    m_switch_ptr_vector[dest]->addInPort(m_toNetQueues[src]);
179}
180
181// From a switch to a switch
182void
183SimpleNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
184                                LinkDirection direction,
185                                const NetDest& routing_table_entry,
186                                bool isReconfiguration)
187{
188    if (isReconfiguration) {
189        m_switch_ptr_vector[src]->reconfigureOutPort(routing_table_entry);
190        return;
191    }
192
193    // Create a set of new MessageBuffers
194    std::vector<MessageBuffer*> queues;
195    for (int i = 0; i < m_virtual_networks; i++) {
196        // allocate a buffer
197        MessageBuffer* buffer_ptr = new MessageBuffer;
198        buffer_ptr->setOrdering(true);
199        if (m_buffer_size > 0) {
200            buffer_ptr->resize(m_buffer_size);
201        }
202        queues.push_back(buffer_ptr);
203        // remember to deallocate it
204        m_buffers_to_free.push_back(buffer_ptr);
205    }
206    // Connect it to the two switches
207    SimpleIntLink *simple_link = safe_cast<SimpleIntLink*>(link);
208
209    m_switch_ptr_vector[dest]->addInPort(queues);
210    m_switch_ptr_vector[src]->addOutPort(queues, routing_table_entry,
211                                         simple_link->m_latency,
212                                         simple_link->m_bw_multiplier);
213}
214
215void
216SimpleNetwork::checkNetworkAllocation(NodeID id, bool ordered, int network_num)
217{
218    assert(id < m_nodes);
219    assert(network_num < m_virtual_networks);
220
221    if (ordered) {
222        m_ordered[network_num] = true;
223    }
224    m_in_use[network_num] = true;
225}
226
227MessageBuffer*
228SimpleNetwork::getToNetQueue(NodeID id, bool ordered, int network_num,
229                             std::string vnet_type)
230{
231    checkNetworkAllocation(id, ordered, network_num);
232    return m_toNetQueues[id][network_num];
233}
234
235MessageBuffer*
236SimpleNetwork::getFromNetQueue(NodeID id, bool ordered, int network_num,
237                               std::string vnet_type)
238{
239    checkNetworkAllocation(id, ordered, network_num);
240    return m_fromNetQueues[id][network_num];
241}
242
243const std::vector<Throttle*>*
244SimpleNetwork::getThrottles(NodeID id) const
245{
246    assert(id >= 0);
247    assert(id < m_nodes);
248    assert(m_endpoint_switches[id] != NULL);
249    return m_endpoint_switches[id]->getThrottles();
250}
251
252void
253SimpleNetwork::printStats(ostream& out) const
254{
255    out << endl;
256    out << "Network Stats" << endl;
257    out << "-------------" << endl;
258    out << endl;
259
260    //
261    // Determine total counts before printing out each switch's stats
262    //
263    std::vector<uint64> total_msg_counts;
264    total_msg_counts.resize(MessageSizeType_NUM);
265    for (MessageSizeType type = MessageSizeType_FIRST;
266         type < MessageSizeType_NUM;
267         ++type) {
268        total_msg_counts[type] = 0;
269    }
270
271    for (int i = 0; i < m_switch_ptr_vector.size(); i++) {
272        const std::vector<Throttle*>* throttles =
273            m_switch_ptr_vector[i]->getThrottles();
274
275        for (int p = 0; p < throttles->size(); p++) {
276
277            const std::vector<std::vector<int> >& message_counts =
278                ((*throttles)[p])->getCounters();
279
280            for (MessageSizeType type = MessageSizeType_FIRST;
281                 type < MessageSizeType_NUM;
282                 ++type) {
283
284                const std::vector<int> &mct = message_counts[type];
285                int sum = accumulate(mct.begin(), mct.end(), 0);
286                total_msg_counts[type] += uint64(sum);
287            }
288        }
289    }
290    uint64 total_msgs = 0;
291    uint64 total_bytes = 0;
292    for (MessageSizeType type = MessageSizeType_FIRST;
293         type < MessageSizeType_NUM;
294         ++type) {
295
296        if (total_msg_counts[type] > 0) {
297            out << "total_msg_count_" << type << ": " << total_msg_counts[type]
298                << " " << total_msg_counts[type] *
299                uint64(RubySystem::getNetwork()->MessageSizeType_to_int(type))
300                << endl;
301
302            total_msgs += total_msg_counts[type];
303
304            total_bytes += total_msg_counts[type] *
305                uint64(RubySystem::getNetwork()->MessageSizeType_to_int(type));
306
307        }
308    }
309
310    out << "total_msgs: " << total_msgs
311        << " total_bytes: " << total_bytes << endl;
312
313    out << endl;
314    for (int i = 0; i < m_switch_ptr_vector.size(); i++) {
315        m_switch_ptr_vector[i]->printStats(out);
316    }
317    m_topology_ptr->printStats(out);
318}
319
320void
321SimpleNetwork::clearStats()
322{
323    for (int i = 0; i < m_switch_ptr_vector.size(); i++) {
324        m_switch_ptr_vector[i]->clearStats();
325    }
326    m_topology_ptr->clearStats();
327}
328
329void
330SimpleNetwork::printConfig(ostream& out) const
331{
332    out << endl;
333    out << "Network Configuration" << endl;
334    out << "---------------------" << endl;
335    out << "network: SIMPLE_NETWORK" << 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_switch_ptr_vector.size(); i++) {
355        m_switch_ptr_vector[i]->printConfig(out);
356    }
357
358    m_topology_ptr->printConfig(out);
359}
360
361void
362SimpleNetwork::print(ostream& out) const
363{
364    out << "[SimpleNetwork]";
365}
366
367
368SimpleNetwork *
369SimpleNetworkParams::create()
370{
371    return new SimpleNetwork(this);
372}
373