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

📄 vpr_utils.c

📁 用于学术研究的FPGA布局布线软件VPR
💻 C
字号:
#include <assert.h>#include "util.h"#include "vpr_types.h"#include "globals.h"#include "vpr_utils.h"/* This module contains subroutines that are used in several unrelated parts * * of VPR.  They are VPR-specific utility routines.                          *//******************** Subroutine definitions ********************************//* Points the grid structure back to the blocks list */voidsync_grid_to_blocks(IN int num_blocks,		    IN const struct s_block block_list[],		    IN int nx,		    IN int ny,		    INOUT struct s_grid_tile **grid){    int i, j, k;    /* Reset usage and allocate blocks list if needed */    for(j = 0; j <= (ny + 1); ++j)	{	    for(i = 0; i <= (nx + 1); ++i)		{		    grid[i][j].usage = 0;		    if(grid[i][j].type)			{			    /* If already allocated, leave it since size doesn't change */			    if(NULL == grid[i][j].blocks)				{				    grid[i][j].blocks =					(int *)my_malloc(sizeof(int) *							 grid[i][j].type->							 capacity);				    /* Set them as unconnected */				    for(k = 0; k < grid[i][j].type->capacity;					++k)					{					    grid[i][j].blocks[k] = OPEN;					}				}			}		}	}    /* Go through each block */    for(i = 0; i < num_blocks; ++i)	{	    /* Check range of block coords */	    if(block[i].x < 0 || block[i].x > (nx + 1) ||	       block[i].y < 0	       || (block[i].y + block[i].type->height - 1) > (ny + 1)	       || block[i].z < 0 || block[i].z > (block[i].type->capacity))		{		    printf(ERRTAG			   "Block %d is at invalid location (%d, %d, %d)\n",			   i, block[i].x, block[i].y, block[i].z);		    exit(1);		}	    /* Check types match */	    if(block[i].type != grid[block[i].x][block[i].y].type)		{		    printf(ERRTAG "A block is in a grid location "			   "(%d x %d) with a conflicting type.\n", block[i].x,			   block[i].y);		    exit(1);		}	    /* Check already in use */	    if(OPEN != grid[block[i].x][block[i].y].blocks[block[i].z])		{		    printf(ERRTAG			   "Location (%d, %d, %d) is used more than once\n",			   block[i].x, block[i].y, block[i].z);		    exit(1);		}	    if(grid[block[i].x][block[i].y].offset != 0)		{		    printf(ERRTAG			   "Large block not aligned in placment for block %d at (%d, %d, %d)",			   i, block[i].x, block[i].y, block[i].z);		    exit(1);		}	    /* Set the block */	    for(j = 0; j < block[i].type->height; j++)		{		    grid[block[i].x][block[i].y + j].blocks[block[i].z] = i;		    grid[block[i].x][block[i].y + j].usage++;		    assert(grid[block[i].x][block[i].y + j].offset == j);		}	}}/* This function updates the nets list to point back to blocks list */voidsync_nets_to_blocks(IN int num_blocks,		    IN const struct s_block block_list[],		    IN int num_nets,		    INOUT struct s_net net_list[]){    int i, j, k, l;    t_type_ptr cur_type;    /* Count the number of sinks for each net */    for(i = 0; i < num_nets; ++i)	{	    for(j = 0; j < num_blocks; ++j)		{		    cur_type = block_list[j].type;		    for(k = 0; k < cur_type->num_pins; ++k)			{			    if(block_list[j].nets[k] == i)				{				    if(RECEIVER ==				       cur_type->class_inf[cur_type->							   pin_class[k]].type)					{					    ++net_list[i].num_sinks;					}				}			}		}	}    /* Alloc and load block lists of nets */    for(i = 0; i < num_nets; ++i)	{	    /* The list should be num_sinks + 1 driver. Re-alloc if already allocated. */	    if(net_list[i].node_block)		{		    free(net_list[i].node_block);		}	    net_list[i].node_block =		(int *)my_malloc(sizeof(int) * (net_list[i].num_sinks + 1));	    if(net_list[i].node_block_pin)		{		    free(net_list[i].node_block_pin);		}	    net_list[i].node_block_pin =		(int *)my_malloc(sizeof(int) * (net_list[i].num_sinks + 1));	    l = 1;		/* First sink goes at position 1, since 0 is for driver */	    for(j = 0; j < num_blocks; ++j)		{		    cur_type = block_list[j].type;		    for(k = 0; k < cur_type->num_pins; ++k)			{			    if(block_list[j].nets[k] == i)				{				    if(RECEIVER ==				       cur_type->class_inf[cur_type->							   pin_class[k]].type)					{					    net_list[i].node_block[l] = j;					    net_list[i].node_block_pin[l] = k;					    ++l;					}				    else					{					    assert(DRIVER ==						   cur_type->						   class_inf[cur_type->							     pin_class[k]].						   type);					    net_list[i].node_block[0] = j;					    net_list[i].node_block_pin[0] = k;					}				}			}		}	}}booleanis_opin(int ipin,	t_type_ptr type){/* Returns TRUE if this clb pin is an output, FALSE otherwise. */    int iclass;    iclass = type->pin_class[ipin];    if(type->class_inf[iclass].type == DRIVER)	return (TRUE);    else	return (FALSE);}voidget_class_range_for_block(IN int iblk,			  OUT int *class_low,			  OUT int *class_high){/* Assumes that the placement has been done so each block has a set of pins allocated to it */    t_type_ptr type;    type = block[iblk].type;    assert(type->num_class % type->capacity == 0);    *class_low = block[iblk].z * (type->num_class / type->capacity);    *class_high =	(block[iblk].z + 1) * (type->num_class / type->capacity) - 1;}voidload_one_fb_fanout_count(t_subblock * subblock_inf,			 int num_subblocks,			 int *num_uses_of_fb_ipin,			 int **num_uses_of_sblk_opin,			 int iblk){/* Loads the fanout counts for one block (iblk).  */    t_type_ptr type = block[iblk].type;    int isub, ipin, conn_pin, opin;    int internal_sub, internal_pin;	/* Reset ipin counts */	for(ipin = 0; ipin < type->num_pins; ipin++)	{	    num_uses_of_fb_ipin[ipin] = 0;	}    /* First pass, reset fanout counts */    for(isub = 0; isub < num_subblocks; isub++)	{	    for(opin = 0; opin < type->max_subblock_outputs; opin++)		{		    num_uses_of_sblk_opin[isub][opin] = 0;		}	}    for(isub = 0; isub < num_subblocks; isub++)	{	    /* Is the subblock output connected to a FB opin that actually goes *	     * somewhere?  Necessary to check that the FB opin connects to      *	     * something because some logic blocks result in netlists where      *	     * subblock outputs being automatically hooked to a FB opin under   *	     * all conditions.                                                   */	    for(opin = 0; opin < type->max_subblock_outputs; opin++)		{		    conn_pin = subblock_inf[isub].outputs[opin];		    if(conn_pin != OPEN)			{			    if(block[iblk].nets[conn_pin] != OPEN)				{	/* FB output is used */				    num_uses_of_sblk_opin[isub][opin]++;				}			}		}	    for(ipin = 0; ipin < type->max_subblock_inputs; ipin++)		{		    conn_pin = subblock_inf[isub].inputs[ipin];		    if(conn_pin != OPEN)			{			    if(conn_pin < type->num_pins)				{	/* Driven by FB ipin */				    num_uses_of_fb_ipin[conn_pin]++;				}			    else				{	/* Driven by sblk output in same fb */				    internal_sub =					(conn_pin -					 type->num_pins) /					type->max_subblock_outputs;				    internal_pin =					(conn_pin -					 type->num_pins) %					type->max_subblock_outputs;				    num_uses_of_sblk_opin[internal_sub]					[internal_pin]++;				}			}		}		/* End for each sblk ipin */	    conn_pin = subblock_inf[isub].clock;	/* Now do clock pin */	    if(conn_pin != OPEN)		{		    if(conn_pin < type->num_pins)			{	/* Driven by FB ipin */			    num_uses_of_fb_ipin[conn_pin]++;			}		    else			{	/* Driven by sblk output in same clb */			    internal_sub =				(conn_pin -				 type->num_pins) / type->max_subblock_outputs;			    internal_pin =				(conn_pin -				 type->num_pins) % type->max_subblock_outputs;			    num_uses_of_sblk_opin[internal_sub]				[internal_pin]++;			}		}	}			/* End for each subblock */}

⌨️ 快捷键说明

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