⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stats.c

📁 用于学术研究的FPGA布局布线软件VPR
💻 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 + -