From 4b9f61612bd2da9c561dc49638126dd3dfe56375 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Tue, 2 May 2023 17:49:44 +0200 Subject: [PATCH] symbol generators may now take attributes like: "mosgen( @model )", with @model expanded to instance (or symbol template) value. update_symbol() updated to reflect this change. --- src/editprop.c | 68 ++++++----- src/scheduler.c | 9 +- xschem_library/generators/{nmosgen => mosgen} | 106 ++++++++++++++++++ xschem_library/generators/test_mosgen.sch | 43 +++++++ xschem_library/generators/test_nmosgen.sch | 27 ----- 5 files changed, 194 insertions(+), 59 deletions(-) rename xschem_library/generators/{nmosgen => mosgen} (52%) create mode 100644 xschem_library/generators/test_mosgen.sch delete mode 100644 xschem_library/generators/test_nmosgen.sch diff --git a/src/editprop.c b/src/editprop.c index 7619f543..e5703b56 100644 --- a/src/editprop.c +++ b/src/editprop.c @@ -1248,9 +1248,9 @@ static void update_symbol(const char *result, int x) int copy_cell=0; int prefix=0, old_prefix = 0; char *name = NULL, *ptr = NULL, *new_prop = NULL; - char symbol[PATH_MAX]; + char symbol[PATH_MAX], *translated_sym = NULL, *old_translated_sym = NULL; char *type; - int cond; + int cond, changed_symbol = 0; int pushed=0; int *ii = &xctx->edit_sym_i; /* static var */ int *netl_com = &xctx->netlist_commands; /* static var */ @@ -1288,19 +1288,9 @@ static void update_symbol(const char *result, int x) remove_symbols(); link_symbols_to_instances(-1); } - /* symbol reference changed? --> sym_number >=0, set prefix to 1st char - to use for inst name (from symbol template) */ - old_prefix = prefix = 0; - sym_number = -1; + /* User edited the Symbol textbox */ if(strcmp(symbol, xctx->inst[*ii].name)) { - char *sym = NULL; - set_modify(1); - my_strdup2(_ALLOC_ID_, &sym, tcl_hook2(symbol)); - sym_number=match_symbol(sym); /* check if exist */ - my_free(_ALLOC_ID_, &sym); - if(sym_number>=0) { - prefix=(get_tok_value((xctx->sym+sym_number)->templ, "name",0))[0]; /* get new symbol prefix */ - } + changed_symbol = 1; } for(k=0;klastsel; ++k) { dbg(1, "update_symbol(): for k loop: k=%d\n", k); @@ -1310,17 +1300,9 @@ static void update_symbol(const char *result, int x) /* 20171220 calculate bbox before changes to correctly redraw areas */ /* must be recalculated as cairo text extents vary with zoom factor. */ symbol_bbox(*ii, &xctx->inst[*ii].x1, &xctx->inst[*ii].y1, &xctx->inst[*ii].x2, &xctx->inst[*ii].y2); - if(sym_number>=0) /* changing symbol ! */ - { - if(!pushed) { xctx->push_undo(); pushed=1;} - delete_inst_node(*ii); /* 20180208 fix crashing bug: delete node info if changing symbol */ - /* if number of pins is different we must delete these data *before* */ - /* changing ysmbol, otherwise *ii might end up deleting non allocated data. */ - my_strdup2(_ALLOC_ID_, &xctx->inst[*ii].name, rel_sym_path(symbol)); - xctx->inst[*ii].ptr=sym_number; /* update instance to point to new symbol */ - } - bbox(ADD, xctx->inst[*ii].x1, xctx->inst[*ii].y1, - xctx->inst[*ii].x2, xctx->inst[*ii].y2); + bbox(ADD, xctx->inst[*ii].x1, xctx->inst[*ii].y1, xctx->inst[*ii].x2, xctx->inst[*ii].y2); + + my_strdup2(_ALLOC_ID_, &old_translated_sym, translate(*ii, xctx->inst[*ii].name)); /* update property string from tcl dialog */ if(!no_change_props) @@ -1340,6 +1322,7 @@ static void update_symbol(const char *result, int x) dbg(1, "update_symbol(): changing prop: |%s| -> |%s|\n", xctx->inst[*ii].prop_ptr, new_prop); if(!pushed) { xctx->push_undo(); pushed=1; set_modify(1);} + dbg(1, "update_symbol(): *ii=%d, new_prop=%s\n", *ii, new_prop ? new_prop : "NULL"); my_strdup(_ALLOC_ID_, &xctx->inst[*ii].prop_ptr, new_prop); } } else { @@ -1349,6 +1332,31 @@ static void update_symbol(const char *result, int x) } } + /* symbol reference changed? --> sym_number >=0, set prefix to 1st char + * to use for inst name (from symbol template) */ + prefix = 0; + sym_number = -1; + my_strdup2(_ALLOC_ID_, &translated_sym, translate(*ii, symbol)); + dbg(1, "update_symbol: %s -- %s\n", translated_sym, old_translated_sym); + if(changed_symbol || + ( !strcmp(symbol, xctx->inst[*ii].name) && strcmp(translated_sym, old_translated_sym) ) ) { + sym_number=match_symbol(translated_sym); /* check if exist */ + if(sym_number>=0) { + prefix=(get_tok_value((xctx->sym+sym_number)->templ, "name",0))[0]; /* get new symbol prefix */ + } + } + + if(sym_number>=0) /* changing symbol ! */ + { + if(!pushed) { xctx->push_undo(); pushed=1; set_modify(1);} + delete_inst_node(*ii); /* 20180208 fix crashing bug: delete node info if changing symbol */ + /* if number of pins is different we must delete these data *before* */ + /* changing ysmbol, otherwise *ii might end up deleting non allocated data. */ + my_strdup2(_ALLOC_ID_, &xctx->inst[*ii].name, rel_sym_path(symbol)); + xctx->inst[*ii].ptr=sym_number; /* update instance to point to new symbol */ + } + my_free(_ALLOC_ID_, &translated_sym); + my_free(_ALLOC_ID_, &old_translated_sym); /* if symbol changed ensure instance name (with new prefix char) is unique */ /* preserve backslashes in name ---------0---------------------------------->. */ @@ -1356,7 +1364,12 @@ static void update_symbol(const char *result, int x) if(name && name[0] ) { dbg(1, "update_symbol(): prefix!='\\0', name=%s\n", name); /* change prefix if changing symbol type; */ - if(prefix && old_prefix && old_prefix != prefix) name[0]=(char)prefix; + if(prefix && old_prefix && old_prefix != prefix) { + name[0]=(char)prefix; + my_strdup(_ALLOC_ID_, &ptr, subst_token(xctx->inst[*ii].prop_ptr, "name", name) ); + } else { + my_strdup(_ALLOC_ID_, &ptr, xctx->inst[*ii].prop_ptr); + } /* set unique name of current inst */ if(!pushed) { xctx->push_undo(); pushed=1;} if(!k) hash_all_names(); @@ -1365,7 +1378,6 @@ static void update_symbol(const char *result, int x) my_strdup2(_ALLOC_ID_, &xctx->inst[*ii].instname, ""); } - /* set cached flags in instances */ type=xctx->sym[xctx->inst[*ii].ptr].type; cond= !type || !IS_LABEL_SH_OR_PIN(type); @@ -1385,8 +1397,6 @@ static void update_symbol(const char *result, int x) } /* end for(k=0;klastsel; ++k) */ - - /* new symbol bbox after prop changes (may change due to text length) */ if(xctx->modified) { xctx->prep_hash_inst=0; diff --git a/src/scheduler.c b/src/scheduler.c index 6b36c573..4df5b48e 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -1559,14 +1559,17 @@ int xschem(ClientData clientdata, Tcl_Interp *interp, int argc, const char * arg else if(!strcmp(argv[1], "instance_list")) { int i; + char *s = NULL; for(i = 0; i < xctx->instances; ++i) { - char *name = xctx->inst[i].name ? xctx->inst[i].name : ""; + const char *name = xctx->inst[i].name ? translate(i, xctx->inst[i].name) : ""; char *instname = xctx->inst[i].instname ? xctx->inst[i].instname : ""; char *type = (xctx->inst[i].ptr + xctx->sym)->type; type = type ? type : ""; - if(i > 0) Tcl_AppendResult(interp, " ", NULL); - Tcl_AppendResult(interp, "{", instname, "} {", name, "} {", type, "}", NULL); + if(i > 0) my_mstrcat(_ALLOC_ID_, &s, " ", NULL); + my_mstrcat(_ALLOC_ID_, &s, "{", instname, "} {", name, "} {", type, "}", NULL); } + Tcl_SetResult(interp, (char *)s, TCL_VOLATILE); + my_free(_ALLOC_ID_, &s); } /* instance_net inst pin * Return the name of the net attached to pin 'pin' of instance 'inst' diff --git a/xschem_library/generators/nmosgen b/xschem_library/generators/mosgen similarity index 52% rename from xschem_library/generators/nmosgen rename to xschem_library/generators/mosgen index 6a8aec75..9d9cb9f7 100755 --- a/xschem_library/generators/nmosgen +++ b/xschem_library/generators/mosgen @@ -110,6 +110,112 @@ hide=true} T {tcleval(id=[to_eng [ngspice::get_node [subst -nocommand \{i(\\@m.$\{path\}@spiceprefix@name\\.msky130_fd_pr__@model\\[id])\}]]] )} 32.5 -30 0 0 0.15 0.15 {layer=15 hide=true} } +} elseif {$model eq {pfet_g5v0d10v5}} { +puts {v {xschem version=3.1.0 file_version=1.2} +G {} +K {type=pmos +lvs_format="@spiceprefix@name @pinlist sky130_fd_pr__@model L=@L W=@W nf=@nf m=@mult" +format="@spiceprefix@name @pinlist sky130_fd_pr__@model L=@L W=@W ++ nf=@nf ad=@ad as=@as pd=@pd ps=@ps ++ nrd=@nrd nrs=@nrs sa=@sa sb=@sb sd=@sd ++ mult=@mult m=@mult" +template="name=M1 +L=0.5 +W=1 +nf=1 +mult=1 +ad=\\"'int((nf+1)/2) * W/nf * 0.29'\\" +pd=\\"'2*int((nf+1)/2) * (W/nf + 0.29)'\\" +as=\\"'int((nf+2)/2) * W/nf * 0.29'\\" +ps=\\"'2*int((nf+2)/2) * (W/nf + 0.29)'\\" +nrd=\\"'0.29 / W'\\" nrs=\\"'0.29 / W'\\" +sa=0 sb=0 sd=0 +model=pfet_g5v0d10v5 +spiceprefix=X +"} +V {} +S {} +E {} +L 4 20 -30 20 -17.5 {} +L 4 20 17.5 20 30 {} +L 4 7.5 17.5 20 17.5 {} +L 4 12.5 -17.5 20 -17.5 {} +L 4 -20 0 -12.5 0 {} +L 4 7.5 -22.5 7.5 22.5 {} +B 5 17.5 27.5 22.5 32.5 {name=D dir=inout} +B 5 -22.5 -2.5 -17.5 2.5 {name=G dir=in} +B 5 17.5 -32.5 22.5 -27.5 {name=S dir=inout} +B 5 19.921875 -0.078125 20.078125 0.078125 {name=B dir=in} +A 4 -7.5 0 5 180 360 {} +P 4 4 12.5 -20 7.5 -17.5 12.5 -15 12.5 -20 {fill=true} +P 4 5 -2.5 15 -2.5 -15 2.5 -15 2.5 15 -2.5 15 {} +P 5 4 15 -2.5 20 0 15 2.5 15 -2.5 {fill=true} +T {@name} 5 -30 0 1 0.2 0.2 {} +T {D} 22.5 17.5 0 0 0.15 0.15 {layer=7} +T {S} 22.5 -17.5 2 1 0.15 0.15 {layer=7} +T {B} 20 -10 0 0 0.15 0.15 {layer=7} +T {G} -11.875 -10 0 1 0.15 0.15 {layer=7} +T {@model} 30 -8.75 2 1 0.2 0.2 {} +T {@mult x @W / @L} 31.25 13.75 0 0 0.2 0.2 { layer=13} +T {nf=@nf} 31.25 1.25 0 0 0.2 0.2 { layer=13} +T {tcleval(gm=[to_eng [ngspice::get_node [subst -nocommand \{\\@m.$\{path\}@spiceprefix@name\\.msky130_fd_pr__@model\\[gm]\}]]] )} 32.5 -8.75 0 0 0.15 0.15 {layer=15 +hide=true} +T {tcleval(id=[to_eng [ngspice::get_node [subst -nocommand \{i(\\@m.$\{path\}@spiceprefix@name\\.msky130_fd_pr__@model\\[id])\}]]] )} 32.5 -30 0 0 0.15 0.15 {layer=15 +hide=true} +} +} elseif {$model eq {pfet_01v8}} { +puts {v {xschem version=3.1.0 file_version=1.2} +G {} +K {type=pmos +lvs_format="@spiceprefix@name @pinlist sky130_fd_pr__@model L=@L W=@W nf=@nf m=@mult" +format="@spiceprefix@name @pinlist sky130_fd_pr__@model L=@L W=@W ++ nf=@nf ad=@ad as=@as pd=@pd ps=@ps ++ nrd=@nrd nrs=@nrs sa=@sa sb=@sb sd=@sd ++ mult=@mult m=@mult" +template="name=M1 +L=0.15 +W=1 +nf=1 +mult=1 +ad=\\"'int((nf+1)/2) * W/nf * 0.29'\\" +pd=\\"'2*int((nf+1)/2) * (W/nf + 0.29)'\\" +as=\\"'int((nf+2)/2) * W/nf * 0.29'\\" +ps=\\"'2*int((nf+2)/2) * (W/nf + 0.29)'\\" +nrd=\\"'0.29 / W'\\" nrs=\\"'0.29 / W'\\" +sa=0 sb=0 sd=0 +model=pfet_01v8 +spiceprefix=X +"} +V {} +S {} +E {} +L 4 7.5 -22.5 7.5 22.5 {} +L 4 20 -30 20 -17.5 {} +L 4 20 17.5 20 30 {} +L 4 2.5 -15 2.5 15 {} +L 4 7.5 17.5 20 17.5 {} +L 4 12.5 -17.5 20 -17.5 {} +L 4 -20 0 -7.5 0 {} +B 5 17.5 27.5 22.5 32.5 {name=D dir=inout} +B 5 -22.5 -2.5 -17.5 2.5 {name=G dir=in} +B 5 17.5 -32.5 22.5 -27.5 {name=S dir=inout} +B 5 19.921875 -0.078125 20.078125 0.078125 {name=B dir=in} +A 4 -2.5 0 5 180 360 {} +P 4 4 12.5 -20 7.5 -17.5 12.5 -15 12.5 -20 {fill=true} +P 5 4 15 -2.5 20 0 15 2.5 15 -2.5 {fill=true} +T {@name} 5 -30 0 1 0.2 0.2 {} +T {D} 22.5 17.5 0 0 0.15 0.15 {layer=7} +T {S} 22.5 -17.5 2 1 0.15 0.15 {layer=7} +T {B} 20 -10 0 0 0.15 0.15 {layer=7} +T {G} -10 -10 0 1 0.15 0.15 {layer=7} +T {@model} 30 -8.75 2 1 0.2 0.2 {} +T {@mult x @W / @L} 31.25 13.75 0 0 0.2 0.2 { layer=13} +T {nf=@nf} 31.25 1.25 0 0 0.2 0.2 { layer=13} +T {tcleval(gm=[to_eng [ngspice::get_node [subst -nocommand \{\\@m.$\{path\}@spiceprefix@name\\.msky130_fd_pr__@model\\[gm]\}]]] )} 32.5 -8.75 0 0 0.15 0.15 {layer=15 +hide=true} +T {tcleval(id=[to_eng [ngspice::get_node [subst -nocommand \{i(\\@m.$\{path\}@spiceprefix@name\\.msky130_fd_pr__@model\\[id])\}]]] )} 32.5 -30 0 0 0.15 0.15 {layer=15 +hide=true} +} } else { puts { G {type=missing diff --git a/xschem_library/generators/test_mosgen.sch b/xschem_library/generators/test_mosgen.sch new file mode 100644 index 00000000..4613c7d3 --- /dev/null +++ b/xschem_library/generators/test_mosgen.sch @@ -0,0 +1,43 @@ +v {xschem version=3.1.0 file_version=1.2 +} +G {} +K {} +V {} +S {} +E {} +N 500 -140 610 -140 { +lab=#net1} +N 500 -230 500 -170 { +lab=#net2} +N 390 -140 460 -140 { +lab=#net3} +N 500 -110 500 -50 { +lab=#net4} +N 790 -140 900 -140 { +lab=#net5} +N 790 -230 790 -170 { +lab=#net6} +N 680 -140 750 -140 { +lab=#net7} +N 790 -110 790 -50 { +lab=#net8} +N 500 -260 610 -260 { +lab=#net9} +N 390 -260 460 -260 { +lab=#net10} +N 790 -260 900 -260 { +lab=#net11} +N 680 -260 750 -260 { +lab=#net12} +N 500 -350 500 -290 { +lab=#net13} +N 790 -350 790 -290 { +lab=#net14} +C {mosgen( @model )} 480 -140 0 0 {name=x1 +model=nfet_01v8} +C {mosgen( @model )} 770 -140 0 0 {name=x2 +model=nfet_g5v0d10v5} +C {mosgen( @model )} 480 -260 0 0 {name=x3 +model=pfet_01v8} +C {mosgen( @model )} 770 -260 0 0 {name=x4 +model=pfet_g5v0d10v5} diff --git a/xschem_library/generators/test_nmosgen.sch b/xschem_library/generators/test_nmosgen.sch deleted file mode 100644 index 2cc62c30..00000000 --- a/xschem_library/generators/test_nmosgen.sch +++ /dev/null @@ -1,27 +0,0 @@ -v {xschem version=3.1.0 file_version=1.2 -} -G {} -K {} -V {} -S {} -E {} -N 500 -140 610 -140 { -lab=#net1} -N 500 -230 500 -170 { -lab=#net2} -N 390 -140 460 -140 { -lab=#net3} -N 500 -110 500 -50 { -lab=#net4} -N 790 -140 900 -140 { -lab=#net5} -N 790 -230 790 -170 { -lab=#net6} -N 680 -140 750 -140 { -lab=#net7} -N 790 -110 790 -50 { -lab=#net8} -C {nmosgen( @model )} 480 -140 0 0 {name=x1 -model=nfet_g5v0d10v5} -C {nmosgen( @model )} 770 -140 0 0 {name=x2 -model=nfet_g5v0d10v5}