16145Snate@binkert.org/*
26145Snate@binkert.org * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
36145Snate@binkert.org * All rights reserved.
46145Snate@binkert.org *
56145Snate@binkert.org * Redistribution and use in source and binary forms, with or without
66145Snate@binkert.org * modification, are permitted provided that the following conditions are
76145Snate@binkert.org * met: redistributions of source code must retain the above copyright
86145Snate@binkert.org * notice, this list of conditions and the following disclaimer;
96145Snate@binkert.org * redistributions in binary form must reproduce the above copyright
106145Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
116145Snate@binkert.org * documentation and/or other materials provided with the distribution;
126145Snate@binkert.org * neither the name of the copyright holders nor the names of its
136145Snate@binkert.org * contributors may be used to endorse or promote products derived from
146145Snate@binkert.org * this software without specific prior written permission.
156145Snate@binkert.org *
166145Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176145Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186145Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196145Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206145Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216145Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226145Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236145Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246145Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256145Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266145Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276145Snate@binkert.org */
286145Snate@binkert.org
2911793Sbrandon.potter@amd.com#include "mem/ruby/network/simple/SimpleNetwork.hh"
3011793Sbrandon.potter@amd.com
317832Snate@binkert.org#include <cassert>
327547SBrad.Beckmann@amd.com#include <numeric>
337547SBrad.Beckmann@amd.com
348645Snilay@cs.wisc.edu#include "base/cast.hh"
357454Snate@binkert.org#include "base/stl_helpers.hh"
367054Snate@binkert.org#include "mem/ruby/common/NetDest.hh"
3710301Snilay@cs.wisc.edu#include "mem/ruby/network/MessageBuffer.hh"
388258SBrad.Beckmann@amd.com#include "mem/ruby/network/simple/SimpleLink.hh"
397054Snate@binkert.org#include "mem/ruby/network/simple/Switch.hh"
407547SBrad.Beckmann@amd.com#include "mem/ruby/network/simple/Throttle.hh"
416154Snate@binkert.org#include "mem/ruby/profiler/Profiler.hh"
426145Snate@binkert.org
437055Snate@binkert.orgusing namespace std;
447454Snate@binkert.orgusing m5::stl_helpers::deletePointers;
457055Snate@binkert.org
466876Ssteve.reinhardt@amd.comSimpleNetwork::SimpleNetwork(const Params *p)
4711124Snilay@cs.wisc.edu    : Network(p), m_buffer_size(p->buffer_size),
4811124Snilay@cs.wisc.edu      m_endpoint_bandwidth(p->endpoint_bandwidth),
4911124Snilay@cs.wisc.edu      m_adaptive_routing(p->adaptive_routing)
506285Snate@binkert.org{
519274Snilay@cs.wisc.edu    // record the routers
529593Snilay@cs.wisc.edu    for (vector<BasicRouter*>::const_iterator i = p->routers.begin();
539593Snilay@cs.wisc.edu         i != p->routers.end(); ++i) {
549274Snilay@cs.wisc.edu        Switch* s = safe_cast<Switch*>(*i);
559858Snilay@cs.wisc.edu        m_switches.push_back(s);
569274Snilay@cs.wisc.edu        s->init_net_ptr(this);
579274Snilay@cs.wisc.edu    }
5811021Sjthestness@gmail.com
5911021Sjthestness@gmail.com    m_int_link_buffers = p->int_link_buffers;
6011021Sjthestness@gmail.com    m_num_connected_buffers = 0;
616881SBrad.Beckmann@amd.com}
626285Snate@binkert.org
637054Snate@binkert.orgvoid
647054Snate@binkert.orgSimpleNetwork::init()
656881SBrad.Beckmann@amd.com{
667054Snate@binkert.org    Network::init();
676881SBrad.Beckmann@amd.com
687054Snate@binkert.org    // The topology pointer should have already been initialized in
697054Snate@binkert.org    // the parent class network constructor.
707054Snate@binkert.org    assert(m_topology_ptr != NULL);
719799Snilay@cs.wisc.edu    m_topology_ptr->createLinks(this);
726285Snate@binkert.org}
736145Snate@binkert.org
746145Snate@binkert.orgSimpleNetwork::~SimpleNetwork()
756145Snate@binkert.org{
769858Snilay@cs.wisc.edu    deletePointers(m_switches);
7711021Sjthestness@gmail.com    deletePointers(m_int_link_buffers);
786145Snate@binkert.org}
796145Snate@binkert.org
806145Snate@binkert.org// From a switch to an endpoint node
817054Snate@binkert.orgvoid
8211663Stushar@ece.gatech.eduSimpleNetwork::makeExtOutLink(SwitchID src, NodeID dest, BasicLink* link,
839799Snilay@cs.wisc.edu                           const NetDest& routing_table_entry)
846145Snate@binkert.org{
857054Snate@binkert.org    assert(dest < m_nodes);
869858Snilay@cs.wisc.edu    assert(src < m_switches.size());
879858Snilay@cs.wisc.edu    assert(m_switches[src] != NULL);
887054Snate@binkert.org
898258SBrad.Beckmann@amd.com    SimpleExtLink *simple_link = safe_cast<SimpleExtLink*>(link);
908258SBrad.Beckmann@amd.com
9110311Snilay@cs.wisc.edu    m_switches[src]->addOutPort(m_fromNetQueues[dest], routing_table_entry,
9210311Snilay@cs.wisc.edu                                simple_link->m_latency,
9310311Snilay@cs.wisc.edu                                simple_link->m_bw_multiplier);
946145Snate@binkert.org}
956145Snate@binkert.org
966145Snate@binkert.org// From an endpoint node to a switch
977054Snate@binkert.orgvoid
9811663Stushar@ece.gatech.eduSimpleNetwork::makeExtInLink(NodeID src, SwitchID dest, BasicLink* link,
999799Snilay@cs.wisc.edu                          const NetDest& routing_table_entry)
1006145Snate@binkert.org{
1017054Snate@binkert.org    assert(src < m_nodes);
1029858Snilay@cs.wisc.edu    m_switches[dest]->addInPort(m_toNetQueues[src]);
1036145Snate@binkert.org}
1046145Snate@binkert.org
1056145Snate@binkert.org// From a switch to a switch
1067054Snate@binkert.orgvoid
10710917Sbrandon.potter@amd.comSimpleNetwork::makeInternalLink(SwitchID src, SwitchID dest, BasicLink* link,
10811664Stushar@ece.gatech.edu                                const NetDest& routing_table_entry,
10911664Stushar@ece.gatech.edu                                PortDirection src_outport,
11011664Stushar@ece.gatech.edu                                PortDirection dst_inport)
1116145Snate@binkert.org{
1126145Snate@binkert.org    // Create a set of new MessageBuffers
11310370Snilay@cs.wisc.edu    std::vector<MessageBuffer*> queues(m_virtual_networks);
11410370Snilay@cs.wisc.edu
1156145Snate@binkert.org    for (int i = 0; i < m_virtual_networks; i++) {
1167054Snate@binkert.org        // allocate a buffer
11711021Sjthestness@gmail.com        assert(m_num_connected_buffers < m_int_link_buffers.size());
11811021Sjthestness@gmail.com        MessageBuffer* buffer_ptr = m_int_link_buffers[m_num_connected_buffers];
11911021Sjthestness@gmail.com        m_num_connected_buffers++;
12010311Snilay@cs.wisc.edu        queues[i] = buffer_ptr;
1217054Snate@binkert.org    }
12210311Snilay@cs.wisc.edu
1237054Snate@binkert.org    // Connect it to the two switches
1248258SBrad.Beckmann@amd.com    SimpleIntLink *simple_link = safe_cast<SimpleIntLink*>(link);
1258258SBrad.Beckmann@amd.com
1269858Snilay@cs.wisc.edu    m_switches[dest]->addInPort(queues);
1279858Snilay@cs.wisc.edu    m_switches[src]->addOutPort(queues, routing_table_entry,
12810311Snilay@cs.wisc.edu                                simple_link->m_latency,
12910311Snilay@cs.wisc.edu                                simple_link->m_bw_multiplier);
1307054Snate@binkert.org}
1317054Snate@binkert.org
1327054Snate@binkert.orgvoid
1339863Snilay@cs.wisc.eduSimpleNetwork::regStats()
1347054Snate@binkert.org{
13511523Sdavid.guillen@arm.com    Network::regStats();
13611523Sdavid.guillen@arm.com
1379863Snilay@cs.wisc.edu    for (MessageSizeType type = MessageSizeType_FIRST;
1389863Snilay@cs.wisc.edu         type < MessageSizeType_NUM; ++type) {
1399863Snilay@cs.wisc.edu        m_msg_counts[(unsigned int) type]
1409863Snilay@cs.wisc.edu            .name(name() + ".msg_count." + MessageSizeType_to_string(type))
1419863Snilay@cs.wisc.edu            .flags(Stats::nozero)
1429863Snilay@cs.wisc.edu            ;
1439863Snilay@cs.wisc.edu        m_msg_bytes[(unsigned int) type]
1449863Snilay@cs.wisc.edu            .name(name() + ".msg_byte." + MessageSizeType_to_string(type))
1459863Snilay@cs.wisc.edu            .flags(Stats::nozero)
1469863Snilay@cs.wisc.edu            ;
1477547SBrad.Beckmann@amd.com
1489863Snilay@cs.wisc.edu        // Now state what the formula is.
1499863Snilay@cs.wisc.edu        for (int i = 0; i < m_switches.size(); i++) {
1509863Snilay@cs.wisc.edu            m_msg_counts[(unsigned int) type] +=
1519863Snilay@cs.wisc.edu                sum(m_switches[i]->getMsgCount(type));
1527547SBrad.Beckmann@amd.com        }
1539863Snilay@cs.wisc.edu
1549863Snilay@cs.wisc.edu        m_msg_bytes[(unsigned int) type] =
1559863Snilay@cs.wisc.edu            m_msg_counts[(unsigned int) type] * Stats::constant(
1569863Snilay@cs.wisc.edu                    Network::MessageSizeType_to_int(type));
1577054Snate@binkert.org    }
1587054Snate@binkert.org}
1597054Snate@binkert.org
1607054Snate@binkert.orgvoid
1619863Snilay@cs.wisc.eduSimpleNetwork::collateStats()
1627054Snate@binkert.org{
1639858Snilay@cs.wisc.edu    for (int i = 0; i < m_switches.size(); i++) {
1649863Snilay@cs.wisc.edu        m_switches[i]->collateStats();
1657054Snate@binkert.org    }
1667054Snate@binkert.org}
1677054Snate@binkert.org
1687054Snate@binkert.orgvoid
1697054Snate@binkert.orgSimpleNetwork::print(ostream& out) const
1706145Snate@binkert.org{
1717054Snate@binkert.org    out << "[SimpleNetwork]";
1726145Snate@binkert.org}
1736876Ssteve.reinhardt@amd.com
1746876Ssteve.reinhardt@amd.comSimpleNetwork *
1756876Ssteve.reinhardt@amd.comSimpleNetworkParams::create()
1766876Ssteve.reinhardt@amd.com{
1776876Ssteve.reinhardt@amd.com    return new SimpleNetwork(this);
1786876Ssteve.reinhardt@amd.com}
1799302Snilay@cs.wisc.edu
1809302Snilay@cs.wisc.edu/*
1819302Snilay@cs.wisc.edu * The simple network has an array of switches. These switches have buffers
1829302Snilay@cs.wisc.edu * that need to be accessed for functional reads and writes. Also the links
1839302Snilay@cs.wisc.edu * between different switches have buffers that need to be accessed.
1849302Snilay@cs.wisc.edu */
1859302Snilay@cs.wisc.edubool
1869302Snilay@cs.wisc.eduSimpleNetwork::functionalRead(Packet *pkt)
1879302Snilay@cs.wisc.edu{
1889858Snilay@cs.wisc.edu    for (unsigned int i = 0; i < m_switches.size(); i++) {
1899858Snilay@cs.wisc.edu        if (m_switches[i]->functionalRead(pkt)) {
1909302Snilay@cs.wisc.edu            return true;
1919302Snilay@cs.wisc.edu        }
1929302Snilay@cs.wisc.edu    }
1939302Snilay@cs.wisc.edu
1949302Snilay@cs.wisc.edu    return false;
1959302Snilay@cs.wisc.edu}
1969302Snilay@cs.wisc.edu
1979302Snilay@cs.wisc.eduuint32_t
1989302Snilay@cs.wisc.eduSimpleNetwork::functionalWrite(Packet *pkt)
1999302Snilay@cs.wisc.edu{
2009302Snilay@cs.wisc.edu    uint32_t num_functional_writes = 0;
2019302Snilay@cs.wisc.edu
2029858Snilay@cs.wisc.edu    for (unsigned int i = 0; i < m_switches.size(); i++) {
2039858Snilay@cs.wisc.edu        num_functional_writes += m_switches[i]->functionalWrite(pkt);
2049302Snilay@cs.wisc.edu    }
2059302Snilay@cs.wisc.edu
20611021Sjthestness@gmail.com    for (unsigned int i = 0; i < m_int_link_buffers.size(); ++i) {
20711021Sjthestness@gmail.com        num_functional_writes += m_int_link_buffers[i]->functionalWrite(pkt);
2089302Snilay@cs.wisc.edu    }
2099302Snilay@cs.wisc.edu    return num_functional_writes;
2109302Snilay@cs.wisc.edu}
211