diff options
Diffstat (limited to 'src/intersim/interconnect_interface.cpp')
| -rw-r--r-- | src/intersim/interconnect_interface.cpp | 574 |
1 files changed, 574 insertions, 0 deletions
diff --git a/src/intersim/interconnect_interface.cpp b/src/intersim/interconnect_interface.cpp new file mode 100644 index 0000000..bb30f81 --- /dev/null +++ b/src/intersim/interconnect_interface.cpp @@ -0,0 +1,574 @@ +#include "booksim.hpp" +#include <string> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <queue> + +#include "routefunc.hpp" +#include "traffic.hpp" +#include "booksim_config.hpp" +#include "trafficmanager.hpp" +#include "random_utils.hpp" +#include "network.hpp" +#include "singlenet.hpp" +#include "kncube.hpp" +#include "fly.hpp" +#include "injection.hpp" +#include "interconnect_interface.h" +#include "../gpgpu-sim/mem_fetch.h" +#include <string.h> + +extern unsigned long long gpu_sim_cycle; +int _flit_size ; +extern unsigned int warp_size; + +bool doub_net = false; //double networks disabled by default + +BookSimConfig icnt_config; +TrafficManager** traffic; +unsigned int g_num_vcs; //number of virtual channels +queue<Flit *> ** ejection_buf; +vector<int> round_robin_turn; //keep track of boundary_buf last used in icnt_pop +unsigned int ejection_buffer_capacity ; +unsigned int boundary_buf_capacity ; + +unsigned int input_buffer_capacity ; + +class boundary_buf{ +private: + queue<void *> buf; + queue<bool> tail_flag; + int packet_n; + unsigned capacity; +public: + boundary_buf(){ + capacity = boundary_buf_capacity; //maximum flits the buffer can hold + packet_n=0; + } + bool is_full(void){ + return (buf.size()>=capacity); + } + bool has_packet() { + return (packet_n); + } + void * pop_packet(){ + assert (packet_n); + void * data = NULL; + void * temp_d = buf.front(); + while (data==NULL) { + if (tail_flag.front()) { + data = buf.front(); + packet_n--; + } + assert(temp_d == buf.front()); //all flits must belong to the same packet + buf.pop(); + tail_flag.pop(); + } + return data; + } + void push_flit_data(void* data,bool is_tail) { + buf.push(data); + tail_flag.push(is_tail); + if (is_tail) { + packet_n++; + } + } +}; + +boundary_buf** clock_boundary_buf; + +class mycomparison { +public: + bool operator() (const void* lhs, const void* rhs) const + { + return( ((mem_fetch_t *)lhs)->icnt_receive_time > ((mem_fetch_t *) rhs)->icnt_receive_time); + } +}; + +bool perfect_icnt = 0; +int fixed_lat_icnt = 0; + +priority_queue<void * , vector<void* >, mycomparison> * out_buf_fixedlat_buf; + + +//perfect icnt stats: +unsigned int* max_fixedlat_buf_size; + +static unsigned int net_c; //number of inetrconnection networks + +static unsigned int _n_shader = 0; +static unsigned int _n_mem = 0; + +static int * node_map; //deviceID to mesh location map + //deviceID : Starts from 0 for shaders and then continues until mem nodes + // which starts at location n_shader and then continues to n_shader+n_mem (last device) +static int * reverse_map; + +void map_gen(int dim,int memcount, int memnodes[]) +{ + int k = 0; + int i=0 ; + int j=0 ; + int memfound=0; + for (i = 0; i < dim*dim ; i++) { + memfound=0; + for (j = 0; j<memcount ; j++) { + if (memnodes[j]==i) { + memfound=1; + } + } + if (!memfound) { + node_map[k]=i; + k++; + } + } + for (int j = 0; j<memcount ; j++) { + node_map[k]=memnodes[j]; + k++; + } + assert(k==dim*dim); +} + +void display_map(int dim,int count){ + int i=0; + for (i=0;i<count;i++) { + printf("%d ",node_map[i]); + if (i%dim ==0) { + printf("\n"); + } + } +} + +void create_node_map(int n_shader, int n_mem, int size, int use_map) { + node_map = (int*)malloc((size)*sizeof(int)); + if (use_map) { + switch (size) { + case 16 : + { // good for 8 shaders and 8 memory cores + int newmap[] = { + 0, 2, 5, 7, + 8,10,13,15, + 1, 3, 4, 6, //memory nodes + 9,11,12,14 //memory nodes + }; + memcpy (node_map, newmap,16*sizeof(int)); + break; + } + case 64: + { // good for 56 shaders and 8 memory cores + int newmap[] = { + 0, 1, 2, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 16, 18, + 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 30, 31, 32, 33, 34, 35, + 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 48, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 62, 63, + 3, 15, 17, 29, 36, 47, 49, 61 //memory nodes are in this line + }; + memcpy (node_map, newmap,64*sizeof(int)); + break; + } + case 121: + { // good for 110 shaders and 11 memory cores + int newmap[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, + 24, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 58, 59, + 61, 62, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 93, 94, 96, + 97, 98, 99,101,102,103,104,105,106,107,109, + 110,111,112,113,114,115,116,117,118,119,120, + 12, 20, 25, 28, 57, 60, 63, 92, 95,100,108 //memory nodes are in this line + }; + memcpy (node_map, newmap,121*sizeof(int)); + break; + } + case 36: + { + int memnodes[8]={3,7,10,12,23,25,28,32}; + map_gen(6/*dim*/,8/*memcount*/,memnodes); + break; + } + default: + { + cout<<"WARNING !!! NO MAPPING IMPLEMENTED YET FOR THIS CONFIG"<<endl; + for (int i=0;i<size;i++) { + node_map[i]=i; + } + } + } + } else { // !use_map + for (int i=0;i<size;i++) { + node_map[i]=i; + } + } + reverse_map = (int*)malloc((size)*sizeof(int)); + for (int i = 0; i < size ; i++) { + for (int j = 0; j<size ; j++) { + if (node_map[j]==i) { + reverse_map[i]=j; + break; + } + } + } + printf("nodemap\n"); + display_map((int) sqrt(size),size); + +} + +int fixed_latency(int input, int output) +{ + int latency; + if (perfect_icnt) { + latency = 1; + } else { + int dim = icnt_config.GetInt( "k" ); + int xhops = abs ( input%dim - output%dim); + int yhops = abs ( input/dim - output/dim); + latency = ( (xhops+yhops)*fixed_lat_icnt ); + } + return latency; +} + +//This function gets a mapped node number and tells if it is a shader node or a memory node +static inline bool is_shd(int node) +{ + if (reverse_map[node] < (int) _n_shader) + return true; + else + return false; +} + +static inline bool is_mem(int node) +{ + return !is_shd(node); +} + +//////////////////// +void interconnect_stats() +{ + if (!fixed_lat_icnt) { + for (unsigned i=0; i<net_c;i++) { + cout <<"Traffic "<<i<< " Stat" << endl; + traffic[i]->ShowStats(); + if (icnt_config.GetInt("enable_link_stats")) { + cout << "%=================================" << endl; + cout <<"Traffic "<<i<< "Link utilizations:" << endl; + traffic[i]->_net->Display(); + } + } + } else { + //show max queue sizes + cout<<"Max Fixed Latency ICNT queue size for"<<endl; + for (unsigned i=0;i<(_n_mem + _n_shader);i++) { + cout<<" node[" << i <<"] is "<<max_fixedlat_buf_size[i]; + } + cout<<endl; + } +} + +void icnt_overal_stat() //should be called upon simulation exit to give an overal stat +{ + if (!fixed_lat_icnt) { + for (unsigned i=0; i<net_c;i++) { + traffic[i]->ShowOveralStat(); + } + } +} + +void icnt_init_grid (){ + for (unsigned i=0; i<net_c;i++) { + traffic[i]->IcntInitPerGrid(0/*_time*/); //initialization before gpu grid start + } +} + +int interconnect_has_buffer(unsigned int input_node, + unsigned int *size) +{ + + unsigned int input = node_map[input_node]; + int has_buffer; + int tot_req_size = 0; + for (unsigned int i=0; i<(_n_mem+_n_shader);i++ ) { + if (size[i]) { + tot_req_size+= size[i]; + } + } + unsigned int n_flits = tot_req_size / _flit_size + ((tot_req_size % _flit_size)? 1:0); + if (!(fixed_lat_icnt || perfect_icnt)) { + has_buffer = (traffic[0]->_partial_packets[input][0].size() + n_flits) <= input_buffer_capacity; + if ((net_c>1) && is_mem(input)) { + has_buffer = (traffic[1]->_partial_packets[input][0].size() + n_flits) <= input_buffer_capacity; + } + } else { + has_buffer = 1; + } + return has_buffer; +} + +void interconnect_push ( unsigned int input_node, unsigned int output_node, + void* data, unsigned int size) +{ + int output = node_map[output_node]; + int input = node_map[input_node]; + +#if 0 + cout<<"Call interconnect push input: "<<input<<" output: "<<output<<endl; +#endif + + if (fixed_lat_icnt) { + ((mem_fetch_t *) data)->icnt_receive_time = gpu_sim_cycle + fixed_latency(input,output); + out_buf_fixedlat_buf[output].push(data); //deliver the whole packet to destination in zero cycles + if (out_buf_fixedlat_buf[output].size() > max_fixedlat_buf_size[output]) { + max_fixedlat_buf_size[output]= out_buf_fixedlat_buf[output].size(); + } + } else { + + unsigned int n_flits = size / _flit_size + ((size % _flit_size)? 1:0); + int nc; + if (!doub_net) { + nc=0; + } else //doub_net enabled + if (is_shd(input) ) { + nc=0; + } else { + nc=1; + } + traffic[nc]->_GeneratePacket( input, n_flits, 0 /*class*/, traffic[nc]->_time, data, output); +#if DOUB + cout <<"Traffic[" << nc << "] (mapped) sending form "<< input << " to " << output <<endl; +#endif + } + +} + +void* interconnect_pop(unsigned int output_node) +{ + int output = node_map[output_node]; +#if DEBUG + cout<<"Call interconnect POP " << output<<endl; +#endif + void* data = NULL; + if (fixed_lat_icnt) { + if (!out_buf_fixedlat_buf[output].empty()) { + if (((mem_fetch_t *)out_buf_fixedlat_buf[output].top())->icnt_receive_time <= gpu_sim_cycle) { + data = out_buf_fixedlat_buf[output].top(); + out_buf_fixedlat_buf[output].pop(); + assert (((mem_fetch_t *)data)->icnt_receive_time); + } + } + } else { + unsigned vc; + unsigned turn = round_robin_turn[output]; + for (vc=0;(vc<g_num_vcs) && (data==NULL);vc++) { + if (clock_boundary_buf[output][turn].has_packet()) { + data = clock_boundary_buf[output][turn].pop_packet(); + } + turn++; + if (turn == g_num_vcs) turn = 0; + } + if (data) { + round_robin_turn[output] = turn; + } + } + return data; +} + +extern int MATLAB_OUTPUT ; +extern int DISPLAY_LAT_DIST ; +extern int DISPLAY_HOP_DIST ; +extern int DISPLAY_PAIR_LATENCY ; +extern unsigned int gpu_n_thread_per_shader; +extern char *gpgpu_cache_dl1_opt; +extern int gpgpu_no_dl1; + + +void init_interconnect (char* 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.Parse( config_file ); + + net_c = icnt_config.GetInt( "network_count" ); + if (net_c==2) { + doub_net = true; + } else if (net_c<1 || net_c>2) { + cout <<net_c<<" Network_count less than 1 or more than 2 not supported."<<endl; + abort(); + } + + g_num_vcs = icnt_config.GetInt( "num_vcs" ); + InitializeRoutingMap( ); + InitializeTrafficMap( ); + InitializeInjectionMap( ); + + RandomSeed( icnt_config.GetInt("seed") ); + + Network **net; + + traffic = new TrafficManager *[net_c]; + net = new Network *[net_c]; + + for (unsigned i=0;i<net_c;i++) { + string topo; + + icnt_config.GetStr( "topology", topo ); + + if ( topo == "torus" ) { + net[i] = new KNCube( icnt_config, true ); + } else if ( topo =="mesh" ) { + net[i] = new KNCube( icnt_config, false ); + } else if ( topo == "fly" ) { + net[i] = new KNFly( icnt_config ); + } else if ( topo == "single" ) { + net[i] = new SingleNet( icnt_config ); + } else { + cerr << "Unknown topology " << topo << endl; + exit(-1); + } + + if ( icnt_config.GetInt( "link_failures" ) ) { + net[i]->InsertRandomFaults( icnt_config ); + } + + traffic[i] = new TrafficManager ( icnt_config, net[i], i/*id*/ ); + } + + fixed_lat_icnt = icnt_config.GetInt( "fixed_lat_per_hop" ); + + if (icnt_config.GetInt( "perfect_icnt" )) { + perfect_icnt = true; + fixed_lat_icnt = 1; + } + _flit_size = icnt_config.GetInt( "flit_size" ); + if (icnt_config.GetInt("ejection_buf_size")) { + ejection_buffer_capacity = icnt_config.GetInt( "ejection_buf_size" ) ; + } else { + ejection_buffer_capacity = icnt_config.GetInt( "vc_buf_size" ); + } + boundary_buf_capacity = icnt_config.GetInt( "boundary_buf_size" ) ; + if (icnt_config.GetInt("input_buf_size")) { + input_buffer_capacity = icnt_config.GetInt("input_buf_size"); + } else { + if (gpgpu_cache_dl1_opt && !gpgpu_no_dl1) { + int l1cache_linesize = 32; + sscanf(gpgpu_cache_dl1_opt,"%*d:%d:%*d:%*c", &l1cache_linesize); + input_buffer_capacity = gpu_n_thread_per_shader*(l1cache_linesize/_flit_size+(int)ceil(8.0f/_flit_size)); + } else { + input_buffer_capacity = gpu_n_thread_per_shader*((int)ceil(8.0f/_flit_size)); + } + } + create_buf(traffic[0]->_dests,warp_size,icnt_config.GetInt( "num_vcs" )); + MATLAB_OUTPUT = icnt_config.GetInt("MATLAB_OUTPUT"); + DISPLAY_LAT_DIST = icnt_config.GetInt("DISPLAY_LAT_DIST"); + DISPLAY_HOP_DIST = icnt_config.GetInt("DISPLAY_HOP_DIST"); + DISPLAY_PAIR_LATENCY = icnt_config.GetInt("DISPLAY_PAIR_LATENCY"); + create_node_map(n_shader,n_mem,traffic[0]->_dests, icnt_config.GetInt("use_map")); + for (unsigned i=0;i<net_c;i++) { + traffic[i]->_FirstStep(); + } +} + +void advance_interconnect () +{ + if (!fixed_lat_icnt) { + for (unsigned i=0;i<net_c;i++) { + traffic[i]->_Step( ); + } + } +} + +unsigned interconnect_busy() +{ + unsigned i,j; + for(i=0; i<net_c;i++) { + if (traffic[i]->_measured_in_flight) { + return 1; + } + } + for ( i=0 ;i<(_n_shader+_n_mem);i++ ) { + if ( !traffic[0]->_partial_packets[i] [0].empty() ) { + return 1; + } + if ( doub_net && !traffic[1]->_partial_packets[i] [0].empty() ) { + return 1; + } + for ( j=0;j<g_num_vcs;j++ ) { + if ( !ejection_buf[i][j].empty() || clock_boundary_buf[i][j].has_packet() ) { + return 1; + } + } + } + return 0; +} + +//create buffers for src_n nodes +void create_buf(int src_n,int warp_n,int vc_n) +{ + int i; + ejection_buf = new queue<Flit *>* [src_n]; + clock_boundary_buf = new boundary_buf* [src_n]; + round_robin_turn.resize( src_n ); + for (i=0;i<src_n;i++){ + ejection_buf[i]= new queue<Flit *>[vc_n]; + clock_boundary_buf[i]= new boundary_buf[vc_n]; + round_robin_turn[vc_n-1]; + } + if (fixed_lat_icnt) { + out_buf_fixedlat_buf = new priority_queue<void * , vector<void* >, mycomparison> [src_n]; + max_fixedlat_buf_size = new unsigned int [src_n]; + for (i=0;i<src_n;i++) { + max_fixedlat_buf_size[i]=0; + } + } + +} + +void write_out_buf(int output, Flit *flit) { + int vc = flit->vc; + assert (ejection_buf[output][vc].size() < ejection_buffer_capacity); + ejection_buf[output][vc].push(flit); +} + +void transfer2boundary_buf(int output) { + Flit* flit; + unsigned vc; + for (vc=0; vc<g_num_vcs;vc++) { + if ( !ejection_buf[output][vc].empty() && !clock_boundary_buf[output][vc].is_full() ) { + flit = ejection_buf[output][vc].front(); + ejection_buf[output][vc].pop(); + clock_boundary_buf[output][vc].push_flit_data( flit->data, flit->tail); + traffic[flit->net_num]->credit_return_queue[output].push(flit); //will send back credit + if ( flit->head ) { + assert (flit->dest == output); + } +#if DOUB + cout <<"Traffic " <<nc<<" push out flit to (mapped)" << output <<endl; +#endif + } + } +} + +void time_vector_update(unsigned int uid, int slot , long int cycle, int type); +extern unsigned long long gpu_tot_sim_cycle; +void time_vector_update_icnt_injected(void* data, int input) { + mem_fetch_t* mf = (mem_fetch_t*) data; + unsigned int uid = mf->write? mf->request_uid : mf->mshr->insts[0].uid; + long int cycle = gpu_sim_cycle + gpu_tot_sim_cycle; + int req_type = mf->write? WT_REQ : RD_REQ; + if (is_mem(input)) { + time_vector_update( uid, MR_2SH_ICNT_INJECTED, cycle, req_type ); + } else { + time_vector_update( uid, MR_ICNT_INJECTED, cycle,req_type ); + } +} |
