diff options
Diffstat (limited to 'graphics/circuit_macros/liblog.m4')
-rw-r--r-- | graphics/circuit_macros/liblog.m4 | 88 |
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 |