.PS # CanLogic log_init divert(-1) ########################################################################### Macros for automatically drawing 2-layer Boolean functions Style parameters define(`dotrad_',(0.01*scale)) define(`gatelineth',1) define(`lineth',0.5) define(`inputsep',`2*jog') define(`jog',`(AND_ht/2)*L_unit') `CanLogic(layer gate type,[N], output gate type,[N], term,term,...) This is the driver macro. Terms are strings of variables or of variables preceded by the ~ character. Each variable is one letter e.g. CanLogic(NAND,,OR,N,abcd,a~b,c,~ad)' define(`CanLogic', `define(`terms',`shift(shift(shift(shift($@))))') # Determine required input variables and negated # variables Loopover_(`t_',`CLvarloop(`v_',`define(X`'v_)',`define(XN`'v_)',t_)',terms) # Draw the inputs with NOT gates as necessary PrevInput: Here-(inputsep,0) Loopover_(`t_',`CLvarloop(`v_', `ifdef(D`'v_,,`ifdef(XN`'v_,`CLDrawInNotIn(v_)',`CLDrawIn(v_)')')', `ifdef(D`'v_,,`ifdef(X`'v_,`CLDrawInNotIn(v_)',`CLDrawNotIn(v_)')')', t_)', terms) # Draw 2nd-layer gates right_ LastGateSE: PrevInput+(5*jog,-(AND_wd*L_unit*1.5)) dnl Loopover_(`t_', `define(`termcount',m4Lx)CLDrawLayerGate(G`'termcount,$1,$2,t_)', terms) # Draw output gate linethick = gatelineth OP: m4xpand(`$3'_gate(termcount,$4)) with .Out at \ 0.5 + (jog/2*(termcount+3)+AND_wd*L_unit,0) Out: Here linethick = lineth # Connect 2nd-layer gates to the output gate CLVectorConnect(G,termcount,OP) # Connect the inputs and negated inputs to # 2nd-layer gates Loopover_(`t_',`CLConnectInputs(G`'m4Lx,t_)',terms) # Clean up Loopover_(`t_',`CLDeleteLogDefs(t_)',terms) ') `CLVectorConnect(number of 2nd layer gates, common 2nd layer gate name, output gate name) Connect the 2nd-layer gate outputs to the output gate inputs' define(`CLVectorConnect', `for_(1,`$2',1, `line from `$1'm4x.Out right `$3'.In1.x-`$1'm4x.Out.x \ - jog/2*(`$2'+1-abs(2*m4x-`$2'-1)) \ then down `$1'm4x.Out.y - `$3'.In`'m4x.y then to `$3'.In`'m4x ')') Draw and label a non-inverted input define(`CLDrawIn', `PrevInput: PrevInput+(inputsep,0) In`'$1: PrevInput "$$1$" ljust at PrevInput # Maybe labels should be done externally Int`'$1: PrevInput define(D`'$1)') Draw and label an inverted input define(`CLDrawNotIn', `PrevInput: PrevInput+(inputsep,0) In`'$1: PrevInput "$$1$" ljust at PrevInput # Maybe labels should be done externally line down_ 2*jog from PrevInput linethick = gatelineth NOT_gate InNt`'$1: Here linethick = lineth define(D`'$1)') Draw and label an input that is required both inverted and uninverted. define(`CLDrawInNotIn', `PrevInput: PrevInput+(inputsep,0) In`'$1: PrevInput "$$1$" ljust at PrevInput # Maybe labels should be done externally line from PrevInput down jog Int`'$1: dot PrevInput: PrevInput+(inputsep,0) line to (PrevInput,Here) then down_ jog linethick = gatelineth NOT_gate linethick = lineth InNt`'$1: Here define(D`'$1)') `CLvarloop(`var',ifnotnegated,ifnegated,term) Loop over term variables performing actions' define(`CLvarloop',`ifelse(`$4',,,substr(`$4',0,1),~, `define(`$1',substr($4,1,1)) $3 CLvarloop(`$1',`$2',`$3',substr($4,2))', `define(`$1',substr($4,0,1)) $2 CLvarloop(`$1',`$2',`$3',substr($4,1))')')') Count gate inputs and mark last appearance define(`CLCountinputs',`CLvarloop(`v_', `define(`incount',incr(incount)) define(Last`'v_,`$1')', `define(`incount',incr(incount)) define(LastN`'v_,`$1')',$2)') Draw a 2nd layer gate define(`CLDrawLayerGate', `define(`incount',0) dnl CLCountinputs($1,$4) dnl ifelse(incount,1, `LastGateSE: LastGateSE-(0,jog) $1: [ In1:Here; line right AND_wd*L_unit; Out: Here] \ with .Out at LastGateSE', `LastGateSE: LastGateSE-(0,jog+AND_ht*L_unit) linethick = gatelineth $1: m4xpand(`$2'_gate(incount,$3)) with .se at LastGateSE linethick = lineth ')') Connect this gate to its input lines define(`CLConnectInputs',`define(`innum',0) CLvarloop(`v_', `define(`innum',incr(innum)) line from `$1'.In`'innum to (In`'v_,`$1'.In`'innum)dnl ifelse(`$1',m4xpand(Last`'v_),`then to In`'v_',`; dot')', `define(`innum',incr(innum)) line from `$1'.In`'innum to (InNt`'v_,`$1'.In`'innum)dnl ifelse(`$1',m4xpand(LastN`'v_), `then to InNt`'v_', `; dot')',$2)') Delete definitions to allow more than one circuit per diagram define(`CLDeleteLogDefs',`CLvarloop(`v_', `undefine(Last`'v_) undefine(D`'v_) undefine(X`'v_)', `undefine(LastN`'v_) undefine(D`'v_) undefine(XN`'v_)',$1)') Thanks to Alexander Ray for suggesting the need for something like these macros ########################################################################### divert(0)dnl linethick = lineth [ CanLogic(AND,,OR,,abcd,~ba,c,d~a) #; line right jog from Out "$f$" above ] {`"\tt CanLogic(AND,,OR,,abcd,\char126{}ba,c,d\char126{}a)"' \ at last [].s -(0,11bp__)} [ CanLogic(OR,N,NAND,,ab~c,a~bc,ac,~d) #; line right jog from Out "$f$" above ] with .sw at last [].se+(0.5,0) {`"\tt CanLogic(OR,N,NAND,,ab\char126{}c,a\char126{}bc,ac,\char126{}d)"' \ at last [].s - (0,11bp__)} .PE