Throttle.cc revision 6154
1955SN/A 2955SN/A/* 311408Sandreas.sandberg@arm.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 49812Sandreas.hansson@arm.com * All rights reserved. 59812Sandreas.hansson@arm.com * 69812Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 79812Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 89812Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 99812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 109812Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 119812Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 129812Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 139812Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 149812Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 157816Ssteve.reinhardt@amd.com * this software without specific prior written permission. 165871Snate@binkert.org * 171762SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28955SN/A */ 29955SN/A 30955SN/A/* 31955SN/A * $Id$ 32955SN/A * 33955SN/A * Description: see Throttle.h 34955SN/A * 35955SN/A */ 36955SN/A 37955SN/A#include "mem/ruby/network/simple/Throttle.hh" 38955SN/A#include "mem/ruby/buffers/MessageBuffer.hh" 39955SN/A#include "mem/ruby/network/Network.hh" 40955SN/A#include "mem/ruby/system/System.hh" 41955SN/A#include "mem/ruby/slicc_interface/NetworkMessage.hh" 422665Ssaidi@eecs.umich.edu#include "mem/protocol/Protocol.hh" 432665Ssaidi@eecs.umich.edu 445863Snate@binkert.orgconst int HIGH_RANGE = 256; 45955SN/Aconst int ADJUST_INTERVAL = 50000; 46955SN/Aconst int MESSAGE_SIZE_MULTIPLIER = 1000; 47955SN/A//const int BROADCAST_SCALING = 4; // Have a 16p system act like a 64p systems 48955SN/Aconst int BROADCAST_SCALING = 1; 49955SN/Aconst int PRIORITY_SWITCH_LIMIT = 128; 508878Ssteve.reinhardt@amd.com 512632Sstever@eecs.umich.edustatic int network_message_to_size(NetworkMessage* net_msg_ptr); 528878Ssteve.reinhardt@amd.com 532632Sstever@eecs.umich.eduextern std::ostream * debug_cout_ptr; 54955SN/A 558878Ssteve.reinhardt@amd.comThrottle::Throttle(int sID, NodeID node, int link_latency, int link_bandwidth_multiplier) 562632Sstever@eecs.umich.edu{ 572761Sstever@eecs.umich.edu init(node, link_latency, link_bandwidth_multiplier); 582632Sstever@eecs.umich.edu m_sID = sID; 592632Sstever@eecs.umich.edu} 602632Sstever@eecs.umich.edu 612761Sstever@eecs.umich.eduThrottle::Throttle(NodeID node, int link_latency, int link_bandwidth_multiplier) 622761Sstever@eecs.umich.edu{ 632761Sstever@eecs.umich.edu init(node, link_latency, link_bandwidth_multiplier); 648878Ssteve.reinhardt@amd.com m_sID = 0; 658878Ssteve.reinhardt@amd.com} 662761Sstever@eecs.umich.edu 672761Sstever@eecs.umich.eduvoid Throttle::init(NodeID node, int link_latency, int link_bandwidth_multiplier) 682761Sstever@eecs.umich.edu{ 692761Sstever@eecs.umich.edu m_node = node; 702761Sstever@eecs.umich.edu m_vnets = 0; 718878Ssteve.reinhardt@amd.com 728878Ssteve.reinhardt@amd.com ASSERT(link_bandwidth_multiplier > 0); 732632Sstever@eecs.umich.edu m_link_bandwidth_multiplier = link_bandwidth_multiplier; 742632Sstever@eecs.umich.edu m_link_latency = link_latency; 758878Ssteve.reinhardt@amd.com 768878Ssteve.reinhardt@amd.com m_bash_counter = HIGH_RANGE; 772632Sstever@eecs.umich.edu m_bandwidth_since_sample = 0; 78955SN/A m_last_bandwidth_sample = 0; 79955SN/A m_wakeups_wo_switch = 0; 80955SN/A clearStats(); 815863Snate@binkert.org} 825863Snate@binkert.org 835863Snate@binkert.orgvoid Throttle::clear() 845863Snate@binkert.org{ 855863Snate@binkert.org for (int counter = 0; counter < m_vnets; counter++) { 865863Snate@binkert.org m_in[counter]->clear(); 875863Snate@binkert.org m_out[counter]->clear(); 885863Snate@binkert.org } 895863Snate@binkert.org} 905863Snate@binkert.org 915863Snate@binkert.orgvoid Throttle::addLinks(const Vector<MessageBuffer*>& in_vec, const Vector<MessageBuffer*>& out_vec) 928878Ssteve.reinhardt@amd.com{ 935863Snate@binkert.org assert(in_vec.size() == out_vec.size()); 945863Snate@binkert.org for (int i=0; i<in_vec.size(); i++) { 955863Snate@binkert.org addVirtualNetwork(in_vec[i], out_vec[i]); 969812Sandreas.hansson@arm.com } 979812Sandreas.hansson@arm.com 985863Snate@binkert.org m_message_counters.setSize(MessageSizeType_NUM); 999812Sandreas.hansson@arm.com for (int i=0; i<MessageSizeType_NUM; i++) { 1005863Snate@binkert.org m_message_counters[i].setSize(in_vec.size()); 1015863Snate@binkert.org for (int j=0; j<m_message_counters[i].size(); j++) { 1025863Snate@binkert.org m_message_counters[i][j] = 0; 1039812Sandreas.hansson@arm.com } 1049812Sandreas.hansson@arm.com } 1055863Snate@binkert.org 1065863Snate@binkert.org if (g_PRINT_TOPOLOGY) { 1078878Ssteve.reinhardt@amd.com m_out_link_vec.insertAtBottom(out_vec); 1085863Snate@binkert.org } 1095863Snate@binkert.org} 1105863Snate@binkert.org 1116654Snate@binkert.orgvoid Throttle::addVirtualNetwork(MessageBuffer* in_ptr, MessageBuffer* out_ptr) 11210196SCurtis.Dunham@arm.com{ 113955SN/A m_units_remaining.insertAtBottom(0); 1145396Ssaidi@eecs.umich.edu m_in.insertAtBottom(in_ptr); 11511401Sandreas.sandberg@arm.com m_out.insertAtBottom(out_ptr); 1165863Snate@binkert.org 1175863Snate@binkert.org // Set consumer and description 1184202Sbinkertn@umich.edu m_in[m_vnets]->setConsumer(this); 1195863Snate@binkert.org string desc = "[Queue to Throttle " + NodeIDToString(m_sID) + " " + NodeIDToString(m_node) + "]"; 1205863Snate@binkert.org m_in[m_vnets]->setDescription(desc); 1215863Snate@binkert.org m_vnets++; 1225863Snate@binkert.org} 123955SN/A 1246654Snate@binkert.orgvoid Throttle::wakeup() 1255273Sstever@gmail.com{ 1265871Snate@binkert.org // Limits the number of message sent to a limited number of bytes/cycle. 1275273Sstever@gmail.com assert(getLinkBandwidth() > 0); 1286655Snate@binkert.org int bw_remaining = getLinkBandwidth(); 1298878Ssteve.reinhardt@amd.com 1306655Snate@binkert.org // Give the highest numbered link priority most of the time 1316655Snate@binkert.org m_wakeups_wo_switch++; 1329219Spower.jg@gmail.com int highest_prio_vnet = m_vnets-1; 1336655Snate@binkert.org int lowest_prio_vnet = 0; 1345871Snate@binkert.org int counter = 1; 1356654Snate@binkert.org bool schedule_wakeup = false; 1368947Sandreas.hansson@arm.com 1375396Ssaidi@eecs.umich.edu // invert priorities to avoid starvation seen in the component network 1388120Sgblack@eecs.umich.edu if (m_wakeups_wo_switch > PRIORITY_SWITCH_LIMIT) { 1398120Sgblack@eecs.umich.edu m_wakeups_wo_switch = 0; 1408120Sgblack@eecs.umich.edu highest_prio_vnet = 0; 1418120Sgblack@eecs.umich.edu lowest_prio_vnet = m_vnets-1; 1428120Sgblack@eecs.umich.edu counter = -1; 1438120Sgblack@eecs.umich.edu } 1448120Sgblack@eecs.umich.edu 1458120Sgblack@eecs.umich.edu for (int vnet = highest_prio_vnet; (vnet*counter) >= (counter*lowest_prio_vnet); vnet -= counter) { 1468879Ssteve.reinhardt@amd.com 1478879Ssteve.reinhardt@amd.com assert(m_out[vnet] != NULL); 1488879Ssteve.reinhardt@amd.com assert(m_in[vnet] != NULL); 1498879Ssteve.reinhardt@amd.com assert(m_units_remaining[vnet] >= 0); 1508879Ssteve.reinhardt@amd.com 1518879Ssteve.reinhardt@amd.com while ((bw_remaining > 0) && ((m_in[vnet]->isReady()) || (m_units_remaining[vnet] > 0)) && m_out[vnet]->areNSlotsAvailable(1)) { 1528879Ssteve.reinhardt@amd.com 1538879Ssteve.reinhardt@amd.com // See if we are done transferring the previous message on this virtual network 1548879Ssteve.reinhardt@amd.com if (m_units_remaining[vnet] == 0 && m_in[vnet]->isReady()) { 1558879Ssteve.reinhardt@amd.com 1568879Ssteve.reinhardt@amd.com // Find the size of the message we are moving 1578879Ssteve.reinhardt@amd.com MsgPtr msg_ptr = m_in[vnet]->peekMsgPtr(); 1588879Ssteve.reinhardt@amd.com NetworkMessage* net_msg_ptr = dynamic_cast<NetworkMessage*>(msg_ptr.ref()); 1598120Sgblack@eecs.umich.edu m_units_remaining[vnet] += network_message_to_size(net_msg_ptr); 1608120Sgblack@eecs.umich.edu 1618120Sgblack@eecs.umich.edu DEBUG_NEWLINE(NETWORK_COMP,HighPrio); 1628120Sgblack@eecs.umich.edu DEBUG_MSG(NETWORK_COMP,HighPrio,"throttle: " + int_to_string(m_node) 1638120Sgblack@eecs.umich.edu + " my bw " + int_to_string(getLinkBandwidth()) 1648120Sgblack@eecs.umich.edu + " bw spent enqueueing net msg " + int_to_string(m_units_remaining[vnet]) 1658120Sgblack@eecs.umich.edu + " time: " + int_to_string(g_eventQueue_ptr->getTime()) + "."); 1668120Sgblack@eecs.umich.edu 1678120Sgblack@eecs.umich.edu // Move the message 1688120Sgblack@eecs.umich.edu m_out[vnet]->enqueue(m_in[vnet]->peekMsgPtr(), m_link_latency); 1698120Sgblack@eecs.umich.edu m_in[vnet]->pop(); 1708120Sgblack@eecs.umich.edu 1718120Sgblack@eecs.umich.edu // Count the message 1728120Sgblack@eecs.umich.edu m_message_counters[net_msg_ptr->getMessageSize()][vnet]++; 1738879Ssteve.reinhardt@amd.com 1748879Ssteve.reinhardt@amd.com DEBUG_MSG(NETWORK_COMP,LowPrio,*m_out[vnet]); 1758879Ssteve.reinhardt@amd.com DEBUG_NEWLINE(NETWORK_COMP,HighPrio); 1768879Ssteve.reinhardt@amd.com } 17710458Sandreas.hansson@arm.com 17810458Sandreas.hansson@arm.com // Calculate the amount of bandwidth we spent on this message 17910458Sandreas.hansson@arm.com int diff = m_units_remaining[vnet] - bw_remaining; 1808879Ssteve.reinhardt@amd.com m_units_remaining[vnet] = max(0, diff); 1818879Ssteve.reinhardt@amd.com bw_remaining = max(0, -diff); 1828879Ssteve.reinhardt@amd.com } 1838879Ssteve.reinhardt@amd.com 1849227Sandreas.hansson@arm.com if ((bw_remaining > 0) && ((m_in[vnet]->isReady()) || (m_units_remaining[vnet] > 0)) && !m_out[vnet]->areNSlotsAvailable(1)) { 1859227Sandreas.hansson@arm.com DEBUG_MSG(NETWORK_COMP,LowPrio,vnet); 1868879Ssteve.reinhardt@amd.com schedule_wakeup = true; // schedule me to wakeup again because I'm waiting for my output queue to become available 1878879Ssteve.reinhardt@amd.com } 1888879Ssteve.reinhardt@amd.com } 1898879Ssteve.reinhardt@amd.com 19010453SAndrew.Bardsley@arm.com // We should only wake up when we use the bandwidth 19110453SAndrew.Bardsley@arm.com // assert(bw_remaining != getLinkBandwidth()); // This is only mostly true 19210453SAndrew.Bardsley@arm.com 19310456SCurtis.Dunham@arm.com // Record that we used some or all of the link bandwidth this cycle 19410456SCurtis.Dunham@arm.com double ratio = 1.0-(double(bw_remaining)/double(getLinkBandwidth())); 19510456SCurtis.Dunham@arm.com // If ratio = 0, we used no bandwidth, if ratio = 1, we used all 19610457Sandreas.hansson@arm.com linkUtilized(ratio); 19710457Sandreas.hansson@arm.com 19811342Sandreas.hansson@arm.com // Sample the link bandwidth utilization over a number of cycles 19911342Sandreas.hansson@arm.com int bw_used = getLinkBandwidth()-bw_remaining; 2008120Sgblack@eecs.umich.edu m_bandwidth_since_sample += bw_used; 2018947Sandreas.hansson@arm.com 2027816Ssteve.reinhardt@amd.com // FIXME - comment out the bash specific code for faster performance 2035871Snate@binkert.org // Start Bash code 2045871Snate@binkert.org // Update the predictor 2056121Snate@binkert.org Time current_time = g_eventQueue_ptr->getTime(); 2065871Snate@binkert.org while ((current_time - m_last_bandwidth_sample) > ADJUST_INTERVAL) { 2075871Snate@binkert.org double utilization = m_bandwidth_since_sample/double(ADJUST_INTERVAL * getLinkBandwidth()); 2089926Sstan.czerniawski@arm.com 2099926Sstan.czerniawski@arm.com if (utilization > g_bash_bandwidth_adaptive_threshold) { 2109119Sandreas.hansson@arm.com // Used more bandwidth 21110068Sandreas.hansson@arm.com m_bash_counter++; 21210068Sandreas.hansson@arm.com } else { 213955SN/A // Used less bandwidth 2149416SAndreas.Sandberg@ARM.com m_bash_counter--; 21511342Sandreas.hansson@arm.com } 21611212Sjoseph.gross@amd.com 21711212Sjoseph.gross@amd.com // Make sure we don't overflow 21811212Sjoseph.gross@amd.com m_bash_counter = min(HIGH_RANGE, m_bash_counter); 21911212Sjoseph.gross@amd.com m_bash_counter = max(0, m_bash_counter); 22011212Sjoseph.gross@amd.com 2219416SAndreas.Sandberg@ARM.com // Reset samples 2229416SAndreas.Sandberg@ARM.com m_last_bandwidth_sample += ADJUST_INTERVAL; 2235871Snate@binkert.org m_bandwidth_since_sample = 0; 22410584Sandreas.hansson@arm.com } 2259416SAndreas.Sandberg@ARM.com // End Bash code 2269416SAndreas.Sandberg@ARM.com 2275871Snate@binkert.org if ((bw_remaining > 0) && !schedule_wakeup) { 228955SN/A // We have extra bandwidth and our output buffer was available, so we must not have anything else to do until another message arrives. 22910671Sandreas.hansson@arm.com DEBUG_MSG(NETWORK_COMP,LowPrio,*this); 23010671Sandreas.hansson@arm.com DEBUG_MSG(NETWORK_COMP,LowPrio,"not scheduled again"); 23110671Sandreas.hansson@arm.com } else { 23210671Sandreas.hansson@arm.com DEBUG_MSG(NETWORK_COMP,LowPrio,*this); 2338881Smarc.orr@gmail.com DEBUG_MSG(NETWORK_COMP,LowPrio,"scheduled again"); 2346121Snate@binkert.org // We are out of bandwidth for this cycle, so wakeup next cycle and continue 2356121Snate@binkert.org g_eventQueue_ptr->scheduleEvent(this, 1); 2361533SN/A } 2379239Sandreas.hansson@arm.com} 2389239Sandreas.hansson@arm.com 2399239Sandreas.hansson@arm.combool Throttle::broadcastBandwidthAvailable(int rand) const 2409239Sandreas.hansson@arm.com{ 2419239Sandreas.hansson@arm.com bool result = !(m_bash_counter > ((HIGH_RANGE/4) + (rand % (HIGH_RANGE/2)))); 2429239Sandreas.hansson@arm.com return result; 2439239Sandreas.hansson@arm.com} 2449239Sandreas.hansson@arm.com 2459239Sandreas.hansson@arm.comvoid Throttle::printStats(ostream& out) const 2469239Sandreas.hansson@arm.com{ 2479239Sandreas.hansson@arm.com out << "utilized_percent: " << getUtilization() << endl; 2489239Sandreas.hansson@arm.com} 2496655Snate@binkert.org 2506655Snate@binkert.orgvoid Throttle::clearStats() 2516655Snate@binkert.org{ 2526655Snate@binkert.org m_ruby_start = g_eventQueue_ptr->getTime(); 2535871Snate@binkert.org m_links_utilized = 0.0; 2545871Snate@binkert.org 2555863Snate@binkert.org for (int i=0; i<m_message_counters.size(); i++) { 2565871Snate@binkert.org for (int j=0; j<m_message_counters[i].size(); j++) { 2578878Ssteve.reinhardt@amd.com m_message_counters[i][j] = 0; 2585871Snate@binkert.org } 2595871Snate@binkert.org } 2605871Snate@binkert.org} 2615863Snate@binkert.org 2626121Snate@binkert.orgvoid Throttle::printConfig(ostream& out) const 2635863Snate@binkert.org{ 26411408Sandreas.sandberg@arm.com 26511408Sandreas.sandberg@arm.com} 2668336Ssteve.reinhardt@amd.com 26711469SCurtis.Dunham@arm.comdouble Throttle::getUtilization() const 26811469SCurtis.Dunham@arm.com{ 2698336Ssteve.reinhardt@amd.com return (100.0 * double(m_links_utilized)) / (double(g_eventQueue_ptr->getTime()-m_ruby_start)); 2704678Snate@binkert.org} 27111887Sandreas.sandberg@arm.com 27211887Sandreas.sandberg@arm.comvoid Throttle::print(ostream& out) const 27311887Sandreas.sandberg@arm.com{ 27411887Sandreas.sandberg@arm.com out << "[Throttle: " << m_sID << " " << m_node << " bw: " << getLinkBandwidth() << "]"; 27511887Sandreas.sandberg@arm.com} 27611887Sandreas.sandberg@arm.com 27711887Sandreas.sandberg@arm.com// Helper function 27811887Sandreas.sandberg@arm.com 27911887Sandreas.sandberg@arm.comstatic 28011887Sandreas.sandberg@arm.comint network_message_to_size(NetworkMessage* net_msg_ptr) 28111887Sandreas.sandberg@arm.com{ 28211408Sandreas.sandberg@arm.com assert(net_msg_ptr != NULL); 28311401Sandreas.sandberg@arm.com 28411401Sandreas.sandberg@arm.com // Artificially increase the size of broadcast messages 28511401Sandreas.sandberg@arm.com if (BROADCAST_SCALING > 1) { 28611401Sandreas.sandberg@arm.com if (net_msg_ptr->getDestination().isBroadcast()) { 28711401Sandreas.sandberg@arm.com return (MessageSizeType_to_int(net_msg_ptr->getMessageSize()) * MESSAGE_SIZE_MULTIPLIER * BROADCAST_SCALING); 28811401Sandreas.sandberg@arm.com } 2898336Ssteve.reinhardt@amd.com } 2908336Ssteve.reinhardt@amd.com return (MessageSizeType_to_int(net_msg_ptr->getMessageSize()) * MESSAGE_SIZE_MULTIPLIER); 2918336Ssteve.reinhardt@amd.com} 2924678Snate@binkert.org