summaryrefslogtreecommitdiff
path: root/src/intersim/fly.cpp
blob: 1793cc295fd0ef80c40c9f61ed2eb2efd40ee7eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "booksim.hpp"
#include <vector>
#include <sstream>

#include "fly.hpp"
#include "misc_utils.hpp"

//#define DEBUG_FLY

KNFly::KNFly( const Configuration &config ) :
Network( config )
{
   _ComputeSize( config );
   _Alloc( );
   _BuildNet( config );
}

void KNFly::_ComputeSize( const Configuration &config )
{
   _k = config.GetInt( "k" );
   _n = config.GetInt( "n" );

   gK = _k; gN = _n;

   _sources = powi( _k, _n );
   _dests   = 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)*_sources;
}

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 );
         router_name.seekp( 0, ios::beg );

#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] );
#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*_sources + 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)*_sources + in_addr*_k + in_port;
}

int KNFly::GetN( ) const
{
   return _n;
}

int KNFly::GetK( ) const
{
   return _k;
}

double KNFly::Capacity( ) const
{
   return 1.0;
}