📄 read_blif.c
字号:
#include <string.h>#include <stdio.h>#include "util.h"#include "vpack.h"#include "globals.h"#include "read_blif.h"/* This source file will read in a FLAT blif netlist consisting ** of .inputs, .outputs, .names and .latch commands. It currently ** does not handle hierarchical blif files. Hierarchical ** blif files can be flattened via the read_blif and write_blif ** commands of sis. LUT circuits should only have .names commands; ** there should be no gates. This parser performs limited error ** checking concerning the consistency of the netlist it obtains. ** .inputs and .outputs statements must be given; this parser does ** not infer primary inputs and outputs from non-driven and fanout ** free nodes. This parser can be extended to do this if necessary, ** or the sis read_blif and write_blif commands can be used to put a ** netlist into the standard format. ** V. Betz, August 25, 1994. ** Added more error checking, March 30, 1995, V. Betz */static int *num_driver, *temp_num_pins;/* # of .input, .output, .model and .end lines */static int ilines, olines, model_lines, endlines; static struct hash_nets **hash;static char *model;static FILE *blif;static int add_net (char *ptr, int type, int bnum, int doall); static void get_tok(char *buffer, int pass, int doall, int *done, int lut_size);static void init_parse(int doall);static void check_net (int lut_size);static void free_parse (void);static void io_line (int in_or_out, int doall);static void add_lut (int doall, int lut_size);static void add_latch (int doall, int lut_size);static void dum_parse (char *buf);static int hash_value (char *name);void read_blif (char *blif_file, int lut_size) { char buffer[BUFSIZE]; int pass, done, doall; blif = my_fopen (blif_file, "r", 0); for (doall=0;doall<=1;doall++) { init_parse(doall);/* Three passes to ensure inputs are first blocks, outputs second and * * LUTs and latches third. Just makes the output netlist more readable. */ for (pass=1;pass<=3;pass++) { linenum = 0; /* Reset line number. */ done = 0; while((my_fgets(buffer,BUFSIZE,blif) != NULL) && !done) { get_tok(buffer, pass, doall, &done, lut_size); } rewind (blif); /* Start at beginning of file again */ } } fclose(blif); check_net(lut_size); free_parse();}static void init_parse(int doall) {/* Allocates and initializes the data structures needed for the parse. */ int i, len; struct hash_nets *h_ptr; if (!doall) { /* Initialization before first (counting) pass */ num_nets = 0; hash = (struct hash_nets **) my_calloc(sizeof(struct hash_nets *), HASHSIZE); }/* 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)); 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; } for (i=0;i<HASHSIZE;i++) { h_ptr = hash[i]; while (h_ptr != NULL) { net[h_ptr->index].pins = (int *) my_malloc(h_ptr->count*sizeof(int));/* For avoiding assigning values beyond end of pins array. */ temp_num_pins[h_ptr->index] = h_ptr->count; len = strlen (h_ptr->name); net[h_ptr->index].name = (char *) my_malloc ((len + 1)* sizeof(char)); strcpy (net[h_ptr->index].name, h_ptr->name); h_ptr = h_ptr->next; } }/* printf("i\ttemp_num_pins\n\n"); for (i=0;i<num_nets;i++) { printf("%d\t%d\n",i,temp_num_pins[i]); } */ }/* Initializations for both passes. */ ilines = 0; olines = 0; model_lines = 0; endlines = 0; num_p_inputs = 0; num_p_outputs = 0; num_luts = 0; num_latches = 0; num_blocks = 0;}static void get_tok (char *buffer, int pass, int doall, int *done, int lut_size) {/* Figures out which, if any token is at the start of this line and * * takes the appropriate action. */#define TOKENS " \t\n" char *ptr; ptr = my_strtok(buffer,TOKENS,blif,buffer); if (ptr == NULL) return; if (strcmp(ptr,".names") == 0) { if (pass == 3) { add_lut(doall, lut_size); } else { dum_parse(buffer); } return; } if (strcmp(ptr,".latch") == 0) { if (pass == 3) { add_latch (doall, lut_size); } else { dum_parse(buffer); } return; } if (strcmp(ptr,".model") == 0) { ptr = my_strtok(NULL,TOKENS,blif,buffer); if (doall && pass == 3) { /* Only bother on main second pass. */ if (ptr != NULL) { model = (char *) my_malloc ((strlen(ptr)+1) * sizeof(char)); strcpy(model,ptr); } else { model = (char *) my_malloc (sizeof(char)); model[0] = '\0'; } model_lines++; /* For error checking only */ } return; } if (strcmp(ptr,".inputs") == 0) { if (pass == 1) { io_line(DRIVER, doall); *done = 1; } else { dum_parse(buffer); if (pass == 3 && doall) ilines++; /* Error checking only */ } return; } if (strcmp(ptr,".outputs") == 0) { if (pass == 2) { io_line(RECEIVER, doall); *done = 1; } else { dum_parse(buffer); if (pass == 3 && doall) olines++; /* Make sure only one .output line */ } /* For error checking only */ return; } if (strcmp(ptr,".end") == 0) { if (pass == 3 && doall) endlines++; /* Error checking only */ return; }/* Could have numbers following a .names command, so not matching any * * of the tokens above is not an error. */}static void dum_parse (char *buf) {/* Continue parsing to the end of this (possibly continued) line. */ while (my_strtok(NULL,TOKENS,blif,buf) != NULL) ;}static void add_lut (int doall, int lut_size) {/* Adds a LUT (.names) 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, saved_names[MAXLUT+2][BUFSIZE], buf[BUFSIZE]; int i, j, len; num_blocks++;/* Count # nets connecting */ i=0; while ((ptr = my_strtok(NULL,TOKENS,blif,buf)) != NULL) { if (i == MAXLUT+1) { fprintf(stderr,"Error: LUT #%d has %d inputs. Increase MAXLUT or" " check the netlist, line %d.\n",num_blocks-1,i-1,linenum); exit(1); } strcpy (saved_names[i], ptr); i++; } if (!doall) { /* Counting pass only ... */ for (j=0;j<i;j++) add_net(saved_names[j],RECEIVER,num_blocks-1,doall); return; } block[num_blocks-1].num_nets = i; block[num_blocks-1].type = LUT; for (i=0;i<block[num_blocks-1].num_nets-1;i++) /* Do inputs */ block[num_blocks-1].nets[i+1] = add_net (saved_names[i],RECEIVER, num_blocks-1,doall); block[num_blocks-1].nets[0] = add_net ( saved_names[block[num_blocks-1].num_nets-1], DRIVER,num_blocks-1,doall); for (i=block[num_blocks-1].num_nets; i<lut_size+2; i++) block[num_blocks-1].nets[i] = OPEN; len = strlen (saved_names[block[num_blocks-1].num_nets-1]); block[num_blocks-1].name = (char *) my_malloc ((len+1) * sizeof (char)); strcpy(block[num_blocks-1].name, saved_names[block[num_blocks-1].num_nets-1]); num_luts++;}static void add_latch (int doall, int lut_size) {/* Adds the flipflop (.latch) 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. Blif format for a latch is: * * .latch <input> <output> <type (latch on)> <control (clock)> <init_val> * * The latch pins are in .nets 0 to 2 in the order: Q D CLOCK. */ char *ptr, buf[BUFSIZE], saved_names[6][BUFSIZE]; int i, len; num_blocks++;/* Count # parameters, making sure we don't go over 6 (avoids memory corr.) *//* Note that we can't rely on the tokens being around unless we copy them. */ for (i=0;i<6;i++) { ptr = my_strtok (NULL,TOKENS,blif,buf); if (ptr == NULL) break; strcpy (saved_names[i], ptr); } if (i != 5) { fprintf(stderr,"Error: .latch does not have 5 parameters.\n" "check the netlist, line %d.\n",linenum); exit(1); } if (!doall) { /* If only a counting pass ... */ add_net(saved_names[0],RECEIVER,num_blocks-1,doall); /* D */ add_net(saved_names[1],DRIVER,num_blocks-1,doall); /* Q */ add_net(saved_names[3],RECEIVER,num_blocks-1,doall); /* Clock */ return; } block[num_blocks-1].num_nets = 3; block[num_blocks-1].type = LATCH; block[num_blocks-1].nets[0] = add_net(saved_names[1],DRIVER,num_blocks-1, doall); /* Q */ block[num_blocks-1].nets[1] = add_net(saved_names[0],RECEIVER,num_blocks-1, doall); /* D */ block[num_blocks-1].nets[lut_size+1] = add_net(saved_names[3],RECEIVER, num_blocks-1,doall); /* Clock */ for (i=2;i<lut_size+1;i++) block[num_blocks-1].nets[i] = OPEN; len = strlen (saved_names[1]); block[num_blocks-1].name = (char *) my_malloc ((len+1) * sizeof (char)); strcpy(block[num_blocks-1].name,saved_names[1]); num_latches++;}static void io_line(int in_or_out, int doall) { /* Adds an input or output block to the block data structures. * * in_or_out: DRIVER for input, RECEIVER for output. * * doall: 1 for final pass when structures are loaded. 0 for * * first pass when hash table is built and pins, nets, etc. are counted. */ char *ptr; char buf2[BUFSIZE]; int nindex, len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -