Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
make cluster routing a bit more flexible, to allow adding other kinds of clusters
authorAugustin Degomme <degomme@idpann.imag.fr>
Wed, 22 Jan 2014 10:06:17 +0000 (11:06 +0100)
committerAugustin Degomme <degomme@idpann.imag.fr>
Wed, 22 Jan 2014 10:06:17 +0000 (11:06 +0100)
for each node, link creation is made inside the specific routing file,
except for loopback and backbone which are done in surf_routing if they are needed

buildtools/Cmake/DefinePackages.cmake
include/simgrid/platf.h
src/surf/surf_routing.cpp
src/surf/surf_routing_cluster.cpp
src/surf/surf_routing_cluster.hpp
src/surf/surf_routing_cluster_torus.cpp [new file with mode: 0644]
src/surf/surf_routing_cluster_torus.hpp [new file with mode: 0644]
src/surf/surf_routing_private.hpp
src/surf/surfxml_parse.c

index d5f6c7f..108d9fe 100644 (file)
@@ -67,6 +67,7 @@ set(EXTRA_DIST
   src/surf/surf_routing_private.hpp
   src/surf/surf_routing.hpp
   src/surf/surf_routing_cluster.hpp
+  src/surf/surf_routing_cluster_torus.hpp
   src/surf/surf_routing_dijkstra.hpp
   src/surf/surf_routing_floyd.hpp
   src/surf/surf_routing_full.hpp
@@ -320,6 +321,7 @@ set(SURF_SRC
   src/surf/surf_c_bindings.cpp
   src/surf/surf_routing.cpp  
   src/surf/surf_routing_cluster.cpp
+  src/surf/surf_routing_cluster_torus.cpp
   src/surf/surf_routing_dijkstra.cpp
   src/surf/surf_routing_floyd.cpp
   src/surf/surf_routing_full.cpp
index 07c0ec7..f5f37fa 100644 (file)
@@ -43,6 +43,11 @@ typedef enum {
   SURF_PROCESS_ON_FAILURE_RESTART = 0
 } e_surf_process_on_failure_t;
 
+typedef enum {
+  SURF_CLUSTER_FLAT = 1,
+  SURF_CLUSTER_TORUS = 0
+} e_surf_cluster_topology_t;
+
 
 typedef struct tmgr_trace *tmgr_trace_t; /**< Opaque structure defining an availability trace */
 
@@ -201,7 +206,8 @@ typedef struct s_sg_platf_cluster_cbarg {
   double loopback_bw;
   double loopback_lat;
   double limiter_link;
-  const char* torus_dimensions;
+  e_surf_cluster_topology_t topology;
+  const char* topo_parameters;
   xbt_dict_t properties;
   const char* router_id;
   e_surf_link_sharing_policy_t sharing_policy;
index 60fcd0f..471d836 100644 (file)
@@ -7,6 +7,8 @@
 #include "surf_routing.hpp"
 #include "surf_routing_private.hpp"
 #include "surf_routing_cluster.hpp"
+#include "surf_routing_cluster_torus.hpp"
+
 
 #include "simgrid/platf_interface.h"    // platform creation API internal interface
 #include "simgrid/sg_config.h"
@@ -82,7 +84,9 @@ typedef enum {
   SURF_MODEL_DIJKSTRACACHE,
   SURF_MODEL_NONE,
   SURF_MODEL_VIVALDI,
-  SURF_MODEL_CLUSTER
+  SURF_MODEL_CLUSTER,
+  SURF_MODEL_TORUS_CLUSTER,
+
 } e_routing_types;
 
 struct s_model_type routing_models[] = {
@@ -104,6 +108,8 @@ struct s_model_type routing_models[] = {
    model_vivaldi_create, NULL},
   {"Cluster", "Cluster routing",
    model_cluster_create, NULL},
+   {"Torus_Cluster", "Torus Cluster routing",
+    model_torus_cluster_create, NULL},
   {NULL, NULL, NULL, NULL}
 };
 
@@ -347,13 +353,14 @@ void routing_AS_begin(sg_platf_AS_cbarg_t AS)
 
   /* search the routing model */
   switch(AS->routing){
-    case A_surfxml_AS_routing_Cluster:       model = &routing_models[SURF_MODEL_CLUSTER];break;
-    case A_surfxml_AS_routing_Dijkstra:      model = &routing_models[SURF_MODEL_DIJKSTRA];break;
-    case A_surfxml_AS_routing_DijkstraCache: model = &routing_models[SURF_MODEL_DIJKSTRACACHE];break;
-    case A_surfxml_AS_routing_Floyd:         model = &routing_models[SURF_MODEL_FLOYD];break;
-    case A_surfxml_AS_routing_Full:          model = &routing_models[SURF_MODEL_FULL];break;
-    case A_surfxml_AS_routing_None:          model = &routing_models[SURF_MODEL_NONE];break;
-    case A_surfxml_AS_routing_Vivaldi:       model = &routing_models[SURF_MODEL_VIVALDI];break;
+    case A_surfxml_AS_routing_Cluster:         model = &routing_models[SURF_MODEL_CLUSTER];break;
+    case A_surfxml_AS_routing_Cluster___torus: model = &routing_models[SURF_MODEL_TORUS_CLUSTER];break;
+    case A_surfxml_AS_routing_Dijkstra:        model = &routing_models[SURF_MODEL_DIJKSTRA];break;
+    case A_surfxml_AS_routing_DijkstraCache:   model = &routing_models[SURF_MODEL_DIJKSTRACACHE];break;
+    case A_surfxml_AS_routing_Floyd:           model = &routing_models[SURF_MODEL_FLOYD];break;
+    case A_surfxml_AS_routing_Full:            model = &routing_models[SURF_MODEL_FULL];break;
+    case A_surfxml_AS_routing_None:            model = &routing_models[SURF_MODEL_NONE];break;
+    case A_surfxml_AS_routing_Vivaldi:         model = &routing_models[SURF_MODEL_VIVALDI];break;
     default: xbt_die("Not a valid model!!!");
     break;
   }
@@ -798,13 +805,12 @@ static void routing_parse_cluster(sg_platf_cluster_cbarg_t cluster)
 {
   char *host_id, *groups, *link_id = NULL;
   xbt_dict_t patterns = NULL;
-  xbt_dynar_t dimensions;
   int rankId=0;
 
   s_sg_platf_host_cbarg_t host;
   s_sg_platf_link_cbarg_t link;
 
-  unsigned int iter, totalRanks=0;
+  unsigned int iter;
   int start, end, i;
   xbt_dynar_t radical_elements;
   xbt_dynar_t radical_ends;
@@ -817,48 +823,36 @@ static void routing_parse_cluster(sg_platf_cluster_cbarg_t cluster)
     xbt_dict_set(patterns, "suffix", xbt_strdup(cluster->suffix), NULL);
   }
 
-  dimensions = xbt_str_split(cluster->torus_dimensions, ",");
-
-
-  int nb_links_per_node = 1;
-
-  if (!xbt_dynar_is_empty(dimensions)) {
-    /**
-     * We are in a torus cluster
-     * Parse attribute dimensions="dim1,dim2,dim3,...,dimN"
-     * and safe it in a dynarray.
-     * Additionally, we need to know how many ranks we have in total
-     */
-    xbt_dynar_foreach(dimensions, iter, groups) {
-        int tmp = surf_parse_get_int(xbt_dynar_get_as(dimensions, iter, char *));
-        xbt_dynar_set_as(dimensions, iter, int, tmp);
-
-        if (totalRanks == 0)
-            totalRanks = tmp;
-        else
-            totalRanks *= tmp;
-    }
-
-    nb_links_per_node = xbt_dynar_length(dimensions);
-    ((AsClusterPtr)current_routing)-> p_dimensions = dimensions;
+  /* parse the topology attribute. If we are not in a flat cluster,
+   * switch to the right mode and initialize the routing with
+   * the parameters in topo_parameters attribute
+   */
+  s_sg_platf_AS_cbarg_t AS = SG_PLATF_AS_INITIALIZER;
+  AS.id = cluster->id;
 
+  if(cluster->topology == SURF_CLUSTER_TORUS){
+      XBT_DEBUG("<AS id=\"%s\"\trouting=\"Torus_Cluster\">", cluster->id);
+      AS.routing = A_surfxml_AS_routing_Cluster___torus;
+      sg_platf_new_AS_begin(&AS);
+      ((AsClusterTorusPtr)current_routing)->parse_specific_arguments(cluster);
+  }else{
+    XBT_DEBUG("<AS id=\"%s\"\trouting=\"Cluster\">", cluster->id);
+    AS.routing = A_surfxml_AS_routing_Cluster;
+    sg_platf_new_AS_begin(&AS);
+    ((AsClusterPtr)current_routing)->p_nb_links_per_node = 1;
   }
 
   if(cluster->loopback_bw!=0 || cluster->loopback_lat!=0){
-      nb_links_per_node++;
+      ((AsClusterPtr)current_routing)->p_nb_links_per_node++;
       ((AsClusterPtr)current_routing)->p_has_loopback=1;
   }
 
   if(cluster->limiter_link!=0){
-      nb_links_per_node++;
+      ((AsClusterPtr)current_routing)->p_nb_links_per_node++;
       ((AsClusterPtr)current_routing)->p_has_limiter=1;
   }
 
-  XBT_DEBUG("<AS id=\"%s\"\trouting=\"Cluster\">", cluster->id);
-  s_sg_platf_AS_cbarg_t AS = SG_PLATF_AS_INITIALIZER;
-  AS.id = cluster->id;
-  AS.routing = A_surfxml_AS_routing_Cluster;
-  sg_platf_new_AS_begin(&AS);
+
 
   current_routing->p_linkUpDownList
             = xbt_dynar_new(sizeof(s_surf_parsing_link_up_down_t),NULL);
@@ -926,13 +920,13 @@ static void routing_parse_cluster(sg_platf_cluster_cbarg_t cluster)
                 cluster->bw, cluster->lat);
 
 
-      s_surf_parsing_link_up_down_t info, info_lim, info_loop;
+      s_surf_parsing_link_up_down_t info_lim, info_loop;
       // All links are saved in a matrix;
       // every row describes a single node; every node
       // may have multiple links.
       // the first column may store a link from x to x if p_has_loopback is set
       // the second column may store a limiter link if p_has_limiter is set
-      // other columns are to store one or more link, if we are in a torus
+      // other columns are to store one or more link for the node
 
       //add a loopback link
       if(cluster->loopback_bw!=0 || cluster->loopback_lat!=0){
@@ -950,9 +944,9 @@ static void routing_parse_cluster(sg_platf_cluster_cbarg_t cluster)
         sg_platf_new_link(&link);
         info_loop.link_up =
             xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL);
-        info_loop.link_down = info.link_up;
+        info_loop.link_down = info_loop.link_up;
         free(tmp_link);
-        xbt_dynar_set(current_routing->p_linkUpDownList, rankId*nb_links_per_node, &info_loop);
+        xbt_dynar_set(current_routing->p_linkUpDownList, rankId*((AsClusterPtr)current_routing)->p_nb_links_per_node, &info_loop);
       }
 
       //add a limiter link (shared link to account for maximal bandwidth of the node)
@@ -971,99 +965,22 @@ static void routing_parse_cluster(sg_platf_cluster_cbarg_t cluster)
         sg_platf_new_link(&link);
         info_lim.link_up =
             xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL);
-        info_lim.link_down = info.link_up;
+        info_lim.link_down = info_lim.link_up;
         free(tmp_link);
         xbt_dynar_set(current_routing->p_linkUpDownList,
-            rankId*nb_links_per_node + ((AsClusterPtr)current_routing)->p_has_loopback ,
+            rankId*((AsClusterPtr)current_routing)->p_nb_links_per_node + ((AsClusterPtr)current_routing)->p_has_loopback ,
             &info_lim);
 
       }
 
 
