SRC/stats.c File Reference

#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"
Include dependency graph for stats.c:

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)

Function Documentation

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the caller graph for this function:

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 }

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:

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 }

Here is the call graph for this function:

Here is the caller graph for this function:


Generated on Tue Jan 5 15:26:37 2010 for VPR5.0 by  doxygen 1.6.1