summaryrefslogtreecommitdiff
path: root/graphics/circuit_macros/liblog.m4
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/circuit_macros/liblog.m4')
-rw-r--r--graphics/circuit_macros/liblog.m488
1 files changed, 47 insertions, 41 deletions
diff --git a/graphics/circuit_macros/liblog.m4 b/graphics/circuit_macros/liblog.m4
index 52e2d116b2..67b9a78773 100644
--- a/graphics/circuit_macros/liblog.m4
+++ b/graphics/circuit_macros/liblog.m4
@@ -1,7 +1,7 @@
divert(-1)
liblog.m4 Logic gates
-* Circuit_macros Version 10.2, copyright (c) 2023 J. D. Aplevich under *
+* Circuit_macros Version 10.3, copyright (c) 2023 J. D. Aplevich under *
* the LaTeX Project Public Licence in file Licence.txt. The files of *
* this distribution may be redistributed or modified provided that this *
* copyright notice is included and provided that modifications are clearly *
@@ -648,7 +648,7 @@ define(`Demux',`[
`$6']')
###########################################################################
- Autogate allowable functions (plus the ~ operator)
+ AutoGate allowable functions (plus the ~ operator)
define(`And',`_AutoGate(AND,$@)')
define(`Or',`_AutoGate(OR,$@)')
define(`Not',`_AutoGate(NOT,$@)')
@@ -677,31 +677,34 @@ define(`autovsep',`L_unit') # vertical separation between input gates
Draw the gate with input sublayer Sg containing
gates G1, G2, ...
-define(`AutoGate',`[ pushdef(`m4nargs',0)dnl
+define(`AutoGate',`[
lu = L_unit define(`m4dirt',m4_dir_)
dnl Count the arguments (inputs) (could use $# )
+ pushdef(`m4nargs',0)dnl
Loopover_(`arg',`define(`m4nargs',incr(m4nargs))',shift($@))dnl
+ ifinstr(`$2',[,`define(`m4nargs',decr(m4nargs))dnl
+ define(`m4PN',substr(`$2',1,eval(len(`$2')-2)))')
`#' m4Delch(`$1') gate(m4nargs)
# Draw the gate
linethick = gatelineth
ifelse(m4Delch(`$1'),NOT,`Q: NOT_gate()',
m4Delch(`$1'),BUFFER,`Q: BUFFER_gate()',
- `Q: m4Delch($1)_gate(m4nargs)') `#' End Q
+ `Q: m4Delch(`$1')_gate(ifinstr(`$2',[,m4PN,m4nargs))') `#' End Q
linethick = lineth
ifelse(substr(m4Delch(`$1'),0,1),N,
`Out: Q.Out',
`line thick lineth from Q.Out m4dirt N_diam*L_unit; Out: Here')
pushdef(`AutoOutNames',m4Path.Out)
T: ifelse(m4dirt,right,`Q.w-(2*lu,0)',`Q.e+(2*lu,0)')
-# Sublayer Sg containing gates G1, G2,... with
-# output vertical median at the height of Q.c
+# Sublayer Sg containing gates or vars G1, G2,...
+# with output vertical median at the height of Q.c
Sg: [ pushdef(`m4_nct',0)dnl
pushdef(`m4Path',m4Path.Sg)dnl
Loopover_(`arg',
`define(`m4_nct',incr(m4_nct))dnl
-# Variable or a sublayer gate
-# Inputs are labelled In<var>_N or In<var>_X
-# Remove initial white space; detect a name or gate
+dnl Variable or a sublayer gate
+dnl Inputs are labelled In<var>_N or In<var>_X
+dnl Remove initial white space; detect a name or gate
pushdef(`m4Path',m4Path.G`'m4_nct)dnl
m4ifboolvar_(arg,
`G`'m4_nct: [dnl
@@ -711,13 +714,13 @@ dnl Count the arguments (inputs) (could use $# )
In`'m4xg`'_N: Here',
`pushdef(`m4InNames',m4Path.In`'arg`'_X)define(X_`'arg)dnl
In`'arg`'_X: Here ')
- Out: Here ] dnl
- ht ifelse(m4nargs,1,`2*autovsep',`abs(Q.In1.y-Q.In2.y)-autovsep')',
+ Out: Here ] ht \
+ ifelse(m4nargs,1,`2*autovsep',`abs(Q.In1.y-Q.In2.y)-autovsep')',
`pushdef(`AutoOutNames',m4Path.Out)dnl
G`'m4_nct: m4Delch(arg)') ifelse(m4_nct,1,,`ifelse(m4dirt,right, \
`with .ne at last [].se',`with .nw at last [].sw')+(0,-autovsep)')
- popdef(`m4Path') ',
- shift($@))
+ popdef(`m4Path') ',
+ ifinstr(`$2',[,`shift(shift($@))',`shift($@)'))
MidOut: 0.5 between G`'eval((m4_nct+1)/2).Out and G`'eval((m4_nct+2)/2).Out
popdef(`m4_nct')dnl
popdef(`m4Path')dnl
@@ -725,7 +728,7 @@ dnl Count the arguments (inputs) (could use $# )
# Draw the connecting lines
define(`m4hhv',`(m4nargs-1)/2')dnl
ifelse(m4dirt,right,
- `for_(1,m4nargs,1,`line thick lineth from Q.In`'m4x \
+ `for_(1,m4nargs,1,`ifelse(m4x,1,,` ')line thick lineth from Q.In`'m4x \
left Q.In`'m4x.x-T.x+(m4hhv-abs(m4x-m4hhv-1))*lu \
then up Sg.G`'m4x.Out.y-Q.In`'m4x.y \
then to Sg.G`'m4x.Out')',
@@ -753,7 +756,7 @@ ifinstr(`$2',N,
NOT_gate
linethick = lineth
InNt`'$1: Here',
- `line thick lineth from PrevInput ifdef(`m4LI',m4_dir_,down) dimen_/4
+ ` line thick lineth from PrevInput ifdef(`m4LI',m4_dir_,down) dimen_/4
Int`'$1: Here')
m4xpand(m4dirt`'_)
')
@@ -839,23 +842,22 @@ define(`Autologic',
Function tree i is drawn by the `AutoGate' macro.
'
define(`Autologix',
-`[ # Auto logix
+`[ `# Autologix'
dnl Split arg1 into FunctionSpecs
undefine(`m4BooleanR')stacksplit_(`m4BooleanR',`$1',;)dnl
dnl
ifinstr(`$2',L,`define(`m4LI')',`undefine(`m4LI')')dnl
undefine(`m4InNames')undefine(`AutoOutNames')define(`m4Path',)dnl
- define(`m4nbf',0)undefine(`m4BooleanFn')undefine(`m4locattr')dnl
-dnl Separate functions from location attributes
+ define(`m4nbf',0)undefine(`m4BooleanFn')undefine(`m4posattr')dnl
+dnl Separate functions from position attributes
stackexec_(`m4BooleanR',,
`define(`m4nbf',incr(m4nbf))define(`m4xi',regexp(m4BooleanR,[a-zA-Z_~]))dnl
ifinstr(m4BooleanR,@,`define(`m4xc',index(m4BooleanR,@))dnl
pushdef(`m4BooleanFn',substr(m4BooleanR,m4xi,eval(m4xc-m4xi)))dnl
- pushdef(`m4locattr',substr(m4BooleanR,incr(m4xc)))',
+ pushdef(`m4posattr',substr(m4BooleanR,incr(m4xc)))',
`pushdef(`m4BooleanFn',substr(m4BooleanR,m4xi))dnl
- pushdef(`m4locattr')')dnl
+ pushdef(`m4posattr')')dnl
')dnl
-dnl
dnl Sublayer of functions, outputs Out1, Out2,..
pushdef(`m4Path',ifelse(m4Path,,,m4Path.)Fx)
Fx: [ define(`m4fno',0)dnl
@@ -867,18 +869,18 @@ dnl
dnl Simple variable or gate
m4ifboolvar_(m4BooleanFn,
`Tx`'m4fno: [ifelse(substr(m4BooleanFn,0,1),~,
- `define(`m4xg',substr(m4BooleanFn,1))dnl
- pushdef(`m4InNames',m4Path.In`'m4xg`'_N)define(N_`'m4xg)
- In`'m4xg`'_N: Here',
- `pushdef(`m4InNames',m4Path.In`'m4BooleanFn`'_X)dnl
- define(X_`'m4BooleanFn)dnl
- In`'m4BooleanFn`'_X: Here'); Out: Here ] ht 2*autovsep',
- `Tx`'m4fno: m4Delch(m4BooleanFn)') ifelse(m4fno,1,,
- `ifelse(m4locattr,,`with .n`'ifinstr(`$2',M,w,e) \
- at Tx`'eval(m4fno-1).s`'ifinstr(`$2',M,w,e)+(0,-dimen_/4)',
- m4locattr)')dnl
+ `define(`m4xg',substr(m4BooleanFn,1))dnl
+ pushdef(`m4InNames',m4Path.In`'m4xg`'_N)define(N_`'m4xg)
+ In`'m4xg`'_N: Here',
+ `pushdef(`m4InNames',m4Path.In`'m4BooleanFn`'_X)dnl
+ define(X_`'m4BooleanFn)dnl
+ In`'m4BooleanFn`'_X: Here'); Out: Here ] ht 2*autovsep',
+ `Tx`'m4fno: m4Delch(m4BooleanFn)') ifelse(m4posattr,,
+ `ifelse(m4fno,1,,`with .n`'ifinstr(`$2',M,w,e) \
+ at Tx`'eval(m4fno-1).s`'ifinstr(`$2',M,w,e)+(0,-dimen_/4)')',
+ m4posattr) dnl
pushdef(`AutoOutNames',m4Path.Out)dnl
- popdef(`m4locattr') `#' End Tx`'m4fno
+ popdef(`m4posattr') `#' End Tx`'m4fno
popdef(`m4Path')dnl
dnl Functions drawn
dnl Out and Out1, Out2, ...
@@ -933,28 +935,32 @@ PrevInput: ifdef(`m4LI',dnl
stackexec_(`m4r',,`undefine(N_`'m4r)undefine(X_`'m4r)')
dnl
dnl Show the internal inputs in comment lines
-`# Internal input names' (m4nargs):dnl
-stackexec_(`m4InNames',`m4R',`
-`#' m4InNames')
-stackexec_(`m4R',`m4InNames')
+dnl `# Internal input names' (m4nargs):dnl
+dnl stackexec_(`m4InNames',`m4R',`
+dnl `#' m4InNames')
+dnl stackexec_(`m4R',`m4InNames')
dnl
# Promote the In and Out locations to the top level
- define(`m4ix',0)dnl
- stackexec_(`AutoOutNames',,`define(`m4ix',incr(m4ix))
- Out`'m4ix: AutoOutNames')
+`# Internal gate input labels' (m4nargs):dnl
define(`m4ix',0)dnl
stackexec_(`m4InNames',`m4R',`define(`m4ix',incr(m4ix))
In`'m4ix: m4InNames')
stackexec_(`m4R',`m4InNames')
+`# Internal gate output labels (there may be duplicate locations)':dnl
+ define(`m4ix',0)define(`m4lastout')dnl
+ stackexec_(`AutoOutNames',,
+ `ifelse(AutoOutNames,m4lastout,,`define(`m4ix',incr(m4ix))
+ Out`'m4ix: AutoOutNames define(`m4lastout',AutoOutNames)')')
# Connect the gates to the inputs and clean up
ifinstr(`$2',N,,
`m4AutoConnex(Fx,`m4InNames',ifdef(`m4LI',`ifinstr(`$2',V,Top,Bot)',Bot))')
stackexec_(`m4TAL',,
`define(`m4bn',basename_(m4TAL))undefine(Bot`'m4bn)undefine(Top`'m4bn)')
-# Define the inputs
+# Define the outputs
ifelse(m4nbf,1,`Out: Fx.Out')
for_(1,m4nbf,1,`Out`'m4x: Fx.Out`'m4x')
- `$3' ] ')
+ `$3' `# End Autologix'
+ ] ')
define(`m4AutoConnex',`define(`m4cx',0)dnl
define(`m4ltn',`substr(`$2',decr(len(`$2')))')dnl