From 1536e77b62dd919586bb1e9f4d8f61231d7d2a23 Mon Sep 17 00:00:00 2001 From: Stefan Schippers Date: Wed, 21 Oct 2020 18:18:53 +0200 Subject: [PATCH] spice netlist postprocessing will not break ".include " lines as ngspice does not like these. make_sch_from_spice.awk adapted to import sky130 standard cells, spice netlister will print extra nodes (inherited connections or pins-by-attribute) in the order specified by the format string, instead of dumping the "extra" attribute after all "real" pins, this allows to mix attribute pins with the other pins. --- src/break.awk | 8 +- src/make_sch_from_spice.awk | 87 +++++++++++++++------ src/spice_netlist.c | 7 +- src/token.c | 8 ++ src/xschem.tcl | 3 +- xschem_library/examples/mos_power_ampli.sch | 26 +++--- 6 files changed, 98 insertions(+), 41 deletions(-) diff --git a/src/break.awk b/src/break.awk index 7a89e2f0..fa17d988 100755 --- a/src/break.awk +++ b/src/break.awk @@ -29,6 +29,10 @@ BEGIN{ quote=0 } pos=0 if(NF==0) { print ""; next } first = substr($0,1,1) + + # dont break .include lines as ngspice chokes on these. + if(tolower($1) ~ /include/) include = 1 + else include = 0 # 20151203 faster executionif no {}' present if($0 ~/[{}']/ || quote) { l = length($0) @@ -36,7 +40,7 @@ BEGIN{ quote=0 } pos++ c = substr($0,i,1) if(c ~/[{}']/) quote=!quote - if(pos> 100 && !quote && (c ~/[ \t]/)) { + if(!include && pos> 100 && !quote && (c ~/[ \t]/)) { if(first=="*") c = "\n*+" c else @@ -50,7 +54,7 @@ BEGIN{ quote=0 } split($0, a, /[^ \t]+/) for(i=1;i<=NF;i++) { pos += length($i)+length(a[i]) - if(pos>100) { + if(!include && pos>100) { if(first=="*") { printf "%s", "\n*+" } else { diff --git a/src/make_sch_from_spice.awk b/src/make_sch_from_spice.awk index 82f9d20e..5648c664 100755 --- a/src/make_sch_from_spice.awk +++ b/src/make_sch_from_spice.awk @@ -30,9 +30,9 @@ BEGIN{ # list of cmos_t9 symbol pin coordinates, generated with build_cmoslib.awk - while ( "ls $HOME/xschem/library/TECHLIB/*.sym"|getline sym ) + while ( "ls $HOME/.xschem/xschem_library/sky130_symbols/*.sym"|getline sym ) { - insert_symbol(sym, "TECHLIB") + insert_symbol(sym, "sky130_symbols") } @@ -42,13 +42,17 @@ BEGIN{ # } - $0="" - - - - + inherited_pin["VGND"]=1 + inherited_pin["VPWR"]=1 + inherited_pin["VNB"]=1 + inherited_pin["VPB"]=1 + + skip_symbol_prefix= "sky130_fd_sc_hd__" + # sym_type = "subcircuit" + sym_type = "primitive" # do not use schematics although they will be generated all_signals="" + $0="" ########################## JOIN ########################## netlist_lines=0 @@ -123,22 +127,40 @@ function insert_symbol(sym, lib, n,cellname, name, dir, tmp) } -function process_subckts( i,name) +function process_subckts( j, i,name) { if(skip==1 && toupper($1) ==".ENDS") { skip=0; return } if(skip==1) return if(toupper($1) ==".SUBCKT") { curr_subckt=$2 + sub(skip_symbol_prefix, "", curr_subckt) + pin_ar[curr_subckt, "name"] = $2 + print " process_subckt(): curr_subckt=|" curr_subckt "|" if(curr_subckt in cell) {print " process_subckt(); skipping " curr_subckt ; skip=1; return } subckt[curr_subckt]=1 template=0 + j = 1 for(i=3;i<=NF;i++) { if($i~ /=/) { template=i; break} - pin_ar[curr_subckt,i-2]=$i + if(!($i in inherited_pin)) { + pin_ar[curr_subckt,j]=$i + pin_ar[curr_subckt,"format"]=pin_ar[curr_subckt,"format"] " @@" $i + j++ + } else { + if(pin_ar[curr_subckt,"extra"]) + pin_ar[curr_subckt,"extra"] = pin_ar[curr_subckt,"extra"] " " $i + else + pin_ar[curr_subckt,"extra"] = $i + pin_ar[curr_subckt,"template"] = pin_ar[curr_subckt,"template"] " " $i "=" $i + pin_ar[curr_subckt,"format"]=pin_ar[curr_subckt,"format"] " @" $i + } } - pin_ar[curr_subckt,"n"]=i-3 - pin_ar[curr_subckt,"template"] = get_template(template) + + pin_ar[curr_subckt,"n"]=j-1 + if(skip_symbol_prefix) pin_ar[curr_subckt,"template"] = pin_ar[curr_subckt,"template"] " prefix=" skip_symbol_prefix + get_template(template) + if(skip_symbol_prefix) pin_ar[curr_subckt,"extra"] = pin_ar[curr_subckt,"extra"] " prefix" print "\n\n\n process_subckt() : " curr_subckt "--> " for(i=1; i<= pin_ar[curr_subckt,"n"]; i++) printf "%s ", pin_ar[curr_subckt,i]; printf "\n" } @@ -164,7 +186,7 @@ function get_template(t, templ, i) if(t) for(i=t;i<=NF;i++) { templ = templ $i " " } - return templ + pin_ar[curr_subckt,"template"] = pin_ar[curr_subckt,"template"] " " templ } @@ -176,6 +198,7 @@ function process( i,name,param) if(skip==1) return if(toupper($1) ==".SUBCKT") { curr_subckt=$2 + sub(skip_symbol_prefix, "", curr_subckt) if(curr_subckt in cell) {print "process(): skipping " curr_subckt ; skip=1; return } space=20 width=150 @@ -206,7 +229,9 @@ function process( i,name,param) print "\n\n" print_sch(curr_subckt, dir_ret, pin_ret) - print_sym(curr_subckt, pin_ar[curr_subckt,"template"], dir_ret, pin_ret) + print_sym(curr_subckt, pin_ar[curr_subckt,"template"], \ + pin_ar[curr_subckt,"format"], pin_ar[curr_subckt,"name"], \ + sym_type, pin_ar[curr_subckt,"extra"], dir_ret, pin_ret) print "----------------------------------------------------------" @@ -640,7 +665,7 @@ function print_signals( inst_name, component_name, param, pin,dir,net, #------------------------------ -function print_sym(sym, template, dir, pin, +function print_sym(sym, template, format, subckt_name, sym_type, extra, dir, pin, size,space,width,lwidth,textdist,labsize,titlesize, i,name,text_voffset,lab_voffset,ip,op,n_pin ,m,x,y,n, iii,ooo) @@ -667,13 +692,23 @@ function print_sym(sym, template, dir, pin, print "start print symbol: " sym + print "v {xschem version=2.9.8 file_version=1.2}" + print "K {type=" sym_type > sym + # print "format=\"@name @pinlist @symname " format_translate(template) "\"" > sym + iii = format_translate(template, extra) + if(iii) iii = " " iii - - print "G {type=subcircuit" > sym - print "format=\"@name @pinlist @symname " format_translate(template) "\"" > sym - print "template=\"name=x1 " template "\"}" > sym - print "T {@symname}" ,-length(name)/2*titlesize*30, -text_voffset*titlesize,0,0, - titlesize, titlesize, "{}" >sym + # since awk strings use backslash escapes and sub also uses backslash escapes (example for \& substitution) + # there are 2 levels of escape substitutions, we need \\\\ to generate one \. + # in the xschem file \\\\ is reduced to \\ in the format string and finally format contains one \ + if(skip_symbol_prefix) sub(skip_symbol_prefix, "@prefix\\\\\\\\\\\\\\\\", subckt_name) + print "format=\"@name" format " " subckt_name iii "\"" > sym + print "template=\"name=x1" template "\"" > sym + print "extra=\"" extra "\"}" > sym + # print "T {@symname}" ,-length(name)/2*titlesize*30, -text_voffset*titlesize,0,0, + # titlesize, titlesize, "{}" >sym + print "T {@symname}" ,0, -text_voffset*titlesize,0,0, + titlesize, titlesize, "{hcenter=true}" >sym n_pin=pin["n"] ip=op=0 @@ -742,7 +777,7 @@ function abs(a) return a>0 ? a: -a } -function format_translate(s, c,quote,str,n,i,ss,sss) +function format_translate(s, extra, n_extra, extra_arr, extra_hash, c,quote,str,n,i,ss,sss) { # 20140321 @@ -758,17 +793,23 @@ function format_translate(s, c,quote,str,n,i,ss,sss) # /20140321 str="" + n_extra = split(extra, extra_arr) + for(i = 1; i <= n_extra; i++) extra_hash[ extra_arr[i] ] = 1 + + n=split(s,ss) for(i=1;i<=n;i++) { gsub(SUBSEP," ", ss[i]) print "subckt params: " ss[i] if(ss[i] ~ /[^=]+=[^=]+/) { split(ss[i],sss,"=") - ss[i] = sss[1] "=@" sss[1] + if(!(sss[1] in extra_hash)) ss[i] = sss[1] "=@" sss[1] + else ss[i] = "" } str = str ss[i] - if(isym[i].prop_ptr,"extra",0) ); - fprintf(fd, "%s ", extra ? extra : "" ); - + /* this is now done in print_spice_subckt */ + /* + * fprintf(fd, "%s ", extra ? extra : "" ); + */ + /* 20081206 new get_sym_template does not return token=value pairs where token listed in extra */ fprintf(fd, "%s", get_sym_template(xctx->sym[i].templ, extra)); my_free(950, &extra); diff --git a/src/token.c b/src/token.c index 9b8862da..8f5819ca 100644 --- a/src/token.c +++ b/src/token.c @@ -1394,6 +1394,12 @@ void print_spice_subckt(FILE *fd, int symbol) } } } + /* this will print the other @parameters, usually "extra" nodes so they will be in the order + * specified by the format string. The 'extra' attribute is no more used to print extra nodes + * in spice_block_netlist(). */ + else if(token[0] == '@') { /* given previous if() conditions not followed by @ or # */ + fprintf(fd, "%s ", token + 1); + } if(c!='$' && c!='@' && c!='\0' ) fputc(c,fd); if(c == '@' || c =='$') s--; state=XBEGIN; @@ -1646,7 +1652,9 @@ void print_spice_element(FILE *fd, int inst) /* do one level of substitutions to resolve @params and equations*/ if(result && strstr(result, "tcleval(")== result) { + dbg(1, "print_spice_element(): before translate()result=%s\n", result); my_strdup(22, &result, translate(inst, result)); + dbg(1, "print_spice_element(): after translate()result=%s\n", result); } fprintf(fd, "%s", result); diff --git a/src/xschem.tcl b/src/xschem.tcl index bd4da48d..ea2fbd7e 100644 --- a/src/xschem.tcl +++ b/src/xschem.tcl @@ -1865,7 +1865,8 @@ proc tclpropeval {s instname symname} { # this hook is called in translate() if whole string is contained in a tcleval(...) construct proc tclpropeval2 {s} { - # puts "tclpropeval2: $s $instname $symname" + global tcl_debug + if {$tcl_debug <=-1} {puts "tclpropeval2: $s"} set path [string range [xschem get sch_path] 1 end] regsub {^tcleval\(} $s {} s regsub {\)([ \n\t]*)$} $s {\1} s diff --git a/xschem_library/examples/mos_power_ampli.sch b/xschem_library/examples/mos_power_ampli.sch index e7e710b0..7cd23beb 100644 --- a/xschem_library/examples/mos_power_ampli.sch +++ b/xschem_library/examples/mos_power_ampli.sch @@ -125,8 +125,8 @@ C {lab_pin.sym} 340 -970 0 1 {name=p23 lab=E2} C {lab_pin.sym} 560 -970 0 1 {name=p28 lab=E6} C {lab_pin.sym} 840 -1000 0 0 {name=p29 lab=E4} C {lab_pin.sym} 180 -1120 0 0 {name=p34 lab=VBOOST} -C {ammeter.sym} 1110 -540 0 0 {name=vd net_name=true current=0.1944} -C {ammeter.sym} 1110 -640 0 0 {name=vu net_name=true current=0.216} +C {ammeter.sym} 1110 -540 0 0 {name=vd net_name=true current=0.2069} +C {ammeter.sym} 1110 -640 0 0 {name=vu net_name=true current=0.2005} C {lab_pin.sym} 60 -1180 0 0 {name=p27 lab=VPP} C {pnp.sym} 200 -950 0 1 {name=Q1 model=q2n2907p area=1 net_name=true} C {pnp.sym} 360 -790 0 1 {name=Q2 model=q2n2907p area=1 net_name=true} @@ -209,18 +209,18 @@ C {lab_pin.sym} 180 -690 0 0 {name=p8 lab=C7} C {lab_pin.sym} 340 -710 0 1 {name=p31 lab=C2} C {title.sym} 160 -30 0 0 {name=l2 author="Stefan Schippers"} C {lab_pin.sym} 860 -700 0 0 {name=p32 lab=SA} -C {ammeter.sym} 1110 -350 0 0 {name=v0 net_name=true current=0.2138} +C {ammeter.sym} 1110 -350 0 0 {name=v0 net_name=true current=0.2263} C {lab_pin.sym} 860 -380 0 0 {name=p35 lab=SB} -C {ammeter.sym} 560 -890 0 0 {name=v1 net_name=true current=0.01954} -C {ammeter.sym} 340 -890 0 0 {name=v2 net_name=true current=0.01944} -C {ammeter.sym} 260 -310 0 0 {name=v3 net_name=true current=0.03919} -C {ammeter.sym} 700 -440 3 0 {name=v4 net_name=true current=0.01939} -C {ammeter.sym} 690 -680 0 0 {name=v5 net_name=true current=0.006273} -C {ammeter.sym} 180 -870 0 1 {name=v6 net_name=true current=0.01952} -C {ammeter.sym} 840 -890 0 0 {name=v7 net_name=true current=0.01947} -C {spice_probe_vdiff.sym} 860 -410 0 0 {name=p37 analysis=tran voltage=3.684} -C {spice_probe_vdiff.sym} 860 -730 0 0 {name=p38 analysis=tran voltage=3.685} -C {ammeter.sym} 1300 -590 3 0 {name=v8 net_name=true current=0.02782} +C {ammeter.sym} 560 -890 0 0 {name=v1 net_name=true current=0.01956} +C {ammeter.sym} 340 -890 0 0 {name=v2 net_name=true current=0.01947} +C {ammeter.sym} 260 -310 0 0 {name=v3 net_name=true current=0.03918} +C {ammeter.sym} 700 -440 3 0 {name=v4 net_name=true current=0.01941} +C {ammeter.sym} 690 -680 0 0 {name=v5 net_name=true current=0.006184} +C {ammeter.sym} 180 -870 0 1 {name=v6 net_name=true current=0.01949} +C {ammeter.sym} 840 -890 0 0 {name=v7 net_name=true current=0.01944} +C {spice_probe_vdiff.sym} 860 -410 0 0 {name=p37 analysis=tran voltage=3.688} +C {spice_probe_vdiff.sym} 860 -730 0 0 {name=p38 analysis=tran voltage=3.68} +C {ammeter.sym} 1300 -590 3 0 {name=v8 net_name=true current=-2.1216e-04} C {opin.sym} 600 -130 0 0 {name=p5 lab=OUT} C {ipin.sym} 530 -180 0 0 {name=p1 lab=MINUS} C {ipin.sym} 530 -140 0 0 {name=p4 lab=VSS}