SimpleNetwork.cc revision 8255:73089f793a0a
16899SN/A/*
26899SN/A * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
36899SN/A * All rights reserved.
46899SN/A *
56899SN/A * Redistribution and use in source and binary forms, with or without
66899SN/A * modification, are permitted provided that the following conditions are
76899SN/A * met: redistributions of source code must retain the above copyright
86899SN/A * notice, this list of conditions and the following disclaimer;
96899SN/A * redistributions in binary form must reproduce the above copyright
106899SN/A * notice, this list of conditions and the following disclaimer in the
116899SN/A * documentation and/or other materials provided with the distribution;
126899SN/A * neither the name of the copyright holders nor the names of its
136899SN/A * contributors may be used to endorse or promote products derived from
146899SN/A * this software without specific prior written permission.
156899SN/A *
166899SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176899SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186899SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196899SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206899SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216899SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226899SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236899SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246899SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256899SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266899SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276899SN/A */
286899SN/A
296899SN/A#include <cassert>
307632SBrad.Beckmann@amd.com#include <numeric>
317053SN/A
326899SN/A#include "base/stl_helpers.hh"
336899SN/A#include "mem/protocol/MachineType.hh"
346899SN/A#include "mem/protocol/Protocol.hh"
357053SN/A#include "mem/protocol/TopologyType.hh"
367053SN/A#include "mem/ruby/buffers/MessageBuffer.hh"
377053SN/A#include "mem/ruby/common/NetDest.hh"
387053SN/A#include "mem/ruby/network/simple/SimpleNetwork.hh"
397053SN/A#include "mem/ruby/network/simple/Switch.hh"
406899SN/A#include "mem/ruby/network/simple/Throttle.hh"
417053SN/A#include "mem/ruby/network/Topology.hh"
426899SN/A#include "mem/ruby/profiler/Profiler.hh"
437053SN/A#include "mem/ruby/system/System.hh"
447053SN/A
457053SN/Ausing namespace std;
467053SN/Ausing m5::stl_helpers::deletePointers;
477053SN/A
487053SN/A#if 0
496899SN/A// ***BIG HACK*** - This is actually code that _should_ be in Network.cc
506899SN/A
517053SN/A// Note: Moved to Princeton Network
527053SN/A// calls new to abstract away from the network
536899SN/ANetwork*
547053SN/ANetwork::createNetwork(int nodes)
557053SN/A{
566899SN/A    return new SimpleNetwork(nodes);
577053SN/A}
587053SN/A#endif
597053SN/A
607053SN/ASimpleNetwork::SimpleNetwork(const Params *p)
616899SN/A    : Network(p)
627053SN/A{
637053SN/A    // Note: the parent Network Object constructor is called before the
647053SN/A    // SimpleNetwork child constructor.  Therefore, the member variables
657053SN/A    // used below should already be initialized.
667053SN/A
677053SN/A    m_endpoint_switches.resize(m_nodes);
687053SN/A
697053SN/A    m_in_use.resize(m_virtual_networks);
707053SN/A    m_ordered.resize(m_virtual_networks);
716899SN/A    for (int i = 0; i < m_virtual_networks; i++) {
726899SN/A        m_in_use[i] = false;
737053SN/A        m_ordered[i] = false;
747053SN/A    }
756899SN/A
767053SN/A    // Allocate to and from queues
776899SN/A    m_toNetQueues.resize(m_nodes);
787053SN/A    m_fromNetQueues.resize(m_nodes);
797053SN/A    for (int node = 0; node < m_nodes; node++) {
807053SN/A        m_toNetQueues[node].resize(m_virtual_networks);
816899SN/A        m_fromNetQueues[node].resize(m_virtual_networks);
827053SN/A        for (int j = 0; j < m_virtual_networks; j++) {
837053SN/A            m_toNetQueues[node][j] =
846899SN/A                new MessageBuffer(csprintf("toNet node %d j %d", node, j));
857053SN/A            m_fromNetQueues[node][j] =
866899SN/A                new MessageBuffer(csprintf("fromNet node %d j %d", node, j));
877053SN/A        }
887053SN/A    }
897053SN/A}
907053SN/A
917053SN/Avoid
927053SN/ASimpleNetwork::init()
937053SN/A{
947053SN/A    Network::init();
957053SN/A
967053SN/A    // The topology pointer should have already been initialized in
977053SN/A    // the parent class network constructor.
986899SN/A    assert(m_topology_ptr != NULL);
996899SN/A    int number_of_switches = m_topology_ptr->numSwitches();
1007568SN/A    for (int i = 0; i < number_of_switches; i++) {
1017568SN/A        m_switch_ptr_vector.push_back(new Switch(i, this));
1027568SN/A    }
1037568SN/A
1047053SN/A    // false because this isn't a reconfiguration
1056899SN/A    m_topology_ptr->createLinks(this, false);
1067053SN/A}
1077053SN/A
1087053SN/Avoid
1097053SN/ASimpleNetwork::reset()
1106899SN/A{
1117053SN/A    for (int node = 0; node < m_nodes; node++) {
1127053SN/A        for (int j = 0; j < m_virtual_networks; j++) {
1137053SN/A            m_toNetQueues[node][j]->clear();
1147053SN/A            m_fromNetQueues[node][j]->clear();
1157053SN/A        }
1167053SN/A    }
1177053SN/A
1187053SN/A    for(int i = 0; i < m_switch_ptr_vector.size(); i++){
1197053SN/A        m_switch_ptr_vector[i]->clearBuffers();
1206899SN/A    }
1217053SN/A}
1227053SN/A
1237053SN/ASimpleNetwork::~SimpleNetwork()
1246899SN/A{
1256899SN/A    for (int i = 0; i < m_nodes; i++) {
1267053SN/A        deletePointers(m_toNetQueues[i]);
1277053SN/A        deletePointers(m_fromNetQueues[i]);
1286899SN/A    }
1297053SN/A    deletePointers(m_switch_ptr_vector);
1307053SN/A    deletePointers(m_buffers_to_free);
1316899SN/A    // delete m_topology_ptr;
1327053SN/A}
1337053SN/A
1347053SN/A// From a switch to an endpoint node
1356899SN/Avoid
1367053SN/ASimpleNetwork::makeOutLink(SwitchID src, NodeID dest,
1376899SN/A    const NetDest& routing_table_entry, int link_latency, int link_weight,
1387053SN/A    int bw_multiplier, bool isReconfiguration)
1397053SN/A{
1406899SN/A    assert(dest < m_nodes);
1417053SN/A    assert(src < m_switch_ptr_vector.size());
1427053SN/A    assert(m_switch_ptr_vector[src] != NULL);
1437053SN/A
1446899SN/A    if (isReconfiguration) {
1457053SN/A        m_switch_ptr_vector[src]->reconfigureOutPort(routing_table_entry);
1467053SN/A        return;
1477053SN/A    }
1487053SN/A
1497053SN/A    m_switch_ptr_vector[src]->addOutPort(m_fromNetQueues[dest],
1507053SN/A        routing_table_entry, link_latency, bw_multiplier);
1516899SN/A    m_endpoint_switches[dest] = m_switch_ptr_vector[src];
1527053SN/A}
1536899SN/A
1547053SN/A// From an endpoint node to a switch
1557053SN/Avoid
1567053SN/ASimpleNetwork::makeInLink(NodeID src, SwitchID dest,
1577053SN/A    const NetDest& routing_table_entry, int link_latency, int bw_multiplier,
1586899SN/A    bool isReconfiguration)
1597053SN/A{
1607053SN/A    assert(src < m_nodes);
1616899SN/A    if (isReconfiguration) {
1627053SN/A        // do nothing
1637053SN/A        return;
1647053SN/A    }
1657053SN/A
1666899SN/A    m_switch_ptr_vector[dest]->addInPort(m_toNetQueues[src]);
1677053SN/A}
1687053SN/A
1697053SN/A// From a switch to a switch
1707053SN/Avoid
1717053SN/ASimpleNetwork::makeInternalLink(SwitchID src, SwitchID dest,
1727053SN/A    const NetDest& routing_table_entry, int link_latency, int link_weight,
1737053SN/A    int bw_multiplier, bool isReconfiguration)
1747053SN/A{
1757053SN/A    if (isReconfiguration) {
1767053SN/A        m_switch_ptr_vector[src]->reconfigureOutPort(routing_table_entry);
1777053SN/A        return;
1787053SN/A    }
1797053SN/A
1807053SN/A    // Create a set of new MessageBuffers
1817053SN/A    std::vector<MessageBuffer*> queues;
1827053SN/A    for (int i = 0; i < m_virtual_networks; i++) {
1837053SN/A        // allocate a buffer
1847053SN/A        MessageBuffer* buffer_ptr = new MessageBuffer;
1857053SN/A        buffer_ptr->setOrdering(true);
1866899SN/A        if (m_buffer_size > 0) {
1876899SN/A            buffer_ptr->resize(m_buffer_size);
1886899SN/A        }
1897053SN/A        queues.push_back(buffer_ptr);
1907053SN/A        // remember to deallocate it
1916899SN/A        m_buffers_to_free.push_back(buffer_ptr);
1927053SN/A    }
1937053SN/A    // Connect it to the two switches
1946899SN/A    m_switch_ptr_vector[dest]->addInPort(queues);
1957053SN/A    m_switch_ptr_vector[src]->addOutPort(queues, routing_table_entry,
1967053SN/A        link_latency, bw_multiplier);
1977053SN/A}
1986899SN/A
1997053SN/Avoid
2006899SN/ASimpleNetwork::checkNetworkAllocation(NodeID id, bool ordered, int network_num)
2017053SN/A{
2027053SN/A    assert(id < m_nodes);
2037053SN/A    assert(network_num < m_virtual_networks);
2047053SN/A
2056899SN/A    if (ordered) {
2067568SN/A        m_ordered[network_num] = true;
2077568SN/A    }
2087568SN/A    m_in_use[network_num] = true;
2097568SN/A}
2107053SN/A
2117053SN/AMessageBuffer*
2127053SN/ASimpleNetwork::getToNetQueue(NodeID id, bool ordered, int network_num)
2136899SN/A{
2147053SN/A    checkNetworkAllocation(id, ordered, network_num);
2157053SN/A    return m_toNetQueues[id][network_num];
2167053SN/A}
2177053SN/A
2186899SN/AMessageBuffer*
2197053SN/ASimpleNetwork::getFromNetQueue(NodeID id, bool ordered, int network_num)
2207053SN/A{
2217053SN/A    checkNetworkAllocation(id, ordered, network_num);
2227053SN/A    return m_fromNetQueues[id][network_num];
2237053SN/A}
2247053SN/A
2257053SN/Aconst std::vector<Throttle*>*
2267053SN/ASimpleNetwork::getThrottles(NodeID id) const
2277053SN/A{
2287053SN/A    assert(id >= 0);
2297053SN/A    assert(id < m_nodes);
2307053SN/A    assert(m_endpoint_switches[id] != NULL);
2317053SN/A    return m_endpoint_switches[id]->getThrottles();
2327053SN/A}
2336899SN/A
2347053SN/Avoid
2357053SN/ASimpleNetwork::printStats(ostream& out) const
2367053SN/A{
2377053SN/A    out << endl;
2387053SN/A    out << "Network Stats" << endl;
2396899SN/A    out << "-------------" << endl;
2406899SN/A    out << endl;
2417053SN/A
2427053SN/A    //
2436899SN/A    // Determine total counts before printing out each switch's stats
2447053SN/A    //
2456899SN/A    std::vector<uint64> total_msg_counts;
2467053SN/A    total_msg_counts.resize(MessageSizeType_NUM);
2477053SN/A    for (MessageSizeType type = MessageSizeType_FIRST;
2486899SN/A         type < MessageSizeType_NUM;
2497053SN/A         ++type) {
2507053SN/A        total_msg_counts[type] = 0;
2517053SN/A    }
2527053SN/A
2536899SN/A    for (int i = 0; i < m_switch_ptr_vector.size(); i++) {
2546899SN/A        const std::vector<Throttle*>* throttles =
2557053SN/A            m_switch_ptr_vector[i]->getThrottles();
2567053SN/A
2577053SN/A        for (int p = 0; p < throttles->size(); p++) {
2587053SN/A
2597053SN/A            const std::vector<std::vector<int> >& message_counts =
2607053SN/A                ((*throttles)[p])->getCounters();
2617053SN/A
2627053SN/A            for (MessageSizeType type = MessageSizeType_FIRST;
2637053SN/A                 type < MessageSizeType_NUM;
2647053SN/A                 ++type) {
2657053SN/A
2667053SN/A                const std::vector<int> &mct = message_counts[type];
2677053SN/A                int sum = accumulate(mct.begin(), mct.end(), 0);
2687053SN/A                total_msg_counts[type] += uint64(sum);
2697053SN/A            }
2707053SN/A        }
2717053SN/A    }
2727053SN/A    uint64 total_msgs = 0;
2737805Snilay@cs.wisc.edu    uint64 total_bytes = 0;
2747805Snilay@cs.wisc.edu    for (MessageSizeType type = MessageSizeType_FIRST;
2757805Snilay@cs.wisc.edu         type < MessageSizeType_NUM;
2767805Snilay@cs.wisc.edu         ++type) {
2777805Snilay@cs.wisc.edu
2787805Snilay@cs.wisc.edu        if (total_msg_counts[type] > 0) {
2797805Snilay@cs.wisc.edu            out << "total_msg_count_" << type << ": " << total_msg_counts[type]
2807053SN/A                << " " << total_msg_counts[type] *
2817053SN/A                uint64(RubySystem::getNetwork()->MessageSizeType_to_int(type))
2827053SN/A                << endl;
2837053SN/A
2846899SN/A            total_msgs += total_msg_counts[type];
2857053SN/A
2867053SN/A            total_bytes += total_msg_counts[type] *
2876899SN/A                uint64(RubySystem::getNetwork()->MessageSizeType_to_int(type));
2887053SN/A
2897053SN/A        }
2907053SN/A    }
2917053SN/A
2927805Snilay@cs.wisc.edu    out << "total_msgs: " << total_msgs
2937805Snilay@cs.wisc.edu        << " total_bytes: " << total_bytes << endl;
2947805Snilay@cs.wisc.edu
2957053SN/A    out << endl;
2967053SN/A    for (int i = 0; i < m_switch_ptr_vector.size(); i++) {
2977053SN/A        m_switch_ptr_vector[i]->printStats(out);
2987053SN/A    }
2997053SN/A    m_topology_ptr->printStats(out);
3007053SN/A}
3016899SN/A
3026899SN/Avoid
3037053SN/ASimpleNetwork::clearStats()
3047053SN/A{
3056899SN/A    for (int i = 0; i < m_switch_ptr_vector.size(); i++) {
3067053SN/A        m_switch_ptr_vector[i]->clearStats();
3077053SN/A    }
3087053SN/A    m_topology_ptr->clearStats();
3097053SN/A}
3106899SN/A
3116899SN/Avoid
3127053SN/ASimpleNetwork::printConfig(ostream& out) const
3137053SN/A{
3146899SN/A    out << endl;
3157053SN/A    out << "Network Configuration" << endl;
3167053SN/A    out << "---------------------" << endl;
3177053SN/A    out << "network: SIMPLE_NETWORK" << endl;
3187053SN/A    out << "topology: " << m_topology_ptr->getName() << endl;
3196899SN/A    out << endl;
3206899SN/A
3217053SN/A    for (int i = 0; i < m_virtual_networks; i++) {
3227053SN/A        out << "virtual_net_" << i << ": ";
3236899SN/A        if (m_in_use[i]) {
3247053SN/A            out << "active, ";
3257053SN/A            if (m_ordered[i]) {
3267053SN/A                out << "ordered" << endl;
3277053SN/A            } else {
3287053SN/A                out << "unordered" << endl;
3296899SN/A            }
3306899SN/A        } else {
3317053SN/A            out << "inactive" << endl;
3327055SN/A        }
3336899SN/A    }
3347053SN/A    out << endl;
3357053SN/A
3367053SN/A    for(int i = 0; i < m_switch_ptr_vector.size(); i++) {
3377053SN/A        m_switch_ptr_vector[i]->printConfig(out);
3387053SN/A    }
3397053SN/A
3407055SN/A    m_topology_ptr->printConfig(out);
3416899SN/A}
3426899SN/A
3437053SN/Avoid
3447053SN/ASimpleNetwork::print(ostream& out) const
3456899SN/A{
3467053SN/A    out << "[SimpleNetwork]";
3477053SN/A}
3487053SN/A
3497053SN/A
3507053SN/ASimpleNetwork *
3516899SN/ASimpleNetworkParams::create()
352{
353    return new SimpleNetwork(this);
354}
355