/* quine_mcclusky.c digital circuit minimization input: boolean equation or truth table or minterms output: prime implicants and equation build: bison calc_eqn.y gcc -o qm quine_mcclusky.c calc_eqn.tab.c -lm run: qm -n 4 -m -i minterms4.dat > minterms4.out Copyright (C) 2002 Free Software Foundation, Inc. qm is free software; you can redistribute it and/or modify it under terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. qm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License distributed with qm; see file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include static void usage(); /* command line usage */ static void readtt(unsigned char *gt, int ng, int *gti, FILE *infile); static void readeqn(unsigned char *gt, int ng, int *gti, FILE *infile); static void readmin(unsigned char *gt, int ng, int *gti, FILE *infile); static void printgt(unsigned char *gt, int ng, int gti); static void countgt(unsigned char *gt, int ng, int gti); static void sortgt(unsigned char *gt, int ng, int *gti); static void printvhdl(unsigned char *pi, int ng, int pii, FILE *outfile); static void printveri(unsigned char *pi, int ng, int pii, FILE *outfile); static void heapsort( void *base, int nmemb, int size, int (*compar)(void *, void *) ); extern int yyparse(void); /* provided in calc_eqn.tab.c file */ int regs[26]; /* load with possible minterm */ char line[32767]; /* load with Verilog equation, translate */ int eqn_result; /* returned value of equation at minterm */ int line_index; /* zero before each call to yyparse */ int main(int argc, char *argv[]) { int i; /* index into argv, etc */ int j; /* general counter */ int k; /* general counter */ int m; /* bit position */ int n=0; /* number of variables */ int tt=0; /* truth table input */ int eqn=0; /* equation input */ int mint=0; /* minterm input */ int debug=0; /* debug print flag */ char inname[128]; /* input file name */ FILE *infile; /* input file handle */ char outname[128]; /* output file name */ FILE *outfile; /* output file handle */ int ng; /* size of gt entry, group+n+cov */ int n2n; /* 2^n */ int room; /* ng*ng*n2n */ unsigned char *gt; /* group table */ unsigned char *gtn; /* group table next */ int gti; /* group table index */ int gtni; /* group table next index */ unsigned char *pi; /* prime implicant table */ int pii=0; /* prime implicant index */ int gix[25]; /* index of group start */ int gixn; /* number of group start */ int gixc; /* group ones count */ int diffcnt; /* number of bits different */ int prev; /* pervious term used */ unsigned char gtdiff[24]; /* difference term with '-' */ printf("Quine McClusky digital circuit minimization V1.0\n"); /* initialize */ inname[0]='\0'; outname[0]='\0'; /* read options */ if(argc < 2) usage(); /* collect [options] */ for( i=1; i=argc) usage(); n = atoi(argv[i]); continue; } if( !strcmp("-input", argv[i]) || !strcmp("-i", argv[i])){ if( ++i>=argc) usage(); strcpy(inname, argv[i]); continue; } if( !strcmp("-output", argv[i]) || !strcmp("-o", argv[i])){ if( ++i>=argc) usage(); strcpy(outname, argv[i]); continue; } if( !strcmp("-tt", argv[i]) || !strcmp("-t", argv[i])){ tt++; continue; } if( !strcmp("-eqn", argv[i]) || !strcmp("-e", argv[i])){ eqn++; continue; } if( !strcmp("-min", argv[i]) || !strcmp("-m", argv[i])){ mint++; continue; } if( !strcmp("-debug", argv[i]) || !strcmp("-d", argv[i])){ debug++; continue; } usage(); } /* end of read options */ /* error checking: n, one type, input file */ if(n<2 || n>24) {printf("n=%d, out of range 2..24 \n", n); exit(0);} if(inname[0]=='\0') {printf("-i required \n"); exit(0);} infile=fopen(inname, "r"); if(infile==NULL) {printf("could not open input file %s \n", inname); exit(0);} if((tt+eqn+mint)!=1) {printf("select one input file type \n"); exit(0);} outfile=stdout; if(outname[0]!='\0'){ outfile=fopen(outname, "w"); if(outfile==NULL) {printf("could not open output file %s \n", outname); exit(0);} } ng=n+2; n2n=pow(2,n); room=ng*ng*n2n; if(debug) printf("asking for three %d byte arrays, %d rows \n", room, ng*n2n); gt= (unsigned char *)malloc(room); if(gt==NULL) {printf("malloc failed on gt, exiting.\n"); exit(1);} gtn=(unsigned char *)malloc(room); if(gtn==NULL) {printf("malloc failed on gtn, exiting.\n"); exit(1);} pi=(unsigned char *)malloc(room); if(pi==NULL) {printf("malloc failed on pi, exiting.\n"); exit(1);} /* get minterms */ if(tt) readtt(gt, ng, >i, infile); if(eqn) readeqn(gt, ng, >i, infile); if(mint) readmin(gt, ng, >i, infile); if(debug||tt||eqn) {printf("initial minterms \n"); printgt(gt, ng, gti);} /* start reduction loop */ reduce: /* count 1's in minterms, general, include "-" */ countgt(gt, ng, gti); if(debug) {printf("count ones \n"); printgt(gt, ng, gti);} /* sort minterms */ sortgt(gt, ng, >i); if(debug) {printf("sorted in groups \n"); printgt(gt, ng, gti);} /* construct next table, start finalized if none combined */ gixn=0; gix[0]=0; gixc=gt[0]; gt[gti*ng]=-1; for(j=1; jroom) {printf("exceeded internal storage gtni=%d\n",gtni); exit(1);} if(debug) {printf("gt groups covered \n"); printgt(gt, ng, gti);} if(debug) {printf("gtn groups \n"); printgt(gtn, ng, gtni);} /* save not covered into prime implicant table */ for(j=0; jroom) {printf("exceeded internal storage pii=%d\n",pii); exit(1);} if(debug) {printf("prime implicants \n"); printgt(pi, ng, pii);} /* copy combined into minterms table gtn into gt*/ for(j=0; j0) goto reduce; /* start finalize */ /* print final prime implicants */ if(debug) {printf("raw pi \n"); printgt(pi, ng, pii);} sortgt(pi, ng, &pii); printf("final prime implicants \n"); printgt(pi, ng, pii); /* output VHDL statement */ printvhdl(pi, ng, pii, outfile); /* output Verilog statement */ printveri(pi, ng, pii, outfile); return 0; } static void usage(){ printf("usage: qm [options] \n"); printf(" [options] can be: \n"); printf(" -n or -n \n"); printf(" -input or -i \n"); printf(" -output or -o \n"); printf(" -tt or -t (truth table input) \n"); printf(" -eqn or -e (equation input) \n"); printf(" -min or -m (minterm input) \n"); printf(" -debug or -d (print each stage, debug) \n"); printf(" -help or -h (gets this output) \n"); exit(0); /* program ends, user invokes again with improved command line */ } /* end usage */ /* read an input file of truth table into a gt table */ static void readtt(unsigned char *gt, int ng, int *gti, FILE *infile) { int i; int j=0; int k=0; int count=0; char mark=0; char line[256]; int debug=0; fgets(line, 256, infile); if(debug) printf("readtt %s\n", line); if(line[0]!='\0') sscanf(line, " %c ", &mark); /* skip lines not starting 0 or 1 */ while(!(mark=='0'||mark=='1')){ fgets(line, 256, infile); if(debug) printf("readtt %s\n", line); if(line[0]!='\0') sscanf(line, " %c ", &mark); } gt[j*ng]=0; for(i=1; i0) return 1; return 0; } /* end compar */ /* sortgt sort and compress out duplicates from a gt format table */ static void sortgt(unsigned char *gt, int ng, int *gti) { int j; int offs=0; int m; int ok; /* printf("enter sortgt with ng=%d, gti=%d\n", ng, *gti); */ heapsort (gt, *gti, ng, compar); /* remove duplicates */ j=0; while(j+offs<*gti){ ok=0; for(m=1; m0){ for(m=0; m=0;index_val--) remake_heap( array_val, index_val, nmemb-1, compar, item_temp, size ); memcpy(item_temp,array_val,size); memcpy(array_val,&array_val[(nmemb-1)*size],size); memcpy(&array_val[(nmemb-1)*size],item_temp,size); for(index_val=nmemb-2;index_val>0;index_val--){ remake_heap( array_val, 0, index_val, compar, item_temp, size ); memcpy(item_temp,array_val,size); memcpy(array_val,&array_val[index_val*size],size); memcpy(&array_val[index_val*size],item_temp,size); } } /* end heapsort */ static void remake_heap (char *array_val, int parent_index ,int last_index, int (*compar)(void *, void *), void *item_temp, int size) { int last_parent_pos = ( last_index - 1 ) / 2; int last_parent_index = last_parent_pos; int l_child; int r_child; int max_child_index; int parent_temp = parent_index; /* code for remake_heap */ for(;;){ if( parent_temp > last_parent_index ) break; l_child = parent_temp * 2 + 1; if( l_child == last_index) { max_child_index = l_child; } else { r_child = l_child+1; if((*compar)(&array_val[l_child*size],&array_val[r_child*size])>0) { max_child_index = l_child; } else { max_child_index = r_child; } } if((*compar)(&array_val[max_child_index*size], &array_val[parent_temp*size])>0) { memcpy(item_temp,&array_val[max_child_index*size],size); memcpy(&array_val[max_child_index*size],&array_val[parent_temp*size] ,size); memcpy(&array_val[parent_temp*size],item_temp,size); parent_temp = max_child_index; } else { break; } } } /* end remake_heap */