// Copyright (c) 2019, Mahmoud Khairy // Purdue University // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // Redistributions in binary form must reproduce the above copyright notice, this // list of conditions and the following disclaimer in the documentation and/or // other materials provided with the distribution. // Neither the name of The University of British Columbia nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include #include #include #include #include #include "local_interconnect.h" #include "mem_fetch.h" xbar_router::xbar_router(unsigned router_id, enum Interconnect_type m_type, unsigned n_shader, unsigned n_mem, unsigned m_in_buffer_limit, unsigned m_out_buffer_limit, enum Arbiteration_type m_arbit_type) { m_id=router_id; router_type=m_type; _n_mem = n_mem; _n_shader = n_shader; total_nodes = n_shader+n_mem; in_buffers.resize(total_nodes); out_buffers.resize(total_nodes); next_node.resize(total_nodes,0); in_buffer_limit = m_in_buffer_limit; out_buffer_limit = m_out_buffer_limit; arbit_type = m_arbit_type; next_node_id=0; if(m_type == REQ_NET) { active_in_buffers=n_shader; active_out_buffers=n_mem; } else if(m_type == REPLY_NET) { active_in_buffers=n_mem; active_out_buffers=n_shader; } cycles = 0; conflicts= 0; out_buffer_full=0; in_buffer_full=0; out_buffer_util=0; in_buffer_util=0; packets_num=0; } xbar_router::~xbar_router() { } void xbar_router::Push(unsigned input_deviceID, unsigned output_deviceID, void* data, unsigned int size) { assert(input_deviceID < total_nodes); in_buffers[input_deviceID].push(Packet(data, output_deviceID)); packets_num++; } void* xbar_router::Pop(unsigned ouput_deviceID) { assert(ouput_deviceID < total_nodes); void* data = NULL; if(!out_buffers[ouput_deviceID].empty()) { data = out_buffers[ouput_deviceID].front().data; out_buffers[ouput_deviceID].pop(); } return data; } bool xbar_router::Has_Buffer_In(unsigned input_deviceID, unsigned size, bool update_counter){ assert(input_deviceID < total_nodes); bool has_buffer = (in_buffers[input_deviceID].size() + size <= in_buffer_limit); if(update_counter && !has_buffer) in_buffer_full++; return has_buffer; } bool xbar_router::Has_Buffer_Out(unsigned output_deviceID, unsigned size){ return (out_buffers[output_deviceID].size() + size <= out_buffer_limit); } void xbar_router::Advance() { if(arbit_type == NAIVE_RR) RR_Advance(); else if(arbit_type == iSLIP) iSLIP_Advance(); else assert(0); } void xbar_router::RR_Advance() { cycles++; vector issued(total_nodes, false); for(unsigned i=0; i node_tmp; //calcaulte how many conflicts are there for stats for (unsigned i=0; i(i), m_n_shader, m_n_mem, m_inct_config.in_buffer_limit, m_inct_config.out_buffer_limit,m_inct_config.arbiter_algo); } } void LocalInterconnect::Init() { //empty //there is nothing to do } void LocalInterconnect::Push(unsigned input_deviceID, unsigned output_deviceID, void* data, unsigned int size){ unsigned subnet; if (n_subnets == 1) { subnet = 0; } else { if (input_deviceID < n_shader ) { subnet = 0; } else { subnet = 1; } } // it should have free buffer //assume all the packets have size of one //no flits are implemented assert(net[subnet]->Has_Buffer_In(input_deviceID, 1)); net[subnet]->Push(input_deviceID, output_deviceID, data, size); } void* LocalInterconnect::Pop(unsigned ouput_deviceID){ // 0-_n_shader-1 indicates reply(network 1), otherwise request(network 0) int subnet = 0; if (ouput_deviceID < n_shader) subnet = 1; return net[subnet]->Pop(ouput_deviceID); } void LocalInterconnect::Advance(){ for (unsigned i = 0; i < n_subnets; ++i) { net[i]->Advance(); } } bool LocalInterconnect::Busy() const{ for (unsigned i = 0; i < n_subnets; ++i) { if(net[i]->Busy()) return true; } return false; } bool LocalInterconnect::HasBuffer(unsigned deviceID, unsigned int size) const{ bool has_buffer = false; if ((n_subnets>1) && deviceID >= n_shader) // deviceID is memory node has_buffer = net[REPLY_NET]->Has_Buffer_In(deviceID, 1, true); else has_buffer = net[REQ_NET]->Has_Buffer_In(deviceID, 1, true); return has_buffer; } void LocalInterconnect::DisplayStats() const{ cout<<"Req_Network_injected_packets_num = "<packets_num<