📄 read_blif.c
字号:
while (1) { ptr = my_strtok(NULL,TOKENS,blif,buf2); if (ptr == NULL) return; num_blocks++; nindex = add_net(ptr,in_or_out,num_blocks-1,doall); /* zero offset indexing */ if (!doall) continue; /* Just counting things when doall == 0 */ len = strlen (ptr); if (in_or_out == RECEIVER) { /* output pads need out: prefix to make names unique from LUTs */ block[num_blocks-1].name = (char *) my_malloc ((len+1+4) * sizeof (char)); /* Space for out: at start */ strcpy(block[num_blocks-1].name,"out:"); strcat(block[num_blocks-1].name,ptr); } else { block[num_blocks-1].name = (char *) my_malloc ((len+1) * sizeof (char)); strcpy(block[num_blocks-1].name,ptr); } block[num_blocks-1].num_nets = 1; block[num_blocks-1].nets[0] = nindex; /* Put in driver position for */ /* OUTPAD, since it has only one pin (even though it's a receiver */ if (in_or_out == DRIVER) { /* processing .inputs line */ num_p_inputs++; block[num_blocks-1].type = INPAD; } else { /* processing .outputs line */ num_p_outputs++; block[num_blocks-1].type = OUTPAD; } } }static int add_net (char *ptr, int type, int bnum, 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 hash_nets *h_ptr, *prev_ptr; int index, j, nindex; index = hash_value(ptr); h_ptr = hash[index]; prev_ptr = h_ptr; while (h_ptr != NULL) { if (strcmp(h_ptr->name,ptr) == 0) { /* Net already in hash table */ nindex = h_ptr->index; if (!doall) { /* Counting pass only */ (h_ptr->count)++; return (nindex); } 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].pins[j] = bnum; return (nindex); } prev_ptr = h_ptr; h_ptr = h_ptr->next; } /* Net was not in the hash table. */ if (doall == 1) { printf("Error in add_net: the second (load) pass could not\n"); printf("find net %s in the symbol table.\n", ptr); exit(1); }/* Add the net (only counting pass will add nets to symbol table). */ num_nets++; h_ptr = (struct hash_nets *) my_malloc (sizeof(struct hash_nets)); if (prev_ptr == NULL) { hash[index] = h_ptr; } else { prev_ptr->next = h_ptr; } h_ptr->next = NULL; h_ptr->index = num_nets - 1; h_ptr->count = 1; h_ptr->name = (char *) my_malloc((strlen(ptr)+1)*sizeof(char)); strcpy(h_ptr->name,ptr); return (h_ptr->index);}static int hash_value (char *name) { int i,k; int val=0, mult=1; i = strlen(name); k = max (i-7,0); for (i=strlen(name)-1;i>=k;i--) { val += mult*((int) name[i]); mult *= 10; } val += (int) name[0]; val %= HASHSIZE; return(val);}void echo_input (char *blif_file, int lut_size, char *echo_file) {/* Echo back the netlist data structures to file input.echo to * * allow the user to look at the internal state of the program * * and check the parsing. */ int i, j, max_pin; FILE *fp; printf("Input netlist file: %s Model: %s\n", blif_file, model); printf("Primary Inputs: %d. Primary Outputs: %d.\n", num_p_inputs, num_p_outputs); printf("LUTs: %d. Latches: %d.\n", num_luts, num_latches); printf("Total Blocks: %d. Total Nets: %d\n", num_blocks, num_nets); fp = my_fopen (echo_file,"w",0); fprintf(fp,"Input netlist file: %s Model: %s\n",blif_file,model); fprintf(fp,"num_p_inputs: %d, num_p_outputs: %d, num_luts: %d," " num_latches: %d\n",num_p_inputs,num_p_outputs,num_luts, num_latches); fprintf(fp,"num_blocks: %d, num_nets: %d\n",num_blocks,num_nets); fprintf(fp,"\nNet\tName\t\t#Pins\tDriver\tRecvs.\n"); for (i=0;i<num_nets;i++) { fprintf(fp,"\n%d\t%s\t", i, net[i].name); if (strlen(net[i].name) < 8) fprintf(fp,"\t"); /* Name field is 16 chars wide */ fprintf(fp,"%d", net[i].num_pins); for (j=0;j<net[i].num_pins;j++) fprintf(fp,"\t%d",net[i].pins[j]); } fprintf(fp,"\n\n\nBlocks\t\t\tBlock Type Legend:\n"); fprintf(fp,"\t\t\tINPAD = %d\tOUTPAD = %d\n", INPAD, OUTPAD); fprintf(fp,"\t\t\tLUT = %d\t\tLATCH = %d\n", LUT, LATCH); fprintf(fp,"\t\t\tEMPTY = %d\tLUT_AND_LATCH = %d\n\n", EMPTY, LUT_AND_LATCH); fprintf(fp,"\nBlock\tName\t\tType\t#Nets\tOutput\tInputs"); for (i=0;i<lut_size;i++) fprintf(fp,"\t"); fprintf(fp,"Clock\n\n"); for (i=0;i<num_blocks;i++) { fprintf(fp,"\n%d\t%s\t",i, block[i].name); if (strlen(block[i].name) < 8) fprintf(fp,"\t"); /* Name field is 16 chars wide */ fprintf(fp,"%d\t%d", block[i].type, block[i].num_nets); /* I'm assuming EMPTY blocks are always INPADs when I print * * them out. This is true right after the netlist is read in, and again * * after ff_packing and compression of the netlist. It's not true after * * ff_packing and before netlist compression. */ if (block[i].type == INPAD || block[i].type == OUTPAD || block[i].type == EMPTY) max_pin = 1; else max_pin = lut_size+2; for (j=0;j<max_pin;j++) { if (block[i].nets[j] == OPEN) fprintf(fp,"\tOPEN"); else fprintf(fp,"\t%d",block[i].nets[j]); } } fprintf(fp,"\n"); fclose(fp);}static void check_net (int lut_size) {/* Checks the input netlist for obvious errors. */ int i, error, iblk; error = 0; if (ilines != 1) { printf("Warning: found %d .inputs lines; expected 1.\n", ilines); error++; } if (olines != 1) { printf("Warning: found %d .outputs lines; expected 1.\n", olines); error++; } if (model_lines != 1) { printf("Warning: found %d .model lines; expected 1.\n", model_lines); error++; } if (endlines != 1) { printf("Warning: found %d .end lines; expected 1.\n", endlines); error++; } for (i=0;i<num_nets;i++) { if (num_driver[i] != 1) { printf ("Warning: net %s has" " %d signals driving it.\n",net[i].name,num_driver[i]); error++; } if ((net[i].num_pins - num_driver[i]) < 1) {/* If this is an input pad, it is unused and I just remove it with * * a warning message. Lots of the mcnc circuits have this problem. */ iblk = net[i].pins[0]; if (block[iblk].type == INPAD) { printf("Warning: Input %s is unused; removing it.\n", block[iblk].name); net[i].pins[0] = OPEN; block[iblk].type = EMPTY; } else { printf("Warning: net %s has no fanout.\n",net[i].name); error++; } } if (strcmp(net[i].name, "open") == 0) { printf("Warning: net #%d has the reserved name %s.\n",i,net[i].name); error++; } } for (i=0;i<num_blocks;i++) { if (block[i].type == LUT) { if (block[i].num_nets < 2) { printf("Warning: logic block #%d with output %s has only %d pin.\n", i,block[i].name,block[i].num_nets);/* LUTs with 1 pin (an output) can be a constant generator. Warn the * * user, but don't exit. */ if (block[i].num_nets != 1) { error++; } else { printf("\tPin is an output -- may be a constant generator.\n"); printf("\tNon-fatal error.\n"); } } if (block[i].num_nets > lut_size + 1) { printf("Warning: logic block #%d with output %s has %d pins.\n", i,block[i].name,block[i].num_nets); error++; } } else if (block[i].type == LATCH) { if (block[i].num_nets != 3) { printf("Warning: Latch #%d with output %s has %d pin(s).\n", i, block[i].name, block[i].num_nets); error++; } } else { if (block[i].num_nets != 1) { printf("Warning: io block #%d with output %s of type %d" "has %d pins.\n", i, block[i].name, block[i].type, block[i].num_nets); error++; } } } if (error != 0) { printf("Found %d fatal errors in the input netlist.\n",error); exit(1); }}static void free_parse (void) { /* Release memory needed only during blif network parsing. */ int i; struct hash_nets *h_ptr, *temp_ptr; for (i=0;i<HASHSIZE;i++) { h_ptr = hash[i]; while (h_ptr != NULL) { free ((void *) h_ptr->name); temp_ptr = h_ptr->next; free ((void *) h_ptr); h_ptr = temp_ptr; } } free ((void *) num_driver); free ((void *) hash); free ((void *) temp_num_pins);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -