summaryrefslogtreecommitdiff
path: root/src/intersim2/networks
diff options
context:
space:
mode:
authorDongdong Li <[email protected]>2013-08-08 00:15:58 -0800
committerAndrew Boktor <[email protected]>2014-08-14 13:50:58 -0700
commit7f49fe9feb174d34efc2a011bad79b38522a360b (patch)
treeab5b7b66e40315a81871acbf386722981020f866 /src/intersim2/networks
parent5f91e7435742bab74dfbeca18afc63e466498f36 (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.cpp501
-rw-r--r--src/intersim2/networks/anynet.hpp69
-rw-r--r--src/intersim2/networks/cmesh.cpp856
-rw-r--r--src/intersim2/networks/cmesh.hpp95
-rw-r--r--src/intersim2/networks/dragonfly.cpp575
-rw-r--r--src/intersim2/networks/dragonfly.hpp74
-rw-r--r--src/intersim2/networks/fattree.cpp270
-rw-r--r--src/intersim2/networks/fattree.hpp76
-rw-r--r--src/intersim2/networks/flatfly_onchip.cpp1331
-rw-r--r--src/intersim2/networks/flatfly_onchip.hpp88
-rw-r--r--src/intersim2/networks/fly.cpp162
-rw-r--r--src/intersim2/networks/fly.hpp53
-rw-r--r--src/intersim2/networks/kncube.cpp319
-rw-r--r--src/intersim2/networks/kncube.hpp62
-rw-r--r--src/intersim2/networks/network.cpp290
-rw-r--r--src/intersim2/networks/network.hpp118
-rw-r--r--src/intersim2/networks/qtree.cpp187
-rw-r--r--src/intersim2/networks/qtree.hpp69
-rw-r--r--src/intersim2/networks/tree4.cpp289
-rw-r--r--src/intersim2/networks/tree4.hpp72
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