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

📄 rr_graph.c

📁 VPR布局布线源码
💻 C
📖 第 1 页 / 共 5 页
字号:
					  nodes_per_chan, Fc, directionality);	}    else	{	    load_uniform_switch_pattern(Type,					tracks_connected_to_pin,					num_phys_pins,					pin_num_ordering,					side_ordering,					offset_ordering,					nodes_per_chan, Fc, directionality);	}    check_all_tracks_reach_pins(Type, tracks_connected_to_pin,				nodes_per_chan, Fc, pin_type);    /* Free all temporary storage. */    free_matrix(num_dir, 0, Type->height - 1, 0, sizeof(int));    free_matrix3(dir_list, 0, Type->height - 1, 0, 3, 0, sizeof(int));    free_matrix(num_done_per_dir, 0, Type->height - 1, 0, sizeof(int));    free(pin_num_ordering);    free(side_ordering);    free(offset_ordering);    return tracks_connected_to_pin;}static voidload_uniform_switch_pattern(IN t_type_ptr type,			    INOUT int ****tracks_connected_to_pin,			    IN int num_phys_pins,			    IN int *pin_num_ordering,			    IN int *side_ordering,			    IN int *offset_ordering,			    IN int nodes_per_chan,			    IN int Fc,			    enum e_directionality directionality){    /* Loads the tracks_connected_to_pin array with an even distribution of     *     * switches across the tracks for each pin.  For example, each pin connects *     * to every 4.3rd track in a channel, with exactly which tracks a pin       *     * connects to staggered from pin to pin.                                   */    int i, j, ipin, iside, ioff, itrack, k;    float f_track, fc_step;    int group_size;    float step_size;    /* Uni-directional drive is implemented to ensure no directional bias and this means      * two important comments noted below                                                */    /* 1. Spacing should be (W/2)/(Fc/2), and step_size should be spacing/(num_phys_pins),     *    and lay down 2 switches on an adjacent pair of tracks at a time to ensure     *    no directional bias. Basically, treat W (even) as W/2 pairs of tracks, and     *    assign switches to a pair at a time. Can do this because W is guaranteed to      *    be even-numbered; however same approach cannot be applied to Fc_out pattern     *    when L > 1 and W <> 2L multiple.      *     * 2. This generic pattern should be considered the tileable physical layout,     *    meaning all track # here are physical #'s,     *    so later must use vpr_to_phy conversion to find actual logical #'s to connect.     *    This also means I will not use get_output_block_companion_track to ensure     *    no bias, since that describes a logical # -> that would confuse people.  */    step_size = (float)nodes_per_chan / (float)(Fc * num_phys_pins);    if(directionality == BI_DIRECTIONAL)	{	    group_size = 1;	}    else	{	    assert(directionality == UNI_DIRECTIONAL);	    group_size = 2;	}    assert((nodes_per_chan % group_size == 0) && (Fc % group_size == 0));    fc_step = (float)nodes_per_chan / (float)Fc;    for(i = 0; i < num_phys_pins; i++)	{	    ipin = pin_num_ordering[i];	    iside = side_ordering[i];	    ioff = offset_ordering[i];	    /* Bi-directional treats each track separately, uni-directional works with pairs of tracks */	    for(j = 0; j < (Fc / group_size); j++)		{		    f_track = (i * step_size) + (j * fc_step);		    itrack = ((int)f_track) * group_size;		    /* Catch possible floating point round error */		    itrack = min(itrack, nodes_per_chan - group_size);		    /* Assign the group of tracks for the Fc pattern */		    for(k = 0; k < group_size; ++k)			{			    tracks_connected_to_pin[ipin][ioff][iside]				[group_size * j + k] = itrack + k;			}		}	}}static voidload_perturbed_switch_pattern(IN t_type_ptr type,			      INOUT int ****tracks_connected_to_pin,			      IN int num_phys_pins,			      IN int *pin_num_ordering,			      IN int *side_ordering,			      IN int *offset_ordering,			      IN int nodes_per_chan,			      IN int Fc,			      enum e_directionality directionality){    /* Loads the tracks_connected_to_pin array with an unevenly distributed     *     * set of switches across the channel.  This is done for inputs when        *     * Fc_input = Fc_output to avoid creating "pin domains" -- certain output   *     * pins being able to talk only to certain input pins because their switch  *     * patterns exactly line up.  Distribute Fc/2 + 1 switches over half the    *     * channel and Fc/2 - 1 switches over the other half to make the switch     *      * pattern different from the uniform one of the outputs.  Also, have half  *     * the pins put the "dense" part of their connections in the first half of  *     * the channel and the other half put the "dense" part in the second half,  *     * to make sure each track can connect to about the same number of ipins.   */    int i, j, ipin, iside, itrack, ihalf, iconn, ioff;    int Fc_dense, Fc_sparse, Fc_half[2];    float f_track, spacing_dense, spacing_sparse, spacing[2];    float step_size;    assert(directionality == BI_DIRECTIONAL);    step_size = (float)nodes_per_chan / (float)(Fc * num_phys_pins);    Fc_dense = (Fc / 2) + 1;    Fc_sparse = Fc - Fc_dense;	/* Works for even or odd Fc */    spacing_dense = (float)nodes_per_chan / (float)(2 * Fc_dense);    spacing_sparse = (float)nodes_per_chan / (float)(2 * Fc_sparse);    for(i = 0; i < num_phys_pins; i++)	{	    ipin = pin_num_ordering[i];	    iside = side_ordering[i];	    ioff = offset_ordering[i];	    /* Flip every pin to balance switch density */	    spacing[i % 2] = spacing_dense;	    Fc_half[i % 2] = Fc_dense;	    spacing[(i + 1) % 2] = spacing_sparse;	    Fc_half[(i + 1) % 2] = Fc_sparse;	    f_track = i * step_size;	/* Start point.  Staggered from pin to pin */	    iconn = 0;	    for(ihalf = 0; ihalf < 2; ihalf++)		{		/* For both dense and sparse halves. */		    for(j = 0; j < Fc_half[ihalf]; ++j)			{			    itrack = (int)f_track;			    /* Can occasionally get wraparound due to floating point rounding. 				   This is okay because the starting position > 0 when this occurs				   so connection is valid and fine */			    itrack = itrack % nodes_per_chan;			    tracks_connected_to_pin[ipin][ioff][iside][iconn]				= itrack;			    f_track += spacing[ihalf];			    iconn++;			}		}	}			/* End for all physical pins. */}static voidcheck_all_tracks_reach_pins(t_type_ptr type,			    int ****tracks_connected_to_pin,			    int nodes_per_chan,			    int Fc,			    enum e_pin_type ipin_or_opin){    /* Checks that all tracks can be reached by some pin.   */    int iconn, iside, itrack, ipin, ioff;    int *num_conns_to_track;	/* [0..nodes_per_chan-1] */	assert(nodes_per_chan > 0);        num_conns_to_track = (int *)my_calloc(nodes_per_chan, sizeof(int));    for(ipin = 0; ipin < type->num_pins; ipin++)	{	    for(ioff = 0; ioff < type->height; ioff++)		{		    for(iside = 0; iside < 4; iside++)			{			    if(tracks_connected_to_pin[ipin][ioff][iside][0]			       != OPEN)				{	/* Pin exists */				    for(iconn = 0; iconn < Fc; iconn++)					{					    itrack =						tracks_connected_to_pin[ipin]						[ioff][iside][iconn];					    num_conns_to_track[itrack]++;					}				}			}		}	}	for(itrack = 0; itrack < nodes_per_chan; itrack++)	{	    if(num_conns_to_track[itrack] <= 0)		{		    printf			("Warning (check_all_tracks_reach_pins):  track %d does not \n"			 "\tconnect to any FB ", itrack);		    if(ipin_or_opin == DRIVER)			printf("OPINs.\n");		    else			printf("IPINs.\n");		}	}    free(num_conns_to_track);}/* Allocates and loads the track to ipin lookup for each physical grid type. This * is the same information as the ipin_to_track map but accessed in a different way. */static struct s_ivec ***alloc_and_load_track_to_pin_lookup(IN int ****pin_to_track_map,				   IN int Fc,				   IN int height,				   IN int num_pins,				   IN int nodes_per_chan){    int ipin, iside, itrack, iconn, ioff, pin_counter;    struct s_ivec ***track_to_pin_lookup;    /* [0..nodes_per_chan-1][0..height][0..3].  For each track number it stores a vector       * for each of the four sides.  x-directed channels will use the TOP and        * BOTTOM vectors to figure out what clb input pins they connect to above       * and below them, respectively, while y-directed channels use the LEFT         * and RIGHT vectors.  Each vector contains an nelem field saying how many      * ipins it connects to.  The list[0..nelem-1] array then gives the pin         * numbers.                                                                */    /* Note that a clb pin that connects to a channel on its RIGHT means that  *     * that channel connects to a clb pin on its LEFT.  The convention used    *     * here is always in the perspective of the CLB                            */    if(num_pins < 1)	{	    return NULL;	}    /* Alloc and zero the the lookup table */    track_to_pin_lookup =	(struct s_ivec ***)alloc_matrix3(0, nodes_per_chan - 1, 0,					 height - 1, 0, 3,					 sizeof(struct s_ivec));    for(itrack = 0; itrack < nodes_per_chan; itrack++)	{	    for(ioff = 0; ioff < height; ioff++)		{		    for(iside = 0; iside < 4; iside++)			{			    track_to_pin_lookup[itrack][ioff][iside].nelem =				0;			    track_to_pin_lookup[itrack][ioff][iside].list =				NULL;			}		}	}    /* Counting pass.  */    for(ipin = 0; ipin < num_pins; ipin++)	{	    for(ioff = 0; ioff < height; ioff++)		{		    for(iside = 0; iside < 4; iside++)			{			    if(pin_to_track_map[ipin][ioff][iside][0] == OPEN)				continue;			    for(iconn = 0; iconn < Fc; iconn++)				{				    itrack =					pin_to_track_map[ipin][ioff][iside]					[iconn];				    track_to_pin_lookup[itrack][ioff][iside].					nelem++;				}			}		}	}    /* Allocate space.  */    for(itrack = 0; itrack < nodes_per_chan; itrack++)	{	    for(ioff = 0; ioff < height; ioff++)		{		    for(iside = 0; iside < 4; iside++)			{			    track_to_pin_lookup[itrack][ioff][iside].list = NULL;	/* Defensive code */			    if(track_to_pin_lookup[itrack][ioff][iside].			       nelem != 0)				{				    track_to_pin_lookup[itrack][ioff][iside].					list =					(int *)					my_malloc(track_to_pin_lookup[itrack]						  [ioff][iside].nelem *						  sizeof(int));				    track_to_pin_lookup[itrack][ioff][iside].					nelem = 0;				}			}		}	}    /* Loading pass. */    for(ipin = 0; ipin < num_pins; ipin++)	{	    for(ioff = 0; ioff < height; ioff++)		{		    for(iside = 0; iside < 4; iside++)			{			    if(pin_to_track_map[ipin][ioff][iside][0] == OPEN)				continue;			    for(iconn = 0; iconn < Fc; iconn++)				{				    itrack =					pin_to_track_map[ipin][ioff][iside]					[iconn];				    pin_counter =					track_to_pin_lookup[itrack][ioff]					[iside].nelem;				    track_to_pin_lookup[itrack][ioff][iside].					list[pin_counter] = ipin;				    track_to_pin_lookup[itrack][ioff][iside].					nelem++;				}			}		}	}    return track_to_pin_lookup;}/* A utility routine to dump the contents of the routing resource graph   * * (everything -- connectivity, occupancy, cost, etc.) into a file.  Used * * only for debugging.                                                    */voiddump_rr_graph(IN const char *file_name){    int inode;    FILE *fp;    fp = my_fopen(file_name, "w");    for(inode = 0; inode < num_rr_nodes; inode++)	{	    print_rr_node(fp, rr_node, inode);	    fprintf(fp, "\n");	}#if 0    fprintf(fp, "\n\n%d rr_indexed_data entries.\n\n", num_rr_indexed_data);    for(index = 0; index < num_rr_indexed_data; index++)	{	    print_rr_indexed_data(fp, index);	    fprintf(fp, "\n");	}#endif    fclose(fp);}/* Prints all the data about node inode to file fp.                    */static voidprint_rr_node(FILE * fp,	      t_rr_node * rr_node,	      int inode){    static const char *name_type[] = {	"SOURCE", "SINK", "IPIN", "OPIN", "CHANX", "CHANY"    };    static const char *direction_name[] = {	"OPEN", "INC_DIRECTION", "DEC_DIRECTION", "BI_DIRECTION"    };    static const char *drivers_name[] = {	"OPEN", "MULTI_BUFFER", "MULTI_MUXED", "MULTI_MERGED", "SINGLE"    };    t_rr_type rr_type;    int iconn;    rr_type = rr_node[inode].type;    /* Make sure we don't overrun const arrays */    assert(rr_type < (sizeof(name_type) / sizeof(char *)));    assert((rr_node[inode].direction + 1) <	   (sizeof(direction_name) / sizeof(char *)));    assert((rr_node[inode].drivers + 1) <	   (sizeof(drivers_name) / sizeof(char *)));    fprintf(fp, "Node: %d %s ", inode, name_type[rr_type]);    if((rr_node[inode].xlow == rr_node[inode].xhigh) &&       (rr_node[inode].ylow == rr_node[inode].yhigh))	{	    fprintf(fp, "(%d, %d) ", rr_node[inode].xlow,		    rr_node[inode].ylow);	}    else	{	    fprintf(fp, "(%d, %d) to (%d, %d) ", rr_node[inode].xlow,		    rr_node[inode].ylow, rr_node[inode].xhigh,		    rr_node[inode].yhigh);	}    fprintf(fp, "Ptc_num: %d ", rr_node[inode].ptc_num);    fprintf(fp, "Direction: %s ",	    direction_name[rr_node[inode].direction + 1]);    fprintf(fp, "Drivers: %s ", drivers_name[rr_node[inode].drivers + 1]);    fprintf(fp, "\n");    fprintf(fp, "%d edge(s):", rr_node[inode].num_edges);    for(iconn = 0; iconn < rr_node[inode].num_edges; iconn++)	fprintf(fp, " %d", rr_node[inode].edges[iconn]);    fprintf(fp, "\n");    fprintf(fp, "Switch types:");    for(iconn = 0; iconn < rr_node[inode].num_edges; iconn++)	fprintf(fp, " %d", rr_node[inode].switches[iconn]);    fprintf(fp, "\n");    fprintf(fp, "Occ: %d  Capacity: %d\n", rr_node[inode].occ,	    rr_node[inode].capacity);    fprintf(fp, "R: %g  C: %g\n", rr_node[inode].R, rr_node[inode].C);    fprintf(fp, "Cost_index: %d\n", rr_node[inode].cost_index);}/* Prints all the rr_indexed_data of index to file fp.   */voidprint_rr_indexed_data(FILE * fp,		      int index){    fprintf(fp, "Index: %d\n", index);    fprintf(fp, "ortho_cost_index: %d  ",	    rr_indexed_data[index].ortho_cost_index);    fprintf(fp, "base_cost: %g  ", rr_indexed_data[index].saved_base_cost);    fprintf(fp, "saved_base_cost: %g\n",	    rr_indexed_data[index].save

⌨️ 快捷键说明

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