📄 stats.c
字号:
#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"/********************** Subroutines local to this module *********************/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);/************************* Subroutine definitions ****************************/voidrouting_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){/* Prints out various statistics about the current routing. Both a routing * * and an rr_graph must exist when you call this routine. */ float T_crit; get_length_and_bends_stats(); get_channel_occupancy_stats(); printf("Logic Area (in minimum width transistor areas):\n"); printf("Total Logic Area: %g Per 1x1 logic tile: %g\n", nx * ny * grid_logic_tile_area, grid_logic_tile_area); if(route_type == DETAILED) { count_routing_transistors(directionality, num_switch, segment_inf, R_minW_nmos, R_minW_pmos); get_segment_usage_stats(num_segment, segment_inf); if(timing_analysis_enabled) { load_net_delay_from_routing(net_delay);#ifdef CREATE_ECHO_FILES print_net_delay(net_delay, "net_delay.echo");#endif /* CREATE_ECHO_FILES */ load_timing_graph_net_delays(net_delay); T_crit = load_net_slack(net_slack, 0);#ifdef CREATE_ECHO_FILES print_timing_graph("timing_graph.echo"); print_net_slack("net_slack.echo", net_slack); print_critical_path("critical_path.echo", subblock_data);#endif /* CREATE_ECHO_FILES */ printf("\n"); printf("Critical Path: %g (s)\n", T_crit); } } if(full_stats == TRUE) print_wirelen_prob_dist();}static voidget_length_and_bends_stats(void){/* Figures out maximum, minimum and average number of bends and net length * * in the routing. */ int inet, bends, total_bends, max_bends; int length, total_length, max_length; int segments, total_segments, max_segments; float av_bends, av_length, av_segments; int num_global_nets; max_bends = 0; total_bends = 0; max_length = 0; total_length = 0; max_segments = 0; total_segments = 0; num_global_nets = 0; for(inet = 0; inet < num_nets; inet++) { if(net[inet].is_global == FALSE) { /* Globals don't count. */ get_num_bends_and_length(inet, &bends, &length, &segments); total_bends += bends; max_bends = max(bends, max_bends); total_length += length; max_length = max(length, max_length); total_segments += segments; max_segments = max(segments, max_segments); } else { num_global_nets++; } } av_bends = (float)total_bends / (float)(num_nets - num_global_nets); printf ("\nAverage number of bends per net: %#g Maximum # of bends: %d\n\n", av_bends, max_bends); av_length = (float)total_length / (float)(num_nets - num_global_nets); printf("\nThe number of routed nets (nonglobal): %d\n", num_nets - num_global_nets); printf("Wirelength results (all in units of 1 clb segments):\n"); printf("\tTotal wirelength: %d Average net length: %#g\n", total_length, av_length); printf("\tMaximum net length: %d\n\n", max_length); av_segments = (float)total_segments / (float)(num_nets - num_global_nets); printf("Wirelength results in terms of physical segments:\n"); printf("\tTotal wiring segments used: %d Av. wire segments per net: " "%#g\n", total_segments, av_segments); printf("\tMaximum segments used by a net: %d\n\n", max_segments);}static voidget_channel_occupancy_stats(void){/* Determines how many tracks are used in each channel. */ int i, j, max_occ, total_x, total_y; float av_occ; int **chanx_occ; /* [1..nx][0..ny] */ int **chany_occ; /* [0..nx][1..ny] */ chanx_occ = (int **)alloc_matrix(1, nx, 0, ny, sizeof(int)); chany_occ = (int **)alloc_matrix(0, nx, 1, ny, sizeof(int)); load_channel_occupancies(chanx_occ, chany_occ); printf("\nX - Directed channels:\n\n"); printf("j\tmax occ\tav_occ\t\tcapacity\n"); total_x = 0; for(j = 0; j <= ny; j++) { total_x += chan_width_x[j]; av_occ = 0.; max_occ = -1; for(i = 1; i <= nx; i++) { max_occ = max(chanx_occ[i][j], max_occ); av_occ += chanx_occ[i][j]; } av_occ /= nx; printf("%d\t%d\t%-#9g\t%d\n", j, max_occ, av_occ, chan_width_x[j]); } printf("\nY - Directed channels:\n\n"); printf("i\tmax occ\tav_occ\t\tcapacity\n"); total_y = 0; for(i = 0; i <= nx; i++) { total_y += chan_width_y[i]; av_occ = 0.; max_occ = -1; for(j = 1; j <= ny; j++) { max_occ = max(chany_occ[i][j], max_occ); av_occ += chany_occ[i][j]; } av_occ /= ny; printf("%d\t%d\t%-#9g\t%d\n", i, max_occ, av_occ, chan_width_y[i]); } printf("\nTotal Tracks in X-direction: %d in Y-direction: %d\n\n", total_x, total_y); free_matrix(chanx_occ, 1, nx, 0, sizeof(int)); free_matrix(chany_occ, 0, nx, 1, sizeof(int));}static voidload_channel_occupancies(int **chanx_occ, int **chany_occ){/* Loads the two arrays passed in with the total occupancy at each of the * * channel segments in the FPGA. */ int i, j, inode, inet; struct s_trace *tptr; t_rr_type rr_type;/* First set the occupancy of everything to zero. */ for(i = 1; i <= nx; i++) for(j = 0; j <= ny; j++) chanx_occ[i][j] = 0; for(i = 0; i <= nx; i++) for(j = 1; j <= ny; j++) chany_occ[i][j] = 0;/* Now go through each net and count the tracks and pins used everywhere */ for(inet = 0; inet < num_nets; inet++) { if(net[inet].is_global) /* Skip global nets. */ continue; tptr = trace_head[inet]; while(tptr != NULL) { inode = tptr->index; rr_type = rr_node[inode].type; if(rr_type == SINK) { tptr = tptr->next; /* Skip next segment. */ if(tptr == NULL) break; } else if(rr_type == CHANX) { j = rr_node[inode].ylow; for(i = rr_node[inode].xlow; i <= rr_node[inode].xhigh; i++) chanx_occ[i][j]++; } else if(rr_type == CHANY) { i = rr_node[inode].xlow; for(j = rr_node[inode].ylow; j <= rr_node[inode].yhigh; j++) chany_occ[i][j]++; } tptr = tptr->next; } }}static voidget_num_bends_and_length(int inet, int *bends_ptr, int *len_ptr, int *segments_ptr){/* Counts and returns the number of bends, wirelength, and number of routing * * resource segments in net inet's routing. */ struct s_trace *tptr, *prevptr; int inode; t_rr_type curr_type, prev_type; int bends, length, segments; bends = 0; length = 0; segments = 0; prevptr = trace_head[inet]; /* Should always be SOURCE. */ if(prevptr == NULL) { printf ("Error in get_num_bends_and_length: net #%d has no traceback.\n", inet); exit(1); } inode = prevptr->index; prev_type = rr_node[inode].type; tptr = prevptr->next; while(tptr != NULL) { inode = tptr->index; curr_type = rr_node[inode].type; if(curr_type == SINK) { /* Starting a new segment */ tptr = tptr->next; /* Link to existing path - don't add to len. */ if(tptr == NULL) break; curr_type = rr_node[tptr->index].type; } else if(curr_type == CHANX || curr_type == CHANY) { segments++; length += 1 + rr_node[inode].xhigh - rr_node[inode].xlow + rr_node[inode].yhigh - rr_node[inode].ylow; if(curr_type != prev_type && (prev_type == CHANX || prev_type == CHANY)) bends++; } prev_type = curr_type; tptr = tptr->next; } *bends_ptr = bends; *len_ptr = length; *segments_ptr = segments;}voidprint_wirelen_prob_dist(void){/* Prints out the probability distribution of the wirelength / number * * input pins on a net -- i.e. simulates 2-point net length probability * * distribution. */ float *prob_dist; float norm_fac, two_point_length; int inet, bends, length, segments, index; float av_length; int prob_dist_size, i, incr; prob_dist_size = nx + ny + 10; prob_dist = (float *)my_calloc(prob_dist_size, sizeof(float)); norm_fac = 0.; for(inet = 0; inet < num_nets; inet++) { if(net[inet].is_global == FALSE) { get_num_bends_and_length(inet, &bends, &length, &segments);/* Assign probability to two integer lengths proportionately -- i.e. * * if two_point_length = 1.9, add 0.9 of the pins to prob_dist[2] and * * only 0.1 to prob_dist[1]. */ two_point_length = (float)length / (float)(net[inet].num_sinks); index = (int)two_point_length; if(index >= prob_dist_size) { printf ("Warning: index (%d) to prob_dist exceeds its allocated size (%d)\n", index, prob_dist_size); printf ("Realloc'ing to increase 2-pin wirelen prob distribution array\n"); incr = index - prob_dist_size + 2; prob_dist_size += incr; prob_dist = my_realloc(prob_dist, prob_dist_size * sizeof(float)); for(i = prob_dist_size - incr; i < prob_dist_size; i++) prob_dist[i] = 0.0; } prob_dist[index] += (net[inet].num_sinks) * (1 - two_point_length + index); index++; if(index >= prob_dist_size) { printf ("Warning: index (%d) to prob_dist exceeds its allocated size (%d)\n", index, prob_dist_size); printf ("Realloc'ing to increase 2-pin wirelen prob distribution array\n"); incr = index - prob_dist_size + 2; prob_dist_size += incr; prob_dist = my_realloc(prob_dist, prob_dist_size * sizeof(float)); for(i = prob_dist_size - incr; i < prob_dist_size; i++) prob_dist[i] = 0.0; } prob_dist[index] += (net[inet].num_sinks) * (1 - index + two_point_length); norm_fac += net[inet].num_sinks; } }/* Normalize so total probability is 1 and print out. */ printf("\nProbability distribution of 2-pin net lengths:\n\n"); printf("Length p(Lenth)\n"); av_length = 0; for(index = 0; index < prob_dist_size; index++) { prob_dist[index] /= norm_fac; printf("%6d %10.6f\n", index, prob_dist[index]); av_length += prob_dist[index] * index; } printf("\nThe number of 2-pin nets is ;%g;\n", norm_fac); printf("\nExpected value of 2-pin net length (R) is ;%g;\n", av_length); printf("\nTotal wire length is ;%g;\n", norm_fac * av_length); free(prob_dist);}voidprint_lambda(void){/* Finds the average number of input pins used per fb. Does not * * count inputs which are hooked to global nets (i.e. the clock * * when it is marked global). */ int bnum, ipin; int num_inputs_used = 0; int iclass, inet; float lambda; t_type_ptr type; for(bnum = 0; bnum < num_blocks; bnum++) { type = block[bnum].type; assert(type != NULL); if(type != IO_TYPE) { for(ipin = 0; ipin < type->num_pins; ipin++) { iclass = type->pin_class[ipin]; if(type->class_inf[iclass].type == RECEIVER) { inet = block[bnum].nets[ipin]; if(inet != OPEN) /* Pin is connected? */ if(net[inet].is_global == FALSE) /* Not a global clock */ num_inputs_used++; } } } } lambda = (float)num_inputs_used / (float)num_blocks; printf("Average lambda (input pins used per fb) is: %g\n", lambda);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -