aboutsummaryrefslogtreecommitdiff
path: root/src/intersim2/.svn/pristine/42
diff options
context:
space:
mode:
authorMyrice <[email protected]>2015-04-07 14:43:05 -0700
committerMyrice <[email protected]>2015-04-07 14:43:05 -0700
commit6b9eb92bd0b03d69a2f2e9c075a8af99d860d4d1 (patch)
treec741ac460cb86219446070765be97536143def55 /src/intersim2/.svn/pristine/42
parent4dc9d53085b568aea0cefe75d599f87bb5e0841f (diff)
Booksim2 abandoned svn and moved to github (https://github.com/booksim/booksim2). This .svn folder is useless now and should be deleted.
For further integration, a git submodule/git subtree may be used. Since I modified their source code, we cannot use git submodule/git subtree easily. Signed-off-by: Myrice <[email protected]>
Diffstat (limited to 'src/intersim2/.svn/pristine/42')
-rw-r--r--src/intersim2/.svn/pristine/42/42777bd5ccda83625dfbf29e7aec13f2e773373a.svn-base1999
1 files changed, 0 insertions, 1999 deletions
diff --git a/src/intersim2/.svn/pristine/42/42777bd5ccda83625dfbf29e7aec13f2e773373a.svn-base b/src/intersim2/.svn/pristine/42/42777bd5ccda83625dfbf29e7aec13f2e773373a.svn-base
deleted file mode 100644
index 6260406..0000000
--- a/src/intersim2/.svn/pristine/42/42777bd5ccda83625dfbf29e7aec13f2e773373a.svn-base
+++ /dev/null
@@ -1,1999 +0,0 @@
-// $Id$
-
-/*
- 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.
-*/
-
-/*routefunc.cpp
- *
- *This is where most of the routing functions reside. Some of the topologies
- *has their own "register routing functions" which must be called to access
- *those routing functions.
- *
- *After writing a routing function, don't forget to register it. The reg
- *format is rfname_topologyname.
- *
- */
-
-#include <map>
-#include <cstdlib>
-#include <cassert>
-
-#include "booksim.hpp"
-#include "routefunc.hpp"
-#include "kncube.hpp"
-#include "random_utils.hpp"
-#include "misc_utils.hpp"
-#include "fattree.hpp"
-#include "tree4.hpp"
-#include "qtree.hpp"
-#include "cmesh.hpp"
-
-
-
-map<string, tRoutingFunction> gRoutingFunctionMap;
-
-/* Global information used by routing functions */
-
-int gNumVCs;
-
-/* Add more functions here
- *
- */
-
-// ============================================================
-// Balfour-Schultz
-int gReadReqBeginVC, gReadReqEndVC;
-int gWriteReqBeginVC, gWriteReqEndVC;
-int gReadReplyBeginVC, gReadReplyEndVC;
-int gWriteReplyBeginVC, gWriteReplyEndVC;
-
-// ============================================================
-// QTree: Nearest Common Ancestor
-// ===
-void qtree_nca( const Router *r, const Flit *f,
- int in_channel, OutputSet* outputs, bool inject)
-{
- 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 height = QTree::HeightFromID( r->GetID() );
- int pos = QTree::PosFromID( r->GetID() );
-
- int dest = f->dest;
-
- for (int i = height+1; i < gN; i++)
- dest /= gK;
- if ( pos == dest / gK )
- // Route down to child
- out_port = dest % gK ;
- else
- // Route up to parent
- out_port = gK;
-
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-// ============================================================
-// Tree4: Nearest Common Ancestor w/ Adaptive Routing Up
-// ===
-void tree4_anca( const Router *r, const Flit *f,
- int in_channel, OutputSet* outputs, bool inject)
-{
- 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 range = 1;
-
- int out_port;
-
- if(inject) {
-
- out_port = -1;
-
- } else {
-
- int dest = f->dest;
-
- const int NPOS = 16;
-
- int rH = r->GetID( ) / NPOS;
- int rP = r->GetID( ) % NPOS;
-
- if ( rH == 0 ) {
- dest /= 16;
- out_port = 2 * dest + RandomInt(1);
- } else if ( rH == 1 ) {
- dest /= 4;
- if ( dest / 4 == rP / 2 )
- out_port = dest % 4;
- else {
- out_port = gK;
- range = gK;
- }
- } else {
- if ( dest/4 == rP )
- out_port = dest % 4;
- else {
- out_port = gK;
- range = 2;
- }
- }
-
- // cout << "Router("<<rH<<","<<rP<<"): id= " << f->id << " dest= " << f->dest << " out_port = "
- // << out_port << endl;
-
- }
-
- outputs->Clear( );
-
- for (int i = 0; i < range; ++i)
- outputs->AddRange( out_port + i, vcBegin, vcEnd );
-}
-
-// ============================================================
-// Tree4: Nearest Common Ancestor w/ Random Routing Up
-// ===
-void tree4_nca( const Router *r, const Flit *f,
- int in_channel, OutputSet* outputs, bool inject)
-{
- 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 = f->dest;
-
- const int NPOS = 16;
-
- int rH = r->GetID( ) / NPOS;
- int rP = r->GetID( ) % NPOS;
-
- if ( rH == 0 ) {
- dest /= 16;
- out_port = 2 * dest + RandomInt(1);
- } else if ( rH == 1 ) {
- dest /= 4;
- if ( dest / 4 == rP / 2 )
- out_port = dest % 4;
- else
- out_port = gK + RandomInt(gK-1);
- } else {
- if ( dest/4 == rP )
- out_port = dest % 4;
- else
- out_port = gK + RandomInt(1);
- }
-
- // cout << "Router("<<rH<<","<<rP<<"): id= " << f->id << " dest= " << f->dest << " out_port = "
- // << out_port << endl;
-
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-// ============================================================
-// FATTREE: Nearest Common Ancestor w/ Random Routing Up
-// ===
-void fattree_nca( const Router *r, const Flit *f,
- int in_channel, OutputSet* outputs, bool inject)
-{
- 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 = f->dest;
- int router_id = r->GetID(); //routers are numbered with smallest at the top level
- int routers_per_level = powi(gK, gN-1);
- int pos = router_id%routers_per_level;
- int router_depth = router_id/ routers_per_level; //which level
- int routers_per_neighborhood = powi(gK,gN-router_depth-1);
- int router_neighborhood = pos/routers_per_neighborhood; //coverage of this tree
- int router_coverage = powi(gK, gN-router_depth); //span of the tree from this router
-
-
- //NCA reached going down
- if(dest <(router_neighborhood+1)* router_coverage &&
- dest >=router_neighborhood* router_coverage){
- //down ports are numbered first
-
- //ejection
- if(router_depth == gN-1){
- out_port = dest%gK;
- } else {
- //find the down port for the destination
- int router_branch_coverage = powi(gK, gN-(router_depth+1));
- out_port = (dest-router_neighborhood* router_coverage)/router_branch_coverage;
- }
- } else {
- //up ports are numbered last
- assert(in_channel<gK);//came from a up channel
- out_port = gK+RandomInt(gK-1);
- }
- }
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-// ============================================================
-// FATTREE: Nearest Common Ancestor w/ Adaptive Routing Up
-// ===
-void fattree_anca( const Router *r, const Flit *f,
- int in_channel, OutputSet* outputs, bool inject)
-{
-
- 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 = f->dest;
- int router_id = r->GetID(); //routers are numbered with smallest at the top level
- int routers_per_level = powi(gK, gN-1);
- int pos = router_id%routers_per_level;
- int router_depth = router_id/ routers_per_level; //which level
- int routers_per_neighborhood = powi(gK,gN-router_depth-1);
- int router_neighborhood = pos/routers_per_neighborhood; //coverage of this tree
- int router_coverage = powi(gK, gN-router_depth); //span of the tree from this router
-
-
- //NCA reached going down
- if(dest <(router_neighborhood+1)* router_coverage &&
- dest >=router_neighborhood* router_coverage){
- //down ports are numbered first
-
- //ejection
- if(router_depth == gN-1){
- out_port = dest%gK;
- } else {
- //find the down port for the destination
- int router_branch_coverage = powi(gK, gN-(router_depth+1));
- out_port = (dest-router_neighborhood* router_coverage)/router_branch_coverage;
- }
- } else {
- //up ports are numbered last
- assert(in_channel<gK);//came from a up channel
- out_port = gK;
- int random1 = RandomInt(gK-1); // Chose two ports out of the possible at random, compare loads, choose one.
- int random2 = RandomInt(gK-1);
- if (r->GetUsedCredit(out_port + random1) > r->GetUsedCredit(out_port + random2)){
- out_port = out_port + random2;
- }else{
- out_port = out_port + random1;
- }
- }
- }
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-
-
-
-// ============================================================
-// Mesh - adatpive XY,YX Routing
-// pick xy or yx min routing adaptively at the source router
-// ===
-
-int dor_next_mesh( int cur, int dest, bool descending = false );
-
-void adaptive_xy_yx_mesh( const Router *r, const Flit *f,
- int in_channel, OutputSet *outputs, bool inject )
-{
- 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(r->GetID() == f->dest) {
-
- // at destination router, we don't need to separate VCs by dim order
- out_port = 2*gN;
-
- } 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 = dor_next_mesh( r->GetID(), f->dest, false );
- int out_port_yx = dor_next_mesh( r->GetID(), f->dest, true );
-
- // Route order (XY or YX) determined when packet is injected
- // into the network, adaptively
- bool x_then_y;
- if(in_channel < 2*gN){
- x_then_y = (f->vc < (vcBegin + available_vcs));
- } else {
- 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);
- }
- }
-
- 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 );
-
-}
-
-void xy_yx_mesh( const Router *r, const Flit *f,
- int in_channel, OutputSet *outputs, bool inject )
-{
- 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(r->GetID() == f->dest) {
-
- // at destination router, we don't need to separate VCs by dim order
- out_port = 2*gN;
-
- } 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);
-
- // Route order (XY or YX) determined when packet is injected
- // into the network
- bool x_then_y = ((in_channel < 2*gN) ?
- (f->vc < (vcBegin + available_vcs)) :
- (RandomInt(1) > 0));
-
- if(x_then_y) {
- out_port = dor_next_mesh( r->GetID(), f->dest, false );
- vcEnd -= available_vcs;
- } else {
- out_port = dor_next_mesh( r->GetID(), f->dest, true );
- vcBegin += available_vcs;
- }
-
- }
-
- outputs->Clear();
-
- outputs->AddRange( out_port , vcBegin, vcEnd );
-
-}
-
-//
-// End Balfour-Schultz
-//=============================================================
-
-//=============================================================
-
-int dor_next_mesh( int cur, int dest, bool descending )
-{
- if ( cur == dest ) {
- return 2*gN; // Eject
- }
-
- int dim_left;
-
- if(descending) {
- for ( dim_left = ( gN - 1 ); dim_left > 0; --dim_left ) {
- if ( ( cur * gK / gNodes ) != ( dest * gK / gNodes ) ) { break; }
- cur = (cur * gK) % gNodes; dest = (dest * gK) % gNodes;
- }
- cur = (cur * gK) / gNodes;
- dest = (dest * gK) / gNodes;
- } else {
- for ( dim_left = 0; dim_left < ( gN - 1 ); ++dim_left ) {
- if ( ( cur % gK ) != ( dest % gK ) ) { break; }
- cur /= gK; dest /= gK;
- }
- cur %= gK;
- dest %= gK;
- }
-
- if ( cur < dest ) {
- return 2*dim_left; // Right
- } else {
- return 2*dim_left + 1; // Left
- }
-}
-
-//=============================================================
-
-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 ( partition ) {
- 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 = inject ? -1 : dor_next_mesh( 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;
- }
- assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0)));
-
- if ( !inject && f->watch ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "Adding VC range ["
- << vcBegin << ","
- << vcEnd << "]"
- << " at output port " << out_port
- << " for flit " << f->id
- << " (input port " << in_channel
- << ", destination " << f->dest << ")"
- << "." << endl;
- }
-
- outputs->Clear();
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-//=============================================================
-
-void dim_order_ni_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
-{
- int out_port = inject ? -1 : dor_next_mesh( 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;
- }
- assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0)));
-
- // at the destination router, we don't need to separate VCs by destination
- if(inject || (r->GetID() != f->dest)) {
-
- int const vcs_per_dest = (vcEnd - vcBegin + 1) / gNodes;
- assert(vcs_per_dest > 0);
-
- vcBegin += f->dest * vcs_per_dest;
- vcEnd = vcBegin + vcs_per_dest - 1;
-
- }
-
- if( !inject && f->watch ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "Adding VC range ["
- << vcBegin << ","
- << vcEnd << "]"
- << " at output port " << out_port
- << " for flit " << f->id
- << " (input port " << in_channel
- << ", destination " << f->dest << ")"
- << "." << endl;
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-//=============================================================
-
-void dim_order_pni_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
-{
- int out_port = inject ? -1 : dor_next_mesh( 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;
- }
- assert(((f->vc >= vcBegin) && (f->vc <= vcEnd)) || (inject && (f->vc < 0)));
-
- if(inject || (r->GetID() != f->dest)) {
- int next_coord = f->dest;
- if(!inject) {
- int out_dim = out_port / 2;
- for(int d = 0; d < out_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;
- }
-
- if( !inject && f->watch ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "Adding VC range ["
- << vcBegin << ","
- << vcEnd << "]"
- << " at output port " << out_port
- << " for flit " << f->id
- << " (input port " << in_channel
- << ", destination " << f->dest << ")"
- << "." << endl;
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-//=============================================================
-
-// 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 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 == 2*gN ) {
- f->ph = 0; // Phase 0
- f->intm = rand_min_intr_mesh( f->src, f->dest );
- }
-
- if ( ( f->ph == 0 ) && ( r->GetID( ) == f->intm ) ) {
- f->ph = 1; // Go to phase 1
- }
-
- out_port = dor_next_mesh( r->GetID( ), (f->ph == 0) ? f->intm : f->dest );
-
- // at the destination router, we don't need to separate VCs by phase
- if(r->GetID() != f->dest) {
-
- //each class must have at least 2 vcs assigned or else valiant valiant will deadlock
- int available_vcs = (vcEnd - vcBegin + 1) / 2;
- assert(available_vcs > 0);
-
- if(f->ph == 0) {
- vcEnd -= available_vcs;
- } else {
- assert(f->ph == 1);
- vcBegin += available_vcs;
- }
- }
-
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-//=============================================================
-
-void romm_ni_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
-{
- 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)));
-
- // at the destination router, we don't need to separate VCs by destination
- if(inject || (r->GetID() != f->dest)) {
-
- int const vcs_per_dest = (vcEnd - vcBegin + 1) / gNodes;
- assert(vcs_per_dest > 0);
-
- vcBegin += f->dest * vcs_per_dest;
- vcEnd = vcBegin + vcs_per_dest - 1;
-
- }
-
- int out_port;
-
- if(inject) {
-
- out_port = -1;
-
- } else {
-
- if ( in_channel == 2*gN ) {
- f->ph = 0; // Phase 0
- f->intm = rand_min_intr_mesh( f->src, f->dest );
- }
-
- if ( ( f->ph == 0 ) && ( r->GetID( ) == f->intm ) ) {
- f->ph = 1; // Go to phase 1
- }
-
- out_port = dor_next_mesh( r->GetID( ), (f->ph == 0) ? f->intm : f->dest );
-
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-//=============================================================
-
-void min_adapt_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
-{
- 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)));
-
- outputs->Clear( );
-
- if(inject) {
- // injection can use all VCs
- outputs->AddRange(-1, vcBegin, vcEnd);
- return;
- } else if(r->GetID() == f->dest) {
- // ejection can also use all VCs
- outputs->AddRange(2*gN, vcBegin, vcEnd);
- return;
- }
-
- int in_vc;
-
- if ( in_channel == 2*gN ) {
- in_vc = vcEnd; // ignore the injection VC
- } else {
- in_vc = f->vc;
- }
-
- // DOR for the escape channel (VC 0), low priority
- int out_port = dor_next_mesh( r->GetID( ), f->dest );
- outputs->AddRange( out_port, 0, vcBegin, vcBegin );
-
- if ( f->watch ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "Adding VC range ["
- << vcBegin << ","
- << vcBegin << "]"
- << " at output port " << out_port
- << " for flit " << f->id
- << " (input port " << in_channel
- << ", destination " << f->dest << ")"
- << "." << endl;
- }
-
- if ( in_vc != vcBegin ) { // If not in the escape VC
- // Minimal adaptive for all other channels
- int cur = r->GetID( );
- int 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
- if ( f->watch ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "Adding VC range ["
- << (vcBegin+1) << ","
- << vcEnd << "]"
- << " at output port " << 2*n
- << " with priority " << 1
- << " for flit " << f->id
- << " (input port " << in_channel
- << ", destination " << f->dest << ")"
- << "." << endl;
- }
- outputs->AddRange( 2*n, vcBegin+1, vcEnd, 1 );
- } else { // Left
- if ( f->watch ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "Adding VC range ["
- << (vcBegin+1) << ","
- << vcEnd << "]"
- << " at output port " << 2*n+1
- << " with priority " << 1
- << " for flit " << f->id
- << " (input port " << in_channel
- << ", destination " << f->dest << ")"
- << "." << endl;
- }
- outputs->AddRange( 2*n + 1, vcBegin+1, vcEnd, 1 );
- }
- }
- cur /= gK;
- dest /= gK;
- }
- }
-}
-
-//=============================================================
-
-void planar_adapt_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
-{
- 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)));
-
- outputs->Clear( );
-
- if(inject) {
- // injection can use all VCs
- outputs->AddRange(-1, vcBegin, vcEnd);
- return;
- }
-
- int cur = r->GetID( );
- int dest = f->dest;
-
- if ( cur != dest ) {
-
- int in_vc = f->vc;
- int vc_mult = (vcEnd - vcBegin + 1) / 3;
-
- // 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.
-
- int n;
- for ( n = 0; n < gN; ++n ) {
- if ( ( ( cur % gK ) != ( dest % gK ) ) &&
- !( ( in_channel/2 == 0 ) &&
- ( n == 0 ) &&
- ( in_vc < vcBegin+2*vc_mult ) ) ) {
- break;
- }
-
- cur /= gK;
- dest /= gK;
- }
-
- assert( n < gN );
-
- if ( f->watch ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "PLANAR ADAPTIVE: flit " << f->id
- << " in adaptive plane " << n << "." << endl;
- }
-
- // We're in adaptive plane n
-
- // Can route productively in d_{i,2}
- bool increase;
- bool fault;
- if ( ( cur % gK ) < ( dest % gK ) ) { // Increasing
- increase = true;
- if ( !r->IsFaultyOutput( 2*n ) ) {
- outputs->AddRange( 2*n, vcBegin+2*vc_mult, vcEnd );
- fault = false;
-
- if ( f->watch ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "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, vcBegin+2*vc_mult, vcEnd );
- fault = false;
-
- if ( f->watch ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "PLANAR ADAPTIVE: decreasing in dimension " << n
- << "." << endl;
- }
- } else {
- fault = true;
- }
- }
-
- n = ( n + 1 ) % gN;
- cur /= gK;
- dest /= gK;
-
- if ( !increase ) {
- vcBegin += vc_mult;
- }
- vcEnd = vcBegin + vc_mult - 1;
-
- int d1_min_c;
- 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 ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "PLANAR ADAPTIVE: avoiding 180 in dimension " << n
- << "." << endl;
- }
- }
-
- if ( d1_min_c != -1 ) {
- if ( !r->IsFaultyOutput( d1_min_c ) ) {
- outputs->AddRange( d1_min_c, vcBegin, vcEnd );
- } 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!
- bool atedge;
- 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, vcBegin, vcEnd );
- } else if ( !atedge && !r->IsFaultyOutput( d1_min_c ^ 1 ) ) {
- outputs->AddRange( d1_min_c ^ 1, vcBegin, vcEnd );
- } 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, vcBegin, vcEnd );
- }
-}
-
-//=============================================================
-/*
- FIXME: This is broken (note that f->dr is never actually modified).
- Even if it were, this should really use f->ph instead of introducing a single-
- use field.
-
-void limited_adapt_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
-{
- outputs->Clear( );
-
- 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)));
-
- if ( inject ) {
- outputs->AddRange( -1, vcBegin, vcEnd - 1 );
- f->dr = 0; // zero dimension reversals
- return;
- }
-
- int cur = r->GetID( );
- int dest = f->dest;
-
- if ( cur != dest ) {
- if ( ( f->vc != vcEnd ) &&
- ( f->dr != vcEnd - 1 ) ) {
-
- for ( int n = 0; n < gN; ++n ) {
- if ( ( cur % gK ) != ( dest % gK ) ) {
- int min_port;
- 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, vcBegin, vcEnd - 1, 2 );
-
- // Go in the non-productive direction with low priority
- outputs->AddRange( min_port ^ 0x1, vcBegin, vcEnd - 1, 1 );
- } else {
- // Both directions are non-productive
- outputs->AddRange( 2*n, vcBegin, vcEnd - 1, 1 );
- outputs->AddRange( 2*n+1, vcBegin, vcEnd - 1, 1 );
- }
-
- cur /= gK;
- dest /= gK;
- }
-
- } else {
- outputs->AddRange( dor_next_mesh( cur, dest ),
- vcEnd, vcEnd, 0 );
- }
-
- } else { // at destination
- outputs->AddRange( 2*gN, vcBegin, vcEnd );
- }
-}
-*/
-//=============================================================
-
-void valiant_mesh( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
-{
- 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 == 2*gN ) {
- f->ph = 0; // Phase 0
- f->intm = RandomInt( gNodes - 1 );
- }
-
- if ( ( f->ph == 0 ) && ( r->GetID( ) == f->intm ) ) {
- f->ph = 1; // Go to phase 1
- }
-
- out_port = dor_next_mesh( r->GetID( ), (f->ph == 0) ? f->intm : f->dest );
-
- // at the destination router, we don't need to separate VCs by phase
- if(r->GetID() != f->dest) {
-
- //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 {
- assert(f->ph == 1);
- vcBegin += available_vcs;
- }
- }
-
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-//=============================================================
-
-void valiant_torus( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
-{
- 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 phase;
- if ( in_channel == 2*gN ) {
- phase = 0; // Phase 0
- f->intm = RandomInt( gNodes - 1 );
- } else {
- phase = f->ph / 2;
- }
-
- if ( ( phase == 0 ) && ( r->GetID( ) == f->intm ) ) {
- phase = 1; // Go to phase 1
- in_channel = 2*gN; // ensures correct vc selection at the beginning of phase 2
- }
-
- int ring_part;
- dor_next_torus( r->GetID( ), (phase == 0) ? f->intm : f->dest, in_channel,
- &out_port, &ring_part, false );
-
- f->ph = 2 * phase + ring_part;
-
- // at the destination router, we don't need to separate VCs by phase, etc.
- if(r->GetID() != f->dest) {
-
- int const ring_available_vcs = (vcEnd - vcBegin + 1) / 2;
- assert(ring_available_vcs > 0);
-
- if(ring_part == 0) {
- vcEnd -= ring_available_vcs;
- } else {
- assert(ring_part == 1);
- vcBegin += ring_available_vcs;
- }
-
- int const ph_available_vcs = ring_available_vcs / 2;
- assert(ph_available_vcs > 0);
-
- if(phase == 0) {
- vcEnd -= ph_available_vcs;
- } else {
- assert(phase == 1);
- vcBegin += ph_available_vcs;
- }
- }
-
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-//=============================================================
-
-void valiant_ni_torus( const Router *r, const Flit *f, int in_channel,
- OutputSet *outputs, bool inject )
-{
- 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)));
-
- // at the destination router, we don't need to separate VCs by destination
- if(inject || (r->GetID() != f->dest)) {
-
- int const vcs_per_dest = (vcEnd - vcBegin + 1) / gNodes;
- assert(vcs_per_dest > 0);
-
- vcBegin += f->dest * vcs_per_dest;
- vcEnd = vcBegin + vcs_per_dest - 1;
-
- }
-
- int out_port;
-
- if(inject) {
-
- out_port = -1;
-
- } else {
-
- int phase;
- if ( in_channel == 2*gN ) {
- phase = 0; // Phase 0
- f->intm = RandomInt( gNodes - 1 );
- } else {
- phase = f->ph / 2;
- }
-
- if ( ( f->ph == 0 ) && ( r->GetID( ) == f->intm ) ) {
- f->ph = 1; // Go to phase 1
- in_channel = 2*gN; // ensures correct vc selection at the beginning of phase 2
- }
-
- int ring_part;
- dor_next_torus( r->GetID( ), (f->ph == 0) ? f->intm : f->dest, in_channel,
- &out_port, &ring_part, false );
-
- f->ph = 2 * phase + ring_part;
-
- // at the destination router, we don't need to separate VCs by phase, etc.
- if(r->GetID() != f->dest) {
-
- int const ring_available_vcs = (vcEnd - vcBegin + 1) / 2;
- assert(ring_available_vcs > 0);
-
- if(ring_part == 0) {
- vcEnd -= ring_available_vcs;
- } else {
- assert(ring_part == 1);
- vcBegin += ring_available_vcs;
- }
-
- int const ph_available_vcs = ring_available_vcs / 2;
- assert(ph_available_vcs > 0);
-
- if(phase == 0) {
- vcEnd -= ph_available_vcs;
- } else {
- assert(phase == 1);
- vcBegin += ph_available_vcs;
- }
- }
-
- if (f->watch) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "Adding VC range ["
- << vcBegin << ","
- << vcEnd << "]"
- << " at output port " << out_port
- << " for flit " << f->id
- << " (input port " << in_channel
- << ", destination " << f->dest << ")"
- << "." << endl;
- }
-
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-//=============================================================
-
-void dim_order_torus( const Router *r, const Flit *f, int in_channel,
- OutputSet *outputs, bool inject )
-{
- 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 cur = r->GetID( );
- int dest = f->dest;
-
- dor_next_torus( cur, dest, in_channel,
- &out_port, &f->ph, false );
-
-
- // at the destination router, we don't need to separate VCs by ring partition
- if(cur != dest) {
-
- int const available_vcs = (vcEnd - vcBegin + 1) / 2;
- assert(available_vcs > 0);
-
- if ( f->ph == 0 ) {
- vcEnd -= available_vcs;
- } else {
- vcBegin += available_vcs;
- }
- }
-
- if ( f->watch ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "Adding VC range ["
- << vcBegin << ","
- << vcEnd << "]"
- << " at output port " << out_port
- << " for flit " << f->id
- << " (input port " << in_channel
- << ", destination " << f->dest << ")"
- << "." << endl;
- }
-
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-//=============================================================
-
-void dim_order_ni_torus( const Router *r, const Flit *f, int in_channel,
- OutputSet *outputs, bool inject )
-{
- 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 cur = r->GetID( );
- int dest = f->dest;
-
- dor_next_torus( cur, dest, in_channel,
- &out_port, NULL, false );
-
- // at the destination router, we don't need to separate VCs by destination
- if(cur != dest) {
-
- int const vcs_per_dest = (vcEnd - vcBegin + 1) / gNodes;
- assert(vcs_per_dest);
-
- vcBegin += f->dest * vcs_per_dest;
- vcEnd = vcBegin + vcs_per_dest - 1;
-
- }
-
- if ( f->watch ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "Adding VC range ["
- << vcBegin << ","
- << vcEnd << "]"
- << " at output port " << out_port
- << " for flit " << f->id
- << " (input port " << in_channel
- << ", destination " << f->dest << ")"
- << "." << endl;
- }
-
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-//=============================================================
-
-void dim_order_bal_torus( const Router *r, const Flit *f, int in_channel,
- OutputSet *outputs, bool inject )
-{
- 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 cur = r->GetID( );
- int dest = f->dest;
-
- dor_next_torus( cur, dest, in_channel,
- &out_port, &f->ph, true );
-
- // at the destination router, we don't need to separate VCs by ring partition
- if(cur != dest) {
-
- int const available_vcs = (vcEnd - vcBegin + 1) / 2;
- assert(available_vcs > 0);
-
- if ( f->ph == 0 ) {
- vcEnd -= available_vcs;
- } else {
- assert(f->ph == 1);
- vcBegin += available_vcs;
- }
- }
-
- if ( f->watch ) {
- *gWatchOut << GetSimTime() << " | " << r->FullName() << " | "
- << "Adding VC range ["
- << vcBegin << ","
- << vcEnd << "]"
- << " at output port " << out_port
- << " for flit " << f->id
- << " (input port " << in_channel
- << ", destination " << f->dest << ")"
- << "." << endl;
- }
-
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-//=============================================================
-
-void min_adapt_torus( const Router *r, const Flit *f, int in_channel, OutputSet *outputs, bool inject )
-{
- 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)));
-
- outputs->Clear( );
-
- if(inject) {
- // injection can use all VCs
- outputs->AddRange(-1, vcBegin, vcEnd);
- return;
- } else if(r->GetID() == f->dest) {
- // ejection can also use all VCs
- outputs->AddRange(2*gN, vcBegin, vcEnd);
- }
-
- int in_vc;
- if ( in_channel == 2*gN ) {
- in_vc = vcEnd; // ignore the injection VC
- } else {
- in_vc = f->vc;
- }
-
- int cur = r->GetID( );
- int dest = f->dest;
-
- int out_port;
-
- if ( in_vc > ( vcBegin + 1 ) ) { // If not in the escape VCs
- // Minimal adaptive for all other channels
-
- for ( int n = 0; n < gN; ++n ) {
- if ( ( cur % gK ) != ( dest % gK ) ) {
- int dist2 = gK - 2 * ( ( ( dest % gK ) - ( cur % gK ) + gK ) % gK );
-
- if ( dist2 > 0 ) { /*) ||
- ( ( dist2 == 0 ) && ( RandomInt( 1 ) ) ) ) {*/
- outputs->AddRange( 2*n, vcBegin+3, vcBegin+3, 1 ); // Right
- } else {
- outputs->AddRange( 2*n + 1, vcBegin+3, vcBegin+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->ph, false );
- } else {
- // DOR for the escape channel (VCs 0-1), low priority
- dor_next_torus( cur, dest, in_channel,
- &out_port, &f->ph, false );
- }
-
- if ( f->ph == 0 ) {
- outputs->AddRange( out_port, vcBegin, vcBegin, 0 );
- } else {
- outputs->AddRange( out_port, vcBegin+1, vcBegin+1, 0 );
- }
-}
-
-//=============================================================
-
-void dest_tag_fly( const Router *r, const Flit *f, int in_channel,
- OutputSet *outputs, bool inject )
-{
- 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 stage = ( r->GetID( ) * gK ) / gNodes;
- int dest = f->dest;
-
- while( stage < ( gN - 1 ) ) {
- dest /= gK;
- ++stage;
- }
-
- out_port = dest % gK;
- }
-
- outputs->Clear( );
-
- outputs->AddRange( out_port, vcBegin, vcEnd );
-}
-
-
-
-//=============================================================
-
-void chaos_torus( const Router *r, const Flit *f,
- int in_channel, OutputSet *outputs, bool inject )
-{
- outputs->Clear( );
-
- if(inject) {
- outputs->AddRange(-1, 0, 0);
- return;
- }
-
- int cur = r->GetID( );
- int dest = f->dest;
-
- if ( cur != dest ) {
- for ( int n = 0; n < gN; ++n ) {
-
- if ( ( cur % gK ) != ( dest % gK ) ) {
- int 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 )
-{
- outputs->Clear( );
-
- if(inject) {
- outputs->AddRange(-1, 0, 0);
- return;
- }
-
- int cur = r->GetID( );
- int 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( const Configuration & config )
-{
-
- gNumVCs = config.GetInt( "num_vcs" );
-
- //
- // traffic class partitions
- //
- gReadReqBeginVC = config.GetInt("read_request_begin_vc");
- if(gReadReqBeginVC < 0) {
- gReadReqBeginVC = 0;
- }
- gReadReqEndVC = config.GetInt("read_request_end_vc");
- if(gReadReqEndVC < 0) {
- gReadReqEndVC = gNumVCs / 2 - 1;
- }
- gWriteReqBeginVC = config.GetInt("write_request_begin_vc");
- if(gWriteReqBeginVC < 0) {
- gWriteReqBeginVC = 0;
- }
- gWriteReqEndVC = config.GetInt("write_request_end_vc");
- if(gWriteReqEndVC < 0) {
- gWriteReqEndVC = gNumVCs / 2 - 1;
- }
- gReadReplyBeginVC = config.GetInt("read_reply_begin_vc");
- if(gReadReplyBeginVC < 0) {
- gReadReplyBeginVC = gNumVCs / 2;
- }
- gReadReplyEndVC = config.GetInt("read_reply_end_vc");
- if(gReadReplyEndVC < 0) {
- gReadReplyEndVC = gNumVCs - 1;
- }
- gWriteReplyBeginVC = config.GetInt("write_reply_begin_vc");
- if(gWriteReplyBeginVC < 0) {
- gWriteReplyBeginVC = gNumVCs / 2;
- }
- gWriteReplyEndVC = config.GetInt("write_reply_end_vc");
- if(gWriteReplyEndVC < 0) {
- gWriteReplyEndVC = gNumVCs - 1;
- }
-
- /* Register routing functions here */
-
- // ===================================================
- // Balfour-Schultz
- gRoutingFunctionMap["nca_fattree"] = &fattree_nca;
- gRoutingFunctionMap["anca_fattree"] = &fattree_anca;
- gRoutingFunctionMap["nca_qtree"] = &qtree_nca;
- gRoutingFunctionMap["nca_tree4"] = &tree4_nca;
- gRoutingFunctionMap["anca_tree4"] = &tree4_anca;
- gRoutingFunctionMap["dor_mesh"] = &dim_order_mesh;
- gRoutingFunctionMap["xy_yx_mesh"] = &xy_yx_mesh;
- gRoutingFunctionMap["adaptive_xy_yx_mesh"] = &adaptive_xy_yx_mesh;
- // End Balfour-Schultz
- // ===================================================
-
- gRoutingFunctionMap["dim_order_mesh"] = &dim_order_mesh;
- gRoutingFunctionMap["dim_order_ni_mesh"] = &dim_order_ni_mesh;
- gRoutingFunctionMap["dim_order_pni_mesh"] = &dim_order_pni_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;
-
- // FIXME: This is broken.
- // 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_fly;
-
- gRoutingFunctionMap["chaos_mesh"] = &chaos_mesh;
- gRoutingFunctionMap["chaos_torus"] = &chaos_torus;
-}