From 822a63974fb7fe172eff4274ad68d48bceabf1df Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Sun, 10 Jan 2021 12:49:00 +0100 Subject: [PATCH] Unused binning models are removed. Flag 'nf', when given on the x lines, is recognized. Tested with TSMC, Skywater, and X-Fab model files. --- src/frontend/inp.c | 35 ++++++++++++++++++++++-- src/frontend/inpcom.c | 51 ++++++++++++++++++++++++++++------- src/frontend/subckt.c | 7 ++++- src/include/ngspice/inpdefs.h | 1 + 4 files changed, 81 insertions(+), 13 deletions(-) diff --git a/src/frontend/inp.c b/src/frontend/inp.c index b0f980f0f..d0737e7e0 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -2452,9 +2452,10 @@ static void rem_unused_mos_models(struct card* deck) { } for (tmpc = deck; tmpc; tmpc = tmpc->nextcard) { char* curr_line = tmpc->line; - /* We only look for MOS devices and extract W and L */ + /* We only look for MOS devices and extract W, L, nf, and wnflag */ if (*curr_line == 'm') { - float w = 0., l = 0.; + float w = 0., l = 0., nf = 1., wnf = 1.; + int wnflag = 0; char* wstr = strstr(curr_line, " w="); if (wstr) { int err; @@ -2475,6 +2476,36 @@ static void rem_unused_mos_models(struct card* deck) { continue; } } + char* nfstr = strstr(curr_line, " nf="); + if (nfstr) { + int err; + nfstr = nfstr + 4; + nfstr = skip_ws(nfstr); + nf = (float)INPevaluate(&nfstr, &err, 0); + if (err) { + continue; + } + } + char* wnstr = strstr(curr_line, " wnflag="); + if (wnstr) { + int err; + wnstr = wnstr + 8; + wnstr = skip_ws(wnstr); + wnf = (float)INPevaluate(&wnstr, &err, 0); + if (err) { + continue; + } + } + if (!cp_getvar("wnflag", CP_NUM, &wnflag, 0)) { + if (newcompat.spe || newcompat.hs) + wnflag = 1; + else + wnflag = 0; + } + + nf = wnflag * wnf > 0.5f ? nf : 1.f; + w = w / nf; + /* what is the device's model name? */ char* mname = nexttok(curr_line); int nonodes = 4; /* FIXME: this is a hack! How to really detect the number of nodes? */ diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 4bb2c04b1..ceb763764 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -617,13 +617,32 @@ static void print_compat_mode(void) { } -/* We check x lines for w= and l= and fill in their values. - To be used when expanding subcircuits with binned model cards. */ +/* We check x lines for nf=, w= and l= and fill in their values. + To be used when expanding subcircuits with binned model cards. + + In subckt.c, function doit(), lines 621ff. the unsused models + are filtered out. 'nf' given on an x line (subcircuit invocation) + is aknowledged. The option 'wnflag', if set to 0 in .spiceinit, + will set 'nf' to 1 and thus suppress its usage. + + In inp.c, function rem_unused_mos_models, another trial to removing + unused MOS models is given, this time on the expanded m lines and + its models.*/ void inp_get_w_l_x(struct card* card) { + int wnflag; + if (!cp_getvar("wnflag", CP_NUM, &wnflag, 0)) { + if (newcompat.spe || newcompat.hs) + wnflag = 1; + else + wnflag = 0; + } for (; card; card = card->nextcard) { char* curr_line = card->line; int skip_control = 0; - char* w = NULL, * l = NULL; + char* w = NULL, * l = NULL, * nf = NULL; + + card->w = card->l = 0; + card->nf = 1.; /* exclude any command inside .control ... .endc */ if (ciprefix(".control", curr_line)) { @@ -639,7 +658,6 @@ void inp_get_w_l_x(struct card* card) { } /* only subcircuit invocations */ if (*curr_line != 'x' && !newcompat.hs && !newcompat.spe) { - card->w = card->l = 0; continue; } @@ -649,30 +667,43 @@ void inp_get_w_l_x(struct card* card) { w = w + 3; card->w = (float)INPevaluate(&w, &err, 0); if(err) { - card->w = card->l = 0; + card->w = 0; continue; - } + } } else { card->w = card->l = 0; continue; } - l = strstr(curr_line, " l="); if (l) { int err; l = l + 3; card->l = (float)INPevaluate(&l, &err, 0); if(err) { - card->w = card->l = 0; + card->l = 0; continue; - } + } } else { card->w = card->l = 0; continue; - } + } + nf = strstr(curr_line, " nf="); + if (nf) { + int err; + nf = nf + 4; + card->nf = (float)INPevaluate(&nf, &err, 0); + if (err) { + card->w = card->l = 0; + card->nf = 1.; + continue; + } + } + else { + continue; + } } } diff --git a/src/frontend/subckt.c b/src/frontend/subckt.c index 2faf56c39..5c78edd2b 100644 --- a/src/frontend/subckt.c +++ b/src/frontend/subckt.c @@ -698,7 +698,9 @@ doit(struct card *deck, wordlist *modnames) { } float csl = (float)scale * c->l; - float csw = (float)scale * c->w; + /* scale by nf */ + float csw = (float)scale * c->w / c->nf; + /*fprintf(stdout, "Debug: nf = %f\n", c->nf);*/ if (csl >= flmin && csl < flmax && csw >= fwmin && csw < fwmax) { /* use the current .model card */ prev = su_deck; @@ -823,6 +825,7 @@ struct card * inp_deckcopy(struct card *deck) { d->linenum = deck->linenum; d->w = deck->w; d->l = deck->l; + d->nf = deck->nf; d->line = copy(deck->line); if (deck->error) d->error = copy(deck->error); @@ -867,6 +870,7 @@ struct card *inp_deckcopy_oc(struct card * deck) } d->w = deck->w; d->l = deck->l; + d->nf = deck->nf; d->linenum_orig = deck->linenum; d->linenum = i++; d->line = copy(deck->line); @@ -923,6 +927,7 @@ struct card* inp_deckcopy_ln(struct card* deck) } d->w = deck->w; d->l = deck->l; + d->nf = deck->nf; d->linenum_orig = deck->linenum_orig; d->linenum = deck->linenum; d->line = copy(deck->line); diff --git a/src/include/ngspice/inpdefs.h b/src/include/ngspice/inpdefs.h index 5eab39d4f..b0376f6be 100644 --- a/src/include/ngspice/inpdefs.h +++ b/src/include/ngspice/inpdefs.h @@ -84,6 +84,7 @@ struct card { struct nscope *level; float w; float l; + float nf; }; /* structure used to save models in after they are read during pass 1 */