From 7f49fe9feb174d34efc2a011bad79b38522a360b Mon Sep 17 00:00:00 2001 From: Dongdong Li Date: Thu, 8 Aug 2013 00:15:58 -0800 Subject: Intesim2 Integration Details: See Review 80001 https://gpgpu-sim-code-review.appspot.com/80001/ [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 16747] --- src/intersim2/interconnect_interface.cpp | 501 +++++++++++++++++++++++++++++++ 1 file changed, 501 insertions(+) create mode 100644 src/intersim2/interconnect_interface.cpp (limited to 'src/intersim2/interconnect_interface.cpp') diff --git a/src/intersim2/interconnect_interface.cpp b/src/intersim2/interconnect_interface.cpp new file mode 100644 index 0000000..338e82e --- /dev/null +++ b/src/intersim2/interconnect_interface.cpp @@ -0,0 +1,501 @@ +// Copyright (c) 2009-2013, Tor M. Aamodt, Dongdong Li, Ali Bakhoda +// The University of British Columbia +// 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 "interconnect_interface.hpp" +#include "routefunc.hpp" +#include "globals.hpp" +#include "trafficmanager.hpp" +#include "power_module.hpp" +#include "mem_fetch.h" +#include "flit.hpp" +#include "gputrafficmanager.hpp" +#include "booksim.hpp" +#include "intersim_config.hpp" +#include "network.hpp" + +InterconnectInterface::InterconnectInterface(const char* const config_file, unsigned int n_shader, unsigned int n_mem) +:_n_shader(n_shader), _n_mem(n_mem) +{ + if (! config_file ) { + cout << "Interconnect Requires a configfile" << endl; + exit (-1); + } + _icnt_config = new IntersimConfig(); + _icnt_config->ParseFile(config_file); + + InitializeRoutingMap(*_icnt_config); + + gPrintActivity = (_icnt_config->GetInt("print_activity") > 0); + gTrace = (_icnt_config->GetInt("viewer_trace") > 0); + + string watch_out_file = _icnt_config->GetStr( "watch_out" ); + if(watch_out_file == "") { + gWatchOut = NULL; + } else if(watch_out_file == "-") { + gWatchOut = &cout; + } else { + gWatchOut = new ofstream(watch_out_file.c_str()); + } + + _subnets = _icnt_config->GetInt("subnets"); + assert(_subnets); + + /*To include a new network, must register the network here + *add an else if statement with the name of the network + */ + _net.resize(_subnets); + for (int i = 0; i < _subnets; ++i) { + ostringstream name; + name << "network_" << i; + _net[i] = Network::New( *_icnt_config, name.str() ); + } + + assert(_icnt_config->GetStr("sim_type") == "gpgpusim"); + _traffic_manager = static_cast(TrafficManager::New( *_icnt_config, _net )) ; + + _flit_size = _icnt_config->GetInt( "flit_size" ); + + // Config for interface buffers + if (_icnt_config->GetInt("ejection_buffer_size")) { + _ejection_buffer_capacity = _icnt_config->GetInt( "ejection_buffer_size" ) ; + } else { + _ejection_buffer_capacity = _icnt_config->GetInt( "vc_buf_size" ); + } + + _boundary_buffer_capacity = _icnt_config->GetInt( "boundary_buffer_size" ) ; + assert(_boundary_buffer_capacity); + if (_icnt_config->GetInt("input_buffer_size")) { + _input_buffer_capacity = _icnt_config->GetInt("input_buffer_size"); + } else { + _input_buffer_capacity = 9; + } + _vcs = _icnt_config->GetInt("num_vcs"); + + _CreateBuffer(); + _CreateNodeMap(_n_shader, _n_mem, _traffic_manager->_nodes, _icnt_config->GetInt("use_map")); + +} + +InterconnectInterface::~InterconnectInterface() +{ + for (int i=0; i<_subnets; ++i) { + ///Power analysis + if(_icnt_config->GetInt("sim_power") > 0){ + Power_Module pnet(_net[i], *_icnt_config); + pnet.run(); + } + delete _net[i]; + } + + delete _traffic_manager; + _traffic_manager = NULL; + delete _icnt_config; +} + +void InterconnectInterface::Init() +{ + _traffic_manager->Init(); + // TODO: Should we init _round_robin_turn? + // _boundary_buffer, _ejection_buffer and _ejected_flit_queue should be cleared +} + +void InterconnectInterface::Push(unsigned input_deviceID, unsigned output_deviceID, void *data, unsigned int size) +{ + int output_icntID = _node_map[output_deviceID]; + int input_icntID = _node_map[input_deviceID]; + +#if 0 + cout<<"Call interconnect push input: "<(data); + + switch (mf->get_type()) { + case READ_REQUEST: packet_type = Flit::READ_REQUEST ;break; + case WRITE_REQUEST: packet_type = Flit::WRITE_REQUEST ;break; + case READ_REPLY: packet_type = Flit::READ_REPLY ;break; + case WRITE_ACK: packet_type = Flit::WRITE_REPLY ;break; + default: assert (0); + } + + //TODO: _include_queuing ? + _traffic_manager->_GeneratePacket( input_icntID, -1, 0 /*class*/, _traffic_manager->_time, subnet, n_flits, packet_type, data, output_icntID); + +#if DOUB + cout <<"Traffic[" << subnet << "] (mapped) sending form "<< input_icntID << " to " << output_icntID << endl; +#endif +// } +} + +void* InterconnectInterface::Pop(unsigned deviceID) +{ + int icntID = _node_map[deviceID]; +#if DEBUG + cout<<"Call interconnect POP " << output<_Step(); +} + +bool InterconnectInterface::Busy() const +{ + bool busy = !_traffic_manager->_measured_in_flight_flits[0].empty(); + if (!busy) { + for (int s = 0; s < _subnets; ++s) { + for (int n = 0; n < _n_shader+_n_mem; ++n) { + //FIXME: if this cannot make sure _partial_packets is empty + assert(_traffic_manager->_input_queue[s][n][0].empty()); + } + } + } + else + return true; + for (int s = 0; s < _subnets; ++s) { + for (int n=0; n < (_n_shader+_n_mem); ++n) { + for (int vc=0; vc<_vcs; ++vc) { + if (_boundary_buffer[s][n][vc].HasPacket() ) { + return true; + } + } + } + } + return false; +} + +bool InterconnectInterface::HasBuffer(unsigned deviceID, unsigned int size) const +{ + bool has_buffer = false; + unsigned int n_flits = size / _flit_size + ((size % _flit_size)? 1:0); + int icntID = _node_map.find(deviceID)->second; + + has_buffer = _traffic_manager->_input_queue[0][icntID][0].size() +n_flits <= _input_buffer_capacity; + + if ((_subnets>1) && int(deviceID) >= _n_shader) // deviceID is memory node + has_buffer = _traffic_manager->_input_queue[1][icntID][0].size() +n_flits <= _input_buffer_capacity; + + return has_buffer; +} + +void InterconnectInterface::DisplayStats() const +{ + _traffic_manager->UpdateStats(); + _traffic_manager->DisplayStats(); +} + +unsigned InterconnectInterface::GetFlitSize() const +{ + return _flit_size; +} + +void InterconnectInterface::DisplayOverallStats() const +{ + // hack: booksim2 use _drain_time and calculate delta time based on it, but we don't, change this if you have a better idea + _traffic_manager->_drain_time = _traffic_manager->_time; + // hack: also _total_sims equals to number of kernel calls + _traffic_manager->_total_sims += 1; + + _traffic_manager->_UpdateOverallStats(); + _traffic_manager->DisplayOverallStats(); + if(_traffic_manager->_print_csv_results) { + _traffic_manager->DisplayOverallStatsCSV(); + } +} + +void InterconnectInterface::DisplayState(FILE *fp) const +{ + fprintf(fp, "GPGPU-Sim uArch: ICNT:Display State: Under implementation\n"); +// fprintf(fp,"GPGPU-Sim uArch: interconnect busy state\n"); + +// for (unsigned i=0; i_measured_in_flight) +// fprintf(fp," Network %u has %u _measured_in_flight\n", i, traffic[i]->_measured_in_flight ); +// } +// +// for (unsigned i=0 ;i<(_n_shader+_n_mem);i++ ) { +// if( !traffic[0]->_partial_packets[i] [0].empty() ) +// fprintf(fp," Network 0 has nonempty _partial_packets[%u][0]\n", i); +// if ( doub_net && !traffic[1]->_partial_packets[i] [0].empty() ) +// fprintf(fp," Network 1 has nonempty _partial_packets[%u][0]\n", i); +// for (unsigned j=0;jdata, flit->tail); + + _ejected_flit_queue[subnet][output].push(flit); //indicate this flit is already popped from ejection buffer and ready for credit return + + if ( flit->head ) { + assert (flit->dest == output); + } + } + } +} + +void InterconnectInterface::WriteOutBuffer(int subnet, int output_icntID, Flit* flit ) +{ + int vc = flit->vc; + assert (_ejection_buffer[subnet][output_icntID][vc].size() < _ejection_buffer_capacity); + _ejection_buffer[subnet][output_icntID][vc].push(flit); +} + +int InterconnectInterface::GetIcntTime() const +{ + return _traffic_manager->getTime(); +} + +Stats* InterconnectInterface::GetIcntStats(const string &name) const +{ + return _traffic_manager->getStats(name); +} + +Flit* InterconnectInterface::GetEjectedFlit(int subnet, int node) +{ + Flit* flit = NULL; + if (!_ejected_flit_queue[subnet][node].empty()) { + flit = _ejected_flit_queue[subnet][node].front(); + _ejected_flit_queue[subnet][node].pop(); + } + return flit; +} + +void InterconnectInterface::_CreateBuffer() +{ + int nodes = _n_shader + _n_mem; + + _boundary_buffer.resize(_subnets); + _ejection_buffer.resize(_subnets); + _round_robin_turn.resize(_subnets); + _ejected_flit_queue.resize(_subnets); + + for (int subnet = 0; subnet < _subnets; ++subnet) { + _ejection_buffer[subnet].resize(nodes); + _boundary_buffer[subnet].resize(nodes); + _round_robin_turn[subnet].resize(nodes); + _ejected_flit_queue[subnet].resize(nodes); + + for (int node=0;node > preset_memory_map; + + // good for 8 shaders and 8 memory cores + { + int memory_node[] = {1, 3, 4, 6, 9, 11, 12, 14}; + preset_memory_map[16] = vector(memory_node, memory_node+8); + } + + // good for 28 shaders and 8 memory cores + { + int memory_node[] = {3, 7, 10, 12, 23, 25, 28, 32}; + preset_memory_map[36] = vector(memory_node, memory_node+8); + } + + // good for 56 shaders and 8 memory cores + { + int memory_node[] = {3, 15, 17, 29, 36, 47, 49, 61}; + preset_memory_map[64] = vector(memory_node, memory_node+sizeof(memory_node)/sizeof(int)); + } + + // good for 110 shaders and 11 memory cores + { + int memory_node[] = {12, 20, 25, 28, 57, 60, 63, 92, 95,100,108}; + preset_memory_map[121] = vector(memory_node, memory_node+sizeof(memory_node)/sizeof(int)); + } + + const vector &memory_node = preset_memory_map[n_node]; + if (memory_node.empty()) { + cerr<<"ERROR!!! NO MAPPING IMPLEMENTED YET FOR THIS CONFIG"<