Hi Zacharias,

Attached please find the topology generator. Please compile the topology 
generator and use the following command to generate a topology file for a 
crossbar interconnect:

./topology -n N -c -w 3 topology-file-name 

where N is three times the number of nodes in the CMP (i.e., if you simulate a 
16-core CMP, N will be 48).  

Regards,
Pejman
________________________________________
From: [email protected] [[email protected]]
Sent: Tuesday, September 04, 2012 10:26 AM
To: [email protected]
Subject: Crossbar Interconnect

Hi,

In scale-out-processors paper you simulated CMP with mesh and crossbar
interconnects. I see that in flexus distribution there are only torus
and mesh topology files. How did you simulate the crossbar
interconnect? Do you have topology files for crossbar?

thanks - Zacharias
#include <iostream>
#include <fstream>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <unistd.h>

#include <getopt.h>

using namespace std;

#define DIMS  2

int numNodes = 0;
int numSwitches = 0;
int nodesPerDim[DIMS] = { 0 };

int fattness = 1;

bool isTorus = false;
bool isAdaptive = false;
bool isCrossbar = false;

char * outFilename;
ofstream outFile;

bool processArguments ( int argc, char ** argv );
bool generateSwitches ( void );

bool generateMeshTopology ( int nodeId );
bool generateTorusTopology ( int nodeId );
bool generateCrossbarTopology ( int nodeId );

bool generateDeadlockFreeMeshRoute ( int currNode,
                                     int destNode );

bool generateDeadlockFreeTorusRoute ( int currNode,
                                      int destNode );

bool generateDeadlockFreeCrossbarRoute ( int currNode,
                                       int destNode );
typedef int XDirection;

enum Direction {
  NORTH,
  SOUTH,
  EAST,
  WEST,
  LOCAL
};


int main ( int argc, char ** argv ) {

  int i, j;
  std::string progname = argv[0];

  if ( processArguments ( argc, argv ) ) {
    cerr << "Usage: " << progname << " -n <numnodes> [-m|-t|-c] [-a] [-w <width>] <output filename>" << endl;
    cerr << "\t-t specifies a 2D torus" << endl;
    cerr << "\t-m specifies a 2D mesh" << endl;
    cerr << "\t-c specifies a crossbar" << endl;
    cerr << "\t-a specifies adaptive routing tables (not implemented)" << endl;
    cerr << "\t-w specifies a fat 2D torus/mesh with <width> nodes per router" << endl;
    return 1;
  }


  // Generate the boilerplate parameters
  outFile << "# Boilerplate stuff" << endl;
  if (isCrossbar)
	outFile << "ChannelLatency 1" << endl;
  else
	outFile << "ChannelLatency 3" << endl;
  outFile << "ChannelLatencyData 4" << endl;
  outFile << "ChannelLatencyControl 1" << endl;
  outFile << "LocalChannelLatencyDivider 1" << endl;
  outFile << "SwitchInputBuffers 6" << endl;
  outFile << "SwitchOutputBuffers 6" << endl;
  outFile << "SwitchInternalBuffersPerVC 6" << endl;
  outFile << endl;

  // Output all of the node->switch connections
  if ( generateSwitches() )
    return true;

  // Make topology
  if ( isTorus ) {
    outFile << endl << "# Topology for a " << numNodes << " node TORUS with " << fattness << " nodes per router" << endl;
  }
  else if(isCrossbar) {
    outFile << endl << "# Topology for a " << numNodes << " node crossbar with " << fattness << " nodes per router" << endl;
  }
  else {
    outFile << endl << "# Topology for a " << numNodes << " node MESH with " << fattness << " nodes per router" << endl;
  }

  for ( i = 0; i < numSwitches; i++ ) {
    if ( isTorus ) {
          if ( generateTorusTopology ( i ) ) return 1;
    }else if (isCrossbar){
          if ( generateCrossbarTopology ( i ) ) return 1;
    }else {
          if ( generateMeshTopology ( i ) ) return 1;
    }
  }

  outFile << endl << "# Deadlock-free routing tables" << endl;

  // For each switch, generate a routing table to each destination
  for ( i = 0; i < numSwitches; i++ ) {

    outFile << endl << "# Switch " << i << " -> *" << endl;

    // For each destination
    for ( j = 0; j < numNodes; j++ ) {
      if ( isTorus ) {
           if ( generateDeadlockFreeTorusRoute ( i, j ) ) return 1;
      }else if(isCrossbar){
           if ( generateDeadlockFreeCrossbarRoute ( i, j ) ) return 1;
      } else {
           if ( generateDeadlockFreeMeshRoute ( i, j ) )  return 1;
      }
    }

  }

  outFile.close();

  return 0;
}


