#include <assert.h>
#include <stdio.h>
#include <math.h>
#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "rr_graph_area.h"
#include "segment_stats.h"
#include "stats.h"
#include "net_delay.h"
#include "path_delay.h"
Go to the source code of this file.
Functions | |
static void | load_channel_occupancies (int **chanx_occ, int **chany_occ) |
static void | get_num_bends_and_length (int inet, int *bends, int *length, int *segments) |
static void | get_length_and_bends_stats (void) |
static void | get_channel_occupancy_stats (void) |
void | routing_stats (boolean full_stats, enum e_route_type route_type, int num_switch, t_segment_inf *segment_inf, int num_segment, float R_minW_nmos, float R_minW_pmos, enum e_directionality directionality, boolean timing_analysis_enabled, float **net_slack, float **net_delay, t_subblock_data subblock_data) |
void | print_wirelen_prob_dist (void) |
void | print_lambda (void) |
static void get_channel_occupancy_stats | ( | void | ) | [static] |
Definition at line 161 of file stats.c.
00162 { 00163 00164 /* Determines how many tracks are used in each channel. */ 00165 00166 int i, j, max_occ, total_x, total_y; 00167 float av_occ; 00168 int **chanx_occ; /* [1..nx][0..ny] */ 00169 int **chany_occ; /* [0..nx][1..ny] */ 00170 00171 00172 chanx_occ = (int **)alloc_matrix(1, nx, 0, ny, sizeof(int)); 00173 chany_occ = (int **)alloc_matrix(0, nx, 1, ny, sizeof(int)); 00174 load_channel_occupancies(chanx_occ, chany_occ); 00175 00176 printf("\nX - Directed channels:\n\n"); 00177 printf("j\tmax occ\tav_occ\t\tcapacity\n"); 00178 00179 total_x = 0; 00180 00181 for(j = 0; j <= ny; j++) 00182 { 00183 total_x += chan_width_x[j]; 00184 av_occ = 0.; 00185 max_occ = -1; 00186 00187 for(i = 1; i <= nx; i++) 00188 { 00189 max_occ = max(chanx_occ[i][j], max_occ); 00190 av_occ += chanx_occ[i][j]; 00191 } 00192 av_occ /= nx; 00193 printf("%d\t%d\t%-#9g\t%d\n", j, max_occ, av_occ, 00194 chan_width_x[j]); 00195 } 00196 00197 00198 printf("\nY - Directed channels:\n\n"); 00199 printf("i\tmax occ\tav_occ\t\tcapacity\n"); 00200 00201 total_y = 0; 00202 00203 for(i = 0; i <= nx; i++) 00204 { 00205 total_y += chan_width_y[i]; 00206 av_occ = 0.; 00207 max_occ = -1; 00208 00209 for(j = 1; j <= ny; j++) 00210 { 00211 max_occ = max(chany_occ[i][j], max_occ); 00212 av_occ += chany_occ[i][j]; 00213 } 00214 av_occ /= ny; 00215 printf("%d\t%d\t%-#9g\t%d\n", i, max_occ, av_occ, 00216 chan_width_y[i]); 00217 } 00218 00219 printf("\nTotal Tracks in X-direction: %d in Y-direction: %d\n\n", 00220 total_x, total_y); 00221 00222 free_matrix(chanx_occ, 1, nx, 0, sizeof(int)); 00223 free_matrix(chany_occ, 0, nx, 1, sizeof(int)); 00224 }
static void get_length_and_bends_stats | ( | void | ) | [static] |
Definition at line 95 of file stats.c.
00096 { 00097 00098 /* Figures out maximum, minimum and average number of bends and net length * 00099 * in the routing. */ 00100 00101 int inet, bends, total_bends, max_bends; 00102 int length, total_length, max_length; 00103 int segments, total_segments, max_segments; 00104 float av_bends, av_length, av_segments; 00105 int num_global_nets; 00106 00107 00108 max_bends = 0; 00109 total_bends = 0; 00110 max_length = 0; 00111 total_length = 0; 00112 max_segments = 0; 00113 total_segments = 0; 00114 num_global_nets = 0; 00115 00116 for(inet = 0; inet < num_nets; inet++) 00117 { 00118 if(net[inet].is_global == FALSE) 00119 { /* Globals don't count. */ 00120 get_num_bends_and_length(inet, &bends, &length, 00121 &segments); 00122 00123 total_bends += bends; 00124 max_bends = max(bends, max_bends); 00125 00126 total_length += length; 00127 max_length = max(length, max_length); 00128 00129 total_segments += segments; 00130 max_segments = max(segments, max_segments); 00131 } 00132 else 00133 { 00134 num_global_nets++; 00135 } 00136 } 00137 00138 00139 av_bends = (float)total_bends / (float)(num_nets - num_global_nets); 00140 printf 00141 ("\nAverage number of bends per net: %#g Maximum # of bends: %d\n\n", 00142 av_bends, max_bends); 00143 00144 av_length = (float)total_length / (float)(num_nets - num_global_nets); 00145 printf("\nThe number of routed nets (nonglobal): %d\n", 00146 num_nets - num_global_nets); 00147 printf("Wirelength results (all in units of 1 clb segments):\n"); 00148 printf("\tTotal wirelength: %d Average net length: %#g\n", 00149 total_length, av_length); 00150 printf("\tMaximum net length: %d\n\n", max_length); 00151 00152 av_segments = (float)total_segments / (float)(num_nets - num_global_nets); 00153 printf("Wirelength results in terms of physical segments:\n"); 00154 printf("\tTotal wiring segments used: %d Av. wire segments per net: " 00155 "%#g\n", total_segments, av_segments); 00156 printf("\tMaximum segments used by a net: %d\n\n", max_segments); 00157 }
static void get_num_bends_and_length | ( | int | inet, | |
int * | bends, | |||
int * | length, | |||
int * | segments | |||
) | [static] |
Definition at line 293 of file stats.c.
00297 { 00298 00299 /* Counts and returns the number of bends, wirelength, and number of routing * 00300 * resource segments in net inet's routing. */ 00301 00302 struct s_trace *tptr, *prevptr; 00303 int inode; 00304 t_rr_type curr_type, prev_type; 00305 int bends, length, segments; 00306 00307 bends = 0; 00308 length = 0; 00309 segments = 0; 00310 00311 prevptr = trace_head[inet]; /* Should always be SOURCE. */ 00312 if(prevptr == NULL) 00313 { 00314 printf 00315 ("Error in get_num_bends_and_length: net #%d has no traceback.\n", 00316 inet); 00317 exit(1); 00318 } 00319 inode = prevptr->index; 00320 prev_type = rr_node[inode].type; 00321 00322 tptr = prevptr->next; 00323 00324 while(tptr != NULL) 00325 { 00326 inode = tptr->index; 00327 curr_type = rr_node[inode].type; 00328 00329 if(curr_type == SINK) 00330 { /* Starting a new segment */ 00331 tptr = tptr->next; /* Link to existing path - don't add to len. */ 00332 if(tptr == NULL) 00333 break; 00334 00335 curr_type = rr_node[tptr->index].type; 00336 } 00337 00338 else if(curr_type == CHANX || curr_type == CHANY) 00339 { 00340 segments++; 00341 length += 1 + rr_node[inode].xhigh - rr_node[inode].xlow + 00342 rr_node[inode].yhigh - rr_node[inode].ylow; 00343 00344 if(curr_type != prev_type 00345 && (prev_type == CHANX || prev_type == CHANY)) 00346 bends++; 00347 } 00348 00349 prev_type = curr_type; 00350 tptr = tptr->next; 00351 } 00352 00353 *bends_ptr = bends; 00354 *len_ptr = length; 00355 *segments_ptr = segments; 00356 }
static void load_channel_occupancies | ( | int ** | chanx_occ, | |
int ** | chany_occ | |||
) | [static] |
Definition at line 228 of file stats.c.
00230 { 00231 00232 /* Loads the two arrays passed in with the total occupancy at each of the * 00233 * channel segments in the FPGA. */ 00234 00235 int i, j, inode, inet; 00236 struct s_trace *tptr; 00237 t_rr_type rr_type; 00238 00239 /* First set the occupancy of everything to zero. */ 00240 00241 for(i = 1; i <= nx; i++) 00242 for(j = 0; j <= ny; j++) 00243 chanx_occ[i][j] = 0; 00244 00245 for(i = 0; i <= nx; i++) 00246 for(j = 1; j <= ny; j++) 00247 chany_occ[i][j] = 0; 00248 00249 /* Now go through each net and count the tracks and pins used everywhere */ 00250 00251 for(inet = 0; inet < num_nets; inet++) 00252 { 00253 00254 if(net[inet].is_global) /* Skip global nets. */ 00255 continue; 00256 00257 tptr = trace_head[inet]; 00258 while(tptr != NULL) 00259 { 00260 inode = tptr->index; 00261 rr_type = rr_node[inode].type; 00262 00263 if(rr_type == SINK) 00264 { 00265 tptr = tptr->next; /* Skip next segment. */ 00266 if(tptr == NULL) 00267 break; 00268 } 00269 00270 else if(rr_type == CHANX) 00271 { 00272 j = rr_node[inode].ylow; 00273 for(i = rr_node[inode].xlow; 00274 i <= rr_node[inode].xhigh; i++) 00275 chanx_occ[i][j]++; 00276 } 00277 00278 else if(rr_type == CHANY) 00279 { 00280 i = rr_node[inode].xlow; 00281 for(j = rr_node[inode].ylow; 00282 j <= rr_node[inode].yhigh; j++) 00283 chany_occ[i][j]++; 00284 } 00285 00286 tptr = tptr->next; 00287 } 00288 } 00289 }
void print_lambda | ( | void | ) |
Definition at line 460 of file stats.c.
00461 { 00462 00463 /* Finds the average number of input pins used per fb. Does not * 00464 * count inputs which are hooked to global nets (i.e. the clock * 00465 * when it is marked global). */ 00466 00467 int bnum, ipin; 00468 int num_inputs_used = 0; 00469 int iclass, inet; 00470 float lambda; 00471 t_type_ptr type; 00472 00473 for(bnum = 0; bnum < num_blocks; bnum++) 00474 { 00475 type = block[bnum].type; 00476 assert(type != NULL); 00477 if(type != IO_TYPE) 00478 { 00479 for(ipin = 0; ipin < type->num_pins; ipin++) 00480 { 00481 iclass = type->pin_class[ipin]; 00482 if(type->class_inf[iclass].type == RECEIVER) 00483 { 00484 inet = block[bnum].nets[ipin]; 00485 if(inet != OPEN) /* Pin is connected? */ 00486 if(net[inet].is_global == FALSE) /* Not a global clock */ 00487 num_inputs_used++; 00488 } 00489 } 00490 } 00491 } 00492 00493 lambda = (float)num_inputs_used / (float)num_blocks; 00494 printf("Average lambda (input pins used per fb) is: %g\n", lambda); 00495 }
void print_wirelen_prob_dist | ( | void | ) |
Definition at line 360 of file stats.c.
00361 { 00362 00363 /* Prints out the probability distribution of the wirelength / number * 00364 * input pins on a net -- i.e. simulates 2-point net length probability * 00365 * distribution. */ 00366 00367 float *prob_dist; 00368 float norm_fac, two_point_length; 00369 int inet, bends, length, segments, index; 00370 float av_length; 00371 int prob_dist_size, i, incr; 00372 00373 prob_dist_size = nx + ny + 10; 00374 prob_dist = (float *)my_calloc(prob_dist_size, sizeof(float)); 00375 norm_fac = 0.; 00376 00377 for(inet = 0; inet < num_nets; inet++) 00378 { 00379 if(net[inet].is_global == FALSE) 00380 { 00381 get_num_bends_and_length(inet, &bends, &length, 00382 &segments); 00383 00384 /* Assign probability to two integer lengths proportionately -- i.e. * 00385 * if two_point_length = 1.9, add 0.9 of the pins to prob_dist[2] and * 00386 * only 0.1 to prob_dist[1]. */ 00387 00388 two_point_length = 00389 (float)length / (float)(net[inet].num_sinks); 00390 index = (int)two_point_length; 00391 if(index >= prob_dist_size) 00392 { 00393 00394 printf 00395 ("Warning: index (%d) to prob_dist exceeds its allocated size (%d)\n", 00396 index, prob_dist_size); 00397 printf 00398 ("Realloc'ing to increase 2-pin wirelen prob distribution array\n"); 00399 incr = index - prob_dist_size + 2; 00400 prob_dist_size += incr; 00401 prob_dist = 00402 my_realloc(prob_dist, 00403 prob_dist_size * sizeof(float)); 00404 for(i = prob_dist_size - incr; i < prob_dist_size; 00405 i++) 00406 prob_dist[i] = 0.0; 00407 } 00408 prob_dist[index] += 00409 (net[inet].num_sinks) * (1 - two_point_length + 00410 index); 00411 00412 index++; 00413 if(index >= prob_dist_size) 00414 { 00415 00416 printf 00417 ("Warning: index (%d) to prob_dist exceeds its allocated size (%d)\n", 00418 index, prob_dist_size); 00419 printf 00420 ("Realloc'ing to increase 2-pin wirelen prob distribution array\n"); 00421 incr = index - prob_dist_size + 2; 00422 prob_dist_size += incr; 00423 prob_dist = 00424 my_realloc(prob_dist, 00425 prob_dist_size * sizeof(float)); 00426 for(i = prob_dist_size - incr; i < prob_dist_size; 00427 i++) 00428 prob_dist[i] = 0.0; 00429 } 00430 prob_dist[index] += (net[inet].num_sinks) * (1 - index + 00431 two_point_length); 00432 00433 norm_fac += net[inet].num_sinks; 00434 } 00435 } 00436 00437 /* Normalize so total probability is 1 and print out. */ 00438 00439 printf("\nProbability distribution of 2-pin net lengths:\n\n"); 00440 printf("Length p(Lenth)\n"); 00441 00442 av_length = 0; 00443 00444 for(index = 0; index < prob_dist_size; index++) 00445 { 00446 prob_dist[index] /= norm_fac; 00447 printf("%6d %10.6f\n", index, prob_dist[index]); 00448 av_length += prob_dist[index] * index; 00449 } 00450 00451 printf("\nThe number of 2-pin nets is ;%g;\n", norm_fac); 00452 printf("\nExpected value of 2-pin net length (R) is ;%g;\n", av_length); 00453 printf("\nTotal wire length is ;%g;\n", norm_fac * av_length); 00454 00455 free(prob_dist); 00456 }
void routing_stats | ( | boolean | full_stats, | |
enum e_route_type | route_type, | |||
int | num_switch, | |||
t_segment_inf * | segment_inf, | |||
int | num_segment, | |||
float | R_minW_nmos, | |||
float | R_minW_pmos, | |||
enum e_directionality | directionality, | |||
boolean | timing_analysis_enabled, | |||
float ** | net_slack, | |||
float ** | net_delay, | |||
t_subblock_data | subblock_data | |||
) |
Definition at line 34 of file stats.c.
00046 { 00047 00048 /* Prints out various statistics about the current routing. Both a routing * 00049 * and an rr_graph must exist when you call this routine. */ 00050 00051 float T_crit; 00052 00053 00054 get_length_and_bends_stats(); 00055 get_channel_occupancy_stats(); 00056 00057 printf("Logic Area (in minimum width transistor areas):\n"); 00058 printf("Total Logic Area: %g Per 1x1 logic tile: %g\n", 00059 nx * ny * grid_logic_tile_area, grid_logic_tile_area); 00060 00061 if(route_type == DETAILED) 00062 { 00063 count_routing_transistors(directionality, num_switch, segment_inf, 00064 R_minW_nmos, R_minW_pmos); 00065 get_segment_usage_stats(num_segment, segment_inf); 00066 00067 if(timing_analysis_enabled) 00068 { 00069 load_net_delay_from_routing(net_delay); 00070 00071 #ifdef CREATE_ECHO_FILES 00072 print_net_delay(net_delay, "net_delay.echo"); 00073 #endif /* CREATE_ECHO_FILES */ 00074 00075 load_timing_graph_net_delays(net_delay); 00076 T_crit = load_net_slack(net_slack, 0); 00077 00078 #ifdef CREATE_ECHO_FILES 00079 print_timing_graph("timing_graph.echo"); 00080 print_net_slack("net_slack.echo", net_slack); 00081 print_critical_path("critical_path.echo", subblock_data); 00082 #endif /* CREATE_ECHO_FILES */ 00083 00084 printf("\n"); 00085 printf("Critical Path: %g (s)\n", T_crit); 00086 } 00087 } 00088 00089 if(full_stats == TRUE) 00090 print_wirelen_prob_dist(); 00091 }