static int check_for_duplicate_block_names (void) { /* Checks that all blocks have duplicate names. Returns the number of * * duplicate names. */ int error, iblk; struct s_hash **block_hash_table, *h_ptr; struct s_hash_iterator hash_iterator; error = 0; block_hash_table = alloc_hash_table (); for (iblk=0;iblk<num_blocks;iblk++) h_ptr = insert_in_hash_table (block_hash_table, block[iblk].name, iblk); hash_iterator = start_hash_table_iterator (); h_ptr = get_next_hash (block_hash_table, &hash_iterator); while (h_ptr != NULL) { if (h_ptr->count != 1) { printf ("Error: %d blocks are named %s. Block names must be unique." "\n", h_ptr->count, h_ptr->name); error++; } h_ptr = get_next_hash (block_hash_table, &hash_iterator); } free_hash_table (block_hash_table); return (error); }
static int add_net (char *ptr, enum e_pin_type type, int bnum, int blk_pnum, int doall) { /* This routine is given a net name in *ptr, either DRIVER or RECEIVER * * specifying whether the block number given by bnum is driving this * * net or in the fan-out and doall, which is 0 for the counting pass * * and 1 for the loading pass. It updates the net data structure and * * returns the net number so the calling routine can update the block * * data structure. */ struct s_hash *h_ptr; int j, nindex; if (doall == 0) { /* Counting pass only */ h_ptr = insert_in_hash_table (hash_table, ptr, num_nets); nindex = h_ptr->index; if (nindex == num_nets) /* Net was not in the hash table */ num_nets++; return (nindex); } else { /* Load pass */ h_ptr = get_hash_entry (hash_table, ptr); nindex = h_ptr->index; if (h_ptr == NULL) { printf("Error in add_net: the second (load) pass found could not\n"); printf("find net %s in the symbol table.\n", ptr); exit(1); } net[nindex].num_pins++; if (type == DRIVER) { num_driver[nindex]++; j=0; /* Driver always in position 0 of pinlist */ } else { j = net[nindex].num_pins - num_driver[nindex]; /* num_driver is the number of signal drivers of this net. * * should always be zero or 1 unless the netlist is bad. */ if (j >= temp_num_pins[nindex]) { printf("Error: Net #%d (%s) has no driver and will cause\n", nindex, ptr); printf("memory corruption.\n"); exit(1); } } net[nindex].blocks[j] = bnum; net[nindex].blk_pin[j] = blk_pnum; return (nindex); } }
/** * Adds pack pattern name to hashtable of pack pattern names. */ static int add_pattern_name_to_hash(INOUTP struct s_hash **nhash, INP char *pattern_name, INOUTP int *ncount) { struct s_hash *hash_value; hash_value = insert_in_hash_table(nhash, pattern_name, *ncount); if (hash_value->count == 1) { assert(*ncount == hash_value->index); (*ncount)++; } return hash_value->index; }
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; printf("\nReading locations of IO pads from %s.\n", pad_loc_file); linenum = 0; fp = my_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) { printf("Error: line %d is incomplete.\n", linenum); exit(1); } sscanf(ptr, "%d", &xtmp); ptr = my_strtok(NULL, TOKENS, fp, buf); if(ptr == NULL) { printf("Error: line %d is incomplete.\n", linenum); exit(1); } sscanf(ptr, "%d", &ytmp); ptr = my_strtok(NULL, TOKENS, fp, buf); if(ptr == NULL) { printf("Error: line %d is incomplete.\n", linenum); exit(1); } sscanf(ptr, "%d", &k); ptr = my_strtok(NULL, TOKENS, fp, buf); if(ptr != NULL) { printf("Error: extra characters at end of line %d.\n", linenum); exit(1); } h_ptr = get_hash_entry(hash_table, bname); if(h_ptr == NULL) { printf("Error: block %s on line %d: no such IO pad.\n", bname, linenum); exit(1); } bnum = h_ptr->index; i = xtmp; j = ytmp; if(block[bnum].x != OPEN) { printf ("Error: line %d. Block %s listed twice in pad file.\n", linenum, bname); exit(1); } if(i < 0 || i > nx + 1 || j < 0 || j > ny + 1) { printf("Error: block #%d (%s) location\n", bnum, bname); printf("(%d,%d) is out of range.\n", 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. */ if(grid[i][j].type != IO_TYPE) { printf("Error: attempt to place IO block %s in \n", bname); printf("an illegal location (%d, %d).\n", i, j); exit(1); } if(k >= IO_TYPE->capacity || k < 0) { printf ("Error: Block %s subblock number (%d) on line %d is out of " "range.\n", bname, k, linenum); 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) { printf ("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); printf("Successfully read %s.\n\n", pad_loc_file); }