+      //call the cluster function that adds the others links
 
-      if(xbt_dynar_length(dimensions) == 0 ) {
-        /**
-         * If torus is not specified, generate one link by node
-         */
+      ((AsClusterPtr)current_routing)->create_links_for_node(cluster, i, rankId, rankId*
+          ((AsClusterPtr)current_routing)->p_nb_links_per_node
+          + ((AsClusterPtr)current_routing)->p_has_loopback
+          + ((AsClusterPtr)current_routing)->p_has_limiter );
 
-        memset(&link, 0, sizeof(link));
-        link.id = link_id;
-        link.bandwidth = cluster->bw;
-        link.latency = cluster->lat;
-        link.state = SURF_RESOURCE_ON;
-        link.policy = cluster->sharing_policy;
-        sg_platf_new_link(&link);
-
-        if (link.policy == SURF_LINK_FULLDUPLEX) {
-          char *tmp_link = bprintf("%s_UP", link_id);
-          info.link_up =
-              xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL);
-          free(tmp_link);
-          tmp_link = bprintf("%s_DOWN", link_id);
-          info.link_down =
-              xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL);
-          free(tmp_link);
-        } else {
-          info.link_up = xbt_lib_get_or_null(link_lib, link_id, SURF_LINK_LEVEL);
-          info.link_down = info.link_up;
-        }
-        xbt_dynar_set(current_routing->p_linkUpDownList, rankId*nb_links_per_node
-            + ((AsClusterPtr)current_routing)->p_has_loopback
-            + ((AsClusterPtr)current_routing)->p_has_limiter,
-            &info);
-      }else{
-
-        unsigned int j = 0;
-        /**
-         * Create all links that exist in the torus.
-         * Each rank creates #dimensions-1 links
-         */
-        int neighbour_rank_id = 0; // The other node the link connects
-        int current_dimension = 0, // which dimension are we currently in?
-                                   // we need to iterate over all dimensions
-                                   // and create all links there
-            dim_product       = 1; // Needed to calculate the next neighbour_id
-        for (j = 0; j < xbt_dynar_length(dimensions); j++) {
-
-          memset(&link, 0, sizeof(link));
-          current_dimension = xbt_dynar_get_as(dimensions, j, int);
-          neighbour_rank_id = ( ((int) i / dim_product) % current_dimension == current_dimension-1) ? i - (current_dimension-1)*dim_product : i + dim_product;
-          link_id           = bprintf("link_from_%i_to_%i", i, neighbour_rank_id);
-          link.id           = link_id;
-          link.bandwidth    = cluster->bw;
-          link.latency      = cluster->lat;
-          link.state        = SURF_RESOURCE_ON;
-          link.policy       = cluster->sharing_policy;
-          sg_platf_new_link(&link);
-          s_surf_parsing_link_up_down_t info;
-          if (link.policy == SURF_LINK_FULLDUPLEX) {
-            char *tmp_link = bprintf("%s_UP", link_id);
-            info.link_up =
-              xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL);
-            free(tmp_link);
-            tmp_link = bprintf("%s_DOWN", link_id);
-            info.link_down =
-              xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL);
-            free(tmp_link);
-          } else {
-            info.link_up = xbt_lib_get_or_null(link_lib, link_id, SURF_LINK_LEVEL);
-            info.link_down = info.link_up;
-          }
-          /**
-           * Add the link to its appropriate position;
-           * note that position rankId*(xbt_dynar_length(dimensions)+has_loopack?+has_limiter?)
-           * holds the link "rankId->rankId"
-           */
-          xbt_dynar_set(current_routing->p_linkUpDownList, rankId*nb_links_per_node
-              + ((AsClusterPtr)current_routing)->p_has_loopback
-              + ((AsClusterPtr)current_routing)->p_has_limiter
-              + j,
-              &info);
-          dim_product   *= current_dimension;
-          xbt_free(link_id);
-
-        }
-      }
       xbt_free(link_id);
       xbt_free(host_id);
       rankId++;
