SimpleNetwork.cc revision 10917:c38f28fad4c3
12SN/A/*
210292SAndreas.Sandberg@ARM.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
34039Sbinkertn@umich.edu * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272SN/A */
282665Ssaidi@eecs.umich.edu
292665Ssaidi@eecs.umich.edu#include <cassert>
302665Ssaidi@eecs.umich.edu#include <numeric>
3110292SAndreas.Sandberg@ARM.com
322SN/A#include "base/cast.hh"
332SN/A#include "base/stl_helpers.hh"
344039Sbinkertn@umich.edu#include "mem/ruby/common/NetDest.hh"
354039Sbinkertn@umich.edu#include "mem/ruby/network/MessageBuffer.hh"
362SN/A#include "mem/ruby/network/simple/SimpleLink.hh"
374039Sbinkertn@umich.edu#include "mem/ruby/network/simple/SimpleNetwork.hh"
382SN/A#include "mem/ruby/network/simple/Switch.hh"
392SN/A#include "mem/ruby/network/simple/Throttle.hh"
402SN/A#include "mem/ruby/profiler/Profiler.hh"
412SN/A#include "mem/ruby/system/System.hh"
428229Snate@binkert.org
432621SN/Ausing namespace std;
442SN/Ausing m5::stl_helpers::deletePointers;
452SN/A
464039Sbinkertn@umich.eduSimpleNetwork::SimpleNetwork(const Params *p)
472SN/A    : Network(p)
484039Sbinkertn@umich.edu{
494039Sbinkertn@umich.edu    m_buffer_size = p->buffer_size;
504039Sbinkertn@umich.edu    m_endpoint_bandwidth = p->endpoint_bandwidth;
514039Sbinkertn@umich.edu    m_adaptive_routing = p->adaptive_routing;
525756Snate@binkert.org
534039Sbinkertn@umich.edu    // Note: the parent Network Object constructor is called before the
544039Sbinkertn@umich.edu    // SimpleNetwork child constructor.  Therefore, the member variables
554039Sbinkertn@umich.edu    // used below should already be initialized.
564039Sbinkertn@umich.edu    m_endpoint_switches.resize(m_nodes);
574039Sbinkertn@umich.edu
585756Snate@binkert.org    // record the routers
595756Snate@binkert.org    for (vector<BasicRouter*>::const_iterator i = p->routers.begin();
609331Schander.sudanthi@arm.com         i != p->routers.end(); ++i) {
614039Sbinkertn@umich.edu        Switch* s = safe_cast<Switch*>(*i);
624039Sbinkertn@umich.edu        m_switches.push_back(s);
634039Sbinkertn@umich.edu        s->init_net_ptr(this);
644039Sbinkertn@umich.edu    }
654039Sbinkertn@umich.edu}
662SN/A
675756Snate@binkert.orgvoid
685756Snate@binkert.orgSimpleNetwork::init()
695756Snate@binkert.org{
705756Snate@binkert.org    Network::init();
715756Snate@binkert.org
725756Snate@binkert.org    // The topology pointer should have already been initialized in
735756Snate@binkert.org    // the parent class network constructor.
745756Snate@binkert.org    assert(m_topology_ptr != NULL);
755756Snate@binkert.org    m_topology_ptr->createLinks(this);
765756Snate@binkert.org}
775756Snate@binkert.org
785756Snate@binkert.orgSimpleNetwork::~SimpleNetwork()
795756Snate@binkert.org{
802SN/A    deletePointers(m_switches);
814039Sbinkertn@umich.edu    deletePointers(m_buffers_to_free);
824039Sbinkertn@umich.edu}
832SN/A
845756Snate@binkert.org// From a switch to an endpoint node
855756Snate@binkert.orgvoid
865756Snate@binkert.orgSimpleNetwork::makeOutLink(SwitchID src, NodeID dest, BasicLink* link,
875756Snate@binkert.org                           LinkDirection direction,
885756Snate@binkert.org                           const NetDest& routing_table_entry)
895756Snate@binkert.org{
905756Snate@binkert.org    assert(dest < m_nodes);
915756Snate@binkert.org    assert(src < m_switches.size());
925756Snate@binkert.org    assert(m_switches[src] != NULL);
935756Snate@binkert.org
945756Snate@binkert.org    SimpleExtLink *simple_link = safe_cast<SimpleExtLink*>(link);
955756Snate@binkert.org
965756Snate@binkert.org    m_switches[src]->addOutPort(m_fromNetQueues[dest], routing_table_entry,
975756Snate@binkert.org                                simple_link->m_latency,
985756Snate@binkert.org                                simple_link->m_bw_multiplier);
995756Snate@binkert.org
1002SN/A    m_endpoint_switches[dest] = m_switches[src];
1014039Sbinkertn@umich.edu}
1024039Sbinkertn@umich.edu
1034039Sbinkertn@umich.edu// From an endpoint node to a switch
1044039Sbinkertn@umich.eduvoid
1052SN/ASimpleNetwork::makeInLink(NodeID src, SwitchID dest, BasicLink* link,
1064039Sbinkertn@umich.edu                          LinkDirection direction,
1074039Sbinkertn@umich.edu                          const NetDest& routing_table_entry)
1084039Sbinkertn@umich.edu{
1092SN/A    assert(src < m_nodes);
1104039Sbinkertn@umich.edu    m_switches[dest]->addInPort(m_toNetQueues[src]);
1114039Sbinkertn@umich.edu}
1124039Sbinkertn@umich.edu
1132SN/A// From a switch to a switch
1144039Sbinkertn@umich.eduvoid
1154039Sbinkertn@umich.eduSimpleNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
1164039Sbinkertn@umich.edu                                LinkDirection direction,
1172SN/A                                const NetDest& routing_table_entry)
1184039Sbinkertn@umich.edu{
1194039Sbinkertn@umich.edu    // Create a set of new MessageBuffers
1204039Sbinkertn@umich.edu    std::vector<MessageBuffer*> queues(m_virtual_networks);
1212SN/A
1222SN/A    for (int i = 0; i < m_virtual_networks; i++) {
1232SN/A        // allocate a buffer
1244039Sbinkertn@umich.edu        MessageBuffer* buffer_ptr = new MessageBuffer;
1252SN/A        buffer_ptr->setOrdering(true);
1262SN/A
1277811Ssteve.reinhardt@amd.com        if (m_buffer_size > 0) {
1284039Sbinkertn@umich.edu            buffer_ptr->resize(m_buffer_size);
12910292SAndreas.Sandberg@ARM.com        }
13010292SAndreas.Sandberg@ARM.com
13110292SAndreas.Sandberg@ARM.com        queues[i] = buffer_ptr;
13210292SAndreas.Sandberg@ARM.com        // remember to deallocate it
13310292SAndreas.Sandberg@ARM.com        m_buffers_to_free.push_back(buffer_ptr);
1344039Sbinkertn@umich.edu    }
13510292SAndreas.Sandberg@ARM.com
13610292SAndreas.Sandberg@ARM.com    // Connect it to the two switches
13710292SAndreas.Sandberg@ARM.com    SimpleIntLink *simple_link = safe_cast<SimpleIntLink*>(link);
13810292SAndreas.Sandberg@ARM.com
13910292SAndreas.Sandberg@ARM.com    m_switches[dest]->addInPort(queues);
14010292SAndreas.Sandberg@ARM.com    m_switches[src]->addOutPort(queues, routing_table_entry,
14110292SAndreas.Sandberg@ARM.com                                simple_link->m_latency,
14210292SAndreas.Sandberg@ARM.com                                simple_link->m_bw_multiplier);
14310292SAndreas.Sandberg@ARM.com}
14410292SAndreas.Sandberg@ARM.com
14510292SAndreas.Sandberg@ARM.comvoid
14610292SAndreas.Sandberg@ARM.comSimpleNetwork::checkNetworkAllocation(NodeID id, bool ordered, int network_num)
1472SN/A{
1484039Sbinkertn@umich.edu    assert(id < m_nodes);
14910292SAndreas.Sandberg@ARM.com    assert(network_num < m_virtual_networks);
15010292SAndreas.Sandberg@ARM.com
1512SN/A    if (ordered) {
1522SN/A        m_ordered[network_num] = true;
15310292SAndreas.Sandberg@ARM.com    }
15410292SAndreas.Sandberg@ARM.com    m_in_use[network_num] = true;
15510292SAndreas.Sandberg@ARM.com}
1564039Sbinkertn@umich.edu
15710292SAndreas.Sandberg@ARM.comvoid
1584039Sbinkertn@umich.eduSimpleNetwork::setToNetQueue(NodeID id, bool ordered, int network_num,
1592SN/A                             std::string vnet_type, MessageBuffer *b)
16010292SAndreas.Sandberg@ARM.com{
16110292SAndreas.Sandberg@ARM.com    checkNetworkAllocation(id, ordered, network_num);
1624039Sbinkertn@umich.edu    while (m_toNetQueues[id].size() <= network_num) {
1634039Sbinkertn@umich.edu        m_toNetQueues[id].push_back(nullptr);
16410292SAndreas.Sandberg@ARM.com    }
1654039Sbinkertn@umich.edu    m_toNetQueues[id][network_num] = b;
1664039Sbinkertn@umich.edu}
1674039Sbinkertn@umich.edu
1684039Sbinkertn@umich.eduvoid
1694039Sbinkertn@umich.eduSimpleNetwork::setFromNetQueue(NodeID id, bool ordered, int network_num,
1704039Sbinkertn@umich.edu                               std::string vnet_type, MessageBuffer *b)
1714039Sbinkertn@umich.edu{
1724039Sbinkertn@umich.edu    checkNetworkAllocation(id, ordered, network_num);
17310292SAndreas.Sandberg@ARM.com    while (m_fromNetQueues[id].size() <= network_num) {
17410292SAndreas.Sandberg@ARM.com        m_fromNetQueues[id].push_back(nullptr);
1754039Sbinkertn@umich.edu    }
17610292SAndreas.Sandberg@ARM.com    m_fromNetQueues[id][network_num] = b;
1774039Sbinkertn@umich.edu}
1782SN/A
17910292SAndreas.Sandberg@ARM.comvoid
18010292SAndreas.Sandberg@ARM.comSimpleNetwork::regStats()
1814039Sbinkertn@umich.edu{
18210292SAndreas.Sandberg@ARM.com    for (MessageSizeType type = MessageSizeType_FIRST;
1834039Sbinkertn@umich.edu         type < MessageSizeType_NUM; ++type) {
1842SN/A        m_msg_counts[(unsigned int) type]
18510292SAndreas.Sandberg@ARM.com            .name(name() + ".msg_count." + MessageSizeType_to_string(type))
18610292SAndreas.Sandberg@ARM.com            .flags(Stats::nozero)
1874039Sbinkertn@umich.edu            ;
18810292SAndreas.Sandberg@ARM.com        m_msg_bytes[(unsigned int) type]
1892SN/A            .name(name() + ".msg_byte." + MessageSizeType_to_string(type))
1902SN/A            .flags(Stats::nozero)
1912SN/A            ;
192
193        // Now state what the formula is.
194        for (int i = 0; i < m_switches.size(); i++) {
195            m_msg_counts[(unsigned int) type] +=
196                sum(m_switches[i]->getMsgCount(type));
197        }
198
199        m_msg_bytes[(unsigned int) type] =
200            m_msg_counts[(unsigned int) type] * Stats::constant(
201                    Network::MessageSizeType_to_int(type));
202    }
203}
204
205void
206SimpleNetwork::collateStats()
207{
208    for (int i = 0; i < m_switches.size(); i++) {
209        m_switches[i]->collateStats();
210    }
211}
212
213void
214SimpleNetwork::print(ostream& out) const
215{
216    out << "[SimpleNetwork]";
217}
218
219SimpleNetwork *
220SimpleNetworkParams::create()
221{
222    return new SimpleNetwork(this);
223}
224
225/*
226 * The simple network has an array of switches. These switches have buffers
227 * that need to be accessed for functional reads and writes. Also the links
228 * between different switches have buffers that need to be accessed.
229 */
230bool
231SimpleNetwork::functionalRead(Packet *pkt)
232{
233    for (unsigned int i = 0; i < m_switches.size(); i++) {
234        if (m_switches[i]->functionalRead(pkt)) {
235            return true;
236        }
237    }
238
239    for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) {
240        if (m_buffers_to_free[i]->functionalRead(pkt)) {
241            return true;
242        }
243    }
244
245    return false;
246}
247
248uint32_t
249SimpleNetwork::functionalWrite(Packet *pkt)
250{
251    uint32_t num_functional_writes = 0;
252
253    for (unsigned int i = 0; i < m_switches.size(); i++) {
254        num_functional_writes += m_switches[i]->functionalWrite(pkt);
255    }
256
257    for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) {
258        num_functional_writes += m_buffers_to_free[i]->functionalWrite(pkt);
259    }
260    return num_functional_writes;
261}
262