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
159
|
.PS
#CanLogic
ifdef(`L_unit',,`include(liblog.m4)')
log_init(svg_font(sans-serif,11bp__))
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
LastInput: 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: LastInput+(5*jog,-(AND_wd*L_unit*1.5))
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<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
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',
`LastInput: LastInput+(inputsep,0)
In`'$1: LastInput
"svg_it($1)" ljust at LastInput # Maybe labels should be done externally
Int`'$1: LastInput
define(D`'$1)')
Draw and label an inverted input
define(`CLDrawNotIn',
`LastInput: LastInput+(inputsep,0)
InN`'$1: LastInput
"svg_it($1)" ljust at LastInput # Maybe labels should be done externally
line down_ 2*jog from LastInput
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',
`LastInput: LastInput+(inputsep,0)
In`'$1: LastInput
"svg_it($1)" ljust at LastInput # Maybe labels should be done externally
line from LastInput down jog
Int`'$1: dot
LastInput: LastInput+(inputsep,0)
line to (LastInput,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)
CLCountinputs($1,$4)
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,a~b,c,~ad) #; line right jog from Out "svg_it(f)" above
]
{`"CanLogic(AND,,OR,,abcd,a~b,c,~ad)"' 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)
{`"CanLogic(OR,N,NAND,,ab~c,a~bc,ac,~d)"' at last [].s - (0,11bp__)}
command "</g>" # end font
.PE
|