index 93503a1..36794d8 100644 (file)
@@ -23,9 +23,9 @@ AsCluster::AsCluster() : AsNone()
   p_backbone = 0;
   p_loopback = 0;
   p_router = 0;
-  p_dimensions = NULL;
   p_has_limiter = 0;
   p_has_loopback = 0;
+  p_nb_links_per_node =0;
 }
 
 /* Business methods */
@@ -145,6 +145,37 @@ void AsCluster::getGraph(xbt_graph_t graph, xbt_dict_t nodes, xbt_dict_t edges)
   }
 }
 
+void AsCluster::create_links_for_node(sg_platf_cluster_cbarg_t cluster, int id, int , int position){
+  s_sg_platf_link_cbarg_t link;
+  s_surf_parsing_link_up_down_t info;
+  char* link_id = bprintf("%s_link_%d", cluster->id, id);
+
+  memset(&link, 0, sizeof(link));
+  link.id = link_id;
+  link.bandwidth = cluster->bw;
+  link.latency = cluster->lat;
+  link.state = SURF_RESOURCE_ON;
+  link.policy = cluster->sharing_policy;
+  sg_platf_new_link(&link);
+
+  if (link.policy == SURF_LINK_FULLDUPLEX) {
+    char *tmp_link = bprintf("%s_UP", link_id);
+    info.link_up =
+               xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL);
+           free(tmp_link);
+           tmp_link = bprintf("%s_DOWN", link_id);
+           info.link_down =
+               xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL);
+           free(tmp_link);
+         } else {
+           info.link_up = xbt_lib_get_or_null(link_lib, link_id, SURF_LINK_LEVEL);
+           info.link_down = info.link_up;
+         }
+         xbt_dynar_set(p_linkUpDownList, position,
+             &info);
+
+}
+
 int AsCluster::parsePU(RoutingEdgePtr elm) {
   XBT_DEBUG("Load process unit \"%s\"", elm->p_name);
   xbt_dynar_push_as(p_indexNetworkElm, RoutingEdgePtr, elm);
@@ -157,4 +188,3 @@ int AsCluster::parseAS(RoutingEdgePtr elm) {
   return xbt_dynar_length(p_indexNetworkElm)-1;
 }
 
-
index 6300c8e..4219d1d 100644 (file)
@@ -18,7 +18,7 @@ class AsCluster: public AsNone {
 public:
   AsCluster();
 
-  void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency);
+  virtual void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency);
   //xbt_dynar_t getOneLinkRoutes();
   //void parseRoute(sg_platf_route_cbarg_t route);
   //void parseASroute(sg_platf_route_cbarg_t route);
