@ -64,6 +64,7 @@ static wordlist *inp_savecurrents(struct card *deck, struct card *options,
void line_free_x ( struct card * deck , bool recurse ) ;
void line_free_x ( struct card * deck , bool recurse ) ;
static void recifeval ( struct card * pdeck ) ;
static void recifeval ( struct card * pdeck ) ;
static char * upper ( register char * string ) ;
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 ;
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
# ifdef SHARED_MODULE
extern void exec_controls ( wordlist * controls ) ;
extern void exec_controls ( wordlist * controls ) ;
# endif
# 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 */
to wl_first with all terminal currents available on selected devices */
wl_first = inp_savecurrents ( deck , options , wl_first , controls ) ;
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. */
/* now load deck into ft_curckt -- the current circuit. */
if ( inp_dodeck ( deck , tt , wl_first , FALSE , options , filename ) ! = 0 )
if ( inp_dodeck ( deck , tt , wl_first , FALSE , options , filename ) ! = 0 )
return 1 ;
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 " ) ;
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 */
/* Now the circuit is defined, so generate the parse trees */
inp_parse_temper_trees ( ft_curckt ) ;
inp_parse_temper_trees ( ft_curckt ) ;
/* Get the actual data for model and device instance parameters */
/* 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 ;
}
}