diff options
| author | Dongdong Li <[email protected]> | 2013-08-08 00:15:58 -0800 |
|---|---|---|
| committer | Andrew Boktor <[email protected]> | 2014-08-14 13:50:58 -0700 |
| commit | 7f49fe9feb174d34efc2a011bad79b38522a360b (patch) | |
| tree | ab5b7b66e40315a81871acbf386722981020f866 /src/intersim2/networks | |
| parent | 5f91e7435742bab74dfbeca18afc63e466498f36 (diff) | |
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]
Diffstat (limited to 'src/intersim2/networks')
| -rw-r--r-- | src/intersim2/networks/anynet.cpp | 501 | ||||
| -rw-r--r-- | src/intersim2/networks/anynet.hpp | 69 | ||||
| -rw-r--r-- | src/intersim2/networks/cmesh.cpp | 856 | ||||
| -rw-r--r-- | src/intersim2/networks/cmesh.hpp | 95 | ||||
| -rw-r--r-- | src/intersim2/networks/dragonfly.cpp | 575 | ||||
| -rw-r--r-- | src/intersim2/networks/dragonfly.hpp | 74 | ||||
| -rw-r--r-- | src/intersim2/networks/fattree.cpp | 270 | ||||
| -rw-r--r-- | src/intersim2/networks/fattree.hpp | 76 | ||||
| -rw-r--r-- | src/intersim2/networks/flatfly_onchip.cpp | 1331 | ||||
| -rw-r--r-- | src/intersim2/networks/flatfly_onchip.hpp | 88 | ||||
| -rw-r--r-- | src/intersim2/networks/fly.cpp | 162 | ||||
| -rw-r--r-- | src/intersim2/networks/fly.hpp | 53 | ||||
| -rw-r--r-- | src/intersim2/networks/kncube.cpp | 319 | ||||
| -rw-r--r-- | src/intersim2/networks/kncube.hpp | 62 | ||||
| -rw-r--r-- | src/intersim2/networks/network.cpp | 290 | ||||
| -rw-r--r-- | src/intersim2/networks/network.hpp | 118 | ||||
| -rw-r--r-- | src/intersim2/networks/qtree.cpp | 187 | ||||
| -rw-r--r-- | src/intersim2/networks/qtree.hpp | 69 | ||||
| -rw-r--r-- | src/intersim2/networks/tree4.cpp | 289 | ||||
| -rw-r--r-- | src/intersim2/networks/tree4.hpp | 72 |
20 files changed, 5556 insertions, 0 deletions
diff --git a/src/intersim2/networks/anynet.cpp b/src/intersim2/networks/anynet.cpp new file mode 100644 index 0000000..4db1dfb --- /dev/null +++ b/src/intersim2/networks/anynet.cpp @@ -0,0 +1,501 @@ +// $Id: anynet.cpp 5354 2012-11-07 23:51:49Z qtedq $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +/*anynet + * + *Network setup file format + *example 1: + *router 0 router 1 15 router 2 + * + *Router 0 is connect to router 1 with a 15-cycle channel, and router 0 is connected to + * router 2 with a 1-cycle channel, the channels latency are unidirectional, so channel + * from router 1 back to router 0 is only single-cycle because it was not specified + * + *example 2: + *router 0 node 0 node 1 5 node 2 5 + * + *Router 0 is directly connected to node 0-2. Channel latency is 5cycles for 1 and 2. In + * this case the latency specification is bidirectional, the injeciton and ejection lat + * for node 1 and 2 are 5-cycle + * + *other notes: + * + *Router and node numbers must be sequential starting with 0 + *Credit channel latency follows the channel latency, even though it travels in revse + * direction this might not be desired + * + */ + +#include "anynet.hpp" +#include <fstream> +#include <sstream> +#include <limits> +#include <algorithm> +//this is a hack, I can't easily get the routing talbe out of the network +map<int, int>* global_routing_table; + +AnyNet::AnyNet( const Configuration &config, const string & name ) + : Network( config, name ){ + + router_list.resize(2); + _ComputeSize( config ); + _Alloc( ); + _BuildNet( config ); +} + +AnyNet::~AnyNet(){ + for(int i = 0; i < 2; ++i) { + for(map<int, map<int, pair<int,int> > >::iterator iter = router_list[i].begin(); + iter != router_list[i].end(); + ++iter) { + iter->second.clear(); + } + } +} + +void AnyNet::_ComputeSize( const Configuration &config ){ + file_name = config.GetStr("network_file"); + if(file_name==""){ + cout<<"No network file name provided"<<endl; + exit(-1); + } + //parse the network description file + readFile(); + + _channels =0; + cout<<"========================Network File Parsed=================\n"; + cout<<"******************node listing**********************\n"; + map<int, int >::iterator iter; + for(iter = node_list.begin(); iter!=node_list.end(); iter++){ + cout<<"Node "<<iter->first; + cout<<"\tRouter "<<iter->second<<endl; + } + + map<int, map<int, pair<int,int> > >::iterator iter3; + cout<<"\n****************router to node listing*************\n"; + for(iter3 = router_list[0].begin(); iter3!=router_list[0].end(); iter3++){ + cout<<"Router "<<iter3->first<<endl; + map<int, pair<int,int> >::iterator iter2; + for(iter2 = iter3->second.begin(); + iter2!=iter3->second.end(); + iter2++){ + cout<<"\t Node "<<iter2->first<<" lat "<<iter2->second.second<<endl; + } + } + + cout<<"\n*****************router to router listing************\n"; + for(iter3 = router_list[1].begin(); iter3!=router_list[1].end(); iter3++){ + cout<<"Router "<<iter3->first<<endl; + map<int, pair<int,int> >::iterator iter2; + if(iter3->second.size() == 0){ + cout<<"Caution Router "<<iter3->first + <<" is not connected to any other Router\n"<<endl; + } + for(iter2 = iter3->second.begin(); + iter2!=iter3->second.end(); + iter2++){ + cout<<"\t Router "<<iter2->first<<" lat "<<iter2->second.second<<endl; + _channels++; + } + } + + _size = router_list[1].size(); + _nodes = node_list.size(); + +} + + + +void AnyNet::_BuildNet( const Configuration &config ){ + + + //I need to keep track the output ports for each router during build + int * outport = (int*)malloc(sizeof(int)*_size); + for(int i = 0; i<_size; i++){outport[i] = 0;} + + cout<<"==========================Node to Router =====================\n"; + //adding the injection/ejection chanenls first + map<int, map<int, pair<int,int> > >::iterator niter; + for(niter = router_list[0].begin(); niter!=router_list[0].end(); niter++){ + map<int, map<int, pair<int,int> > >::iterator riter = router_list[1].find(niter->first); + //calculate radix + int radix = niter->second.size()+riter->second.size(); + int node = niter->first; + cout<<"router "<<node<<" radix "<<radix<<endl; + //decalre the routers + ostringstream router_name; + router_name << "router"; + router_name << "_" << node ; + _routers[node] = Router::NewRouter( config, this, router_name.str( ), + node, radix, radix ); + _timed_modules.push_back(_routers[node]); + //add injeciton ejection channels + map<int, pair<int,int> >::iterator nniter; + for(nniter = niter->second.begin();nniter!=niter->second.end(); nniter++){ + int link = nniter->first; + //add the outport port assined to the map + (niter->second)[link].first = outport[node]; + outport[node]++; + cout<<"\t connected to node "<<link<<" at outport "<<nniter->second.first + <<" lat "<<nniter->second.second<<endl; + _inject[link]->SetLatency(nniter->second.second); + _inject_cred[link]->SetLatency(nniter->second.second); + _eject[link]->SetLatency(nniter->second.second); + _eject_cred[link]->SetLatency(nniter->second.second); + + _routers[node]->AddInputChannel( _inject[link], _inject_cred[link] ); + _routers[node]->AddOutputChannel( _eject[link], _eject_cred[link] ); + } + + } + + cout<<"==========================Router to Router =====================\n"; + //add inter router channels + //since there is no way to systematically number the channels we just start from 0 + //the map, is a mapping of output->input + int channel_count = 0; + for(niter = router_list[0].begin(); niter!=router_list[0].end(); niter++){ + map<int, map<int, pair<int,int> > >::iterator riter = router_list[1].find(niter->first); + int node = niter->first; + map<int, pair<int,int> >::iterator rriter; + cout<<"router "<<node<<endl; + for(rriter = riter->second.begin();rriter!=riter->second.end(); rriter++){ + int other_node = rriter->first; + int link = channel_count; + //add the outport port assined to the map + (riter->second)[other_node].first = outport[node]; + outport[node]++; + cout<<"\t connected to router "<<other_node<<" using link "<<link + <<" at outport "<<rriter->second.first + <<" lat "<<rriter->second.second<<endl; + + _chan[link]->SetLatency(rriter->second.second); + _chan_cred[link]->SetLatency(rriter->second.second); + + _routers[node]->AddOutputChannel( _chan[link], _chan_cred[link] ); + _routers[other_node]->AddInputChannel( _chan[link], _chan_cred[link]); + channel_count++; + } + } + + buildRoutingTable(); + +} + + +void AnyNet::RegisterRoutingFunctions() { + gRoutingFunctionMap["min_anynet"] = &min_anynet; +} + +void min_anynet( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ){ + int out_port=-1; + if(!inject){ + assert(global_routing_table[r->GetID()].count(f->dest)!=0); + out_port=global_routing_table[r->GetID()][f->dest]; + } + + + int vcBegin = 0, vcEnd = gNumVCs-1; + if ( f->type == Flit::READ_REQUEST ) { + vcBegin = gReadReqBeginVC; + vcEnd = gReadReqEndVC; + } else if ( f->type == Flit::WRITE_REQUEST ) { + vcBegin = gWriteReqBeginVC; + vcEnd = gWriteReqEndVC; + } else if ( f->type == Flit::READ_REPLY ) { + vcBegin = gReadReplyBeginVC; + vcEnd = gReadReplyEndVC; + } else if ( f->type == Flit::WRITE_REPLY ) { + vcBegin = gWriteReplyBeginVC; + vcEnd = gWriteReplyEndVC; + } + + outputs->Clear( ); + + outputs->AddRange( out_port , vcBegin, vcEnd ); +} + +void AnyNet::buildRoutingTable(){ + cout<<"========================== Routing table =====================\n"; + routing_table.resize(_size); + for(int i = 0; i<_size; i++){ + route(i); + } + global_routing_table = &routing_table[0]; +} + + +//11/7/2012 +//basically djistra's, tested on a large dragonfly anynet configuration +void AnyNet::route(int r_start){ + int* dist = new int[_size]; + int* prev = new int[_size]; + set<int> rlist; + for(int i = 0; i<_size; i++){ + dist[i] = numeric_limits<int>::max(); + prev[i] = -1; + rlist.insert(i); + } + dist[r_start] = 0; + while(!rlist.empty()){ + //find min + int min_dist = numeric_limits<int>::max(); + int min_cand = -1; + for(set<int>::iterator i = rlist.begin(); + i!=rlist.end(); + i++){ + if(dist[*i]<min_dist){ + min_dist = dist[*i]; + min_cand = *i; + } + } + rlist.erase(min_cand); + + //neighbor + for(map<int,pair<int,int> >::iterator i = router_list[1][min_cand].begin(); + i!=router_list[1][min_cand].end(); + i++){ + int new_dist = dist[min_cand] + i->second.second;//distance is hops not cycles + if(new_dist < dist[i->first]){ + dist[i->first] = new_dist; + prev[i->first] = min_cand; + } + } + } + + //post process from the prev list + for(int i = 0; i<_size; i++){ + if(prev[i] ==-1){ //self + assert(i == r_start); + for(map<int, pair<int, int> >::iterator iter = router_list[0][i].begin(); + iter!=router_list[0][i].end(); + iter++){ + routing_table[r_start][iter->first]=iter->second.first; + //cout<<"node "<<iter->first<<" port "<< iter->second.first<<endl; + } + } else { + int distance=0; + int neighbor=i; + while(prev[neighbor]!=r_start){ + assert(router_list[1][neighbor].count(prev[neighbor])>0); + distance+=router_list[1][prev[neighbor]][neighbor].second;//REVERSE lat + neighbor= prev[neighbor]; + } + distance+=router_list[1][prev[neighbor]][neighbor].second;//lat + + assert( router_list[1][r_start].count(neighbor)!=0); + int port = router_list[1][r_start][neighbor].first; + for(map<int, pair<int,int> >::iterator iter = router_list[0][i].begin(); + iter!=router_list[0][i].end(); + iter++){ + routing_table[r_start][iter->first]=port; + //cout<<"node "<<iter->first<<" port "<< port<<" dist "<<distance<<endl; + } + } + } +} + + +void AnyNet::readFile(){ + + ifstream network_list; + string line; + enum ParseState{HEAD_TYPE=0, + HEAD_ID, + BODY_TYPE, + BODY_ID, + LINK_WEIGHT}; + enum ParseType{NODE=0, + ROUTER, + UNKNOWN}; + + network_list.open(file_name.c_str()); + if(!network_list.is_open()){ + cout<<"Anynet:can't open network file "<<file_name<<endl; + exit(-1); + } + + //loop through the entire file + while(!network_list.eof()){ + getline(network_list,line); + if(line==""){ + continue; + } + + ParseState state=HEAD_TYPE; + //position to parse out white sspace + int pos = 0; + int next_pos=-1; + string temp; + //the first node and its type + int head_id = -1; + ParseType head_type = UNKNOWN; + //stuff that head are linked to + ParseType body_type = UNKNOWN; + int body_id = -1; + int link_weight = 1; + + do{ + + //skip empty spaces + next_pos = line.find(" ",pos); + temp = line.substr(pos,next_pos-pos); + pos = next_pos+1; + if(temp=="" || temp==" "){ + continue; + } + + switch(state){ + case HEAD_TYPE: + if(temp=="router"){ + head_type = ROUTER; + } else if (temp == "node"){ + head_type = NODE; + } else { + cout<<"Anynet:Unknow head of line type "<<temp<<"\n"; + assert(false); + } + state=HEAD_ID; + break; + case HEAD_ID: + //need better error check + head_id = atoi(temp.c_str()); + + //intialize router structures + if(router_list[NODE].count(head_id) == 0){ + router_list[NODE][head_id] = map<int, pair<int,int> >(); + } + if(router_list[ROUTER].count(head_id) == 0){ + router_list[ROUTER][head_id] = map<int, pair<int,int> >(); + } + + state=BODY_TYPE; + break; + case LINK_WEIGHT: + if(temp=="router"|| + temp == "node"){ + //ignore + } else { + link_weight= atoi(temp.c_str()); + router_list[head_type][head_id][body_id].second=link_weight; + break; + } + //intentionally letting it flow through + case BODY_TYPE: + if(temp=="router"){ + body_type = ROUTER; + } else if (temp == "node"){ + body_type = NODE; + } else { + cout<<"Anynet:Unknow body type "<<temp<<"\n"; + assert(false); + } + state=BODY_ID; + break; + case BODY_ID: + body_id = atoi(temp.c_str()); + //intialize router structures if necessary + if(body_type==ROUTER){ + if(router_list[NODE].count(body_id) ==0){ + router_list[NODE][body_id] = map<int, pair<int,int> >(); + } + if(router_list[ROUTER].count(body_id) == 0){ + router_list[ROUTER][body_id] = map<int, pair<int,int> >(); + } + } + + if(head_type==NODE && body_type==NODE){ + + cout<<"Anynet:Cannot connect node to node "<<temp<<"\n"; + assert(false); + + } else if(head_type==NODE && body_type==ROUTER){ + + if(node_list.count(head_id)!=0 && + node_list[head_id]!=body_id){ + cout<<"Anynet:Node "<<body_id<<" trying to connect to multiple router " + <<body_id<<" and "<<node_list[head_id]<<endl; + assert(false); + } + node_list[head_id]=body_id; + router_list[NODE][body_id][head_id]=pair<int, int>(-1,1); + + } else if(head_type==ROUTER && body_type==NODE){ + //insert and check node + if(node_list.count(body_id) != 0 && + node_list[body_id]!=head_id){ + cout<<"Anynet:Node "<<body_id<<" trying to connect to multiple router " + <<body_id<<" and "<<node_list[head_id]<<endl; + assert(false); + } + node_list[body_id] = head_id; + router_list[NODE][head_id][body_id]=pair<int, int>(-1,1); + + } else if(head_type==ROUTER && body_type==ROUTER){ + router_list[ROUTER][head_id][body_id]=pair<int, int>(-1,1); + if(router_list[ROUTER][body_id].count(head_id)==0){ + router_list[ROUTER][body_id][head_id]=pair<int, int>(-1,1); + } + } + state=LINK_WEIGHT; + break ; + default: + cout<<"Anynet:Unknow parse state\n"; + assert(false); + break; + } + + } while(pos!=0); + if(state!=LINK_WEIGHT && + state!=BODY_TYPE){ + cout<<"Anynet:Incomplete parse of the line: "<<line<<endl; + } + + } + + //map verification, make sure the information contained in bother maps + //are the same + assert(router_list[0].size() == router_list[1].size()); + + //traffic generator assumes node list is sequenctial and starts at 0 + vector<int> node_check; + for(map<int,int>::iterator i = node_list.begin(); + i!=node_list.end(); + i++){ + node_check.push_back(i->first); + } + sort(node_check.begin(), node_check.end()); + for(size_t i = 0; i<node_check.size(); i++){ + if(node_check[i] != i){ + cout<<"Anynet:booksim trafficmanager assumes sequential node numbering starting at 0\n"; + assert(false); + } + } + +} + diff --git a/src/intersim2/networks/anynet.hpp b/src/intersim2/networks/anynet.hpp new file mode 100644 index 0000000..1cfe904 --- /dev/null +++ b/src/intersim2/networks/anynet.hpp @@ -0,0 +1,69 @@ +// $Id: anynet.hpp 5354 2012-11-07 23:51:49Z qtedq $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +#ifndef _ANYNET_HPP_ +#define _ANYNET_HPP_ + +#include "network.hpp" +#include "routefunc.hpp" +#include <cassert> +#include <string> +#include <map> +#include <list> + +class AnyNet : public Network { + + string file_name; + //associtation between nodes and routers + map<int, int > node_list; + //[link type][src router][dest router]=(port, latency) + vector<map<int, map<int, pair<int,int> > > > router_list; + //stores minimal routing information from every router to every node + //[router][dest_node]=port + vector<map<int, int> > routing_table; + + void _ComputeSize( const Configuration &config ); + void _BuildNet( const Configuration &config ); + void readFile(); + void buildRoutingTable(); + void route(int r_start); + +public: + AnyNet( const Configuration &config, const string & name ); + ~AnyNet(); + + int GetN( ) const{ return -1;} + int GetK( ) const{ return -1;} + + static void RegisterRoutingFunctions(); + double Capacity( ) const {return -1;} + void InsertRandomFaults( const Configuration &config ){} +}; + +void min_anynet( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ); +#endif diff --git a/src/intersim2/networks/cmesh.cpp b/src/intersim2/networks/cmesh.cpp new file mode 100644 index 0000000..06580d3 --- /dev/null +++ b/src/intersim2/networks/cmesh.cpp @@ -0,0 +1,856 @@ +// $Id: cmesh.cpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +// ---------------------------------------------------------------------- +// +// CMesh: Network with <Int> Terminal Nodes arranged in a concentrated +// mesh topology +// +// ---------------------------------------------------------------------- + +// ---------------------------------------------------------------------- +// $Author: jbalfour $ +// $Date: 2007/06/28 17:24:35 $ +// $Id: cmesh.cpp 5188 2012-08-30 00:31:31Z dub $ +// Modified 11/6/2007 by Ted Jiang +// Now handeling n = most power of 2: 16, 64, 256, 1024 +// ---------------------------------------------------------------------- +#include "booksim.hpp" +#include <vector> +#include <sstream> +#include <cassert> +#include "random_utils.hpp" +#include "misc_utils.hpp" +#include "cmesh.hpp" + +int CMesh::_cX = 0 ; +int CMesh::_cY = 0 ; +int CMesh::_memo_NodeShiftX = 0 ; +int CMesh::_memo_NodeShiftY = 0 ; +int CMesh::_memo_PortShiftY = 0 ; + +CMesh::CMesh( const Configuration& config, const string & name ) + : Network(config, name) +{ + _ComputeSize( config ); + _Alloc(); + _BuildNet(config); +} + +void CMesh::RegisterRoutingFunctions() { + gRoutingFunctionMap["dor_cmesh"] = &dor_cmesh; + gRoutingFunctionMap["dor_no_express_cmesh"] = &dor_no_express_cmesh; + gRoutingFunctionMap["xy_yx_cmesh"] = &xy_yx_cmesh; + gRoutingFunctionMap["xy_yx_no_express_cmesh"] = &xy_yx_no_express_cmesh; +} + +void CMesh::_ComputeSize( const Configuration &config ) { + + int k = config.GetInt( "k" ); + int n = config.GetInt( "n" ); + assert(n <= 2); // broken for n > 2 + int c = config.GetInt( "c" ); + assert(c == 4); // broken for c != 4 + + ostringstream router_name; + //how many routers in the x or y direction + _xcount = config.GetInt("x"); + _ycount = config.GetInt("y"); + assert(_xcount == _ycount); // broken for asymmetric topologies + //configuration of hohw many clients in X and Y per router + _xrouter = config.GetInt("xr"); + _yrouter = config.GetInt("yr"); + assert(_xrouter == _yrouter); // broken for asymmetric concentration + + gK = _k = k ; + gN = _n = n ; + gC = _c = c ; + + assert(c == _xrouter*_yrouter); + + _nodes = _c * powi( _k, _n); // Number of nodes in network + _size = powi( _k, _n); // Number of routers in network + _channels = 2 * _n * _size; // Number of channels in network + + _cX = _c / _n ; // Concentration in X Dimension + _cY = _c / _cX ; // Concentration in Y Dimension + + // + _memo_NodeShiftX = _cX >> 1 ; + _memo_NodeShiftY = log_two(gK * _cX) + ( _cY >> 1 ) ; + _memo_PortShiftY = log_two(gK * _cX) ; + +} + +void CMesh::_BuildNet( const Configuration& config ) { + + int x_index ; + int y_index ; + + //standard trace configuration + if(gTrace){ + cout<<"Setup Finished Router"<<endl; + } + + //latency type, noc or conventional network + bool use_noc_latency; + use_noc_latency = (config.GetInt("use_noc_latency")==1); + + ostringstream name; + // The following vector is used to check that every + // processor in the system is connected to the network + vector<bool> channel_vector(_nodes, false) ; + + // + // Routers and Channel + // + for (int node = 0; node < _size; ++node) { + + // Router index derived from mesh index + y_index = node / _k ; + x_index = node % _k ; + + const int degree_in = 2 *_n + _c ; + const int degree_out = 2 *_n + _c ; + + name << "router_" << y_index << '_' << x_index; + _routers[node] = Router::NewRouter( config, + this, + name.str(), + node, + degree_in, + degree_out); + _timed_modules.push_back(_routers[node]); + name.str(""); + + // + // Port Numbering: as best as I can determine, the order in + // which the input and output channels are added to the + // router determines the associated port number that must be + // used by the router. Output port number increases with + // each new channel + // + + // + // Processing node channels + // + for (int y = 0; y < _cY ; y++) { + for (int x = 0; x < _cX ; x++) { + int link = (_k * _cX) * (_cY * y_index + y) + (_cX * x_index + x) ; + assert( link >= 0 ) ; + assert( link < _nodes ) ; + assert( channel_vector[ link ] == false ) ; + channel_vector[link] = true ; + // Ingress Ports + _routers[node]->AddInputChannel(_inject[link], _inject_cred[link]); + // Egress Ports + _routers[node]->AddOutputChannel(_eject[link], _eject_cred[link]); + //injeciton ejection latency is 1 + _inject[link]->SetLatency( 1 ); + _eject[link]->SetLatency( 1 ); + } + } + + // + // router to router channels + // + const int x = node % _k ; + const int y = node / _k ; + const int offset = powi( _k, _n ) ; + + //the channel number of the input output channels. + int px_out = _k * y + x + 0 * offset ; + int nx_out = _k * y + x + 1 * offset ; + int py_out = _k * y + x + 2 * offset ; + int ny_out = _k * y + x + 3 * offset ; + int px_in = _k * y + ((x+1)) + 1 * offset ; + int nx_in = _k * y + ((x-1)) + 0 * offset ; + int py_in = _k * ((y+1)) + x + 3 * offset ; + int ny_in = _k * ((y-1)) + x + 2 * offset ; + + // Express Channels + if (x == 0){ + // Router on left edge of mesh. Connect to -x output of + // another router on the left edge of the mesh. + if (y < _k / 2 ) + nx_in = _k * (y + _k/2) + x + offset ; + else + nx_in = _k * (y - _k/2) + x + offset ; + } + + if (x == (_k-1)){ + // Router on right edge of mesh. Connect to +x output of + // another router on the right edge of the mesh. + if (y < _k / 2) + px_in = _k * (y + _k/2) + x ; + else + px_in = _k * (y - _k/2) + x ; + } + + if (y == 0) { + // Router on bottom edge of mesh. Connect to -y output of + // another router on the bottom edge of the mesh. + if (x < _k / 2) + ny_in = _k * y + (x + _k/2) + 3 * offset ; + else + ny_in = _k * y + (x - _k/2) + 3 * offset ; + } + + if (y == (_k-1)) { + // Router on top edge of mesh. Connect to +y output of + // another router on the top edge of the mesh + if (x < _k / 2) + py_in = _k * y + (x + _k/2) + 2 * offset ; + else + py_in = _k * y + (x - _k/2) + 2 * offset ; + } + + /*set latency and add the channels*/ + + // Port 0: +x channel + if(use_noc_latency) { + int const px_latency = (x == _k-1) ? (_cY*_k/2) : _cX; + _chan[px_out]->SetLatency( px_latency ); + _chan_cred[px_out]->SetLatency( px_latency ); + } else { + _chan[px_out]->SetLatency( 1 ); + _chan_cred[px_out]->SetLatency( 1 ); + } + _routers[node]->AddOutputChannel( _chan[px_out], _chan_cred[px_out] ); + _routers[node]->AddInputChannel( _chan[px_in], _chan_cred[px_in] ); + + if(gTrace) { + cout<<"Link "<<" "<<px_out<<" "<<px_in<<" "<<node<<" "<<_chan[px_out]->GetLatency()<<endl; + } + + // Port 1: -x channel + if(use_noc_latency) { + int const nx_latency = (x == 0) ? (_cY*_k/2) : _cX; + _chan[nx_out]->SetLatency( nx_latency ); + _chan_cred[nx_out]->SetLatency( nx_latency ); + } else { + _chan[nx_out]->SetLatency( 1 ); + _chan_cred[nx_out]->SetLatency( 1 ); + } + _routers[node]->AddOutputChannel( _chan[nx_out], _chan_cred[nx_out] ); + _routers[node]->AddInputChannel( _chan[nx_in], _chan_cred[nx_in] ); + + if(gTrace){ + cout<<"Link "<<" "<<nx_out<<" "<<nx_in<<" "<<node<<" "<<_chan[nx_out]->GetLatency()<<endl; + } + + // Port 2: +y channel + if(use_noc_latency) { + int const py_latency = (y == _k-1) ? (_cX*_k/2) : _cY; + _chan[py_out]->SetLatency( py_latency ); + _chan_cred[py_out]->SetLatency( py_latency ); + } else { + _chan[py_out]->SetLatency( 1 ); + _chan_cred[py_out]->SetLatency( 1 ); + } + _routers[node]->AddOutputChannel( _chan[py_out], _chan_cred[py_out] ); + _routers[node]->AddInputChannel( _chan[py_in], _chan_cred[py_in] ); + + if(gTrace){ + cout<<"Link "<<" "<<py_out<<" "<<py_in<<" "<<node<<" "<<_chan[py_out]->GetLatency()<<endl; + } + + // Port 3: -y channel + if(use_noc_latency){ + int const ny_latency = (y == 0) ? (_cX*_k/2) : _cY; + _chan[ny_out]->SetLatency( ny_latency ); + _chan_cred[ny_out]->SetLatency( ny_latency ); + } else { + _chan[ny_out]->SetLatency( 1 ); + _chan_cred[ny_out]->SetLatency( 1 ); + } + _routers[node]->AddOutputChannel( _chan[ny_out], _chan_cred[ny_out] ); + _routers[node]->AddInputChannel( _chan[ny_in], _chan_cred[ny_in] ); + + if(gTrace){ + cout<<"Link "<<" "<<ny_out<<" "<<ny_in<<" "<<node<<" "<<_chan[ny_out]->GetLatency()<<endl; + } + + } + + // Check that all processors were connected to the network + for ( int i = 0 ; i < _nodes ; i++ ) + assert( channel_vector[i] == true ) ; + + if(gTrace){ + cout<<"Setup Finished Link"<<endl; + } +} + + +// ---------------------------------------------------------------------- +// +// Routing Helper Functions +// +// ---------------------------------------------------------------------- + +int CMesh::NodeToRouter( int address ) { + + int y = (address / (_cX*gK))/_cY ; + int x = (address % (_cX*gK))/_cY ; + int router = y*gK + x ; + + return router ; +} + +int CMesh::NodeToPort( int address ) { + + const int maskX = _cX - 1 ; + const int maskY = _cY - 1 ; + + int x = address & maskX ; + int y = (int)(address/(2*gK)) & maskY ; + + return (gC / 2) * y + x; +} + +// ---------------------------------------------------------------------- +// +// Routing Functions +// +// ---------------------------------------------------------------------- + +// Concentrated Mesh: X-Y +int cmesh_xy( int cur, int dest ) { + + const int POSITIVE_X = 0 ; + const int NEGATIVE_X = 1 ; + const int POSITIVE_Y = 2 ; + const int NEGATIVE_Y = 3 ; + + int cur_y = cur / gK; + int cur_x = cur % gK; + int dest_y = dest / gK; + int dest_x = dest % gK; + + // Dimension-order Routing: x , y + if (cur_x < dest_x) { + // Express? + if ((dest_x - cur_x) > 1){ + if (cur_y == 0) + return gC + NEGATIVE_Y ; + if (cur_y == (gK-1)) + return gC + POSITIVE_Y ; + } + return gC + POSITIVE_X ; + } + if (cur_x > dest_x) { + // Express ? + if ((cur_x - dest_x) > 1){ + if (cur_y == 0) + return gC + NEGATIVE_Y ; + if (cur_y == (gK-1)) + return gC + POSITIVE_Y ; + } + return gC + NEGATIVE_X ; + } + if (cur_y < dest_y) { + // Express? + if ((dest_y - cur_y) > 1) { + if (cur_x == 0) + return gC + NEGATIVE_X ; + if (cur_x == (gK-1)) + return gC + POSITIVE_X ; + } + return gC + POSITIVE_Y ; + } + if (cur_y > dest_y) { + // Express ? + if ((cur_y - dest_y) > 1 ){ + if (cur_x == 0) + return gC + NEGATIVE_X ; + if (cur_x == (gK-1)) + return gC + POSITIVE_X ; + } + return gC + NEGATIVE_Y ; + } + return 0; +} + +// Concentrated Mesh: Y-X +int cmesh_yx( int cur, int dest ) { + const int POSITIVE_X = 0 ; + const int NEGATIVE_X = 1 ; + const int POSITIVE_Y = 2 ; + const int NEGATIVE_Y = 3 ; + + int cur_y = cur / gK ; + int cur_x = cur % gK ; + int dest_y = dest / gK ; + int dest_x = dest % gK ; + + // Dimension-order Routing: y, x + if (cur_y < dest_y) { + // Express? + if ((dest_y - cur_y) > 1) { + if (cur_x == 0) + return gC + NEGATIVE_X ; + if (cur_x == (gK-1)) + return gC + POSITIVE_X ; + } + return gC + POSITIVE_Y ; + } + if (cur_y > dest_y) { + // Express ? + if ((cur_y - dest_y) > 1 ){ + if (cur_x == 0) + return gC + NEGATIVE_X ; + if (cur_x == (gK-1)) + return gC + POSITIVE_X ; + } + return gC + NEGATIVE_Y ; + } + if (cur_x < dest_x) { + // Express? + if ((dest_x - cur_x) > 1){ + if (cur_y == 0) + return gC + NEGATIVE_Y ; + if (cur_y == (gK-1)) + return gC + POSITIVE_Y ; + } + return gC + POSITIVE_X ; + } + if (cur_x > dest_x) { + // Express ? + if ((cur_x - dest_x) > 1){ + if (cur_y == 0) + return gC + NEGATIVE_Y ; + if (cur_y == (gK-1)) + return gC + POSITIVE_Y ; + } + return gC + NEGATIVE_X ; + } + return 0; +} + +void xy_yx_cmesh( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + + // ( Traffic Class , Routing Order ) -> Virtual Channel Range + int vcBegin = 0, vcEnd = gNumVCs-1; + if ( f->type == Flit::READ_REQUEST ) { + vcBegin = gReadReqBeginVC; + vcEnd = gReadReqEndVC; + } else if ( f->type == Flit::WRITE_REQUEST ) { + vcBegin = gWriteReqBeginVC; + vcEnd = gWriteReqEndVC; + } else if ( f->type == Flit::READ_REPLY ) { + vcBegin = gReadReplyBeginVC; + vcEnd = gReadReplyEndVC; + } else if ( f->type == Flit::WRITE_REPLY ) { + vcBegin = gWriteReplyBeginVC; + vcEnd = gWriteReplyEndVC; + } + assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0))); + + int out_port; + + if(inject) { + + out_port = -1; + + } else { + + // Current Router + int cur_router = r->GetID(); + + // Destination Router + int dest_router = CMesh::NodeToRouter( f->dest ) ; + + if (dest_router == cur_router) { + + // Forward to processing element + out_port = CMesh::NodeToPort( f->dest ); + + } else { + + // Forward to neighbouring router + + //each class must have at least 2 vcs assigned or else xy_yx will deadlock + int const available_vcs = (vcEnd - vcBegin + 1) / 2; + assert(available_vcs > 0); + + // randomly select dimension order at first hop + bool x_then_y = ((in_channel < gC) ? + (RandomInt(1) > 0) : + (f->vc < (vcBegin + available_vcs))); + + if(x_then_y) { + out_port = cmesh_xy( cur_router, dest_router ); + vcEnd -= available_vcs; + } else { + out_port = cmesh_yx( cur_router, dest_router ); + vcBegin += available_vcs; + } + } + + } + + outputs->Clear(); + + outputs->AddRange( out_port , vcBegin, vcEnd ); +} + +// ---------------------------------------------------------------------- +// +// Concentrated Mesh: Random XY-YX w/o Express Links +// +// <int> cur: current router address +/// <int> dest: destination router address +// +// ---------------------------------------------------------------------- + +int cmesh_xy_no_express( int cur, int dest ) { + + const int POSITIVE_X = 0 ; + const int NEGATIVE_X = 1 ; + const int POSITIVE_Y = 2 ; + const int NEGATIVE_Y = 3 ; + + const int cur_y = cur / gK ; + const int cur_x = cur % gK ; + const int dest_y = dest / gK ; + const int dest_x = dest % gK ; + + + // Note: channel numbers bellow gC (degree of concentration) are + // injection and ejection links + + // Dimension-order Routing: X , Y + if (cur_x < dest_x) { + return gC + POSITIVE_X ; + } + if (cur_x > dest_x) { + return gC + NEGATIVE_X ; + } + if (cur_y < dest_y) { + return gC + POSITIVE_Y ; + } + if (cur_y > dest_y) { + return gC + NEGATIVE_Y ; + } + return 0; +} + +int cmesh_yx_no_express( int cur, int dest ) { + + const int POSITIVE_X = 0 ; + const int NEGATIVE_X = 1 ; + const int POSITIVE_Y = 2 ; + const int NEGATIVE_Y = 3 ; + + const int cur_y = cur / gK ; + const int cur_x = cur % gK ; + const int dest_y = dest / gK ; + const int dest_x = dest % gK ; + + // Note: channel numbers bellow gC (degree of concentration) are + // injection and ejection links + + // Dimension-order Routing: X , Y + if (cur_y < dest_y) { + return gC + POSITIVE_Y ; + } + if (cur_y > dest_y) { + return gC + NEGATIVE_Y ; + } + if (cur_x < dest_x) { + return gC + POSITIVE_X ; + } + if (cur_x > dest_x) { + return gC + NEGATIVE_X ; + } + return 0; +} + +void xy_yx_no_express_cmesh( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + // ( Traffic Class , Routing Order ) -> Virtual Channel Range + int vcBegin = 0, vcEnd = gNumVCs-1; + if ( f->type == Flit::READ_REQUEST ) { + vcBegin = gReadReqBeginVC; + vcEnd = gReadReqEndVC; + } else if ( f->type == Flit::WRITE_REQUEST ) { + vcBegin = gWriteReqBeginVC; + vcEnd = gWriteReqEndVC; + } else if ( f->type == Flit::READ_REPLY ) { + vcBegin = gReadReplyBeginVC; + vcEnd = gReadReplyEndVC; + } else if ( f->type == Flit::WRITE_REPLY ) { + vcBegin = gWriteReplyBeginVC; + vcEnd = gWriteReplyEndVC; + } + assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0))); + + int out_port; + + if(inject) { + + out_port = -1; + + } else { + + // Current Router + int cur_router = r->GetID(); + + // Destination Router + int dest_router = CMesh::NodeToRouter( f->dest ); + + if (dest_router == cur_router) { + + // Forward to processing element + out_port = CMesh::NodeToPort( f->dest ); + + } else { + + // Forward to neighbouring router + + //each class must have at least 2 vcs assigned or else xy_yx will deadlock + int const available_vcs = (vcEnd - vcBegin + 1) / 2; + assert(available_vcs > 0); + + // randomly select dimension order at first hop + bool x_then_y = ((in_channel < gC) ? + (RandomInt(1) > 0) : + (f->vc < (vcBegin + available_vcs))); + + if(x_then_y) { + out_port = cmesh_xy_no_express( cur_router, dest_router ); + vcEnd -= available_vcs; + } else { + out_port = cmesh_yx_no_express( cur_router, dest_router ); + vcBegin += available_vcs; + } + } + } + + outputs->Clear(); + + outputs->AddRange( out_port , vcBegin, vcEnd ); +} +//============================================================ +// +//===== +int cmesh_next( int cur, int dest ) { + + const int POSITIVE_X = 0 ; + const int NEGATIVE_X = 1 ; + const int POSITIVE_Y = 2 ; + const int NEGATIVE_Y = 3 ; + + int cur_y = cur / gK ; + int cur_x = cur % gK ; + int dest_y = dest / gK ; + int dest_x = dest % gK ; + + // Dimension-order Routing: x , y + if (cur_x < dest_x) { + // Express? + if ((dest_x - cur_x) > gK/2-1){ + if (cur_y == 0) + return gC + NEGATIVE_Y ; + if (cur_y == (gK-1)) + return gC + POSITIVE_Y ; + } + return gC + POSITIVE_X ; + } + if (cur_x > dest_x) { + // Express ? + if ((cur_x - dest_x) > gK/2-1){ + if (cur_y == 0) + return gC + NEGATIVE_Y ; + if (cur_y == (gK-1)) + return gC + POSITIVE_Y ; + } + return gC + NEGATIVE_X ; + } + if (cur_y < dest_y) { + // Express? + if ((dest_y - cur_y) > gK/2-1) { + if (cur_x == 0) + return gC + NEGATIVE_X ; + if (cur_x == (gK-1)) + return gC + POSITIVE_X ; + } + return gC + POSITIVE_Y ; + } + if (cur_y > dest_y) { + // Express ? + if ((cur_y - dest_y) > gK/2-1){ + if (cur_x == 0) + return gC + NEGATIVE_X ; + if (cur_x == (gK-1)) + return gC + POSITIVE_X ; + } + return gC + NEGATIVE_Y ; + } + + assert(false); + return -1; +} + +void dor_cmesh( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + // ( Traffic Class , Routing Order ) -> Virtual Channel Range + int vcBegin = 0, vcEnd = gNumVCs-1; + if ( f->type == Flit::READ_REQUEST ) { + vcBegin = gReadReqBeginVC; + vcEnd = gReadReqEndVC; + } else if ( f->type == Flit::WRITE_REQUEST ) { + vcBegin = gWriteReqBeginVC; + vcEnd = gWriteReqEndVC; + } else if ( f->type == Flit::READ_REPLY ) { + vcBegin = gReadReplyBeginVC; + vcEnd = gReadReplyEndVC; + } else if ( f->type == Flit::WRITE_REPLY ) { + vcBegin = gWriteReplyBeginVC; + vcEnd = gWriteReplyEndVC; + } + assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0))); + + int out_port; + + if(inject) { + + out_port = -1; + + } else { + + // Current Router + int cur_router = r->GetID(); + + // Destination Router + int dest_router = CMesh::NodeToRouter( f->dest ) ; + + if (dest_router == cur_router) { + + // Forward to processing element + out_port = CMesh::NodeToPort( f->dest ) ; + + } else { + + // Forward to neighbouring router + out_port = cmesh_next( cur_router, dest_router ); + } + } + + outputs->Clear(); + + outputs->AddRange( out_port, vcBegin, vcEnd); +} + +//============================================================ +// +//===== +int cmesh_next_no_express( int cur, int dest ) { + + const int POSITIVE_X = 0 ; + const int NEGATIVE_X = 1 ; + const int POSITIVE_Y = 2 ; + const int NEGATIVE_Y = 3 ; + + //magic constant 2, which is supose to be _cX and _cY + int cur_y = cur/gK ; + int cur_x = cur%gK ; + int dest_y = dest/gK; + int dest_x = dest%gK ; + + // Dimension-order Routing: x , y + if (cur_x < dest_x) { + return gC + POSITIVE_X ; + } + if (cur_x > dest_x) { + return gC + NEGATIVE_X ; + } + if (cur_y < dest_y) { + return gC + POSITIVE_Y ; + } + if (cur_y > dest_y) { + return gC + NEGATIVE_Y ; + } + assert(false); + return -1; +} + +void dor_no_express_cmesh( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + // ( Traffic Class , Routing Order ) -> Virtual Channel Range + int vcBegin = 0, vcEnd = gNumVCs-1; + if ( f->type == Flit::READ_REQUEST ) { + vcBegin = gReadReqBeginVC; + vcEnd = gReadReqEndVC; + } else if ( f->type == Flit::WRITE_REQUEST ) { + vcBegin = gWriteReqBeginVC; + vcEnd = gWriteReqEndVC; + } else if ( f->type == Flit::READ_REPLY ) { + vcBegin = gReadReplyBeginVC; + vcEnd = gReadReplyEndVC; + } else if ( f->type == Flit::WRITE_REPLY ) { + vcBegin = gWriteReplyBeginVC; + vcEnd = gWriteReplyEndVC; + } + assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0))); + + int out_port; + + if(inject) { + + out_port = -1; + + } else { + + // Current Router + int cur_router = r->GetID(); + + // Destination Router + int dest_router = CMesh::NodeToRouter( f->dest ) ; + + if (dest_router == cur_router) { + + // Forward to processing element + out_port = CMesh::NodeToPort( f->dest ); + + } else { + + // Forward to neighbouring router + out_port = cmesh_next_no_express( cur_router, dest_router ); + } + } + + outputs->Clear(); + + outputs->AddRange( out_port, vcBegin, vcEnd ); +} diff --git a/src/intersim2/networks/cmesh.hpp b/src/intersim2/networks/cmesh.hpp new file mode 100644 index 0000000..1ee55a6 --- /dev/null +++ b/src/intersim2/networks/cmesh.hpp @@ -0,0 +1,95 @@ +// $Id: cmesh.hpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +//////////////////////////////////////////////////////////////////////// +// +// CMesh: Mesh topology with concentration and express links along the +// edge of the network +// +//////////////////////////////////////////////////////////////////////// +// +// RCS Information: +// $Author: jbalfour $ +// $Date: 2007/06/26 22:49:23 $ +// $Id: cmesh.hpp 5188 2012-08-30 00:31:31Z dub $ +// +//////////////////////////////////////////////////////////////////////// +#ifndef _CMESH_HPP_ +#define _CMESH_HPP_ + +#include "network.hpp" +#include "routefunc.hpp" + +class CMesh : public Network { +public: + CMesh( const Configuration &config, const string & name ); + int GetN() const; + int GetK() const; + + static int NodeToRouter( int address ) ; + static int NodeToPort( int address ) ; + + static void RegisterRoutingFunctions() ; + +private: + + static int _cX ; + static int _cY ; + + static int _memo_NodeShiftX ; + static int _memo_NodeShiftY ; + static int _memo_PortShiftY ; + + void _ComputeSize( const Configuration &config ); + void _BuildNet( const Configuration& config ); + + int _k ; + int _n ; + int _c ; + int _xcount; + int _ycount; + int _xrouter; + int _yrouter; + bool _express_channels; +}; + +// +// Routing Functions +// +void xy_yx_cmesh( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) ; + +void xy_yx_no_express_cmesh( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) ; + +void dor_cmesh( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) ; + +void dor_no_express_cmesh( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) ; + +#endif diff --git a/src/intersim2/networks/dragonfly.cpp b/src/intersim2/networks/dragonfly.cpp new file mode 100644 index 0000000..b539cc6 --- /dev/null +++ b/src/intersim2/networks/dragonfly.cpp @@ -0,0 +1,575 @@ +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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 Stanford University 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 OWNER 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 "booksim.hpp" +#include <vector> +#include <sstream> + +#include "dragonfly.hpp" +#include "random_utils.hpp" +#include "misc_utils.hpp" +#include "globals.hpp" + +#define DRAGON_LATENCY + +int gP, gA, gG; + +//calculate the hop count between src and estination +int dragonflynew_hopcnt(int src, int dest) +{ + int hopcnt; + int dest_grp_ID, src_grp_ID; + int src_hopcnt, dest_hopcnt; + int src_intm, dest_intm; + int grp_output, dest_grp_output; + int grp_output_RID; + + int _grp_num_routers= gA; + int _grp_num_nodes =_grp_num_routers*gP; + + dest_grp_ID = int(dest/_grp_num_nodes); + src_grp_ID = int(src / _grp_num_nodes); + + //source and dest are in the same group, either 0-1 hop + if (dest_grp_ID == src_grp_ID) { + if ((int)(dest / gP) == (int)(src /gP)) + hopcnt = 0; + else + hopcnt = 1; + + } else { + //source and dest are in the same group + //find the number of hops in the source group + //find the number of hops in the dest group + if (src_grp_ID > dest_grp_ID) { + grp_output = dest_grp_ID; + dest_grp_output = src_grp_ID - 1; + } + else { + grp_output = dest_grp_ID - 1; + dest_grp_output = src_grp_ID; + } + grp_output_RID = ((int) (grp_output / (gP))) + src_grp_ID * _grp_num_routers; + src_intm = grp_output_RID * gP; + + grp_output_RID = ((int) (dest_grp_output / (gP))) + dest_grp_ID * _grp_num_routers; + dest_intm = grp_output_RID * gP; + + //hop count in source group + if ((int)( src_intm / gP) == (int)( src / gP ) ) + src_hopcnt = 0; + else + src_hopcnt = 1; + + //hop count in destination group + if ((int)( dest_intm / gP) == (int)( dest / gP ) ){ + dest_hopcnt = 0; + }else{ + dest_hopcnt = 1; + } + + //tally + hopcnt = src_hopcnt + 1 + dest_hopcnt; + } + + return hopcnt; +} + + +//packet output port based on the source, destination and current location +int dragonfly_port(int rID, int source, int dest){ + int _grp_num_routers= gA; + int _grp_num_nodes =_grp_num_routers*gP; + + int out_port = -1; + int grp_ID = int(rID / _grp_num_routers); + int dest_grp_ID = int(dest/_grp_num_nodes); + int grp_output=-1; + int grp_RID=-1; + int group_dest=-1; + + //which router within this group the packet needs to go to + if (dest_grp_ID == grp_ID) { + grp_RID = int(dest / gP); + } else { + if (grp_ID > dest_grp_ID) { + grp_output = dest_grp_ID; + } else { + grp_output = dest_grp_ID - 1; + } + grp_RID = int(grp_output /gP) + grp_ID * _grp_num_routers; + group_dest = grp_RID * gP; + } + + //At the last hop + if (dest >= rID*gP && dest < (rID+1)*gP) { + out_port = dest%gP; + } else if (grp_RID == rID) { + //At the optical link + out_port = gP + (gA-1) + grp_output %(gP); + } else { + //need to route within a group + assert(grp_RID!=-1); + + if (rID < grp_RID){ + out_port = (grp_RID % _grp_num_routers) - 1 + gP; + }else{ + out_port = (grp_RID % _grp_num_routers) + gP; + } + } + + assert(out_port!=-1); + return out_port; +} + + +DragonFlyNew::DragonFlyNew( const Configuration &config, const string & name ) : + Network( config, name ) +{ + + _ComputeSize( config ); + _Alloc( ); + _BuildNet( config ); +} + +void DragonFlyNew::_ComputeSize( const Configuration &config ) +{ + + // LIMITATION + // -- only one dimension between the group + // _n == # of dimensions within a group + // _p == # of processors within a router + // inter-group ports : _p + // terminal ports : _p + // intra-group ports : 2*_p - 1 + _p = config.GetInt( "k" ); // # of ports in each switch + _n = config.GetInt( "n" ); + + + assert(_n==1); + // dimension + + if (_n == 1) + _k = _p + _p + 2*_p - 1; + else + _k = _p + _p + 2*_p; + + + // FIX... + gK = _p; gN = _n; + + // with 1 dimension, total of 2p routers per group + // N = 2p * p * (2p^2 + 1) + // a = # of routers per group + // = 2p (if n = 1) + // = p^(n) (if n > 2) + // g = # of groups + // = a * p + 1 + // N = a * p * g; + + if (_n == 1) + _a = 2 * _p; + else + _a = powi(_p, _n); + + _g = _a * _p + 1; + _nodes = _a * _p * _g; + + _num_of_switch = _nodes / _p; + _channels = _num_of_switch * (_k - _p); + _size = _num_of_switch; + + + + gG = _g; + gP = _p; + gA = _a; + _grp_num_routers = gA; + _grp_num_nodes =_grp_num_routers*gP; + +} + +void DragonFlyNew::_BuildNet( const Configuration &config ) +{ + + int _output; + int _input; + int c; + int _dim_ID; + int _num_ports_per_switch; + int _dim_size; + + ostringstream router_name; + + + + cout << " Dragonfly " << endl; + cout << " p = " << _p << " n = " << _n << endl; + cout << " each switch - total radix = "<< _k << endl; + cout << " # of switches = "<< _num_of_switch << endl; + cout << " # of channels = "<< _channels << endl; + cout << " # of nodes ( size of network ) = " << _nodes << endl; + cout << " # of groups (_g) = " << _g << endl; + cout << " # of routers per group (_a) = " << _a << endl; + + for ( int node = 0; node < _num_of_switch; ++node ) { + // ID of the group + int grp_ID; + grp_ID = (int) (node/_a); + router_name << "router"; + + router_name << "_" << node ; + + _routers[node] = Router::NewRouter( config, this, router_name.str( ), + node, _k, _k ); + _timed_modules.push_back(_routers[node]); + + router_name.str(""); + + for ( int cnt = 0; cnt < _p; ++cnt ) { + c = _p * node + cnt; + _routers[node]->AddInputChannel( _inject[c], _inject_cred[c] ); + + } + + for ( int cnt = 0; cnt < _p; ++cnt ) { + c = _p * node + cnt; + _routers[node]->AddOutputChannel( _eject[c], _eject_cred[c] ); + + } + + // add OUPUT channels + // _k == # of processor per router + // need 2*_k routers --thus, + // 2_k-1 outputs channels within group + // _k-1 outputs for intra-group + + // + + if (_n > 1 ) { cout << " ERROR: n>1 dimension NOT supported yet... " << endl; exit(-1); } + + //******************************************** + // connect OUTPUT channels + //******************************************** + // add intra-group output channel + for ( int dim = 0; dim < _n; ++dim ) { + for ( int cnt = 0; cnt < (2*_p -1); ++cnt ) { + _output = (2*_p-1 + _p) * _n * node + (2*_p-1) * dim + cnt; + + _routers[node]->AddOutputChannel( _chan[_output], _chan_cred[_output] ); + +#ifdef DRAGON_LATENCY + _chan[_output]->SetLatency(10); + _chan_cred[_output]->SetLatency(10); +#endif + } + } + + // add inter-group output channel + + for ( int cnt = 0; cnt < _p; ++cnt ) { + _output = (2*_p-1 + _p) * node + (2*_p - 1) + cnt; + + // _chan[_output].global = true; + _routers[node]->AddOutputChannel( _chan[_output], _chan_cred[_output] ); +#ifdef DRAGON_LATENCY + _chan[_output]->SetLatency(100); + _chan_cred[_output]->SetLatency(100); +#endif + } + + + //******************************************** + // connect INPUT channels + //******************************************** + // # of non-local nodes + _num_ports_per_switch = (_k - _p); + + + // intra-group GROUP channels + for ( int dim = 0; dim < _n; ++dim ) { + + _dim_size = powi(_k,dim); + + _dim_ID = ((int) (node / ( powi(_p, dim)))); + + + + // NODE ID withing group + _dim_ID = node % _a; + + + + + for ( int cnt = 0; cnt < (2*_p-1); ++cnt ) { + + if ( cnt < _dim_ID) { + + _input = grp_ID * _num_ports_per_switch * _a - + (_dim_ID - cnt) * _num_ports_per_switch + + _dim_ID * _num_ports_per_switch + + (_dim_ID - 1); + } + else { + + _input = grp_ID * _num_ports_per_switch * _a + + _dim_ID * _num_ports_per_switch + + (cnt - _dim_ID + 1) * _num_ports_per_switch + + _dim_ID; + + } + + if (_input < 0) { + cout << " ERROR: _input less than zero " << endl; + exit(-1); + } + + + _routers[node]->AddInputChannel( _chan[_input], _chan_cred[_input] ); + } + } + + + // add INPUT channels -- "optical" channels connecting the groups + int _grp_num_routers; + int grp_output; + int grp_ID2; + + for ( int cnt = 0; cnt < _p; ++cnt ) { + // _dim_ID + grp_output = _dim_ID* _p + cnt; + + _grp_num_routers = powi(_k, _n-1); + grp_ID2 = (int) ((grp_ID - 1) / (_k - 1)); + + if ( grp_ID > grp_output) { + + _input = (grp_output) * _num_ports_per_switch * _a + // starting point of group + (_num_ports_per_switch - _p) * (int) ((grp_ID - 1) / _p) + // find the correct router within grp + (_num_ports_per_switch - _p) + // add offset within router + grp_ID - 1; + } else { + + _input = (grp_output + 1) * _num_ports_per_switch * _a + + (_num_ports_per_switch - _p) * (int) ((grp_ID) / _p) + // find the correct router within grp + (_num_ports_per_switch - _p) + + grp_ID; + } + + _routers[node]->AddInputChannel( _chan[_input], _chan_cred[_input] ); + } + + } + + cout<<"Done links"<<endl; +} + + +int DragonFlyNew::GetN( ) const +{ + return _n; +} + +int DragonFlyNew::GetK( ) const +{ + return _k; +} + +void DragonFlyNew::InsertRandomFaults( const Configuration &config ) +{ + +} + +double DragonFlyNew::Capacity( ) const +{ + return (double)_k / 8.0; +} + +void DragonFlyNew::RegisterRoutingFunctions(){ + + gRoutingFunctionMap["min_dragonflynew"] = &min_dragonflynew; + gRoutingFunctionMap["ugal_dragonflynew"] = &ugal_dragonflynew; +} + + +void min_dragonflynew( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + outputs->Clear( ); + + if(inject) { + int inject_vc= RandomInt(gNumVCs-1); + outputs->AddRange(-1, inject_vc, inject_vc); + return; + } + + int _grp_num_routers= gA; + + int dest = f->dest; + int rID = r->GetID(); + + int grp_ID = int(rID / _grp_num_routers); + int debug = f->watch; + int out_port = -1; + int out_vc = 0; + int dest_grp_ID=-1; + + if ( in_channel < gP ) { + out_vc = 0; + f->ph = 0; + if (dest_grp_ID == grp_ID) { + f->ph = 1; + } + } + + + out_port = dragonfly_port(rID, f->src, dest); + + //optical dateline + if (out_port >=gP + (gA-1)) { + f->ph = 1; + } + + out_vc = f->ph; + if (debug) + *gWatchOut << GetSimTime() << " | " << r->FullName() << " | " + << " through output port : " << out_port + << " out vc: " << out_vc << endl; + outputs->AddRange( out_port, out_vc, out_vc ); +} + + +//Basic adaptive routign algorithm for the dragonfly +void ugal_dragonflynew( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + //need 3 VCs for deadlock freedom + + assert(gNumVCs==3); + outputs->Clear( ); + if(inject) { + int inject_vc= RandomInt(gNumVCs-1); + outputs->AddRange(-1, inject_vc, inject_vc); + return; + } + + //this constant biases the adaptive decision toward minimum routing + //negative value woudl biases it towards nonminimum routing + int adaptive_threshold = 30; + + int _grp_num_routers= gA; + int _grp_num_nodes =_grp_num_routers*gP; + int _network_size = gA * gP * gG; + + + int dest = f->dest; + int rID = r->GetID(); + int grp_ID = (int) (rID / _grp_num_routers); + int dest_grp_ID = int(dest/_grp_num_nodes); + + int debug = f->watch; + int out_port = -1; + int out_vc = 0; + int min_queue_size, min_hopcnt; + int nonmin_queue_size, nonmin_hopcnt; + int intm_grp_ID; + int intm_rID; + + if(debug){ + cout<<"At router "<<rID<<endl; + } + int min_router_output, nonmin_router_output; + + //at the source router, make the adaptive routing decision + if ( in_channel < gP ) { + //dest are in the same group, only use minimum routing + if (dest_grp_ID == grp_ID) { + f->ph = 2; + } else { + //select a random node + f->intm =RandomInt(_network_size - 1); + intm_grp_ID = (int)(f->intm/_grp_num_nodes); + if (debug){ + cout<<"Intermediate node "<<f->intm<<" grp id "<<intm_grp_ID<<endl; + } + + //random intermediate are in the same group, use minimum routing + if(grp_ID == intm_grp_ID){ + f->ph = 1; + } else { + //congestion metrics using queue length, obtained by GetUsedCredit() + min_hopcnt = dragonflynew_hopcnt(f->src, f->dest); + min_router_output = dragonfly_port(rID, f->src, f->dest); + min_queue_size = max(r->GetUsedCredit(min_router_output), 0) ; + + + nonmin_hopcnt = dragonflynew_hopcnt(f->src, f->intm) + + dragonflynew_hopcnt(f->intm,f->dest); + nonmin_router_output = dragonfly_port(rID, f->src, f->intm); + nonmin_queue_size = max(r->GetUsedCredit(nonmin_router_output), 0); + + //congestion comparison, could use hopcnt instead of 1 and 2 + if ((1 * min_queue_size ) <= (2 * nonmin_queue_size)+adaptive_threshold ) { + if (debug) cout << " MINIMAL routing " << endl; + f->ph = 1; + } else { + f->ph = 0; + } + } + } + } + + //transition from nonminimal phase to minimal + if(f->ph==0){ + intm_rID= (int)(f->intm/gP); + if( rID == intm_rID){ + f->ph = 1; + } + } + + //port assignement based on the phase + if(f->ph == 0){ + out_port = dragonfly_port(rID, f->src, f->intm); + } else if(f->ph == 1){ + out_port = dragonfly_port(rID, f->src, f->dest); + } else if(f->ph == 2){ + out_port = dragonfly_port(rID, f->src, f->dest); + } else { + assert(false); + } + + //optical dateline + if (f->ph == 1 && out_port >=gP + (gA-1)) { + f->ph = 2; + } + + //vc assignemnt based on phase + out_vc = f->ph; + + outputs->AddRange( out_port, out_vc, out_vc ); +} diff --git a/src/intersim2/networks/dragonfly.hpp b/src/intersim2/networks/dragonfly.hpp new file mode 100644 index 0000000..02228ef --- /dev/null +++ b/src/intersim2/networks/dragonfly.hpp @@ -0,0 +1,74 @@ +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + + + +#ifndef _DragonFly_HPP_ +#define _DragonFly_HPP_ + +#include "network.hpp" +#include "routefunc.hpp" + +class DragonFlyNew : public Network { + + int _m; + int _n; + int _r; + int _k; + int _p, _a, _g; + int _radix; + int _net_size; + int _stageout; + int _numinput; + int _stages; + int _num_of_switch; + int _grp_num_routers; + int _grp_num_nodes; + + + void _ComputeSize( const Configuration &config ); + void _BuildNet( const Configuration &config ); + + + +public: + DragonFlyNew( const Configuration &config, const string & name ); + + int GetN( ) const; + int GetK( ) const; + + double Capacity( ) const; + static void RegisterRoutingFunctions(); + void InsertRandomFaults( const Configuration &config ); + +}; +int dragonfly_port(int rID, int source, int dest); + +void ugal_dragonflynew( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ); +void min_dragonflynew( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ); + +#endif diff --git a/src/intersim2/networks/fattree.cpp b/src/intersim2/networks/fattree.cpp new file mode 100644 index 0000000..81cd2b1 --- /dev/null +++ b/src/intersim2/networks/fattree.cpp @@ -0,0 +1,270 @@ +// $Id: fattree.cpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +//////////////////////////////////////////////////////////////////////// +// +// FatTree +// +// Each level of the hierarchical indirect Network has +// k^(n-1) Routers. The Routers are organized such that +// each node has k descendents, and each parent is +// replicated k times. +// most routers has 2K ports, excep the top level has only K +//////////////////////////////////////////////////////////////////////// +// +// RCS Information: +// $Author: jbalfour $ +// $Date: 2007/06/26 22:50:48 $ +// $Id: fattree.cpp 5188 2012-08-30 00:31:31Z dub $ +// +//////////////////////////////////////////////////////////////////////// + + +#include "booksim.hpp" +#include <vector> +#include <sstream> +#include <cmath> + +#include "fattree.hpp" +#include "misc_utils.hpp" + + + //#define FATTREE_DEBUG + +FatTree::FatTree( const Configuration& config,const string & name ) + : Network( config ,name) +{ + + + _ComputeSize( config ); + _Alloc( ); + _BuildNet( config ); + +} + +void FatTree::_ComputeSize( const Configuration& config ) +{ + + _k = config.GetInt( "k" ); + _n = config.GetInt( "n" ); + + gK = _k; gN = _n; + + _nodes = powi( _k, _n ); + + //levels * routers_per_level + _size = _n * powi( _k , _n - 1 ); + + //(channels per level = k*routers_per_level* up/down) * (levels-1) + _channels = (2*_k * powi( _k , _n-1 ))*(_n-1); + + +} + + +void FatTree::RegisterRoutingFunctions() { + +} + +void FatTree::_BuildNet( const Configuration& config ) +{ + cout << "Fat Tree" << endl; + cout << " k = " << _k << " levels = " << _n << endl; + cout << " each switch - total radix = "<< 2*_k << endl; + cout << " # of switches = "<< _size << endl; + cout << " # of channels = "<< _channels << endl; + cout << " # of nodes ( size of network ) = " << _nodes << endl; + + + // Number of router positions at each depth of the network + const int nPos = powi( _k, _n-1); + + // + // Allocate Routers + // + ostringstream name; + int level, pos, id, degree, port; + for ( level = 0 ; level < _n ; ++level ) { + for ( pos = 0 ; pos < nPos ; ++pos ) { + + if ( level == 0 ) //top routers is zero + degree = _k; + else + degree = 2 * _k; + + id = level * nPos + pos; + + name.str(""); + name << "router_level" << level << "_" << pos; + Router * r = Router::NewRouter( config, this, name.str( ), id, + degree, degree ); + _Router( level, pos ) = r; + _timed_modules.push_back(r); + } + } + + // + // Connect Channels to Routers + // + + // + // Router Connection Rule: Output Ports <gK Move DOWN Network + // Output Ports >=gK Move UP Network + // Input Ports <gK from DOWN Network + // Input Ports >=gK from up Network + + // Connecting Injection & Ejection Channels + for ( pos = 0 ; pos < nPos ; ++pos ) { + for(int index = 0; index<_k; index++){ + int link = pos*_k + index; + _Router( _n-1, pos)->AddInputChannel( _inject[link], + _inject_cred[link]); + _Router( _n-1, pos)->AddOutputChannel( _eject[link], + _eject_cred[link]); + _inject[link]->SetLatency( 1 ); + _inject_cred[link]->SetLatency( 1 ); + _eject[link]->SetLatency( 1 ); + _eject_cred[link]->SetLatency( 1 ); + } + } + +#ifdef FATTREE_DEBUG + cout<<"\nAssigning output\n"; +#endif + + //channels are numbered sequentially from an output channel perspective + int chan_per_direction = (_k * powi( _k , _n-1 )); //up or down + int chan_per_level = 2*(_k * powi( _k , _n-1 )); //up+down + + //connect all down output channels + //level n-1's down channel are injection channels + for (level = 0; level<_n-1; level++){ + for ( pos = 0; pos < nPos; ++pos ) { + for ( port = 0; port < _k; ++port ) { + int link = (level*chan_per_level) + pos*_k + port; + _Router(level, pos)->AddOutputChannel( _chan[link], + _chan_cred[link] ); + _chan[link]->SetLatency( 1 ); + _chan_cred[link]->SetLatency( 1 ); +#ifdef FATTREE_DEBUG + cout<<_Router(level, pos)->Name()<<" " + <<"down output "<<port<<" " + <<"channel_id "<<link<<endl; +#endif + + } + } + } + //connect all up output channels + //level 0 has no up chnanels + for (level = 1; level<_n; level++){ + for ( pos = 0; pos < nPos; ++pos ) { + for ( port = 0; port < _k; ++port ) { + int link = (level*chan_per_level - chan_per_direction) + pos*_k + port ; + _Router(level, pos)->AddOutputChannel( _chan[link], + _chan_cred[link] ); + _chan[link]->SetLatency( 1 ); + _chan_cred[link]->SetLatency( 1 ); +#ifdef FATTREE_DEBUG + cout<<_Router(level, pos)->Name()<<" " + <<"up output "<<port<<" " + <<"channel_id "<<link<<endl; +#endif + } + } + } + +#ifdef FATTREE_DEBUG + cout<<"\nAssigning Input\n"; +#endif + + //connect all down input channels + for (level = 0; level<_n-1; level++){ + //input channel are numbered interleavely, the interleaev depends on level + int routers_per_neighborhood = powi(_k,_n-1-(level)); + int routers_per_branch = powi(_k,_n-1-(level+1)); + int level_offset = routers_per_neighborhood*_k; + for ( pos = 0; pos < nPos; ++pos ) { + int neighborhood = pos/routers_per_neighborhood; + int neighborhood_pos = pos%routers_per_neighborhood; + for ( port = 0; port < _k; ++port ) { + int link = + ((level+1)*chan_per_level - chan_per_direction) //which levellevel + +neighborhood*level_offset //region in level + +port*routers_per_branch*gK //sub region in region + +(neighborhood_pos)%routers_per_branch*gK //router in subregion + +(neighborhood_pos)/routers_per_branch; //port on router + + _Router(level, pos)->AddInputChannel( _chan[link], + _chan_cred[link] ); +#ifdef FATTREE_DEBUG + cout<<_Router(level, pos)->Name()<<" " + <<"down input "<<port<<" " + <<"channel_id "<<link<<endl; +#endif + } + } + } + + + //connect all up input channels + for (level = 1; level<_n; level++){ + //input channel are numbered interleavely, the interleaev depends on level + int routers_per_neighborhood = powi(_k,_n-1-(level-1)); + int routers_per_branch = powi(_k,_n-1-(level)); + int level_offset = routers_per_neighborhood*_k; + for ( pos = 0; pos < nPos; ++pos ) { + int neighborhood = pos/routers_per_neighborhood; + int neighborhood_pos = pos%routers_per_neighborhood; + for ( port = 0; port < _k; ++port ) { + int link = + ((level-1)*chan_per_level) //which levellevel + +neighborhood*level_offset //region in level + +port*routers_per_branch*gK //sub region in region + +(neighborhood_pos)%routers_per_branch*gK //router in subregion + +(neighborhood_pos)/routers_per_branch; //port on router + + _Router(level, pos)->AddInputChannel( _chan[link], + _chan_cred[link] ); +#ifdef FATTREE_DEBUG + cout<<_Router(level, pos)->Name()<<" " + <<"up input "<<port<<" " + <<"channel_id "<<link<<endl; +#endif + } + } + } +#ifdef FATTREE_DEBUG + cout<<"\nChannel assigned\n"; +#endif +} + +Router*& FatTree::_Router( int depth, int pos ) +{ + assert( depth < _n && pos < powi( _k, _n-1) ); + return _routers[depth * powi( _k, _n-1) + pos]; +} diff --git a/src/intersim2/networks/fattree.hpp b/src/intersim2/networks/fattree.hpp new file mode 100644 index 0000000..e537e5a --- /dev/null +++ b/src/intersim2/networks/fattree.hpp @@ -0,0 +1,76 @@ +// $Id: fattree.hpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +//////////////////////////////////////////////////////////////////////// +// +// FatTree +// +//////////////////////////////////////////////////////////////////////// +// +// RCS Information: +// $Author: jbalfour $ +// $Date: 2007/06/26 22:49:23 $ +// $Id: fattree.hpp 5188 2012-08-30 00:31:31Z dub $ +// +//////////////////////////////////////////////////////////////////////// + +#ifndef _FatTree_HPP_ +#define _FatTree_HPP_ + +#include "network.hpp" + +class FatTree : public Network { + + int _k; + int _n; + + + void _ComputeSize( const Configuration& config ); + void _BuildNet( const Configuration& config ); + + Router*& _Router( int depth, int pos ); + + int _mapSize; + int* _inputChannelMap; + int* _outputChannelMap; + int* _latencyMap; + + + +public: + + FatTree( const Configuration& config ,const string & name ); + static void RegisterRoutingFunctions() ; + + // + // Methods to Assit Routing Functions + // + static int PreferedPort( const Router* r, int index ); + +}; + +#endif diff --git a/src/intersim2/networks/flatfly_onchip.cpp b/src/intersim2/networks/flatfly_onchip.cpp new file mode 100644 index 0000000..fd17c1a --- /dev/null +++ b/src/intersim2/networks/flatfly_onchip.cpp @@ -0,0 +1,1331 @@ +// $Id: flatfly_onchip.cpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +//Flattened butterfly simulator +//Created by John Kim +// +//Updated 11/6/2007 by Ted Jiang, now scales +//with any n such that N = K^3, k is a power of 2 +//however, the change restrict it to a 2D FBfly +// +//updated sometimes in december by Ted Jiang, now works for updat to 4 +//dimension. +// +//Updated 2/4/08 by Ted Jiang disabling partial networks +//change concentrations +// +//More update 3/31/08 to correctly assign the nodes to the routers +//UGAL now has added a "mapping" to account for this new assignment +//of the nodes to the routers +// +//Updated by mihelog 27 Aug to add progressive choice of intermediate destination. +//Also, half of the total vcs are used for non-minimal routing, others for minimal (for UGAL and valiant). + + +#include "booksim.hpp" +#include <vector> +#include <sstream> +#include <limits> +#include <cmath> +#include "flatfly_onchip.hpp" +#include "random_utils.hpp" +#include "misc_utils.hpp" +#include "globals.hpp" + + + +//#define DEBUG_FLATFLY + +static int _xcount; +static int _ycount; +static int _xrouter; +static int _yrouter; + +FlatFlyOnChip::FlatFlyOnChip( const Configuration &config, const string & name ) : + Network( config, name ) +{ + + _ComputeSize( config ); + _Alloc( ); + _BuildNet( config ); +} + +void FlatFlyOnChip::_ComputeSize( const Configuration &config ) +{ + _k = config.GetInt( "k" ); // # of routers per dimension + _n = config.GetInt( "n" ); // dimension + _c = config.GetInt( "c" ); //concentration, may be different from k + _r = _c + (_k-1)*_n ; // total radix of the switch ( # of inputs/outputs) + + //how many routers in the x or y direction + _xcount = config.GetInt("x"); + _ycount = config.GetInt("y"); + assert(_xcount == _ycount); + //configuration of hohw many clients in X and Y per router + _xrouter = config.GetInt("xr"); + _yrouter = config.GetInt("yr"); + assert(_xrouter == _yrouter); + gK = _k; + gN = _n; + gC = _c; + + assert(_c == _xrouter*_yrouter); + + _nodes = powi( _k, _n )*_c; //network size + + _num_of_switch = _nodes / _c; + _channels = _num_of_switch * (_r - _c); + _size = _num_of_switch; + +} + +void FlatFlyOnChip::_BuildNet( const Configuration &config ) +{ + int _output; + + ostringstream router_name; + + + if(gTrace){ + + cout<<"Setup Finished Router"<<endl; + + } + + //latency type, noc or conventional network + bool use_noc_latency; + use_noc_latency = (config.GetInt("use_noc_latency")==1); + + cout << " Flat Bufferfly " << endl; + cout << " k = " << _k << " n = " << _n << " c = "<<_c<< endl; + cout << " each switch - total radix = "<< _r << endl; + cout << " # of switches = "<< _num_of_switch << endl; + cout << " # of channels = "<< _channels << endl; + cout << " # of nodes ( size of network ) = " << _nodes << endl; + + for ( int node = 0; node < _num_of_switch; ++node ) { + + router_name << "router"; + router_name << "_" << node ; + + _routers[node] = Router::NewRouter( config, this, router_name.str( ), + node, _r, _r ); + _timed_modules.push_back(_routers[node]); + + +#ifdef DEBUG_FLATFLY + cout << " ======== router node : " << node << " ======== " << " router_" << router_name.str() << " router node # : " << node << endl; +#endif + + router_name.str(""); + + //****************************************************************** + // add inject/eject channels connected to the processor nodes + //****************************************************************** + + //as accurately model the length of these channels as possible + int yleng = -_yrouter/2; + int xleng = -_xrouter/2; + bool yodd = _yrouter%2==1; + bool xodd = _xrouter%2==1; + + int y_index = node/(_xcount); + int x_index = node%(_xcount); + //estimating distance from client to router + for (int y = 0; y < _yrouter ; y++) { + for (int x = 0; x < _xrouter ; x++) { + //Zero is a naughty number + if(yleng == 0 && !yodd){ + yleng++; + } + if(xleng == 0 && !xodd){ + xleng++; + } + int ileng = 1; //at least 1 away + //measure distance in the y direction + if(abs(yleng)>1){ + ileng+=(abs(yleng)-1); + } + //measure distance in the x direction + if(abs(xleng)>1){ + ileng+=(abs(xleng)-1); + } + //increment for the next client, add Y, if full, reset y add x + yleng++; + if(yleng>_yrouter/2){ + yleng= -_yrouter/2; + xleng++; + } + //adopted from the CMESH, the first node has 0,1,8,9 (as an example) + int link = (_xcount * _xrouter) * (_yrouter * y_index + y) + (_xrouter * x_index + x) ; + + if(use_noc_latency){ + _inject[link]->SetLatency(ileng); + _inject_cred[link]->SetLatency(ileng); + _eject[link] ->SetLatency(ileng); + _eject_cred[link]->SetLatency(ileng); + } else { + _inject[link]->SetLatency(1); + _inject_cred[link]->SetLatency(1); + _eject[link] ->SetLatency(1); + _eject_cred[link]->SetLatency(1); + } + _routers[node]->AddInputChannel( _inject[link], _inject_cred[link] ); + +#ifdef DEBUG_FLATFLY + cout << " Adding injection channel " << link << endl; +#endif + + _routers[node]->AddOutputChannel( _eject[link], _eject_cred[link] ); +#ifdef DEBUG_FLATFLY + cout << " Adding ejection channel " << link << endl; +#endif + } + } + } + //****************************************************************** + // add output inter-router channels + //****************************************************************** + + //for every router, in every dimension + for ( int node = 0; node < _num_of_switch; ++node ) { + for ( int dim = 0; dim < _n; ++dim ) { + + //locate itself in every dimension + int xcurr = node%_k; + int ycurr = (int)(node/_k); + int curr3 = node%(_k*_k); + int curr4 = (int)(node/(_k*_k)); + int curr5 = (int)(node/(_k*_k*_k));//mmm didn't mean to be racist + int curr6 = (node%(_k*_k*_k));//mmm didn't mean to be racist + + //for every other router in the dimension + for ( int cnt = 0; cnt < (_k ); ++cnt ) { + int other=0; //the other router that we are trying to connect + int offset = 0; //silly ness when node< other or when node>other + //if xdimension + if(dim == 0){ + other = ycurr * _k +cnt; + } else if (dim ==1){ + other = cnt * _k + xcurr; + if(_n==3){ + other+= curr4*_k*_k; + } + if(_n==4){ + curr4=((int)(node/(_k*_k)))%_k; + other+= curr4*_k*_k+curr5*_k*_k*_k; + } + }else if (dim ==2){ + other = cnt*_k*_k + curr3; + if(_n==4){ + other+= curr5*_k*_k*_k; + } + }else if (dim ==3){ + other = cnt*_k*_k*_k+curr6; + } + assert(dim < 4); + if(other == node){ +#ifdef DEBUG_FLATFLY + cout << "ignore channel : " << _output << " to node " << node <<" and "<<other<<endl; +#endif + continue; + } + //calculate channel length + int length = 0; + int oned = abs((node%_xcount)-(other%_xcount)); + int twod = abs(node/_xcount-other/_xcount); + length = _xrouter*oned + _yrouter *twod; + //oh the node<other silly ness + if(node<other){ + offset = -1; + } + //node, dimension, router within dimension. Good luck understanding this + _output = (_k-1) * _n * node + (_k-1) * dim + cnt+offset; + + +#ifdef DEBUG_FLATFLY + cout << "Adding channel : " << _output << " to node " << node <<" and "<<other<<" with length "<<length<<endl; +#endif + if(use_noc_latency){ + _chan[_output]->SetLatency(length); + _chan_cred[_output]->SetLatency(length); + } else { + _chan[_output]->SetLatency(1); + _chan_cred[_output]->SetLatency(1); + } + _routers[node]->AddOutputChannel( _chan[_output], _chan_cred[_output] ); + + _routers[other]->AddInputChannel( _chan[_output], _chan_cred[_output]); + + if(gTrace){ + cout<<"Link "<<_output<<" "<<node<<" "<<other<<" "<<length<<endl; + } + + } + } + } + if(gTrace){ + cout<<"Setup Finished Link"<<endl; + } +} + + +int FlatFlyOnChip::GetN( ) const +{ + return _n; +} + +int FlatFlyOnChip::GetK( ) const +{ + return _k; +} + +void FlatFlyOnChip::InsertRandomFaults( const Configuration &config ) +{ + +} + +double FlatFlyOnChip::Capacity( ) const +{ + return (double)_k / 8.0; +} + + +void FlatFlyOnChip::RegisterRoutingFunctions(){ + + + gRoutingFunctionMap["ran_min_flatfly"] = &min_flatfly; + gRoutingFunctionMap["adaptive_xyyx_flatfly"] = &adaptive_xyyx_flatfly; + gRoutingFunctionMap["xyyx_flatfly"] = &xyyx_flatfly; + gRoutingFunctionMap["valiant_flatfly"] = &valiant_flatfly; + gRoutingFunctionMap["ugal_flatfly"] = &ugal_flatfly_onchip; + gRoutingFunctionMap["ugal_pni_flatfly"] = &ugal_pni_flatfly_onchip; + gRoutingFunctionMap["ugal_xyyx_flatfly"] = &ugal_xyyx_flatfly_onchip; + +} + +//The initial XY or YX minimal routing direction is chosen adaptively +void adaptive_xyyx_flatfly( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + // ( Traffic Class , Routing Order ) -> Virtual Channel Range + int vcBegin = 0, vcEnd = gNumVCs-1; + if ( f->type == Flit::READ_REQUEST ) { + vcBegin = gReadReqBeginVC; + vcEnd = gReadReqEndVC; + } else if ( f->type == Flit::WRITE_REQUEST ) { + vcBegin = gWriteReqBeginVC; + vcEnd = gWriteReqEndVC; + } else if ( f->type == Flit::READ_REPLY ) { + vcBegin = gReadReplyBeginVC; + vcEnd = gReadReplyEndVC; + } else if ( f->type == Flit::WRITE_REPLY ) { + vcBegin = gWriteReplyBeginVC; + vcEnd = gWriteReplyEndVC; + } + assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0))); + + int out_port; + + if(inject) { + + out_port = -1; + + } else { + + int dest = flatfly_transformation(f->dest); + int targetr = (int)(dest/gC); + + if(targetr==r->GetID()){ //if we are at the final router, yay, output to client + out_port = dest % gC; + + } else { + + //each class must have at least 2 vcs assigned or else xy_yx will deadlock + int const available_vcs = (vcEnd - vcBegin + 1) / 2; + assert(available_vcs > 0); + + int out_port_xy = flatfly_outport(dest, r->GetID()); + int out_port_yx = flatfly_outport_yx(dest, r->GetID()); + + // Route order (XY or YX) determined when packet is injected + // into the network, adaptively + bool x_then_y; + if(in_channel < gC){ + int credit_xy = r->GetUsedCredit(out_port_xy); + int credit_yx = r->GetUsedCredit(out_port_yx); + if(credit_xy > credit_yx) { + x_then_y = false; + } else if(credit_xy < credit_yx) { + x_then_y = true; + } else { + x_then_y = (RandomInt(1) > 0); + } + } else { + x_then_y = (f->vc < (vcBegin + available_vcs)); + } + + if(x_then_y) { + out_port = out_port_xy; + vcEnd -= available_vcs; + } else { + out_port = out_port_yx; + vcBegin += available_vcs; + } + } + + } + + outputs->Clear( ); + + outputs->AddRange( out_port , vcBegin, vcEnd ); +} + +//The initial XY or YX minimal routing direction is chosen randomly +void xyyx_flatfly( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + // ( Traffic Class , Routing Order ) -> Virtual Channel Range + int vcBegin = 0, vcEnd = gNumVCs-1; + if ( f->type == Flit::READ_REQUEST ) { + vcBegin = gReadReqBeginVC; + vcEnd = gReadReqEndVC; + } else if ( f->type == Flit::WRITE_REQUEST ) { + vcBegin = gWriteReqBeginVC; + vcEnd = gWriteReqEndVC; + } else if ( f->type == Flit::READ_REPLY ) { + vcBegin = gReadReplyBeginVC; + vcEnd = gReadReplyEndVC; + } else if ( f->type == Flit::WRITE_REPLY ) { + vcBegin = gWriteReplyBeginVC; + vcEnd = gWriteReplyEndVC; + } + assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0))); + + int out_port; + + if(inject) { + + out_port = -1; + + } else { + + int dest = flatfly_transformation(f->dest); + int targetr = (int)(dest/gC); + + if(targetr==r->GetID()){ //if we are at the final router, yay, output to client + out_port = dest % gC; + + } else { + + //each class must have at least 2 vcs assigned or else xy_yx will deadlock + int const available_vcs = (vcEnd - vcBegin + 1) / 2; + assert(available_vcs > 0); + + // randomly select dimension order at first hop + bool x_then_y = ((in_channel < gC) ? + (RandomInt(1) > 0) : + (f->vc < (vcBegin + available_vcs))); + + if(x_then_y) { + out_port = flatfly_outport(dest, r->GetID()); + vcEnd -= available_vcs; + } else { + out_port = flatfly_outport_yx(dest, r->GetID()); + vcBegin += available_vcs; + } + } + + } + + outputs->Clear( ); + + outputs->AddRange( out_port , vcBegin, vcEnd ); +} + +int flatfly_outport_yx(int dest, int rID) { + int dest_rID = (int) (dest / gC); + int _dim = gN; + int output = -1, dID, sID; + + if(dest_rID==rID){ + return dest % gC; + } + + for (int d=_dim-1;d >= 0; d--) { + int power = powi(gK,d); + dID = int(dest_rID / power); + sID = int(rID / power); + if ( dID != sID ) { + output = gC + ((gK-1)*d) - 1; + if (dID > sID) { + output += dID; + } else { + output += dID + 1; + } + return output; + } + dest_rID = (int) (dest_rID %power); + rID = (int) (rID %power); + } + if (output == -1) { + cout << " ERROR ---- FLATFLY_OUTPORT function : output not found yx" << endl; + exit(-1); + } + return -1; +} + +void valiant_flatfly( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + // ( Traffic Class , Routing Order ) -> Virtual Channel Range + int vcBegin = 0, vcEnd = gNumVCs-1; + if ( f->type == Flit::READ_REQUEST ) { + vcBegin = gReadReqBeginVC; + vcEnd = gReadReqEndVC; + } else if ( f->type == Flit::WRITE_REQUEST ) { + vcBegin = gWriteReqBeginVC; + vcEnd = gWriteReqEndVC; + } else if ( f->type == Flit::READ_REPLY ) { + vcBegin = gReadReplyBeginVC; + vcEnd = gReadReplyEndVC; + } else if ( f->type == Flit::WRITE_REPLY ) { + vcBegin = gWriteReplyBeginVC; + vcEnd = gWriteReplyEndVC; + } + assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0))); + + int out_port; + + if(inject) { + + out_port = -1; + + } else { + + if ( in_channel < gC ){ + f->ph = 0; + f->intm = RandomInt( powi( gK, gN )*gC-1); + } + + int intm = flatfly_transformation(f->intm); + int dest = flatfly_transformation(f->dest); + + if((int)(intm/gC) == r->GetID() || (int)(dest/gC)== r->GetID()){ + f->ph = 1; + } + + if(f->ph == 0) { + out_port = flatfly_outport(intm, r->GetID()); + } else { + assert(f->ph == 1); + out_port = flatfly_outport(dest, r->GetID()); + } + + if((int)(dest/gC) != r->GetID()) { + + //each class must have at least 2 vcs assigned or else valiant valiant will deadlock + int const available_vcs = (vcEnd - vcBegin + 1) / 2; + assert(available_vcs > 0); + + if(f->ph == 0) { + vcEnd -= available_vcs; + } else { + // If routing to final destination use the second half of the VCs. + assert(f->ph == 1); + vcBegin += available_vcs; + } + } + + } + + outputs->Clear( ); + + outputs->AddRange( out_port , vcBegin, vcEnd ); +} + +void min_flatfly( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + // ( Traffic Class , Routing Order ) -> Virtual Channel Range + int vcBegin = 0, vcEnd = gNumVCs-1; + if ( f->type == Flit::READ_REQUEST ) { + vcBegin = gReadReqBeginVC; + vcEnd = gReadReqEndVC; + } else if ( f->type == Flit::WRITE_REQUEST ) { + vcBegin = gWriteReqBeginVC; + vcEnd = gWriteReqEndVC; + } else if ( f->type == Flit::READ_REPLY ) { + vcBegin = gReadReplyBeginVC; + vcEnd = gReadReplyEndVC; + } else if ( f->type == Flit::WRITE_REPLY ) { + vcBegin = gWriteReplyBeginVC; + vcEnd = gWriteReplyEndVC; + } + assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0))); + + int out_port; + + if(inject) { + + out_port = -1; + + } else { + + int dest = flatfly_transformation(f->dest); + int targetr= (int)(dest/gC); + //int xdest = ((int)(dest/gC)) % gK; + //int xcurr = ((r->GetID())) % gK; + + //int ydest = ((int)(dest/gC)) / gK; + //int ycurr = ((r->GetID())) / gK; + + if(targetr==r->GetID()){ //if we are at the final router, yay, output to client + out_port = dest % gC; + } else{ //else select a dimension at random + out_port = flatfly_outport(dest, r->GetID()); + } + + } + + outputs->Clear( ); + + outputs->AddRange( out_port , vcBegin, vcEnd ); +} + +//=============================================================^M +// route UGAL in the flattened butterfly +//=============================================================^M + + +//same as ugal except uses xyyx routing +void ugal_xyyx_flatfly_onchip( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + // ( Traffic Class , Routing Order ) -> Virtual Channel Range + int vcBegin = 0, vcEnd = gNumVCs-1; + if ( f->type == Flit::READ_REQUEST ) { + vcBegin = gReadReqBeginVC; + vcEnd = gReadReqEndVC; + } else if ( f->type == Flit::WRITE_REQUEST ) { + vcBegin = gWriteReqBeginVC; + vcEnd = gWriteReqEndVC; + } else if ( f->type == Flit::READ_REPLY ) { + vcBegin = gReadReplyBeginVC; + vcEnd = gReadReplyEndVC; + } else if ( f->type == Flit::WRITE_REPLY ) { + vcBegin = gWriteReplyBeginVC; + vcEnd = gWriteReplyEndVC; + } + assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0))); + + int out_port; + + if(inject) { + + out_port = -1; + + } else { + + int dest = flatfly_transformation(f->dest); + + int rID = r->GetID(); + int _concentration = gC; + int found; + int debug = 0; + int tmp_out_port, _ran_intm; + int _min_hop, _nonmin_hop, _min_queucnt, _nonmin_queucnt; + int threshold = 2; + + + if ( in_channel < gC ){ + if(gTrace){ + cout<<"New Flit "<<f->src<<endl; + } + f->ph = 0; + } + + if(gTrace){ + int load = 0; + cout<<"Router "<<rID<<endl; + cout<<"Input Channel "<<in_channel<<endl; + //need to modify router to report the buffere depth + load +=r->GetBufferOccupancy(in_channel); + cout<<"Rload "<<load<<endl; + } + + if (debug){ + cout << " FLIT ID: " << f->id << " Router: " << rID << " routing from src : " << f->src << " to dest : " << dest << " f->ph: " <<f->ph << " intm: " << f->intm << endl; + } + // f->ph == 0 ==> make initial global adaptive decision + // f->ph == 1 ==> route nonminimaly to random intermediate node + // f->ph == 2 ==> route minimally to destination + + found = 0; + + if (f->ph == 1){ + dest = f->intm; + } + + if (dest >= rID*_concentration && dest < (rID+1)*_concentration) { + if (f->ph == 1) { + f->ph = 2; + dest = flatfly_transformation(f->dest); + if (debug) cout << " done routing to intermediate "; + } + else { + found = 1; + out_port = dest % gC; + if (debug) cout << " final routing to destination "; + } + } + + if (!found) { + + int const xy_available_vcs = (vcEnd - vcBegin + 1) / 2; + assert(xy_available_vcs > 0); + + // randomly select dimension order at first hop + bool x_then_y = ((in_channel < gC) ? + (RandomInt(1) > 0) : + (f->vc < (vcBegin + xy_available_vcs))); + + if (f->ph == 0) { + //find the min port and min distance + _min_hop = find_distance(flatfly_transformation(f->src),dest); + if(x_then_y){ + tmp_out_port = flatfly_outport(dest, rID); + } else { + tmp_out_port = flatfly_outport_yx(dest, rID); + } + if (f->watch){ + cout << " MIN tmp_out_port: " << tmp_out_port; + } + //sum over all vcs of that port + _min_queucnt = r->GetUsedCredit(tmp_out_port); + + //find the nonmin router, nonmin port, nonmin count + _ran_intm = find_ran_intm(flatfly_transformation(f->src), dest); + _nonmin_hop = find_distance(flatfly_transformation(f->src),_ran_intm) + find_distance(_ran_intm, dest); + if(x_then_y){ + tmp_out_port = flatfly_outport(_ran_intm, rID); + } else { + tmp_out_port = flatfly_outport_yx(_ran_intm, rID); + } + + if (f->watch){ + cout << " NONMIN tmp_out_port: " << tmp_out_port << endl; + } + if (_ran_intm >= rID*_concentration && _ran_intm < (rID+1)*_concentration) { + _nonmin_queucnt = numeric_limits<int>::max(); + } else { + _nonmin_queucnt = r->GetUsedCredit(tmp_out_port); + } + + if (debug){ + cout << " _min_hop " << _min_hop << " _min_queucnt: " <<_min_queucnt << " _nonmin_hop: " << _nonmin_hop << " _nonmin_queucnt :" << _nonmin_queucnt << endl; + } + + if (_min_hop * _min_queucnt <= _nonmin_hop * _nonmin_queucnt +threshold) { + + if (debug) cout << " Route MINIMALLY " << endl; + f->ph = 2; + } else { + // route non-minimally + if (debug) { cout << " Route NONMINIMALLY int node: " <<_ran_intm << endl; } + f->ph = 1; + f->intm = _ran_intm; + dest = f->intm; + if (dest >= rID*_concentration && dest < (rID+1)*_concentration) { + f->ph = 2; + dest = flatfly_transformation(f->dest); + } + } + } + + //dest here should be == intm if ph==1, or dest == dest if ph == 2 + if(x_then_y){ + out_port = flatfly_outport(dest, rID); + if(out_port >= gC) { + vcEnd -= xy_available_vcs; + } + } else { + out_port = flatfly_outport_yx(dest, rID); + if(out_port >= gC) { + vcBegin += xy_available_vcs; + } + } + + // if we haven't reached our destination, restrict VCs appropriately to avoid routing deadlock + if(out_port >= gC) { + + int const ph_available_vcs = xy_available_vcs / 2; + assert(ph_available_vcs > 0); + + if(f->ph == 1) { + vcEnd -= ph_available_vcs; + } else { + assert(f->ph == 2); + vcBegin += ph_available_vcs; + } + } + + found = 1; + } + + if (!found) { + cout << " ERROR: output not found in routing. " << endl; + cout << *f; exit (-1); + } + + if (out_port >= gN*(gK-1) + gC) { + cout << " ERROR: output port too big! " << endl; + cout << " OUTPUT select: " << out_port << endl; + cout << " router radix: " << gN*(gK-1) + gK << endl; + exit (-1); + } + + if (debug) cout << " through output port : " << out_port << endl; + if(gTrace){cout<<"Outport "<<out_port<<endl;cout<<"Stop Mark"<<endl;} + + } + + outputs->Clear( ); + + outputs->AddRange( out_port , vcBegin, vcEnd ); +} + + + +//ugal now uses modified comparison, modefied getcredit +void ugal_flatfly_onchip( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + // ( Traffic Class , Routing Order ) -> Virtual Channel Range + int vcBegin = 0, vcEnd = gNumVCs-1; + if ( f->type == Flit::READ_REQUEST ) { + vcBegin = gReadReqBeginVC; + vcEnd = gReadReqEndVC; + } else if ( f->type == Flit::WRITE_REQUEST ) { + vcBegin = gWriteReqBeginVC; + vcEnd = gWriteReqEndVC; + } else if ( f->type == Flit::READ_REPLY ) { + vcBegin = gReadReplyBeginVC; + vcEnd = gReadReplyEndVC; + } else if ( f->type == Flit::WRITE_REPLY ) { + vcBegin = gWriteReplyBeginVC; + vcEnd = gWriteReplyEndVC; + } + assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0))); + + int out_port; + + if(inject) { + + out_port = -1; + + } else { + + int dest = flatfly_transformation(f->dest); + + int rID = r->GetID(); + int _concentration = gC; + int found; + int debug = 0; + int tmp_out_port, _ran_intm; + int _min_hop, _nonmin_hop, _min_queucnt, _nonmin_queucnt; + int threshold = 2; + + if ( in_channel < gC ){ + if(gTrace){ + cout<<"New Flit "<<f->src<<endl; + } + f->ph = 0; + } + + if(gTrace){ + int load = 0; + cout<<"Router "<<rID<<endl; + cout<<"Input Channel "<<in_channel<<endl; + //need to modify router to report the buffere depth + load +=r->GetBufferOccupancy(in_channel); + cout<<"Rload "<<load<<endl; + } + + if (debug){ + cout << " FLIT ID: " << f->id << " Router: " << rID << " routing from src : " << f->src << " to dest : " << dest << " f->ph: " <<f->ph << " intm: " << f->intm << endl; + } + // f->ph == 0 ==> make initial global adaptive decision + // f->ph == 1 ==> route nonminimaly to random intermediate node + // f->ph == 2 ==> route minimally to destination + + found = 0; + + if (f->ph == 1){ + dest = f->intm; + } + + + if (dest >= rID*_concentration && dest < (rID+1)*_concentration) { + + if (f->ph == 1) { + f->ph = 2; + dest = flatfly_transformation(f->dest); + if (debug) cout << " done routing to intermediate "; + } + else { + found = 1; + out_port = dest % gC; + if (debug) cout << " final routing to destination "; + } + } + + if (!found) { + + if (f->ph == 0) { + _min_hop = find_distance(flatfly_transformation(f->src),dest); + _ran_intm = find_ran_intm(flatfly_transformation(f->src), dest); + tmp_out_port = flatfly_outport(dest, rID); + if (f->watch){ + *gWatchOut << GetSimTime() << " | " << r->FullName() << " | " + << " MIN tmp_out_port: " << tmp_out_port; + } + + _min_queucnt = r->GetUsedCredit(tmp_out_port); + + _nonmin_hop = find_distance(flatfly_transformation(f->src),_ran_intm) + find_distance(_ran_intm, dest); + tmp_out_port = flatfly_outport(_ran_intm, rID); + + if (f->watch){ + *gWatchOut << GetSimTime() << " | " << r->FullName() << " | " + << " NONMIN tmp_out_port: " << tmp_out_port << endl; + } + if (_ran_intm >= rID*_concentration && _ran_intm < (rID+1)*_concentration) { + _nonmin_queucnt = numeric_limits<int>::max(); + } else { + _nonmin_queucnt = r->GetUsedCredit(tmp_out_port); + } + + if (debug){ + cout << " _min_hop " << _min_hop << " _min_queucnt: " <<_min_queucnt << " _nonmin_hop: " << _nonmin_hop << " _nonmin_queucnt :" << _nonmin_queucnt << endl; + } + + if (_min_hop * _min_queucnt <= _nonmin_hop * _nonmin_queucnt +threshold) { + + if (debug) cout << " Route MINIMALLY " << endl; + f->ph = 2; + } else { + // route non-minimally + if (debug) { cout << " Route NONMINIMALLY int node: " <<_ran_intm << endl; } + f->ph = 1; + f->intm = _ran_intm; + dest = f->intm; + if (dest >= rID*_concentration && dest < (rID+1)*_concentration) { + f->ph = 2; + dest = flatfly_transformation(f->dest); + } + } + } + + // find minimal correct dimension to route through + out_port = flatfly_outport(dest, rID); + + // if we haven't reached our destination, restrict VCs appropriately to avoid routing deadlock + if(out_port >= gC) { + int const available_vcs = (vcEnd - vcBegin + 1) / 2; + assert(available_vcs > 0); + if(f->ph == 1) { + vcEnd -= available_vcs; + } else { + assert(f->ph == 2); + vcBegin += available_vcs; + } + } + + found = 1; + } + + if (!found) { + cout << " ERROR: output not found in routing. " << endl; + cout << *f; exit (-1); + } + + if (out_port >= gN*(gK-1) + gC) { + cout << " ERROR: output port too big! " << endl; + cout << " OUTPUT select: " << out_port << endl; + cout << " router radix: " << gN*(gK-1) + gK << endl; + exit (-1); + } + + if (debug) cout << " through output port : " << out_port << endl; + if(gTrace) { + cout<<"Outport "<<out_port<<endl; + cout<<"Stop Mark"<<endl; + } + } + + outputs->Clear( ); + + outputs->AddRange( out_port , vcBegin, vcEnd ); +} + + +// partially non-interfering (i.e., packets ordered by hash of destination) UGAL +void ugal_pni_flatfly_onchip( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ) +{ + // ( Traffic Class , Routing Order ) -> Virtual Channel Range + int vcBegin = 0, vcEnd = gNumVCs-1; + if ( f->type == Flit::READ_REQUEST ) { + vcBegin = gReadReqBeginVC; + vcEnd = gReadReqEndVC; + } else if ( f->type == Flit::WRITE_REQUEST ) { + vcBegin = gWriteReqBeginVC; + vcEnd = gWriteReqEndVC; + } else if ( f->type == Flit::READ_REPLY ) { + vcBegin = gReadReplyBeginVC; + vcEnd = gReadReplyEndVC; + } else if ( f->type == Flit::WRITE_REPLY ) { + vcBegin = gWriteReplyBeginVC; + vcEnd = gWriteReplyEndVC; + } + assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0))); + + int out_port; + + if(inject) { + + out_port = -1; + + } else { + + int dest = flatfly_transformation(f->dest); + + int rID = r->GetID(); + int _concentration = gC; + int found; + int debug = 0; + int tmp_out_port, _ran_intm; + int _min_hop, _nonmin_hop, _min_queucnt, _nonmin_queucnt; + int threshold = 2; + + if ( in_channel < gC ){ + if(gTrace){ + cout<<"New Flit "<<f->src<<endl; + } + f->ph = 0; + } + + if(gTrace){ + int load = 0; + cout<<"Router "<<rID<<endl; + cout<<"Input Channel "<<in_channel<<endl; + //need to modify router to report the buffere depth + load +=r->GetBufferOccupancy(in_channel); + cout<<"Rload "<<load<<endl; + } + + if (debug){ + cout << " FLIT ID: " << f->id << " Router: " << rID << " routing from src : " << f->src << " to dest : " << dest << " f->ph: " <<f->ph << " intm: " << f->intm << endl; + } + // f->ph == 0 ==> make initial global adaptive decision + // f->ph == 1 ==> route nonminimaly to random intermediate node + // f->ph == 2 ==> route minimally to destination + + found = 0; + + if (f->ph == 1){ + dest = f->intm; + } + + + if (dest >= rID*_concentration && dest < (rID+1)*_concentration) { + + if (f->ph == 1) { + f->ph = 2; + dest = flatfly_transformation(f->dest); + if (debug) cout << " done routing to intermediate "; + } + else { + found = 1; + out_port = dest % gC; + if (debug) cout << " final routing to destination "; + } + } + + if (!found) { + + if (f->ph == 0) { + _min_hop = find_distance(flatfly_transformation(f->src),dest); + _ran_intm = find_ran_intm(flatfly_transformation(f->src), dest); + tmp_out_port = flatfly_outport(dest, rID); + if (f->watch){ + *gWatchOut << GetSimTime() << " | " << r->FullName() << " | " + << " MIN tmp_out_port: " << tmp_out_port; + } + + _min_queucnt = r->GetUsedCredit(tmp_out_port); + + _nonmin_hop = find_distance(flatfly_transformation(f->src),_ran_intm) + find_distance(_ran_intm, dest); + tmp_out_port = flatfly_outport(_ran_intm, rID); + + if (f->watch){ + *gWatchOut << GetSimTime() << " | " << r->FullName() << " | " + << " NONMIN tmp_out_port: " << tmp_out_port << endl; + } + if (_ran_intm >= rID*_concentration && _ran_intm < (rID+1)*_concentration) { + _nonmin_queucnt = numeric_limits<int>::max(); + } else { + _nonmin_queucnt = r->GetUsedCredit(tmp_out_port); + } + + if (debug){ + cout << " _min_hop " << _min_hop << " _min_queucnt: " <<_min_queucnt << " _nonmin_hop: " << _nonmin_hop << " _nonmin_queucnt :" << _nonmin_queucnt << endl; + } + + if (_min_hop * _min_queucnt <= _nonmin_hop * _nonmin_queucnt +threshold) { + + if (debug) cout << " Route MINIMALLY " << endl; + f->ph = 2; + } else { + // route non-minimally + if (debug) { cout << " Route NONMINIMALLY int node: " <<_ran_intm << endl; } + f->ph = 1; + f->intm = _ran_intm; + dest = f->intm; + if (dest >= rID*_concentration && dest < (rID+1)*_concentration) { + f->ph = 2; + dest = flatfly_transformation(f->dest); + } + } + } + + // find minimal correct dimension to route through + out_port = flatfly_outport(dest, rID); + + // if we haven't reached our destination, restrict VCs appropriately to avoid routing deadlock + if(out_port >= gC) { + int const available_vcs = (vcEnd - vcBegin + 1) / 2; + assert(available_vcs > 0); + if(f->ph == 1) { + vcEnd -= available_vcs; + } else { + assert(f->ph == 2); + vcBegin += available_vcs; + } + } + + found = 1; + } + + if (!found) { + cout << " ERROR: output not found in routing. " << endl; + cout << *f; exit (-1); + } + + if (out_port >= gN*(gK-1) + gC) { + cout << " ERROR: output port too big! " << endl; + cout << " OUTPUT select: " << out_port << endl; + cout << " router radix: " << gN*(gK-1) + gK << endl; + exit (-1); + } + + if (debug) cout << " through output port : " << out_port << endl; + if(gTrace) { + cout<<"Outport "<<out_port<<endl; + cout<<"Stop Mark"<<endl; + } + } + + if(inject || (out_port >= gC)) { + + // NOTE: for "proper" flattened butterfly configurations (i.e., ones + // derived from flattening an actual butterfly), gK and gC are the same! + assert(gK == gC); + + assert(inject ? (f->ph == -1) : (f->ph == 1 || f->ph == 2)); + + int next_coord = flatfly_transformation(f->dest); + if(inject) { + next_coord /= gC; + next_coord %= gK; + } else { + int next_dim = (out_port - gC) / (gK - 1) + 1; + if(next_dim == gN) { + next_coord %= gC; + } else { + next_coord /= gC; + for(int d = 0; d < next_dim; ++d) { + next_coord /= gK; + } + next_coord %= gK; + } + } + assert(next_coord >= 0 && next_coord < gK); + int vcs_per_dest = (vcEnd - vcBegin + 1) / gK; + assert(vcs_per_dest > 0); + vcBegin += next_coord * vcs_per_dest; + vcEnd = vcBegin + vcs_per_dest - 1; + } + + outputs->Clear( ); + + outputs->AddRange( out_port , vcBegin, vcEnd ); +} + + +//=============================================================^M +// UGAL : calculate distance (hop cnt) between src and destination +//=============================================================^M +int find_distance (int src, int dest) { + int dist = 0; + int _dim = gN; + int _dim_size; + + int src_tmp= (int) src / gC; + int dest_tmp = (int) dest / gC; + int src_id, dest_id; + + // cout << " HOP CNT between src: " << src << " dest: " << dest; + for (int d=0;d < _dim; d++) { + _dim_size = powi(gK, d )*gC; + //if ((int)(src / _dim_size) != (int)(dest / _dim_size)) + // dist++; + src_id = src_tmp % gK; + dest_id = dest_tmp % gK; + if (src_id != dest_id) + dist++; + src_tmp = (int) (src_tmp / gK); + dest_tmp = (int) (dest_tmp / gK); + } + + // cout << " : " << dist << endl; + + return dist; +} + +//=============================================================^M +// UGAL : find random node for load balancing +//=============================================================^M +int find_ran_intm (int src, int dest) { + int _dim = gN; + int _dim_size; + int _ran_dest = 0; + int debug = 0; + + if (debug) + cout << " INTM node for src: " << src << " dest: " <<dest << endl; + + src = (int) (src / gC); + dest = (int) (dest / gC); + + _ran_dest = RandomInt(gC - 1); + if (debug) cout << " ............ _ran_dest : " << _ran_dest << endl; + for (int d=0;d < _dim; d++) { + + _dim_size = powi(gK, d)*gC; + if ((src % gK) == (dest % gK)) { + _ran_dest += (src % gK) * _dim_size; + if (debug) + cout << " share same dimension : " << d << " int node : " << _ran_dest << " src ID : " << src % gK << endl; + } else { + // src and dest are in the same dimension "d" + 1 + // ==> thus generate a random destination within + _ran_dest += RandomInt(gK - 1) * _dim_size; + if (debug) + cout << " different dimension : " << d << " int node : " << _ran_dest << " _dim_size: " << _dim_size << endl; + } + src = (int) (src / gK); + dest = (int) (dest / gK); + } + + if (debug) cout << " intermediate destination NODE: " << _ran_dest << endl; + return _ran_dest; +} + + + +//============================================================= +// UGAL : calculated minimum distance output port for flatfly +// given the dimension and destination +//============================================================= +// starting from DIM 0 (x first) +int flatfly_outport(int dest, int rID) { + int dest_rID = (int) (dest / gC); + int _dim = gN; + int output = -1, dID, sID; + + if(dest_rID==rID){ + return dest % gC; + } + + + for (int d=0;d < _dim; d++) { + dID = (dest_rID % gK); + sID = (rID % gK); + if ( dID != sID ) { + output = gC + ((gK-1)*d) - 1; + if (dID > sID) { + + output += dID; + } else { + output += dID + 1; + } + + return output; + } + dest_rID = (int) (dest_rID / gK); + rID = (int) (rID / gK); + } + if (output == -1) { + cout << " ERROR ---- FLATFLY_OUTPORT function : output not found " << endl; + exit(-1); + } + return -1; +} + +int flatfly_transformation(int dest){ + //the magic of destination transformation + + //destination transformation, translate how the nodes are actually arranged + //to the easier way of routing + //this transformation only support 64 nodes + + //cout<<"ORiginal destination "<<dest<<endl; + //router in the x direction = find which column, and then mod by cY to find + //which horizontal router + int horizontal = (dest%(_xcount*_xrouter))/(_xrouter); + int horizontal_rem = (dest%(_xcount*_xrouter))%(_xrouter); + //router in the y direction = find which row, and then divided by cX to find + //vertical router + int vertical = (dest/(_xcount*_xrouter))/(_yrouter); + int vertical_rem = (dest/(_xcount*_xrouter))%(_yrouter); + //transform the destination to as if node0 was 0,1,2,3 and so forth + dest = (vertical*_xcount + horizontal)*gC+_xrouter*vertical_rem+horizontal_rem; + //cout<<"Transformed destination "<<dest<<endl<<endl; + return dest; +} diff --git a/src/intersim2/networks/flatfly_onchip.hpp b/src/intersim2/networks/flatfly_onchip.hpp new file mode 100644 index 0000000..2f164be --- /dev/null +++ b/src/intersim2/networks/flatfly_onchip.hpp @@ -0,0 +1,88 @@ +// $Id: flatfly_onchip.hpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +#ifndef _FlatFlyOnChip_HPP_ +#define _FlatFlyOnChip_HPP_ + +#include "network.hpp" + +#include "routefunc.hpp" +#include <cassert> + + +class FlatFlyOnChip : public Network { + + int _m; + int _n; + int _r; + int _k; + int _c; + int _radix; + int _net_size; + int _stageout; + int _numinput; + int _stages; + int _num_of_switch; + + void _ComputeSize( const Configuration &config ); + void _BuildNet( const Configuration &config ); + + int _OutChannel( int stage, int addr, int port, int outputs ) const; + int _InChannel( int stage, int addr, int port ) const; + +public: + FlatFlyOnChip( const Configuration &config, const string & name ); + + int GetN( ) const; + int GetK( ) const; + + static void RegisterRoutingFunctions() ; + double Capacity( ) const; + void InsertRandomFaults( const Configuration &config ); +}; +void adaptive_xyyx_flatfly( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ); +void xyyx_flatfly( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ); +void min_flatfly( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ); +void ugal_xyyx_flatfly_onchip( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ); +void ugal_flatfly_onchip( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ); +void ugal_pni_flatfly_onchip( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ); +void valiant_flatfly( const Router *r, const Flit *f, int in_channel, + OutputSet *outputs, bool inject ); + +int find_distance (int src, int dest); +int find_ran_intm (int src, int dest); +int flatfly_outport(int dest, int rID); +int flatfly_transformation(int dest); +int flatfly_outport_yx(int dest, int rID); + +#endif diff --git a/src/intersim2/networks/fly.cpp b/src/intersim2/networks/fly.cpp new file mode 100644 index 0000000..8e0bdd7 --- /dev/null +++ b/src/intersim2/networks/fly.cpp @@ -0,0 +1,162 @@ +// $Id: fly.cpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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 "booksim.hpp" +#include <vector> +#include <sstream> + +#include "fly.hpp" +#include "misc_utils.hpp" + +//#define DEBUG_FLY + +KNFly::KNFly( const Configuration &config, const string & name ) : +Network( config, name ) +{ + _ComputeSize( config ); + _Alloc( ); + _BuildNet( config ); +} + +void KNFly::_ComputeSize( const Configuration &config ) +{ + _k = config.GetInt( "k" ); + _n = config.GetInt( "n" ); + + gK = _k; gN = _n; + + _nodes = powi( _k, _n ); + + // n stages of k^(n-1) k x k switches + _size = _n*powi( _k, _n-1 ); + + // n-1 sets of wiring between the stages + _channels = (_n-1)*_nodes; +} + +void KNFly::_BuildNet( const Configuration &config ) +{ + ostringstream router_name; + + int per_stage = powi( _k, _n-1 ); + + int node = 0; + int c; + + for ( int stage = 0; stage < _n; ++stage ) { + for ( int addr = 0; addr < per_stage; ++addr ) { + + router_name << "router_" << stage << "_" << addr; + _routers[node] = Router::NewRouter( config, this, router_name.str( ), + node, _k, _k ); + _timed_modules.push_back(_routers[node]); + router_name.str(""); + +#ifdef DEBUG_FLY + cout << "connecting node " << node << " to:" << endl; +#endif + + for ( int port = 0; port < _k; ++port ) { + // Input connections + if ( stage == 0 ) { + c = addr*_k + port; + _routers[node]->AddInputChannel( _inject[c], _inject_cred[c] ); +#ifdef DEBUG_FLY + cout << " injection channel " << c << endl; +#endif + } else { + c = _InChannel( stage, addr, port ); + _routers[node]->AddInputChannel( _chan[c], _chan_cred[c] ); + _chan[c]->SetLatency( 1 ); + +#ifdef DEBUG_FLY + cout << " input channel " << c << endl; +#endif + } + + // Output connections + if ( stage == _n - 1 ) { + c = addr*_k + port; + _routers[node]->AddOutputChannel( _eject[c], _eject_cred[c] ); +#ifdef DEBUG_FLY + cout << " ejection channel " << c << endl; +#endif + } else { + c = _OutChannel( stage, addr, port ); + _routers[node]->AddOutputChannel( _chan[c], _chan_cred[c] ); +#ifdef DEBUG_FLY + cout << " output channel " << c << endl; +#endif + } + } + + ++node; + } + } +} + +int KNFly::_OutChannel( int stage, int addr, int port ) const +{ + return stage*_nodes + addr*_k + port; +} + +int KNFly::_InChannel( int stage, int addr, int port ) const +{ + int in_addr; + int in_port; + + // Channels are between {node,port} + // { d_{n-1} ... d_{n-stage} ... d_0 } and + // { d_{n-1} ... d_0 ... d_{n-stage} } + + int shift = powi( _k, _n-stage-1 ); + + int last_digit = port; + int zero_digit = ( addr / shift ) % _k; + + // swap zero and last digit to get first node's address + in_addr = addr - zero_digit*shift + last_digit*shift; + in_port = zero_digit; + + return (stage-1)*_nodes + in_addr*_k + in_port; +} + +int KNFly::GetN( ) const +{ + return _n; +} + +int KNFly::GetK( ) const +{ + return _k; +} + +double KNFly::Capacity( ) const +{ + return 1.0; +} + diff --git a/src/intersim2/networks/fly.hpp b/src/intersim2/networks/fly.hpp new file mode 100644 index 0000000..c32062f --- /dev/null +++ b/src/intersim2/networks/fly.hpp @@ -0,0 +1,53 @@ +// $Id: fly.hpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +#ifndef _FLY_HPP_ +#define _FLY_HPP_ + +#include "network.hpp" + +class KNFly : public Network { + + int _k; + int _n; + + void _ComputeSize( const Configuration &config ); + void _BuildNet( const Configuration &config ); + + int _OutChannel( int stage, int addr, int port ) const; + int _InChannel( int stage, int addr, int port ) const; + +public: + KNFly( const Configuration &config, const string & name ); + + int GetN( ) const; + int GetK( ) const; + static void RegisterRoutingFunctions(){}; + double Capacity( ) const; +}; + +#endif diff --git a/src/intersim2/networks/kncube.cpp b/src/intersim2/networks/kncube.cpp new file mode 100644 index 0000000..6915f22 --- /dev/null +++ b/src/intersim2/networks/kncube.cpp @@ -0,0 +1,319 @@ +// $Id: kncube.cpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +/*kn.cpp + * + *Meshs, cube, torus + * + */ + +#include "booksim.hpp" +#include <vector> +#include <sstream> +#include "kncube.hpp" +#include "random_utils.hpp" +#include "misc_utils.hpp" + //#include "iq_router.hpp" + + +KNCube::KNCube( const Configuration &config, const string & name, bool mesh ) : +Network( config, name ) +{ + _mesh = mesh; + + _ComputeSize( config ); + _Alloc( ); + _BuildNet( config ); +} + +void KNCube::_ComputeSize( const Configuration &config ) +{ + _k = config.GetInt( "k" ); + _n = config.GetInt( "n" ); + + gK = _k; gN = _n; + _size = powi( _k, _n ); + _channels = 2*_n*_size; + + _nodes = _size; +} + +void KNCube::RegisterRoutingFunctions() { + +} +void KNCube::_BuildNet( const Configuration &config ) +{ + int left_node; + int right_node; + + int right_input; + int left_input; + + int right_output; + int left_output; + + ostringstream router_name; + + //latency type, noc or conventional network + bool use_noc_latency; + use_noc_latency = (config.GetInt("use_noc_latency")==1); + + for ( int node = 0; node < _size; ++node ) { + + router_name << "router"; + + if ( _k > 1 ) { + for ( int dim_offset = _size / _k; dim_offset >= 1; dim_offset /= _k ) { + router_name << "_" << ( node / dim_offset ) % _k; + } + } + + _routers[node] = Router::NewRouter( config, this, router_name.str( ), + node, 2*_n + 1, 2*_n + 1 ); + _timed_modules.push_back(_routers[node]); + + router_name.str(""); + + for ( int dim = 0; dim < _n; ++dim ) { + + //find the neighbor + left_node = _LeftNode( node, dim ); + right_node = _RightNode( node, dim ); + + // + // Current (N)ode + // (L)eft node + // (R)ight node + // + // L--->N<---R + // L<---N--->R + // + + // torus channel is longer due to wrap around + int latency = _mesh ? 1 : 2 ; + + //get the input channel number + right_input = _LeftChannel( right_node, dim ); + left_input = _RightChannel( left_node, dim ); + + //add the input channel + _routers[node]->AddInputChannel( _chan[right_input], _chan_cred[right_input] ); + _routers[node]->AddInputChannel( _chan[left_input], _chan_cred[left_input] ); + + //set input channel latency + if(use_noc_latency){ + _chan[right_input]->SetLatency( latency ); + _chan[left_input]->SetLatency( latency ); + _chan_cred[right_input]->SetLatency( latency ); + _chan_cred[left_input]->SetLatency( latency ); + } else { + _chan[left_input]->SetLatency( 1 ); + _chan_cred[right_input]->SetLatency( 1 ); + _chan_cred[left_input]->SetLatency( 1 ); + _chan[right_input]->SetLatency( 1 ); + } + //get the output channel number + right_output = _RightChannel( node, dim ); + left_output = _LeftChannel( node, dim ); + + //add the output channel + _routers[node]->AddOutputChannel( _chan[right_output], _chan_cred[right_output] ); + _routers[node]->AddOutputChannel( _chan[left_output], _chan_cred[left_output] ); + + //set output channel latency + if(use_noc_latency){ + _chan[right_output]->SetLatency( latency ); + _chan[left_output]->SetLatency( latency ); + _chan_cred[right_output]->SetLatency( latency ); + _chan_cred[left_output]->SetLatency( latency ); + } else { + _chan[right_output]->SetLatency( 1 ); + _chan[left_output]->SetLatency( 1 ); + _chan_cred[right_output]->SetLatency( 1 ); + _chan_cred[left_output]->SetLatency( 1 ); + + } + } + //injection and ejection channel, always 1 latency + _routers[node]->AddInputChannel( _inject[node], _inject_cred[node] ); + _routers[node]->AddOutputChannel( _eject[node], _eject_cred[node] ); + _inject[node]->SetLatency( 1 ); + _eject[node]->SetLatency( 1 ); + } +} + +int KNCube::_LeftChannel( int node, int dim ) +{ + // The base channel for a node is 2*_n*node + int base = 2*_n*node; + // The offset for a left channel is 2*dim + 1 + int off = 2*dim + 1; + + return ( base + off ); +} + +int KNCube::_RightChannel( int node, int dim ) +{ + // The base channel for a node is 2*_n*node + int base = 2*_n*node; + // The offset for a right channel is 2*dim + int off = 2*dim; + return ( base + off ); +} + +int KNCube::_LeftNode( int node, int dim ) +{ + int k_to_dim = powi( _k, dim ); + int loc_in_dim = ( node / k_to_dim ) % _k; + int left_node; + // if at the left edge of the dimension, wraparound + if ( loc_in_dim == 0 ) { + left_node = node + (_k-1)*k_to_dim; + } else { + left_node = node - k_to_dim; + } + + return left_node; +} + +int KNCube::_RightNode( int node, int dim ) +{ + int k_to_dim = powi( _k, dim ); + int loc_in_dim = ( node / k_to_dim ) % _k; + int right_node; + // if at the right edge of the dimension, wraparound + if ( loc_in_dim == ( _k-1 ) ) { + right_node = node - (_k-1)*k_to_dim; + } else { + right_node = node + k_to_dim; + } + + return right_node; +} + +int KNCube::GetN( ) const +{ + return _n; +} + +int KNCube::GetK( ) const +{ + return _k; +} + +/*legacy, not sure how this fits into the own scheme of things*/ +void KNCube::InsertRandomFaults( const Configuration &config ) +{ + int num_fails; + unsigned long prev_seed; + + int node, chan; + int i, j, t, n, c; + bool available; + + bool edge; + + num_fails = config.GetInt( "link_failures" ); + + if ( num_fails ) { + prev_seed = RandomIntLong( ); + RandomSeed( config.GetInt( "fail_seed" ) ); + + vector<bool> fail_nodes(_size); + + for ( i = 0; i < _size; ++i ) { + node = i; + + // edge test + edge = false; + for ( n = 0; n < _n; ++n ) { + if ( ( ( node % _k ) == 0 ) || + ( ( node % _k ) == _k - 1 ) ) { + edge = true; + } + node /= _k; + } + + if ( edge ) { + fail_nodes[i] = true; + } else { + fail_nodes[i] = false; + } + } + + for ( i = 0; i < num_fails; ++i ) { + j = RandomInt( _size - 1 ); + available = false; + + for ( t = 0; ( t < _size ) && (!available); ++t ) { + node = ( j + t ) % _size; + + if ( !fail_nodes[node] ) { + // check neighbors + c = RandomInt( 2*_n - 1 ); + + for ( n = 0; ( n < 2*_n ) && (!available); ++n ) { + chan = ( n + c ) % 2*_n; + + if ( chan % 1 ) { + available = fail_nodes[_LeftNode( node, chan/2 )]; + } else { + available = fail_nodes[_RightNode( node, chan/2 )]; + } + } + } + + if ( !available ) { + cout << "skipping " << node << endl; + } + } + + if ( t == _size ) { + Error( "Could not find another possible fault channel" ); + } + + + OutChannelFault( node, chan ); + fail_nodes[node] = true; + + for ( n = 0; ( n < _n ) && available ; ++n ) { + fail_nodes[_LeftNode( node, n )] = true; + fail_nodes[_RightNode( node, n )] = true; + } + + cout << "failure at node " << node << ", channel " + << chan << endl; + } + + RandomSeed( prev_seed ); + } +} + +double KNCube::Capacity( ) const +{ + return (double)_k / ( _mesh ? 8.0 : 4.0 ); +} diff --git a/src/intersim2/networks/kncube.hpp b/src/intersim2/networks/kncube.hpp new file mode 100644 index 0000000..b3ca1ca --- /dev/null +++ b/src/intersim2/networks/kncube.hpp @@ -0,0 +1,62 @@ +// $Id: kncube.hpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +#ifndef _KNCUBE_HPP_ +#define _KNCUBE_HPP_ + +#include "network.hpp" + +class KNCube : public Network { + + bool _mesh; + + int _k; + int _n; + + void _ComputeSize( const Configuration &config ); + void _BuildNet( const Configuration &config ); + + int _LeftChannel( int node, int dim ); + int _RightChannel( int node, int dim ); + + int _LeftNode( int node, int dim ); + int _RightNode( int node, int dim ); + +public: + KNCube( const Configuration &config, const string & name, bool mesh ); + static void RegisterRoutingFunctions(); + + int GetN( ) const; + int GetK( ) const; + + double Capacity( ) const; + + void InsertRandomFaults( const Configuration &config ); + +}; + +#endif diff --git a/src/intersim2/networks/network.cpp b/src/intersim2/networks/network.cpp new file mode 100644 index 0000000..2909429 --- /dev/null +++ b/src/intersim2/networks/network.cpp @@ -0,0 +1,290 @@ +// $Id: network.cpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +/*network.cpp + * + *This class is the basis of the entire network, it contains, all the routers + *channels in the network, and is extended by all the network topologies + * + */ + +#include <cassert> +#include <sstream> + +#include "booksim.hpp" +#include "network.hpp" + +#include "kncube.hpp" +#include "fly.hpp" +#include "cmesh.hpp" +#include "flatfly_onchip.hpp" +#include "qtree.hpp" +#include "tree4.hpp" +#include "fattree.hpp" +#include "anynet.hpp" +#include "dragonfly.hpp" + + +Network::Network( const Configuration &config, const string & name ) : + TimedModule( 0, name ) +{ + _size = -1; + _nodes = -1; + _channels = -1; + _classes = config.GetInt("classes"); +} + +Network::~Network( ) +{ + for ( int r = 0; r < _size; ++r ) { + if ( _routers[r] ) delete _routers[r]; + } + for ( int s = 0; s < _nodes; ++s ) { + if ( _inject[s] ) delete _inject[s]; + if ( _inject_cred[s] ) delete _inject_cred[s]; + } + for ( int d = 0; d < _nodes; ++d ) { + if ( _eject[d] ) delete _eject[d]; + if ( _eject_cred[d] ) delete _eject_cred[d]; + } + for ( int c = 0; c < _channels; ++c ) { + if ( _chan[c] ) delete _chan[c]; + if ( _chan_cred[c] ) delete _chan_cred[c]; + } +} + +Network * Network::New(const Configuration & config, const string & name) +{ + const string topo = config.GetStr( "topology" ); + Network * n = NULL; + if ( topo == "torus" ) { + KNCube::RegisterRoutingFunctions() ; + n = new KNCube( config, name, false ); + } else if ( topo == "mesh" ) { + KNCube::RegisterRoutingFunctions() ; + n = new KNCube( config, name, true ); + } else if ( topo == "cmesh" ) { + CMesh::RegisterRoutingFunctions() ; + n = new CMesh( config, name ); + } else if ( topo == "fly" ) { + KNFly::RegisterRoutingFunctions() ; + n = new KNFly( config, name ); + } else if ( topo == "qtree" ) { + QTree::RegisterRoutingFunctions() ; + n = new QTree( config, name ); + } else if ( topo == "tree4" ) { + Tree4::RegisterRoutingFunctions() ; + n = new Tree4( config, name ); + } else if ( topo == "fattree" ) { + FatTree::RegisterRoutingFunctions() ; + n = new FatTree( config, name ); + } else if ( topo == "flatfly" ) { + FlatFlyOnChip::RegisterRoutingFunctions() ; + n = new FlatFlyOnChip( config, name ); + } else if ( topo == "anynet"){ + AnyNet::RegisterRoutingFunctions() ; + n = new AnyNet(config, name); + } else if ( topo == "dragonflynew"){ + DragonFlyNew::RegisterRoutingFunctions() ; + n = new DragonFlyNew(config, name); + } else { + cerr << "Unknown topology: " << topo << endl; + } + + /*legacy code that insert random faults in the networks + *not sure how to use this + */ + if ( n && ( config.GetInt( "link_failures" ) > 0 ) ) { + n->InsertRandomFaults( config ); + } + return n; +} + +void Network::_Alloc( ) +{ + assert( ( _size != -1 ) && + ( _nodes != -1 ) && + ( _channels != -1 ) ); + + _routers.resize(_size); + gNodes = _nodes; + + /*booksim used arrays of flits as the channels which makes have capacity of + *one. To simulate channel latency, flitchannel class has been added + *which are fifos with depth = channel latency and each cycle the channel + *shifts by one + *credit channels are the necessary counter part + */ + _inject.resize(_nodes); + _inject_cred.resize(_nodes); + for ( int s = 0; s < _nodes; ++s ) { + ostringstream name; + name << Name() << "_fchan_ingress" << s; + _inject[s] = new FlitChannel(this, name.str(), _classes); + _inject[s]->SetSource(NULL, s); + _timed_modules.push_back(_inject[s]); + name.str(""); + name << Name() << "_cchan_ingress" << s; + _inject_cred[s] = new CreditChannel(this, name.str()); + _timed_modules.push_back(_inject_cred[s]); + } + _eject.resize(_nodes); + _eject_cred.resize(_nodes); + for ( int d = 0; d < _nodes; ++d ) { + ostringstream name; + name << Name() << "_fchan_egress" << d; + _eject[d] = new FlitChannel(this, name.str(), _classes); + _eject[d]->SetSink(NULL, d); + _timed_modules.push_back(_eject[d]); + name.str(""); + name << Name() << "_cchan_egress" << d; + _eject_cred[d] = new CreditChannel(this, name.str()); + _timed_modules.push_back(_eject_cred[d]); + } + _chan.resize(_channels); + _chan_cred.resize(_channels); + for ( int c = 0; c < _channels; ++c ) { + ostringstream name; + name << Name() << "_fchan_" << c; + _chan[c] = new FlitChannel(this, name.str(), _classes); + _timed_modules.push_back(_chan[c]); + name.str(""); + name << Name() << "_cchan_" << c; + _chan_cred[c] = new CreditChannel(this, name.str()); + _timed_modules.push_back(_chan_cred[c]); + } +} + +void Network::ReadInputs( ) +{ + for(deque<TimedModule *>::const_iterator iter = _timed_modules.begin(); + iter != _timed_modules.end(); + ++iter) { + (*iter)->ReadInputs( ); + } +} + +void Network::Evaluate( ) +{ + for(deque<TimedModule *>::const_iterator iter = _timed_modules.begin(); + iter != _timed_modules.end(); + ++iter) { + (*iter)->Evaluate( ); + } +} + +void Network::WriteOutputs( ) +{ + for(deque<TimedModule *>::const_iterator iter = _timed_modules.begin(); + iter != _timed_modules.end(); + ++iter) { + (*iter)->WriteOutputs( ); + } +} + +void Network::WriteFlit( Flit *f, int source ) +{ + assert( ( source >= 0 ) && ( source < _nodes ) ); + _inject[source]->Send(f); +} + +Flit *Network::ReadFlit( int dest ) +{ + assert( ( dest >= 0 ) && ( dest < _nodes ) ); + return _eject[dest]->Receive(); +} + +void Network::WriteCredit( Credit *c, int dest ) +{ + assert( ( dest >= 0 ) && ( dest < _nodes ) ); + _eject_cred[dest]->Send(c); +} + +Credit *Network::ReadCredit( int source ) +{ + assert( ( source >= 0 ) && ( source < _nodes ) ); + return _inject_cred[source]->Receive(); +} + +void Network::InsertRandomFaults( const Configuration &config ) +{ + Error( "InsertRandomFaults not implemented for this topology!" ); +} + +void Network::OutChannelFault( int r, int c, bool fault ) +{ + assert( ( r >= 0 ) && ( r < _size ) ); + _routers[r]->OutChannelFault( c, fault ); +} + +double Network::Capacity( ) const +{ + return 1.0; +} + +/* this function can be heavily modified to display any information + * neceesary of the network, by default, call display on each router + * and display the channel utilization rate + */ +void Network::Display( ostream & os ) const +{ + for ( int r = 0; r < _size; ++r ) { + _routers[r]->Display( os ); + } +} + +void Network::DumpChannelMap( ostream & os, string const & prefix ) const +{ + os << prefix << "source_router,source_port,dest_router,dest_port" << endl; + for(int c = 0; c < _nodes; ++c) + os << prefix + << "-1," + << _inject[c]->GetSourcePort() << ',' + << _inject[c]->GetSink()->GetID() << ',' + << _inject[c]->GetSinkPort() << endl; + for(int c = 0; c < _channels; ++c) + os << prefix + << _chan[c]->GetSource()->GetID() << ',' + << _chan[c]->GetSourcePort() << ',' + << _chan[c]->GetSink()->GetID() << ',' + << _chan[c]->GetSinkPort() << endl; + for(int c = 0; c < _nodes; ++c) + os << prefix + << _eject[c]->GetSource()->GetID() << ',' + << _eject[c]->GetSourcePort() << ',' + << "-1," + << _eject[c]->GetSinkPort() << endl; +} + +void Network::DumpNodeMap( ostream & os, string const & prefix ) const +{ + os << prefix << "source_router,dest_router" << endl; + for(int s = 0; s < _nodes; ++s) + os << prefix + << _eject[s]->GetSource()->GetID() << ',' + << _inject[s]->GetSink()->GetID() << endl; +} diff --git a/src/intersim2/networks/network.hpp b/src/intersim2/networks/network.hpp new file mode 100644 index 0000000..fcf0253 --- /dev/null +++ b/src/intersim2/networks/network.hpp @@ -0,0 +1,118 @@ +// $Id: network.hpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +#ifndef _NETWORK_HPP_ +#define _NETWORK_HPP_ + +#include <vector> +#include <deque> + +#include "module.hpp" +#include "flit.hpp" +#include "credit.hpp" +#include "router.hpp" +#include "module.hpp" +#include "timed_module.hpp" +#include "flitchannel.hpp" +#include "channel.hpp" +#include "config_utils.hpp" +#include "globals.hpp" + +typedef Channel<Credit> CreditChannel; + + +class Network : public TimedModule { +protected: + + int _size; + int _nodes; + int _channels; + int _classes; + + vector<Router *> _routers; + + vector<FlitChannel *> _inject; + vector<CreditChannel *> _inject_cred; + + vector<FlitChannel *> _eject; + vector<CreditChannel *> _eject_cred; + + vector<FlitChannel *> _chan; + vector<CreditChannel *> _chan_cred; + + deque<TimedModule *> _timed_modules; + + virtual void _ComputeSize( const Configuration &config ) = 0; + virtual void _BuildNet( const Configuration &config ) = 0; + + void _Alloc( ); + +public: + Network( const Configuration &config, const string & name ); + virtual ~Network( ); + + static Network *New( const Configuration &config, const string & name ); + + virtual void WriteFlit( Flit *f, int source ); + virtual Flit *ReadFlit( int dest ); + + virtual void WriteCredit( Credit *c, int dest ); + virtual Credit *ReadCredit( int source ); + + inline int NumNodes( ) const {return _nodes;} + + virtual void InsertRandomFaults( const Configuration &config ); + void OutChannelFault( int r, int c, bool fault = true ); + + virtual double Capacity( ) const; + + virtual void ReadInputs( ); + virtual void Evaluate( ); + virtual void WriteOutputs( ); + + void Display( ostream & os = cout ) const; + void DumpChannelMap( ostream & os = cout, string const & prefix = "" ) const; + void DumpNodeMap( ostream & os = cout, string const & prefix = "" ) const; + + int NumChannels() const {return _channels;} + const vector<FlitChannel *> & GetInject() {return _inject;} + FlitChannel * GetInject(int index) {return _inject[index];} + const vector<CreditChannel *> & GetInjectCred() {return _inject_cred;} + CreditChannel * GetInjectCred(int index) {return _inject_cred[index];} + const vector<FlitChannel *> & GetEject(){return _eject;} + FlitChannel * GetEject(int index) {return _eject[index];} + const vector<CreditChannel *> & GetEjectCred(){return _eject_cred;} + CreditChannel * GetEjectCred(int index) {return _eject_cred[index];} + const vector<FlitChannel *> & GetChannels(){return _chan;} + const vector<CreditChannel *> & GetChannelsCred(){return _chan_cred;} + const vector<Router *> & GetRouters(){return _routers;} + Router * GetRouter(int index) {return _routers[index];} + int NumRouters() const {return _size;} +}; + +#endif + diff --git a/src/intersim2/networks/qtree.cpp b/src/intersim2/networks/qtree.cpp new file mode 100644 index 0000000..7214947 --- /dev/null +++ b/src/intersim2/networks/qtree.cpp @@ -0,0 +1,187 @@ +// $Id: qtree.cpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +//////////////////////////////////////////////////////////////////////// +// +// QTree: A Quad-Tree Indirect Network. +// +// +//////////////////////////////////////////////////////////////////////// +// +// RCS Information: +// $Author: jbalfour $ +// $Date: 2007/05/17 17:14:07 $ +// $Id: qtree.cpp 5188 2012-08-30 00:31:31Z dub $ +// +//////////////////////////////////////////////////////////////////////// + +#include "booksim.hpp" +#include <vector> +#include <sstream> +#include "qtree.hpp" +#include "misc_utils.hpp" + +QTree::QTree( const Configuration& config, const string & name ) +: Network ( config, name ) +{ + _ComputeSize( config ); + _Alloc( ); + _BuildNet( config ); +} + + +void QTree::_ComputeSize( const Configuration& config ) +{ + + _k = config.GetInt( "k" ); + _n = config.GetInt( "n" ); + + assert( _k == 4 && _n == 3 ); + + gK = _k; gN = _n; + + _nodes = powi( _k, _n ); + + _size = 0; + for (int i = 0; i < _n; i++) + _size += powi( _k, i ); + + _channels = 0; + for (int j = 1; j < _n; j++) + _channels += 2 * powi( _k, j ); + +} + +void QTree::RegisterRoutingFunctions(){ + +} + +void QTree::_BuildNet( const Configuration& config ) +{ + + ostringstream routerName; + int h, r, pos, port; + + for (h = 0; h < _n; h++) { + for (pos = 0 ; pos < powi( _k, h ) ; ++pos ) { + + int id = h * 256 + pos; + r = _RouterIndex( h, pos ); + + routerName << "router_" << h << "_" << pos; + + int d = ( h == 0 ) ? _k : _k + 1; + _routers[r] = Router::NewRouter( config, this, + routerName.str( ), + id, d, d); + _timed_modules.push_back(_routers[r]); + routerName.str(""); + } + } + + // Injection & Ejection Channels + for ( pos = 0 ; pos < powi( _k, _n-1 ) ; ++pos ) { + r = _RouterIndex( _n-1, pos ); + for ( port = 0 ; port < _k ; port++ ) { + + _routers[r]->AddInputChannel( _inject[_k*pos+port], + _inject_cred[_k*pos+port]); + + _routers[r]->AddOutputChannel( _eject[_k*pos+port], + _eject_cred[_k*pos+port]); + } + } + + int c; + for ( h = 0 ; h < _n ; ++h ) { + for ( pos = 0 ; pos < powi( _k, h ) ; ++pos ) { + for ( port = 0 ; port < _k ; port++ ) { + + r = _RouterIndex( h, pos ); + + if ( h < _n-1 ) { + // Channels to Children Nodes + c = _InputIndex( h , pos, port ); + _routers[r]->AddInputChannel( _chan[c], + _chan_cred[c] ); + + c = _OutputIndex( h, pos, port ); + _routers[r]->AddOutputChannel( _chan[c], + _chan_cred[c] ); + + } + } + if ( h > 0 ) { + // Channels to Parent Nodes + c = _OutputIndex( h - 1, pos / _k, pos % _k ); + _routers[r]->AddInputChannel( _chan[c], + _chan_cred[c] ); + + c = _InputIndex( h - 1, pos / _k, pos % _k ); + _routers[r]->AddOutputChannel( _chan[c], + _chan_cred[c]); + } + } + } +} + +int QTree::_RouterIndex( int height, int pos ) +{ + int r = 0; + for ( int h = 0; h < height; h++ ) + r += powi( _k, h ); + return (r + pos); +} + +int QTree::_InputIndex( int height, int pos, int port ) +{ + assert( height >= 0 && height < powi( _k,_n-1 ) ); + int c = 0; + for ( int h = 0; h < height; h++) + c += powi( _k, h+1 ); + return ( c + _k * pos + port ); +} + +int QTree::_OutputIndex( int height, int pos, int port ) +{ + assert( height >= 0 && height < powi( _k,_n-1 ) ); + int c = _channels / 2; + for ( int h = 0; h < height; h++) + c += powi( _k, h+1 ); + return ( c + _k * pos + port ); +} + + +int QTree::HeightFromID( int id ) +{ + return id / 256; +} + +int QTree::PosFromID( int id ) +{ + return id % 256; +} diff --git a/src/intersim2/networks/qtree.hpp b/src/intersim2/networks/qtree.hpp new file mode 100644 index 0000000..0a31a92 --- /dev/null +++ b/src/intersim2/networks/qtree.hpp @@ -0,0 +1,69 @@ +// $Id: qtree.hpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +//////////////////////////////////////////////////////////////////////// +// +// QTree: A Quad-Tree Indirect Network. +// +// +//////////////////////////////////////////////////////////////////////// +// +// RCS Information: +// $Author: jbalfour $ +// $Date: 2007/05/17 17:14:07 $ +// $Id: qtree.hpp 5188 2012-08-30 00:31:31Z dub $ +// +//////////////////////////////////////////////////////////////////////// + +#ifndef _QTREE_HPP_ +#define _QTREE_HPP_ +#include <cassert> +#include "network.hpp" + +class QTree : public Network { + + int _k; + int _n; + + void _ComputeSize( const Configuration& config ); + void _BuildNet( const Configuration& config ); + + int _RouterIndex( int height, int pos ); + int _InputIndex( int height, int pos, int port ); + int _OutputIndex( int height, int pos, int port ); + +public: + + QTree( const Configuration& config, const string & name ); + static void RegisterRoutingFunctions() ; + + static int HeightFromID( int id ); + static int PosFromID( int id ); + +}; + +#endif diff --git a/src/intersim2/networks/tree4.cpp b/src/intersim2/networks/tree4.cpp new file mode 100644 index 0000000..5650fe4 --- /dev/null +++ b/src/intersim2/networks/tree4.cpp @@ -0,0 +1,289 @@ +// $Id: tree4.cpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +//////////////////////////////////////////////////////////////////////// +// +// Tree4: Network with 64 Terminal Nodes arranged in a tree topology +// with 4 routers at the root of the tree +// +// Level 0 : 4 8 x 8 Routers (8 Descending Links per Router) +// Level 1 : 8 8 x 8 Routers (4 Descending Links per Router) +// Level 2 : 16 6 x 6 Routers (4 Descending Links per Router) +// Level 3 : 64 Terminal Nodes +// +//////////////////////////////////////////////////////////////////////// +// +// RCS Information: +// $Author: jbalfour $ +// $Date: 2007/06/26 22:49:23 $ +// $Id: tree4.cpp 5188 2012-08-30 00:31:31Z dub $ +// +//////////////////////////////////////////////////////////////////////// + +#include "booksim.hpp" +#include <vector> +#include <sstream> +#include <cmath> + +#include "tree4.hpp" +#include "misc_utils.hpp" + +Tree4::Tree4( const Configuration& config, const string & name ) +: Network ( config, name ) +{ + _ComputeSize( config ); + _Alloc( ); + _BuildNet( config ); +} + +void Tree4::_ComputeSize( const Configuration& config ) +{ + int h; + + _k = config.GetInt( "k" ); + assert(_k == 4); + _n = config.GetInt( "n" ); + assert(_n == 3); + + gK = _k; gN = _n; + + _nodes = powi( _k, _n ); + + _size = 0; + for ( h = 0; h < _n; ++h ) + _size += (4 >> h) * powi( _k, h ); + + _channels = 2 // Two Channels per Connection + * ( 2 * powi( _k, 1) ) // Number of Middle Routers + * ( 2 * _k ); // Connectivity of Middle Routers +} + +void Tree4::RegisterRoutingFunctions(){ + +} + +void Tree4::_BuildNet( const Configuration& config ) +{ + + // + // Allocate Routers + // + ostringstream name; + int h, pos, nPos, degree, id; + + for ( h = 0; h < _n; h++ ) { + nPos = (4 >> h) * powi( _k, h ); + for ( pos = 0; pos < nPos; ++pos) { + if ( h < _n-1 ) + degree = 8; + else + degree = 6; + + name.str(""); + name << "router_" << h << "_" << pos; + id = h * powi( _k, _n-1 ) + pos; + Router * r = Router::NewRouter( config, this, name.str( ), + id, degree, degree ); + _Router( h, pos ) = r; + _timed_modules.push_back(r); + } + } + + // + // Connect Channels to Routers + // + int pp, pc; + // + // Connection Rule: Output Ports 0:3 Move DOWN Network + // Output Ports 4:7 Move UP Network + // + + // Injection & Ejection Channels + nPos = powi( _k, _n - 1 ); + for ( pos = 0 ; pos < nPos ; ++pos ) { + for ( int port = 0 ; port < _k ; ++port ) { + + _Router( _n-1, pos)->AddInputChannel( _inject[_k*pos+port], + _inject_cred[_k*pos+port]); + + + _inject[_k*pos+port]->SetLatency( 1 ); + _inject_cred[_k*pos+port]->SetLatency( 1 ); + + _Router( _n-1, pos)->AddOutputChannel( _eject[_k*pos+port], + _eject_cred[_k*pos+port]); + + _eject[_k*pos+port]->SetLatency( 1 ); + _eject_cred[_k*pos+port]->SetLatency( 1 ); + + } + } + + // Connections between h = 1 and h = 2 Levels + int c = 0; + nPos = 2 * powi( _k, 1 ); + for ( pos = 0; pos < nPos; ++pos ) { + for ( int port = 0; port < _k; ++port ) { + + pp = pos; + pc = _k * ( pos / 2 ) + port; + + // cout << "connecting (1,"<<pp<<") <-> (2,"<<pc<<")"<<endl; + + _Router( 1, pp)->AddOutputChannel( _chan[c], _chan_cred[c] ); + _Router( 2, pc)->AddInputChannel( _chan[c], _chan_cred[c] ); + + //_chan[c]->SetLatency( L ); + //_chan_cred[c]->SetLatency( L ); + + _chan[c]->SetLatency( 1 ); + _chan_cred[c]->SetLatency( 1 ); + + c++; + + _Router(1, pp)->AddInputChannel( _chan[c], _chan_cred[c] ); + _Router(2, pc)->AddOutputChannel( _chan[c], _chan_cred[c] ); + + //_chan[c]->SetLatency( L ); + //_chan_cred[c]->SetLatency( L ); + _chan[c]->SetLatency( 1 ); + _chan_cred[c]->SetLatency( 1 ); + + c++; + } + } + + // Connections between h = 0 and h = 1 Levels + nPos = 4 * powi( _k, 0 ); + for ( pos = 0; pos < nPos; ++pos ) { + for ( int port = 0; port < 2 * _k; ++port ) { + pp = pos; + pc = port; + + // cout << "connecting (0,"<<pp<<") <-> (1,"<<pc<<")"<<endl; + + _Router(0, pp)->AddOutputChannel( _chan[c], _chan_cred[c] ); + _Router(1, pc)->AddInputChannel( _chan[c], _chan_cred[c] ); + + // _chan[c]->SetLatency( L ); + //_chan_cred[c]->SetLatency( L ); + _chan[c]->SetLatency( 1 ); + _chan_cred[c]->SetLatency( 1 ); + + c++; + + _Router(0, pp)->AddInputChannel( _chan[c], _chan_cred[c] ); + _Router(1, pc)->AddOutputChannel( _chan[c], _chan_cred[c] ); + + // _chan[c]->SetLatency( L ); + // _chan_cred[c]->SetLatency( L ); + _chan[c]->SetLatency( 1 ); + _chan_cred[c]->SetLatency( 1 ); + c++; + } + } + + // cout << "Used " << c << " of " << _channels << " channels" << endl; + +} + +Router*& Tree4::_Router( int height, int pos ) +{ + assert( height < _n ); + assert( pos < (4 >> height) * powi( _k, height) ); + + int i = 0; + for ( int h = 0; h < height; ++h ) + i += (4 >> h) * powi( _k, h ); + return _routers[i+pos]; + +} + +int Tree4::_WireLatency( int height1, int pos1, int height2, int pos2 ) +{ + int heightChild, heightParent, posChild, posParent; + + int L; + + if (height1 < height2) { + heightChild = height2; + posChild = pos2; + heightParent = height1; + posParent = pos1; + } else { + heightChild = height1; + posChild = pos1; + heightParent = height2; + posParent = pos2; + } + + int _length_d2_d1 = 2 ; + int _length_d1_d0_0 = 2 ; + int _length_d1_d0_1 = 2 ; + int _length_d1_d0_2 = 6 ; + int _length_d1_d0_3 = 6 ; + + assert( heightChild == heightParent+1 ); + + // We must decrement the delays by one to account for how the + // simulator interprets the specified delay (with 0 indicating one + // cycle of delay). + + if ( heightChild == 2 ) + L = _length_d2_d1; + else { + if ( posChild == 0 || posChild == 6 ) + switch ( posParent ) { + case 0: L =_length_d1_d0_0; break; + case 1: L =_length_d1_d0_1; break; + case 2: L =_length_d1_d0_2; break; + case 3: L =_length_d1_d0_3; break; + } + if ( posChild == 1 || posChild == 7 ) + switch ( posParent ) { + case 0: L =_length_d1_d0_3; break; + case 1: L =_length_d1_d0_2; break; + case 2: L =_length_d1_d0_1; break; + case 3: L =_length_d1_d0_0; break; + } + if ( posChild == 2 || posChild == 4 ) + switch ( posParent ) { + case 0: L = _length_d1_d0_0; break; + case 1: L = _length_d1_d0_1; break; + case 2: L = _length_d1_d0_2; break; + case 3: L = _length_d1_d0_3; break; + } + if ( posChild == 3|| posChild == 5 ) + switch ( posParent ) { + case 0: L =_length_d1_d0_3; break; + case 1: L =_length_d1_d0_2; break; + case 2: L =_length_d1_d0_1; break; + case 3: L =_length_d1_d0_0; break; + } + } + return L; +} diff --git a/src/intersim2/networks/tree4.hpp b/src/intersim2/networks/tree4.hpp new file mode 100644 index 0000000..76e5be8 --- /dev/null +++ b/src/intersim2/networks/tree4.hpp @@ -0,0 +1,72 @@ +// $Id: tree4.hpp 5188 2012-08-30 00:31:31Z dub $ + +/* + Copyright (c) 2007-2012, Trustees of The Leland Stanford Junior 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. + + 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 OWNER 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. +*/ + +//////////////////////////////////////////////////////////////////////// +// +// Tree4: Network with 64 Terminal Nodes arranged in a tree topology +// with 4 routers at the root of the tree +// +//////////////////////////////////////////////////////////////////////// +// +// RCS Information: +// $Author: jbalfour $ +// $Date: 2007/06/26 22:49:23 $ +// $Id: tree4.hpp 5188 2012-08-30 00:31:31Z dub $ +// +//////////////////////////////////////////////////////////////////////// + +#ifndef _TREE4_HPP_ +#define _TREE4_HPP_ +#include <cassert> +#include "network.hpp" + +class Tree4 : public Network { + + int _k; + int _n; + + int _channelWidth; + + void _ComputeSize( const Configuration& config ); + void _BuildNet( const Configuration& config ); + + + Router*& _Router( int height, int pos ); + + int _WireLatency( int height1, int pos1, int height2, int pos2 ); + +public: + + Tree4( const Configuration& config, const string & name ); + static void RegisterRoutingFunctions() ; + + static int HeightFromID( int id ); + static int PosFromID( int id ); + static int SpeedUp( int height ); +}; + +#endif |
