| #include <limits.h> |
| #include "util.h" |
| #include "vpr_types.h" |
| #include "globals.h" |
| #include "mst.h" |
| |
| #define ABS_DIFF(X, Y) (((X) > (Y))? ((X) - (Y)):((Y) - (X))) |
| |
| static int min_dist_from_mst(int node_outside, |
| int inet, |
| boolean * in_mst, |
| int *node_inside); |
| |
| t_mst_edge * |
| get_mst_of_net(int inet) |
| { |
| int i, ipin, node_dist, num_pins_on_net, num_edges, blk1, blk2; |
| int nearest_node; |
| t_mst_edge *min_spantree; |
| boolean *in_mst; |
| int *edge_weight_with_curr_mst, *nearest_node_with_curr_mst; |
| |
| /* given the net number, find and return its minimum spanning tree */ |
| |
| num_pins_on_net = (clb_net[inet].num_sinks + 1); |
| |
| if(num_pins_on_net > USHRT_MAX) |
| { |
| printf("Error: num_pins_on_net (%d) > USHRT_MAX(%u)\n", |
| num_pins_on_net, USHRT_MAX); |
| exit(1); |
| } |
| |
| /* minimum spanning tree represented by a set of edges */ |
| min_spantree = |
| (t_mst_edge *) my_malloc(sizeof(t_mst_edge) * (num_pins_on_net - 1)); |
| in_mst = (boolean *) my_malloc(sizeof(boolean) * (num_pins_on_net)); |
| edge_weight_with_curr_mst = (int *) my_malloc(sizeof(int) * (num_pins_on_net)); |
| nearest_node_with_curr_mst = (int *) my_malloc(sizeof(int) * (num_pins_on_net)); |
| |
| /* identifier for minimum spanning tree by nodes */ |
| in_mst[0] = TRUE; |
| for(ipin = 1; ipin < num_pins_on_net; ipin++) { |
| in_mst[ipin] = FALSE; |
| blk1 = clb_net[inet].node_block[0]; |
| blk2 = clb_net[inet].node_block[ipin]; |
| edge_weight_with_curr_mst[ipin] = ABS_DIFF(block[blk1].x, block[blk2].x) + |
| ABS_DIFF(block[blk1].y, block[blk2].y); |
| nearest_node_with_curr_mst[ipin] = 0; |
| } |
| |
| num_edges = 0; |
| |
| /* need to add num_pins - 1 number of edges */ |
| for(i = 1; i < num_pins_on_net; i++) |
| { |
| /* look at remaining num_pins - 1 pins, and add them to the mst one at a time */ |
| |
| nearest_node = -1; |
| |
| for(ipin = 1; ipin < num_pins_on_net; ipin++) |
| { |
| /* look at each pin not in the mst, find the nearest to the current partial mst */ |
| if(!in_mst[ipin]) |
| { |
| if(nearest_node == -1 || edge_weight_with_curr_mst[ipin] <= edge_weight_with_curr_mst[nearest_node]) { |
| nearest_node = ipin; |
| } |
| } |
| } |
| |
| /* found the nearest to the current partial mst, so add an edge to mst */ |
| min_spantree[num_edges].from_node = nearest_node_with_curr_mst[nearest_node]; |
| |
| min_spantree[num_edges].to_node = nearest_node; |
| |
| num_edges++; |
| |
| in_mst[nearest_node] = TRUE; |
| |
| for(ipin = 1; ipin < num_pins_on_net; ipin++) |
| { |
| /* Update closest node to partial mst */ |
| if(!in_mst[ipin]) |
| { |
| blk1 = clb_net[inet].node_block[nearest_node]; |
| blk2 = clb_net[inet].node_block[ipin]; |
| node_dist = ABS_DIFF(block[blk1].x, block[blk2].x) + |
| ABS_DIFF(block[blk1].y, block[blk2].y); |
| if(node_dist < edge_weight_with_curr_mst[ipin]) { |
| edge_weight_with_curr_mst[ipin] = node_dist; |
| nearest_node_with_curr_mst[ipin] = nearest_node; |
| } |
| } |
| } |
| } |
| |
| free(in_mst); |
| free(edge_weight_with_curr_mst); |
| free(nearest_node_with_curr_mst); |
| return min_spantree; |
| } |