blob: e6c15cc1e8a94d848d07e28d0de970d9ded82746 [file] [log] [blame]
#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;
}