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); }
/** * Find all packing patterns in architecture * [0..num_packing_patterns-1] * * Limitations: Currently assumes that forced pack nets must be single-fanout as this covers all the reasonable architectures we wanted. More complicated structures should probably be handled either downstream (general packing) or upstream (in tech mapping) * If this limitation is too constraining, code is designed so that this limitation can be removed */ t_pack_patterns *alloc_and_load_pack_patterns(OUTP int *num_packing_patterns) { int i, j, ncount; int L_num_blocks; struct s_hash **nhash; t_pack_patterns *list_of_packing_patterns; t_pb_graph_edge *expansion_edge; /* alloc and initialize array of packing patterns based on architecture complex blocks */ nhash = alloc_hash_table(); ncount = 0; for (i = 0; i < num_types; i++) { discover_pattern_names_in_pb_graph_node( type_descriptors[i].pb_graph_head, nhash, &ncount); } list_of_packing_patterns = alloc_and_init_pattern_list_from_hash(ncount, nhash); /* load packing patterns by traversing the edges to find edges belonging to pattern */ for (i = 0; i < ncount; i++) { for (j = 0; j < num_types; j++) { expansion_edge = find_expansion_edge_of_pattern(i, type_descriptors[j].pb_graph_head); if (expansion_edge == NULL) { continue; } L_num_blocks = 0; list_of_packing_patterns[i].base_cost = 0; backward_expand_pack_pattern_from_edge(expansion_edge, list_of_packing_patterns, i, NULL, NULL, &L_num_blocks); list_of_packing_patterns[i].num_blocks = L_num_blocks; break; } } free_hash_table(nhash); *num_packing_patterns = ncount; return list_of_packing_patterns; }
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); }
void setup (void) { test_hash_table = alloc_hash_table(); }
static void init_parse(int doall) { /* Allocates and initializes the data structures needed for the parse. */ int i, j, len, nindex, pin_count; int *tmp_ptr; struct s_hash_iterator hash_iterator; struct s_hash *h_ptr; if (!doall) { /* Initialization before first (counting) pass */ num_nets = 0; hash_table = alloc_hash_table (); #define INITIAL_BLOCK_STORAGE 2000 temp_block_storage = INITIAL_BLOCK_STORAGE; num_subblocks_per_block = my_malloc (INITIAL_BLOCK_STORAGE * sizeof(int)); ch_subblock_bytes_avail = 0; ch_subblock_next_avail_mem = NULL; ch_subblock_head_ptr = NULL; } /* Allocate memory for second (load) pass */ else { net = (struct s_net *) my_malloc (num_nets*sizeof(struct s_net)); block = (struct s_block *) my_malloc (num_blocks* sizeof(struct s_block)); is_global = (boolean *) my_calloc (num_nets, sizeof(boolean)); num_driver = (int *) my_malloc (num_nets * sizeof(int)); temp_num_pins = (int *) my_malloc (num_nets * sizeof(int)); for (i=0;i<num_nets;i++) { num_driver[i] = 0; net[i].num_pins = 0; } /* Allocate block pin connection storage. Some is wasted for io blocks. * * Method used below "chunks" the malloc of a bunch of small things to * * reduce the memory housekeeping overhead of malloc. */ tmp_ptr = (int *) my_malloc (pins_per_clb * num_blocks * sizeof(int)); for (i=0;i<num_blocks;i++) block[i].nets = tmp_ptr + i * pins_per_clb; /* I use my_chunk_malloc for some storage locations below. my_chunk_malloc * * avoids the 12 byte or so overhead incurred by malloc, but since I call it * * with a NULL head_ptr, it will not keep around enough information to ever * * free these data arrays. If you ever have compatibility problems on a * * non-SPARC architecture, just change all the my_chunk_malloc calls to * * my_malloc calls. */ hash_iterator = start_hash_table_iterator (); h_ptr = get_next_hash (hash_table, &hash_iterator); while (h_ptr != NULL) { nindex = h_ptr->index; pin_count = h_ptr->count; net[nindex].blocks = (int *) my_chunk_malloc(pin_count * sizeof(int), NULL, &chunk_bytes_avail, &chunk_next_avail_mem); net[nindex].blk_pin = (int *) my_chunk_malloc (pin_count * sizeof(int), NULL, &chunk_bytes_avail, &chunk_next_avail_mem); /* For avoiding assigning values beyond end of pins array. */ temp_num_pins[nindex] = pin_count; len = strlen (h_ptr->name); net[nindex].name = (char *) my_chunk_malloc ((len + 1) * sizeof(char), NULL, &chunk_bytes_avail, &chunk_next_avail_mem); strcpy (net[nindex].name, h_ptr->name); h_ptr = get_next_hash (hash_table, &hash_iterator); } /* Allocate storage for subblock info. (what's in each logic block) */ num_subblocks_per_block = (int *) my_realloc (num_subblocks_per_block, num_blocks * sizeof (int)); subblock_inf = (t_subblock **) my_malloc (num_blocks * sizeof(t_subblock *)); for (i=0;i<num_blocks;i++) { if (num_subblocks_per_block[i] == 0) subblock_inf[i] = NULL; else { subblock_inf[i] = (t_subblock *) my_chunk_malloc ( num_subblocks_per_block[i] * sizeof (t_subblock), &ch_subblock_head_ptr, &ch_subblock_bytes_avail, &ch_subblock_next_avail_mem); for (j=0;j<num_subblocks_per_block[i];j++) subblock_inf[i][j].inputs = (int *) my_chunk_malloc (subblock_lut_size * sizeof(int), &ch_subblock_head_ptr, &ch_subblock_bytes_avail, &ch_subblock_next_avail_mem); } } } /* Initializations for both passes. */ linenum = 0; num_p_inputs = 0; num_p_outputs = 0; num_clbs = 0; num_blocks = 0; num_globals = 0; }