# qmc - perform Quine-McCluskey tabulation # by A. Akin 4/18/77 for ICS 4610 assignment #3 include "/syscom/defi" # Software Tools definitions define(DONTCARE,3) define(DONTCARES,:37777777777) define(ENDOFLINE,1) define(MAXIMPL,100) define(NOTSYM,2) define(ORSYM,3) define(VARIABLE,4) define(WSPSIZE,100) call init repeat { call input # read data call qmc # perform Quine-McCluskey tabulation call smplfy # simplify prime implicants call output # output prime implicants } end # input - input data for Quine-McCluskey tabulation subroutine input include qmccom character arg (2) integer getarg, getvar, getexp pflag = YES if (getarg (1, arg, 2) ~= EOF) andif (arg (1) == MINUS) pflag = NO if (pflag == YES) call instru # print instructions repeat { force = YES call prompt ("Variables: .") } until (getvar (0) ~= ERR) # get list of variables repeat { force = YES call prompt ("Expression: .") } until (getexp (0) ~= ERR) # get expression to be reduced return end # getvar - get list of variables to be used in expression integer function getvar (dummy) integer dummy include qmccom character line (MAXLINE) integer i, j integer getlin, length, type, index getvar = ERR numvar = 0 vars (1) = EOS if (getlin (line, STDIN) == EOF) call swt # exit if EOF encountered i = length (line) line (i) = EOS i = i - 1 if (i == 0) call swt # exit if null line entered for (j = 1; j <= i; j = j + 1) { if (type (line (j)) ~= LETTER) next # ignore non-alpha characters if (index (vars, line (j)) ~= 0) { call remark ("duplicate variable:.") call putch (line (j), ERROUT) call putch (NEWLINE, ERROUT) return } if (numvar >= 15) { call remark ("number of variables must be <= 15.") return } numvar = numvar + 1 vars (numvar) = line (j) vars (numvar + 1) = EOS } if (numvar == 0) { call remark ("no variables detected.") return } getvar = OK return end # getexp - get boolean expression for Quine-McCluskey tabulation integer function getexp (dummy) integer dummy include qmccom integer * 4 term integer geterm curlis = 0 # top of current terms list lisend = 1 # end of new list - where items are added getexp = ERR call getsym repeat { if (geterm (term) == ERR) return call enter (term) if (symbol ~= ORSYM) if (symbol == ENDOFLINE) break # end of expression else { call remark ("unrecognized symbol.") return } call getsym } curlis = 1 # start of current list newlis = lisend # start of next list getexp = OK return end # geterm - get a term of a boolean expression, for qmc integer function geterm (term) integer * 4 term include qmccom integer var, negate integer addfac, getvp geterm = ERR term = DONTCARES while (symbol == VARIABLE) { if (getvp (var, negate) == ERR) break if (addfac (var, negate, term) == ERR) return } if (term ~= DONTCARES) geterm = OK else call remark ("missing or illegal term.") return end # getvp - get a variable, optionally followed by a negation symbol (') integer function getvp (var, negate) integer var, negate include qmccom integer index getvp = ERR if (symbol ~= VARIABLE) return var = index (vars, inchar) if (var == 0) return call getsym if (symbol == NOTSYM) { negate = YES call getsym } else negate = NO getvp = OK return end # addfac - add a factor into a term integer function addfac (var, negate, term) integer var, negate integer * 4 term include qmccom integer * 4 yn integer * 4 and, rs, ls, not, or addfac = ERR if (and (rs (term, 2 * (var - 1)), 3) ~= DONTCARE) { call remark ("same variable appears twice in a term.") return } if (negate == YES) yn = 0 else yn = 1 term = or( ls(yn, 2 *(var - 1)), and(term, not(ls(intl(3), 2*(var-1))))) addfac = OK return end # getsym - get next symbol in input stream subroutine getsym include qmccom integer ptr character buf (MAXLINE) integer getlin data ptr /MAXLINE/ if (force == YES | ptr >= MAXLINE) { if (getlin (buf, STDIN) == EOF) call swt force = NO ptr = 1 } 10 while (buf (ptr) == BLANK | buf (ptr) == TAB) ptr = ptr + 1 if (buf (ptr) == NEWLINE) symbol = ENDOFLINE else if (buf (ptr) == SQUOTE) symbol = NOTSYM else if (buf (ptr) == PLUS) symbol = ORSYM else if (buf (ptr) == AMPER) { if (getlin (buf, STDIN) == EOF) call swt ptr = 1 goto 10 20 continue # to fake off fortran } else { # variable, by default inchar = buf (ptr) symbol = VARIABLE } ptr = ptr + 1 return end # qmc - perform Quine-McCluskey tabulation on table worksp subroutine qmc include qmccom integer change, i, j integer * 4 newtrm integer onedif, deld, next nimpl = 0 repeat { change = NO for (i = curlis; i ~= newlis; i = next (i)) for (j = i; j ~= newlis; j = next (j)) { if (deld (worksp (j)) == YES) next if (onedif (worksp (i), worksp (j)) == YES) { call combin (worksp (i), worksp (j), newtrm) call enter (newtrm) change = YES call delete (worksp (i)) call delete (worksp (j)) break } } for (i = curlis; i ~= newlis; i = next (i)) if (deld (worksp (i)) == NO) { call remem (worksp (i)) call delete (worksp (i)) } if (change == NO) break curlis = newlis newlis = lisend } return end # deld - is an element deleted? integer function deld (elem) integer * 4 elem integer * 4 and if (and (elem, intl (3)) == intl (2)) deld = YES else deld = NO return end # delete - flag an element as deleted subroutine delete (elem) integer * 4 elem elem = 2 return end # onedif - do two elements differ in only one variable position? integer function onedif (elt1, elt2) integer * 4 elt1, elt2 integer i integer * 4 mask, res integer * 4 xor, ls mask = 1 res = xor (elt1, elt2) onedif = YES for (i = 1; i <= 15; i = i + 1) { if (mask == res) return mask = ls (mask, 2) # shift mask left two places } onedif = NO return end # combin - combine two elements to form a third with a "don't care" position subroutine combin (elt1, elt2, newelt) integer * 4 elt1, elt2, newelt integer * 4 mask integer * 4 xor, or, ls mask = xor (elt1, elt2) # find the bit that differs mask = or (mask, ls (mask, 1)) # make a "don't care" mask newelt = or (mask, elt1) return end # remem - remember prime implicants for later output subroutine remem (impl) integer * 4 impl include qmccom if (nimpl >= MAXIMPL) call error ("too many prime implicants generated.") nimpl = nimpl + 1 implis (nimpl) = impl return end # next - determine the next position in array worksp integer function next (pos) integer pos integer mod n e x t = mod (pos + 1, WSPSIZE) + 1 return end # prompt - print a prompting string if in verbose mode (pflag == YES) subroutine prompt (str) character str (ARB) include qmccom if (pflag == YES) call putlit (str, PERIOD, ERROUT) return end # enter - enter a term into table worksp subroutine enter (term) integer * 4 term include qmccom integer next if (lisend == curlis) call error ("too many temporaries generated in workspace.") worksp (lisend) = term lisend = next (lisend) return end # smplfy - simplify generated prime implicants subroutine smplfy # do nothing, for the present return end # instru - print instructions subroutine instru integer done data done /NO/ if (done == YES) return done = YES call remark ("Quine-McCluskey tabulation program.") call remark ("The response to a request for variables should be.") call remark ("a string of alphabetic characters which will be .") call remark ("used in your boolean expression; non-alpha characters.") call remark ("in this list will be ignored.") call remark ("Examples: xyz.") call remark (" a,b,c,d.") call remark (" .") call remark ("The response to a request for an expression should be.") call remark ("a boolean expression in the variables you listed,.") call remark ("in the form of a sum of products.") call remark ("The postfix prime (') may be used to negate a variable.") call remark ("The operator 'and' is designated by juxtaposition of.") call remark ("variables, eg 'x and not y' is entered as xy'.") call remark ("The operator 'or' is designated by the plus sign (+);.") call remark ("for example 'x or y' is entered as x + y.") call remark ("Examples: xy + xy'.") call remark (" abc + abc' + ab'c + ab'c' + d.") call remark ("Blanks are not significant in expressions; if an expression.") call remark ("is too long to fit on a line, terminate each line but the .") call remark ("last with an ampersand (&) and more input will be requested.") call remark (" .") call remark ("To terminate this program, enter a blank line in response.") call remark ("to the 'variables' request, or generate EOF by typing.") call remark ("control-c in the first position of a line.") call remark (" .") call remark ("Instructions and prompts will be inhibited if this program.") call remark ("is called with a dash (-) as its first argument, eg .") call remark (" qmc -.") call remark (" .") return end # output - print prime implicants in table implis subroutine output include qmccom integer i, j integer * 4 pos integer * 4 and, rs if (pflag == YES) { call putlit ("Prime implicants:.", PERIOD, STDOUT) call putch (NEWLINE, STDOUT) } for (i = 1; i <= nimpl; i = i + 1) { for (j = 1; j <= 15; j = j + 1) { pos = and (rs (implis (i), 2 * (j - 1)), intl (3)) if (pos == intl (0)) { call putch (vars (j), STDOUT) call putch (SQUOTE, STDOUT) } else if (pos == intl (1)) call putch (vars (j), STDOUT) } call putch (NEWLINE, STDOUT) } return end