Add function rem_unused_mos_models()
Netlist is flat at this stage, all numbers expanded, but not yet parsed into the circuit structure. So again try to remove unused MOS models. All binning models are still here when w or l have been determined by an expression from within the PDK.
This commit is contained in:
parent
19fb3ec38f
commit
e1eb851ec4
|
|
@ -64,6 +64,7 @@ static wordlist *inp_savecurrents(struct card *deck, struct card *options,
|
|||
void line_free_x(struct card *deck, bool recurse);
|
||||
static void recifeval(struct card *pdeck);
|
||||
static char *upper(register char *string);
|
||||
static void rem_unused_mos_models(struct card* deck);
|
||||
|
||||
|
||||
|
||||
|
|
@ -75,6 +76,11 @@ void eval_seed_opt(struct card *deck);
|
|||
|
||||
extern bool ft_batchmode;
|
||||
|
||||
/* from inpcom.c */
|
||||
extern struct nscope* inp_add_levels(struct card *deck);
|
||||
extern void comment_out_unused_subckt_models(struct card *deck);
|
||||
extern void inp_rem_unused_models(struct nscope *root, struct card *deck);
|
||||
|
||||
#ifdef SHARED_MODULE
|
||||
extern void exec_controls(wordlist *controls);
|
||||
#endif
|
||||
|
|
@ -864,6 +870,13 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
|
|||
to wl_first with all terminal currents available on selected devices */
|
||||
wl_first = inp_savecurrents(deck, options, wl_first, controls);
|
||||
|
||||
/* Circuit is flat, all numbers expanded.
|
||||
So again try to remove unused MOS models.
|
||||
All binning models are still here when w or l have been
|
||||
determined by an expression. */
|
||||
if (newcompat.hs || newcompat.spe)
|
||||
rem_unused_mos_models(deck->nextcard);
|
||||
|
||||
/* now load deck into ft_curckt -- the current circuit. */
|
||||
if(inp_dodeck(deck, tt, wl_first, FALSE, options, filename) != 0)
|
||||
return 1;
|
||||
|
|
@ -972,6 +985,21 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile)
|
|||
fprintf(stderr, "Warning: Cannot open file debug-out3.txt for saving debug info\n");
|
||||
}
|
||||
|
||||
/* Remove comment lines
|
||||
if (newcompat.hs || newcompat.spe) {
|
||||
struct card *prev, *fcard, *tmpdeck;
|
||||
prev = deck;
|
||||
tmpdeck = deck->nextcard;
|
||||
for (fcard = tmpdeck; fcard; fcard = fcard->nextcard) {
|
||||
if (*(prev->nextcard->line) == '*') {
|
||||
struct card* tmpcard = fcard->nextcard;
|
||||
line_free_x(prev->nextcard, FALSE);
|
||||
fcard = prev->nextcard = tmpcard;
|
||||
}
|
||||
prev = fcard;
|
||||
}
|
||||
}*/
|
||||
|
||||
/* Now the circuit is defined, so generate the parse trees */
|
||||
inp_parse_temper_trees(ft_curckt);
|
||||
/* Get the actual data for model and device instance parameters */
|
||||
|
|
@ -2310,3 +2338,189 @@ eval_agauss(struct card *deck, char *fcn)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct mlist {
|
||||
struct card* mod;
|
||||
struct card* prevmod;
|
||||
struct card* prevcard;
|
||||
char* mname;
|
||||
float wmin;
|
||||
float wmax;
|
||||
float lmin;
|
||||
float lmax;
|
||||
struct mlist* nextm;
|
||||
bool used;
|
||||
bool checked;
|
||||
};
|
||||
|
||||
/* Finally get rid of unused MOS models */
|
||||
static void rem_unused_mos_models(struct card* deck) {
|
||||
struct card *tmpc, *tmppc = NULL;
|
||||
struct mlist* modellist = NULL, *tmplist;
|
||||
double scale;
|
||||
if (!cp_getvar("scale", CP_REAL, &scale, 0))
|
||||
scale = 1;
|
||||
/* the old way to remove unused models */
|
||||
struct nscope* root = inp_add_levels(deck);
|
||||
comment_out_unused_subckt_models(deck);
|
||||
inp_rem_unused_models(root, deck);
|
||||
/* remove unused binning models */
|
||||
for (tmpc = deck; tmpc; tmppc = tmpc, tmpc = tmpc->nextcard) {
|
||||
char* curr_line;
|
||||
char* nline = curr_line = tmpc->line;
|
||||
if (ciprefix(".model", nline)) {
|
||||
float fwmin, fwmax, flmin, flmax;
|
||||
char* wmin = strstr(curr_line, " wmin=");
|
||||
if (wmin) {
|
||||
int err;
|
||||
wmin = wmin + 6;
|
||||
wmin = skip_ws(wmin);
|
||||
fwmin = (float)INPevaluate(&wmin, &err, 0);
|
||||
if (err) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
char* wmax = strstr(curr_line, " wmax=");
|
||||
if (wmax) {
|
||||
int err;
|
||||
wmax = wmax + 6;
|
||||
wmax = skip_ws(wmax);
|
||||
fwmax = (float)INPevaluate(&wmax, &err, 0);
|
||||
if (err) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
|
||||
char* lmin = strstr(curr_line, " lmin=");
|
||||
if (lmin) {
|
||||
int err;
|
||||
lmin = lmin + 6;
|
||||
lmin = skip_ws(lmin);
|
||||
flmin = (float)INPevaluate(&lmin, &err, 0);
|
||||
if (err) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
char* lmax = strstr(curr_line, " lmax=");
|
||||
if (lmax) {
|
||||
int err;
|
||||
lmax = lmax + 6;
|
||||
lmax = skip_ws(lmax);
|
||||
flmax = (float)INPevaluate(&lmax, &err, 0);
|
||||
if (err) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
|
||||
nline = nexttok(nline);
|
||||
char* modname = gettok(&nline);
|
||||
struct mlist* newm = TMALLOC(struct mlist, 1);
|
||||
newm->mname = modname;
|
||||
newm->mod = tmpc;
|
||||
newm->prevmod = tmppc;
|
||||
newm->wmin = newm->wmax = newm->lmin = newm->lmax = 0.;
|
||||
newm->nextm = NULL;
|
||||
newm->used = FALSE;
|
||||
newm->checked = FALSE;
|
||||
newm->lmax = flmax;
|
||||
newm->lmin = flmin;
|
||||
newm->wmax = fwmax;
|
||||
newm->wmin = fwmin;
|
||||
|
||||
if (!modellist) {
|
||||
modellist = newm;
|
||||
}
|
||||
else {
|
||||
struct mlist* tmpl = modellist;
|
||||
modellist = newm;
|
||||
modellist->nextm = tmpl;
|
||||
}
|
||||
modellist->prevcard = tmppc;
|
||||
}
|
||||
}
|
||||
for (tmpc = deck; tmpc; tmpc = tmpc->nextcard) {
|
||||
char* curr_line = tmpc->line;
|
||||
/* We only look for MOS devices and extract W and L */
|
||||
if (*curr_line == 'm') {
|
||||
float w = 0., l = 0.;
|
||||
char* wstr = strstr(curr_line, " w=");
|
||||
if (wstr) {
|
||||
int err;
|
||||
wstr = wstr + 3;
|
||||
wstr = skip_ws(wstr);
|
||||
w = (float)INPevaluate(&wstr, &err, 0);
|
||||
if (err) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
char* lstr = strstr(curr_line, " l=");
|
||||
if (lstr) {
|
||||
int err;
|
||||
lstr = lstr + 3;
|
||||
lstr = skip_ws(lstr);
|
||||
l = (float)INPevaluate(&lstr, &err, 0);
|
||||
if (err) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* what is the device's model name? */
|
||||
char* mname = nexttok(curr_line);
|
||||
int nonodes = 4;
|
||||
int jj;
|
||||
for (jj = 0; jj < nonodes; jj++) {
|
||||
mname = nexttok(mname);
|
||||
}
|
||||
mname = gettok(&mname);
|
||||
/* We now check all models */
|
||||
for (tmplist = modellist; tmplist; tmplist = tmplist->nextm) {
|
||||
if (strstr(tmplist->mname, mname)) {
|
||||
float ls = l * (float)scale;
|
||||
float ws = w * (float)scale;
|
||||
if (tmplist->lmin <= ls && tmplist->lmax >= ls && tmplist->wmin <= ws && tmplist->wmax >= ws)
|
||||
tmplist->used = TRUE;
|
||||
else
|
||||
tmplist->checked = TRUE;
|
||||
}
|
||||
else {
|
||||
tmplist->checked = TRUE;
|
||||
}
|
||||
}
|
||||
tfree(mname);
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete the models that have been checked, but are unused */
|
||||
for (tmplist = modellist; tmplist; tmplist = tmplist->nextm) {
|
||||
if (tmplist->checked && !tmplist->used) {
|
||||
if (tmplist->prevcard == NULL) {
|
||||
struct card* tmpcard = tmplist->mod;
|
||||
tmplist->mod = tmplist->mod->nextcard;
|
||||
line_free_x(tmpcard, FALSE);
|
||||
}
|
||||
else {
|
||||
struct card* tmpcard = tmplist->prevcard;
|
||||
tmpcard->nextcard = tmplist->mod->nextcard;
|
||||
line_free_x(tmplist->mod, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Remove modellist */
|
||||
while (modellist) {
|
||||
struct mlist* tlist = modellist->nextm;
|
||||
tfree(modellist->mname);
|
||||
tfree(modellist);
|
||||
modellist = tlist;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue