#include #include #include #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); }