1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
.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_',`varloop(`v_',`define(X`'v_)',`define(XN`'v_)',t_)',terms)
# Draw the inputs with NOT gates as necessary
PrevInput: Here-(inputsep,0)
Loopover_(`t_',`varloop(`v_',
`ifdef(D`'v_,,`ifdef(XN`'v_,`DrawInNotIn(v_)',`DrawIn(v_)')')',
`ifdef(D`'v_,,`ifdef(X`'v_,`DrawInNotIn(v_)',`DrawNotIn(v_)')')', t_)',
terms)
# Draw 2nd-layer gates
right_
LastGateSE: PrevInput+(5*jog,-(AND_wd*L_unit*1.5)) dnl
Loopover_(`t_',
`define(`termcount',m4Lx)DrawLayerGate(G`'termcount,$1,$2,t_)',
terms)
# Draw output gate
linethick = gatelineth
OP: m4xpand(`$3'_gate(termcount,$4)) with .Out at \
0.5<G1.Out,G`'termcount.Out> + (jog/2*(termcount+3)+AND_wd*L_unit,0)
Out: Here
linethick = lineth
# Connect 2nd-layer gates to the output gate
VectorConnect(G,termcount,OP)
# Connect the inputs and negated inputs to
# 2nd-layer gates
Loopover_(`t_',`ConnectInputs(G`'m4Lx,t_)',terms)
# Clean up
Loopover_(`t_',`DeleteLogDefs(t_)',terms)
')
`VectorConnect(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(`VectorConnect',
`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(`DrawIn',
`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(`DrawNotIn',
`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(`DrawInNotIn',
`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)')
`varloop(`var',ifnotnegated,ifnegated,term)
Loop over term variables performing actions'
define(`varloop',`ifelse(`$4',,,substr(`$4',0,1),~,
`define(`$1',substr($4,1,1)) $3
varloop(`$1',`$2',`$3',substr($4,2))',
`define(`$1',substr($4,0,1)) $2
varloop(`$1',`$2',`$3',substr($4,1))')')')
Count gate inputs and mark last appearance
define(`Countinputs',`varloop(`v_',
`define(`incount',incr(incount)) define(Last`'v_,`$1')',
`define(`incount',incr(incount)) define(LastN`'v_,`$1')',$2)')
Draw a 2nd layer gate
define(`DrawLayerGate',
`define(`incount',0) dnl
Countinputs($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(`ConnectInputs',`define(`innum',0) varloop(`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(`DeleteLogDefs',`varloop(`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
|