From 69f2911e04ffb1b19eef1fafb8c040af271f656e Mon Sep 17 00:00:00 2001 From: Tor Aamodt Date: Thu, 15 Jul 2010 18:09:46 -0800 Subject: creating branch for adding support for CUDA 3.x and Fermi [git-p4: depot-paths = "//depot/gpgpu_sim_research/fermi/distribution/": change = 6829] --- src/intersim/routefunc.cpp | 1045 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1045 insertions(+) create mode 100644 src/intersim/routefunc.cpp (limited to 'src/intersim/routefunc.cpp') 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 +#include +#include + +#include "routefunc.hpp" +#include "kncube.hpp" +#include "random_utils.hpp" + +map 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::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; +} + + -- cgit v1.3