📄 setupvpr.c
字号:
#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 + -