Unused binning models are removed.

Flag 'nf', when given on the x lines, is
recognized.
Tested with TSMC, Skywater, and X-Fab model
files.
This commit is contained in:
Holger Vogt 2021-01-10 12:49:00 +01:00
parent e601325149
commit 822a63974f
4 changed files with 81 additions and 13 deletions

View File

@ -2452,9 +2452,10 @@ static void rem_unused_mos_models(struct card* deck) {
} }
for (tmpc = deck; tmpc; tmpc = tmpc->nextcard) { for (tmpc = deck; tmpc; tmpc = tmpc->nextcard) {
char* curr_line = tmpc->line; 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') { 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="); char* wstr = strstr(curr_line, " w=");
if (wstr) { if (wstr) {
int err; int err;
@ -2475,6 +2476,36 @@ static void rem_unused_mos_models(struct card* deck) {
continue; 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? */ /* what is the device's model name? */
char* mname = nexttok(curr_line); char* mname = nexttok(curr_line);
int nonodes = 4; /* FIXME: this is a hack! How to really detect the number of nodes? */ int nonodes = 4; /* FIXME: this is a hack! How to really detect the number of nodes? */

View File

@ -617,13 +617,32 @@ static void print_compat_mode(void) {
} }
/* We check x lines for w= and l= and fill in their values. /* We check x lines for nf=, w= and l= and fill in their values.
To be used when expanding subcircuits with binned model cards. */ 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) { 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) { for (; card; card = card->nextcard) {
char* curr_line = card->line; char* curr_line = card->line;
int skip_control = 0; 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 */ /* exclude any command inside .control ... .endc */
if (ciprefix(".control", curr_line)) { if (ciprefix(".control", curr_line)) {
@ -639,7 +658,6 @@ void inp_get_w_l_x(struct card* card) {
} }
/* only subcircuit invocations */ /* only subcircuit invocations */
if (*curr_line != 'x' && !newcompat.hs && !newcompat.spe) { if (*curr_line != 'x' && !newcompat.hs && !newcompat.spe) {
card->w = card->l = 0;
continue; continue;
} }
@ -649,7 +667,7 @@ void inp_get_w_l_x(struct card* card) {
w = w + 3; w = w + 3;
card->w = (float)INPevaluate(&w, &err, 0); card->w = (float)INPevaluate(&w, &err, 0);
if(err) { if(err) {
card->w = card->l = 0; card->w = 0;
continue; continue;
} }
} }
@ -658,14 +676,13 @@ void inp_get_w_l_x(struct card* card) {
continue; continue;
} }
l = strstr(curr_line, " l="); l = strstr(curr_line, " l=");
if (l) { if (l) {
int err; int err;
l = l + 3; l = l + 3;
card->l = (float)INPevaluate(&l, &err, 0); card->l = (float)INPevaluate(&l, &err, 0);
if(err) { if(err) {
card->w = card->l = 0; card->l = 0;
continue; continue;
} }
} }
@ -673,6 +690,20 @@ void inp_get_w_l_x(struct card* card) {
card->w = card->l = 0; card->w = card->l = 0;
continue; 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;
}
} }
} }

View File

@ -698,7 +698,9 @@ doit(struct card *deck, wordlist *modnames) {
} }
float csl = (float)scale * c->l; 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) { if (csl >= flmin && csl < flmax && csw >= fwmin && csw < fwmax) {
/* use the current .model card */ /* use the current .model card */
prev = su_deck; prev = su_deck;
@ -823,6 +825,7 @@ struct card * inp_deckcopy(struct card *deck) {
d->linenum = deck->linenum; d->linenum = deck->linenum;
d->w = deck->w; d->w = deck->w;
d->l = deck->l; d->l = deck->l;
d->nf = deck->nf;
d->line = copy(deck->line); d->line = copy(deck->line);
if (deck->error) if (deck->error)
d->error = copy(deck->error); d->error = copy(deck->error);
@ -867,6 +870,7 @@ struct card *inp_deckcopy_oc(struct card * deck)
} }
d->w = deck->w; d->w = deck->w;
d->l = deck->l; d->l = deck->l;
d->nf = deck->nf;
d->linenum_orig = deck->linenum; d->linenum_orig = deck->linenum;
d->linenum = i++; d->linenum = i++;
d->line = copy(deck->line); d->line = copy(deck->line);
@ -923,6 +927,7 @@ struct card* inp_deckcopy_ln(struct card* deck)
} }
d->w = deck->w; d->w = deck->w;
d->l = deck->l; d->l = deck->l;
d->nf = deck->nf;
d->linenum_orig = deck->linenum_orig; d->linenum_orig = deck->linenum_orig;
d->linenum = deck->linenum; d->linenum = deck->linenum;
d->line = copy(deck->line); d->line = copy(deck->line);

View File

@ -84,6 +84,7 @@ struct card {
struct nscope *level; struct nscope *level;
float w; float w;
float l; float l;
float nf;
}; };
/* structure used to save models in after they are read during pass 1 */ /* structure used to save models in after they are read during pass 1 */