📄 read_netlist.c
字号:
ptr = my_strtok(NULL,TOKENS,fp_net,temp_buf); while (ptr != NULL) { /* For each subblock pin. */ if (doall == 1) { connect_to = get_pin_number (ptr); if (ipin < subblock_lut_size) { /* LUT input. */ subblock_inf[bnum][num_subblocks-1].inputs[ipin] = connect_to; } else if (ipin == subblock_lut_size) { /* LUT output. */ subblock_inf[bnum][num_subblocks-1].output = connect_to; } else if (ipin == subblock_lut_size+1) { /* Clock input. */ subblock_inf[bnum][num_subblocks-1].clock = connect_to; } } ipin++; ptr = my_strtok(NULL,TOKENS,fp_net,temp_buf); } if (ipin != subblock_lut_size + 2) { printf("Error in load_subblock_array at line %d of netlist file.\n", linenum); printf("Subblock had %d pins, expected %d.\n", ipin, subblock_lut_size+2); printf("Aborting.\n\n"); exit (1); }}static void set_subblock_count (int bnum, int num_subblocks) {/* Sets the temporary subblock count for block bnum to num_subblocks. * * Properly allocates whatever temporary storage is needed. */ if (bnum >= temp_block_storage) { temp_block_storage *= 2; num_subblocks_per_block = (int *) my_realloc (num_subblocks_per_block, temp_block_storage * sizeof (int)); } num_subblocks_per_block[bnum] = num_subblocks;}static char *parse_subblocks (int doall, FILE *fp_net, char *buf, int bnum) {/* Loads the subblock arrays with the proper values. */ char temp_buf[BUFSIZE], *ptr; int num_subblocks; num_subblocks = 0; while (1) { ptr = my_fgets (temp_buf, BUFSIZE, fp_net); if (ptr == NULL) break; /* EOF */ /* Save line in case it's not a sublock */ strcpy (buf, temp_buf); ptr = my_strtok(temp_buf,TOKENS,fp_net,temp_buf); if (ptr == NULL) continue; /* Blank or comment line. Skip. */ if (strcmp("subblock:", ptr) == 0) { num_subblocks++; load_subblock_array (doall, fp_net, temp_buf, num_subblocks, bnum); } else { break; /* Subblock list has ended. Buf contains next line. */ } } /* End infinite while */ if (num_subblocks < 1 || num_subblocks > max_subblocks_per_block) { printf("Error in parse_subblocks on line %d of netlist file.\n", linenum); printf("Block #%d has %d subblocks. Out of range.\n", bnum, num_subblocks); printf("Aborting.\n\n"); exit (1); } if (doall == 0) set_subblock_count (bnum, num_subblocks); else assert (num_subblocks == num_subblocks_per_block[bnum]); return (ptr);}static char *add_clb (int doall, FILE *fp_net, char *buf) {/* Adds the clb (.clb) currently being parsed to the block array. Adds * * its pins to the nets data structure by calling add_net. If doall is * * zero this is a counting pass; if it is 1 this is the final (loading) * * pass. */ char *ptr; int pin_index, iclass, inet; enum e_pin_type type; num_blocks++; parse_name_and_pinlist (doall, fp_net, buf); num_clbs++; if (doall) block[num_blocks - 1].type = CLB; pin_index = -1; ptr = my_strtok(NULL,TOKENS,fp_net,buf); while (ptr != NULL) { pin_index++; if (pin_index >= pins_per_clb) { printf("Error in add_clb on line %d of netlist file.\n",linenum); printf("Too many pins on this clb. Expected %d.\n",pins_per_clb); exit (1); } iclass = clb_pin_class[pin_index]; type = class_inf[iclass].type; /* DRIVER or RECEIVER */ if (strcmp(ptr,"open") != 0) { /* Pin is connected. */ inet = add_net (ptr, type, num_blocks-1, pin_index, doall); if (doall) /* Loading pass only */ block[num_blocks - 1].nets[pin_index] = inet; } else { /* Pin is unconnected (open) */ if (doall) block[num_blocks - 1].nets[pin_index] = OPEN; } ptr = my_strtok(NULL,TOKENS,fp_net,buf); } if (pin_index != pins_per_clb - 1) { printf("Error in add_clb on line %d of netlist file.\n",linenum); printf("Expected %d pins on clb, got %d.\n", pins_per_clb, pin_index + 1); exit (1); } ptr = parse_subblocks (doall, fp_net, buf, num_blocks-1); return (ptr);}static void add_io (int doall, int block_type, FILE *fp_net, char *buf) {/* Adds the INPAD or OUTPAD (specified by block_type) currently being * * parsed to the block array. Adds its pin to the nets data structure * * by calling add_net. If doall is zero this is a counting pass; if it * * is 1 this is the final (loading) pass. */ char *ptr; int inet, pin_index, i; enum e_pin_type type; num_blocks++; if (doall == 0) set_subblock_count (num_blocks-1, 0); /* No subblocks for IO */ parse_name_and_pinlist (doall, fp_net, buf); if (block_type == INPAD) { num_p_inputs++; type = DRIVER; } else { num_p_outputs++; type = RECEIVER; } if (doall) block[num_blocks - 1].type = block_type; pin_index = -1; ptr = my_strtok(NULL,TOKENS,fp_net,buf); while (ptr != NULL) { pin_index++; if (pin_index >= 1) { printf("Error in add_io on line %d of netlist file.\n",linenum); printf("Too many pins on this io. Expected 1.\n"); exit (1); } if (strcmp(ptr,"open") == 0) { /* Pin unconnected. */ printf("Error in add_io, line %d of netlist file.\n",linenum); printf("Inputs and Outputs cannot have open pins.\n"); exit (1); } /* Note the dummy pin number for IO pins. Change this if necessary. I set * * them to OPEN because I want the code to crash if I try to look up the * * class of an I/O pin (since I/O pins don't have classes). */ inet = add_net (ptr, type, num_blocks-1, OPEN, doall); if (doall) /* Loading pass only */ block[num_blocks - 1].nets[pin_index] = inet; ptr = my_strtok(NULL,TOKENS,fp_net,buf); } if (pin_index != 0) { printf("Error in add_io on line %d of netlist file.\n",linenum); printf("Expected 1 pin on pad, got %d.\n", pin_index + 1); exit (1); } if (doall) { for (i=1;i<pins_per_clb;i++) block[num_blocks-1].nets[i] = OPEN; }}static void parse_name_and_pinlist (int doall, FILE *fp_net, char *buf) {/* This routine does the first part of the parsing of a block. It is * * called whenever any type of block (.clb, .input or .output) is to * * be parsed. It increments the block count (num_blocks), and checks * * that the block has a name. If doall is 1, this is the loading * * pass and it copies the name to the block data structure. Finally * * it checks that the pinlist: keyword exists. On return, my_strtok * * is set so that the next call will get the first net connected to * * this block. */ char *ptr; int len; /* Get block name. */ ptr = my_strtok(NULL,TOKENS,fp_net,buf); if (ptr == NULL) { printf("Error in parse_name_and_pinlist on line %d of netlist file.\n", linenum); printf(".clb, .input or .output line has no associated name.\n"); exit (1); } if (doall == 1) { /* Second (loading) pass, store block name */ len = strlen (ptr); block[num_blocks-1].name = my_chunk_malloc ((len + 1) * sizeof(char), NULL, &chunk_bytes_avail, &chunk_next_avail_mem); strcpy (block[num_blocks-1].name, ptr); } ptr = my_strtok (NULL,TOKENS,fp_net,buf); if (ptr != NULL) { printf("Error in parse_name_and_pinlist on line %d of netlist file.\n", linenum); printf("Extra characters at end of line.\n"); exit (1); } /* Now get pinlist from the next line. Note that a NULL return value * * from my_gets means EOF, while a NULL return from my_strtok just * * means we had a blank or comment line. */ do { ptr = my_fgets (buf, BUFSIZE, fp_net); if (ptr == NULL) { printf("Error in parse_name_and_pinlist on line %d of netlist file.\n", linenum); printf("Missing pinlist: keyword.\n"); exit (1); } ptr = my_strtok(buf,TOKENS,fp_net,buf); } while (ptr == NULL); if (strcmp (ptr, "pinlist:") != 0) { printf("Error in parse_name_and_pinlist on line %d of netlist file.\n", linenum); printf("Expected pinlist: keyword, got %s.\n",ptr); exit (1); }}static void add_global (int doall, FILE *fp_net, char *buf) {/* Doall is 0 for the first (counting) pass and 1 for the second * * (loading) pass. fp_net is a pointer to the netlist file. This * * routine sets the proper entry(ies) in is_global to TRUE during the * * loading pass. The routine does nothing during the counting pass. If * * is_global = TRUE for a net, it will not be considered in the placement * * cost function, nor will it be routed. This is useful for global * * signals like clocks that generally have dedicated routing in FPGAs. */ char *ptr; struct s_hash *h_ptr; int nindex;/* Do nothing if this is the counting pass. */ if (doall == 0) return; ptr = my_strtok(NULL,TOKENS,fp_net,buf); while (ptr != NULL) { /* For each .global signal */ num_globals++; h_ptr = get_hash_entry (hash_table, ptr); if (h_ptr == NULL) { /* Net was not found in list! */ printf("Error in add_global on netlist file line %d.\n",linenum); printf("Global signal %s does not exist.\n",ptr); exit(1); } nindex = h_ptr->index; is_global[nindex] = TRUE; /* Flagged as global net */ ptr = my_strtok(NULL,TOKENS,fp_net,buf); }}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); }}static void free_parse (void) { /* Release memory needed only during circuit netlist parsing. */ free (num_driver); free_hash_table (hash_table); free (temp_num_pins);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -