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

📄 place_and_route.c

📁 VPR布局布线源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			{			    current = (high + low) / 2;			}		    else			{			    current = high / 2;	/* haven't found lower bound yet */			}		}	    else		{		/* last route not successful */		    if(success && Fc_clipped)			{			    printf				("Routing rejected, Fc_output was too high.\n");			    success = FALSE;			}		    low = current;		    if(high != -1)			{			    if((high - low) <= 1 * udsd_multiplier)				final = high;			    current = (high + low) / 2;			}		    else			{			    if(router_opts.fixed_channel_width !=			       NO_FIXED_CHANNEL_WIDTH)				{				    /* FOR Wneed = f(Fs) search */				    if(low <				       router_opts.fixed_channel_width + 30)					{					    current =						low + 5 * udsd_multiplier;					}				    else					{					    printf						("Aborting: Wneed = f(Fs) search found exceedingly large Wneed (at least %d)\n",						 low);					    exit(1);					}				}			    else				{				    current = low * 2;	/* Haven't found upper bound yet */				}			}		}	    current = current + current % udsd_multiplier;	}/* The binary search above occassionally does not find the minimum    * * routeable channel width.  Sometimes a circuit that will not route  * * in 19 channels will route in 18, due to router flukiness.  If      *   * verify_binary_search is set, the code below will ensure that FPGAs * * with channel widths of final-2 and final-3 wil not route           *   * successfully.  If one does route successfully, the router keeps    * * trying smaller channel widths until two in a row (e.g. 8 and 9)    * * fail.                                                              */    if(verify_binary_search)	{	    printf		("\nVerifying that binary search found min. channel width ...\n");	    prev_success = TRUE;	/* Actually final - 1 failed, but this makes router */	    /* try final-2 and final-3 even if both fail: safer */	    prev2_success = TRUE;	    current = final - 2;	    while(prev2_success || prev_success)		{		    if((router_opts.fixed_channel_width !=			NO_FIXED_CHANNEL_WIDTH)		       && (current < router_opts.fixed_channel_width))			{			    break;			}		    fflush(stdout);		    if(current < 1)			break;		    if(placer_opts.place_freq == PLACE_ALWAYS)			{			    placer_opts.place_chan_width = current;			    try_place(placer_opts, annealing_sched,				      chan_width_dist, router_opts,				      det_routing_arch, segment_inf,				      timing_inf, subblock_data_ptr, &mst);			}		    success =			try_route(current, router_opts, det_routing_arch,				  segment_inf, timing_inf, net_slack,				  net_delay, chan_width_dist,				  fb_opins_used_locally, mst, &Fc_clipped);		    if(success && Fc_clipped == FALSE)			{			    final = current;			    save_routing(best_routing, fb_opins_used_locally,					 saved_clb_opins_used_locally);			    if(placer_opts.place_freq == PLACE_ALWAYS)				{				    print_place(place_file, net_file,						arch_file);				}			}		    prev2_success = prev_success;		    prev_success = success;		    current--;			if(det_routing_arch.directionality == UNI_DIRECTIONAL) {				current--; /* width must be even */			}		}	}    /* End binary search verification. */    /* Restore the best placement (if necessary), the best routing, and  *     * * the best channel widths for final drawing and statistics output.  */    init_chan(final, chan_width_dist);#if 0    if(placer_opts.place_freq == PLACE_ALWAYS)	{	    printf("Reading best placement back in.\n");	    placer_opts.place_chan_width = final;	    read_place(place_file, net_file, arch_file, placer_opts,		       router_opts, chan_width_dist, det_routing_arch,		       segment_inf, timing_inf, subblock_data_ptr, &mst);	}#endif    free_rr_graph();    build_rr_graph(graph_type,		   num_types, type_descriptors, nx, ny, grid,		   chan_width_x[0], NULL,		   det_routing_arch.switch_block_type, det_routing_arch.Fs,		   det_routing_arch.num_segment, det_routing_arch.num_switch, segment_inf,		   det_routing_arch.global_route_switch,		   det_routing_arch.delayless_switch, timing_inf,		   det_routing_arch.wire_to_ipin_switch,		   router_opts.base_cost_type, &warnings);    restore_routing(best_routing, fb_opins_used_locally,		    saved_clb_opins_used_locally);    check_route(router_opts.route_type, det_routing_arch.num_switch,		fb_opins_used_locally);    get_serial_num();    if(Fc_clipped)	{	    printf		("Warning: Best routing Fc_output too high, clipped to full (maximum) connectivity.\n");	}    printf("Best routing used a channel width factor of %d.\n\n", final);    routing_stats(full_stats, router_opts.route_type,		  det_routing_arch.num_switch, segment_inf,		  det_routing_arch.num_segment,		  det_routing_arch.R_minW_nmos,		  det_routing_arch.R_minW_pmos,		  det_routing_arch.directionality,		  timing_inf.timing_analysis_enabled, net_slack, net_delay,		  *subblock_data_ptr);    print_route(route_file);#ifdef CREATE_ECHO_FILES    /* print_sink_delays("routing_sink_delays.echo"); */#endif /* CREATE_ECHO_FILES */    init_draw_coords(max_pins_per_fb);    sprintf(msg, "Routing succeeded with a channel width factor of %d.",	    final);    update_screen(MAJOR, msg, ROUTING, timing_inf.timing_analysis_enabled);    free_subblock_data(subblock_data_ptr);    if(timing_inf.timing_analysis_enabled)	{	    free_timing_graph(net_slack);	    free_net_delay(net_delay, &net_delay_chunk_list_head);	}    free_route_structs(fb_opins_used_locally);    free_saved_routing(best_routing, saved_clb_opins_used_locally);    fflush(stdout);    return (final);}voidinit_chan(int cfactor,	  t_chan_width_dist chan_width_dist){/* Assigns widths to channels (in tracks).  Minimum one track          *  * per channel.  io channels are io_rat * maximum in interior          *  * tracks wide.  The channel distributions read from the architecture  * * file are scaled by cfactor.                                         */    float x, separation, chan_width_io;    int nio, i;    t_chan chan_x_dist, chan_y_dist;    chan_width_io = chan_width_dist.chan_width_io;    chan_x_dist = chan_width_dist.chan_x_dist;    chan_y_dist = chan_width_dist.chan_y_dist;/* io channel widths */    nio = (int)floor(cfactor * chan_width_io + 0.5);    if(nio == 0)	nio = 1;		/* No zero width channels */    chan_width_x[0] = chan_width_x[ny] = nio;    chan_width_y[0] = chan_width_y[nx] = nio;    if(ny > 1)	{	    separation = 1. / (ny - 2.);	/* Norm. distance between two channels. */	    x = 0.;		/* This avoids div by zero if ny = 2. */	    chan_width_x[1] = (int)floor(cfactor * comp_width(&chan_x_dist, x,							      separation) +					 0.5);	    /* No zero width channels */	    chan_width_x[1] = max(chan_width_x[1], 1);	    for(i = 1; i < ny - 1; i++)		{		    x = (float)i / ((float)(ny - 2.));		    chan_width_x[i + 1] =			(int)floor(cfactor *				   comp_width(&chan_x_dist, x,					      separation) + 0.5);		    chan_width_x[i + 1] = max(chan_width_x[i + 1], 1);		}	}    if(nx > 1)	{	    separation = 1. / (nx - 2.);	/* Norm. distance between two channels. */	    x = 0.;		/* Avoids div by zero if nx = 2. */	    chan_width_y[1] = (int)floor(cfactor * comp_width(&chan_y_dist, x,							      separation) +					 0.5);	    chan_width_y[1] = max(chan_width_y[1], 1);	    for(i = 1; i < nx - 1; i++)		{		    x = (float)i / ((float)(nx - 2.));		    chan_width_y[i + 1] =			(int)floor(cfactor *				   comp_width(&chan_y_dist, x,					      separation) + 0.5);		    chan_width_y[i + 1] = max(chan_width_y[i + 1], 1);		}	}#ifdef VERBOSE    printf("\nchan_width_x:\n");    for(i = 0; i <= ny; i++)	printf("%d  ", chan_width_x[i]);    printf("\n\nchan_width_y:\n");    for(i = 0; i <= nx; i++)	printf("%d  ", chan_width_y[i]);    printf("\n\n");#endif}static floatcomp_width(t_chan * chan,	   float x,	   float separation){/* Return the relative channel density.  *chan points to a channel   * * functional description data structure, and x is the distance      *    * (between 0 and 1) we are across the chip.  separation is the      *    * distance between two channels, in the 0 to 1 coordinate system.   */    float val;    switch (chan->type)	{	case UNIFORM:	    val = chan->peak;	    break;	case GAUSSIAN:	    val = (x - chan->xpeak) * (x - chan->xpeak) / (2 * chan->width *							   chan->width);	    val = chan->peak * exp(-val);	    val += chan->dc;	    break;	case PULSE:	    val = (float)fabs((double)(x - chan->xpeak));	    if(val > chan->width / 2.)		{		    val = 0;		}	    else		{		    val = chan->peak;		}	    val += chan->dc;	    break;	case DELTA:	    val = x - chan->xpeak;	    if(val > -separation / 2. && val <= separation / 2.)		val = chan->peak;	    else		val = 0.;	    val += chan->dc;	    break;	default:	    printf("Error in comp_width:  Unknown channel type %d.\n",		   chan->type);	    exit(1);	    break;	}    return (val);}/* After placement, logical pins for subblocks, blocks, and nets must be updated to correspond with physical pins of type *//* This function should only be called once */voidpost_place_sync(IN int num_blocks,		INOUT const struct s_block block_list[],		INOUT t_subblock_data * subblock_data_ptr){    int iblk, j, k, inet;    t_type_ptr type;    int max_num_block_pins;    t_subblock **subblock_inf;    subblock_inf = subblock_data_ptr->subblock_inf;    /* Go through each block */    for(iblk = 0; iblk < num_blocks; ++iblk)	{	    type = block[iblk].type;	    assert(type->num_pins % type->capacity == 0);	    max_num_block_pins = type->num_pins / type->capacity;	    /* Logical location and physical location is offset by z * max_num_block_pins */	    /* Sync blocks and nets */	    for(j = 0; j < max_num_block_pins; j++)		{		    inet = block[iblk].nets[j];		    if(inet != OPEN && block[iblk].z > 0)			{			    assert(block[iblk].				   nets[j +					block[iblk].z * max_num_block_pins] ==				   OPEN);			    block[iblk].nets[j +					     block[iblk].z *					     max_num_block_pins] =				block[iblk].nets[j];			    block[iblk].nets[j] = OPEN;			    for(k = 0; k < type->num_pins; k++)				{				    if(net[inet].node_block[k] == iblk)					{					    assert(net[inet].						   node_block_pin[k] == j);					    net[inet].node_block_pin[k] =						j +						block[iblk].z *						max_num_block_pins;					    break;					}				}			}		}	    /* Shift subblock pins to point to synced block pins */	    for(j = 0; j < subblock_data_ptr->num_subblocks_per_block[iblk];		j++)		{		    for(k = 0; k < type->max_subblock_inputs; k++)			{			    if(subblock_inf[iblk][j].inputs[k] != OPEN)				{				    subblock_inf[iblk][j].inputs[k] =					subblock_inf[iblk][j].inputs[k] +					block[iblk].z * max_num_block_pins;				}			}		    for(k = 0; k < type->max_subblock_outputs; k++)			{			    if(subblock_inf[iblk][j].outputs[k] != OPEN)				{				    subblock_inf[iblk][j].outputs[k] =					subblock_inf[iblk][j].outputs[k] +					block[iblk].z * max_num_block_pins;				}			}		    if(subblock_inf[iblk][j].clock != OPEN)			{			    subblock_inf[iblk][j].clock =				subblock_inf[iblk][j].clock +				block[iblk].z * max_num_block_pins;			}		}	}}voidfree_subblock_data(t_subblock_data * subblock_data_ptr){	int i, j;	/* Frees all the subblock data structures.                                 */	for(i = 0; i < num_blocks; i++) {		if(subblock_data_ptr->subblock_inf[i] != NULL) {			for(j = 0; j < subblock_data_ptr->num_subblocks_per_block[i]; j++) {				free(subblock_data_ptr->subblock_inf[i][j].name);				free(subblock_data_ptr->subblock_inf[i][j].outputs);				free(subblock_data_ptr->subblock_inf[i][j].inputs);			}			free(subblock_data_ptr->subblock_inf[i]);		}	}    free(subblock_data_ptr->subblock_inf);    free(subblock_data_ptr->num_subblocks_per_block);	/* Mark as freed. */    subblock_data_ptr->num_subblocks_per_block = NULL;    subblock_data_ptr->subblock_inf = NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -