summaryrefslogtreecommitdiff
path: root/graphics/circuit_macros/examples/dpv/CanLogicDPV.m4
blob: b6c1d02e2f2b79655fdd726fb0d0fa4e33a319ea (plain)
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_',`varloop(`v_',`define(X`'v_)',`define(XN`'v_)',t_)',terms)
#                               Draw the inputs with NOT gates as necessary
  LastInput: 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: LastInput+(5*jog,-(AND_wd*L_unit*1.5))
  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',
 `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(`DrawNotIn',
 `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(`DrawInNotIn',
 `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)')
                               `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)
  Countinputs($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(`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,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