Switch.cc revision 10918:dd3ab1f109ad
12SN/A/*
22188SN/A * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
32SN/A * 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.
272665SN/A */
282665SN/A
292665SN/A#include <numeric>
302665SN/A
312665SN/A#include "base/cast.hh"
322SN/A#include "base/stl_helpers.hh"
332SN/A#include "mem/ruby/network/MessageBuffer.hh"
342SN/A#include "mem/ruby/network/simple/PerfectSwitch.hh"
352SN/A#include "mem/ruby/network/simple/SimpleNetwork.hh"
362465SN/A#include "mem/ruby/network/simple/Switch.hh"
371717SN/A#include "mem/ruby/network/simple/Throttle.hh"
382683Sktlim@umich.edu
392680SN/Ausing namespace std;
405529Snate@binkert.orgusing m5::stl_helpers::deletePointers;
412SN/Ausing m5::stl_helpers::operator<<;
421858SN/A
433565Sgblack@eecs.umich.eduSwitch::Switch(const Params *p) : BasicRouter(p)
445529Snate@binkert.org{
451917SN/A    m_perfect_switch = new PerfectSwitch(m_id, this, p->virt_nets);
461070SN/A}
471917SN/A
482188SN/ASwitch::~Switch()
491917SN/A{
502290SN/A    delete m_perfect_switch;
511070SN/A
521917SN/A    // Delete throttles (one per output port)
532SN/A    deletePointers(m_throttles);
545529Snate@binkert.org
55360SN/A    // Delete MessageBuffers
562519SN/A    deletePointers(m_buffers_to_free);
572SN/A}
582SN/A
592SN/Avoid
602SN/ASwitch::init()
612SN/A{
621858SN/A    BasicRouter::init();
632683Sktlim@umich.edu    m_perfect_switch->init(m_network_ptr);
643453Sgblack@eecs.umich.edu}
652683Sktlim@umich.edu
663402Sktlim@umich.eduvoid
672683Sktlim@umich.eduSwitch::addInPort(const vector<MessageBuffer*>& in)
682521SN/A{
692SN/A    m_perfect_switch->addInPort(in);
702683Sktlim@umich.edu
712190SN/A    for (auto& it : in) {
722680SN/A        if (it != nullptr) {
732290SN/A            it->setReceiver(this);
742526SN/A        }
751917SN/A    }
765529Snate@binkert.org}
771982SN/A
781917SN/Avoid
792683Sktlim@umich.eduSwitch::addOutPort(const vector<MessageBuffer*>& out,
802683Sktlim@umich.edu                   const NetDest& routing_table_entry,
811917SN/A                   Cycles link_latency, int bw_multiplier)
821917SN/A{
831917SN/A    // Create a throttle
841917SN/A    RubySystem *rs = m_network_ptr->params()->ruby_system;
851917SN/A    Throttle* throttle_ptr = new Throttle(m_id, rs, m_throttles.size(),
861917SN/A                                          link_latency, bw_multiplier,
871917SN/A                                          m_network_ptr->getEndpointBandwidth(),
881917SN/A                                          this);
892521SN/A
905482Snate@binkert.org    m_throttles.push_back(throttle_ptr);
913548Sgblack@eecs.umich.edu
922SN/A    // Create one buffer per vnet (these are intermediaryQueues)
932SN/A    vector<MessageBuffer*> intermediateBuffers;
944997Sgblack@eecs.umich.edu
954997Sgblack@eecs.umich.edu    for (int i = 0; i < out.size(); ++i) {
963402Sktlim@umich.edu        if (out[i] != nullptr) {
974997Sgblack@eecs.umich.edu            out[i]->setSender(this);
982SN/A        }
992526SN/A
1002683Sktlim@umich.edu        MessageBuffer* buffer_ptr = new MessageBuffer;
1012SN/A        // Make these queues ordered
1022190SN/A        buffer_ptr->setOrdering(true);
1032862Sktlim@umich.edu        if (m_network_ptr->getBufferSize() > 0) {
1042862Sktlim@umich.edu            buffer_ptr->resize(m_network_ptr->getBufferSize());
1052864Sktlim@umich.edu        }
1062862Sktlim@umich.edu
1073402Sktlim@umich.edu        intermediateBuffers.push_back(buffer_ptr);
1082862Sktlim@umich.edu        m_buffers_to_free.push_back(buffer_ptr);
1093402Sktlim@umich.edu
1102862Sktlim@umich.edu        buffer_ptr->setSender(this);
1112190SN/A        buffer_ptr->setReceiver(this);
1122683Sktlim@umich.edu    }
1132862Sktlim@umich.edu
1142190SN/A    // Hook the queues to the PerfectSwitch
1152190SN/A    m_perfect_switch->addOutPort(intermediateBuffers, routing_table_entry);
1162683Sktlim@umich.edu
1171070SN/A    // Hook the queues to the Throttle
1183486Sktlim@umich.edu    throttle_ptr->addLinks(intermediateBuffers, out);
1193486Sktlim@umich.edu}
1203486Sktlim@umich.edu
1213486Sktlim@umich.educonst Throttle*
1222680SN/ASwitch::getThrottle(LinkID link_number) const
1231070SN/A{
1241070SN/A    assert(m_throttles[link_number] != NULL);
1251917SN/A    return m_throttles[link_number];
1262683Sktlim@umich.edu}
127180SN/A
128180SN/Avoid
1291858SN/ASwitch::regStats()
1302235SN/A{
131180SN/A    for (int link = 0; link < m_throttles.size(); link++) {
1322235SN/A        m_throttles[link]->regStats(name());
133180SN/A    }
134180SN/A
1352862Sktlim@umich.edu    m_avg_utilization.name(name() + ".percent_links_utilized");
1362862Sktlim@umich.edu    for (unsigned int i = 0; i < m_throttles.size(); i++) {
1372313SN/A        m_avg_utilization += m_throttles[i]->getUtilization();
1382313SN/A    }
1392680SN/A    m_avg_utilization /= Stats::constant(m_throttles.size());
1402313SN/A
1412680SN/A    for (unsigned int type = MessageSizeType_FIRST;
1422313SN/A         type < MessageSizeType_NUM; ++type) {
1432313SN/A        m_msg_counts[type]
1442680SN/A            .name(name() + ".msg_count." +
1452313SN/A                MessageSizeType_to_string(MessageSizeType(type)))
1462361SN/A            .flags(Stats::nozero)
1473548Sgblack@eecs.umich.edu            ;
1482361SN/A        m_msg_bytes[type]
1492361SN/A            .name(name() + ".msg_bytes." +
1502361SN/A                MessageSizeType_to_string(MessageSizeType(type)))
1512235SN/A            .flags(Stats::nozero)
152180SN/A            ;
153180SN/A
154180SN/A        for (unsigned int i = 0; i < m_throttles.size(); i++) {
1552680SN/A            m_msg_counts[type] += m_throttles[i]->getMsgCount(type);
156180SN/A        }
157180SN/A        m_msg_bytes[type] = m_msg_counts[type] * Stats::constant(
1582SN/A                Network::MessageSizeType_to_int(MessageSizeType(type)));
1592864Sktlim@umich.edu    }
1602864Sktlim@umich.edu}
1612864Sktlim@umich.edu
1622864Sktlim@umich.eduvoid
1632864Sktlim@umich.eduSwitch::resetStats()
1642864Sktlim@umich.edu{
1652864Sktlim@umich.edu    m_perfect_switch->clearStats();
1662864Sktlim@umich.edu    for (int i = 0; i < m_throttles.size(); i++) {
1672864Sktlim@umich.edu        m_throttles[i]->clearStats();
1683548Sgblack@eecs.umich.edu    }
1692864Sktlim@umich.edu}
1702864Sktlim@umich.edu
1712864Sktlim@umich.eduvoid
1722864Sktlim@umich.eduSwitch::collateStats()
1732864Sktlim@umich.edu{
1742864Sktlim@umich.edu    m_perfect_switch->collateStats();
1752864Sktlim@umich.edu    for (int i = 0; i < m_throttles.size(); i++) {
1762862Sktlim@umich.edu        m_throttles[i]->collateStats();
1772862Sktlim@umich.edu    }
1782862Sktlim@umich.edu}
1792862Sktlim@umich.edu
1802862Sktlim@umich.eduvoid
1812862Sktlim@umich.eduSwitch::print(std::ostream& out) const
1822862Sktlim@umich.edu{
1832862Sktlim@umich.edu    // FIXME printing
1842862Sktlim@umich.edu    out << "[Switch]";
1852915Sktlim@umich.edu}
1862862Sktlim@umich.edu
1872862Sktlim@umich.edubool
1882862Sktlim@umich.eduSwitch::functionalRead(Packet *pkt)
1892683Sktlim@umich.edu{
190217SN/A    // Access the buffers in the switch for performing a functional read
1912862Sktlim@umich.edu    for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) {
1925606Snate@binkert.org        if (m_buffers_to_free[i]->functionalRead(pkt)) {
193223SN/A            return true;
194217SN/A        }
195217SN/A    }
196217SN/A    return false;
197217SN/A}
1982683Sktlim@umich.edu
199217SN/Auint32_t
2002862Sktlim@umich.eduSwitch::functionalWrite(Packet *pkt)
2015606Snate@binkert.org{
202223SN/A    // Access the buffers in the switch for performing a functional write
203217SN/A    uint32_t num_functional_writes = 0;
204217SN/A    for (unsigned int i = 0; i < m_buffers_to_free.size(); ++i) {
2052683Sktlim@umich.edu        num_functional_writes += m_buffers_to_free[i]->functionalWrite(pkt);
2062683Sktlim@umich.edu    }
2072683Sktlim@umich.edu    return num_functional_writes;
2082683Sktlim@umich.edu}
2092683Sktlim@umich.edu
2102683Sktlim@umich.eduSwitch *
2112683Sktlim@umich.eduSwitchParams::create()
2122683Sktlim@umich.edu{
213217SN/A    return new Switch(this);
214217SN/A}
2152683Sktlim@umich.edu