blob: 3ba8d85bbfbf250d8009dc15f3968703606645af [file] [log] [blame]
#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, node_in_mst, num_pins_on_net, num_edges;
int nearest_node, nearest_node_dist, nearest_node_in_mst;
t_mst_edge *min_spantree;
boolean *in_mst;
/* given the net number, find and return its minimum spanning tree */
num_pins_on_net = (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));
/* identifier for minimum spanning tree by nodes */
in_mst[0] = TRUE;
for(ipin = 1; ipin < num_pins_on_net; ipin++)
in_mst[ipin] = FALSE;
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;
nearest_node_dist = -1;
nearest_node_in_mst = -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])
{
node_dist =
min_dist_from_mst(ipin, inet, in_mst,
&node_in_mst);
if(nearest_node == -1)
{
nearest_node = ipin;
nearest_node_dist = node_dist;
nearest_node_in_mst = node_in_mst;
}
else
{
/* Does 0 make sense? Currently allow. 0 means the net loops back to the same block */
if(nearest_node_dist >= node_dist)
{
nearest_node = ipin;
nearest_node_dist = node_dist;
nearest_node_in_mst = node_in_mst;
}
if(nearest_node_dist < 0)
{
printf
("Error: distance is negative\n");
exit(1);
}
}
}
}
/* found the nearest to the current partial mst, so add an edge to mst */
min_spantree[num_edges].from_node = nearest_node_in_mst;
min_spantree[num_edges].to_node = nearest_node;
num_edges++;
in_mst[nearest_node] = TRUE;
}
free(in_mst);
return min_spantree;
}
static int
min_dist_from_mst(int node_outside,
int inet,
boolean * in_mst,
int *node_inside)
{
int ipin, blk1, blk2, dist, closest_node_in_mst, shortest_dist;
/* given a node outside the mst this routine finds its shortest distance to the current partial
* mst, as well as the corresponding node inside mst */
closest_node_in_mst = -1;
shortest_dist = -1;
/* search over all blocks inside mst */
for(ipin = 0; ipin < (net[inet].num_sinks + 1); ipin++)
{
if(in_mst[ipin])
{
blk1 = net[inet].node_block[node_outside];
blk2 = net[inet].node_block[ipin];
dist =
ABS_DIFF(block[blk1].x,
block[blk2].x) + ABS_DIFF(block[blk1].y,
block[blk2].y);
if(closest_node_in_mst == -1)
{
closest_node_in_mst = ipin;
shortest_dist = dist;
}
else
{
if(shortest_dist > dist)
{
closest_node_in_mst = ipin;
shortest_dist = dist;
}
}
}
}
*node_inside = closest_node_in_mst;
return shortest_dist;
}