00001 #include <assert.h>
00002 #include <stdio.h>
00003 #include <math.h>
00004 #include "util.h"
00005 #include "vpr_types.h"
00006 #include "globals.h"
00007 #include "rr_graph_area.h"
00008 #include "segment_stats.h"
00009 #include "stats.h"
00010 #include "net_delay.h"
00011 #include "path_delay.h"
00012
00013
00014
00015
00016 static void load_channel_occupancies(int **chanx_occ,
00017 int **chany_occ);
00018
00019 static void get_num_bends_and_length(int inet,
00020 int *bends,
00021 int *length,
00022 int *segments);
00023
00024 static void get_length_and_bends_stats(void);
00025
00026 static void get_channel_occupancy_stats(void);
00027
00028
00029
00030
00031
00032
00033 void
00034 routing_stats(boolean full_stats,
00035 enum e_route_type route_type,
00036 int num_switch,
00037 t_segment_inf * segment_inf,
00038 int num_segment,
00039 float R_minW_nmos,
00040 float R_minW_pmos,
00041 enum e_directionality directionality,
00042 boolean timing_analysis_enabled,
00043 float **net_slack,
00044 float **net_delay,
00045 t_subblock_data subblock_data)
00046 {
00047
00048
00049
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
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
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 }
00092
00093
00094 static void
00095 get_length_and_bends_stats(void)
00096 {
00097
00098
00099
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 {
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 }
00158
00159
00160 static void
00161 get_channel_occupancy_stats(void)
00162 {
00163
00164
00165
00166 int i, j, max_occ, total_x, total_y;
00167 float av_occ;
00168 int **chanx_occ;
00169 int **chany_occ;
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 }
00225
00226
00227 static void
00228 load_channel_occupancies(int **chanx_occ,
00229 int **chany_occ)
00230 {
00231
00232
00233
00234
00235 int i, j, inode, inet;
00236 struct s_trace *tptr;
00237 t_rr_type rr_type;
00238
00239
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
00250
00251 for(inet = 0; inet < num_nets; inet++)
00252 {
00253
00254 if(net[inet].is_global)
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;
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 }
00290
00291
00292 static void
00293 get_num_bends_and_length(int inet,
00294 int *bends_ptr,
00295 int *len_ptr,
00296 int *segments_ptr)
00297 {
00298
00299
00300
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];
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 {
00331 tptr = tptr->next;
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 }
00357
00358
00359 void
00360 print_wirelen_prob_dist(void)
00361 {
00362
00363
00364
00365
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
00385
00386
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
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 }
00457
00458
00459 void
00460 print_lambda(void)
00461 {
00462
00463
00464
00465
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)
00486 if(net[inet].is_global == FALSE)
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 }