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

📄 setupvpr.c

📁 用于学术研究的FPGA布局布线软件VPR
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <assert.h>#include <string.h>#include "util.h"#include "vpr_types.h"#include "check_netlist.h"#include "OptionTokens.h"#include "ReadOptions.h"#include "read_netlist.h"#include "globals.h"#include "xml_arch.h"#include "SetupVPR.h"static void SetupOperation(IN t_options Options,			   OUT enum e_operation *Operation);static void SetupPlacerOpts(IN t_options Options,			    IN boolean TimingEnabled,			    OUT struct s_placer_opts *PlacerOpts);static void SetupAnnealSched(IN t_options Options,			     OUT struct s_annealing_sched *AnnealSched);static void SetupRouterOpts(IN t_options Options,			    IN boolean TimingEnabled,			    OUT struct s_router_opts *RouterOpts);static void SetupGlobalRoutingArch(OUT struct s_det_routing_arch *RoutingArch,				   OUT t_segment_inf ** Segments);static void SetupRoutingArch(IN t_arch Arch,			     OUT struct s_det_routing_arch *RoutingArch);static void SetupTiming(IN t_options Options,			IN t_arch Arch,			IN boolean TimingEnabled,			IN enum e_operation Operation,			IN struct s_placer_opts PlacerOpts,			IN struct s_router_opts RouterOpts,			OUT t_timing_inf * Timing);static void load_subblock_info_to_type(INOUT t_subblock_data * subblocks,				       INOUT t_type_ptr type);static void InitArch(IN t_arch Arch);static void alloc_and_load_grid(INOUT int *num_instances_type);	/* [0..num_types-1] */static void freeGrid();static void CheckGrid(void);static t_type_ptr find_type_col(IN int x);static void SetupSwitches(IN t_arch Arch,			  INOUT struct s_det_routing_arch *RoutingArch,			  IN struct s_switch_inf *ArchSwitches,			  IN int NumArchSwitches);/* Sets VPR parameters and defaults. Does not do any error checking * as this should have been done by the various input checkers */voidSetupVPR(IN t_options Options,	 IN boolean TimingEnabled,	 OUT t_arch * Arch,	 OUT enum e_operation *Operation,	 OUT struct s_placer_opts *PlacerOpts,	 OUT struct s_annealing_sched *AnnealSched,	 OUT struct s_router_opts *RouterOpts,	 OUT struct s_det_routing_arch *RoutingArch,	 OUT t_segment_inf ** Segments,	 OUT t_timing_inf * Timing,	 OUT t_subblock_data * Subblocks,	 OUT boolean * ShowGraphics,	 OUT int *GraphPause){    SetupOperation(Options, Operation);    SetupPlacerOpts(Options, TimingEnabled, PlacerOpts);    SetupAnnealSched(Options, AnnealSched);    SetupRouterOpts(Options, TimingEnabled, RouterOpts);    XmlReadArch(Options.ArchFile, TimingEnabled, Arch,		&type_descriptors, &num_types);    *Segments = Arch->Segments;    RoutingArch->num_segment = Arch->num_segments;    SetupSwitches(*Arch, RoutingArch, Arch->Switches, Arch->num_switches);    SetupRoutingArch(*Arch, RoutingArch);    SetupTiming(Options, *Arch, TimingEnabled, *Operation,		*PlacerOpts, *RouterOpts, Timing);    /* init global variables */    OutFilePrefix = Options.OutFilePrefix;    grid_logic_tile_area = Arch->grid_logic_tile_area;    ipin_mux_trans_size = Arch->ipin_mux_trans_size;    /* Set seed for pseudo-random placement, default seed to 1 */    PlacerOpts->seed = 1;    if(Options.Count[OT_SEED])	{	    PlacerOpts->seed = Options.Seed;	}    my_srandom(PlacerOpts->seed);    *GraphPause = 1;		/* DEFAULT */    if(Options.Count[OT_AUTO])	{	    *GraphPause = Options.GraphPause;	}#ifdef NO_GRAPHICS    *ShowGraphics = FALSE;	/* DEFAULT */#else /* NO_GRAPHICS */    *ShowGraphics = TRUE;	/* DEFAULT */    if(Options.Count[OT_NODISP])	{	    *ShowGraphics = FALSE;	}#endif /* NO_GRAPHICS */#ifdef CREATE_ECHO_FILES    EchoArch("arch.echo", type_descriptors, num_types);#endif    if(Options.NetFile)	{	    read_netlist(Options.NetFile, num_types, type_descriptors,			 IO_TYPE, 0, 1, Subblocks, &num_blocks, &block,			 &num_nets, &net);	    /* This is done so that all blocks have subblocks and can be treated the same */	    load_subblock_info_to_type(Subblocks, IO_TYPE);	    check_netlist(Subblocks);	}    InitArch(*Arch);}/* This is a modification of the init_arch function to use Arch as param. * Sets globals: nx, ny * Allocs globals: chan_width_x, chan_width_y, grid * Depends on num_clbs, pins_per_clb */static voidInitArch(IN t_arch Arch){    int *num_instances_type, *num_blocks_type;    int i;    int current, high, low;    boolean fit;    current = nint(sqrt(num_blocks));	/* current is the value of the smaller side of the FPGA */    low = 1;    high = -1;    num_instances_type = my_calloc(num_types, sizeof(int));    num_blocks_type = my_calloc(num_types, sizeof(int));    for(i = 0; i < num_blocks; i++)	{	    num_blocks_type[block[i].type->index]++;	}    if(Arch.clb_grid.IsAuto)	{	    /* Auto-size FPGA, perform a binary search */	    while(high == -1 || low < high)		{		    /* Generate grid */		    if(Arch.clb_grid.Aspect >= 1.0)			{			    ny = current;			    nx = nint(current * Arch.clb_grid.Aspect);			}		    else			{			    nx = current;			    ny = nint(current / Arch.clb_grid.Aspect);			}#if DEBUG		    printf("Auto-sizing FPGA, try x = %d y = %d\n", nx, ny);#endif		    alloc_and_load_grid(num_instances_type);		    freeGrid();		    /* Test if netlist fits in grid */		    fit = TRUE;		    for(i = 0; i < num_types; i++)			{			    if(num_blocks_type[i] > num_instances_type[i])				{				    fit = FALSE;				    break;				}			}		    /* get next value */		    if(!fit)			{			    /* increase size of max */			    if(high == -1)				{				    current = current * 2;				    if(current > MAX_SHORT)					{					    printf(ERRTAG						   "FPGA required is too large for current architecture settings\n");					    exit(1);					}				}			    else				{				    if(low == current)					current++;				    low = current;				    current = low + ((high - low) / 2);				}			}		    else			{			    high = current;			    current = low + ((high - low) / 2);			}		}	    /* Generate grid */	    if(Arch.clb_grid.Aspect >= 1.0)		{		    ny = current;		    nx = nint(current * Arch.clb_grid.Aspect);		}	    else		{		    nx = current;		    ny = nint(current / Arch.clb_grid.Aspect);		}	    alloc_and_load_grid(num_instances_type);	    printf("FPGA auto-sized to, x = %d y = %d\n", nx, ny);	}    else	{	    nx = Arch.clb_grid.W;	    ny = Arch.clb_grid.H;	    alloc_and_load_grid(num_instances_type);	}    /* Test if netlist fits in grid */    fit = TRUE;    for(i = 0; i < num_types; i++)	{	    if(num_blocks_type[i] > num_instances_type[i])		{		    fit = FALSE;		    break;		}	}    if(!fit)	{	    printf(ERRTAG "Not enough physical locations for type %s, "		   "number of blocks is %d but number of locations is %d\n",		   num_blocks_type[i], num_instances_type[i]);	    exit(1);	}	printf("\nResource Usage:\n");	for(i = 0; i < num_types; i++)	{		printf("Netlist      %d\tblocks of type %s\n", 			num_blocks_type[i], type_descriptors[i].name);		printf("Architecture %d\tblocks of type %s\n", 			num_instances_type[i], type_descriptors[i].name);	}	printf("\n");    chan_width_x = (int *)my_malloc((ny + 1) * sizeof(int));    chan_width_y = (int *)my_malloc((nx + 1) * sizeof(int));    free(num_blocks_type);    free(num_instances_type);}/* Create and fill FPGA architecture grid.         */static voidalloc_and_load_grid(INOUT int *num_instances_type){    int i, j;    t_type_ptr type;#ifdef SHOW_ARCH    FILE *dump;#endif    /* If both nx and ny are 1, we only have one valid location for a clb. *     * That's a major problem, as won't be able to move the clb and the    *     * find_to routine that tries moves in the placer will go into an      *     * infinite loop trying to move it.  Exit with an error message        *     * instead.                                                            */    if((nx == 1) && (ny == 1) && (num_blocks > 0))	{	    printf("Error:\n");	    printf		("Sorry, can't place a circuit with only one valid location\n");	    printf("for a logic block (clb).\n");	    printf("Try me with a more realistic circuit!\n");	    exit(1);	}    /* To remove this limitation, change ylow etc. in t_rr_node to        *     * * be ints instead.  Used shorts to save memory.                      */    if((nx > 32766) || (ny > 32766))	{	    printf("Error:  nx and ny must be less than 32767, since the \n");	    printf("router uses shorts (16-bit) to store coordinates.\n");	    printf("nx: %d.  ny: %d.\n", nx, ny);	    exit(1);	}    assert(nx >= 1 && ny >= 1);    grid = (struct s_grid_tile **)alloc_matrix(0, (nx + 1),					       0, (ny + 1),					       sizeof(struct s_grid_tile));    /* Clear the full grid to have no type (NULL), no capacity, etc */    for(i = 0; i <= (nx + 1); ++i)	{	    for(j = 0; j <= (ny + 1); ++j)		{		    memset(&grid[i][j], 0, (sizeof(struct s_grid_tile)));		}	}    for(i = 0; i < num_types; i++)	{	    num_instances_type[i] = 0;	}    /* Nothing goes in the corners. */    grid[0][0].type = grid[nx + 1][0].type = EMPTY_TYPE;    grid[0][ny + 1].type = grid[nx + 1][ny + 1].type = EMPTY_TYPE;    num_instances_type[EMPTY_TYPE->index] = 4;    for(i = 1; i <= nx; i++)	{	    grid[i][0].blocks =		(int *)my_malloc(sizeof(int) * IO_TYPE->capacity);	    grid[i][0].type = IO_TYPE;	    grid[i][ny + 1].blocks =		(int *)my_malloc(sizeof(int) * IO_TYPE->capacity);	    grid[i][ny + 1].type = IO_TYPE;	    for(j = 0; j < IO_TYPE->capacity; j++)		{		    grid[i][0].blocks[j] = EMPTY;		    grid[i][ny + 1].blocks[j] = EMPTY;		}	}    for(i = 1; i <= ny; i++)	{	    grid[0][i].blocks =		(int *)my_malloc(sizeof(int) * IO_TYPE->capacity);	    grid[0][i].type = IO_TYPE;	    grid[nx + 1][i].blocks =		(int *)my_malloc(sizeof(int) * IO_TYPE->capacity);	    grid[nx + 1][i].type = IO_TYPE;	    for(j = 0; j < IO_TYPE->capacity; j++)		{		    grid[0][i].blocks[j] = EMPTY;		    grid[nx + 1][i].blocks[j] = EMPTY;		}	}    num_instances_type[IO_TYPE->index] = 2 * IO_TYPE->capacity * (nx + ny);    for(i = 1; i <= nx; i++)	{			/* Interior (LUT) cells */	    type = find_type_col(i);	    for(j = 1; j <= ny; j++)		{		    grid[i][j].type = type;		    grid[i][j].offset = (j - 1) % type->height;		    if(j + grid[i][j].type->height - 1 - grid[i][j].offset >		       ny)			{			    grid[i][j].type = EMPTY_TYPE;			    grid[i][j].offset = 0;			}		    if(type->capacity > 1)			{			    printf(ERRTAG				   "In FillArch() expected core blocks to have capacity <= 1 but "				   "(%d, %d) has type '%s' and capacity %d\n",				   i, j, grid[i][j].type->name,				   grid[i][j].type->capacity);			    exit(1);			}		    grid[i][j].blocks = (int *)my_malloc(sizeof(int));		    grid[i][j].blocks[0] = EMPTY;		    if(grid[i][j].offset == 0)			{			    num_instances_type[grid[i][j].type->index]++;			}		}	}    CheckGrid();#ifdef SHOW_ARCH    /* DEBUG code */    dump = my_fopen("grid_type_dump.txt", "w");    for(j = (ny + 1); j >= 0; --j)	{	    for(i = 0; i <= (nx + 1); ++i)		{		    fprintf(dump, "%c", grid[i][j].type->name[1]);		}	    fprintf(dump, "\n");	}    fclose(dump);#endif}static voidfreeGrid(){    int i, j;    for(i = 0; i <= (nx + 1); ++i)	{	    for(j = 0; j <= (ny + 1); ++j)		{		    free(grid[i][j].blocks);		}	}    free_matrix(grid, 0, nx + 1, 0, sizeof(struct s_grid_tile));}static voidCheckGrid(){    int i, j;    /* Check grid is valid */    for(i = 0; i <= (nx + 1); ++i)	{	    for(j = 0; j <= (ny + 1); ++j)		{		    if(NULL == grid[i][j].type)			{			    printf(ERRTAG "grid[%d][%d] has no type.\n", i,				   j);			    exit(1);			}		    if(grid[i][j].usage != 0)			{			    printf(ERRTAG				   "grid[%d][%d] has non-zero usage (%d) "				   "before netlist load.\n", i, j,				   grid[i][j].usage);			    exit(1);			}		    if((grid[i][j].offset < 0) ||		       (grid[i][j].offset >= grid[i][j].type->height))			{			    printf(ERRTAG				   "grid[%d][%d] has invalid offset (%d)\n",				   i, j, grid[i][j].offset);			    exit(1);			}		    if((NULL == grid[i][j].blocks) &&		       (grid[i][j].type->capacity > 0))			{			    printf(ERRTAG				   "grid[%d][%d] has no block list allocated.\n",				   i, j);			    exit(1);			}		}	}}static t_type_ptrfind_type_col(IN int x){    int i, j;    int start, repeat;    float rel;    boolean match;    int priority, num_loc;    t_type_ptr column_type;    priority = FILL_TYPE->grid_loc_def[0].priority;    column_type = FILL_TYPE;    for(i = 0; i < num_types; i++)	{	    if(&type_descriptors[i] == IO_TYPE ||	       &type_descriptors[i] == EMPTY_TYPE ||	       &type_descriptors[i] == FILL_TYPE)		continue;	    num_loc = type_descriptors[i].num_grid_loc_def;	    for(j = 0; j < num_loc; j++)		{		    if(priority <		       type_descriptors[i].grid_loc_def[j].priority)			{			    match = FALSE;			    if(type_descriptors[i].grid_loc_def[j].			       grid_loc_type == COL_REPEAT)				{				    start =					type_descriptors[i].grid_loc_def[j].					start_col;				    repeat =					type_descriptors[i].grid_loc_def[j].					repeat;				    if(start < 0)					{					    start += (nx + 1);					}				    if(x == start)					{					    match = TRUE;					}				    else if(repeat > 0 && x > start					    && start > 0)					{					    if((x - start) % repeat == 0)						{						    match = TRUE;						}					}				}			    else if(type_descriptors[i].grid_loc_def[j].				    grid_loc_type == COL_REL)				{				    rel =					type_descriptors[i].grid_loc_def[j].					col_rel;				    if(nint(rel * nx) == x)					{					    match = TRUE;					}				}			    if(match)				{				    priority =					type_descriptors[i].grid_loc_def[j].					priority;				    column_type = &type_descriptors[i];				}

⌨️ 快捷键说明

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