VPR-6.0

vpr/SRC/util/mst.c

Go to the documentation of this file.
00001 #include <limits.h>
00002 #include "util.h"
00003 #include "vpr_types.h"
00004 #include "globals.h"
00005 #include "mst.h"
00006 
00007 #define ABS_DIFF(X, Y) (((X) > (Y))? ((X) - (Y)):((Y) - (X)))
00008 
00009 static int min_dist_from_mst(int node_outside,
00010                              int inet,
00011                              boolean * in_mst,
00012                              int *node_inside);
00013 
00014 /** given the net number, find and return its minimum spanning tree */
00015 t_mst_edge *
00016 get_mst_of_net(int inet)
00017 {
00018     int i, ipin, node_dist, num_pins_on_net, num_edges, blk1, blk2;
00019     int nearest_node;
00020     t_mst_edge *min_spantree;
00021     boolean *in_mst;
00022         int *edge_weight_with_curr_mst, *nearest_node_with_curr_mst;
00023 
00024 
00025     num_pins_on_net = (clb_net[inet].num_sinks + 1);
00026         
00027     if(num_pins_on_net > USHRT_MAX)
00028         {
00029             printf("Error: num_pins_on_net (%d) > USHRT_MAX(%u)\n",
00030                    num_pins_on_net, USHRT_MAX);
00031             exit(1);
00032         }
00033 
00034     /* minimum spanning tree represented by a set of edges */
00035     min_spantree =
00036         (t_mst_edge *) my_malloc(sizeof(t_mst_edge) * (num_pins_on_net - 1));
00037     in_mst = (boolean *) my_malloc(sizeof(boolean) * (num_pins_on_net));
00038         edge_weight_with_curr_mst = (int *) my_malloc(sizeof(int) * (num_pins_on_net));
00039         nearest_node_with_curr_mst = (int *) my_malloc(sizeof(int) * (num_pins_on_net));
00040 
00041     /* identifier for minimum spanning tree by nodes */
00042     in_mst[0] = TRUE;
00043     for(ipin = 1; ipin < num_pins_on_net; ipin++) {
00044                 in_mst[ipin] = FALSE;
00045                 blk1 = clb_net[inet].node_block[0];
00046                 blk2 = clb_net[inet].node_block[ipin];
00047                 edge_weight_with_curr_mst[ipin] = ABS_DIFF(block[blk1].x, block[blk2].x) + 
00048                                                                         ABS_DIFF(block[blk1].y, block[blk2].y);
00049                 nearest_node_with_curr_mst[ipin] = 0;
00050         }
00051 
00052     num_edges = 0;
00053 
00054     /* need to add num_pins - 1 number of edges */
00055     for(i = 1; i < num_pins_on_net; i++)
00056         {
00057             /* look at remaining num_pins - 1 pins, and add them to the mst one at a time */
00058 
00059             nearest_node = -1;
00060 
00061             for(ipin = 1; ipin < num_pins_on_net; ipin++)
00062                 {
00063                     /* look at each pin not in the mst, find the nearest to the current partial mst */
00064                     if(!in_mst[ipin])
00065                         {
00066                                 if(nearest_node == -1 || edge_weight_with_curr_mst[ipin] <= edge_weight_with_curr_mst[nearest_node]) {
00067                                     nearest_node = ipin;
00068                                 }
00069                         }
00070                 }
00071 
00072             /* found the nearest to the current partial mst, so add an edge to mst */
00073             min_spantree[num_edges].from_node = nearest_node_with_curr_mst[nearest_node];
00074 
00075             min_spantree[num_edges].to_node = nearest_node;
00076 
00077             num_edges++;
00078 
00079             in_mst[nearest_node] = TRUE;
00080 
00081                 for(ipin = 1; ipin < num_pins_on_net; ipin++)
00082                 {
00083                     /* Update closest node to partial mst */
00084                     if(!in_mst[ipin])
00085                         {
00086                                 blk1 = clb_net[inet].node_block[nearest_node];
00087                                 blk2 = clb_net[inet].node_block[ipin];
00088                                 node_dist = ABS_DIFF(block[blk1].x, block[blk2].x) + 
00089                                                                         ABS_DIFF(block[blk1].y, block[blk2].y);
00090                                 if(node_dist < edge_weight_with_curr_mst[ipin]) {
00091                                     edge_weight_with_curr_mst[ipin] = node_dist;
00092                                         nearest_node_with_curr_mst[ipin] = nearest_node;
00093                                 }
00094                         }
00095                 }
00096         }       
00097 
00098     free(in_mst);
00099         free(edge_weight_with_curr_mst);
00100         free(nearest_node_with_curr_mst);
00101     return min_spantree;
00102 }