bool processArguments ( int argc, char ** argv ) {

  static struct option long_options[] = {
    { "torus",		0,	NULL,	't'},
    { "mesh",		0,	NULL,	'm'},
    { "crossbar",       0,      NULL,   'c'},
    { "adaptive",	0,	NULL, 	'a'},
    { "width",		1,	NULL,	'w'},
    { "nodes",		1,	NULL,	'n'},
    { "file",		1,	NULL,	'f'}
  };
  int c, index;
  while ( (c = getopt_long(argc, argv, "af:chmn:tw:", long_options, &index)) >= 0) {
    switch (c) {
      case 'a':
        isAdaptive = false;
        break;
      case 'f':
        outFilename = optarg;
        break;
      case 'c':
        isCrossbar = true;
        isTorus = false;
        break;
      case 'h':
        return true;
      case 'm':
        isTorus = false;
        isCrossbar = false;
        break;
      case 'n':
        numNodes = atoi(optarg);
        break;
      case 't':
        isTorus = true;
        isCrossbar = false;
        break;
      case 'w':
        fattness = atoi(optarg);
        break;
      case '?':
        cout << "Unrecognized option '" << optopt << "'" << endl;
        return true;
    }
  }


  if (optind < argc) {
    outFilename = argv[optind];
  }

  if(numNodes % fattness !=0) { 
    cerr << "ERROR: Numer of nodes must be divisible with the fattness!"<< endl;
    return true;
  }
  numSwitches = numNodes / fattness;


 int dim1= (int)sqrt ( (float)numSwitches );
 while((numSwitches%dim1) !=0) dim1--;
 
 nodesPerDim[1] = dim1;
 nodesPerDim[0] = numSwitches/dim1;
 

  for ( int i = 0; i < DIMS; i++ ) {
    cout << nodesPerDim[i] << " switches per dimension " << i << endl;
  }

  outFile.open ( outFilename );
  if ( !outFile.good() ) {
    cerr << "ERROR opening output file: " << outFilename << endl;
    return true;
  }

  return false;
}

bool generateSwitches ( void ) {
  int i;

  outFile << "# Basic Switch/Node connections" << endl;
  outFile << "NumNodes " << numNodes << endl;
  outFile << "NumSwitches " << numSwitches << endl;
  if(isCrossbar)  outFile << "SwitchPorts   " << (numSwitches + fattness) << endl;
  else outFile << "SwitchPorts   " << (4 + fattness) << endl;
  outFile << "SwitchBandwidth 4" << endl;
  outFile << endl;

  for ( i = 0; i < numNodes; i++ ) {
    outFile << "Top Node " << i << " -> Switch " << (i % numSwitches) << ":" << (int)(i / numSwitches) << endl;
  }

  return false;
}

int getXCoord ( int nodeId ) {
  return ( nodeId % nodesPerDim[0] );
}

int getYCoord ( int nodeId ) {
  return ( nodeId / nodesPerDim[0] );
}

int getNodeIdCoord ( int x, int y ) {
  int
  id;

  id = ( x + ( y * nodesPerDim[0] ) );

  if ( id >= numSwitches ) {
    cerr << "ERROR: node coordinates out of bounds: " << x << ", " << y << endl;
    exit ( 1 );
  }

  return id;
}

int getNodeIdOffset ( int nodeId, Direction dir ) {
  int
  x,
  y;

  x = getXCoord ( nodeId );
  y = getYCoord ( nodeId );

  switch ( dir ) {
    case NORTH:
      y--;
      break;
    case SOUTH:
      y++;
      break;
    case EAST:
      x++;
      break;
    case WEST:
      x--;
      break;

    default:
      cerr << "Invalid direction" << dir << endl;
      exit ( 1 );
  }

  if ( isTorus ) {

    if ( x < 0 )
      x = nodesPerDim[0] - 1;

    if ( x >= nodesPerDim[0] )
      x = 0;

    if ( y < 0 )
      y = nodesPerDim[1] - 1;

    if ( y >= nodesPerDim[1] )
      y = 0;

  } else {

    // Invalid offset for a mesh
    if ( x < 0 || y < 0 ||
         x >= nodesPerDim[0] ||
         y >= nodesPerDim[1] ) {

      cerr << "ERROR: invalid offset for a mesh!" << endl;
      return -1;
    }
  }

  return getNodeIdCoord ( x, y );
}


