diff options
| author | Tor Aamodt <[email protected]> | 2010-07-15 18:09:46 -0800 |
|---|---|---|
| committer | Tor Aamodt <[email protected]> | 2010-07-15 18:09:46 -0800 |
| commit | 69f2911e04ffb1b19eef1fafb8c040af271f656e (patch) | |
| tree | 231d3b6bdc3a202f7c255bfcf7bf2c36e32cee9e /src/intersim/routefunc.cpp | |
creating branch for adding support for CUDA 3.x and Fermi
[git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 6829]
Diffstat (limited to 'src/intersim/routefunc.cpp')
| -rw-r--r-- | src/intersim/routefunc.cpp | 1045 |
1 files changed, 1045 insertions, 0 deletions
diff --git a/src/intersim/routefunc.cpp b/src/intersim/routefunc.cpp new file mode 100644 index 0000000..055baf8 --- /dev/null +++ b/src/intersim/routefunc.cpp @@ -0,0 +1,1045 @@ +#include "booksim.hpp"
+
+#include <map>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "routefunc.hpp"
+#include "kncube.hpp"
+#include "random_utils.hpp"
+
+map<string, tRoutingFunction> gRoutingFunctionMap;
+
+/* Global information used by routing functions */
+
+int gNumVCS;
+
+/* Add routing functions here */
+
+//=============================================================
+
+void singlerf( const Router *, const Flit *f, int, OutputSet *outputs, bool inject )
+{
+ outputs->Clear( );
+ outputs->Add( f->dest, f->dest % gNumVCS ); // VOQing
+}
+
+//=============================================================
+
+int dor_next_mesh( int cur, int dest )
+{
+ int dim_left;
+ int out_port;
+
+ for ( dim_left = 0; dim_left < gN; ++dim_left ) {
+ if ( ( cur % gK ) != ( dest % gK ) ) {
+ break;
+ }
+ cur /= gK; dest /= gK;
+ }
+
+ if ( dim_left < gN ) {
+ cur %= gK; dest %= gK;
+
+ if ( cur < dest ) {
+ out_port = 2*dim_left; // Right
+ } else {
+ out_port = 2*dim_left + 1; // Left
+ }
+ } else {
+ out_port = 2*gN; // Eject
+ }
+
+ return out_port;
+}
+
+//=============================================================
+
+void dor_next_torus( int cur, int dest, int in_port,
+ int *out_port, int *partition,
+ bool balance = false )
+{
+ int dim_left;
+ int dir;
+ int dist2;
+
+ for ( dim_left = 0; dim_left < gN; ++dim_left ) {
+ if ( ( cur % gK ) != ( dest % gK ) ) {
+ break;
+ }
+ cur /= gK; dest /= gK;
+ }
+
+ if ( dim_left < gN ) {
+
+ if ( (in_port/2) != dim_left ) {
+ // Turning into a new dimension
+
+ cur %= gK; dest %= gK;
+ dist2 = gK - 2 * ( ( dest - cur + gK ) % gK );
+
+ if ( ( dist2 > 0 ) ||
+ ( ( dist2 == 0 ) && ( RandomInt( 1 ) ) ) ) {
+ *out_port = 2*dim_left; // Right
+ dir = 0;
+ } else {
+ *out_port = 2*dim_left + 1; // Left
+ dir = 1;
+ }
+
+ if ( balance ) {
+ // Cray's "Partition" allocation
+ // Two datelines: one between k-1 and 0 which forces VC 1
+ // another between ((k-1)/2) and ((k-1)/2 + 1) which forces VC 0
+ // otherwise any VC can be used
+
+ if ( ( ( dir == 0 ) && ( cur > dest ) ) ||
+ ( ( dir == 1 ) && ( cur < dest ) ) ) {
+ *partition = 1;
+ } else if ( ( ( dir == 0 ) && ( cur <= (gK-1)/2 ) && ( dest > (gK-1)/2 ) ) ||
+ ( ( dir == 1 ) && ( cur > (gK-1)/2 ) && ( dest <= (gK-1)/2 ) ) ) {
+ *partition = 0;
+ } else {
+ *partition = RandomInt( 1 ); // use either VC set
+ }
+ } else {
+ // Deterministic, fixed dateline between nodes k-1 and 0
+
+ if ( ( ( dir == 0 ) && ( cur > dest ) ) ||
+ ( ( dir == 1 ) && ( dest < cur ) ) ) {
+ *partition = 1;
+ } else {
+ *partition = 0;
+ }
+ }
+ } else {
+ // Inverting the least significant bit keeps
+ // the packet moving in the same direction
+ *out_port = in_port ^ 0x1;
+ }
+
+ } else {
+ *out_port = 2*gN; // Eject
+ }
+}
+
+//=============================================================
+
+void dim_order_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
+{
+ int out_port;
+
+ outputs->Clear( );
+
+ if ( inject ) { // use any VC for injection
+ outputs->AddRange( 0, 0, gNumVCS - 1 );
+ } else {
+ out_port = dor_next_mesh( r->GetID( ), f->dest );
+
+ if ( f->watch ) {
+ cout << "flit " << f->id << " (" << f << ") at " << r->GetID( ) << " destined to "
+ << f->dest << " using channel " << out_port << ", vc range = ["
+ << 0 << "," << gNumVCS - 1 << "] (in_channel is " << in_channel << ")" << endl;
+ }
+
+ outputs->AddRange( out_port, 0, gNumVCS - 1 );
+ }
+}
+
+//=============================================================
+
+void dim_order_ni_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
+{
+ int out_port;
+ int vcs_per_dest = gNumVCS / gNodes;
+
+ outputs->Clear( );
+ out_port = dor_next_mesh( r->GetID( ), f->dest );
+
+ if ( f->watch ) {
+ cout << "flit " << f->id << " (" << f << ") at " << r->GetID( ) << " destined to "
+ << f->dest << " using channel " << out_port << ", vc range = ["
+ << f->dest*vcs_per_dest << "," << (f->dest+1)*vcs_per_dest - 1
+ << "] (in_channel is " << in_channel << ")" << endl;
+ }
+
+ outputs->AddRange( out_port, f->dest*vcs_per_dest, (f->dest+1)*vcs_per_dest - 1 );
+}
+
+//=============================================================
+
+// Random intermediate in the minimal quadrant defined
+// by the source and destination
+int rand_min_intr_mesh( int src, int dest )
+{
+ int dist;
+
+ int intm = 0;
+ int offset = 1;
+
+ for ( int n = 0; n < gN; ++n ) {
+ dist = ( dest % gK ) - ( src % gK );
+
+ if ( dist > 0 ) {
+ intm += offset * ( ( src % gK ) + RandomInt( dist ) );
+ } else {
+ intm += offset * ( ( dest % gK ) + RandomInt( -dist ) );
+ }
+
+ offset *= gK;
+ dest /= gK; src /= gK;
+ }
+
+ return intm;
+}
+
+//=============================================================
+
+void romm_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
+{
+ int out_port;
+ int vc_min, vc_max;
+
+ outputs->Clear( );
+
+ if ( in_channel == 2*gN ) {
+ f->ph = 1; // Phase 1
+ f->intm = rand_min_intr_mesh( f->src, f->dest );
+ }
+
+ if ( ( f->ph == 1 ) && ( r->GetID( ) == f->intm ) ) {
+ f->ph = 2; // Go to phase 2
+ }
+
+ if ( f->ph == 1 ) { // In phase 1
+ out_port = dor_next_mesh( r->GetID( ), f->intm );
+ vc_min = 0;
+ vc_max = gNumVCS/2 - 1;
+ } else { // In phase 2
+ out_port = dor_next_mesh( r->GetID( ), f->dest );
+ vc_min = gNumVCS/2;
+ vc_max = gNumVCS - 1;
+ }
+
+ outputs->AddRange( out_port, vc_min, vc_max );
+}
+
+//=============================================================
+
+void romm_ni_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
+{
+ int out_port;
+ int vcs_per_dest = gNumVCS / gNodes;
+
+ outputs->Clear( );
+
+ if ( in_channel == 2*gN ) {
+ f->ph = 1; // Phase 1
+ f->intm = rand_min_intr_mesh( f->src, f->dest );
+ }
+
+ if ( ( f->ph == 1 ) && ( r->GetID( ) == f->intm ) ) {
+ f->ph = 2; // Go to phase 2
+ }
+
+ if ( f->ph == 1 ) { // In phase 1
+ out_port = dor_next_mesh( r->GetID( ), f->intm );
+ } else { // In phase 2
+ out_port = dor_next_mesh( r->GetID( ), f->dest );
+ }
+
+ outputs->AddRange( out_port, f->dest*vcs_per_dest, (f->dest+1)*vcs_per_dest - 1 );
+}
+
+//=============================================================
+
+void min_adapt_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
+{
+ int out_port;
+ int cur, dest;
+ int in_vc;
+
+ outputs->Clear( );
+
+ if ( in_channel == 2*gN ) {
+ in_vc = gNumVCS - 1; // ignore the injection VC
+ } else {
+ in_vc = f->vc;
+ }
+
+ // DOR for the escape channel (VC 0), low priority
+ out_port = dor_next_mesh( r->GetID( ), f->dest );
+ outputs->AddRange( out_port, 0, 0, 0 );
+
+ if ( f->watch ) {
+ cout << "flit " << f->id << " (" << f << ") at " << r->GetID( ) << " destined to "
+ << f->dest << " using channel " << out_port << ", vc range = ["
+ << 0 << "," << gNumVCS - 1 << "] (in_channel is " << in_channel << ")" << endl;
+ }
+
+ if ( in_vc != 0 ) { // If not in the escape VC
+ // Minimal adaptive for all other channels
+ cur = r->GetID( ); dest = f->dest;
+
+ for ( int n = 0; n < gN; ++n ) {
+ if ( ( cur % gK ) != ( dest % gK ) ) {
+ // Add minimal direction in dimension 'n'
+ if ( ( cur % gK ) < ( dest % gK ) ) { // Right
+ outputs->AddRange( 2*n, 1, gNumVCS - 1, 1 );
+ } else { // Left
+ outputs->AddRange( 2*n + 1, 1, gNumVCS - 1, 1 );
+ }
+ }
+ cur /= gK;
+ dest /= gK;
+ }
+ }
+}
+
+//=============================================================
+
+void planar_adapt_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
+{
+ int cur, dest;
+ int vc_mult;
+ int vc_min, vc_max;
+ int d1_min_c;
+ int in_vc;
+ int n;
+
+ bool increase;
+ bool fault;
+ bool atedge;
+
+ outputs->Clear( );
+
+ cur = r->GetID( );
+ dest = f->dest;
+ in_vc = f->vc;
+ vc_mult = gNumVCS / 3;
+
+ if ( cur != dest ) {
+
+ // Find the first unmatched dimension -- except
+ // for when we're in the first dimension because
+ // of misrouting in the last adaptive plane.
+ // In this case, go to the last dimension instead.
+
+ for ( n = 0; n < gN; ++n ) {
+ if ( ( ( cur % gK ) != ( dest % gK ) ) &&
+ !( ( in_channel/2 == 0 ) &&
+ ( n == 0 ) &&
+ ( in_vc < 2*vc_mult ) ) ) {
+ break;
+ }
+
+ cur /= gK;
+ dest /= gK;
+ }
+
+ assert( n < gN );
+
+ if ( f->watch ) {
+ cout << "PLANAR ADAPTIVE: flit " << f->id
+ << " in adaptive plane " << n << " at " << r->GetID( ) << endl;
+ }
+
+ // We're in adaptive plane n
+
+ // Can route productively in d_{i,2}
+ if ( ( cur % gK ) < ( dest % gK ) ) { // Increasing
+ increase = true;
+ if ( !r->IsFaultyOutput( 2*n ) ) {
+ outputs->AddRange( 2*n, 2*vc_mult, gNumVCS - 1 );
+ fault = false;
+
+ if ( f->watch ) {
+ cout << "PLANAR ADAPTIVE: increasing in dimension " << n << endl;
+ }
+ } else {
+ fault = true;
+ }
+ } else { // Decreasing
+ increase = false;
+ if ( !r->IsFaultyOutput( 2*n + 1 ) ) {
+ outputs->AddRange( 2*n + 1, 2*vc_mult, gNumVCS - 1 );
+ fault = false;
+
+ if ( f->watch ) {
+ cout << "PLANAR ADAPTIVE: decreasing in dimension " << n << endl;
+ }
+ } else {
+ fault = true;
+ }
+ }
+
+ n = ( n + 1 ) % gN;
+ cur /= gK;
+ dest /= gK;
+
+ if ( increase ) {
+ vc_min = 0;
+ vc_max = vc_mult - 1;
+ } else {
+ vc_min = vc_mult;
+ vc_max = 2*vc_mult - 1;
+ }
+
+ if ( ( cur % gK ) < ( dest % gK ) ) { // Increasing in d_{i+1}
+ d1_min_c = 2*n;
+ } else if ( ( cur % gK ) != ( dest % gK ) ) { // Decreasing in d_{i+1}
+ d1_min_c = 2*n + 1;
+ } else {
+ d1_min_c = -1;
+ }
+
+ // do we want to 180? if so, the last
+ // route was a misroute in this dimension,
+ // if there is no fault in d_i, just ignore
+ // this dimension, otherwise continue to misroute
+ if ( d1_min_c == in_channel ) {
+ if ( fault ) {
+ d1_min_c = in_channel ^ 1;
+ } else {
+ d1_min_c = -1;
+ }
+
+ if ( f->watch ) {
+ cout << "PLANAR ADAPTIVE: avoiding 180 in dimension " << n << endl;
+ }
+ }
+
+ if ( d1_min_c != -1 ) {
+ if ( !r->IsFaultyOutput( d1_min_c ) ) {
+ outputs->AddRange( d1_min_c, vc_min, vc_max );
+ } else if ( fault ) {
+ // major problem ... fault in d_i and d_{i+1}
+ r->Error( "There seem to be faults in d_i and d_{i+1}" );
+ }
+ } else if ( fault ) { // need to misroute!
+ if ( cur % gK == 0 ) {
+ d1_min_c = 2*n;
+ atedge = true;
+ } else if ( cur % gK == gK - 1 ) {
+ d1_min_c = 2*n + 1;
+ atedge = true;
+ } else {
+ d1_min_c = 2*n + RandomInt( 1 ); // random misroute
+
+ if ( d1_min_c == in_channel ) { // don't 180
+ d1_min_c = in_channel ^ 1;
+ }
+ atedge = false;
+ }
+
+ if ( !r->IsFaultyOutput( d1_min_c ) ) {
+ outputs->AddRange( d1_min_c, vc_min, vc_max );
+ } else if ( !atedge && !r->IsFaultyOutput( d1_min_c ^ 1 ) ) {
+ outputs->AddRange( d1_min_c ^ 1, vc_min, vc_max );
+ } else {
+ // major problem ... fault in d_i and d_{i+1}
+ r->Error( "There seem to be faults in d_i and d_{i+1}" );
+ }
+ }
+ } else {
+ outputs->AddRange( 2*gN, 0, gNumVCS - 1 );
+ }
+}
+
+//=============================================================
+
+void limited_adapt_mesh_old( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
+{
+ int in_vc;
+ int in_dim;
+
+ int min_port;
+
+ bool dor_dim;
+ bool equal;
+
+ int cur, dest;
+
+ outputs->Clear( );
+
+ if ( inject ) {
+ outputs->AddRange( 0, 0, gNumVCS - 1 );
+ f->ph = 0; // zero dimension reversals
+ } else {
+
+ cur = r->GetID( ); dest = f->dest;
+ if ( cur != dest ) {
+
+ if ( f->ph == 0 ) {
+ f->ph = 1;
+
+ in_vc = 0;
+ in_dim = 0;
+ } else {
+ in_vc = f->vc;
+ in_dim = in_channel/2;
+ }
+
+ // The first remaining is the DOR escape path
+ dor_dim = true;
+
+ for ( int n = 0; n < gN; ++n ) {
+ if ( ( cur % gK ) != ( dest % gK ) ) {
+ if ( ( cur % gK ) < ( dest % gK ) ) {
+ min_port = 2*n; // Right
+ } else {
+ min_port = 2*n + 1; // Left
+ }
+
+ if ( dor_dim ) {
+ // Low priority escape path
+ outputs->AddRange( min_port, gNumVCS - 1, gNumVCS - 1, 0 );
+ dor_dim = false;
+ }
+
+ equal = false;
+ } else {
+ equal = true;
+ min_port = 2*n;
+ }
+
+ if ( in_vc < gNumVCS - 1 ) { // adaptive VC's left?
+ if ( n < in_dim ) {
+ // Productive (minimal) direction, with reversal
+ if ( in_vc == gNumVCS - 2 ) {
+ outputs->AddRange( min_port, in_vc + 1, in_vc + 1, equal ? 1 : 2 );
+ } else {
+ outputs->AddRange( min_port, in_vc + 1, gNumVCS - 2, equal ? 1 : 2 );
+ }
+
+ // Unproductive (non-minimal) direction, with reversal
+ if ( in_vc < gNumVCS - 2 ) {
+ if ( in_vc == gNumVCS - 3 ) {
+ outputs->AddRange( min_port ^ 0x1, in_vc + 1, in_vc + 1, 1 );
+ } else {
+ outputs->AddRange( min_port ^ 0x1, in_vc + 1, gNumVCS - 3, 1 );
+ }
+ }
+ } else if ( n == in_dim ) {
+ if ( !equal ) {
+ // Productive (minimal) direction, no reversal
+ outputs->AddRange( min_port, in_vc, gNumVCS - 2, 4 );
+ }
+ } else {
+ // Productive (minimal) direction, no reversal
+ outputs->AddRange( min_port, in_vc, gNumVCS - 2, equal ? 1 : 3 );
+ // Unproductive (non-minimal) direction, no reversal
+ if ( in_vc < gNumVCS - 2 ) {
+ outputs->AddRange( min_port ^ 0x1, in_vc, gNumVCS - 2, 1 );
+ }
+ }
+ }
+
+ cur /= gK;
+ dest /= gK;
+ }
+ } else { // at destination
+ outputs->AddRange( 2*gN, 0, gNumVCS - 1 );
+ }
+ }
+}
+
+void limited_adapt_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
+{
+ int min_port;
+
+ int cur, dest;
+
+ outputs->Clear( );
+
+ if ( inject ) {
+ outputs->AddRange( 0, 0, gNumVCS - 2 );
+ f->dr = 0; // zero dimension reversals
+ } else {
+ cur = r->GetID( ); dest = f->dest;
+
+ if ( cur != dest ) {
+ if ( ( f->vc != gNumVCS - 1 ) &&
+ ( f->dr != gNumVCS - 2 ) ) {
+
+ for ( int n = 0; n < gN; ++n ) {
+ if ( ( cur % gK ) != ( dest % gK ) ) {
+ if ( ( cur % gK ) < ( dest % gK ) ) {
+ min_port = 2*n; // Right
+ } else {
+ min_port = 2*n + 1; // Left
+ }
+
+ // Go in a productive direction with high priority
+ outputs->AddRange( min_port, 0, gNumVCS - 2, 2 );
+
+ // Go in the non-productive direction with low priority
+ outputs->AddRange( min_port ^ 0x1, 0, gNumVCS - 2, 1 );
+ } else {
+ // Both directions are non-productive
+ outputs->AddRange( 2*n, 0, gNumVCS - 2, 1 );
+ outputs->AddRange( 2*n+1, 0, gNumVCS - 2, 1 );
+ }
+
+ cur /= gK;
+ dest /= gK;
+ }
+
+ } else {
+ outputs->AddRange( dor_next_mesh( cur, dest ),
+ gNumVCS - 1, gNumVCS - 1, 0 );
+ }
+
+ } else { // at destination
+ outputs->AddRange( 2*gN, 0, gNumVCS - 1 );
+ }
+ }
+}
+
+//=============================================================
+
+void valiant_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
+{
+ int out_port;
+ int vc_min, vc_max;
+
+ outputs->Clear( );
+
+
+ if ( in_channel == 2*gN ) {
+ f->ph = 1; // Phase 1
+ f->intm = RandomInt( gNodes - 1 );
+ }
+
+ if ( ( f->ph == 1 ) && ( r->GetID( ) == f->intm ) ) {
+ f->ph = 2; // Go to phase 2
+ }
+
+ if ( f->ph == 1 ) { // In phase 1
+ out_port = dor_next_mesh( r->GetID( ), f->intm );
+ vc_min = 0;
+ vc_max = gNumVCS/2 - 1;
+ } else { // In phase 2
+ out_port = dor_next_mesh( r->GetID( ), f->dest );
+ vc_min = gNumVCS/2;
+ vc_max = gNumVCS - 1;
+ }
+
+ outputs->AddRange( out_port, vc_min, vc_max );
+}
+
+//=============================================================
+
+void valiant_torus( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
+{
+ int out_port;
+ int vc_min, vc_max;
+
+ outputs->Clear( );
+
+ if ( in_channel == 2*gN ) {
+ f->ph = 1; // Phase 1
+ f->intm = RandomInt( gNodes - 1 );
+ }
+
+ if ( ( f->ph == 1 ) && ( r->GetID( ) == f->intm ) ) {
+ f->ph = 2; // Go to phase 2
+ in_channel = 2*gN; // ensures correct vc selection at the beginning of phase 2
+ }
+
+ if ( f->ph == 1 ) { // In phase 1
+ dor_next_torus( r->GetID( ), f->intm, in_channel,
+ &out_port, &f->ring_par, false );
+
+ if ( f->ring_par == 0 ) {
+ vc_min = 0;
+ vc_max = gNumVCS/4 - 1;
+ } else {
+ vc_min = gNumVCS/4;
+ vc_max = gNumVCS/2 - 1;
+ }
+ } else { // In phase 2
+ dor_next_torus( r->GetID( ), f->dest, in_channel,
+ &out_port, &f->ring_par, false );
+
+ if ( f->ring_par == 0 ) {
+ vc_min = gNumVCS/2;
+ vc_max = (3*gNumVCS)/4 - 1;
+ } else {
+ vc_min = (3*gNumVCS)/4;
+ vc_max = gNumVCS - 1;
+ }
+ }
+
+ outputs->AddRange( out_port, vc_min, vc_max );
+}
+
+//=============================================================
+
+void valiant_ni_torus( const Router *r, const Flit *f, int in_channel,
+ OutputSet *outputs, bool inject )
+{
+ int out_port;
+ int vc_min, vc_max;
+
+ outputs->Clear( );
+
+ if ( in_channel == 2*gN ) {
+ f->ph = 1; // Phase 1
+ f->intm = RandomInt( gNodes - 1 );
+ }
+
+ if ( ( f->ph == 1 ) && ( r->GetID( ) == f->intm ) ) {
+ f->ph = 2; // Go to phase 2
+ in_channel = 2*gN; // ensures correct vc selection at the beginning of phase 2
+ }
+
+ if ( f->ph == 1 ) { // In phase 1
+ dor_next_torus( r->GetID( ), f->intm, in_channel,
+ &out_port, &f->ring_par, false );
+
+ if ( f->ring_par == 0 ) {
+ vc_min = f->dest;
+ vc_max = f->dest;
+ } else {
+ vc_min = f->dest + gNodes;
+ vc_max = f->dest + gNodes;
+ }
+
+ } else { // In phase 2
+ dor_next_torus( r->GetID( ), f->dest, in_channel,
+ &out_port, &f->ring_par, false );
+
+ if ( f->ring_par == 0 ) {
+ vc_min = f->dest + 2*gNodes;
+ vc_max = f->dest + 2*gNodes;
+ } else {
+ vc_min = f->dest + 3*gNodes;
+ vc_max = f->dest + 3*gNodes;
+ }
+ }
+
+ if ( f->watch ) {
+ cout << "flit " << f->id << " (" << f << ") at " << r->GetID( ) << " destined to "
+ << f->dest << " using channel " << out_port << ", vc range = ["
+ << vc_min << "," << vc_max
+ << "] (in_channel is " << in_channel << ")" << endl;
+ }
+
+ outputs->AddRange( out_port, vc_min, vc_max );
+}
+
+//=============================================================
+
+void dim_order_torus( const Router *r, const Flit *f, int in_channel,
+ OutputSet *outputs, bool inject )
+{
+ int cur;
+ int dest;
+
+ int out_port;
+ int vc_min, vc_max;
+
+ outputs->Clear( );
+
+ cur = r->GetID( );
+ dest = f->dest;
+
+ dor_next_torus( cur, dest, in_channel,
+ &out_port, &f->ring_par, false );
+
+ if ( f->ring_par == 0 ) {
+ vc_min = 0;
+ vc_max = gNumVCS/2 - 1;
+ } else {
+ vc_min = gNumVCS/2;
+ vc_max = gNumVCS - 1;
+ }
+
+ if ( f->watch ) {
+ cout << "flit " << f->id << " (" << f << ") at " << r->GetID( ) << " destined to "
+ << f->dest << " using channel " << out_port << ", vc range = ["
+ << vc_min << "," << vc_max << "] (in_channel is " << in_channel << ")" << endl;
+ }
+
+ outputs->AddRange( out_port, vc_min, vc_max );
+}
+
+//=============================================================
+
+void dim_order_ni_torus( const Router *r, const Flit *f, int in_channel,
+ OutputSet *outputs, bool inject )
+{
+ int cur;
+ int dest;
+
+ int out_port;
+ int vcs_per_dest = gNumVCS / gNodes;
+
+ outputs->Clear( );
+
+ cur = r->GetID( );
+ dest = f->dest;
+
+ outputs->Clear( );
+ dor_next_torus( cur, dest, in_channel,
+ &out_port, &f->ring_par, false );
+
+ if ( f->watch ) {
+ cout << "flit " << f->id << " (" << f << ") at " << r->GetID( ) << " destined to "
+ << f->dest << " using channel " << out_port << ", vc range = ["
+ << f->dest*vcs_per_dest << "," << (f->dest+1)*vcs_per_dest - 1
+ << "] (in_channel is " << in_channel << ")" << endl;
+ }
+
+ outputs->AddRange( out_port, f->dest*vcs_per_dest, (f->dest+1)*vcs_per_dest - 1 );
+}
+
+//=============================================================
+
+void dim_order_bal_torus( const Router *r, const Flit *f, int in_channel,
+ OutputSet *outputs, bool inject )
+{
+ int cur;
+ int dest;
+
+ int out_port;
+ int vc_min, vc_max;
+
+ outputs->Clear( );
+
+ cur = r->GetID( );
+ dest = f->dest;
+
+ dor_next_torus( cur, dest, in_channel,
+ &out_port, &f->ring_par, true );
+
+ if ( f->ring_par == 0 ) {
+ vc_min = 0;
+ vc_max = gNumVCS/2 - 1;
+ } else {
+ vc_min = gNumVCS/2;
+ vc_max = gNumVCS - 1;
+ }
+
+ if ( f->watch ) {
+ cout << "flit " << f->id << " (" << f << ") at " << r->GetID( ) << " destined to "
+ << f->dest << " using channel " << out_port << ", vc range = ["
+ << vc_min << "," << vc_max << "] (in_channel is " << in_channel << ")" << endl;
+ }
+
+ outputs->AddRange( out_port, vc_min, vc_max );
+}
+
+//=============================================================
+
+void min_adapt_torus( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
+{
+ int cur, dest, dist2;
+ int in_vc;
+ int out_port;
+
+ outputs->Clear( );
+
+ if ( in_channel == 2*gN ) {
+ in_vc = gNumVCS - 1; // ignore the injection VC
+ } else {
+ in_vc = f->vc;
+ }
+
+ if ( in_vc > 1 ) { // If not in the escape VCs
+ // Minimal adaptive for all other channels
+ cur = r->GetID( ); dest = f->dest;
+
+ for ( int n = 0; n < gN; ++n ) {
+ if ( ( cur % gK ) != ( dest % gK ) ) {
+ dist2 = gK - 2 * ( ( ( dest % gK ) - ( cur % gK ) + gK ) % gK );
+
+ if ( dist2 > 0 ) { /*) ||
+ ( ( dist2 == 0 ) && ( RandomInt( 1 ) ) ) ) {*/
+ outputs->AddRange( 2*n, 3, 3, 1 ); // Right
+ } else {
+ outputs->AddRange( 2*n + 1, 3, 3, 1 ); // Left
+ }
+ }
+
+ cur /= gK;
+ dest /= gK;
+ }
+
+ // DOR for the escape channel (VCs 0-1), low priority ---
+ // trick the algorithm with the in channel. want VC assignment
+ // as if we had injected at this node
+ dor_next_torus( r->GetID( ), f->dest, 2*gN,
+ &out_port, &f->ring_par, false );
+ } else {
+ // DOR for the escape channel (VCs 0-1), low priority
+ dor_next_torus( r->GetID( ), f->dest, in_channel,
+ &out_port, &f->ring_par, false );
+ }
+
+ if ( f->ring_par == 0 ) {
+ outputs->AddRange( out_port, 0, 0, 0 );
+ } else {
+ outputs->AddRange( out_port, 1, 1, 0 );
+ }
+
+ if ( f->watch ) {
+ cout << "flit " << f->id << " (" << f << ") at " << r->GetID( ) << " destined to "
+ << f->dest << " using channel " << out_port << ", vc range = ["
+ << 0 << "," << gNumVCS - 1 << "] (in_channel is " << in_channel << ")" << endl;
+ }
+
+
+}
+
+//=============================================================
+
+void dest_tag( const Router *r, const Flit *f, int in_channel,
+ OutputSet *outputs, bool inject )
+{
+ outputs->Clear( );
+
+ int stage = ( r->GetID( ) * gK ) / gNodes;
+ int dest = f->dest;
+
+ while ( stage < ( gN - 1 ) ) {
+ dest /= gK;
+ ++stage;
+ }
+
+ int out_port = dest % gK;
+
+ outputs->AddRange( out_port, 0, gNumVCS - 1 );
+}
+
+//=============================================================
+
+void chaos_torus( const Router *r, const Flit *f,
+ int in_channel, OutputSet *outputs, bool inject )
+{
+ int cur, dest;
+ int dist2;
+
+ outputs->Clear( );
+
+ cur = r->GetID( ); dest = f->dest;
+
+ if ( cur != dest ) {
+ for ( int n = 0; n < gN; ++n ) {
+
+ if ( ( cur % gK ) != ( dest % gK ) ) {
+ dist2 = gK - 2 * ( ( ( dest % gK ) - ( cur % gK ) + gK ) % gK );
+
+ if ( dist2 >= 0 ) {
+ outputs->AddRange( 2*n, 0, 0 ); // Right
+ }
+
+ if ( dist2 <= 0 ) {
+ outputs->AddRange( 2*n + 1, 0, 0 ); // Left
+ }
+ }
+
+ cur /= gK;
+ dest /= gK;
+ }
+ } else {
+ outputs->AddRange( 2*gN, 0, 0 );
+ }
+}
+
+
+//=============================================================
+
+void chaos_mesh( const Router *r, const Flit *f,
+ int in_channel, OutputSet *outputs, bool inject )
+{
+ int cur, dest;
+
+ outputs->Clear( );
+
+ cur = r->GetID( ); dest = f->dest;
+
+ if ( cur != dest ) {
+ for ( int n = 0; n < gN; ++n ) {
+ if ( ( cur % gK ) != ( dest % gK ) ) {
+ // Add minimal direction in dimension 'n'
+ if ( ( cur % gK ) < ( dest % gK ) ) { // Right
+ outputs->AddRange( 2*n, 0, 0 );
+ } else { // Left
+ outputs->AddRange( 2*n + 1, 0, 0 );
+ }
+ }
+ cur /= gK;
+ dest /= gK;
+ }
+ } else {
+ outputs->AddRange( 2*gN, 0, 0 );
+ }
+}
+
+//=============================================================
+
+void InitializeRoutingMap( )
+{
+ /* Register routing functions here */
+
+ gRoutingFunctionMap["single_single"] = &singlerf;
+
+ gRoutingFunctionMap["dim_order_mesh"] = &dim_order_mesh;
+ gRoutingFunctionMap["dim_order_ni_mesh"] = &dim_order_ni_mesh;
+ gRoutingFunctionMap["dim_order_torus"] = &dim_order_torus;
+ gRoutingFunctionMap["dim_order_ni_torus"] = &dim_order_ni_torus;
+ gRoutingFunctionMap["dim_order_bal_torus"] = &dim_order_bal_torus;
+
+ gRoutingFunctionMap["romm_mesh"] = &romm_mesh;
+ gRoutingFunctionMap["romm_ni_mesh"] = &romm_ni_mesh;
+
+ gRoutingFunctionMap["min_adapt_mesh"] = &min_adapt_mesh;
+ gRoutingFunctionMap["min_adapt_torus"] = &min_adapt_torus;
+
+ gRoutingFunctionMap["planar_adapt_mesh"] = &planar_adapt_mesh;
+
+ gRoutingFunctionMap["limited_adapt_mesh"] = &limited_adapt_mesh;
+
+ gRoutingFunctionMap["valiant_mesh"] = &valiant_mesh;
+ gRoutingFunctionMap["valiant_torus"] = &valiant_torus;
+ gRoutingFunctionMap["valiant_ni_torus"] = &valiant_ni_torus;
+
+ gRoutingFunctionMap["dest_tag_fly"] = &dest_tag;
+
+ gRoutingFunctionMap["chaos_mesh"] = &chaos_mesh;
+ gRoutingFunctionMap["chaos_torus"] = &chaos_torus;
+}
+
+tRoutingFunction GetRoutingFunction( const Configuration& config )
+{
+ map<string, tRoutingFunction>::const_iterator match;
+ tRoutingFunction rf;
+
+ string fn, topo, fn_topo;
+
+ gNumVCS = config.GetInt( "num_vcs" );
+
+ config.GetStr( "topology", topo );
+
+ config.GetStr( "routing_function", fn, "none" );
+ fn_topo = fn + "_" + topo;
+ match = gRoutingFunctionMap.find( fn_topo );
+
+ if ( match != gRoutingFunctionMap.end( ) ) {
+ rf = match->second;
+ } else {
+ if ( fn == "none" ) {
+ cout << "Error: No routing function specified in configuration." << endl;
+ } else {
+ cout << "Error: Undefined routing function '" << fn << "' for the topology '"
+ << topo << "'." << endl;
+ }
+ exit(-1);
+ }
+
+ return rf;
+}
+
+
|
