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

📄 setupvpr.c

📁 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 */
void
SetupVPR(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 void
InitArch(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 void
alloc_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 void
freeGrid()
{
    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 void
CheckGrid()
{
    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_ptr
find_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 + -