ostream & operator <<  ( ostream & out, const Direction dir ) {

  switch ( dir ) {
    case NORTH:
      out << (fattness + 1);
      break;
    case SOUTH:
      out << (fattness + 3);
      break;
    case EAST:
      out << (fattness + 2);
      break;
    case WEST:
      out << (fattness + 0);
      break;
    case LOCAL:
      out << 0;
      break;
  };

  return out;
}



void printXDir(const XDirection dir, ostream& out)
{
   if(dir==numSwitches) out<<0;
   else out<<(fattness+dir);
}


bool writeS2SCrossbar (const int       node1,
                       const XDirection dir1,
                       const int       node2,
                       const XDirection dir2 ) {

  outFile << "Top Switch "
          << node1 << ":" ; printXDir(dir1,outFile); outFile << " -> Switch "
          << node2 << ":" ; printXDir(dir2,outFile); outFile << endl;

  return false;
}




bool writeS2S ( const int       node1,
                const Direction dir1,
                const int       node2,
                const Direction dir2 ) {

  outFile << "Top Switch "
          << node1 << ":" << dir1 << " -> Switch "
          << node2 << ":" << dir2 << endl;

  return false;
}

/* A switch looks like this:
 *  (port numbers on inside, port 0 to n are the local CPUs)
 *
 *                 N
 *                 |
 *        +-----------------+
 *        |       n+2       |
 *        |                 |
 *   W -- | n+1   0-n   n+3 | -- E
 *        |                 |
 *        |       n+4       |
 *        +-----------------+
 *                 |
 *                 S
 */
bool generateMeshTopology ( int nodeId ) {
  int x, y;

  x = getXCoord ( nodeId );
  y = getYCoord ( nodeId );

  // East
  if ( x != nodesPerDim[0] - 1 )
    writeS2S ( getNodeIdCoord ( x, y ),
               EAST,
               getNodeIdCoord ( x + 1, y ),
               WEST );

  // South
  if ( y != nodesPerDim[1] - 1 )
    writeS2S ( getNodeIdCoord ( x, y ),
               SOUTH,
               getNodeIdCoord ( x, y + 1 ),
               NORTH );

  return false;
}

bool generateTorusTopology ( int nodeId ) {
  int
  x,
  y;

  x = getXCoord ( nodeId );
  y = getYCoord ( nodeId );

  // East
  writeS2S ( getNodeIdCoord ( x, y ),
             EAST,
             getNodeIdCoord ( (x + 1) % nodesPerDim[0], y ),
             WEST );

  // South
  writeS2S ( getNodeIdCoord ( x, y ),
             SOUTH,
             getNodeIdCoord ( x, (y + 1) % nodesPerDim[1] ),
             NORTH );

  return false;
}


bool generateCrossbarTopology ( int nodeId ) {
  int
  x,
  y;

  x = getXCoord ( nodeId );
  y = getYCoord ( nodeId );
  int src = getNodeIdCoord(x,y);
 
  for(int dest=nodeId+1; dest<numSwitches; dest++) {
     writeS2SCrossbar(src, dest, dest, src);          
  }
  
  return false;
}


bool writeBasicRoute ( int currNode,
                       int destNode,
                       int outPort,
                       int outVC ) {
  outFile << "Route Switch " << currNode << " -> " << destNode
          << " { " << outPort << ":" << outVC << " } " << endl;
  return false;
}

bool writeBasicRoute ( int currNode,
                       int destNode,
                       Direction outPort,
                       int outVC ) {
  outFile << "Route Switch " << currNode << " -> " << destNode
          << " { " << outPort << ":" << outVC << " } " << endl;
  return false;
}


