OpenFPGA/vpr7_x2p/vpr/SRC/place/timing_place_lookup.c

1068 lines
34 KiB
C
Raw Normal View History

2018-07-26 12:28:21 -05:00
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "route_common.h"
#include "place_and_route.h"
#include "route_tree_timing.h"
#include "route_timing.h"
#include "timing_place_lookup.h"
#include "rr_graph.h"
#include "route_export.h"
#include <assert.h>
#include "read_xml_arch_file.h"
/* mrFPGA : Xifan TANG */
#include "mrfpga_globals.h"
#include "net_delay_types.h"
#include "net_delay_local_void.h"
/* end */
/*this file contains routines that generate the array containing*/
/*the delays between blocks, this is used in the timing driven */
/*placement routines */
/*To compute delay between blocks we place temporary blocks at */
/*different locations in the FPGA and route nets between */
/*the blocks. From this procedure we generate a lookup table */
/*which tells us the delay between different locations in */
/*the FPGA */
/*Note: these routines assume that there is a uniform and even */
/*distribution of the different wire segments. If this is not */
/*the case, then this lookup table will be off */
/*Note: This code removes all heterogeneous types and creates an
artificial 1x1 tile. A good lookup for heterogeniety
requires more research */
#define NET_COUNT 1 /*we only use one net in these routines, */
/*it is repeatedly routed and ripped up */
/*to compute delays between different */
/*locations, this value should not change */
#define NET_USED 0 /*we use net at location zero of the net */
/*structure */
#define NET_USED_SOURCE_BLOCK 0 /*net.block[0] is source block */
#define NET_USED_SINK_BLOCK 1 /*net.block[1] is sink block */
#define SOURCE_BLOCK 0 /*block[0] is source */
#define SINK_BLOCK 1 /*block[1] is sink */
#define BLOCK_COUNT 2 /*use 2 blocks to compute delay between */
/*the various FPGA locations */
/*do not change this number unless you */
/*really know what you are doing, it is */
/*assumed that the net only connects to */
/*two blocks */
#define NUM_TYPES_USED 3 /* number of types used in look up */
#define DEBUG_TIMING_PLACE_LOOKUP /*initialize arrays to known state */
#define DUMPFILE "lookup_dump.echo"
/* #define PRINT_ARRAYS *//*only used during debugging, calls routine to */
/*print out the various lookup arrays */
/***variables that are exported to other modules***/
/*the delta arrays are used to contain the best case routing delay */
/*between different locations on the FPGA. */
float **delta_io_to_clb;
float **delta_clb_to_clb;
float **delta_clb_to_io;
float **delta_io_to_io;
/*** Other Global Arrays ******/
/* I could have allocated these as local variables, and passed them all */
/* around, but was too lazy, since this is a small file, it should not */
/* be a big problem */
static float **net_delay;
static float *pin_criticality;
static int *sink_order;
static t_rt_node **rt_node_of_sink;
static t_type_ptr IO_TYPE_BACKUP;
static t_type_ptr EMPTY_TYPE_BACKUP;
static t_type_ptr FILL_TYPE_BACKUP;
static t_type_descriptor dummy_type_descriptors[NUM_TYPES_USED];
static t_type_descriptor *type_descriptors_backup;
static struct s_grid_tile **grid_backup;
static int num_types_backup;
static t_ivec **clb_opins_used_locally;
#ifdef PRINT_ARRAYS
static FILE *lookup_dump; /* If debugging mode is on, print out to
* the file defined in DUMPFILE */
#endif /* PRINT_ARRAYS */
/*** Function Prototypes *****/
static void alloc_net(void);
static void alloc_block(void);
static void load_simplified_device(void);
static void restore_original_device(void);
static void alloc_and_assign_internal_structures(struct s_net **original_net,
struct s_block **original_block, int *original_num_nets,
int *original_num_blocks);
static void free_and_reset_internal_structures(struct s_net *original_net,
struct s_block *original_block, int original_num_nets,
int original_num_blocks);
static void setup_chan_width(struct s_router_opts router_opts,
t_chan_width_dist chan_width_dist);
static void alloc_routing_structs(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf, INP t_direct_inf *directs,
INP int num_directs);
static void free_routing_structs(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf);
static void assign_locations(t_type_ptr source_type, int source_x_loc,
int source_y_loc, int source_z_loc, t_type_ptr sink_type,
int sink_x_loc, int sink_y_loc, int sink_z_loc);
static float assign_blocks_and_route_net(t_type_ptr source_type,
int source_x_loc, int source_y_loc, t_type_ptr sink_type,
int sink_x_loc, int sink_y_loc, struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf);
static void alloc_delta_arrays(void);
static void free_delta_arrays(void);
static void generic_compute_matrix(float ***matrix_ptr, t_type_ptr source_type,
t_type_ptr sink_type, int source_x, int source_y, int start_x,
int end_x, int start_y, int end_y, struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf);
static void compute_delta_clb_to_clb(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf, int longest_length);
static void compute_delta_io_to_clb(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf);
static void compute_delta_clb_to_io(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf);
static void compute_delta_io_to_io(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf);
static void compute_delta_arrays(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf, int longest_length);
static int get_first_pin(enum e_pin_type pintype, t_type_ptr type);
static int get_longest_segment_length(
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf);
static void reset_placement(void);
/* mrFPGA: Xifan TANG */
void try_buffer_for_net( int inet, t_rc_node** rc_node_free_list, t_linked_rc_edge** rc_edge_free_list, t_linked_rc_ptr* rr_node_to_rc_node, float* net_delay );
static void buffer_net(float* cur_net_delay);
/* end */
#ifdef PRINT_ARRAYS
static void print_array(float **array_to_print,
int x1,
int x2,
int y1,
int y2);
#endif
/**************************************/
static int get_first_pin(enum e_pin_type pintype, t_type_ptr type) {
/*this code assumes logical equivilance between all driving pins */
/*global pins are not hooked up to the temporary net */
int i, currpin;
currpin = 0;
for (i = 0; i < type->num_class; i++) {
if (type->class_inf[i].type == pintype && !type->is_global_pin[currpin])
return (type->class_inf[i].pinlist[0]);
else
currpin += type->class_inf[i].num_pins;
}
assert(0);
exit(0); /*should never hit this line */
}
/**************************************/
static int get_longest_segment_length(
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf) {
int i, length;
length = 0;
for (i = 0; i < det_routing_arch.num_segment; i++) {
if (segment_inf[i].length > length)
length = segment_inf[i].length;
}
return (length);
}
/**************************************/
static void alloc_net(void) {
int i, len;
clb_net = (struct s_net *) my_malloc(num_nets * sizeof(struct s_net));
for (i = 0; i < NET_COUNT; i++) {
/* FIXME: We *really* shouldn't be allocating write-once copies */
len = strlen("TEMP_NET");
clb_net[i].name = (char *) my_malloc((len + 1) * sizeof(char));
clb_net[i].is_global = FALSE;
strcpy(clb_net[NET_USED].name, "TEMP_NET");
clb_net[i].num_sinks = (BLOCK_COUNT - 1);
clb_net[i].node_block = (int *) my_malloc(BLOCK_COUNT * sizeof(int));
clb_net[i].node_block[NET_USED_SOURCE_BLOCK] = NET_USED_SOURCE_BLOCK; /*driving block */
clb_net[i].node_block[NET_USED_SINK_BLOCK] = NET_USED_SINK_BLOCK; /*target block */
clb_net[i].node_block_pin = (int *) my_malloc(
BLOCK_COUNT * sizeof(int));
/*the values for this are allocated in assign_blocks_and_route_net */
}
}
/**************************************/
static void alloc_block(void) {
/*allocates block structure, and assigns values to known parameters */
/*type and x,y fields are left undefined at this stage since they */
/*are not known until we start moving blocks through the clb array */
int ix_b, ix_p, len, i;
int max_pins;
max_pins = 0;
for (i = 0; i < NUM_TYPES_USED; i++) {
max_pins = std::max(max_pins, type_descriptors[i].num_pins);
}
block = (struct s_block *) my_malloc(num_blocks * sizeof(struct s_block));
for (ix_b = 0; ix_b < BLOCK_COUNT; ix_b++) {
len = strlen("TEMP_BLOCK");
block[ix_b].name = (char *) my_malloc((len + 1) * sizeof(char));
strcpy(block[ix_b].name, "TEMP_BLOCK");
block[ix_b].nets = (int *) my_malloc(max_pins * sizeof(int));
block[ix_b].nets[0] = 0;
for (ix_p = 1; ix_p < max_pins; ix_p++)
block[ix_b].nets[ix_p] = OPEN;
}
}
/**************************************/
static void load_simplified_device(void) {
int i, j;
/* Backup original globals */
EMPTY_TYPE_BACKUP = EMPTY_TYPE;
IO_TYPE_BACKUP = IO_TYPE;
FILL_TYPE_BACKUP = FILL_TYPE;
type_descriptors_backup = type_descriptors;
num_types_backup = num_types;
num_types = NUM_TYPES_USED;
/* Fill in homogeneous core type info */
dummy_type_descriptors[0] = *EMPTY_TYPE;
dummy_type_descriptors[0].index = 0;
dummy_type_descriptors[1] = *IO_TYPE;
dummy_type_descriptors[1].index = 1;
dummy_type_descriptors[2] = *FILL_TYPE;
dummy_type_descriptors[2].index = 2;
type_descriptors = dummy_type_descriptors;
EMPTY_TYPE = &dummy_type_descriptors[0];
IO_TYPE = &dummy_type_descriptors[1];
FILL_TYPE = &dummy_type_descriptors[2];
/* Fill in homogeneous core grid info */
grid_backup = grid;
grid = (struct s_grid_tile **) alloc_matrix(0, nx + 1, 0, ny + 1,
sizeof(struct s_grid_tile));
for (i = 0; i < nx + 2; i++) {
for (j = 0; j < ny + 2; j++) {
if ((i == 0 && j == 0) || (i == nx + 1 && j == 0)
|| (i == 0 && j == ny + 1)
|| (i == nx + 1 && j == ny + 1)) {
grid[i][j].type = EMPTY_TYPE;
} else if (i == 0 || i == nx + 1 || j == 0 || j == ny + 1) {
grid[i][j].type = IO_TYPE;
} else {
grid[i][j].type = FILL_TYPE;
}
grid[i][j].blocks = (int*)my_malloc(
grid[i][j].type->capacity * sizeof(int));
grid[i][j].offset = 0;
}
}
}
static void restore_original_device(void) {
int i, j;
/* restore previous globals */
IO_TYPE = IO_TYPE_BACKUP;
EMPTY_TYPE = EMPTY_TYPE_BACKUP;
FILL_TYPE = FILL_TYPE_BACKUP;
type_descriptors = type_descriptors_backup;
num_types = num_types_backup;
/* free allocatd data */
for (i = 0; i < nx + 2; i++) {
for (j = 0; j < ny + 2; j++) {
free(grid[i][j].blocks);
}
}
free_matrix(grid, 0, nx + 1, 0, sizeof(struct s_grid_tile));
grid = grid_backup;
}
/**************************************/
static void reset_placement(void) {
int i, j, k;
for (i = 0; i <= nx + 1; i++) {
for (j = 0; j <= ny + 1; j++) {
grid[i][j].usage = 0;
for (k = 0; k < grid[i][j].type->capacity; k++) {
grid[i][j].blocks[k] = EMPTY;
}
}
}
}
/**************************************/
static void alloc_and_assign_internal_structures(struct s_net **original_net,
struct s_block **original_block, int *original_num_nets,
int *original_num_blocks) {
/*allocate new data structures to hold net, and block info */
*original_net = clb_net;
*original_num_nets = num_nets;
num_nets = NET_COUNT;
alloc_net();
*original_block = block;
*original_num_blocks = num_blocks;
num_blocks = BLOCK_COUNT;
alloc_block();
/* [0..num_nets-1][1..num_pins-1] */
net_delay = (float **) alloc_matrix(0, NET_COUNT - 1, 1, BLOCK_COUNT - 1,
sizeof(float));
reset_placement();
}
/**************************************/
static void free_and_reset_internal_structures(struct s_net *original_net,
struct s_block *original_block, int original_num_nets,
int original_num_blocks) {
/*reset gloabal data structures to the state that they were in before these */
/*lookup computation routines were called */
int i;
/*there should be only one net to free, but this is safer */
for (i = 0; i < NET_COUNT; i++) {
free(clb_net[i].name);
free(clb_net[i].node_block);
free(clb_net[i].node_block_pin);
}
free(clb_net);
clb_net = original_net;
for (i = 0; i < BLOCK_COUNT; i++) {
free(block[i].name);
free(block[i].nets);
}
free(block);
block = original_block;
num_nets = original_num_nets;
num_blocks = original_num_blocks;
free_matrix(net_delay, 0, NET_COUNT - 1, 1, sizeof(float));
}
/**************************************/
static void setup_chan_width(struct s_router_opts router_opts,
t_chan_width_dist chan_width_dist) {
/*we give plenty of tracks, this increases routability for the */
/*lookup table generation */
int width_fac, i, max_pins_per_clb;
max_pins_per_clb = 0;
for (i = 0; i < num_types; i++) {
max_pins_per_clb = std::max(max_pins_per_clb, type_descriptors[i].num_pins);
}
if (router_opts.fixed_channel_width == NO_FIXED_CHANNEL_WIDTH)
width_fac = 4 * max_pins_per_clb; /*this is 2x the value that binary search starts */
/*this should be enough to allow most pins to */
/*connect to tracks in the architecture */
else
width_fac = router_opts.fixed_channel_width;
init_chan(width_fac, chan_width_dist);
}
/**************************************/
static void alloc_routing_structs(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf, INP t_direct_inf *directs,
INP int num_directs) {
int bb_factor;
int warnings;
t_graph_type graph_type;
/*calls routines that set up routing resource graph and associated structures */
/*must set up dummy blocks for the first pass through to setup locally used opins */
/* Only one block per tile */
assign_locations(FILL_TYPE, 1, 1, 0, FILL_TYPE, nx, ny, 0);
clb_opins_used_locally = alloc_route_structs();
free_rr_graph();
if (router_opts.route_type == GLOBAL) {
graph_type = GRAPH_GLOBAL;
} else {
graph_type = (
det_routing_arch.directionality == BI_DIRECTIONAL ?
GRAPH_BIDIR : GRAPH_UNIDIR);
}
build_rr_graph(graph_type, num_types, dummy_type_descriptors, nx, ny, grid,
chan_width_x[0], NULL,
det_routing_arch.switch_block_type, det_routing_arch.Fs,
det_routing_arch.switch_block_sub_type, det_routing_arch.sub_Fs,
det_routing_arch.num_segment,
2018-07-26 12:28:21 -05:00
det_routing_arch.num_switch, segment_inf,
det_routing_arch.global_route_switch,
det_routing_arch.delayless_switch, timing_inf,
det_routing_arch.wire_to_ipin_switch, router_opts.base_cost_type,
NULL, 0, TRUE, /* do not send in direct connections because we care about general placement timing instead of special pin placement timing */
&warnings, 0, NULL, FALSE, FALSE);
alloc_and_load_rr_node_route_structs();
alloc_timing_driven_route_structs(&pin_criticality, &sink_order,
&rt_node_of_sink);
bb_factor = nx + ny; /*set it to a huge value */
init_route_structs(bb_factor);
}
/**************************************/
static void free_routing_structs(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf) {
int i;
free_rr_graph();
free_rr_node_route_structs();
free_route_structs();
free_trace_structs();
free_timing_driven_route_structs(pin_criticality, sink_order,
rt_node_of_sink);
if (clb_opins_used_locally != NULL) {
for (i = 0; i < num_blocks; i++) {
free_ivec_vector(clb_opins_used_locally[i], 0,
block[i].type->num_class - 1);
}
free(clb_opins_used_locally);
clb_opins_used_locally = NULL;
}
}
/**************************************/
static void assign_locations(t_type_ptr source_type, int source_x_loc,
int source_y_loc, int source_z_loc, t_type_ptr sink_type,
int sink_x_loc, int sink_y_loc, int sink_z_loc) {
/*all routing occurs between block 0 (source) and block 1 (sink) */
block[SOURCE_BLOCK].type = source_type;
block[SOURCE_BLOCK].x = source_x_loc;
block[SOURCE_BLOCK].y = source_y_loc;
block[SOURCE_BLOCK].z = source_z_loc;
block[SINK_BLOCK].type = sink_type;
block[SINK_BLOCK].x = sink_x_loc;
block[SINK_BLOCK].y = sink_y_loc;
block[SINK_BLOCK].z = sink_z_loc;
grid[source_x_loc][source_y_loc].blocks[source_z_loc] = SOURCE_BLOCK;
grid[sink_x_loc][sink_y_loc].blocks[sink_z_loc] = SINK_BLOCK;
clb_net[NET_USED].node_block_pin[NET_USED_SOURCE_BLOCK] = get_first_pin(
DRIVER, block[SOURCE_BLOCK].type);
clb_net[NET_USED].node_block_pin[NET_USED_SINK_BLOCK] = get_first_pin(
RECEIVER, block[SINK_BLOCK].type);
grid[source_x_loc][source_y_loc].usage += 1;
grid[sink_x_loc][sink_y_loc].usage += 1;
}
/**************************************/
static float assign_blocks_and_route_net(t_type_ptr source_type,
int source_x_loc, int source_y_loc, t_type_ptr sink_type,
int sink_x_loc, int sink_y_loc, struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf) {
/*places blocks at the specified locations, and routes a net between them */
/*returns the delay of this net */
float pres_fac, net_delay_value;
int source_z_loc, sink_z_loc;
/* Only one block per tile */
source_z_loc = 0;
sink_z_loc = 0;
net_delay_value = IMPOSSIBLE; /*set to known value for debug purposes */
assign_locations(source_type, source_x_loc, source_y_loc, source_z_loc,
sink_type, sink_x_loc, sink_y_loc, sink_z_loc);
load_net_rr_terminals(rr_node_indices);
pres_fac = 0; /* ignore congestion */
/* Route this net with a dummy criticality of 0 by calling
timing_driven_route_net with slacks set to NULL. */
timing_driven_route_net(NET_USED, pres_fac,
router_opts.max_criticality, router_opts.criticality_exp,
router_opts.astar_fac, router_opts.bend_cost,
pin_criticality, sink_order, rt_node_of_sink,
net_delay[NET_USED], NULL);
/* mrFPGA */
if (is_mrFPGA && is_wire_buffer) {
buffer_net(net_delay[NET_USED]);
}
/* end */
net_delay_value = net_delay[NET_USED][NET_USED_SINK_BLOCK];
grid[source_x_loc][source_y_loc].usage = 0;
grid[source_x_loc][source_y_loc].blocks[source_z_loc] = EMPTY;
grid[sink_x_loc][sink_y_loc].usage = 0;
grid[sink_x_loc][sink_y_loc].blocks[sink_z_loc] = EMPTY;
return (net_delay_value);
}
/**************************************/
static void alloc_delta_arrays(void) {
int id_x, id_y;
delta_clb_to_clb = (float **) alloc_matrix(0, nx - 1, 0, ny - 1,
sizeof(float));
delta_io_to_clb = (float **) alloc_matrix(0, nx, 0, ny, sizeof(float));
delta_clb_to_io = (float **) alloc_matrix(0, nx, 0, ny, sizeof(float));
delta_io_to_io = (float **) alloc_matrix(0, nx + 1, 0, ny + 1,
sizeof(float));
/*initialize all of the array locations to -1 */
for (id_x = 0; id_x <= nx; id_x++) {
for (id_y = 0; id_y <= ny; id_y++) {
delta_io_to_clb[id_x][id_y] = IMPOSSIBLE;
}
}
for (id_x = 0; id_x <= nx - 1; id_x++) {
for (id_y = 0; id_y <= ny - 1; id_y++) {
delta_clb_to_clb[id_x][id_y] = IMPOSSIBLE;
}
}
for (id_x = 0; id_x <= nx; id_x++) {
for (id_y = 0; id_y <= ny; id_y++) {
delta_clb_to_io[id_x][id_y] = IMPOSSIBLE;
}
}
for (id_x = 0; id_x <= nx + 1; id_x++) {
for (id_y = 0; id_y <= ny + 1; id_y++) {
delta_io_to_io[id_x][id_y] = IMPOSSIBLE;
}
}
}
/**************************************/
static void free_delta_arrays(void) {
free_matrix(delta_io_to_clb, 0, nx, 0, sizeof(float));
free_matrix(delta_clb_to_clb, 0, nx - 1, 0, sizeof(float));
free_matrix(delta_clb_to_io, 0, nx, 0, sizeof(float));
free_matrix(delta_io_to_io, 0, nx + 1, 0, sizeof(float));
}
/**************************************/
static void generic_compute_matrix(float ***matrix_ptr, t_type_ptr source_type,
t_type_ptr sink_type, int source_x, int source_y, int start_x,
int end_x, int start_y, int end_y, struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf) {
int delta_x, delta_y;
int sink_x, sink_y;
for (sink_x = start_x; sink_x <= end_x; sink_x++) {
for (sink_y = start_y; sink_y <= end_y; sink_y++) {
delta_x = abs(sink_x - source_x);
delta_y = abs(sink_y - source_y);
if (delta_x == 0 && delta_y == 0)
continue; /*do not compute distance from a block to itself */
/*if a value is desired, pre-assign it somewhere else */
(*matrix_ptr)[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
}
}
/**************************************/
static void compute_delta_clb_to_clb(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf, int longest_length) {
/*this routine must compute delay values in a slightly different way than the */
/*other compute routines. We cannot use a location close to the edge as the */
/*source location for the majority of the delay computations because this */
/*would give gradually increasing delay values. To avoid this from happening */
/*a clb that is at least longest_length away from an edge should be chosen */
/*as a source , if longest_length is more than 0.5 of the total size then */
/*choose a CLB at the center as the source CLB */
int source_x, source_y, sink_x, sink_y;
int start_x, start_y, end_x, end_y;
int delta_x, delta_y;
t_type_ptr source_type, sink_type;
source_type = FILL_TYPE;
sink_type = FILL_TYPE;
if (longest_length < 0.5 * (nx)) {
start_x = longest_length;
} else {
start_x = (int) (0.5 * nx);
}
end_x = nx;
source_x = start_x;
if (longest_length < 0.5 * (ny)) {
start_y = longest_length;
} else {
start_y = (int) (0.5 * ny);
}
end_y = ny;
source_y = start_y;
/*don't put the sink all the way to the corner, until it is necessary */
for (sink_x = start_x; sink_x <= end_x - 1; sink_x++) {
for (sink_y = start_y; sink_y <= end_y - 1; sink_y++) {
delta_x = abs(sink_x - source_x);
delta_y = abs(sink_y - source_y);
if (delta_x == 0 && delta_y == 0) {
delta_clb_to_clb[delta_x][delta_y] = 0.0;
continue;
}
delta_clb_to_clb[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
}
sink_x = end_x - 1;
sink_y = end_y - 1;
for (source_x = start_x - 1; source_x >= 1; source_x--) {
for (source_y = start_y; source_y <= end_y - 1; source_y++) {
delta_x = abs(sink_x - source_x);
delta_y = abs(sink_y - source_y);
delta_clb_to_clb[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
}
for (source_x = 1; source_x <= end_x - 1; source_x++) {
for (source_y = 1; source_y < start_y; source_y++) {
delta_x = abs(sink_x - source_x);
delta_y = abs(sink_y - source_y);
delta_clb_to_clb[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
}
/*now move sink into the top right corner */
sink_x = end_x;
sink_y = end_y;
source_x = 1;
for (source_y = 1; source_y <= end_y; source_y++) {
delta_x = abs(sink_x - source_x);
delta_y = abs(sink_y - source_y);
delta_clb_to_clb[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
sink_x = end_x;
sink_y = end_y;
source_y = 1;
for (source_x = 1; source_x <= end_x; source_x++) {
delta_x = abs(sink_x - source_x);
delta_y = abs(sink_y - source_y);
delta_clb_to_clb[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
}
/**************************************/
static void compute_delta_io_to_clb(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf) {
int source_x, source_y;
int start_x, start_y, end_x, end_y;
t_type_ptr source_type, sink_type;
source_type = IO_TYPE;
sink_type = FILL_TYPE;
delta_io_to_clb[0][0] = IMPOSSIBLE;
delta_io_to_clb[nx][ny] = IMPOSSIBLE;
source_x = 0;
source_y = 1;
start_x = 1;
end_x = nx;
start_y = 1;
end_y = ny;
generic_compute_matrix(&delta_io_to_clb, source_type, sink_type, source_x,
source_y, start_x, end_x, start_y, end_y, router_opts,
det_routing_arch, segment_inf, timing_inf);
source_x = 1;
source_y = 0;
start_x = 1;
end_x = 1;
start_y = 1;
end_y = ny;
generic_compute_matrix(&delta_io_to_clb, source_type, sink_type, source_x,
source_y, start_x, end_x, start_y, end_y, router_opts,
det_routing_arch, segment_inf, timing_inf);
start_x = 1;
end_x = nx;
start_y = ny;
end_y = ny;
generic_compute_matrix(&delta_io_to_clb, source_type, sink_type, source_x,
source_y, start_x, end_x, start_y, end_y, router_opts,
det_routing_arch, segment_inf, timing_inf);
}
/**************************************/
static void compute_delta_clb_to_io(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf) {
int source_x, source_y, sink_x, sink_y;
int delta_x, delta_y;
t_type_ptr source_type, sink_type;
source_type = FILL_TYPE;
sink_type = IO_TYPE;
delta_clb_to_io[0][0] = IMPOSSIBLE;
delta_clb_to_io[nx][ny] = IMPOSSIBLE;
sink_x = 0;
sink_y = 1;
for (source_x = 1; source_x <= nx; source_x++) {
for (source_y = 1; source_y <= ny; source_y++) {
delta_x = abs(source_x - sink_x);
delta_y = abs(source_y - sink_y);
delta_clb_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
}
sink_x = 1;
sink_y = 0;
source_x = 1;
delta_x = abs(source_x - sink_x);
for (source_y = 1; source_y <= ny; source_y++) {
delta_y = abs(source_y - sink_y);
delta_clb_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
sink_x = 1;
sink_y = 0;
source_y = ny;
delta_y = abs(source_y - sink_y);
for (source_x = 2; source_x <= nx; source_x++) {
delta_x = abs(source_x - sink_x);
delta_clb_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
}
/**************************************/
static void compute_delta_io_to_io(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf) {
int source_x, source_y, sink_x, sink_y;
int delta_x, delta_y;
t_type_ptr source_type, sink_type;
source_type = IO_TYPE;
sink_type = IO_TYPE;
delta_io_to_io[0][0] = 0; /*delay to itself is 0 (this can happen) */
delta_io_to_io[nx + 1][ny + 1] = IMPOSSIBLE;
delta_io_to_io[0][ny] = IMPOSSIBLE;
delta_io_to_io[nx][0] = IMPOSSIBLE;
delta_io_to_io[nx][ny + 1] = IMPOSSIBLE;
delta_io_to_io[nx + 1][ny] = IMPOSSIBLE;
source_x = 0;
source_y = 1;
sink_x = 0;
delta_x = abs(sink_x - source_x);
for (sink_y = 2; sink_y <= ny; sink_y++) {
delta_y = abs(sink_y - source_y);
delta_io_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
source_x = 0;
source_y = 1;
sink_x = nx + 1;
delta_x = abs(sink_x - source_x);
for (sink_y = 1; sink_y <= ny; sink_y++) {
delta_y = abs(sink_y - source_y);
delta_io_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
source_x = 1;
source_y = 0;
sink_y = 0;
delta_y = abs(sink_y - source_y);
for (sink_x = 2; sink_x <= nx; sink_x++) {
delta_x = abs(sink_x - source_x);
delta_io_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
source_x = 1;
source_y = 0;
sink_y = ny + 1;
delta_y = abs(sink_y - source_y);
for (sink_x = 1; sink_x <= nx; sink_x++) {
delta_x = abs(sink_x - source_x);
delta_io_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
source_x = 0;
sink_y = ny + 1;
for (source_y = 1; source_y <= ny; source_y++) {
for (sink_x = 1; sink_x <= nx; sink_x++) {
delta_y = abs(source_y - sink_y);
delta_x = abs(source_x - sink_x);
delta_io_to_io[delta_x][delta_y] = assign_blocks_and_route_net(
source_type, source_x, source_y, sink_type, sink_x, sink_y,
router_opts, det_routing_arch, segment_inf, timing_inf);
}
}
}
/**************************************/
#ifdef PRINT_ARRAYS
static void
print_array(float **array_to_print,
int x1,
int x2,
int y1,
int y2)
{
int idx_x, idx_y;
fprintf(lookup_dump, "\nPrinting Array \n\n");
for (idx_y = y2; idx_y >= y1; idx_y--)
{
for (idx_x = x1; idx_x <= x2; idx_x++)
{
fprintf(lookup_dump, " %9.2e",
array_to_print[idx_x][idx_y]);
}
fprintf(lookup_dump, "\n");
}
fprintf(lookup_dump, "\n\n");
}
#endif
/**************************************/
static void compute_delta_arrays(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf, int longest_length) {
vpr_printf(TIO_MESSAGE_INFO, "Computing delta_io_to_io lookup matrix, may take a few seconds, please wait...\n");
compute_delta_io_to_io(router_opts, det_routing_arch, segment_inf, timing_inf);
vpr_printf(TIO_MESSAGE_INFO, "Computing delta_io_to_clb lookup matrix, may take a few seconds, please wait...\n");
compute_delta_io_to_clb(router_opts, det_routing_arch, segment_inf, timing_inf);
vpr_printf(TIO_MESSAGE_INFO, "Computing delta_clb_to_io lookup matrix, may take a few seconds, please wait...\n");
compute_delta_clb_to_io(router_opts, det_routing_arch, segment_inf, timing_inf);
vpr_printf(TIO_MESSAGE_INFO, "Computing delta_clb_to_clb lookup matrix, may take a few seconds, please wait...\n");
compute_delta_clb_to_clb(router_opts, det_routing_arch, segment_inf, timing_inf, longest_length);
#ifdef PRINT_ARRAYS
lookup_dump = my_fopen(DUMPFILE, "w", 0);
fprintf(lookup_dump, "\n\nprinting delta_clb_to_clb\n");
print_array(delta_clb_to_clb, 0, nx - 1, 0, ny - 1);
fprintf(lookup_dump, "\n\nprinting delta_io_to_clb\n");
print_array(delta_io_to_clb, 0, nx, 0, ny);
fprintf(lookup_dump, "\n\nprinting delta_clb_to_io\n");
print_array(delta_clb_to_io, 0, nx, 0, ny);
fprintf(lookup_dump, "\n\nprinting delta_io_to_io\n");
print_array(delta_io_to_io, 0, nx + 1, 0, ny + 1);
fclose(lookup_dump);
#endif
}
/******* Globally Accessable Functions **********/
/**************************************/
void compute_delay_lookup_tables(struct s_router_opts router_opts,
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
t_timing_inf timing_inf, t_chan_width_dist chan_width_dist, INP t_direct_inf *directs,
INP int num_directs) {
static struct s_net *original_net; /*this will be used as a pointer to remember what */
/*the "real" nets in the circuit are. This is */
/*required because we are using the net structure */
/*in these routines to find delays between blocks */
static struct s_block *original_block; /*same def as original_nets, but for block */
static int original_num_nets;
static int original_num_blocks;
static int longest_length;
load_simplified_device();
alloc_and_assign_internal_structures(&original_net, &original_block,
&original_num_nets, &original_num_blocks);
setup_chan_width(router_opts, chan_width_dist);
alloc_routing_structs(router_opts, det_routing_arch, segment_inf,
timing_inf, directs, num_directs);
longest_length = get_longest_segment_length(det_routing_arch, segment_inf);
/*now setup and compute the actual arrays */
alloc_delta_arrays();
compute_delta_arrays(router_opts, det_routing_arch, segment_inf, timing_inf,
longest_length);
/*free all data structures that are no longer needed */
free_routing_structs(router_opts, det_routing_arch, segment_inf,
timing_inf);
restore_original_device();
free_and_reset_internal_structures(original_net, original_block,
original_num_nets, original_num_blocks);
}
/**************************************/
void free_place_lookup_structs(void) {
free_delta_arrays();
}
/* mrFPGA */
static void buffer_net( float* cur_net_delay )
{
t_rc_node *rc_node_free_list;
t_linked_rc_edge *rc_edge_free_list;
//int inet;
t_linked_rc_ptr *rr_node_to_rc_node; /* [0..num_rr_nodes-1] */
vpr_printf(TIO_MESSAGE_INFO, "mrFPGA: net delay before buffer: %g\n", cur_net_delay[NET_USED_SINK_BLOCK] );
rr_node_to_rc_node = (t_linked_rc_ptr *) my_calloc (num_rr_nodes,
sizeof (t_linked_rc_ptr));
rc_node_free_list = NULL;
rc_edge_free_list = NULL;
try_buffer_for_net( NET_USED, &rc_node_free_list, &rc_edge_free_list, rr_node_to_rc_node, cur_net_delay );
free_rc_node_free_list (rc_node_free_list);
free_rc_edge_free_list (rc_edge_free_list);
free (rr_node_to_rc_node);
vpr_printf(TIO_MESSAGE_INFO, "mrFPGA: net delay after buffer: %g\n", cur_net_delay[NET_USED_SINK_BLOCK] );
}
/* end */