added flatten_savenodes.awk for flattening in-subcircuit .save instructions

This commit is contained in:
Stefan Frederik 2020-12-14 16:31:20 +01:00
parent 5af6a38d2e
commit ce5adbffdb
9 changed files with 192 additions and 11 deletions

View File

@ -11,9 +11,9 @@ put /local/src {
# list all files that need to be installed in "$(XSHAREDIR)"
put /local/install_shares {
keys.help xschem.help xschem.tcl break.awk convert_to_verilog2001.awk
flatten.awk flatten_tedax.awk make_sym.awk symgen.awk order_labels.awk sort_labels.awk spice.awk
tedax.awk verilog.awk vhdl.awk hspice_backannotate.tcl change_index.tcl resources.tcl
xschemrc ngspice_backannotate.tcl rawtovcd gschemtoxschem.awk
flatten.awk flatten_tedax.awk flatten_savenodes.awk make_sym.awk symgen.awk order_labels.awk
sort_labels.awk spice.awk tedax.awk verilog.awk vhdl.awk hspice_backannotate.tcl
change_index.tcl resources.tcl xschemrc ngspice_backannotate.tcl rawtovcd gschemtoxschem.awk
}
# generate a list of objects from the list of source files

View File

@ -31,7 +31,7 @@ BEGIN{ quote=0 }
first = substr($0,1,1)
# dont break .include lines as ngspice chokes on these.
if(tolower($1) ~ /\.include|\.lib|\.title/) nobreak = 1
if(tolower($1) ~ /\.include|\.lib|\.title|\.save/) nobreak = 1
else nobreak = 0
# 20151203 faster executionif no {}' present
if($0 ~/[{}']/ || quote) {

155
src/flatten_savenodes.awk Executable file
View File

@ -0,0 +1,155 @@
#!/usr/bin/awk -f
#
# File: flatten.awk
#
# This file is part of XSCHEM,
# a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
# simulation.
# Copyright (C) 1998-2020 Stefan Frederik Schippers
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
# flatten .SAVE netlist lines
BEGIN{
# topcell=toupper(ARGV[2])
# ARGC=2
first_subckt = 1
pathsep="."
}
{
up = toupper($0)
if(up ~/^[ \t]*\.END([ \t]+|$)/ ) do_end = $0
else if(up ~/^[ \t]*\.SAVE[ \t]+/){
if(toupper($2) !="ALL") do_save = 1
gsub(/V\([ \t]*/, "V( ", up)
gsub(/[ \t]*\)/, " )", up)
} else print
$0=up
if($0 ~ /^\**\.SUBCKT/ && first_subckt) {
topcell=$2
sub(/^\*\*/,"",$0)
}
if($0 ~ /^\**\.ENDS/ && first_subckt) {
first_subckt = 0
sub(/^\*\*/,"",$0)
}
if($0 ~/^\+/) # join folded lines
{
a[lines-1]=a[lines-1] " " substr($0,2); next
}
a[lines++]=$0
}
END{
for(j=0;j<lines;j++)
{
$0=a[j]
if($1 ~ /\.GLOBAL/) # get global nodes
for(i=2;i<=NF;i++) global[$i]=i;
if($1 ~ /^\.SUBCKT/) # parse subckts
{ # subckt["name","first"]= first line
subname=$2 # subckt["name","last"]= last line
subckt[subname,"first"]=j # subckt["name", "ports"] = # of ports
for(k=3;k<=NF;k++) # subckt["name", "port","node"]=
# port number (1,2,...)
{
if($k ~ /=/) break
subckt[subname,"port",$k]=k-2
}
subckt[subname,"ports"]=k-3
}
if($1 ~ /^\.ENDS/) {
subckt[subname,"last"]=j
}
}
print "** flattened .save nodes"
expand(topcell,"","")
# parameters:
# - subckt name to expand
# - current path (will be prefixed to inst & node names)
# - port list to connect the subckt to.
if(do_end !="") print do_end
}
# recursive routine!!! private variables must be declared local !!
function expand(name, path,ports, # func. params
portlist,portarray,j,k,subname, # local vars
pathname,pathnode, # local vars
instname,num,line,subname_pos) # local vars
{
if(path != "")
{
pathname=pathsep path ; pathnode=path pathsep
}
split(ports,portarray)
for(j=subckt[name , "first"]+1;j<subckt[name , "last"];j++) {
num=split(a[j],line)
if(line[1] ~ /^X/ ) {
portlist = ""; subname=""
for(k=num;k>=2;k--) {
if(line[k] !~ /=/) {
if(subname=="") {subname=line[k]; subname_pos=k }
else if( (subname,ports) in subckt && k<subckt[subname,"ports"]+0)
portlist = getnode(name,pathnode,portarray,line[k]) " " portlist
else if(k<subname_pos){
# undefined subcircuit
portlist = getnode(name,pathnode,portarray,line[k]) " " portlist
}
}
}
# print "*--------BEGIN_" pathnode line[1]_"->" subname
if( (subname,"first") in subckt) # 30032003 do not expand subcircuit call if undefined subckt
expand(subname,pathnode line[1],portlist)
# print "*--------END___" pathnode line[1] "->" subname
}
else {
if(line[1] ~ /^\.SAVE$/) {
printf ".SAVE "
for(k = 2; k <= num; k++) {
if(k > 2) printf " "
if(line[k] ~ /^V\($/) {
printf "V(%s)",getnode(name,pathnode,portarray,line[k+1])
k += 2
} else {
printf "%s", line[k]
}
}
printf "\n"
}
if(line[1] ~ /^\V/ && do_save == 1) {
if(name !=topcell)
printf ".SAVE I(V.%s)\n", pathnode line[1]
else
printf ".SAVE I(%s)\n", line[1]
}
}
}
}
function getnode(name, path, portarray, node)
# return the full path-name of <node> in subckt <name>
# in path <path>, called with ports <portarray>
{
if(name!=topcell) { # if we are in top cell, nothing to do
if(name SUBSEP "port" SUBSEP node in subckt)
return portarray[subckt[name,"port",node]] # <node> is a port, return port mapping
if(!(node in global)) return path node # local node
}
return node # if <node> is a top level or global (not a port) just return
}

View File

@ -122,7 +122,9 @@ proc netlist {source_file show netlist_file} {
}
if {$flat_netlist==0} {
eval exec {awk -f ${XSCHEM_SHAREDIR}/spice.awk -- $hspice $source_file | \
awk -f ${XSCHEM_SHAREDIR}/break.awk > $netlist_dir/$netlist_file}
awk -f ${XSCHEM_SHAREDIR}/break.awk | \
awk -f ${XSCHEM_SHAREDIR}/flatten_savenodes.awk \
> $netlist_dir/$netlist_file}
} else {
eval exec {awk -f ${XSCHEM_SHAREDIR}/spice.awk -- $hspice $source_file | \
awk -f ${XSCHEM_SHAREDIR}/flatten.awk | awk -f ${XSCHEM_SHAREDIR}/break.awk > $netlist_dir/$netlist_file}

View File

@ -94,6 +94,8 @@ N 340 -1180 560 -1180 {lab=VPP}
N 1110 -1180 1110 -790 { lab=VPP}
N 560 -1180 1110 -1180 {lab=VPP}
N 230 -950 800 -950 { lab=#net2}
N 1360 -920 1570 -920 {lab=TEST[3:0]}
N 1360 -860 1360 -840 { lab=VSS}
C {ipin.sym} 530 -160 0 0 {name=p0 lab=PLUS}
C {ipin.sym} 530 -120 0 0 {name=p2 lab=VPP}
C {ipin.sym} 530 -100 0 0 {name=p3 lab=VNN}
@ -408,3 +410,13 @@ load $netlist_dir/$rawfile
table_set $rawfile\\"
unset rawfile"
}
C {spice_probe.sym} 1010 -760 0 0 {name=p40 analysis=tran}
C {spice_probe.sym} 1000 -440 0 0 {name=p56 analysis=tran}
C {spice_probe.sym} 420 -790 0 0 {name=p57 analysis=tran}
C {spice_probe.sym} 280 -950 0 0 {name=p58 analysis=tran}
C {spice_probe.sym} 180 -720 0 0 {name=p59 analysis=tran}
C {lab_wire.sym} 1420 -920 0 0 {name=l3 lab=TEST[3:0]}
C {spice_probe.sym} 1510 -920 0 0 {name=p60 analysis=tran}
C {res.sym} 1360 -890 0 1 {name=R8[3:0] m=1 value=200 net_name=true}
C {lab_pin.sym} 1360 -840 0 0 {name=p61 lab=VSS}
C {spice_probe.sym} 1020 -1120 0 0 {name=p62 analysis=tran}

View File

@ -116,11 +116,11 @@ vvss vss 0 dc 0
** SPICE models for active devices and put them into the below
** referenced file in simulation directory.
.include \\"models_poweramp.txt\\"
.save all
.option savecurrents
* .save all
* .option savecurrents
* .FOUR 20k v(outm,outp)
* .probe i(*)
* .probe p(r*) p(v*)
.save p(r*) p(v*)
"}
C {vsource.sym} 160 -1200 0 0 {name=V1 value="dc 50 pwl 0 0 1m 50"}
C {vsource.sym} 160 -1140 0 0 {name=V0 value="dc 50 pwl 0 0 1m 50"}
@ -254,3 +254,8 @@ load $netlist_dir/$rawfile
table_set $rawfile\\"
unset rawfile"
}
C {spice_probe.sym} 730 -700 0 0 {name=p40 analysis=tran}
C {spice_probe.sym} 740 -240 0 0 {name=p41 analysis=tran}
C {spice_probe.sym} 670 -1250 0 0 {name=p42 analysis=tran}
C {spice_probe.sym} 680 -1170 0 0 {name=p43 analysis=tran}
C {spice_probe.sym} 960 -1250 0 0 {name=p44 analysis=tran}

View File

@ -19,7 +19,6 @@ C {code_shown.sym} 640 -210 0 0 {name=STIMULI
only_toplevel=true
tclcommand="xschem edit_vi_prop"
value="
.tran 10n 800u uic
.save all
"}

View File

@ -61,7 +61,7 @@ C {code_shown.sym} 1050 -240 0 0 {name=s1 value="* .control
* write led_driver.raw
* tran 5n 1000u uic
* .endc
.save all
* .save all
.tran 5n 1000u uic
"}
C {ammeter.sym} 750 -470 3 0 {name=VVled}
@ -107,3 +107,7 @@ C {bsource.sym} 880 -670 0 0 {name=B1 VAR=V FUNC="pwl(V(VLED,VCC),
}
C {lab_pin.sym} 880 -640 0 0 {name=l9 sig_type=std_logic lab=0}
C {lab_pin.sym} 880 -730 0 0 {name=l10 sig_type=std_logic lab=COMP}
C {spice_probe.sym} 780 -470 0 0 {name=p1 analysis=tran}
C {spice_probe.sym} 90 -640 0 0 {name=p2 analysis=tran}
C {spice_probe.sym} 410 -460 0 0 {name=p3 analysis=tran}
C {spice_probe.sym} 290 -400 0 0 {name=p4 analysis=tran}

View File

@ -96,7 +96,7 @@ C {code_shown.sym} 245 -245 0 0 {name=CONTROL value="* .control
* write led_driver.raw
* .endc
.option savecurrents
.save all
*.save all
.tran 5n 200u uic
* .dc VP 0 21 0.01
" net_name=true}
@ -185,3 +185,7 @@ C {ammeter.sym} 860 -400 2 0 {name=Vdiode net_name=true}
C {launcher.sym} 655 -165 0 0 {name=h1
descr="Simulate + gaw reload"
tclcommand="set sim(spice,default) 1; set sim(spice,1,fg) 1; set sim(spice,1,st) 0;xschem netlist; xschem simulate; gaw_cmd reload_all" net_name=true}
C {spice_probe.sym} 1160 -480 0 0 {name=p1 analysis=tran}
C {spice_probe.sym} 360 -450 0 0 {name=p2 analysis=tran}
C {spice_probe.sym} 860 -550 0 1 {name=p3 analysis=tran}
C {spice_probe.sym} 100 -450 0 1 {name=p4 analysis=tran}