| #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(); | |
| } | |
| /**************************************/ |