[Arya Raychaudhuri's one-man enterprise that believes in Always Move Ahead with New Ideas]
"home" , "code snippets", "via check add paper" "backpage" buttons on the left side, to select a specific page
[Norton Security Seal is now discontinued by Yahoo for Site Solution based websites, but moved from http to https]
the pages are best viewed through internet explorer
WordPress
BLOG PAGE: blog/
[kept inactive to avoid spam]
This is the age of search engines - quickly search for entities and their inter-relationships. And, LVS Debug is all about analyzing netlists and gds/oasis layout databases, and finding their correspondences/matches/mismatches in the post-PD domain. So, much of the codes presented in the 'code snippets' page focus on searching and parsing these huge netlist and layout files, to extract the relevant information and their connection. The other important thing is the focus on revenue/jobs generating creative ideas - because if you cannot come up with new product ideas every now and then, what will you sell tomorrow, in the future? I have now transformed LVS DEBUG SOLUTIONS LLC into a multi-engineering concepts platform (please review the code snippets* pages under https://www.lvs-debug-solutions.com)
google email: arya.raychaudhuri@gmail.com
Please direct all official communications to
arya@lvs-debug-solutions.com, or call 408-480-1936
I typically don't answer calls from unknown callers, to avoid spam. If you are a serious caller, please leave voice or text message, or email...For text message from international locations, please use cellphone number as 1-408-480-1936
LVS DEBUG SOLUTIONS LLC
980 Kiely Blvd, Unit 308
Santa Clara, CA 95051
United States
ph: 1-408-480-1936
arya
Listing of the edits (in orange) used in edited subCkt query routine of Item#531, as used in Item#532
echo "}" >> tempTemp.dot;}
mysubPath=$2
mysub=`echo $mysubPath|awk '{print $NF}'`
subCkt_name=`echo $mysub|sed -e 's?\[?{?g' -e 's?\]?}?g'|sed -e 's?\_?\-?g'|sed -e 's?\#?\+?g'|sed -e 's?\%?\~?g'`
subCkt_path=`echo $mysubPath|sed -e 's?\[?{?g' -e 's?\]?}?g'|sed -e 's?\_?\-?g'|sed -e 's?\#?\+?g'|sed -e 's?\%?\~?g'`
for ll in `grep -v -i -f grepf $1 |
::::::::::::::::::::::
:::::::::::::::::::::
printf $(i) " " $(i-1) " "; printf $2 " " $1 " " $NF "\n"}'|
grep "$subCkt_path"|
sed -e 's?{?\[?g' -e 's?}?\]?g'|sed -e 's?\-?\_?g'|sed -e 's?\+?\#?g'|sed -e 's?\~?\%?g'`;
echo $inst_chain;
Listing of the codes used in subCkt query in Item#531
#! /usr/bin/bash
## Arya, Apr 07, 2022,
## Usage: ./flatten_func.full.sh <fllattened_netlist> <query_subCkt_in_quotes> <full_or_inst_dotFile>
## e.g., ./subCktQ.sh test3sq.flt.net 'mysub[3]' test3sq.full.dot
## This shell routine requires the python script "show_path.py" to exist in the current directory
pin_extract(){ pin_name=`echo $px|sed -e 's?%??'|sed -e 's?\_? ?g'|
awk '{print $1}'|sed -e 's?{?\[?g' -e 's?}?\]?g'|
sed -e 's?\-?\_?g'|sed -e 's?\+?\#?g'|sed -e 's?\~?\%?g'`;
pin_from_lx=`echo $px|sed -e 's?%??'|sed -e 's?\_? ?g'|
sed -e 's?(? ?g' -e 's?)? ?g' |
awk '{for (i=3; i<=NF; i=i+2) printf $i " " $(i-1) " "}'|
sed -e 's?{?\[?g' -e 's?}?\]?g'|sed -e 's?\-?\_?g'|
sed -e 's?\+?\#?g'|sed -e 's?\~?\%?g'`;
if [[ $pin_from_lx == "" ]];
then pin_from=`echo $inst_chain|
awk '{print $1}'`; else pin_from=`echo $inst_chain |
sed -e "s?$pin_from_lx??"|awk '{print $1}'`;
fi;}
pins_enter(){ sed -i "s?^}??" tempTemp.dot; pin_label="PINS OF $mysub:\n";
for px in `echo $pins`; do if [[ `echo $px |grep %` ]];
then pin_extract $px;
else pin_extract $px;
pin_from=`echo $inst_chain|awk '{print $NF}'`;
fi;
pin_label=`echo $pin_label`" "$pin_name" from "$pin_from"\n";
done;
echo "BB[shape=none, fontcolor=black, label=\"$pin_label\"]" >> tempTemp.dot;
echo "}" >> tempTemp.dot;}
mysub=$2
subCkt_name=`echo $mysub|sed -e 's?\[?{?g' -e 's?\]?}?g'|sed -e 's?\_?\-?g'|sed -e 's?\#?\+?g'|sed -e 's?\%?\~?g'`
for ll in `grep -v -i -f grepf $1 |
grep -v -i EnDS|grep -v -i 'REC_DEPTH'|sed -e 's?^[\*]*??' |
awk '{IGNORECASE=1;
if ($1 !~ /subckt/) printf $1;
else for (i=2; i<=NF; i=i+1) printf " " $i;printf "\n"}'|
awk '{IGNORECASE=1;
if ($1 ~ /@x/) printf $1;
else print $0}'|
sed -e 's? ?\,?g'`;
do llx=`echo $ll|sed -e 's?,? ?g'|
grep ' '$subCkt_name' '`; echo "#####" $llx; inst_chain=`echo $llx|
sed -e 's?@??g'|
awk '{printf $1 " " $2}'|
sed -e 's?\_? ?'g|awk '{IGNORECASE=1; if ($1 ~ /^x/) print $0}'|
sed -e 's?(? ?g' -e 's?)? ?g'|
awk '{for(i=4; i<=NF-1; i=i+2)
printf $(i) " " $(i-1) " "; printf $2 " " $1 " " $NF "\n"}'|
sed -e 's?{?\[?g' -e 's?}?\]?g'|sed -e 's?\-?\_?g'|sed -e 's?\+?\#?g'|sed -e 's?\~?\%?g'`;
echo $inst_chain;
if [[ $inst_chain != "" ]];
then cp $3 tempTemp.dot
temp_dot="tempTemp.dot"
pins=`echo $llx|awk '{for (i=3; i<=NF; i=i+1) printf $i " "; printf "\n"}'`
pins_enter $pins
./show_path.py $temp_dot "$inst_chain";
##echo "enter Y to continue:"
##read cont_var
##if [[ $cont_var != 'Y' ]]; then exit; fi
fi;
done
The edits (added code in 'orange') to the show_path.py ((tem#518) run as a subprocess in the above shell routine :
-----------------------------------------
import magic
from pathlib import Path
import random
:::::::
:::::::
for jj in range(len(editDotLines(myPath_lst, dotLines))):
Nch=fprintf(dotF, "%s" % dotLines[jj])
dotF.close()
subprocess.run(["dot", "-Tjpg", dot_filename, "-o", jpg_filename])
xx=random.choice([50, 100, 150, 200, 250])
yy=random.choice([25, 50, 75, 100, 125])
xvcmd = '/usr/bin/xview -geometry 2000x2000+{0}+{1} {2} >/dev/null &'.format(xx,yy,jpg_filename)
## xvcmd = '/usr/bin/xview {0} >/dev/null &'.format(jpg_filename)
subprocess.run(xvcmd, shell=True)
::::::::::::::
::::::::::::::
while len(pathString.split()) > 0:
mainProg(sys.argv[1], pathString)
DONTrepeat = 1
if DONTrepeat: break
pathString = input("Enter next Path to plot, Press <return> to exit: ")
if pathString.startswith(('"',"'")) and pathString.endswith(('"',"'")):
pathString = pathString[1:-1]
Listing of the shell code to unlatten the pendant devices of a netlist, given its fully flattened edges table, as used in Item#530
cat devices_no_flatten.sh
-->
#! /usr/bin/bash
## Usage: ./devices_no_flatten.sh <full_flattened_edges_table>
## Example: ./devices_no_flatten.sh bidirShift.full.edge_table
## Arya, April 02, 2022
temp_edges=`echo $1`'_tmp'
reduced_edges=`echo $1`'_red'
reduced_dot=`echo $1`'_red.dot'
reduced_jpg=`echo $1`'_red.jpg'
echo 's?Mos[0-9]* ?Mos ?' > sedf
echo 's?Diode[0-9]* ?Diode ?' >> sedf
echo 's?Bipolar[0-9]* ?Bipolar ?' >> sedf
echo 's?Res[0-9]* ?Res ?' >> sedf
echo 's?Cap[0-9]* ?Cap ?' >> sedf
sed -f sedf $1 |sort|uniq > $temp_edges
let ii=0;for ll in `cat $temp_edges|sed -e 's? ?@?g'`;do col2=`echo $ll|sed -e 's?@? ?g' |awk '{print $2}'`; if [[ $col2 == 'Res' || $col2 == 'Mos' || $col2 == 'Diode' || $col2 == 'Cap' || $col2 == 'Bipolar' ]]; then let ii=ii+1; col2x=$col2`echo $ii`; echo $ll|sed -e "s?$col2?$col2x?"|sed -e 's?@? ?g'; else echo $ll|sed -e 's?@? ?g';fi; done > $reduced_edges
rm -f $temp_edges
./edges_to_dot.sh $reduced_edges $reduced_dot
dot -Tjpg $reduced_dot -o $reduced_jpg
xview $reduced_jpg
Listing of the Net query python code discussed in Item#528
cat netQ.py
-->
#! /usr/bin/env python3
### Arya, March 25, 2022, edited March31, 2022
## Usage: netQ.py <minimal_full_treeFile> <flattened_netlist> <dot_file_of_full_tree>
## Example run command : netQ.py test2sq.full.tree test2sq.flt.net test2sq.full.dot
import sys
import os
import re
import subprocess
import time
import magic
from pathlib import Path
def printf(args):
N_ = sys.stdout.write(args)
return N_
def fprintf(fH, args):
N_ = fH.write(args)
return N_
def badTreeFile(badFile):
print(f'{badFile} does not contain valid tree')
print('Usage: ./netQ.py <minimal_full_treeFile> <flattened_netlist> <dot_file_of_full_tree>')
exit()
def usageText():
print('Usage: ./netQ.py <minimal_full_treeFile> <flattened_netlist> <dot_file_of_full_tree>')
exit()
def devTerm(devType, devName,nt, devices):
devSn=int(re.sub(devType,'', devName, re.IGNORECASE))
devices_lst= devices[devSn-1].split()
if debug: print(devices_lst)
txEd=[]
for ii in range(nt):
jj = ii+1
tx = re.sub('_', '@', devices_lst[jj])
txEd.append(tx.replace('{','[').replace('}',']').replace('-','_').replace('+','#').replace('~','%'))
return txEd
def getTermNet(Termflat, InstSubDict):
TermSplit_lst = Termflat.split('@')
nlen = len(TermSplit_lst)
if nlen == 1:
keyval = 'null'
else:
keyval = TermSplit_lst[nlen -1]
if debug: print(keyval)
if debug: print(InstSubDict)
subName= InstSubDict[keyval]
netName = TermSplit_lst[0]
returnVal = ' ' + netName + ' from ' + subName
return returnVal
def check_args(argv):
global treeLines, dotFile, fltFile, dev_ids, topsub
nArgs = len(argv)
if nArgs != 4:
print('Too many or too few arguments')
print('Usage: ./netQ.py <minimal_full_treeFile> <flattened_netlist> <dot_file_of_full_tree>')
exit()
fltFile = argv[2]
path_to_fltNet = Path(argv[2])
if (not path_to_fltNet.is_file()) or (magic.from_file(argv[2], mime=True) != 'text/plain'):
print(f'{argv[2]} does not exist OR not a proper ascii tree')
usageText()
else:
oscmd='grep -i -m 1 ^.subckt ' + argv[2] + '|awk \'{print $2}\''
topsub = os.popen(oscmd).read().strip()
if not topsub :
print('The flattened netlist does not have any subckts')
usageText()
if debug: print('Top Level SubCkt =', topsub)
treeFile = argv[1]
path_to_tree = Path(argv[1])
if (not path_to_tree.is_file()) or (magic.from_file(argv[1], mime=True) != 'text/plain'):
print(f'{argv[1]} does not exist OR not a proper ascii tree')
usageText()
else:
treeLines = []
dev_ids=[]
with open(treeFile, 'r') as f:
for line in f:
lx = line.strip()
dev_ids.append(lx.split()[-1])
treeLines.append(lx)
f.close()
if re.match(topsub, treeLines[0]):
if not re.match('Mos', dev_ids[0], re.IGNORECASE):
if not re.match('Res', dev_ids[0], re.IGNORECASE):
if not re.match('Cap', dev_ids[0], re.IGNORECASE):
if not re.match('Diode', dev_ids[0], re.IGNORECASE):
if not re.match('Bipolar', dev_ids[0], re.IGNORECASE):
badTreeFile(argv[1])
else:
badTreeFile(argv[1])
if debug: print('Valid Device Ids =', dev_ids)
dotFile = argv[3]
path_to_dot = Path(argv[3])
oscmd = "head -1 " + argv[3]
if (not path_to_dot.is_file()) or (magic.from_file(argv[3], mime=True) != 'text/plain') or ('digraph {' != (os.popen(oscmd).read()).strip()):
print(f'{argv[3]} does not exist OR not a proper ascii dotFile')
usageText()
global debug
debug = 0
#print('Hi')
check_args(sys.argv)
devLines=[]
with open(fltFile, 'r') as f:
for line in f:
mm = re.match('^M', line, re.IGNORECASE)
cc = re.match('^c', line, re.IGNORECASE)
dd = re.match('^D', line, re.IGNORECASE)
rr = re.match('^R', line, re.IGNORECASE)
qq = re.match('^Q', line, re.IGNORECASE)
if mm or cc or dd or rr or qq:
devLines.append(line)
if debug: print(line)
f.close()
ix=0
topNets = []
for line in devLines:
if debug: print(line)
treeLine_lst = treeLines[ix].split()
subcktCalls = { 'null' : treeLine_lst[0] }
if debug: print(subcktCalls)
nstrt=0
for ii in range(nstrt,len(treeLine_lst)-4,2):
nextKey = treeLine_lst[ii+1] + "(" + treeLine_lst[ii] + ")"
subcktCalls[nextKey] = treeLine_lst[ii+2]
if debug: print(nextKey)
if debug: print('call seq hash')
if debug: print(subcktCalls)
if re.match('^M', line, re.IGNORECASE):
devStr = 'Mos'
nn =4
if re.match('^C', line, re.IGNORECASE):
devStr = 'Cap'
nn =2
if re.match('^R', line, re.IGNORECASE):
devStr = 'Res'
nn =2
if re.match('^Q', line, re.IGNORECASE):
devStr = 'Bipolar'
nn =3
if re.match('^D', line, re.IGNORECASE):
devStr = 'Diode'
nn =2
devId = devStr + str(ix+1)
devTerms = devTerm(devStr, devId, nn, devLines)
dev_ids[ix] = str(devTerms) + ' ' + dev_ids[ix]
if debug: print(dev_ids[ix])
for devTermx in devTerms:
if re.search(topsub, getTermNet(devTermx, subcktCalls), re.IGNORECASE):
if debug: print(getTermNet(devTermx, subcktCalls))
topNetName = getTermNet(devTermx, subcktCalls).split()[0]
if debug: print(topNetName)
if topNetName not in topNets: topNets.append(topNetName)
subcktCalls = {}
ix=ix+1
print('Your Top Level Nets Are: ', topNets)
plotnetName = input("Enter top level net name to get propagation for:")
print(plotnetName)
show_path_cmd = './show_path.py'
for devLineCand in dev_ids:
if plotnetName in devLineCand:
for treeLine in treeLines:
dmx = devLineCand.split()[-1]; tmx = treeLine.split()[-1];
if re.match(dmx, tmx, re.IGNORECASE) and re.match(tmx, dmx, re.IGNORECASE):
print(treeLine)
subprocess.run([ show_path_cmd, dotFile, treeLine])
dotFile = 'myPath_color_edited.dot'
dotLines=[]
with open('myPath_color_edited.dot', 'r') as f:
for line in f:
dotLines.append(line)
##printf(line)
f.close()
dotLines = dotLines[0:-1]
ZZ_node = 'ZZ[shape=rect, fontstyle=bold, fontsize=40, label="Net Propagation for ' + plotnetName + '"]\n'
ENDBRACE = '}\n'
dotLines.append(ZZ_node)
dotLines.append(ENDBRACE)
if debug: print(dotLines)
dot_filename = 'myPath_color_edited.dot'
jpg_filename = dot_filename.replace('dot', 'jpg')
FW = open(dot_filename, 'w')
for line in dotLines:
fprintf(FW,line)
FW.close()
subprocess.run(["dot", "-Tjpg", dot_filename, "-o", jpg_filename])
xvcmd = '/usr/bin/xview {0} >/dev/null &'.format(jpg_filename)
subprocess.run(xvcmd, shell=True)
-----------------------------------------------------------------------
The edits (added code in 'orange') to the show_path.py (beyond item#526 edit) run as a subprocess in the above python
for jj in range(len(editDotLines(myPath_lst, dotLines))):
Nch=fprintf(dotF, "%s" % dotLines[jj])
dotF.close()
return
subprocess.run(["dot", "-Tjpg", dot_filename, "-o", jpg_filename])
xvcmd = '/usr/bin/xview {0} >/dev/null &'.format(jpg_filename)
subprocess.run(xvcmd, shell=True)
Listing of the device query python code discussed in Item#526
cat devQ.py
-->
#! /usr/bin/env python3
### Arya, March 21, 2022, Apr 01, 2022
## Usage: devQ.py <device_Id> <minimal_full_treeFile> <flattened_netlist> <dot_file_of_full_tree>
## Example run command : devQ.py Cap10 test2sq.full.tree test2sq.flt.net test2sq.full.dot
import sys
import os
import re
import subprocess
import time
import magic
from pathlib import Path
def printf(args):
N_ = sys.stdout.write(args)
return N_
def fprintf(fH, args):
N_ = fH.write(args)
return N_
def badTreeFile(badFile):
print(f'{badFile} does not contain valid tree')
print('Usage: ./devQ.py <device_Id> <minimal_full_treeFile> <flattened_netlist> <dot_file_of_full_tree>')
exit()
def usageText():
print('Usage: ./devQ.py <device_Id> <minimal_full_treeFile> <flattened_netlist> <dot_file_of_full_tree>')
exit()
def devTerm(devType, devName,nt, devices):
devSn=int(re.sub(devType,'', devName, re.IGNORECASE))
devices_lst= devices[devSn-1].split()
if debug: print(devices_lst)
txEd=[]
for ii in range(nt):
jj = ii+1
tx = re.sub('_', '@', devices_lst[jj])
txEd.append(tx.replace('{','[').replace('}',']').replace('-','_').replace('+','#').replace('~','%'))
return txEd
def getTermNet(Termflat, InstSubDict):
TermSplit_lst = Termflat.split('@')
nlen = len(TermSplit_lst)
if nlen == 1:
keyval = 'null'
else:
keyval = TermSplit_lst[nlen -1]
if debug: print(keyval)
if debug: print(InstSubDict)
subName= InstSubDict[keyval]
netName = TermSplit_lst[0]
returnVal = ' ' + netName + ' from ' + subName
return returnVal
nArgs = len(sys.argv)
if nArgs != 5:
print('Too many or too few arguments')
print('Usage: ./devQ.py <device_Id> <minimal_full_treeFile> <flattened_netlist> <dot_file_of_full_tree>')
exit()
fltFile = sys.argv[3]
path_to_fltNet = Path(sys.argv[3])
if (not path_to_fltNet.is_file()) or (magic.from_file(sys.argv[3], mime=True) != 'text/plain'):
print(f'{sys.argv[3]} does not exist OR not a proper ascii tree')
usageText()
else:
oscmd='grep -i -m 1 ^.subckt ' + sys.argv[3] + '|awk \'{print $2}\''
topsub = os.popen(oscmd).read().strip()
if not topsub :
print('The flattened netlist does not have any subckts')
usageText()
print('Top Level SubCkt =', topsub)
treeFile = sys.argv[2]
path_to_tree = Path(sys.argv[2])
if (not path_to_tree.is_file()) or (magic.from_file(sys.argv[2], mime=True) != 'text/plain'):
print(f'{sys.argv[2]} does not exist OR not a proper ascii tree')
usageText()
else:
treeLines = []
dev_ids=[]
with open(treeFile, 'r') as f:
for line in f:
lx = line.strip()
dev_ids.append(lx.split()[-1])
treeLines.append(lx)
f.close()
if re.match(topsub, treeLines[0]):
if not re.match('Mos', dev_ids[0], re.IGNORECASE):
if not re.match('Res', dev_ids[0], re.IGNORECASE):
if not re.match('Cap', dev_ids[0], re.IGNORECASE):
if not re.match('Diode', dev_ids[0], re.IGNORECASE):
if not re.match('Bipolar', dev_ids[0], re.IGNORECASE):
badTreeFile(sys.argv[2])
else:
badTreeFile(sys.argv[2])
print('Valid Device Ids =', dev_ids)
dotFile = sys.argv[4]
path_to_dot = Path(sys.argv[4])
oscmd = "head -1 " + sys.argv[4]
if (not path_to_dot.is_file()) or (magic.from_file(sys.argv[4], mime=True) != 'text/plain') or ('digraph {' != (os.popen(oscmd).read()).strip()):
print(f'{sys.argv[4]} does not exist OR not a proper ascii dotFile')
usageText()
devId = sys.argv[1]
devId_not_found =1
for dId in dev_ids:
if re.match(devId, dId, re.IGNORECASE) and re.match(dId, devId, re.IGNORECASE):
devId = dId
devId_not_found =0
break
if devId_not_found:
print('Device Id not proper')
usageText()
global debug
debug = 0
##global f
##global stdout_default
##f = open(os.devnull, 'w')
##stdout_default = sys.stdout
##sys.stdout = f
treeLine = ""
for line in treeLines:
tmx = line.split()[-1];
if re.match(devId, tmx, re.IGNORECASE) and re.match(tmx, devId, re.IGNORECASE):
treeLine=line
if debug: print(treeLine)
treeLine_lst = treeLine.split()
if debug: print("TreeLine turned into a list: {}".format(treeLine_lst))
subcktCalls = { 'null' : treeLine_lst[0] }
if debug: print(subcktCalls)
nstrt=0
for ii in range(nstrt,len(treeLine_lst)-4,2):
nextKey = treeLine_lst[ii+1] + "(" + treeLine_lst[ii] + ")"
subcktCalls[nextKey] = treeLine_lst[ii+2]
if debug: print(nextKey)
if debug: print(subcktCalls)
devLines=[]
with open(fltFile, 'r') as f:
for line in f:
mm = re.match('^M', line, re.IGNORECASE)
cc = re.match('^c', line, re.IGNORECASE)
dd = re.match('^D', line, re.IGNORECASE)
rr = re.match('^R', line, re.IGNORECASE)
qq = re.match('^Q', line, re.IGNORECASE)
if mm or cc or dd or rr or qq:
devLines.append(line)
if debug: print(line)
f.close()
show_path_cmd = './show_path.py'
subprocess.run([ show_path_cmd, dotFile, treeLine])
dotLines=[]
with open('myPath_color_edited.dot', 'r') as f:
for line in f:
dotLines.append(line)
##printf(line)
f.close()
dotLines = dotLines[0:-1]
if debug: print(dotLines)
DQ_node = '"' + devId + '" [shape=diamond, width=1.5, fontname ="times-bold", fontcolor=red, label="'+devId+'"]\n'
dotLines.append(DQ_node);
XX_node = 'XX[shape=rect, color=white,label="CallSeq of ' + devId + ' (Below)"]\n'
YY_node = 'YY[shape=rect, color=white, label="Terminals Net Trace of ' + devId + ' (Above)"]\n'
ZZ_node = 'ZZ[shape=rect, fontstyle=bold, fontsize=40, label="Device Query Result for ' + devId + '"]\n'
ENDBRACE = '}\n'
#######################MOSFET######################
if re.match('Mos', devId, re.IGNORECASE):
devTerms = devTerm('Mos', devId, 4, devLines)
DD_node = 'DD[shape=oval ,fontcolor=red, label=' + '"' + 'dd:' + getTermNet(devTerms[0], subcktCalls) + '"]\n'
GG_node = 'GG[shape=oval ,fontcolor=red, label=' + '"' + 'gg:' + getTermNet(devTerms[1], subcktCalls) + '"]\n'
SS_node = 'SS[shape=oval ,fontcolor=red, label=' + '"' + 'ss:' + getTermNet(devTerms[2], subcktCalls) + '"]\n'
BB_node = 'BB[shape=oval ,fontcolor=red, label=' + '"' + 'bb:' + getTermNet(devTerms[3], subcktCalls) + '"]\n'
dotLines.append(XX_node); dotLines.append(YY_node); dotLines.append(BB_node); dotLines.append(SS_node);
dotLines.append(GG_node); dotLines.append(DD_node); dotLines.append(ZZ_node); dotLines.append(ENDBRACE) ;
if debug: print('dd =', getTermNet(devTerms[0], subcktCalls))
if debug: print('gg =', getTermNet(devTerms[1], subcktCalls))
if debug: print('ss =', getTermNet(devTerms[2], subcktCalls))
if debug: print('bb =', getTermNet(devTerms[3], subcktCalls))
#######################Diode########################
if re.match('Diode', devId, re.IGNORECASE):
devTerms = devTerm('Diode', devId, 2, devLines)
if debug: print('anode =', getTermNet(devTerms[0], subcktCalls))
if debug: print('cathode =', getTermNet(devTerms[1], subcktCalls))
ANODE_node = 'ANODE[shape=oval ,fontcolor=red, label=' + '"' + 'anode:' + getTermNet(devTerms[0], subcktCalls) + '"]\n'
CATHODE_node = 'CATHODE[shape=oval ,fontcolor=red, label=' + '"' + 'cathode:' + getTermNet(devTerms[1], subcktCalls) + '"]\n'
dotLines.append(XX_node); dotLines.append(YY_node);
dotLines.append(CATHODE_node); dotLines.append(ANODE_node); dotLines.append(ZZ_node); dotLines.append(ENDBRACE);
#######################Caps########################
if re.match('Cap', devId, re.IGNORECASE):
devTerms = devTerm('Cap', devId, 2, devLines)
if debug: print('Cplus =', getTermNet(devTerms[0], subcktCalls))
if debug: print('Cminus =', getTermNet(devTerms[1], subcktCalls))
CPLUS_node = 'CPLUS[shape=oval ,fontcolor=red, label=' + '"' + 'Cplus:' + getTermNet(devTerms[0], subcktCalls) + '"]\n'
CMINUS_node = 'CMINUS[shape=oval ,fontcolor=red, label=' + '"' + 'Cminus:' + getTermNet(devTerms[1], subcktCalls) + '"]\n'
dotLines.append(XX_node); dotLines.append(YY_node);
dotLines.append(CPLUS_node); dotLines.append(CMINUS_node); dotLines.append(ZZ_node); dotLines.append(ENDBRACE);
#######################Res########################
if re.match('Res', devId, re.IGNORECASE):
devTerms = devTerm('Res', devId, 2, devLines)
if debug: print('N1 =', getTermNet(devTerms[0], subcktCalls))
if debug: print('N2 =', getTermNet(devTerms[1], subcktCalls))
N1_node = 'N1[shape=oval ,fontcolor=red, label=' + '"' + 'N1:' + getTermNet(devTerms[0], subcktCalls) + '"]\n'
N2_node = 'N2[shape=oval ,fontcolor=red, label=' + '"' + 'N2:' + getTermNet(devTerms[1], subcktCalls) + '"]\n'
dotLines.append(XX_node); dotLines.append(YY_node);
dotLines.append(N1_node); dotLines.append(N2_node); dotLines.append(ZZ_node); dotLines.append(ENDBRACE);
#######################Bipolar######################
if re.match('Bipolar', devId, re.IGNORECASE):
devTerms = devTerm('Bipolar', devId, 3, devLines)
if debug: print('Coll =', getTermNet(devTerms[0], subcktCalls))
if debug: print('Base =', getTermNet(devTerms[1], subcktCalls))
if debug: print('Emit =', getTermNet(devTerms[1], subcktCalls))
COLL_node = 'COLL[shape=oval ,fontcolor=red, label=' + '"' + 'Coll:' + getTermNet(devTerms[0], subcktCalls) + '"]\n'
BASE_node = 'BASE[shape=oval ,fontcolor=red, label=' + '"' + 'Base:' + getTermNet(devTerms[1], subcktCalls) + '"]\n'
EMIT_node = 'EMIT[shape=oval ,fontcolor=red, label=' + '"' + 'Emit:' + getTermNet(devTerms[2], subcktCalls) + '"]\n'
dotLines.append(XX_node); dotLines.append(YY_node);
dotLines.append(COLL_node); dotLines.append(BASE_node); dotLines.append(EMIT_node);
dotLines.append(ZZ_node);dotLines.append(ENDBRACE);
combined_dotF = 'device_query.dot'
FW = open(combined_dotF, 'w')
for line in dotLines:
fprintf(FW,line)
FW.close()
jpg_filename = 'device_query.jpg'
subprocess.run(["dot", "-Tjpg", combined_dotF, "-o", jpg_filename])
xvcmd = '/usr/bin/xview {0} >/dev/null &'.format(jpg_filename)
subprocess.run(xvcmd, shell=True)
The edits (added code in 'orange') to the show_path.py ((tem#518) run as a subprocess in the above python:
while len(pathString.split()) > 0:
mainProg(sys.argv[1], pathString)
DONTrepeat = 1
if DONTrepeat: break
pathString = input("Enter next Path to plot, Press <return> to exit: ")
if pathString.startswith(('"',"'")) and pathString.endswith(('"',"'")):
pathString = pathString[1:-1]
Listing of the updated spice netlist flattener bash script discussed in Item#519
cat flatten_func.full.sh
-->
#! /usr/bin/bash
## Arya, Oct 27, 2012, edited Oct 31, 2012
## Arya, Aug 07, 2021, slight edit
## Arya, March 08, 2022, edits
## Usage: ./flatten_func.full.sh <spice_netlist> <topSubCkt>|tee <fllattened_netlist>
## e.g., ./flatten_func.full.sh test1sq.net toplevel|tee test1sq.flt.net
## The flattened netlist at this stage is raw,
## and contains shifted special chars, etc.
## To get a cleaned up flattened netlist (a device netlist),
## the following command is used
## grep -i -f grepf <fllattened_netlist>|sed -e 's?{?\[?g' -e 's?}?\]?g'|sed -e 's?\-?\_?g'|sed -e 's?\+?\#?g'|sed -e 's?\~?\%?g'> <device_netlist>
## e.g.,
## grep -i -f grepf test1sq.flt.net|sed -e 's?{?\[?g' -e 's?}?\]?g'|sed -e 's?\-?\_?g'|sed -e 's?\+?\#?g'|sed -e 's?\~?\%?g'>test1sq.dev.net
## Where the file grepf contains the following lines (between the grepf markers)
<< 'grepf'
^M
^D
^C
^R
^Q
grepf
flatten_func () {
let rec_depth=$rec_depth+1 ; echo "****REC_DEPTH =" $rec_depth
for ii in `cat $fff|sed -e 's/ /#/g'`
do ll=`echo $ii|sed -e 's/#/ /g'`
fld1=`echo $ll|awk '{print $1}'`
if [[ `echo $fld1|grep -i '@D'` || `echo $fld1|grep -i '@C'` || `echo $fld1|grep -i '@R'` ]]
then nn=4
else if [ `echo $fld1|grep -i '@Q'` ]
then nn=5
else if [ `echo $fld1|grep -i '@M'` ]
then nn=6
else if [ `echo $fld1|grep -i '@X'` ]
then nn=`echo $ll|awk '{print NF}'`; let nn++
# then nn=`echo $ll|awk '{print NF}'`;
fi
fi
fi
fi
if [ $erx ]
then let rec_depth=$rec_depth-1 ; echo "REC_DEPTH =" $rec_depth; return
fi
lx=`echo $ll|awk '{ for (i=1 ; i<="'$nn'"-1 ; i++) if ($i ~ /%/) {printf $i " "} else {printf $i "'$suffx'" " "}; for (i="'$nn'"; i<=NF; i++) printf $i " "}'|sed -e 's/%//g'`
if [ `echo $fld1|grep -i '@X'` ]
then fffx=`echo $ll|awk '{print $NF}'`
inst=$fld1
XXX=$XXX' '$inst
suffx=`echo $XXX|awk '{for (i=1; i<=NF; i++) printf "_" $i}'`
rm -f sedf*
touch sedf1 sedf2
cat $fffx|grep -i subckt |awk '{for (i=3; i<=NF ; i++) printf $i "\n"}' >>sedf1
echo $lx|awk '{for (i=2; i<NF; i++) printf $i "\n"}' >> sedf2
echo '**'$lx
npo=`wc sedf2|awk '{print $1}'`
npi=`wc sedf1|awk '{print $1}'`
if [ $npo -le $npi ]
then
head -n $npo sedf1 > sedf1chop
mv sedf1chop sedf1
else
echo 'Error '`echo $lx|awk '{print $NF}'`' has less pins than ports in calling instance:'
echo $lx|awk '{print $1}'
erx=1
let rec_depth=$rec_depth-1 ; echo "REC_DEPTH =" $rec_depth
return
fi
paste sedf1 sedf2 |sed -e 's/\t/ /' -e 's/^/s\//' -e 's/ /\//' -e 's/$/%\/g/'> sedf
fff=$fffx''$suffx
sed -f sedf $fffx > $fff
flatten_func
else if [[ `echo $ii|grep -i subckt` || `echo $ii|grep -i ends` ]]
##then if [[ $fld1 == '.ends' || $fld1 == '.ENDS' ]]
then if [ `echo $fld1|grep -i '.ends'` ]
then XXX=`echo $XXX|awk '{for (i=1; i<NF; i++) printf $i " "}'`
suffx=`echo $XXX|awk '{for (i=1; i<=NF; i++) printf "_" $i}'`
let nx--
let nx--
fi
if [[ $fff == $fftop || $nx -eq 0 ]]
then echo $ll|sed -e 's/@//g'; let nx++
else echo '**'$ll|sed -e 's/@//g'; let nx++
fi
else echo $lx|sed -e 's/@//g'
fi
fi
if [[ -e $fff && `echo $fff|grep '_'` ]]
then rm -f $fff
fi
done
let rec_depth=$rec_depth-1 ; echo "****REC_DEPTH =" $rec_depth
}
### Shifting special chars and lower case starters
cat $1 |sed -e 's?^[ ]*??'|grep -v '^\*'|awk '{if ($1 != "+") printf "\n"; for (i=1; i<=NF; i++) printf "%s ", $i}' |sed -e 's/+//g' > temp_ljX.sp
cat temp_ljX.sp |sed -e 's?\[?{?g' -e 's?\]?}?g'|sed -e 's?\_?\-?g'|sed -e 's?\#?\+?g'|sed -e 's?\%?\~?g'> temp.net
##sed -i 's?^x?X?' temp.net; sed -i 's?^m?M?' temp.net; sed -i 's?^d?D?' temp.net;
##sed -i 's?^c?C?' temp.net; sed -i 's?^r?R?' temp.net; sed -i 's?^q?Q?' temp.net;
rm -f temp_ljX.sp
######################
for ix in `cat temp.net|sed -e 's?\s\+$??'|sed -e 's/ /#/g'`
do ll=`echo $ix|sed -e 's/#/ /g'`
l1=`echo $ll|awk '{print $1}'`
##if [[ $l1 == '.subckt' || $l1 == '.SUBCKT' ]]
if [ `echo $l1|grep -i '.subckt'` ]
then l2=`echo $ll|awk '{print $2}'`
fff='@'$l2'@'
rm -f $fff
touch $fff
echo $ll|awk '{printf $1;for (i=2; i<=NF; i++) printf " @" $i "@ "; printf "\n"}' >> $fff;
else if [ `echo $l1|grep -i '.ends'` ]; then echo $ll >> $fff
else echo $ll |awk '{for (i=1; i<=1; i++) printf " @" $i "('$l2')@ "; for (i=2; i<=NF; i++) printf " @" $i "@ "; printf "\n"}'>> $fff
fi
fi;
done
topSub=$2
fftop='@'`echo $topSub`'@'; fff=$fftop; XXX=""; nx=1; suffx="";erx=""; set +C; let rec_depth=0; echo "****REC_DEPTH=" $rec_depth; flatten_func; rm -f @*@; rm -f sedf*; rm -f temp.net;erx=""
Listing of the Python3 path plotter (on graph) script discussed in Item#518
show_path.py -->
#! /usr/bin/env python3
## A python script to display a graph path using xview
## Usage: ./show_path.py <path_of_dot_file> <a_graph_path_in_single_quotes>
## Arya, March 3, 2022, edited Apr 02, 2022
import sys
import os
import subprocess
import time
import magic
from pathlib import Path
def printf(args):
N_ = sys.stdout.write(args)
return N_
def fprintf(fH, args):
N_ = fH.write(args)
return N_
def editDotLines(path1_lst, dotLines):
if (len(path1_lst) % 2) == 0:
nstrt = 1
else:
nstrt = 0
for ii in range(nstrt,len(path1_lst)-2,2):
nodesf = '"' + path1_lst[ii] + '"' + ' -> ' + '"' + path1_lst[ii+2] + '"'
nodesr = '"' + path1_lst[ii+2] + '"' + ' -> ' + '"' + path1_lst[ii] + '"'
edgeval = 'label=' + '"' + path1_lst[ii+1] + '"'
for jj in range(len(dotLines)):
if ((nodesf in dotLines[jj]) and (edgeval in dotLines[jj])):
dotLines[jj] = dotLines[jj].replace('color=blue', 'color=red')
dotLines[jj] = dotLines[jj].replace('penwidth = 5', 'penwidth = 15')
Nch=printf("%s" %(dotLines[jj]))
if ((nodesr in dotLines[jj]) and (edgeval in dotLines[jj])):
if 'dir=none' in dotLines[jj]:
dotLines[jj] = dotLines[jj].replace('color=blue', 'color=red')
dotLines[jj] = dotLines[jj].replace('penwidth = 5', 'penwidth = 15')
Nch=printf("%s" %(dotLines[jj]))
return dotLines
def mainProg(dotFile, myPath):
dotLines = []
with open(dotFile, 'r') as f:
for line in f:
dotLines.append(line)
f.close()
dot_filename = 'myPath_color_edited.dot'
jpg_filename = dot_filename.replace('dot', 'jpg')
myPath_lst = myPath.split()
print("Your path turned into a list: {}".format(myPath_lst))
dotF = open(dot_filename, 'w')
for jj in range(len(editDotLines(myPath_lst, dotLines))):
Nch=fprintf(dotF, "%s" % dotLines[jj])
dotF.close()
subprocess.run(["dot", "-Tjpg", dot_filename, "-o", jpg_filename])
xvcmd = '/usr/bin/xview {0} >/dev/null &'.format(jpg_filename)
subprocess.run(xvcmd, shell=True)
nArgs = len(sys.argv)
if nArgs != 3:
print('Too many or too few arguments')
print('Usage: ./show_path.py <path_of_dot_file> <a_graph_path_in_quotes>')
exit()
path_to_dot = Path(sys.argv[1])
##print(path_to_dot)
pathString = sys.argv[2]
oscmd = "head -1 " + sys.argv[1]
##print(len(sys.argv[2].split()))
if (not path_to_dot.is_file()) or (magic.from_file(sys.argv[1], mime=True) != 'text/plain') or ('digraph {' != (os.popen(oscmd).read()).strip()):
##print(len(sys.argv[2].split()))
print(f'{sys.argv[1]} does not exist OR not a proper ascii dotFile')
print('Usage: ./show_path.py <path_of_dot_file> <a_graph_path_in_single_quotes>')
exit()
while len(pathString.split()) > 0:
mainProg(sys.argv[1], pathString)
pathString = input("Enter next Path to plot, Press <return> to exit: ")
if pathString.startswith(('"',"'")) and pathString.endswith(('"',"'")):
pathString = pathString[1:-1]
## time.sleep(2)
Listing of the Python3-Tkinter wrapper script used in Item#515
wrapper_pathFind.py -->
#! /usr/bin/env python3
## A python3-tkinter based wrapper script for the mixed-multi
## graphs paths finder algorithm : pathFind_allGraphs.sh
## Arya, Feb 2022, working with Linux Mint 20.3 Cinnamon 64-bit,
## on a Lenovo IdeaPad (S145)
## The progDir (containing the invoked routines) needs to be SET first
## The routines that run as subprocess are:
## pathFind_allGraphs.sh, use the latest version down below (Item#511)
## edges_to_dot.sh (see listing of edited version just under this one)
##
## Following modules and their dependencies are needed:
## sudo apt install xloadimage - enables the xview (jpg viewer) command
## sudo apt install graphviz - enables the dot (graph drawing) command
## sudo apt install python3 - should be python 3.8.10 or later
## sudo apt install python3-tk - this is tkinter, enables the gui widgets
## This program (wrapper_pathFind.py) should also be saved in the progDir
## This can be run in two ways:
## 1. Go to suitblle Work directory on a terminal, and type
## <progDir path>/wrapper_pathFind.py <Return>
## Then the GUI widgets guide you
## 2. Double-Clicking on a launcher icon on the desktop, and letting
## guide you the widgets
## To create a launcher icon on the Linux Mint desktop,
## Right-click on a free space, select: + Create a new launcher here ...
## Launcher Properties Entry widget comes up. For example, I give a
## Name: graphPathsFind
## Command: /home/arya/python/wrapper_allGraphs/wrapper_pathFind.py
## Comment: Python3-Tk wrapper runs Graph Paths Finder Recursive Shell
## Click Ok, Click Yes to the menu entry query
## "graphPathsFind" launcher icon shows up on desktop as well as
## on Menu --> Other
progDir = "/home/arya/python/wrapper_allGraphs/"
import os
import os.path
from os import path
import signal
import subprocess
from subprocess import Popen,PIPE, run
import time
import shutil
import tkinter as tk
from tkinter import filedialog
from tkinter import *
import PIL
from PIL import ImageTk
from PIL import Image
from subprocess import check_output
import magic
f = magic.Magic(mime=True)
def get_pid(ProcName):
return check_output(["pidof",ProcName])
global cont_
cont_ = 1
def cont_loop():
global cont_
cont_ = 1
root.destroy()
#def clear_():
# listSlaves = ww.slaves()
# for slave_wid in listSlaves:
# slave_wid.destroy()
def labelsButtons_(winx):
label1 = tk.Label(winx, text='Does it look Ok? Continue ...')
button1= tk.Button(winx, text="Continue", command=winx.destroy)
label2 = tk.Label(winx, text='Want to exit session? Exit ...')
button2 = tk.Button(winx,text="Exit", command=exit)
label3 = tk.Label(winx, text='Try another filename? Retry ...')
button3 = tk.Button(winx,text="Retry", command=cont_loop)
label1.pack()
button1.pack()
label2.pack()
button2.pack()
label3.pack()
button3.pack()
def get_workdir():
global WorkDir
WorkDir = filedialog.askdirectory(title='DoubleClick on Work Dir of choice, press Open')
root.destroy()
def getNodeList():
nodeList = []
nodeListUniq = []
with open(edgesFilePath, 'r') as f:
for line in f:
nodeList.extend(line.split()[:2])
f.close()
for xx in nodeList:
if xx not in nodeListUniq:
nodeListUniq.append(xx)
##myset = set(nodeList)
##nodeListUniq = list(myset)
nodeListStr = ' '
for xx in nodeListUniq:
nodeListStr += ' '+ xx
##print(nodeListStr)
return nodeListStr
def getStrtNode():
global strtNode
if nodeSelBox.tag_ranges("sel"):
strtNode = nodeSelBox.selection_get()
strtEntryBtn.insert(0,strtNode)
## print(nodeSelBox.selection_get())
strtNode =strt_var.get()
print(strtNode)
def getEndNode():
global endNode
if nodeSelBox.tag_ranges("sel"):
endNode = nodeSelBox.selection_get()
endEntryBtn.insert(0,endNode)
## print(nodeSelBox.selection_get())
endNode = end_var.get()
print(endNode)
while cont_:
while cont_:
global root
###########GET THE EDGE TABLE FILE UNTIL CORRECT ##############
cont_ = 0
root = tk.Tk()
##root.withdraw()
edgesFilePath = ""
while not os.path.isfile(edgesFilePath):
edgesFilePath = filedialog.askopenfilename(title='Click on the edges table file, press Open')
if os.path.isfile(edgesFilePath): break
while f.from_file(edgesFilePath) != 'text/plain':
edgesFilePath = filedialog.askopenfilename(title='BAD file type, enter correct, press Open')
if f.from_file(edgesFilePath) == 'text/plain': break
### if not edgesFilePath : exit()
##with open(edgesFilePath,'r') as fx:
## label = tk.Label(root, text=fx.read())
## label.config(width=20, font=("Courier", 10))
## label.pack()
fx = open(edgesFilePath,'r')
data = fx.read()
fx.close()
root.title('Scroll to check the edges table file')
widget = tk.Text(root, height=40, width= 40)
scrollbar = tk.Scrollbar(root)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
widget.pack(side=tk.LEFT, fill=tk.Y)
scrollbar.config(command=widget.yview)
widget.config(yscrollcommand=scrollbar.set)
widget.insert(tk.END, data)
label = tk.Label(root, text=edgesFilePath)
label.config(fg='brown')
label_spc = tk.Label(root)
label.pack()
label_spc.pack()
labelsButtons_(root)
root.mainloop()
edgesFileName = os.path.basename(edgesFilePath)
dot_filename = edgesFileName + '.dot'
print(dot_filename)
# outputDir = os.chdir(os.path.dirname(edgesFilePath))
################WORK DIR CHOOSE ######################
print(os.getcwd())
CurDir = os.getcwd()
WorkDir = CurDir
root = tk.Tk()
root.geometry('600x100+50+50')
root.title(CurDir)
labelDir = tk.Label(root, text='Is ths WorkDir (for saving results) Ok?')
buttonOk= tk.Button(root, text="YES OK", command=root.destroy)
buttonNOK = tk.Button(root, text="NOT OK", command=get_workdir)
buttonNOK.pack(side=BOTTOM)
buttonOk.pack(side=TOP)
labelDir.pack()
root.mainloop()
print(WorkDir)
os.chdir(WorkDir)
############### CREATE DOT, JPG, CHECK WITH XVIEW UNTIL CORRECT ####
edgesToDotSh = progDir + "edges_to_dot.sh"
jpg_filename = edgesFileName + '.jpg'
subprocess.run([ edgesToDotSh, edgesFilePath, dot_filename])
subprocess.run(["dot", "-Tjpg", dot_filename, "-o", jpg_filename])
xvcmd = '/usr/bin/xview {0} &'.format(jpg_filename)
command_list = xvcmd.split()
subprocess.run(xvcmd, shell=True)
# subprocess.run(["xview", jpg_filename, "&" ], shell=True)
# os.system("xview {jpg_filename} &")
root = tk.Tk()
root.geometry('300x200+50+50')
## frame_ = tk.Frame(root, width = 300, height = 50)
root.title(jpg_filename)
## frame_.pack()
# canvas = tk.Canvas(root, width = 800, height = 500)
# root.title(jpg_filename)
# canvas.pack()
# img = PIL.ImageTk.PhotoImage(PIL.Image.open(jpg_filename))
# canvas.create_image(0, 0, anchor=NW, image=img)
labelsButtons_(root)
## print(root.pack_slaves())
root.mainloop()
######## MOUSE SELECT START AND END NODES FOR PATHS FIND ##########
data = getNodeList()
print(data)
root = tk.Tk()
root.title('START, END nodes (Must be non-identical) selection from All nodes listed below')
global strt_var
global end_var
strt_var = tk.StringVar(root)
end_var = tk.StringVar(root)
label = tk.Label(root, text='mouse-select or type, then grab-button press start, end nodes')
label.pack()
nodeSelBox = tk.Text(root, height= 10, width=60)
nodeSelBox.insert(tk.END, data)
nodeSelBox.pack()
strtNodeBtn = tk.Button(root, text="Grab Start Node>>", command=getStrtNode)
endNodeBtn = tk.Button(root, text="<<Grab End Node", command=getEndNode)
doneBtn = tk.Button(root, text="Done", command=root.destroy)
strtEntryBtn = tk.Entry(root, textvariable = strt_var)
endEntryBtn = tk.Entry(root, textvariable = end_var)
strtNodeBtn.pack(side=LEFT)
strtEntryBtn.pack(side=LEFT)
endNodeBtn.pack(side=RIGHT)
endEntryBtn.pack(side=RIGHT)
doneBtn.pack(side=BOTTOM)
root.mainloop()
print(strtNode)
print(endNode)
################# RUN THE RECURSIVE GRAPH PATHS FINDER ##############
reducMode = "10"
transcript_file = "transcript" + "_" + strtNode + "_" + endNode + "_" + reducMode
treedone_file = "treedone" + "_" + strtNode + "_" + endNode + "_" + reducMode
root= tk.Tk()
rootTitle = 'Transcript will be saved in ' + transcript_file + ' Paths in ' + treedone_file
root.title(rootTitle)
widget = tk.Text(root, height=40, width=70)
scrollbar = tk.Scrollbar(root)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
widget.pack(side=tk.LEFT, fill=tk.Y)
scrollbar.config(command=widget.yview)
widget.config(yscrollcommand=scrollbar.set)
workDoneBtn = tk.Button(root, text="Work Done!", command=root.destroy)
workDoneBtn.pack(side=tk.RIGHT)
progPath = progDir + "pathFind_allGraphs.sh"
##edgesFile = "edge_table_mm_DK"
##strtNode = "C"
##endNode = "U"
##reducMode = "10"
##transcript_file = "transcript" + "_" + strtNode + "_" + endNode + "_" + reducMode
trF = open(transcript_file, 'w')
####### LAUNCHING THE PATHS FINDER SUBPROCESS HERE ################
p = subprocess.Popen([progPath, edgesFilePath, strtNode , endNode, reducMode], stdout=PIPE)
while True:
txt = p.stdout.readline()
widget.insert('1.0', txt)
widget.update()
xx = txt.decode('utf8').strip("\n")
# print(xx)
trF.writelines(xx)
trF.writelines("\n")
if p.poll() is not None: break
trF.close()
widget.insert('1.0', "###############################################\n")
widget.insert('1.0', "TRANSCRIPT ENDS HERE. PATHS LISTED ABOVE#######\n")
widget.insert('1.0', "###############################################\n")
with open(treedone_file,'r') as file:
AllPaths = file.read()
widget.insert('1.0', AllPaths)
##### PATHS LISTING DONE ####################
root.mainloop()
########### DELETING THE XVIEW WINDOW ####################
xxx = get_pid("xview").decode('utf8').strip("\n")
for xx in xxx.split():
yy = int(xx)
os.kill(yy, signal.SIGTERM)
################## DELETING THE INTERMEDIATE RUN FILES #############
##### LEAVING ONLY THE DOT FILE, GRAPH JPG, TRANSCRIPT AND PATHS FILES
for ff in ['1nodesList','edgeTableSimple','grepf','path_list.padded','path_list.padded_1','vertices','vertices_sorted','vertices_sorted_1']:
os.remove(ff)
for dd in ['hashFiles','hashFiles_0']:
shutil.rmtree(dd)
cat edges_to_dot.sh -->
#! /usr/bin/bash
echo ""|awk '{printf "digraph {\n"; printf "rankdir=LR\n";\
printf "node [shape=diamond, width=1.5, fontname ="times-bold", fontsize=32]\n";\
printf "edge [fontname=Arial, fontcolor=red, fontstyle=bold, fontsize=32 ]\n";\
printf "graph [layout = dot]\n";\
printf "size=8\n"; printf "ratio=0.6\n" }' >$2;
cat $1 |awk '{printf "\""$1"\"" " -> " "\""$2"\"" "[style=bold, label=" "\""$3"\"" ;\
if ($4 == ">") printf ", penwidth = 5, color=blue]\n";\
else printf ", dir=none, penwidth = 5, color=blue]\n"}' >> $2;echo "}" >> $2
** This version draws Left to Right graphs with thicker node text, wider blue edges, bigger edge labels
Listing of the special characters handling shell scripts "spice_to_edges_splC.sh" , "edges_to_dot_splC.sh" , and pathFind_allGraphs_splC.sh as indicated in Item#513
cat spice_to_edges_splC.sh -->
for ix in `cat $1|sed -e 's?\s\+$??'|sed -e 's/ /\!/g'`
do ll=`echo $ix|sed -e 's/\!/ /g'`
l1=`echo $ll|awk '{print $1}'`
l2=`echo $ll|awk '{print $2}'`
lend=`echo $ll|awk '{print $NF}'`
if [[ $l1 == '.subckt' || $l1 == '.SUBCKT' ]]
then N1=$l2
fi
if [[ ${l1::1} == "x" || ${l1::1} == "X" ]]
then N2=$lend
echo $N1 $N2 $l1 ">"
fi
done > $2
cat edges_to_dot_splC.sh -->
echo ""|awk '{printf "digraph {\n"; printf "rankdir=TD\n";\
printf "node [shape=diamond]\n";\
printf "graph [layout = dot]\n";\
printf "size=4\n"; printf "ratio=0.6\n" }' >$2;
cat $1 |awk '{printf "\""$1"\"" " -> " "\""$2"\"" "[style=bold, label=" "\""$3"\"" ;\
if ($4 == ">") printf "]\n";\
else printf ", dir=none]\n"}' >> $2;echo "}" >> $2
cat pathFind_allGraphs_splC.sh -->
#! /usr/bin/bash
## Edited recursive bash based simple/mixed-multi graph paths finder from a edges list
## With optimal pendant nodes filtering with specifiable switch as the optional 4th argument
## 0 for ==0 mode, 1 for ==1 mode, 10 for twoStage, Nothing for no filtering
## Arya, Nov 18, 2021
##Usage: ./pathFind_allGraphs_splC.sh <paths list file> <'startNode'> <'endNode'>
## Please enclose startNode and endNode in single quotes
ReduceGraph () {
mode_sw=$1
let pendants=1
while [ $pendants == 1 ]
do let pendants=0
for ff in `ls ./hashFiles`
do echo $ff
if [[ `wc -l ./hashFiles/$ff|awk '{print $1}'` == $mode_sw && ($ff != $startNode && $ff != $endNode) ]]
then let pendants=1
rm -f ./hashFiles/$ff
echo YES
echo $ff >> 1nodesList
for fx in `ls ./hashFiles`; do grep -v $ff ./hashFiles/$fx > tmpFile; mv -f tmpFile ./hashFiles/$fx; done
fi
done
echo '###################################'
done ## removing non-relevant pendant vertex hashFiles
}
pullback () {
llx=`echo $1 |sed -e 's/%/ /g'|awk '{for (i=1; i<=NF-2; i++) printf $i " "; printf "\n"}'|sed -e 's/ /%/g'`
}
pathRec_func () {
let DepthRec=$DepthRec+1; let jj=$jj+1; echo $jj " DepthRec=" $DepthRec #entering the recursive function, incrementing the depth of recursion by 1
llx=$1 ## new parent path
echo $llx|tr "%" '\n'|grep '#' > grepf ##parent path grepf
endent=`echo $llx|sed -e 's/%/ /g'|awk '{print $NF}'` ##child node of the parent path
if [[ $endent != $endNode ]] ## Got a path if the child node is the destination node
then
grep -v -f grepf ./hashFiles_0/$endent > ./hashFiles/$endent ##filtering off the parent path vertices before for loop to stop vertex looping
for hx in `cat ./hashFiles/$endent|sed -e 's/ /%/g'` ## looking for new children of the child node
do
cllx=`echo $llx $hx|sed -e 's/ /%/g'` ##augmenting the parent path with the child node
pathRec_func $cllx # re-invoke pathRec_func () since the child node was good
done
else
echo $llx |sed -e 's/%/ /g'|sed -e 's/ X[1-9]*_/ /g'|sed -e 's/#//g'|awk '{sum=0;for(i=2;i<NF;i=i+2) sum+=$i ; printf sum " "; print $0}'>> treedone ##write out the found path
let ii=$ii+1; echo " "$ii
fi
pullback $llx ##exiting the recursive function, pulling back the entering parent path by its child node
rm -f -r hashFiles; cp -r hashFiles_0 hashFiles #restore the hashFiles with the hashFiles_0
let DepthRec=$DepthRec-1; let jj=$jj+1; echo $jj " DepthRec=" $DepthRec ## reducing the depth of recursion
}
echo $0 $1 $2 $3 $4
pathlist=$1
if [[ $1 && -e $pathlist ]]
then echo ""
else echo "paths list file does not exist"
echo 'Usage: ./pathFind_allGraphs_splC.sh <paths list file> <'startNode'> <'endNode'> <pendants_reduce_switch>'
echo '<pendants_reduce_switch> can be 0 or 1 or 10 or nothing'
echo '## Please enclose startNode and endNode in single quotes'
exit
fi
sed -e 's/\[/\,/g' -e 's/\]/\;/g' -e 's/\#/\!/g' -e 's/\%/\?/g' $pathlist > edge_table_sed_spl_char
pathlist='edge_table_sed_spl_char'
if [[ $2 && $3 ]]
then strtN=`echo $2|sed -e 's/\[/\,/g' -e 's/\]/\;/g' -e 's/\#/\!/g' -e 's/\%/\?/g'`
endN=`echo $3|sed -e 's/\[/\,/g' -e 's/\]/\;/g' -e 's/\#/\!/g' -e 's/\%/\?/g'`
startNode=`echo "#"$strtN"#"`; endNode=`echo "#"$endN"#"`;
else echo "valid startNode and endNode must be specified"
echo 'Usage: ./pathFind_allGraphs_splC.sh <paths list file> <'startNode'> <'endNode'> <pendants_reduce_switch>'
echo '<pendants_reduce_switch> can be 0 or 1 or 10 or nothing'
echo '## Please enclose startNode and endNode in single quotes'
exit
fi
if [[ $4 ]]
then if [[ $4 == 0 || $4 == 1 || $4 == 10 ]]
then echo ""
else echo 'Bad pendants reduce switch, must be 0 or 1 or 10 or nothing'
echo 'Usage: ./pathFind_allGraphs_splC.sh <paths list file> <'startNode'> <'endNode'> <pendants_reduce_switch>'
echo '## Please enclose startNode and endNode in single quotes'
echo '<pendants_reduce_switch> can be 0 or 1 or 10 or nothing'
exit
fi
fi
echo "start hasher"
echo 'the vertex_edge hash files are saved in the "hashFiles" sub-directory'
#sleep 3
date
echo '###################################'
if [ -e hashFiles ]
then rm -rf hashFiles
fi
mkdir hashFiles
if [ -e hashFiles_0 ]
then rm -rf hashFiles_0
fi
mkdir hashFiles_0
if [ -e vertices ]
then rm -f vertices
fi
touch vertices
if [ -e 1nodesList ]
then rm -f 1nodesList
fi
touch 1nodesList
for ln in `cat $pathlist|awk '{print $1 " " $2}'`
do echo $ln >> vertices
done
sort vertices|uniq|sed -e 's/^/#/' -e 's/$/#/' > vertices_sorted
if [[ $4 == 10 ]]
then echo "## First create a non-mixed_multi edges table for applying ==1 pendants filter"
cat $pathlist|awk '{str_ab_ba=$1<$2?$1" "$2:$2" "$1;printf str_ab_ba " 1\n"}'|sort|uniq > edgeTableSimple
for lx in `cat edgeTableSimple|sed -e 's/ /%/g'`
do echo $lx|sed -e 's/%/ /g'|awk '{printf "#" $1 "# "; printf "#" $2 "# "; printf $3 "\n"}'
done >path_list.padded
for plp in `cat vertices_sorted`
do if [ -e $plp ]; then rm -f $plp; fi
touch $plp
let ii=0
grep $plp path_list.padded |sed -e "s/$plp//" >> $plp
touch plp_tmp
for ll in `cat $plp |awk '{print $NF "%" $1}'`
do let ii=$ii+1
echo "X"$ii"_"$ll| sed -e 's/%/ /' >> plp_tmp
done;
mv -f plp_tmp $plp
cp $plp ./hashFiles
mv -f $plp ./hashFiles_0
done
echo "#########First Stage Pendants Filtering on the Equiv Simple Graph with ==1###########"
ReduceGraph 1
rm -f -r hashFiles_0; mkdir hashFiles_0;
rm -f -r hashFiles; mkdir hashFiles;
echo '############First Stage reduction completed #######################'
fi
for lx in `cat $pathlist|sed -e 's/ /%/g'`
do echo $lx|sed -e 's/%/ /g'|awk '{printf "#" $1 "# "; printf "#" $2 "# "; printf $3 " " ; printf $4 "\n"}'
done >path_list.padded
grep -v -f 1nodesList vertices_sorted > vertices_sorted_1
grep -v -f 1nodesList path_list.padded > path_list.padded_1
for plp in `cat vertices_sorted_1`
do if [ -e $plp ]; then rm -f $plp; fi
touch $plp
let ii=0
## grep $plp path_list.padded |sed -e "s/$plp//" >> $plp
grep $plp path_list.padded_1 >> $plp
cat $plp | awk '{if ($NF == ">" && $1 == "'$plp'" ) printf $2 " " $3; printf "\n"; if ($NF != ">" ) printf $0; printf "\n";}'|sed -e "s/$plp//"|grep -v '^$' > plp_xxx
mv -f plp_xxx $plp
touch plp_xxx
for ll in `cat $plp |awk '{print $2 "%" $1}'`
do let ii=$ii+1
echo "X"$ii"_"$ll| sed -e 's/%/ /' >> plp_xxx
done;
mv -f plp_xxx $plp
cp $plp ./hashFiles
mv -f $plp ./hashFiles_0
done
if [[ ! -e ./hashFiles/$startNode || ! -e ./hashFiles/$endNode ]]
then echo "valid startNode and endNode must be specified"
echo 'Usage: ./pathFind_allGraphs_splC.sh <paths list file> <'startNode'> <'endNode'> <pendants_reduce_switch>'
echo '## Please enclose startNode and endNode in single quotes'
echo '<pendants_reduce_switch> can be 0 or 1 or 10 or nothing'
exit
fi
if [[ $4 == 0 || $4 == 1 || $4 == 10 ]]
then mode_sw=$([ $4 == 1 ] && echo 1 || echo 0)
echo "#########final filtering with ==" $mode_sw " on Reduced/Unreduced Graph###########"
ReduceGraph $mode_sw
rm -f -r hashFiles_0; cp -r ./hashFiles hashFiles_0
echo '###########Final Stage Reduction Completed########################'
fi
echo '###################################'
echo "end hasher"
date
############################################################################
echo "start path find"
echo "the path#s are reported on the screen as the successive paths are figured"
echo 'the file "treedone" saves the paths - sorted for the path lengths (the first number in each line)'
##sleep 3
date; strt_time=`date|awk '{print $5}'`
rm -f treedone; touch treedone
echo $startNode ; let ii=0; let jj=0;
let DepthRec=0; echo $jj " DepthRec=" $DepthRec
pathRec_func $startNode
sort -n -k 1 treedone| sed -e 's/ / /g' > tmpTree1
mv tmpTree1 treedone
treeFile='treedone_'$2'->'$3
if [[ $4 ]]
then treeFile=`echo $treeFile`'_'$4
fi
touch $treeFile
sed -e 's/\,/\[/g' -e 's/\;/\]/g' -e 's/\!/\#/g' -e 's/\?/\%/g' treedone > $treeFile
echo "###################"
echo "end path find"
date
echo "strt_time was" $strt_time
***
Listing of the shell scripts "spice_to_edges.sh" and "edges_to_dot.sh" indicated in Item#512
cat spice_to_edges.sh -->
for ix in `cat $1|sed -e 's?\s\+$??'|sed -e 's/ /#/g'`
do ll=`echo $ix|sed -e 's/#/ /g'`
l1=`echo $ll|awk '{print $1}'`
l2=`echo $ll|awk '{print $2}'`
lend=`echo $ll|awk '{print $NF}'`
if [[ $l1 == '.subckt' || $l1 == '.SUBCKT' ]]
then N1=$l2
fi
if [[ ${l1::1} == "x" || ${l1::1} == "X" ]]
then N2=$lend
echo $N1 $N2 $l1 ">"
fi
done > $2
cat edges_to_dot.sh -->
#! /usr/bin/bash
echo ""|awk '{printf "digraph {\n"; printf "rankdir=TD\n";\
printf "node [shape=diamond]\n";\
printf "graph [layout = dot]\n";\
printf "size=8\n"; printf "ratio=0.6\n" }' >$2;
cat $1 |awk '{printf $1 " -> " $2 "[style=bold, label=" $3 ;\
if ($4 == ">") printf "]\n";\
else printf ", dir=none]\n"}' >> $2;echo "}" >> $2
***
Listing of the optimal nodes filtering shell algorithm indicated in Item#511
cat pathFind_allGraphs.sh -->
#! /usr/bin/bash
## Edited recursive bash based simple/mixed-multi graph paths finder from a edges list
## With optimal pendant nodes filtering with specifiable switch as the optional 4th argument
## 0 for ==0 mode, 1 for ==1 mode, 10 for twoStage, Nothing for no filtering
## Arya, Nov 19, 2021
##Usage: ./pathFind_allGraphs.sh <paths list file> <startNode> <endNode> <pendants_reduce_switch>
ReduceGraph () {
mode_sw=$1
let pendants=1
while [ $pendants == 1 ]
do let pendants=0
for ff in `ls ./hashFiles`
do echo $ff
if [[ `wc -l ./hashFiles/$ff|awk '{print $1}'` == $mode_sw && ($ff != $startNode && $ff != $endNode) ]]
then let pendants=1
rm -f ./hashFiles/$ff
echo YES
echo $ff >> 1nodesList
for fx in `ls ./hashFiles`; do grep -v $ff ./hashFiles/$fx > tmpFile; mv -f tmpFile ./hashFiles/$fx; done
fi
done
echo '###################################'
done ## removing non-relevant pendant vertex hashFiles
}
pullback () {
llx=`echo $1 |sed -e 's/%/ /g'|awk '{for (i=1; i<=NF-2; i++) printf $i " "; printf "\n"}'|sed -e 's/ /%/g'`
}
pathRec_func () {
let DepthRec=$DepthRec+1; let jj=$jj+1; echo $jj " DepthRec=" $DepthRec #entering the recursive function, incrementing the depth of recursion by 1
llx=$1 ## new parent path
echo $llx|tr "%" '\n'|grep '#' > grepf ##parent path grepf
endent=`echo $llx|sed -e 's/%/ /g'|awk '{print $NF}'` ##child node of the parent path
if [[ $endent != $endNode ]] ## Got a path if the child node is the destination node
then
grep -v -f grepf ./hashFiles_0/$endent > ./hashFiles/$endent ##filtering off the parent path vertices before for loop to stop vertex looping
for hx in `cat ./hashFiles/$endent|sed -e 's/ /%/g'` ## looking for new children of the child node
do
cllx=`echo $llx $hx|sed -e 's/ /%/g'` ##augmenting the parent path with the child node
pathRec_func $cllx # re-invoke pathRec_func () since the child node was good
done
else
echo $llx |sed -e 's/%/ /g'|sed -e 's? X[1-9]*_? ?g'|sed -e 's?#??g'|awk '{sum=0;for(i=2;i<NF;i=i+2) sum+=$i ; printf sum " "; print $0}'>> treedone ##write out the found path
let ii=$ii+1; echo " "$ii
fi
pullback $llx ##exiting the recursive function, pulling back the entering parent path by its child node
rm -f -r hashFiles; cp -r hashFiles_0 hashFiles #restore the hashFiles with the hashFiles_0
let DepthRec=$DepthRec-1; let jj=$jj+1; echo $jj " DepthRec=" $DepthRec ## reducing the depth of recursion
}
echo $0 $1 $2 $3 $4
pathlist=$1
if [[ $1 && -e $pathlist ]]
then echo ""
else echo "paths list file does not exist"
echo 'Usage: ./pathFind_allGraphs.sh <paths list file> <startNode> <endNode> <pendants_reduce_switch>'
echo '<pendants_reduce_switch> can be 0 or 1 or 10 or nothing'
exit
fi
if [[ $2 && $3 ]]
then startNode=`echo "#"$2"#"`; endNode=`echo "#"$3"#"`;
else echo "valid startNode and endNode must be specified"
echo 'Usage: ./pathFind_allGraphs.sh <paths list file> <startNode> <endNode> <pendants_reduce_switch>'
echo '<pendants_reduce_switch> can be 0 or 1 or 10 or nothing'
exit
fi
if [[ $4 ]]
then if [[ $4 == 0 || $4 == 1 || $4 == 10 ]]
then echo ""
else echo 'Bad pendants reduce switch, must be 0 or 1 or 10 or nothing'
echo 'Usage: ./pathFind_rec_mm_opt.sh <paths list file> <startNode> <endNode> <pendants_reduce_switch>'
echo '<pendants_reduce_switch> can be 0 or 1 or 10 or nothing'
exit
fi
fi
echo "start hasher"
echo 'the vertex_edge hash files are saved in the "hashFiles" sub-directory'
#sleep 3
date
echo '###################################'
if [ -e hashFiles ]
then rm -rf hashFiles
fi
mkdir hashFiles
if [ -e hashFiles_0 ]
then rm -rf hashFiles_0
fi
mkdir hashFiles_0
if [ -e vertices ]
then rm -f vertices
fi
touch vertices
if [ -e 1nodesList ]
then rm -f 1nodesList
fi
touch 1nodesList
for ln in `cat $pathlist|awk '{print $1 " " $2}'`
do echo $ln >> vertices
done
sort vertices|uniq|sed -e 's?^?#?' -e 's?$?#?' > vertices_sorted
if [[ $4 == 10 ]]
then echo "## First create a non-mixed_multi edges table for applying ==1 pendants filter"
cat $pathlist|awk '{str_ab_ba=$1<$2?$1" "$2:$2" "$1;printf str_ab_ba " 1\n"}'|sort|uniq > edgeTableSimple
for lx in `cat edgeTableSimple|sed -e 's? ?%?g'`
do echo $lx|sed -e 's?%? ?g'|awk '{printf "#" $1 "# "; printf "#" $2 "# "; printf $3 "\n"}'
done >path_list.padded
for plp in `cat vertices_sorted`
do if [ -e $plp ]; then rm -f $plp; fi
touch $plp
let ii=0
grep $plp path_list.padded |sed -e "s?$plp??" >> $plp
touch plp_tmp
for ll in `cat $plp |awk '{print $NF "%" $1}'`
do let ii=$ii+1
echo "X"$ii"_"$ll| sed -e 's?%? ?' >> plp_tmp
done;
mv -f plp_tmp $plp
cp $plp ./hashFiles
mv -f $plp ./hashFiles_0
done
echo "#########First Stage Pendants Filtering on the Equiv Simple Graph with ==1###########"
ReduceGraph 1
rm -f -r hashFiles_0; mkdir hashFiles_0;
rm -f -r hashFiles; mkdir hashFiles;
echo '############First Stage reduction completed #######################'
fi
for lx in `cat $pathlist|sed -e 's? ?%?g'`
do echo $lx|sed -e 's?%? ?g'|awk '{printf "#" $1 "# "; printf "#" $2 "# "; printf $3 " " ; printf $4 "\n"}'
done >path_list.padded
grep -v -f 1nodesList vertices_sorted > vertices_sorted_1
grep -v -f 1nodesList path_list.padded > path_list.padded_1
for plp in `cat vertices_sorted_1`
do if [ -e $plp ]; then rm -f $plp; fi
touch $plp
let ii=0
## grep $plp path_list.padded |sed -e "s?$plp??" >> $plp
grep $plp path_list.padded_1 >> $plp
cat $plp | awk '{if ($NF == ">" && $1 == "'$plp'" ) printf $2 " " $3; printf "\n"; if ($NF != ">" ) printf $0; printf "\n";}'|sed -e "s?$plp??"|grep -v '^$' > plp_xxx
mv -f plp_xxx $plp
touch plp_xxx
for ll in `cat $plp |awk '{print $2 "%" $1}'`
do let ii=$ii+1
echo "X"$ii"_"$ll| sed -e 's?%? ?' >> plp_xxx
done;
mv -f plp_xxx $plp
cp $plp ./hashFiles
mv -f $plp ./hashFiles_0
done
if [[ ! -e ./hashFiles/$startNode || ! -e ./hashFiles/$endNode ]]
then echo "valid startNode and endNode must be specified"
echo 'Usage: ./pathFind_allGraphs.sh <paths list file> <startNode> <endNode> <pendants_reduce_switch>'
echo '<pendants_reduce_switch> can be 0 or 1 or 10 or nothing'
exit
fi
if [[ $4 == 0 || $4 == 1 || $4 == 10 ]]
then mode_sw=$([ $4 == 1 ] && echo 1 || echo 0)
echo "#########final filtering with ==" $mode_sw " on Reduced/Unreduced Graph###########"
ReduceGraph $mode_sw
rm -f -r hashFiles_0; cp -r ./hashFiles hashFiles_0
echo '###########Final Stage Reduction Completed########################'
fi
echo '###################################'
echo "end hasher"
date
############################################################################
echo "start path find"
echo "the path#s are reported on the screen as the successive paths are figured"
echo 'the file "treedone" saves the paths - sorted for the path lengths (the first number in each line)'
##sleep 3
date; strt_time=`date|awk '{print $5}'`
rm -f treedone; touch treedone
echo $startNode ; let ii=0; let jj=0;
let DepthRec=0; echo $jj " DepthRec=" $DepthRec
pathRec_func $startNode
sort -n -k 1 treedone| sed -e 's? ? ?g' > tmpTree1
mv tmpTree1 treedone
treeFile='treedone_'$2'_'$3
if [[ $4 ]]
then treeFile=`echo $treeFile`'_'$4
fi
touch $treeFile
mv treedone $treeFile
echo "###################"
echo "end path find"
date
echo "strt_time was" $strt_time
sleep 0.003
*** The three ms time delay (sleep) is added at the end to prevent the code from overloading the subprocess PIPE of the python3-tkinter wrapper
***
Script to superimpose (Item#510) the reduced "red" graph on the original "black" graph of Item#509
cat redGraph.sh -->
grep -B 1 YES transcript_CU_0|grep -v YES|grep -v '\-\-'|sed -e 's?#??g' > grepNodes_0
grep style= edge_table_mm.dot| grep -v -f grepNodes_0|sed -e 's?\[?\\\[ ?'|awk '{print "s?" $1 " " $2 " " $3 "?" $1 " " $2 " " $3 "color=red, ?"}' > sedNodes_0
sed -f sedNodes_0 edge_table_mm.dot > edge_table_mm_0.dot
dot -Tjpg edge_table_mm_0.dot -o edge_table_mm_0.jpg
xview edge_table_mm_0.jpg &
grep -B 1 YES transcript_CU_1|grep -v YES|grep -v '\-\-'|sed -e 's?#??g' > grepNodes_1
grep style= edge_table_mm.dot| grep -v -f grepNodes_1|sed -e 's?\[?\\\[ ?'|awk '{print "s?" $1 " " $2 " " $3 "?" $1 " " $2 " " $3 "color=red, ?"}' > sedNodes_1
sed -f sedNodes_1 edge_table_mm.dot > edge_table_mm_1.dot
dot -Tjpg edge_table_mm_1.dot -o edge_table_mm_1.jpg
xview edge_table_mm_1.jpg &
Usage : ./redGraph.sh
Instantaneously puts out the two superimpositions
***
Listings of the mixed_multi edges table, the corresponding "dot" format file, and the format conversion bash script, as used Item#509
cat edge_table_mm -->
A B 4
B C 1 >
C D 4
D L 3 >
L N 1 >
B E 1 >
E J 1 >
J V 1 >
V P 3
P S 1
E D 2 >
D E 1 >
D K 1
K V 2
K M 1
M L 1 >
M P 1
M O 1 >
O M 2 >
M R 1
R S 1
B F 3
F H 1
H I 2
I Q 3 >
Q T 1 >
H E 2
I E 2 >
I V 1 >
P Q 2 >
Q P 1 >
S T 2
G F 3 >
Q U 2
cat edge_table_mm.dot -->
digraph {
rankdir=LR
node [shape=diamond]
graph [layout = dot]
size=8
ratio=0.6
A -> B[style=bold, label=4, dir=none]
B -> C[style=bold, label=1]
C -> D[style=bold, label=4, dir=none]
D -> L[style=bold, label=3]
L -> N[style=bold, label=1]
B -> E[style=bold, label=1]
E -> J[style=bold, label=1]
J -> V[style=bold, label=1]
V -> P[style=bold, label=3, dir=none]
P -> S[style=bold, label=1, dir=none]
E -> D[style=bold, label=2]
D -> E[style=bold, label=1]
D -> K[style=bold, label=1, dir=none]
K -> V[style=bold, label=2, dir=none]
K -> M[style=bold, label=1, dir=none]
M -> L[style=bold, label=1]
M -> P[style=bold, label=1, dir=none]
M -> O[style=bold, label=1]
O -> M[style=bold, label=2]
M -> R[style=bold, label=1, dir=none]
R -> S[style=bold, label=1, dir=none]
B -> F[style=bold, label=3, dir=none]
F -> H[style=bold, label=1, dir=none]
H -> I[style=bold, label=2, dir=none]
I -> Q[style=bold, label=3]
Q -> T[style=bold, label=1]
H -> E[style=bold, label=2, dir=none]
I -> E[style=bold, label=2]
I -> V[style=bold, label=1]
P -> Q[style=bold, label=2]
Q -> P[style=bold, label=1]
S -> T[style=bold, label=2, dir=none]
G -> F[style=bold, label=3]
Q -> U[style=bold, label=2, dir=none]
}
cat edges_to_dot.sh -->
echo ""|awk '{printf "digraph {\n"; printf "rankdir=LR\n"; printf "node [shape=diamond]\n"; printf "graph [layout = dot]\n"; printf "size=8\n"; printf "ratio=0.6\n" }' >edge_table_mm.dot; cat edge_table_mm |awk '{printf $1 " -> " $2 "[style=bold, label=" $3 ; if ($4 == ">") printf "]\n"; else printf ", dir=none]\n"}' >> edge_table_mm.dot;echo "}" >> edge_table_mm.dot
***
Listing of the recursive shell codes (pathFind_rec_mm.sh) for the mixed-multi graph paths finder of Item#508
cat pathFind_rec_mm.sh -->
#! /usr/bin/bash
## Edited recursive bash based mixed-multi graph paths finder from a paths list
## Arya, Nov 10, 2021, last edit Nov 17, 2021
##Usage: ./pathFind_rec_mm.sh <paths list file> <startNode> <endNode>
pullback () {
llx=`echo $1 |sed -e 's/%/ /g'|awk '{for (i=1; i<=NF-2; i++) printf $i " "; printf "\n"}'|sed -e 's/ /%/g'`
}
pathRec_func () {
let DepthRec=$DepthRec+1; let jj=$jj+1; echo $jj " DepthRec=" $DepthRec #entering the recursive function, incrementing the depth of recursion by 1
llx=$1 ## new parent path
echo $llx|tr "%" '\n'|grep '#' > grepf ##parent path grepf
endent=`echo $llx|sed -e 's/%/ /g'|awk '{print $NF}'` ##child node of the parent path
if [[ $endent != $endNode ]] ## Got a path if the child node is the destination node
then
grep -v -f grepf ./hashFiles_0/$endent > ./hashFiles/$endent ##filtering off the parent path vertices before for loop to stop vertex looping
for hx in `cat ./hashFiles/$endent|sed -e 's/ /%/g'` ## looking for new children of the child node
do
cllx=`echo $llx $hx|sed -e 's/ /%/g'` ##augmenting the parent path with the child node
pathRec_func $cllx # re-invoke pathRec_func () since the child node was good
done
else
echo $llx |sed -e 's/%/ /g'|sed -e 's? X[1-9]*_? ?g'|sed -e 's?#??g'|awk '{sum=0;for(i=2;i<NF;i=i+2) sum+=$i ; printf sum " "; print $0}'>> treedone ##write out the found path
let ii=$ii+1; echo " "$ii
fi
pullback $llx ##exiting the recursive function, pulling back the entering parent path by its child node
rm -f -r hashFiles; cp -r hashFiles_0 hashFiles #restore the hashFiles with the hashFiles_0
let DepthRec=$DepthRec-1; let jj=$jj+1; echo $jj " DepthRec=" $DepthRec ## reducing the depth of recursion
}
echo $0 $1 $2 $3
pathlist=$1
if [[ $1 && -e $pathlist ]]
then echo ""
else echo "paths list file does not exist"
echo 'Usage: ./pathFind_rec_mm.sh <paths list file> <startNode> <endNode>'
exit
fi
echo "start hasher"
echo 'the vertex_edge hash files are saved in the "hashFiles" sub-directory'
sleep 3
date
echo '###################################'
if [ -e hashFiles ]
then rm -rf hashFiles
fi
mkdir hashFiles
if [ -e hashFiles_0 ]
then rm -rf hashFiles_0
fi
mkdir hashFiles_0
if [ -e vertices ]
then rm -f vertices
fi
touch vertices
for ln in `cat $pathlist|awk '{print $1 " " $2}'`
do echo $ln >> vertices
done
sort vertices|uniq|sed -e 's?^?#?' -e 's?$?#?' > vertices_sorted
for lx in `cat $pathlist|sed -e 's? ?%?g'`
do echo $lx|sed -e 's?%? ?g'|awk '{printf "#" $1 "# "; printf "#" $2 "# "; printf $3 " " ; printf $4 "\n"}'
done >path_list.padded
for plp in `cat vertices_sorted`
do if [ -e $plp ]; then rm -f $plp; fi
touch $plp
let ii=0
## grep $plp path_list.padded |sed -e "s?$plp??" >> $plp
grep $plp path_list.padded >> $plp
cat $plp | awk '{if ($NF == ">" && $1 == "'$plp'" ) printf $2 " " $3; printf "\n"; if ($NF != ">" ) printf $0; printf "\n";}'|sed -e "s?$plp??"|grep -v '^$' > plp_xxx
mv -f plp_xxx $plp
touch plp_tmp
for ll in `cat $plp |awk '{print $2 "%" $1}'`
do let ii=$ii+1
echo "X"$ii"_"$ll| sed -e 's?%? ?' >> plp_tmp
done;
mv -f plp_tmp $plp
cp $plp ./hashFiles
mv -f $plp ./hashFiles_0
done
echo '###################################'
echo "end hasher"
date
############################################################################
if [[ $2 && $3 ]]
then startNode=`echo "#"$2"#"`; endNode=`echo "#"$3"#"`;
else echo "valid startNode and endNode must be specified"
echo 'Usage: ./pathFind_rec_mm.sh <paths list file> <startNode> <endNode>'
exit
fi
if [[ ! -e ./hashFiles/$startNode || ! -e ./hashFiles/$endNode ]]
then echo "valid startNode and endNode must be specified"
echo 'Usage: ./pathFind_rec_mm.sh <paths list file> <startNode> <endNode>'
exit
fi
echo "start path find"
echo "the path#s are reported on the screen as the successive paths are figured"
echo 'the file "treedone" saves the paths - sorted for the path lengths (the first number in each line)'
sleep 3
date; strt_time=`date|awk '{print $5}'`
echo "####################"
let pendants=1
while [ $pendants == 1 ]
do let pendants=0
for ff in `ls ./hashFiles`
do echo $ff
if [[ `wc -l ./hashFiles/$ff|awk '{print $1}'` == 0 && ($ff != $startNode && $ff != $endNode) ]]
then let pendants=1
rm -f ./hashFiles/$ff
echo YES
for fx in `ls ./hashFiles`; do grep -v $ff ./hashFiles/$fx > tmpFile; mv -f tmpFile ./hashFiles/$fx; done
fi
done
echo '###################################'
done ## removing non-relevant pendant vertex hashFiles
## exit
rm -f -r hashFiles_0; cp -r ./hashFiles hashFiles_0
rm -f treedone; touch treedone
echo $startNode ; let ii=0; let jj=0;
let DepthRec=0; echo $jj " DepthRec=" $DepthRec
pathRec_func $startNode
sort -n -k 1 treedone| sed -e 's? ? ?g' > tmpTree1
mv tmpTree1 treedone
echo "###################"
echo "end path find"
date
echo "strt_time was" $strt_time
***
Listing of all of the 211 paths extracted in Item#s 503, 504, 506
9 C 1 B 1 E 1 V 1 I 3 Q 2 U
9 C 1 B 1 E 2 I 3 Q 2 U
10 C 1 B 1 E 1 V 3 P 2 Q 2 U
11 C 1 B 1 E 1 V 2 K 1 M 1 P 2 Q 2 U
11 C 1 B 1 E 2 D 1 K 1 M 1 P 2 Q 2 U
11 C 1 B 1 E 2 H 2 I 3 Q 2 U
11 C 4 D 1 K 1 M 1 P 2 Q 2 U
12 C 1 B 1 E 1 V 3 P 1 S 2 T 1 Q 2 U
12 C 1 B 1 E 2 I 1 V 3 P 2 Q 2 U
12 C 1 B 3 F 1 H 2 I 3 Q 2 U
13 C 1 B 1 E 1 V 2 K 1 M 1 P 1 S 2 T 1 Q 2 U
13 C 1 B 1 E 1 V 2 K 1 M 1 R 1 S 1 P 2 Q 2 U
13 C 1 B 1 E 1 V 2 K 1 M 1 R 1 S 2 T 1 Q 2 U
13 C 1 B 1 E 2 D 1 K 1 M 1 P 1 S 2 T 1 Q 2 U
13 C 1 B 1 E 2 D 1 K 1 M 1 R 1 S 1 P 2 Q 2 U
13 C 1 B 1 E 2 D 1 K 1 M 1 R 1 S 2 T 1 Q 2 U
13 C 1 B 1 E 2 D 1 K 2 V 1 I 3 Q 2 U
13 C 1 B 1 E 2 D 3 L 1 M 1 P 2 Q 2 U
13 C 1 B 1 E 2 I 1 V 2 K 1 M 1 P 2 Q 2 U
13 C 4 D 1 K 1 M 1 P 1 S 2 T 1 Q 2 U
13 C 4 D 1 K 1 M 1 R 1 S 1 P 2 Q 2 U
13 C 4 D 1 K 1 M 1 R 1 S 2 T 1 Q 2 U
13 C 4 D 1 K 2 V 1 I 3 Q 2 U
13 C 4 D 2 E 1 V 1 I 3 Q 2 U
13 C 4 D 2 E 2 I 3 Q 2 U
13 C 4 D 3 L 1 M 1 P 2 Q 2 U
14 C 1 B 1 E 1 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
14 C 1 B 1 E 2 D 1 K 2 V 3 P 2 Q 2 U
14 C 1 B 1 E 2 H 2 I 1 V 3 P 2 Q 2 U
14 C 1 B 1 E 2 I 1 V 3 P 1 S 2 T 1 Q 2 U
14 C 1 B 3 F 1 H 2 E 1 V 1 I 3 Q 2 U
14 C 1 B 3 F 1 H 2 E 2 I 3 Q 2 U
14 C 4 D 1 K 2 V 3 P 2 Q 2 U
14 C 4 D 2 E 1 V 3 P 2 Q 2 U
15 C 1 B 1 E 1 V 2 K 1 D 3 L 1 M 1 P 2 Q 2 U
15 C 1 B 1 E 2 D 3 L 1 M 1 P 1 S 2 T 1 Q 2 U
15 C 1 B 1 E 2 D 3 L 1 M 1 R 1 S 1 P 2 Q 2 U
15 C 1 B 1 E 2 D 3 L 1 M 1 R 1 S 2 T 1 Q 2 U
15 C 1 B 1 E 2 H 2 I 1 V 2 K 1 M 1 P 2 Q 2 U
15 C 1 B 1 E 2 I 1 V 2 K 1 M 1 P 1 S 2 T 1 Q 2 U
15 C 1 B 1 E 2 I 1 V 2 K 1 M 1 R 1 S 1 P 2 Q 2 U
15 C 1 B 1 E 2 I 1 V 2 K 1 M 1 R 1 S 2 T 1 Q 2 U
15 C 1 B 3 F 1 H 2 E 1 V 3 P 2 Q 2 U
15 C 1 B 3 F 1 H 2 I 1 V 3 P 2 Q 2 U
15 C 4 D 1 K 2 V 1 E 2 I 3 Q 2 U
15 C 4 D 2 E 1 V 2 K 1 M 1 P 2 Q 2 U
15 C 4 D 2 E 2 H 2 I 3 Q 2 U
15 C 4 D 3 L 1 M 1 P 1 S 2 T 1 Q 2 U
15 C 4 D 3 L 1 M 1 R 1 S 1 P 2 Q 2 U
15 C 4 D 3 L 1 M 1 R 1 S 2 T 1 Q 2 U
16 C 1 B 1 E 2 D 1 K 1 M 1 P 3 V 1 I 3 Q 2 U
16 C 1 B 1 E 2 D 1 K 2 V 3 P 1 S 2 T 1 Q 2 U
16 C 1 B 1 E 2 H 2 I 1 V 3 P 1 S 2 T 1 Q 2 U
16 C 1 B 1 E 2 I 1 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
16 C 1 B 3 F 1 H 2 E 1 V 2 K 1 M 1 P 2 Q 2 U
16 C 1 B 3 F 1 H 2 E 2 D 1 K 1 M 1 P 2 Q 2 U
16 C 1 B 3 F 1 H 2 I 1 V 2 K 1 M 1 P 2 Q 2 U
16 C 4 D 1 K 1 M 1 P 3 V 1 I 3 Q 2 U
16 C 4 D 1 K 2 V 3 P 1 S 2 T 1 Q 2 U
16 C 4 D 2 E 1 V 3 P 1 S 2 T 1 Q 2 U
16 C 4 D 2 E 2 I 1 V 3 P 2 Q 2 U
17 C 1 B 1 E 1 V 2 K 1 D 3 L 1 M 1 P 1 S 2 T 1 Q 2 U
17 C 1 B 1 E 1 V 2 K 1 D 3 L 1 M 1 R 1 S 1 P 2 Q 2 U
17 C 1 B 1 E 1 V 2 K 1 D 3 L 1 M 1 R 1 S 2 T 1 Q 2 U
17 C 1 B 1 E 2 D 3 L 1 M 1 K 2 V 1 I 3 Q 2 U
17 C 1 B 1 E 2 H 2 I 1 V 2 K 1 M 1 P 1 S 2 T 1 Q 2 U
17 C 1 B 1 E 2 H 2 I 1 V 2 K 1 M 1 R 1 S 1 P 2 Q 2 U
17 C 1 B 1 E 2 H 2 I 1 V 2 K 1 M 1 R 1 S 2 T 1 Q 2 U
17 C 1 B 1 E 2 I 1 V 2 K 1 D 3 L 1 M 1 P 2 Q 2 U
17 C 1 B 3 F 1 H 2 E 1 V 3 P 1 S 2 T 1 Q 2 U
17 C 1 B 3 F 1 H 2 E 2 I 1 V 3 P 2 Q 2 U
17 C 1 B 3 F 1 H 2 I 1 V 3 P 1 S 2 T 1 Q 2 U
17 C 1 B 3 F 1 H 2 I 2 E 1 V 3 P 2 Q 2 U
17 C 4 D 1 K 2 V 1 E 2 H 2 I 3 Q 2 U
17 C 4 D 2 E 1 V 2 K 1 M 1 P 1 S 2 T 1 Q 2 U
17 C 4 D 2 E 1 V 2 K 1 M 1 R 1 S 1 P 2 Q 2 U
17 C 4 D 2 E 1 V 2 K 1 M 1 R 1 S 2 T 1 Q 2 U
17 C 4 D 2 E 2 I 1 V 2 K 1 M 1 P 2 Q 2 U
17 C 4 D 3 L 1 M 1 K 2 V 1 I 3 Q 2 U
18 C 1 B 1 E 2 D 1 K 1 M 1 R 1 S 1 P 3 V 1 I 3 Q 2 U
18 C 1 B 1 E 2 D 1 K 2 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
18 C 1 B 1 E 2 D 3 L 1 M 1 K 2 V 3 P 2 Q 2 U
18 C 1 B 1 E 2 D 3 L 1 M 1 P 3 V 1 I 3 Q 2 U
18 C 1 B 1 E 2 H 2 I 1 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
18 C 1 B 3 F 1 H 2 E 1 V 2 K 1 M 1 P 1 S 2 T 1 Q 2 U
18 C 1 B 3 F 1 H 2 E 1 V 2 K 1 M 1 R 1 S 1 P 2 Q 2 U
18 C 1 B 3 F 1 H 2 E 1 V 2 K 1 M 1 R 1 S 2 T 1 Q 2 U
18 C 1 B 3 F 1 H 2 E 2 D 1 K 1 M 1 P 1 S 2 T 1 Q 2 U
18 C 1 B 3 F 1 H 2 E 2 D 1 K 1 M 1 R 1 S 1 P 2 Q 2 U
18 C 1 B 3 F 1 H 2 E 2 D 1 K 1 M 1 R 1 S 2 T 1 Q 2 U
18 C 1 B 3 F 1 H 2 E 2 D 1 K 2 V 1 I 3 Q 2 U
18 C 1 B 3 F 1 H 2 E 2 D 3 L 1 M 1 P 2 Q 2 U
18 C 1 B 3 F 1 H 2 E 2 I 1 V 2 K 1 M 1 P 2 Q 2 U
18 C 1 B 3 F 1 H 2 I 1 V 1 E 2 D 1 K 1 M 1 P 2 Q 2 U
18 C 1 B 3 F 1 H 2 I 1 V 2 K 1 M 1 P 1 S 2 T 1 Q 2 U
18 C 1 B 3 F 1 H 2 I 1 V 2 K 1 M 1 R 1 S 1 P 2 Q 2 U
18 C 1 B 3 F 1 H 2 I 1 V 2 K 1 M 1 R 1 S 2 T 1 Q 2 U
18 C 1 B 3 F 1 H 2 I 2 E 1 V 2 K 1 M 1 P 2 Q 2 U
18 C 1 B 3 F 1 H 2 I 2 E 2 D 1 K 1 M 1 P 2 Q 2 U
18 C 4 D 1 K 1 M 1 P 3 V 1 E 2 I 3 Q 2 U
18 C 4 D 1 K 1 M 1 R 1 S 1 P 3 V 1 I 3 Q 2 U
18 C 4 D 1 K 2 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
18 C 4 D 2 E 1 B 3 F 1 H 2 I 3 Q 2 U
18 C 4 D 2 E 1 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
18 C 4 D 2 E 2 H 2 I 1 V 3 P 2 Q 2 U
18 C 4 D 2 E 2 I 1 V 3 P 1 S 2 T 1 Q 2 U
18 C 4 D 3 L 1 M 1 K 2 V 3 P 2 Q 2 U
18 C 4 D 3 L 1 M 1 P 3 V 1 I 3 Q 2 U
19 C 1 B 1 E 2 H 2 I 1 V 2 K 1 D 3 L 1 M 1 P 2 Q 2 U
19 C 1 B 1 E 2 I 1 V 2 K 1 D 3 L 1 M 1 P 1 S 2 T 1 Q 2 U
19 C 1 B 1 E 2 I 1 V 2 K 1 D 3 L 1 M 1 R 1 S 1 P 2 Q 2 U
19 C 1 B 1 E 2 I 1 V 2 K 1 D 3 L 1 M 1 R 1 S 2 T 1 Q 2 U
19 C 1 B 3 F 1 H 2 E 1 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
19 C 1 B 3 F 1 H 2 E 2 D 1 K 2 V 3 P 2 Q 2 U
19 C 1 B 3 F 1 H 2 E 2 I 1 V 3 P 1 S 2 T 1 Q 2 U
19 C 1 B 3 F 1 H 2 I 1 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
19 C 1 B 3 F 1 H 2 I 2 E 1 V 3 P 1 S 2 T 1 Q 2 U
19 C 4 D 2 E 2 H 2 I 1 V 2 K 1 M 1 P 2 Q 2 U
19 C 4 D 2 E 2 I 1 V 2 K 1 M 1 P 1 S 2 T 1 Q 2 U
19 C 4 D 2 E 2 I 1 V 2 K 1 M 1 R 1 S 1 P 2 Q 2 U
19 C 4 D 2 E 2 I 1 V 2 K 1 M 1 R 1 S 2 T 1 Q 2 U
19 C 4 D 3 L 1 M 1 K 2 V 1 E 2 I 3 Q 2 U
20 C 1 B 1 E 2 D 3 L 1 M 1 K 2 V 3 P 1 S 2 T 1 Q 2 U
20 C 1 B 1 E 2 D 3 L 1 M 1 R 1 S 1 P 3 V 1 I 3 Q 2 U
20 C 1 B 3 F 1 H 2 E 1 V 2 K 1 D 3 L 1 M 1 P 2 Q 2 U
20 C 1 B 3 F 1 H 2 E 2 D 3 L 1 M 1 P 1 S 2 T 1 Q 2 U
20 C 1 B 3 F 1 H 2 E 2 D 3 L 1 M 1 R 1 S 1 P 2 Q 2 U
20 C 1 B 3 F 1 H 2 E 2 D 3 L 1 M 1 R 1 S 2 T 1 Q 2 U
20 C 1 B 3 F 1 H 2 E 2 I 1 V 2 K 1 M 1 P 1 S 2 T 1 Q 2 U
20 C 1 B 3 F 1 H 2 E 2 I 1 V 2 K 1 M 1 R 1 S 1 P 2 Q 2 U
20 C 1 B 3 F 1 H 2 E 2 I 1 V 2 K 1 M 1 R 1 S 2 T 1 Q 2 U
20 C 1 B 3 F 1 H 2 I 1 V 1 E 2 D 1 K 1 M 1 P 1 S 2 T 1 Q 2 U
20 C 1 B 3 F 1 H 2 I 1 V 1 E 2 D 1 K 1 M 1 R 1 S 1 P 2 Q 2 U
20 C 1 B 3 F 1 H 2 I 1 V 1 E 2 D 1 K 1 M 1 R 1 S 2 T 1 Q 2 U
20 C 1 B 3 F 1 H 2 I 1 V 1 E 2 D 3 L 1 M 1 P 2 Q 2 U
20 C 1 B 3 F 1 H 2 I 1 V 2 K 1 D 3 L 1 M 1 P 2 Q 2 U
20 C 1 B 3 F 1 H 2 I 2 E 1 V 2 K 1 M 1 P 1 S 2 T 1 Q 2 U
20 C 1 B 3 F 1 H 2 I 2 E 1 V 2 K 1 M 1 R 1 S 1 P 2 Q 2 U
20 C 1 B 3 F 1 H 2 I 2 E 1 V 2 K 1 M 1 R 1 S 2 T 1 Q 2 U
20 C 1 B 3 F 1 H 2 I 2 E 2 D 1 K 1 M 1 P 1 S 2 T 1 Q 2 U
20 C 1 B 3 F 1 H 2 I 2 E 2 D 1 K 1 M 1 R 1 S 1 P 2 Q 2 U
20 C 1 B 3 F 1 H 2 I 2 E 2 D 1 K 1 M 1 R 1 S 2 T 1 Q 2 U
20 C 1 B 3 F 1 H 2 I 2 E 2 D 3 L 1 M 1 P 2 Q 2 U
20 C 4 D 1 K 1 M 1 P 3 V 1 E 2 H 2 I 3 Q 2 U
20 C 4 D 1 K 1 M 1 R 1 S 1 P 3 V 1 E 2 I 3 Q 2 U
20 C 4 D 1 K 2 V 1 E 1 B 3 F 1 H 2 I 3 Q 2 U
20 C 4 D 2 E 2 H 2 I 1 V 3 P 1 S 2 T 1 Q 2 U
20 C 4 D 2 E 2 I 1 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
20 C 4 D 3 L 1 M 1 K 2 V 3 P 1 S 2 T 1 Q 2 U
20 C 4 D 3 L 1 M 1 P 3 V 1 E 2 I 3 Q 2 U
20 C 4 D 3 L 1 M 1 R 1 S 1 P 3 V 1 I 3 Q 2 U
21 C 1 B 1 E 2 H 2 I 1 V 2 K 1 D 3 L 1 M 1 P 1 S 2 T 1 Q 2 U
21 C 1 B 1 E 2 H 2 I 1 V 2 K 1 D 3 L 1 M 1 R 1 S 1 P 2 Q 2 U
21 C 1 B 1 E 2 H 2 I 1 V 2 K 1 D 3 L 1 M 1 R 1 S 2 T 1 Q 2 U
21 C 1 B 3 F 1 H 2 E 2 D 1 K 1 M 1 P 3 V 1 I 3 Q 2 U
21 C 1 B 3 F 1 H 2 E 2 D 1 K 2 V 3 P 1 S 2 T 1 Q 2 U
21 C 1 B 3 F 1 H 2 E 2 I 1 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
21 C 1 B 3 F 1 H 2 I 2 E 1 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
21 C 1 B 3 F 1 H 2 I 2 E 2 D 1 K 2 V 3 P 2 Q 2 U
21 C 4 D 2 E 1 B 3 F 1 H 2 I 1 V 3 P 2 Q 2 U
21 C 4 D 2 E 2 H 2 I 1 V 2 K 1 M 1 P 1 S 2 T 1 Q 2 U
21 C 4 D 2 E 2 H 2 I 1 V 2 K 1 M 1 R 1 S 1 P 2 Q 2 U
21 C 4 D 2 E 2 H 2 I 1 V 2 K 1 M 1 R 1 S 2 T 1 Q 2 U
21 C 4 D 3 L 1 M 1 K 2 V 1 E 2 H 2 I 3 Q 2 U
22 C 1 B 3 F 1 H 2 E 1 V 2 K 1 D 3 L 1 M 1 P 1 S 2 T 1 Q 2 U
22 C 1 B 3 F 1 H 2 E 1 V 2 K 1 D 3 L 1 M 1 R 1 S 1 P 2 Q 2 U
22 C 1 B 3 F 1 H 2 E 1 V 2 K 1 D 3 L 1 M 1 R 1 S 2 T 1 Q 2 U
22 C 1 B 3 F 1 H 2 E 2 D 3 L 1 M 1 K 2 V 1 I 3 Q 2 U
22 C 1 B 3 F 1 H 2 E 2 I 1 V 2 K 1 D 3 L 1 M 1 P 2 Q 2 U
22 C 1 B 3 F 1 H 2 I 1 V 1 E 2 D 3 L 1 M 1 P 1 S 2 T 1 Q 2 U
22 C 1 B 3 F 1 H 2 I 1 V 1 E 2 D 3 L 1 M 1 R 1 S 1 P 2 Q 2 U
22 C 1 B 3 F 1 H 2 I 1 V 1 E 2 D 3 L 1 M 1 R 1 S 2 T 1 Q 2 U
22 C 1 B 3 F 1 H 2 I 1 V 2 K 1 D 3 L 1 M 1 P 1 S 2 T 1 Q 2 U
22 C 1 B 3 F 1 H 2 I 1 V 2 K 1 D 3 L 1 M 1 R 1 S 1 P 2 Q 2 U
22 C 1 B 3 F 1 H 2 I 1 V 2 K 1 D 3 L 1 M 1 R 1 S 2 T 1 Q 2 U
22 C 1 B 3 F 1 H 2 I 2 E 1 V 2 K 1 D 3 L 1 M 1 P 2 Q 2 U
22 C 1 B 3 F 1 H 2 I 2 E 2 D 3 L 1 M 1 P 1 S 2 T 1 Q 2 U
22 C 1 B 3 F 1 H 2 I 2 E 2 D 3 L 1 M 1 R 1 S 1 P 2 Q 2 U
22 C 1 B 3 F 1 H 2 I 2 E 2 D 3 L 1 M 1 R 1 S 2 T 1 Q 2 U
22 C 4 D 1 K 1 M 1 R 1 S 1 P 3 V 1 E 2 H 2 I 3 Q 2 U
22 C 4 D 2 E 1 B 3 F 1 H 2 I 1 V 2 K 1 M 1 P 2 Q 2 U
22 C 4 D 2 E 2 H 2 I 1 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
22 C 4 D 3 L 1 M 1 P 3 V 1 E 2 H 2 I 3 Q 2 U
22 C 4 D 3 L 1 M 1 R 1 S 1 P 3 V 1 E 2 I 3 Q 2 U
23 C 1 B 3 F 1 H 2 E 2 D 1 K 1 M 1 R 1 S 1 P 3 V 1 I 3 Q 2 U
23 C 1 B 3 F 1 H 2 E 2 D 1 K 2 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
23 C 1 B 3 F 1 H 2 E 2 D 3 L 1 M 1 K 2 V 3 P 2 Q 2 U
23 C 1 B 3 F 1 H 2 E 2 D 3 L 1 M 1 P 3 V 1 I 3 Q 2 U
23 C 1 B 3 F 1 H 2 I 2 E 2 D 1 K 2 V 3 P 1 S 2 T 1 Q 2 U
23 C 4 D 1 K 1 M 1 P 3 V 1 E 1 B 3 F 1 H 2 I 3 Q 2 U
23 C 4 D 2 E 1 B 3 F 1 H 2 I 1 V 3 P 1 S 2 T 1 Q 2 U
24 C 1 B 3 F 1 H 2 E 2 I 1 V 2 K 1 D 3 L 1 M 1 P 1 S 2 T 1 Q 2 U
24 C 1 B 3 F 1 H 2 E 2 I 1 V 2 K 1 D 3 L 1 M 1 R 1 S 1 P 2 Q 2 U
24 C 1 B 3 F 1 H 2 E 2 I 1 V 2 K 1 D 3 L 1 M 1 R 1 S 2 T 1 Q 2 U
24 C 1 B 3 F 1 H 2 I 2 E 1 V 2 K 1 D 3 L 1 M 1 P 1 S 2 T 1 Q 2 U
24 C 1 B 3 F 1 H 2 I 2 E 1 V 2 K 1 D 3 L 1 M 1 R 1 S 1 P 2 Q 2 U
24 C 1 B 3 F 1 H 2 I 2 E 1 V 2 K 1 D 3 L 1 M 1 R 1 S 2 T 1 Q 2 U
24 C 4 D 2 E 1 B 3 F 1 H 2 I 1 V 2 K 1 M 1 P 1 S 2 T 1 Q 2 U
24 C 4 D 2 E 1 B 3 F 1 H 2 I 1 V 2 K 1 M 1 R 1 S 1 P 2 Q 2 U
24 C 4 D 2 E 1 B 3 F 1 H 2 I 1 V 2 K 1 M 1 R 1 S 2 T 1 Q 2 U
24 C 4 D 3 L 1 M 1 K 2 V 1 E 1 B 3 F 1 H 2 I 3 Q 2 U
24 C 4 D 3 L 1 M 1 R 1 S 1 P 3 V 1 E 2 H 2 I 3 Q 2 U
25 C 1 B 3 F 1 H 2 E 2 D 3 L 1 M 1 K 2 V 3 P 1 S 2 T 1 Q 2 U
25 C 1 B 3 F 1 H 2 E 2 D 3 L 1 M 1 R 1 S 1 P 3 V 1 I 3 Q 2 U
25 C 1 B 3 F 1 H 2 I 2 E 2 D 1 K 2 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
25 C 1 B 3 F 1 H 2 I 2 E 2 D 3 L 1 M 1 K 2 V 3 P 2 Q 2 U
25 C 4 D 1 K 1 M 1 R 1 S 1 P 3 V 1 E 1 B 3 F 1 H 2 I 3 Q 2 U
25 C 4 D 2 E 1 B 3 F 1 H 2 I 1 V 3 P 1 M 1 R 1 S 2 T 1 Q 2 U
25 C 4 D 3 L 1 M 1 P 3 V 1 E 1 B 3 F 1 H 2 I 3 Q 2 U
27 C 1 B 3 F 1 H 2 I 2 E 2 D 3 L 1 M 1 K 2 V 3 P 1 S 2 T 1 Q 2 U
27 C 4 D 3 L 1 M 1 R 1 S 1 P 3 V 1 E 1 B 3 F 1 H 2 I 3 Q 2 U
***
Listing of the shell codes (pathFind_rec_ed.sh) for the recursive bash graph paths finder of Item#506
#! /usr/bin/bash
## Edited bash based recursive graph paths finder from a paths list
## Arya, Nov 1, 2021
##Usage: ./pathFind_rec_ed.sh <paths list file> <startNode> <endNode>
pullback () {
llx=`echo $1 |sed -e 's/%/ /g'|awk '{for (i=1; i<=NF-2; i++) printf $i " "; printf "\n"}'|sed -e 's/ /%/g'`
}
pathRec_func () {
let DepthRec=$DepthRec+1; echo "DepthRec=" $DepthRec #entering the recursive function, incrementing the depth of recursion by 1
llx=$1 ## new parent path
echo $llx|tr "%" '\n'|grep '#' > grepf ##parent path grepf
endent=`echo $llx|sed -e 's/%/ /g'|awk '{print $NF}'` ##child node of the parent path
if [[ $endent != $endNode ]] ## Got a path if the child node is the destination node
then
grep -v -f grepf ./hashFiles_0/$endent > ./hashFiles/$endent ##filtering off the parent path vertices before for loop to stop vertex looping
for hx in `cat ./hashFiles/$endent|sed -e 's/ /%/g'` ## looking for new children of the child node
do
cllx=`echo $llx $hx|sed -e 's/ /%/g'` ##augmenting the parent path with the child node
pathRec_func $cllx # re-invoke pathRec_func () since the child node was good
done
else
echo $llx |sed -e 's/%/ /g'|sed -e 's? X[1-9]*_? ?g'|sed -e 's?#??g'|awk '{sum=0;for(i=2;i<NF;i=i+2) sum+=$i ; printf sum " "; print $0}'>> treedone ##write out the found path
let ii=$ii+1; echo " "$ii
fi
pullback $llx ##exiting the recursive function, pulling back the entering parent path by its child node
rm -f -r hashFiles; cp -r hashFiles_0 hashFiles #restore the hashFiles with the hashFiles_0
let DepthRec=$DepthRec-1; echo "DepthRec=" $DepthRec ## reducing the depth of recursion
}
pathlist=$1
if [[ $1 && -e $pathlist ]]
then echo ""
else echo "paths list file does not exist"
echo 'Usage: ./pathFind_rec_ed.sh <paths list file> <startNode> <endNode>'
exit
fi
echo "start hasher"
echo 'the vertex_edge hash files are saved in the "hashFiles" sub-directory'
sleep 3
date
echo '###################################'
if [ -e hashFiles ]
then rm -rf hashFiles
fi
mkdir hashFiles
if [ -e hashFiles_0 ]
then rm -rf hashFiles_0
fi
mkdir hashFiles_0
if [ -e vertices ]
then rm -f vertices
fi
touch vertices
for ln in `cat $pathlist|awk '{print $1 " " $2}'`
do echo $ln >> vertices
done
sort vertices|uniq|sed -e 's?^?#?' -e 's?$?#?' > vertices_sorted
for lx in `cat $pathlist|sed -e 's? ?%?g'`
do echo $lx|sed -e 's?%? ?g'|awk '{printf "#" $1 "# "; printf "#" $2 "# "; printf $3 "\n"}'
done >path_list.padded
for plp in `cat vertices_sorted`
do if [ -e $plp ]; then rm -f $plp; fi
touch $plp
let ii=0
grep $plp path_list.padded |sed -e "s?$plp??" >> $plp
touch plp_tmp
for ll in `cat $plp |awk '{print $NF "%" $1}'`
do let ii=$ii+1
echo "X"$ii"_"$ll| sed -e 's?%? ?' >> plp_tmp
done;
mv -f plp_tmp $plp
cp $plp ./hashFiles
mv -f $plp ./hashFiles_0
done
echo '###################################'
echo "end hasher"
date
############################################################################
if [[ $2 && $3 ]]
then startNode=`echo "#"$2"#"`; endNode=`echo "#"$3"#"`;
else echo "valid startNode and endNode must be specified"
echo 'Usage: ./pathFind_rec_ed.sh <paths list file> <startNode> <endNode>'
exit
fi
if [[ ! -e ./hashFiles/$startNode || ! -e ./hashFiles/$endNode ]]
then echo "valid startNode and endNode must be specified"
echo 'Usage: ./pathFind_rec_ed.sh <paths list file> <startNode> <endNode>'
exit
fi
echo "start path find"
echo "the path#s are reported on the screen as the successive paths are figured"
echo 'the file "treedone" saves the paths - sorted for the path lengths (the first number in each line)'
sleep 3
date; strt_time=`date|awk '{print $5}'`
echo "####################"
let pendants=1
while [ $pendants == 1 ]
do let pendants=0
for ff in `ls ./hashFiles`
do echo $ff
if [[ `wc -l ./hashFiles/$ff|awk '{print $1}'` == 1 && ($ff != $startNode && $ff != $endNode) ]]
then let pendants=1
rm -f ./hashFiles/$ff
echo YES
for fx in `ls ./hashFiles`; do grep -v $ff ./hashFiles/$fx > tmpFile; mv -f tmpFile ./hashFiles/$fx; done
fi
done
echo '###################################'
done ## removing non-relevant pendant vertex hashFiles
## exit
rm -f -r hashFiles_0; cp -r ./hashFiles hashFiles_0
rm -f treedone; touch treedone
echo $startNode ; let ii=0; let jj=1;
let DepthRec=0; echo "DepthRec=" $DepthRec
pathRec_func $startNode
sort -n -k 1 treedone| uniq| sed -e 's? ? ?g' > tmpTree1
mv tmpTree1 treedone
echo "###################"
echo "end path find"
date
echo "strt_time was" $strt_time
***
The Transcript for the run of the recursive shell of Item#504, as needed to make the Depth of Recusion plot of Item#505; also, the plotting codes used are listed
transcript_home_factory -->
start hasher
the vertex_edge hash files are saved in the "hashFiles" sub-directory
Fri 29 Oct 2021 11:40:54 AM PDT
###################################
###################################
end hasher
Fri 29 Oct 2021 11:40:54 AM PDT
start path find
the path#s are reported on the screen as the successive paths are figured
the file "treedone" saves the paths - sorted for the path lengths (the first number in each line)
Fri 29 Oct 2021 11:40:57 AM PDT
####################
#home#
DepthRec= 0
DepthRec= 1
DepthRec= 2
DepthRec= 3
DepthRec= 4
DepthRec= 5
DepthRec= 6
1
DepthRec= 5
DepthRec= 4
DepthRec= 3
DepthRec= 2
DepthRec= 3
DepthRec= 4
DepthRec= 5
DepthRec= 4
DepthRec= 3
DepthRec= 4
2
DepthRec= 3
DepthRec= 2
DepthRec= 1
DepthRec= 2
DepthRec= 3
DepthRec= 4
DepthRec= 5
DepthRec= 4
DepthRec= 5
3
DepthRec= 4
DepthRec= 3
DepthRec= 2
DepthRec= 3
DepthRec= 4
DepthRec= 5
DepthRec= 4
DepthRec= 5
4
DepthRec= 4
DepthRec= 3
DepthRec= 2
DepthRec= 1
DepthRec= 2
DepthRec= 3
DepthRec= 4
DepthRec= 5
DepthRec= 4
DepthRec= 3
DepthRec= 2
DepthRec= 3
DepthRec= 4
DepthRec= 5
DepthRec= 4
DepthRec= 3
DepthRec= 2
DepthRec= 3
5
DepthRec= 2
DepthRec= 1
DepthRec= 0
###################
end path find
Fri 29 Oct 2021 11:40:58 AM PDT
strt_time was 11:40:57
One could capture the above transcript using command
./pathFind_rec.sh path_list home factory |tee transcript_home_facory
The shell code for parsing the transcript to create the gnuplot .dat file is:
parse_transcript.sh -->
#! /usr/bin/bash
##USAGE : parse_transcript.sh <transcript_file> < .dat file for gnuplot>
for ii in `cat $1|grep -A 1 'DepthRec=' |grep -v '###' |sed -e "s?\s\+? ?g"|sed -e 's?= ?=?'|sed -e 's?\n??'` ; do echo $ii|awk '{printf $ii " "}'; done|tr 'DepthRec=' '\n'|grep -v '^$'|grep -n '^'|sed -e 's?\:? ?'|awk '{if (NF==3) printf $1 " " $2 " " $2; printf "\n"; if (NF==2) printf $1 " " $2 ; printf "\n"}'|grep -v '^$' |tee $2
--------------------------------------------
e.g.,
chmod 755 parse_transcript.sh
./parse_transcript.sh transcript_home_factory DR_paths.dat
Then the gnuplot script uses the DR_paths.dat as in:
DepthRec.gnu -->
set xlabel "Recursive function entry/exit events"
set ylabel "Depth of Recursion"
plot 'DR_paths.dat' u 1:2 w lp lw 3 lc 3 pt 3 t "Depths of Recursion", \
'DR_paths.dat' using 1:3 w points pt 6 ps 3 lc rgb 'red' t "paths found"
set term jpeg
set output "DR_paths.jpg"
replot
set term x11
--------------------------------------------
The command used for running the gnuplot was:
gnuplot -persist DepthRec.gnu
***
Listing of the path_list (input file) and the shell codes (pathFind_rec.sh) for the recursive bash graph paths finder of Item#504
path_list -->
home doctors 1
home market 1
market doctors 2
market police 1
doctors school 1
police school 1
home school 3
school factory 2
pathFind_rec.sh -->
#! /usr/bin/bash
## Simple bash based recursive graph paths finder from a paths list
## Arya, October 25, 2021
pullback () {
llx=`echo $1 |sed -e 's/%/ /g'|awk '{for (i=1; i<=NF-2; i++) printf $i " "; printf "\n"}'|sed -e 's/ /%/g'`
}
pathRec_func () {
let DepthRec=$DepthRec+1; echo "DepthRec=" $DepthRec #entering the recursive function, incrementing the depth of recursion by 1
llx=$1 ## new parent path
endent=`echo $llx|sed -e 's/%/ /g'|awk '{print $NF}'` ##child node of the parent path
if [[ $endent != $endNode ]] ## Got a path if the child node is the destination node
then for hx in `cat ./hashFiles/$endent|sed -e 's/ /%/g'` ## looking for new children of the child node
do hx_node=`echo $hx |sed -e 's/%/ /g'|awk '{print $NF}'`
hx_padded=`echo "%"$hx_node"%"`
cllx=`echo $llx $hx|sed -e 's/ /%/g'` ##augmenting the parent path with the new child node
if [[ `echo "%"$llx | grep $hx_padded` ]]
then
badchildnode="no looping around"
pullback $cllx
else
pathRec_func $cllx # re-invoke pathRec_func () since the child node was good
fi
done
else
echo $llx |sed -e 's/%/ /g'|sed -e 's? X[1-9]*_? ?g'|sed -e 's?#??g'|awk '{sum=0;for(i=2;i<NF;i=i+2) sum+=$i ; printf sum " "; print $0}'>> treedone ##write out the found path
let ii=$ii+1; echo " "$ii
fi
pullback $llx ##exiting the recursive function, pulling back the entering parent path by its child node
let DepthRec=$DepthRec-1; echo "DepthRec=" $DepthRec ## reducing the depth of recursion
}
pathlist=$1
if [[ $1 && -e $pathlist ]]
then echo ""
else echo "paths list file does not exist"
echo 'Usage: ./pathFind_rec.sh <paths list file> <startNode> <endNode>'
exit
fi
echo "start hasher"
echo 'the vertex_edge hash files are saved in the "hashFiles" sub-directory'
sleep 3
date
echo '###################################'
if [ -e hashFiles ]
then rm -rf hashFiles
fi
mkdir hashFiles
if [ -e vertices ]
then rm -f vertices
fi
touch vertices
for ln in `cat $pathlist|awk '{print $1 " " $2}'`
do echo $ln >> vertices
done
sort vertices|uniq|sed -e 's?^?#?' -e 's?$?#?' > vertices_sorted
for lx in `cat $pathlist|sed -e 's? ?%?g'`
do echo $lx|sed -e 's?%? ?g'|awk '{printf "#" $1 "# "; printf "#" $2 "# "; printf $3 "\n"}'
done >path_list.padded
for plp in `cat vertices_sorted`
do if [ -e $plp ]; then rm -f $plp; fi
touch $plp
let ii=0
grep $plp path_list.padded |sed -e "s?$plp??" >> $plp
touch plp_tmp
for ll in `cat $plp |awk '{print $NF "%" $1}'`
do let ii=$ii+1
echo "X"$ii"_"$ll| sed -e 's?%? ?' >> plp_tmp
done;
## echo $plp
## cat $plp
## cat plp_tmp
mv -f plp_tmp $plp
cp $plp ./hashFiles
done
echo '###################################'
echo "end hasher"
date
############################################################################
if [[ $2 && $3 ]]
then startNode=`echo "#"$2"#"`; endNode=`echo "#"$3"#"`;
else echo "valid startNode and endNode must be specified"
echo 'Usage: ./pathFind_rec.sh <paths list file> <startNode> <endNode>'
exit
fi
if [[ ! -e ./hashFiles/$startNode || ! -e ./hashFiles/$endNode ]]
then echo "valid startNode and endNode must be specified"
echo 'Usage: ./pathFind_rec.sh <paths list file> <startNode> <endNode>'
exit
fi
echo "start path find"
echo "the path#s are reported on the screen as the successive paths are figured"
echo 'the file "treedone" saves the paths - sorted for the path lengths (the first number in each line)'
sleep 3
date; strt_time=`date|awk '{print $5}'`
echo "####################"
for ff in `ls ./hashFiles`; do grep -v $startNode ./hashFiles/$ff > tmpFile; mv -f tmpFile ./hashFiles/$ff; done
rm -f treedone; touch treedone
echo $startNode ; let ii=0
let DepthRec=0; echo "DepthRec=" $DepthRec
pathRec_func $startNode
sort -n -k 1 treedone| uniq| sed -e 's? ? ?g' > tmpTree1
mv tmpTree1 treedone
echo "###################"
echo "end path find"
date
echo "strt_time was" $strt_time
Listing of the path_list.txt (input file) and the shell codes (graphPaths.sh) for the graph paths finder of Item#503
path_list.txt -->
A B 4
B C 1
C D 4
D L 3
L N 1
B E 1
E V 1
V P 3
P S 1
E D 2
D K 1
K V 2
K M 1
M L 1
M P 1
M O 1
M R 1
R S 1
B F 3
F H 1
H I 2
I Q 3
Q T 1
H E 2
E I 2
I V 1
P Q 2
S T 2
F G 3
Q U 2
graphPaths.sh -->
#! /usr/bin/bash
## bash based non-recursive graph paths finder from a paths list file
## Arya, Oct 20, 2021
pathlist=$1
if [[ $1 && -e $pathlist ]]
then echo ""
else echo "paths list file does not exist"
echo "Usage: ./graphPaths.sh <paths list file> <startNode> <endNode>"
exit
fi
echo "start hasher"
echo 'the vertex_edge hash files are saved in the "hashFiles" sub-directory'
sleep 3
date
echo '###################################'
if [ -e hashFiles ]
then rm -rf hashFiles
fi
mkdir hashFiles
if [ -e vertices ]
then rm -f vertices
fi
touch vertices
for ln in `cat $pathlist|awk '{print $1 " " $2}'`
do echo $ln >> vertices
done
sort vertices|uniq|sed -e 's?^?#?' -e 's?$?#?' > vertices_sorted
for lx in `cat $pathlist|sed -e 's? ?%?g'`
do echo $lx|sed -e 's?%? ?g'|awk '{printf "#" $1 "# "; printf "#" $2 "# "; printf $3 "\n"}'
done >path_list.padded
for plp in `cat vertices_sorted`
do if [ -e $plp ]; then rm -f $plp; fi
touch $plp
let ii=0
grep $plp path_list.padded |sed -e "s?$plp??" >> $plp
touch plp_tmp
for ll in `cat $plp |awk '{print $NF "%" $1}'`
do let ii=$ii+1
echo "X"$ii"_"$ll| sed -e 's?%? ?' >> plp_tmp
done;
## echo $plp
## cat $plp
## cat plp_tmp
mv -f plp_tmp $plp
cp $plp ./hashFiles
done
echo '###################################'
echo "end hasher"
date
############################################################################
if [[ $2 && $3 ]]
then startNode=`echo "#"$2"#"`; endNode=`echo "#"$3"#"`;
else echo "valid startNode and endNode must be specified"
echo "Usage: ./graphPaths.sh <paths list file> <startNode> <endNode>"
exit
fi
if [[ ! -e ./hashFiles/$startNode || ! -e ./hashFiles/$endNode ]]
then echo "valid startNode and endNode must be specified"
echo "Usage: ./graphPaths.sh <paths list file> <startNode> <endNode>"
exit
fi
echo "start path find"
echo "the path#s are reported on the screen as the successive paths are figured"
echo 'the file "treedone" saves the paths - sorted for the path lengths (the first number in each line)'
sleep 3
date
echo "####################"
#startNode='#U#'
#endNode='#C#'
rm -f treeFile; touch treeFile; echo $startNode >> treeFile
rm -f tmpTree; touch tmpTree
rm -f treedone; touch treedone
mv ./hashFiles/$endNode ./hashFiles/ENDNODE
let ii=0
let JJ=1
while [[ $JJ == 1 ]]
do let JJ=0
for lx in `cat treeFile|sed -e 's/ /%/g'`
do treeLine=`echo $lx|sed -e 's/%/ /g'`
endent=`echo $treeLine|awk '{print $NF}'`
if [[ $endent != $endNode ]]
then for hx in `cat ./hashFiles/$endent|sed -e 's/ /%/g'`
do hx_node=`echo $hx |sed -e 's/%/ /g'|awk '{print $NF}'`
hx_padded=`echo "%"$hx_node"%"`
if [[ `echo "%"$lx | grep $hx_padded` ]]
then aa=`echo "no re-enter"`
else echo $treeLine $hx|sed -e 's/%/ /g' >> tmpTree
fi
done
fi
if [[ `echo $treeLine |grep $endNode` ]]
then echo $treeLine |sed -e 's? X[1-9]*_? ?g'|sed -e 's?#??g'|awk '{sum=0;for(i=2;i<NF;i=i+2) sum+=$i ; printf sum " "; print $0}'>> treedone
let ii=$ii+1; echo $ii
fi
done
if [ -e tmpTree ]
then mv -f tmpTree treeFile
let JJ=1
fi
done
sort -n -k 1 treedone> tmpTree
mv tmpTree treedone
if [ -e treeFile ]
then rm -f treeFile
fi
mv ./hashFiles/ENDNODE ./hashFiles/$endNode
echo "####################"
echo "end path find"
date
echo "####################"
***
Listing of shell codes for the recursive bash tree parser of Item#502 treeRec.sh -->
#! /usr/bin/bash
## Simple bash based recursive Tree parser from a Spice Netlist
## Arya, Sept 6, 2021
treeRec_func () {
llx=$1
subName=`echo $llx|sed -e 's/#/ /g'|awk '{print $NF}'`
for hx in `cat ./hashFiles/$subName`
do lx=`echo $hx|sed -e 's/#/ /g'`
wrtln=`echo $llx $lx |sed -e 's/#/ /g'`
echo $wrtln; echo $wrtln >> treedone
cllx=`echo $llx $lx|sed -e 's/ /#/g'|sed -e 's/##/#/'`
treeRec_func $cllx
llx=`echo $llx|sed -e 's/#/ /g'|awk '{for (i=1; i<=NF-2; i++) printf $i " "; printf "\n"}'|sed -e 's/#/ /g'`
done
}
spicenet=$1
if [[ $1 && -e $spicenet ]]
then echo ""
else echo "spice netlist file does not exist"
echo "Usage: ./treeparse.sh <spice netlist> <topSubCkt>"
exit
fi
echo "start hasher"
date
echo '###################################'
if [ -e hashFiles ]
then rm -rf hashFiles
fi
mkdir hashFiles
for ix in `cat $spicenet|sed -e 's?\s\+$??'|sed -e 's/ /#/g'`
do ll=`echo $ix|sed -e 's/#/ /g'`
l1=`echo $ll|awk '{print $1}'`
l2=`echo $ll|awk '{print $2}'`
lend=`echo $ll|awk '{print $NF}'`
if [[ $l1 == '.subckt' || $l1 == '.SUBCKT' ]]
then echo $l2; touch ./hashFiles/$l2
subckt=`echo $l2`
fi
if [[ ${l1::1} == "x" || ${l1::1} == "X" ]]
then echo $l1'#'$lend; echo $l1'#'$lend >> ./hashFiles/$subckt
fi
done
echo '###################################'
echo "end hasher"
date
############################################################################
topSub=$2
if [[ $2 && -e ./hashFiles/$topSub ]]
then echo ""
else echo "valid top subckt named hash doesn't exist"
echo "Usage: ./treeparse.sh <spice netlist> <topSubCkt>"
exit
fi
echo $topSub
echo "start tree parse"
date
echo "####################"
rm -f treedone; touch treedone
echo $topSub ; echo $topSub >> treedone
treeRec_func $topSub
sort treedone |uniq > tmpTree; mv -f tmpTree treedone
echo "###################"
echo "end tree parse"
date
***
Listing of shell codes for the non-recursive bash tree parser of Item#501 treeparse.sh -->
#! /usr/bin/bash
## Simple bash based non-recursive Tree parser from a Spice Netlist
## Arya, Aug 27, 2021
spicenet=$1
if [[ $1 && -e $spicenet ]]
then echo ""
else echo "spice netlist file does not exist"
echo "Usage: ./treeparse.sh <spice netlist> <topSubCkt>"
exit
fi
echo "start hasher"
date
echo '###################################'
if [ -e hashFiles ]
then rm -rf hashFiles
fi
mkdir hashFiles
for ix in `cat $spicenet|sed -e 's?\s\+$??'|sed -e 's/ /#/g'`
do ll=`echo $ix|sed -e 's/#/ /g'`
l1=`echo $ll|awk '{print $1}'`
l2=`echo $ll|awk '{print $2}'`
lend=`echo $ll|awk '{print $NF}'`
if [[ $l1 == '.subckt' || $l1 == '.SUBCKT' ]]
then echo $l2; touch ./hashFiles/$l2
subckt=`echo $l2`
fi
if [[ ${l1::1} == "x" || ${l1::1} == "X" ]]
then echo $l1'#'$lend; echo $l1'#'$lend >> ./hashFiles/$subckt
fi
done
echo '###################################'
echo "end hasher"
date
############################################################################
topSub=$2
if [[ $2 && -e ./hashFiles/$topSub ]]
then echo ""
else echo "valid top subckt named hash doesn't exist"
echo "Usage: ./treeparse.sh <spice netlist> <topSubCkt>"
exit
fi
echo "start tree parse"
date
echo "####################"
rm -f treeFile; touch treeFile; echo $topSub >> treeFile
rm -f tmpTree; touch tmpTree
rm -f treedone; touch treedone
let JJ=1
while [[ $JJ == 1 ]]
do let JJ=0
for lx in `cat treeFile|sed -e 's/ /#/g'`
do treeLine=`echo $lx|sed -e 's/#/ /g'`
endent=`echo $treeLine|awk '{print $NF}'`
for hx in `cat ./hashFiles/$endent`
do echo $treeLine $hx|sed -e 's/#/ /g' >> tmpTree
done
echo $treeLine >> treedone
done
if [ -e tmpTree ]
then mv -f tmpTree treeFile
## cat tmpTree
## echo 'mv -f tmpTree treeFile'
let JJ=1
fi
## cat treedone
done
sort treedone|uniq|tee tmpTree
mv tmpTree treedone
echo "###################"
echo "end tree parse"
date
***
Listing of shell codes for the recursive bash circuit flattener of Item#497
fltnr2.sh -->
## Arya, Oct 27, 2012, slight edit Aug 07, 2021
## Using parentheses [(, )] for "?" to avoid special char sensitivity
for ix in `cat test1.net|sed -e 's?\s\+$??'|sed -e 's/ /#/g'`
do ll=`echo $ix|sed -e 's/#/ /g'`
l1=`echo $ll|awk '{print $1}'`
if [[ $l1 == '.subckt' || $l1 == '.SUBCKT' ]]
then l2=`echo $ll|awk '{print $2}'`
fff='@'$l2'@'
rm -f $fff
touch $fff
echo $ll|awk '{printf $1;for (i=2; i<=NF; i++) printf " @" $i "@ "; printf "\n"}' >> $fff;
else if [[ $l1 == '.ends' || $l1 == '.ENDS' ]]; then echo $ll >> $fff
else echo $ll |awk '{for (i=1; i<=1; i++) printf " @" $i "('$l2')@ "; for (i=2; i<=NF; i++) printf " @" $i "@ "; printf "\n"}'>> $fff
fi
fi;
done
flatten_func.fsh -->
## Arya, Oct 27, 2012, edited Oct 31, 2012
## Arya, Aug 07, 2021, slight edit
flatten_func () {
let rec_depth=$rec_depth+1 ; echo "****REC_DEPTH =" $rec_depth
for ii in `cat $fff|sed -e 's/ /#/g'`
do ll=`echo $ii|sed -e 's/#/ /g'`
fld1=`echo $ll|awk '{print $1}'`
if [[ `echo $fld1|grep '@D'` || `echo $fld1|grep '@C'` || `echo $fld1|grep '@R'` ]]
then nn=4
else if [ `echo $fld1|grep '@Q'` ]
then nn=5
else if [ `echo $fld1|grep '@M'` ]
then nn=6
else if [ `echo $fld1|grep '@X'` ]
then nn=`echo $ll|awk '{print NF}'`; let nn++
# then nn=`echo $ll|awk '{print NF}'`;
fi
fi
fi
fi
if [ $erx ]
then let rec_depth=$rec_depth-1 ; echo "REC_DEPTH =" $rec_depth; return
fi
lx=`echo $ll|awk '{ for (i=1 ; i<="'$nn'"-1 ; i++) if ($i ~ /%/) {printf $i " "} else {printf $i "'$suffx'" " "}; for (i="'$nn'"; i<=NF; i++) printf $i " "}'|sed -e 's/%//g'`
if [ `echo $fld1|grep '@X'` ]
then fffx=`echo $ll|awk '{print $NF}'`
inst=$fld1
XXX=$XXX' '$inst
suffx=`echo $XXX|awk '{for (i=1; i<=NF; i++) printf "_" $i}'`
rm -f sedf*
touch sedf1 sedf2
cat $fffx|grep -i subckt |awk '{for (i=3; i<=NF ; i++) printf $i "\n"}' >>sedf1
echo $lx|awk '{for (i=2; i<NF; i++) printf $i "\n"}' >> sedf2
echo '**'$lx
npo=`wc sedf2|awk '{print $1}'`
npi=`wc sedf1|awk '{print $1}'`
if [ $npo -le $npi ]
then
head -n $npo sedf1 > sedf1chop
mv sedf1chop sedf1
else
echo 'Error '`echo $lx|awk '{print $NF}'`' has less pins than ports in calling instance:'
echo $lx|awk '{print $1}'
erx=1
let rec_depth=$rec_depth-1 ; echo "REC_DEPTH =" $rec_depth
return
fi
paste sedf1 sedf2 |sed -e 's/\t/ /' -e 's/^/s\//' -e 's/ /\//' -e 's/$/%\/g/'> sedf
fff=$fffx''$suffx
sed -f sedf $fffx > $fff
flatten_func
else if [[ `echo $ii|grep -i subckt` || `echo $ii|grep -i ends` ]]
then if [[ $fld1 == '.ends' || $fld1 == '.ENDS' ]]
then XXX=`echo $XXX|awk '{for (i=1; i<NF; i++) printf $i " "}'`
suffx=`echo $XXX|awk '{for (i=1; i<=NF; i++) printf "_" $i}'`
let nx--
let nx--
fi
if [[ $fff == $fftop || $nx -eq 0 ]]
then echo $ll|sed -e 's/@//g'; let nx++
else echo '**'$ll|sed -e 's/@//g'; let nx++
fi
else echo $lx|sed -e 's/@//g'
fi
fi
if [[ -e $fff && `echo $fff|grep '_'` ]]
then rm -f $fff
fi
done
let rec_depth=$rec_depth-1 ; echo "****REC_DEPTH =" $rec_depth
}
main_flat.sh -->
## Arya, Oct 27, 2012, slight edit, Aug 07, 2021
fftop=@toplevel@; fff=$fftop; XXX=""; nx=1; suffx="";erx=""; set +C; let rec_depth=0; echo "****REC_DEPTH=" $rec_depth; flatten_func; rm -f @*@; rm -f sedf*; erx=""
***
Listings of the Full Tree (with instances) and the subckts only Tree for the clk-to-q bidirectional shift register, as in Item#499
Full Tree (with instances) - bidirShift.instabces.tree
bidirShift Xbit0 shiftstage XNANDLR NAND3shift
bidirShift Xbit0 shiftstage XNANDRL NAND3shift
bidirShift Xbit0 shiftstage XRSLX RSLX XNAND1 NAND4shift
bidirShift Xbit0 shiftstage XRSLX RSLX XNAND2 NAND4shift
bidirShift Xbit1 shiftstage XNANDLR NAND3shift
bidirShift Xbit1 shiftstage XNANDRL NAND3shift
bidirShift Xbit1 shiftstage XRSLX RSLX XNAND1 NAND4shift
bidirShift Xbit1 shiftstage XRSLX RSLX XNAND2 NAND4shift
bidirShift Xbit2 shiftstage XNANDLR NAND3shift
bidirShift Xbit2 shiftstage XNANDRL NAND3shift
bidirShift Xbit2 shiftstage XRSLX RSLX XNAND1 NAND4shift
bidirShift Xbit2 shiftstage XRSLX RSLX XNAND2 NAND4shift
bidirShift Xbit3 shiftstage XNANDLR NAND3shift
bidirShift Xbit3 shiftstage XNANDRL NAND3shift
bidirShift Xbit3 shiftstage XRSLX RSLX XNAND1 NAND4shift
bidirShift Xbit3 shiftstage XRSLX RSLX XNAND2 NAND4shift
bidirShift Xbit4 shiftstage XNANDLR NAND3shift
bidirShift Xbit4 shiftstage XNANDRL NAND3shift
bidirShift Xbit4 shiftstage XRSLX RSLX XNAND1 NAND4shift
bidirShift Xbit4 shiftstage XRSLX RSLX XNAND2 NAND4shift
bidirShift Xbit5 shiftstage XNANDLR NAND3shift
bidirShift Xbit5 shiftstage XNANDRL NAND3shift
bidirShift Xbit5 shiftstage XRSLX RSLX XNAND1 NAND4shift
bidirShift Xbit5 shiftstage XRSLX RSLX XNAND2 NAND4shift
bidirShift Xbit6 shiftstage XNANDLR NAND3shift
bidirShift Xbit6 shiftstage XNANDRL NAND3shift
bidirShift Xbit6 shiftstage XRSLX RSLX XNAND1 NAND4shift
bidirShift Xbit6 shiftstage XRSLX RSLX XNAND2 NAND4shift
bidirShift Xbit7 shiftstage XNANDLR NAND3shift
bidirShift Xbit7 shiftstage XNANDRL NAND3shift
bidirShift Xbit7 shiftstage XRSLX RSLX XNAND1 NAND4shift
bidirShift Xbit7 shiftstage XRSLX RSLX XNAND2 NAND4shift
bidirShift Xbit8 shiftstage XNANDLR NAND3shift
bidirShift Xbit8 shiftstage XNANDRL NAND3shift
bidirShift Xbit8 shiftstage XRSLX RSLX XNAND1 NAND4shift
bidirShift Xbit8 shiftstage XRSLX RSLX XNAND2 NAND4shift
bidirShift Xbit9 shiftstage XNANDLR NAND3shift
bidirShift Xbit9 shiftstage XNANDRL NAND3shift
bidirShift Xbit9 shiftstage XRSLX RSLX XNAND1 NAND4shift
bidirShift Xbit9 shiftstage XRSLX RSLX XNAND2 NAND4shift
Subckts only Tree - bidirShift.subckts.tree
bidirShift shiftstage NAND3shift
bidirShift shiftstage RSLX NAND4shift
[Note that only the lines ending with leafcells containing the basic components (FETs) are listed in the minimal trees]
Listing of the top net 'sysreset' impacted segment of the flat netlist, bidirShift.dev.net
bidirShift.sysreset.net -->
MN3(NAND4shift)_Xbit0(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) midx2_Xbit0(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) sysreset midx3_Xbit0(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) vss NMOS L=0.09um W=0.045um
MP3(NAND4shift)_Xbit0(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) qq0bar sysreset vdd vdd PMOS L=0.09um W=0.09um
MN3(NAND4shift)_Xbit1(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) midx2_Xbit1(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) sysreset midx3_Xbit1(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) vss NMOS L=0.09um W=0.045um
MP3(NAND4shift)_Xbit1(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) qq1bar sysreset vdd vdd PMOS L=0.09um W=0.09um
MN3(NAND4shift)_Xbit2(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) midx2_Xbit2(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) sysreset midx3_Xbit2(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) vss NMOS L=0.09um W=0.045um
MP3(NAND4shift)_Xbit2(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) qq2bar sysreset vdd vdd PMOS L=0.09um W=0.09um
MN3(NAND4shift)_Xbit3(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) midx2_Xbit3(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) sysreset midx3_Xbit3(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) vss NMOS L=0.09um W=0.045um
MP3(NAND4shift)_Xbit3(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) qq3bar sysreset vdd vdd PMOS L=0.09um W=0.09um
MN3(NAND4shift)_Xbit4(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) midx2_Xbit4(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) sysreset midx3_Xbit4(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) vss NMOS L=0.09um W=0.045um
MP3(NAND4shift)_Xbit4(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) qq4bar sysreset vdd vdd PMOS L=0.09um W=0.09um
MN3(NAND4shift)_Xbit5(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) midx2_Xbit5(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) sysreset midx3_Xbit5(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) vss NMOS L=0.09um W=0.045um
MP3(NAND4shift)_Xbit5(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) qq5bar sysreset vdd vdd PMOS L=0.09um W=0.09um
MN3(NAND4shift)_Xbit6(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) midx2_Xbit6(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) sysreset midx3_Xbit6(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) vss NMOS L=0.09um W=0.045um
MP3(NAND4shift)_Xbit6(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) qq6bar sysreset vdd vdd PMOS L=0.09um W=0.09um
MN3(NAND4shift)_Xbit7(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) midx2_Xbit7(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) sysreset midx3_Xbit7(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) vss NMOS L=0.09um W=0.045um
MP3(NAND4shift)_Xbit7(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) qq7bar sysreset vdd vdd PMOS L=0.09um W=0.09um
MN3(NAND4shift)_Xbit8(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) midx2_Xbit8(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) sysreset midx3_Xbit8(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) vss NMOS L=0.09um W=0.045um
MP3(NAND4shift)_Xbit8(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) qq8bar sysreset vdd vdd PMOS L=0.09um W=0.09um
MN3(NAND4shift)_Xbit9(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) midx2_Xbit9(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) sysreset midx3_Xbit9(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) vss NMOS L=0.09um W=0.045um
MP3(NAND4shift)_Xbit9(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) qq9bar sysreset vdd vdd PMOS L=0.09um W=0.09um
***
Listing of bidirShift.ctlout4lr.net as derived in Item#500
MN1(NAND3shift)_Xbit4(bidirShift)_XNANDLR(shiftstage) ctlout4lr qq4 midx_Xbit4(bidirShift)_XNANDLR(shiftstage) vss NMOS L=0.09um W=0.045um
MP1(NAND3shift)_Xbit4(bidirShift)_XNANDLR(shiftstage) ctlout4lr qq4 vdd vdd PMOS L=0.09um W=0.09um
MP2(NAND3shift)_Xbit4(bidirShift)_XNANDLR(shiftstage) ctlout4lr pulsein1 vdd vdd PMOS L=0.09um W=0.09um
MP3(NAND3shift)_Xbit4(bidirShift)_XNANDLR(shiftstage) ctlout4lr LR vdd vdd PMOS L=0.09um W=0.09um
MN1(NAND4shift)_Xbit4(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) qq4bar ctlout4lr midx_Xbit4(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) vss NMOS L=0.09um W=0.045um
MP1(NAND4shift)_Xbit4(bidirShift)_XRSLX(shiftstage)_XNAND2(RSLX) qq4bar ctlout4lr vdd vdd PMOS L=0.09um W=0.09um
MN1(NAND4shift)_Xbit5(bidirShift)_XRSLX(shiftstage)_XNAND1(RSLX) qq5 ctlout4lr midx_Xbit5(bidirShift)_XRSLX(shiftstage)_XNAND1(RSLX) vss NMOS L=0.09um W=0.045um
MP1(NAND4shift)_Xbit5(bidirShift)_XRSLX(shiftstage)_XNAND1(RSLX) qq5 ctlout4lr vdd vdd PMOS L=0.09um W=0.09um
[8 FETs]
All snippets/codes presented here are strictly proprietary to LVS DEBUG SOLUTIONS LLC, any commercial use of these is prohibited, without proper distribution agreement with the owner
Arya Raychaudhuri
Copyright 2011 LVS DEBUG SOLUTIONS & 2012 LVS DEBUG SOLUTIONS LLC All rights reserved.
LVS DEBUG SOLUTIONS LLC
980 Kiely Blvd, Unit 308
Santa Clara, CA 95051
United States
ph: 1-408-480-1936
arya