153 lines
4.8 KiB
C
153 lines
4.8 KiB
C
|
#include <stdio.h>
|
||
|
#include <math.h>
|
||
|
#include "util.h"
|
||
|
#include "vpr_types.h"
|
||
|
#include "globals.h"
|
||
|
#include "path_delay.h"
|
||
|
#include "path_delay2.h"
|
||
|
#include "net_delay.h"
|
||
|
#include "timing_place_lookup.h"
|
||
|
#include "timing_place.h"
|
||
|
|
||
|
float **timing_place_crit; /*available externally */
|
||
|
|
||
|
static t_chunk timing_place_crit_ch = {NULL, 0, NULL};
|
||
|
static t_chunk net_delay_ch = {NULL, 0, NULL};
|
||
|
|
||
|
/*static struct s_linked_vptr *timing_place_crit_chunk_list_head;
|
||
|
static struct s_linked_vptr *net_delay_chunk_list_head;*/
|
||
|
|
||
|
/******** prototypes ******************/
|
||
|
/*static float **alloc_crit(struct s_linked_vptr **chunk_list_head_ptr);
|
||
|
|
||
|
static void free_crit(struct s_linked_vptr **chunk_list_head_ptr);*/
|
||
|
|
||
|
static float **alloc_crit(t_chunk *chunk_list_ptr);
|
||
|
|
||
|
static void free_crit(t_chunk *chunk_list_ptr);
|
||
|
|
||
|
/**************************************/
|
||
|
|
||
|
static float ** alloc_crit(t_chunk *chunk_list_ptr) {
|
||
|
|
||
|
/* Allocates space for the timing_place_crit data structure *
|
||
|
* [0..num_nets-1][1..num_pins-1]. I chunk the data to save space on large *
|
||
|
* problems. */
|
||
|
|
||
|
float **local_crit; /* [0..num_nets-1][1..num_pins-1] */
|
||
|
float *tmp_ptr;
|
||
|
int inet;
|
||
|
|
||
|
local_crit = (float **) my_malloc(num_nets * sizeof(float *));
|
||
|
|
||
|
for (inet = 0; inet < num_nets; inet++) {
|
||
|
tmp_ptr = (float *) my_chunk_malloc(
|
||
|
(clb_net[inet].num_sinks) * sizeof(float), chunk_list_ptr);
|
||
|
local_crit[inet] = tmp_ptr - 1; /* [1..num_sinks] */
|
||
|
}
|
||
|
|
||
|
return (local_crit);
|
||
|
}
|
||
|
|
||
|
/**************************************/
|
||
|
static void free_crit(t_chunk *chunk_list_ptr){
|
||
|
free_chunk_memory(chunk_list_ptr);
|
||
|
}
|
||
|
|
||
|
/**************************************/
|
||
|
void print_sink_delays(const char *fname) {
|
||
|
|
||
|
int num_at_level, num_edges, inode, ilevel, i;
|
||
|
FILE *fp;
|
||
|
|
||
|
fp = my_fopen(fname, "w", 0);
|
||
|
|
||
|
for (ilevel = num_tnode_levels - 1; ilevel >= 0; ilevel--) {
|
||
|
num_at_level = tnodes_at_level[ilevel].nelem;
|
||
|
|
||
|
for (i = 0; i < num_at_level; i++) {
|
||
|
inode = tnodes_at_level[ilevel].list[i];
|
||
|
num_edges = tnode[inode].num_edges;
|
||
|
|
||
|
if (num_edges == 0) { /* sink */
|
||
|
fprintf(fp, "%g\n", tnode[inode].T_arr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fclose(fp);
|
||
|
}
|
||
|
|
||
|
/**************************************/
|
||
|
void load_criticalities(t_slack * slacks, float crit_exponent) {
|
||
|
/* Performs a 1-to-1 mapping from criticality to timing_place_crit.
|
||
|
For every pin on every net (or, equivalently, for every tedge ending
|
||
|
in that pin), timing_place_crit = criticality^(criticality exponent) */
|
||
|
|
||
|
int inet, ipin;
|
||
|
#ifdef PATH_COUNTING
|
||
|
float timing_criticality, path_criticality;
|
||
|
#endif
|
||
|
|
||
|
for (inet = 0; inet < num_nets; inet++) {
|
||
|
if (inet == OPEN)
|
||
|
continue;
|
||
|
if (clb_net[inet].is_global)
|
||
|
continue;
|
||
|
for (ipin = 1; ipin <= clb_net[inet].num_sinks; ipin++) {
|
||
|
if (slacks->timing_criticality[inet][ipin] < HUGE_NEGATIVE_FLOAT + 1) {
|
||
|
/* We didn't analyze this connection, so give it a timing_place_crit of 0. */
|
||
|
timing_place_crit[inet][ipin] = 0.;
|
||
|
} else {
|
||
|
#ifdef PATH_COUNTING
|
||
|
/* Calculate criticality as a weighted sum of timing criticality and path
|
||
|
criticality. The placer likes a great deal of contrast between criticalities.
|
||
|
Since path criticality varies much more than timing, we "sharpen" timing
|
||
|
criticality by taking it to some power, crit_exponent (between 1 and 8 by default). */
|
||
|
path_criticality = slacks->path_criticality[inet][ipin];
|
||
|
timing_criticality = pow(slacks->timing_criticality[inet][ipin], crit_exponent);
|
||
|
|
||
|
timing_place_crit[inet][ipin] = PLACE_PATH_WEIGHT * path_criticality
|
||
|
+ (1 - PLACE_PATH_WEIGHT) * timing_criticality;
|
||
|
#else
|
||
|
/* Just take timing criticality to some power (crit_exponent). */
|
||
|
timing_place_crit[inet][ipin] = pow(slacks->timing_criticality[inet][ipin], crit_exponent);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**************************************/
|
||
|
t_slack * alloc_lookups_and_criticalities(t_chan_width_dist chan_width_dist,
|
||
|
struct s_router_opts router_opts,
|
||
|
struct s_det_routing_arch det_routing_arch, t_segment_inf * segment_inf,
|
||
|
t_timing_inf timing_inf, float ***net_delay, INP t_direct_inf *directs,
|
||
|
INP int num_directs) {
|
||
|
|
||
|
t_slack * slacks = alloc_and_load_timing_graph(timing_inf);
|
||
|
|
||
|
(*net_delay) = alloc_net_delay(&net_delay_ch, clb_net,
|
||
|
num_nets);
|
||
|
|
||
|
compute_delay_lookup_tables(router_opts, det_routing_arch, segment_inf,
|
||
|
timing_inf, chan_width_dist, directs, num_directs);
|
||
|
|
||
|
timing_place_crit = alloc_crit(&timing_place_crit_ch);
|
||
|
|
||
|
return slacks;
|
||
|
}
|
||
|
|
||
|
/**************************************/
|
||
|
void free_lookups_and_criticalities(float ***net_delay, t_slack * slacks) {
|
||
|
|
||
|
free(timing_place_crit);
|
||
|
free_crit(&timing_place_crit_ch);
|
||
|
|
||
|
free_timing_graph(slacks);
|
||
|
free_net_delay(*net_delay, &net_delay_ch);
|
||
|
|
||
|
free_place_lookup_structs();
|
||
|
}
|
||
|
|
||
|
/**************************************/
|