@@ -32,13 +32,14 @@ public:
    * Of course, only the routing model of this AS is informed, not every ones */
   int parsePU(RoutingEdgePtr elm); /* A host or a router, whatever */
   int parseAS(RoutingEdgePtr elm);
-
+  virtual void create_links_for_node(sg_platf_cluster_cbarg_t cluster, int id, int rank, int position);
   NetworkLinkPtr p_backbone;
   void *p_loopback;
   RoutingEdgePtr p_router;
   xbt_dynar_t p_dimensions;
   int p_has_limiter;
   int p_has_loopback;
+  int p_nb_links_per_node;
 
 };
 
diff --git a/src/surf/surf_routing_cluster_torus.cpp b/src/surf/surf_routing_cluster_torus.cpp
new file mode 100644 (file)
index 0000000..c16646d
--- /dev/null
@@ -0,0 +1,222 @@
+#include "surf_routing_cluster_torus.hpp"
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_cluster_torus, surf_route_cluster, "Torus Routing part of surf");
+
+
+inline unsigned int* rankId_to_coords(int rankId, xbt_dynar_t dimensions) {
+
+    unsigned int i = 0, cur_dim_size = 1, dim_size_product = 1;
+    unsigned int* coords = (unsigned int*)malloc(xbt_dynar_length(dimensions)*sizeof(unsigned int));
+    for (i = 0; i < xbt_dynar_length(dimensions); i++) {
+        cur_dim_size = xbt_dynar_get_as(dimensions, i, int);
+        coords[i] = (rankId / dim_size_product) % cur_dim_size;
+        dim_size_product *= cur_dim_size;
+    }
+
+    return coords;
+}
+
+
+AS_t model_torus_cluster_create(void)
+{
+  return new AsClusterTorus();
+}
+
+/* Creation routing model functions */
+AsClusterTorus::AsClusterTorus() : AsCluster()
+{
+  p_dimensions = NULL;
+}
+
+
+
+void AsClusterTorus::create_links_for_node(sg_platf_cluster_cbarg_t cluster, int id, int rank, int position){
+  s_sg_platf_link_cbarg_t link;
+  char* link_id;
+  unsigned int j = 0;
+  /**
+   * Create all links that exist in the torus.
+   * Each rank creates #dimensions-1 links
+   */
+  int neighbour_rank_id = 0; // The other node the link connects
+  int current_dimension = 0, // which dimension are we currently in?
+      // we need to iterate over all dimensions
+      // and create all links there
+      dim_product       = 1; // Needed to calculate the next neighbour_id
+  for (j = 0; j < xbt_dynar_length(p_dimensions); j++) {
+
+      memset(&link, 0, sizeof(link));
+      current_dimension = xbt_dynar_get_as(p_dimensions, j, int);
+      neighbour_rank_id = ( ((int) rank / dim_product) % current_dimension == current_dimension-1) ? rank - (current_dimension-1)*dim_product : rank + dim_product;
+      //name of neighbour is not right for non contiguous cluster radicals (as id != rank in this case)
+      link_id           = bprintf("%s_link_from_%i_to_%i", cluster->id, id, neighbour_rank_id);
+      link.id           = link_id;
+      link.bandwidth    = cluster->bw;
+      link.latency      = cluster->lat;
+      link.state        = SURF_RESOURCE_ON;
+      link.policy       = cluster->sharing_policy;
+      sg_platf_new_link(&link);
+      s_surf_parsing_link_up_down_t info;
+      if (link.policy == SURF_LINK_FULLDUPLEX) {
+          char *tmp_link = bprintf("%s_UP", link_id);
+          info.link_up =
+              xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL);
+          free(tmp_link);
+          tmp_link = bprintf("%s_DOWN", link_id);
+          info.link_down =
+              xbt_lib_get_or_null(link_lib, tmp_link, SURF_LINK_LEVEL);
+          free(tmp_link);
+      } else {
+          info.link_up = xbt_lib_get_or_null(link_lib, link_id, SURF_LINK_LEVEL);
+          info.link_down = info.link_up;
+      }
+      /**
+       * Add the link to its appropriate position;
+       * note that position rankId*(xbt_dynar_length(dimensions)+has_loopack?+has_limiter?)
+       * holds the link "rankId->rankId"
+       */
+      xbt_dynar_set(p_linkUpDownList, position
+          + j,
+          &info);
+      dim_product   *= current_dimension;
+      xbt_free(link_id);
+  }
+  rank++;
+}
+
+void AsClusterTorus::parse_specific_arguments(sg_platf_cluster_cbarg_t cluster){
+
+  unsigned int iter;
+  char *groups;
+  p_dimensions = xbt_str_split(cluster->topo_parameters, ",");
+
+    if (!xbt_dynar_is_empty(p_dimensions)) {
+      /**
+       * We are in a torus cluster
+       * Parse attribute dimensions="dim1,dim2,dim3,...,dimN"
+       * and safe it in a dynarray.
+       * Additionally, we need to know how many ranks we have in total
+       */
+      xbt_dynar_foreach(p_dimensions, iter, groups) {
+          int tmp = surf_parse_get_int(xbt_dynar_get_as(p_dimensions, iter, char *));
+          xbt_dynar_set_as(p_dimensions, iter, int, tmp);
+      }
+
+      p_nb_links_per_node = xbt_dynar_length(p_dimensions);
+
+    }
+}
+
+void AsClusterTorus::getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t route, double *lat){
+
+  XBT_INFO("torus_get_route_and_latency from '%s'[%d] to '%s'[%d]",
+               src->p_name,src->m_id,
+               dst->p_name,dst->m_id);
+
+     if (dst->p_rcType == SURF_NETWORK_ELEMENT_ROUTER || src->p_rcType == SURF_NETWORK_ELEMENT_ROUTER) return;
+
+     if((src->m_id == dst->m_id) && p_has_loopback  ){
+       s_surf_parsing_link_up_down_t info = xbt_dynar_get_as(p_linkUpDownList, src->m_id * p_nb_links_per_node, s_surf_parsing_link_up_down_t);
+       xbt_dynar_push_as(route->link_list, void *, info.link_up);
+
+       if (lat)
+         *lat += static_cast<NetworkLinkPtr>(info.link_up)->getLatency();
+       return;
+     }
+
+
+     /**
+      * Dimension based routing routes through each dimension consecutively
+      * TODO Change to dynamic assignment
+      */
+     unsigned int j, cur_dim, dim_product   = 1;
+     long current_node    = src->m_id;
+     long unsigned next_node       = 0;
+     /**
+      * Arrays that hold the coordinates of the current node and
+      * the target; comparing the values at the i-th position of
+      * both arrays, we can easily assess whether we need to route
+      * into this dimension or not.
+      */
+     unsigned int* myCoords, *targetCoords;
+     myCoords     = rankId_to_coords(src->m_id, p_dimensions);
+     targetCoords = rankId_to_coords(dst->m_id, p_dimensions);
+     /**
+      * linkOffset describes the offset where the link
+      * we want to use is stored
+      * (+1 is added because each node has a link from itself to itself,
+      * which can only be the case if src->m_id == dst->m_id -- see above
+      * for this special case)
+      */
+     long nodeOffset = (xbt_dynar_length(p_dimensions)+1)*src->m_id;
+
+     long linkOffset = nodeOffset;
+     bool use_lnk_up          = false; // Is this link of the form "cur -> next" or "next -> cur"?
+                                       // false means: next -> cur
+     while (current_node != dst->m_id) {
+       dim_product = 1; // First, we will route in x-dimension
+       for (j = 0; j < xbt_dynar_length(p_dimensions); j++) {
+           cur_dim = xbt_dynar_get_as(p_dimensions, j, int);
+
+           // current_node/dim_product = position in current dimension
+           if ((current_node/dim_product) % cur_dim != (dst->m_id/dim_product) % cur_dim) {
+
+               if (( targetCoords[j] > myCoords[j] && targetCoords[j] <= myCoords[j]+cur_dim/2) // Is the target node on the right, without the wrap-around?
+                   || ( myCoords[j] > cur_dim/2 && (myCoords[j]+cur_dim/2)%cur_dim >= targetCoords[j] )) { // Or do we need to use the wrap around to reach it?
+                 if ((current_node / dim_product) % cur_dim == cur_dim-1)
+                     next_node = (current_node+dim_product-dim_product*cur_dim);
+                 else
+                     next_node = (current_node+dim_product);
+
+                 // HERE: We use *CURRENT* node for calculation (as opposed to next_node)
+                 nodeOffset = current_node*(p_nb_links_per_node);
+                 linkOffset = nodeOffset+p_has_loopback+p_has_limiter+j;
+                 use_lnk_up = true;
+                 assert(linkOffset >= 0);
+               }
+               else { // Route to the left
+                 if ((current_node / dim_product) % cur_dim == 0)
+                     next_node = (current_node-dim_product+dim_product*cur_dim);
+                 else
+                     next_node = (current_node-dim_product);
+
+                 // HERE: We use *next* node for calculation (as opposed to current_node!)
+                 nodeOffset = next_node*(p_nb_links_per_node);
+                 linkOffset = nodeOffset+j+p_has_loopback+p_has_limiter;
+                 use_lnk_up = false;
+
+                 assert(linkOffset >= 0);
+               }
+               XBT_DEBUG("torus_get_route_and_latency - current_node: %lu, next_node: %lu, linkOffset is %lu",
+               current_node, next_node, linkOffset);
+
+               break;
+           }
+
+           dim_product *= cur_dim;
+       }
+
+       s_surf_parsing_link_up_down_t info;
+
+       if (p_has_limiter){          // limiter for sender
+             info = xbt_dynar_get_as(p_linkUpDownList, nodeOffset + p_has_loopback, s_surf_parsing_link_up_down_t);
+             xbt_dynar_push_as(route->link_list, void *, info.link_up);
+       }
+
+       info = xbt_dynar_get_as(p_linkUpDownList,linkOffset, s_surf_parsing_link_up_down_t);
+
+       if (use_lnk_up == false)
+           xbt_dynar_push_as(route->link_list,void*,info.link_down);
+       else
+           xbt_dynar_push_as(route->link_list,void*,info.link_up);
+
+       current_node = next_node;
+       next_node = 0;
+     }
+     free(myCoords);
+     free(targetCoords);
+
+
+
+  return;
+}
diff --git a/src/surf/surf_routing_cluster_torus.hpp b/src/surf/surf_routing_cluster_torus.hpp
new file mode 100644 (file)
index 0000000..995700f
--- /dev/null
@@ -0,0 +1,26 @@
+#include "surf_routing_none.hpp"
+#include "network_interface.hpp"
+#include "surf_routing_cluster.hpp"
+
+
+#ifndef SURF_ROUTING_CLUSTER_TORUS_HPP_
+#define SURF_ROUTING_CLUSTER_TORUS_HPP_
+
+class AsClusterTorus;
+typedef AsClusterTorus *AsClusterTorusPtr;
+
+
+class AsClusterTorus: public AsCluster {
+public:
+   AsClusterTorus();
+   virtual void create_links_for_node(sg_platf_cluster_cbarg_t cluster, int id, int rank, int position);
+   virtual void getRouteAndLatency(RoutingEdgePtr src, RoutingEdgePtr dst, sg_platf_route_cbarg_t into, double *latency);
+   void parse_specific_arguments(sg_platf_cluster_cbarg_t cluster);
+
+
+   xbt_dynar_t p_dimensions;
+
+};
+
+
+#endif
index 5528943..54c50b7 100644 (file)
@@ -67,6 +67,8 @@ void model_floyd_parse_route(AS_t rc, sg_platf_route_cbarg_t route);
 /* **************  Cluster ROUTING   **************** */
 
 AsPtr model_cluster_create(void);      /* create structures for cluster routing model */
