OpenFPGA/vpr7_x2p/vpr/SRC/base/read_place.c

290 lines
7.6 KiB
C
Raw Normal View History

2018-07-26 12:28:21 -05:00
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "hash.h"
#include "read_place.h"
#include "read_xml_arch_file.h"
#include "ReadLine.h"
/* extern, should be a header */
char **ReadLineTokens(INOUTP FILE * InFile, INOUTP int *LineNum);
void read_place(INP const char *place_file, INP const char *arch_file,
INP const char *net_file, INP int L_nx, INP int L_ny,
INP int L_num_blocks, INOUTP struct s_block block_list[]) {
FILE *infile;
char **tokens;
int line;
int i;
int error;
struct s_block *cur_blk;
infile = fopen(place_file, "r");
/* Check filenames in first line match */
tokens = ReadLineTokens(infile, &line);
error = 0;
if (NULL == tokens) {
error = 1;
}
for (i = 0; i < 6; ++i) {
if (!error) {
if (NULL == tokens[i]) {
error = 1;
}
}
}
if (!error) {
if ((0 != strcmp(tokens[0], "Netlist"))
|| (0 != strcmp(tokens[1], "file:"))
|| (0 != strcmp(tokens[3], "Architecture"))
|| (0 != strcmp(tokens[4], "file:"))) {
error = 1;
};
}
if (error) {
vpr_printf(TIO_MESSAGE_ERROR, "'%s' - Bad filename specification line in placement file.\n", place_file);
exit(1);
}
if (0 != strcmp(tokens[2], arch_file)) {
vpr_printf(TIO_MESSAGE_ERROR, "'%s' - Architecture file that generated placement (%s) does not match current architecture file (%s).\n",
place_file, tokens[2], arch_file);
exit(1);
}
if (0 != strcmp(tokens[5], net_file)) {
vpr_printf(TIO_MESSAGE_ERROR, "'%s' - Netlist file that generated placement (%s) does not match current netlist file (%s).\n",
place_file, tokens[5], net_file);
exit(1);
}
free(*tokens);
free(tokens);
/* Check array size in second line matches */
tokens = ReadLineTokens(infile, &line);
error = 0;
if (NULL == tokens) {
error = 1;
}
for (i = 0; i < 7; ++i) {
if (!error) {
if (NULL == tokens[i]) {
error = 1;
}
}
}
if (!error) {
if ((0 != strcmp(tokens[0], "Array"))
|| (0 != strcmp(tokens[1], "size:"))
|| (0 != strcmp(tokens[3], "x"))
|| (0 != strcmp(tokens[5], "logic"))
|| (0 != strcmp(tokens[6], "blocks"))) {
error = 1;
};
}
if (error) {
vpr_printf(TIO_MESSAGE_ERROR, "'%s' - Bad FPGA size specification line in placement file.\n",
place_file);
exit(1);
}
if ((my_atoi(tokens[2]) != L_nx) || (my_atoi(tokens[4]) != L_ny)) {
vpr_printf(TIO_MESSAGE_ERROR, "'%s' - Current FPGA size (%d x %d) is different from size when placement generated (%d x %d).\n",
place_file, L_nx, L_ny, my_atoi(tokens[2]), my_atoi(tokens[4]));
exit(1);
}
free(*tokens);
free(tokens);
tokens = ReadLineTokens(infile, &line);
while (tokens) {
/* Linear search to match pad to netlist */
cur_blk = NULL;
for (i = 0; i < L_num_blocks; ++i) {
if (0 == strcmp(block_list[i].name, tokens[0])) {
cur_blk = (block_list + i);
break;
}
}
/* Error if invalid block */
if (NULL == cur_blk) {
vpr_printf(TIO_MESSAGE_ERROR, "'%s':%d - Block in placement file does not exist in netlist.\n",
place_file, line);
exit(1);
}
/* Set pad coords */
cur_blk->x = my_atoi(tokens[1]);
cur_blk->y = my_atoi(tokens[2]);
cur_blk->z = my_atoi(tokens[3]);
/* Get next line */
assert(*tokens);
free(*tokens);
free(tokens);
tokens = ReadLineTokens(infile, &line);
}
fclose(infile);
}
void read_user_pad_loc(char *pad_loc_file) {
/* Reads in the locations of the IO pads from a file. */
struct s_hash **hash_table, *h_ptr;
int iblk, i, j, xtmp, ytmp, bnum, k;
FILE *fp;
char buf[BUFSIZE], bname[BUFSIZE], *ptr;
vpr_printf(TIO_MESSAGE_INFO, "\n");
vpr_printf(TIO_MESSAGE_INFO, "Reading locations of IO pads from '%s'.\n", pad_loc_file);
file_line_number = 0;
fp = fopen(pad_loc_file, "r");
hash_table = alloc_hash_table();
for (iblk = 0; iblk < num_blocks; iblk++) {
if (block[iblk].type == IO_TYPE) {
h_ptr = insert_in_hash_table(hash_table, block[iblk].name, iblk);
block[iblk].x = OPEN; /* Mark as not seen yet. */
}
}
for (i = 0; i <= nx + 1; i++) {
for (j = 0; j <= ny + 1; j++) {
if (grid[i][j].type == IO_TYPE) {
for (k = 0; k < IO_TYPE->capacity; k++)
grid[i][j].blocks[k] = OPEN; /* Flag for err. check */
}
}
}
ptr = my_fgets(buf, BUFSIZE, fp);
while (ptr != NULL) {
ptr = my_strtok(buf, TOKENS, fp, buf);
if (ptr == NULL) {
ptr = my_fgets(buf, BUFSIZE, fp);
continue; /* Skip blank or comment lines. */
}
strcpy(bname, ptr);
ptr = my_strtok(NULL, TOKENS, fp, buf);
if (ptr == NULL) {
vpr_printf(TIO_MESSAGE_ERROR, "[Line %d] Incomplete.\n", file_line_number);
exit(1);
}
sscanf(ptr, "%d", &xtmp);
ptr = my_strtok(NULL, TOKENS, fp, buf);
if (ptr == NULL) {
vpr_printf(TIO_MESSAGE_ERROR, "[Line %d] Incomplete.\n", file_line_number);
exit(1);
}
sscanf(ptr, "%d", &ytmp);
ptr = my_strtok(NULL, TOKENS, fp, buf);
if (ptr == NULL) {
vpr_printf(TIO_MESSAGE_ERROR, "[Line %d] Incomplete.\n", file_line_number);
exit(1);
}
sscanf(ptr, "%d", &k);
ptr = my_strtok(NULL, TOKENS, fp, buf);
if (ptr != NULL) {
vpr_printf(TIO_MESSAGE_ERROR, "[Line %d] Extra characters at end of line.\n",
file_line_number);
exit(1);
}
h_ptr = get_hash_entry(hash_table, bname);
if (h_ptr == NULL) {
vpr_printf(TIO_MESSAGE_WARNING, "[Line %d] Block %s invalid, no such IO pad.\n",
file_line_number, bname);
ptr = my_fgets(buf, BUFSIZE, fp);
continue;
}
bnum = h_ptr->index;
i = xtmp;
j = ytmp;
if (block[bnum].x != OPEN) {
vpr_printf(TIO_MESSAGE_ERROR, "[Line %d] Block %s is listed twice in pad file.\n",
file_line_number, bname);
exit(1);
}
if (i < 0 || i > nx + 1 || j < 0 || j > ny + 1) {
vpr_printf(TIO_MESSAGE_ERROR, "Block #%d (%s) location, (%d,%d) is out of range.\n",
bnum, bname, i, j);
exit(1);
}
block[bnum].x = i; /* Will be reloaded by initial_placement anyway. */
block[bnum].y = j; /* I need to set .x only as a done flag. */
block[bnum].isFixed = TRUE;
if (grid[i][j].type != IO_TYPE) {
vpr_printf(TIO_MESSAGE_ERROR, "Attempt to place IO block %s at illegal location (%d, %d).\n",
bname, i, j);
exit(1);
}
if (k >= IO_TYPE->capacity || k < 0) {
vpr_printf(TIO_MESSAGE_ERROR, "[Line %d] Block %s subblock number (%d) is out of range.\n",
file_line_number, bname, k);
exit(1);
}
grid[i][j].blocks[k] = bnum;
grid[i][j].usage++;
ptr = my_fgets(buf, BUFSIZE, fp);
}
for (iblk = 0; iblk < num_blocks; iblk++) {
if (block[iblk].type == IO_TYPE && block[iblk].x == OPEN) {
vpr_printf(TIO_MESSAGE_ERROR, "IO block %s location was not specified in the pad file.\n",
block[iblk].name);
exit(1);
}
}
fclose(fp);
free_hash_table(hash_table);
vpr_printf(TIO_MESSAGE_INFO, "Successfully read %s.\n", pad_loc_file);
vpr_printf(TIO_MESSAGE_INFO, "\n");
}
void print_place(char *place_file, char *net_file, char *arch_file) {
/* Prints out the placement of the circuit. The architecture and *
* netlist files used to generate this placement are recorded in the *
* file to avoid loading a placement with the wrong support files *
* later. */
FILE *fp;
int i;
fp = fopen(place_file, "w");
fprintf(fp, "Netlist file: %s Architecture file: %s\n", net_file,
arch_file);
fprintf(fp, "Array size: %d x %d logic blocks\n\n", nx, ny);
fprintf(fp, "#block name\tx\ty\tsubblk\tblock number\n");
fprintf(fp, "#----------\t--\t--\t------\t------------\n");
for (i = 0; i < num_blocks; i++) {
fprintf(fp, "%s\t", block[i].name);
if (strlen(block[i].name) < 8)
fprintf(fp, "\t");
fprintf(fp, "%d\t%d\t%d", block[i].x, block[i].y, block[i].z);
fprintf(fp, "\t#%d\n", i);
}
fclose(fp);
}