VPR-6.0
|
Go to the source code of this file.
Functions | |
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) |
void | print_wirelen_prob_dist (void) |
void | print_lambda (void) |
void | get_num_bends_and_length (int inet, int *bends, int *length, int *segments) |
void get_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.
Definition at line 320 of file stats.c.
{ 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; }
void print_lambda | ( | void | ) |
Finds the average number of input pins used per clb. Does not count inputs which are hooked to global nets (i.e. the clock when it is marked global).
Definition at line 487 of file stats.c.
{ 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(clb_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 clb) is: %g\n", lambda); }
void print_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.
Definition at line 387 of file stats.c.
{ 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(clb_net[inet].is_global == FALSE && clb_net[inet].num_sinks != 0) { 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)(clb_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] += (clb_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] += (clb_net[inet].num_sinks) * (1 - index + two_point_length); norm_fac += clb_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); }
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 | ||
) |
Prints out various statistics about the current routing. Both a routing and an rr_graph must exist when you call this routine.
Definition at line 32 of file stats.c.
{ float T_crit; float area, used_area; int i, j; get_length_and_bends_stats(); get_channel_occupancy_stats(); printf("Logic Area (in minimum width transistor areas, excludes I/Os and empty grid tiles):\n"); area = 0; for(i = 1; i <= nx; i++) { for(j = 1; j <= ny; j++) { if(grid[i][j].offset == 0) { if(grid[i][j].type->area == UNDEFINED) { area += grid_logic_tile_area * grid[i][j].type->height; } else { area += grid[i][j].type->area; } } } } /* Todo: need to add pitch of routing to blocks with height > 3 */ printf("Total Logic Block Area (Warning, need to add pitch of routing to blocks with height > 3): %g \n", area); used_area = 0; for(i = 0; i < num_blocks; i++) { if(block[i].type != IO_TYPE) { if(block[i].type->area == UNDEFINED) { used_area += grid_logic_tile_area * block[i].type->height; } else { used_area += block[i].type->area; } } } printf("Total Used Logic Block Area: %g \n", used_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, clb_net, num_nets); #ifdef CREATE_ECHO_FILES print_net_delay(net_delay, "net_delay.echo", clb_net, num_nets); #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"); #endif /* CREATE_ECHO_FILES */ printf("\n"); if(pb_max_internal_delay == UNDEFINED || pb_max_internal_delay < T_crit) { printf("Critical Path: %g (s)\n", T_crit); } else { printf("Critical Path: %g (s) - capped by fmax of block type %s\n", pb_max_internal_delay, pbtype_max_internal_delay->name); } } } if(full_stats == TRUE) print_wirelen_prob_dist(); }