+AsPtr model_torus_cluster_create(void);      /* create structures for cluster routing model */
+
 
 /* ************************************************** */
 /* **************  Vivaldi ROUTING   **************** */
index f4439bb..86635a1 100644 (file)
@@ -520,7 +520,20 @@ void ETag_surfxml_cluster(void){
     cluster.loopback_bw = surf_parse_get_bandwidth(A_surfxml_cluster_loopback___bw);
   if(strcmp(A_surfxml_cluster_loopback___lat,""))
     cluster.loopback_lat = surf_parse_get_time(A_surfxml_cluster_loopback___lat);
-  cluster.torus_dimensions = A_surfxml_cluster_torus___dimensions;
+
+  switch(AX_surfxml_cluster_topology){
+  case A_surfxml_cluster_topology_FLAT:
+    cluster.topology= SURF_CLUSTER_FLAT ;
+    break;
+  case A_surfxml_cluster_topology_TORUS:
+    cluster.topology= SURF_CLUSTER_TORUS ;
+    break;
+  default:
+    surf_parse_error("Invalid cluster topology for cluster %s",
+                     cluster.id);
+    break;
+  }
+  cluster.topo_parameters = A_surfxml_cluster_topo___parameters;
   cluster.router_id = A_surfxml_cluster_router___id;
 
   switch (AX_surfxml_cluster_sharing___policy) {