bool writeBasicXRoute ( int currNode,
                       int destNode,
                       XDirection outPort,
                       int outVC ) {
  if(outVC == 0) {
    outFile << "Route Switch " << currNode << " -> " << destNode
           << " { ";  printXDir(outPort, outFile); outFile<< ":" << outVC << " } " << endl;
  }
  else {
    outFile << "Route Switch " << currNode << " -> " << destNode
           << " { "<<outVC<< ":" << 0 << " } " << endl;
 
  }
  return false;
}

#define ABS(X) ((X) > 0 ? (X) : -(X))

bool generateDeadlockFreeTorusRoute ( int currNode,
                                      int destNode ) {
  int
  xoff,
  yoff;

  // Trivial case, output to port 0, VC 0
  if ( currNode == (destNode % numSwitches) ) {
    return writeBasicRoute ( currNode,
                             destNode,
                             (int)(destNode / numSwitches),
                             0 );
  }

  xoff =
    getXCoord ( (destNode % numSwitches) ) -
    getXCoord ( currNode );

  yoff =
    getYCoord ( (destNode % numSwitches) ) -
    getYCoord ( currNode );

  if ( xoff != 0 ) {

    if ( xoff > 0 && xoff < (nodesPerDim[0] / 2) ||
         xoff < (-nodesPerDim[0] / 2) ) {
      // Go EAST
      return writeBasicRoute ( currNode,
                               destNode,
                               EAST,
                               getXCoord ( destNode ) >
                               getXCoord ( currNode ) );
    } else {
      // Go WEST
      return writeBasicRoute ( currNode,
                               destNode,
                               WEST,
                               getXCoord ( destNode ) >
                               getXCoord ( currNode ) );
    }
  }

  if ( yoff > 0 && yoff < (nodesPerDim[1] / 2) ||
       yoff < (-nodesPerDim[1] / 2) ) {
    // Go SOUTH
    return writeBasicRoute ( currNode,
                             destNode,
                             SOUTH,
                             getYCoord ( destNode ) >
                             getYCoord ( currNode ) );
  } else {
    // Go NORTH
    return writeBasicRoute ( currNode,
                             destNode,
                             NORTH,
                             getYCoord ( destNode ) >
                             getYCoord ( currNode ) );
  }

  return false;
}


bool generateDeadlockFreeMeshRoute ( int currNode,
                                     int destNode ) {
  int xoff, yoff;

  xoff =
    getXCoord ( (destNode % numSwitches) ) -
    getXCoord ( currNode );

  yoff =
    getYCoord ( (destNode % numSwitches) ) -
    getYCoord ( currNode );

  // Trivial case, output to port 0, VC 0
  if ( currNode == (destNode % numSwitches) ) {
    return writeBasicRoute ( currNode,
                             destNode,
                             (int)(destNode / numSwitches),
                             0 );
  }

  if ( xoff < 0 ) {
    return writeBasicRoute ( currNode,
                             destNode,
                             WEST,
                             0 );
  }

  if ( xoff > 0 ) {
    return writeBasicRoute ( currNode,
                             destNode,
                             EAST,
                             0 );
  }

  if ( yoff < 0 ) {
    return writeBasicRoute ( currNode,
                             destNode,
                             NORTH,
                             0 );
  }

  if ( yoff > 0 ) {
    return writeBasicRoute ( currNode,
                             destNode,
                             SOUTH,
                             0 );
  }

  cerr << "ERROR: mesh routing found no route from " << currNode << " to " << destNode << " offset is " << xoff << ", " << yoff <<  endl;

  return true;
}

bool generateDeadlockFreeCrossbarRoute ( int currNode,
                                     int destNode ) {
 
 int xs =  getXCoord ( currNode );
 int xd = getXCoord ( (destNode % numSwitches) );


 int ys =  getYCoord ( currNode );
 int yd =  getYCoord ( (destNode % numSwitches) );


  // Trivial case, output to port 0, VC 0
  if ( currNode == (destNode % numSwitches) ) {
    return writeBasicXRoute ( currNode,
                              destNode,
                              (int)(numSwitches),
                              destNode/numSwitches );
  }
  
  return writeBasicXRoute(currNode, destNode, (int)(destNode%numSwitches), 0);
 
  cerr << "ERROR: crossbar routing found no route from " << currNode << " to " << destNode <<  endl;

  return true;
}


Reply via email to