1/* 2 * Copyright (c) 2008 Princeton University 3 * Copyright (c) 2016 Georgia Institute of Technology 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Authors: Niket Agarwal 30 * Tushar Krishna 31 */ 32 33 34#include "mem/ruby/network/garnet2.0/OutputUnit.hh" 35 36#include "base/stl_helpers.hh" 37#include "debug/RubyNetwork.hh" 38#include "mem/ruby/network/garnet2.0/Credit.hh" 39#include "mem/ruby/network/garnet2.0/Router.hh" 40 41using namespace std; 42using m5::stl_helpers::deletePointers; 43 44OutputUnit::OutputUnit(int id, PortDirection direction, Router *router) 45 : Consumer(router) 46{ 47 m_id = id; 48 m_direction = direction; 49 m_router = router; 50 m_num_vcs = m_router->get_num_vcs(); 51 m_vc_per_vnet = m_router->get_vc_per_vnet(); 52 m_out_buffer = new flitBuffer(); 53 54 for (int i = 0; i < m_num_vcs; i++) { 55 m_outvc_state.push_back(new OutVcState(i, m_router->get_net_ptr())); 56 } 57} 58 59OutputUnit::~OutputUnit() 60{ 61 delete m_out_buffer; 62 deletePointers(m_outvc_state); 63} 64 65void 66OutputUnit::decrement_credit(int out_vc) 67{ 68 DPRINTF(RubyNetwork, "Router %d OutputUnit %d decrementing credit for " 69 "outvc %d at time: %lld\n", 70 m_router->get_id(), m_id, out_vc, m_router->curCycle()); 71 72 m_outvc_state[out_vc]->decrement_credit(); 73} 74 75void 76OutputUnit::increment_credit(int out_vc) 77{ 78 DPRINTF(RubyNetwork, "Router %d OutputUnit %d incrementing credit for " 79 "outvc %d at time: %lld\n", 80 m_router->get_id(), m_id, out_vc, m_router->curCycle()); 81 82 m_outvc_state[out_vc]->increment_credit(); 83} 84 85// Check if the output VC (i.e., input VC at next router) 86// has free credits (i..e, buffer slots). 87// This is tracked by OutVcState 88bool 89OutputUnit::has_credit(int out_vc) 90{ 91 assert(m_outvc_state[out_vc]->isInState(ACTIVE_, m_router->curCycle())); 92 return m_outvc_state[out_vc]->has_credit(); 93} 94 95 96// Check if the output port (i.e., input port at next router) has free VCs. 97bool 98OutputUnit::has_free_vc(int vnet) 99{ 100 int vc_base = vnet*m_vc_per_vnet; 101 for (int vc = vc_base; vc < vc_base + m_vc_per_vnet; vc++) { 102 if (is_vc_idle(vc, m_router->curCycle())) 103 return true; 104 } 105 106 return false; 107} 108 109// Assign a free output VC to the winner of Switch Allocation 110int 111OutputUnit::select_free_vc(int vnet) 112{ 113 int vc_base = vnet*m_vc_per_vnet; 114 for (int vc = vc_base; vc < vc_base + m_vc_per_vnet; vc++) { 115 if (is_vc_idle(vc, m_router->curCycle())) { 116 m_outvc_state[vc]->setState(ACTIVE_, m_router->curCycle()); 117 return vc; 118 } 119 } 120 121 return -1; 122} 123 124/* 125 * The wakeup function of the OutputUnit reads the credit signal from the 126 * downstream router for the output VC (i.e., input VC at downstream router). 127 * It increments the credit count in the appropriate output VC state. 128 * If the credit carries is_free_signal as true, 129 * the output VC is marked IDLE. 130 */ 131 132void 133OutputUnit::wakeup() 134{ 135 if (m_credit_link->isReady(m_router->curCycle())) { 136 Credit *t_credit = (Credit*) m_credit_link->consumeLink(); 137 increment_credit(t_credit->get_vc()); 138 139 if (t_credit->is_free_signal()) 140 set_vc_state(IDLE_, t_credit->get_vc(), m_router->curCycle()); 141 142 delete t_credit; 143 } 144} 145 146flitBuffer* 147OutputUnit::getOutQueue() 148{ 149 return m_out_buffer; 150} 151 152void 153OutputUnit::set_out_link(NetworkLink *link) 154{ 155 m_out_link = link; 156} 157 158void 159OutputUnit::set_credit_link(CreditLink *credit_link) 160{ 161 m_credit_link = credit_link; 162} 163 164uint32_t 165OutputUnit::functionalWrite(Packet *pkt) 166{ 167 return m_out_buffer->functionalWrite(pkt); 168} 169