| #include <assert.h> | |
| #include <string.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 ********************************/ | |
| /** | |
| * print tabs given number of tabs to file | |
| */ | |
| void | |
| print_tabs(FILE * fpout, int num_tab) { | |
| int i; | |
| for(i = 0; i < num_tab; i++) { | |
| fprintf(fpout, "\t"); | |
| } | |
| } | |
| /* Points the grid structure back to the blocks list */ | |
| void | |
| sync_grid_to_blocks(INP int num_blocks, | |
| INP const struct s_block block_list[], | |
| INP int nx, | |
| INP int ny, | |
| INOUTP 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); | |
| } | |
| } | |
| } | |
| boolean | |
| is_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); | |
| } | |
| void | |
| get_class_range_for_block(INP int iblk, | |
| OUTP int *class_low, | |
| OUTP 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; | |
| } |