Browse Source

Model improvements from Phil Barker

pre-master-46
pnenzi 19 years ago
parent
commit
53e52f4a59
  1. 16
      ChangeLog
  2. 90
      src/frontend/spiceif.c
  3. 1
      src/frontend/spiceif.h
  4. 31
      src/frontend/subckt.c
  5. 1
      src/include/fteext.h
  6. 1
      src/include/inpdefs.h
  7. 6
      src/main.c
  8. 1
      src/spicelib/parser/inp.h
  9. 4
      src/spicelib/parser/inp2dot.c
  10. 2
      src/spicelib/parser/inpdomod.c
  11. 38
      src/spicelib/parser/inpfindv.c
  12. 345
      src/spicelib/parser/inpgmod.c

16
ChangeLog

@ -1,5 +1,15 @@
2007-10-8 Paolo Nenzi <p.nenzi@ieee.org> 2007-10-8 Paolo Nenzi <p.nenzi@ieee.org>
*src/frontend/{inp.c, inpcom.c, inpcom.h, measure.c, nutimp.c, runcoms.c
* src/main.c, src/frontend/{spiceif.c, spiceif.h, subckt.c},
src/include/{fteext.h, inpdefs.h},
src/spicelib/parser/{inp.h, inp2dot.c, inpdomod.c, inpfindv.c,
inpgmod.c}: other improvements by Phil Barker:
- Added model binning function
- Added model version function
- enhanced the interactive command 'alter' to allow for changing the model
of a device
2007-10-8 Paolo Nenzi <p.nenzi@ieee.org>
* src/frontend/{inp.c, inpcom.c, inpcom.h, measure.c, nutimp.c, runcoms.c
subckt.c, ftedefs.c, fteext.c, dctran.c, inp2dot.c, inppas2.c}: added subckt.c, ftedefs.c, fteext.c, dctran.c, inp2dot.c, inppas2.c}: added
several improvements mad by Phil Barker: several improvements mad by Phil Barker:
- .measure statements: trig/targ, max, min, avg, rms, integral, param - .measure statements: trig/targ, max, min, avg, rms, integral, param
@ -14,10 +24,6 @@
reading in additional .include and .lib files defined in other netlist files reading in additional .include and .lib files defined in other netlist files
- changed the flattened netlist names created in 'subckt.c' to match other - changed the flattened netlist names created in 'subckt.c' to match other
spice simulators spice simulators
- allow for .ic, .nodeset names to be embedded in a subckt;
enhanced subckt.c to created appropriate node names for flattened simulation
netlist
2007-10-8 Paolo Nenzi <p.nenzi@ieee.org> 2007-10-8 Paolo Nenzi <p.nenzi@ieee.org>
* src/frontend/{rawfile.c, outitf.c, runcoms.c}, src/include/ftedefs.h: * src/frontend/{rawfile.c, outitf.c, runcoms.c}, src/include/ftedefs.h:

90
src/frontend/spiceif.c

@ -161,7 +161,7 @@ if_inpdeck(struct line *deck, INPtables **tab)
INPpas1((void *) ckt, (card *) deck->li_next,(INPtables *)*tab); INPpas1((void *) ckt, (card *) deck->li_next,(INPtables *)*tab);
INPpas2((void *) ckt, (card *) deck->li_next, INPpas2((void *) ckt, (card *) deck->li_next,
(INPtables *) *tab,ft_curckt->ci_defTask); (INPtables *) *tab,ft_curckt->ci_defTask);
INPkillMods();
/* INPkillMods(); PJB 09/29/03 -- keep global set of model descriptors */
/* INPpas2 has been modified to ignore .NODESET and .IC /* INPpas2 has been modified to ignore .NODESET and .IC
* cards. These are left till INPpas3 so that we can check for * cards. These are left till INPpas3 so that we can check for
@ -623,6 +623,87 @@ spif_getparam(void *ckt, char **name, char *param, int ind, int do_model)
return (if_getstat(ckt, *name)); return (if_getstat(ckt, *name));
} }
/* 9/26/03 PJB : function to allow setting model of device */
void
if_setparam_model( void *ckt, char **name, char *val )
{
GENinstance *dev = (GENinstance *)NULL;
GENinstance *prevDev = (GENinstance *)NULL;
GENmodel *curMod = (GENmodel *) NULL;
GENmodel *newMod = (GENmodel *) NULL;
INPmodel *inpmod = (INPmodel *) NULL;
GENinstance *iter;
GENmodel *mods, *prevMod;
int typecode;
/* retrieve device name from symbol table */
INPretrieve(name,(INPtables *)ft_curckt->ci_symtab);
/* find the specified device */
typecode = finddev(ckt, *name, (void**)&dev, (void **)&curMod);
if (typecode == -1) {
fprintf(cp_err, "Error: no such device or model name %s\n", *name);
return;
}
curMod = dev->GENmodPtr;
/*
retrieve the model from the global model table; also add the model to 'ckt'
and indicate model is being used
*/
INPgetMod( ckt, val, &inpmod, (INPtables *)ft_curckt->ci_symtab );
if ( inpmod == NULL ) {
fprintf(cp_err, "Error: no such model %s.\n", val);
return;
}
newMod = (GENmodel*)(inpmod->INPmodfast);
/* see if new model name same as current model name */
if ( newMod->GENmodName == curMod->GENmodName ) {
fprintf(cp_err, "Warning: new model same as current model; nothing changed.\n");
return;
}
if ( newMod->GENmodType != curMod->GENmodType ) {
fprintf(cp_err, "Error: new model %s must be same type as current model.\n", val);
return;
}
/* fix current model linked list */
prevDev = NULL;
for( iter = curMod->GENinstances; iter != NULL; iter = iter->GENnextInstance ) {
if ( iter->GENname == dev->GENname ) {
/* see if at beginning of linked list */
if ( prevDev == NULL ) curMod->GENinstances = iter->GENnextInstance;
else prevDev->GENnextInstance = iter->GENnextInstance;
/* update model for device */
dev->GENmodPtr = newMod;
dev->GENnextInstance = newMod->GENinstances;
newMod->GENinstances = dev;
break;
}
prevDev = iter;
}
/* see if any devices remaining that reference current model */
if ( curMod->GENinstances == NULL ) {
prevMod = NULL;
for( mods = ((CKTcircuit *)ckt)->CKThead[typecode]; mods != NULL; mods = mods->GENnextModel ) {
if ( mods->GENmodName == curMod->GENmodName ) {
/* see if at beginning of linked list */
if ( prevMod == NULL ) ((CKTcircuit *)ckt)->CKThead[typecode] = mods->GENnextModel;
else prevMod->GENnextModel = mods->GENnextModel;
INPgetMod( ckt, (char *)mods->GENmodName, &inpmod, (INPtables *)ft_curckt->ci_symtab );
inpmod->INPmodUsed = 0;
FREE(mods);
break;
}
prevMod = mods;
}
}
}
void void
if_setparam(void *ckt, char **name, char *param, struct dvec *val, int do_model) if_setparam(void *ckt, char **name, char *param, struct dvec *val, int do_model)
{ {
@ -877,7 +958,6 @@ finddev(void *ck, char *name, void **devptr, void **modptr)
if(err == OK) return(type); if(err == OK) return(type);
*modptr = (void *)NULL; *modptr = (void *)NULL;
return(-1); return(-1);
} }
/* get an analysis parameter by name instead of id */ /* get an analysis parameter by name instead of id */
@ -1165,7 +1245,7 @@ do {\
if(__i) {\ if(__i) {\
if(name)\ if(name)\
tfree(name);\ tfree(name);\
name = tmalloc(__i);\
name = (type *)tmalloc(__i);\
fread(name,1,__i,file);\ fread(name,1,__i,file);\
} else {\ } else {\
fprintf(cp_err, "size for vector " #name " is 0\n");\ fprintf(cp_err, "size for vector " #name " is 0\n");\
@ -1196,7 +1276,7 @@ do {\
_foo(ckt->CKTbreaks,double,ckt->CKTbreakSize); _foo(ckt->CKTbreaks,double,ckt->CKTbreakSize);
_foo(ft_curckt->ci_curTask,TSKtask,1);
_foo((TSKtask *)ft_curckt->ci_curTask,TSKtask,1);
/* To stop the Free */ /* To stop the Free */
((TSKtask *)ft_curckt->ci_curTask)->TSKname = NULL; ((TSKtask *)ft_curckt->ci_curTask)->TSKname = NULL;
@ -1204,7 +1284,7 @@ do {\
_foo(((TSKtask *)ft_curckt->ci_curTask)->TSKname,char,-1); _foo(((TSKtask *)ft_curckt->ci_curTask)->TSKname,char,-1);
_foo(((TSKtask *)ft_curckt->ci_curTask)->jobs,TRANan,1);
_foo(((TRANan *)((TSKtask *)ft_curckt->ci_curTask)->jobs),TRANan,1);
((TSKtask *)ft_curckt->ci_curTask)->jobs->JOBname = NULL; ((TSKtask *)ft_curckt->ci_curTask)->jobs->JOBname = NULL;
ckt->CKTcurJob = (JOB *)((TSKtask *)ft_curckt->ci_curTask)->jobs; ckt->CKTcurJob = (JOB *)((TSKtask *)ft_curckt->ci_curTask)->jobs;

1
src/frontend/spiceif.h

@ -14,6 +14,7 @@ void if_dump(void *ckt, FILE *file);
void if_cktfree(void *ckt, char *tab); void if_cktfree(void *ckt, char *tab);
char * if_errstring(int code); char * if_errstring(int code);
struct variable * spif_getparam(void *ckt, char **name, char *param, int ind, int do_model); struct variable * spif_getparam(void *ckt, char **name, char *param, int ind, int do_model);
void if_setparam_model(void *ckt, char **name, char *val);
void if_setparam(void *ckt, char **name, char *param, struct dvec *val, int do_model); void if_setparam(void *ckt, char **name, char *param, struct dvec *val, int do_model);
int if_analQbyName(void *ckt, int which, void *anal, char *name, IFvalue *parm); int if_analQbyName(void *ckt, int which, void *anal, char *name, IFvalue *parm);
bool if_tranparams(struct circ *ci, double *start, double *stop, double *step); bool if_tranparams(struct circ *ci, double *start, double *stop, double *step);

31
src/frontend/subckt.c

@ -1315,6 +1315,31 @@ gettrans(char *name)
return (NULL); return (NULL);
} }
/*
check if current token matches model bin name -- <token>.[0-9]+
*/
static bool
model_bin_match( char* token, char* model_name )
{
char* dot_char;
bool flag = FALSE;
if ( strncmp( model_name, token, strlen(token) ) == 0 ) {
if ( (dot_char = strstr( model_name, "." )) ) {
flag = TRUE;
dot_char++;
while( *dot_char != '\0' ) {
if ( !isdigit( *dot_char ) ) {
flag = FALSE;
break;
}
dot_char++;
}
}
}
return flag;
}
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
static int static int
@ -1375,9 +1400,11 @@ numnodes(char *name)
txfree(gettok(&s)); /* Skip component name */ txfree(gettok(&s)); /* Skip component name */
while ((i < n) && (*s) && !gotit) { while ((i < n) && (*s) && !gotit) {
t = gettok_node(&s); /* get nodenames . . . */ t = gettok_node(&s); /* get nodenames . . . */
for (wl = modnames; wl; wl = wl->wl_next)
if (eq(t, wl->wl_word))
for (wl = modnames; wl; wl = wl->wl_next) {
/* also need to check if binnable device model */
if (eq(t, wl->wl_word) || model_bin_match( t, wl->wl_word ) )
gotit = 1; gotit = 1;
}
i++; i++;
tfree(t); tfree(t);
} /* while . . . . */ } /* while . . . . */

1
src/include/fteext.h

@ -452,6 +452,7 @@ extern void if_cktfree();
extern void if_dump(); extern void if_dump();
extern int if_option(); extern int if_option();
extern void if_setndnames(); extern void if_setndnames();
extern void if_setparam_model();
extern void if_setparam(); extern void if_setparam();
extern struct variable *if_getstat(); extern struct variable *if_getstat();

1
src/include/inpdefs.h

@ -97,6 +97,7 @@ char *INPerror(int);
double INPevaluate(char**,int*,int); double INPevaluate(char**,int*,int);
char * INPfindLev(char*,int*); char * INPfindLev(char*,int*);
char * INPgetMod(void*,char*,INPmodel**,INPtables*); char * INPgetMod(void*,char*,INPmodel**,INPtables*);
char * INPgetModBin(void*,char*,INPmodel**,INPtables*,char*);
int INPgetTok(char**,char**,int); int INPgetTok(char**,char**,int);
int INPgetNetTok(char**,char**,int); int INPgetNetTok(char**,char**,int);
void INPgetTree(char**,INPparseTree**,void*,INPtables*); void INPgetTree(char**,INPparseTree**,void*,INPtables*);

6
src/main.c

@ -247,6 +247,10 @@ if_errstring(int code)
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
void
if_setparam_model(char *ckt, char *name, struct variable *val)
{}
void void
if_setparam(char *ckt, char *name, char *param, struct variable *val) if_setparam(char *ckt, char *name, char *param, struct variable *val)
{} {}
@ -785,6 +789,8 @@ main(int argc, char **argv)
case 'o': /* Output file */ case 'o': /* Output file */
if (optarg) { if (optarg) {
/* turn off buffering for stdout */
setbuf(stdout, NULL);
#ifdef PARALLEL_ARCH #ifdef PARALLEL_ARCH
sprintf (buf, "%s%03d", optarg, ARCHme); sprintf (buf, "%s%03d", optarg, ARCHme);
#else #else

1
src/spicelib/parser/inp.h

@ -58,6 +58,7 @@ char * INPerrCat(char *a, char *b);
char * INPerror(int type); char * INPerror(int type);
double INPevaluate(char **line, int *error, int gobble); double INPevaluate(char **line, int *error, int gobble);
char * INPfindLev(char *line, int *level); char * INPfindLev(char *line, int *level);
char * INPfindVer(char *line, char *version);
char * INPgetMod(void *ckt, char *name, INPmodel **model, INPtables *tab); char * INPgetMod(void *ckt, char *name, INPmodel **model, INPtables *tab);
int INPgetStr(char **line, char **token, int gobble); int INPgetStr(char **line, char **token, int gobble);
int INPgetTitle(void **ckt, card **data); int INPgetTitle(void **ckt, card **data);

4
src/spicelib/parser/inp2dot.c

@ -642,7 +642,7 @@ INP2dot(void *ckt, INPtables *tab, card *current, void *task, void *gnode)
/* the part of the current line left to parse */ /* the part of the current line left to parse */
char *line = current->line; char *line = current->line;
int rtn = 0; int rtn = 0;
INPgetTok(&line, &token, 1); INPgetTok(&line, &token, 1);
if (strcmp(token, ".model") == 0) { if (strcmp(token, ".model") == 0) {
/* don't have to do anything, since models were all done in /* don't have to do anything, since models were all done in
@ -656,7 +656,9 @@ INP2dot(void *ckt, INPtables *tab, card *current, void *task, void *gnode)
} else if ((strcmp(token, ".temp") == 0)) { } else if ((strcmp(token, ".temp") == 0)) {
/* .temp temp1 temp2 temp3 temp4 ..... */ /* .temp temp1 temp2 temp3 temp4 ..... */
/* not yet implemented - warn & ignore */ /* not yet implemented - warn & ignore */
/*
LITERR(" Warning: .TEMP card obsolete - use .options TEMP and TNOM\n"); LITERR(" Warning: .TEMP card obsolete - use .options TEMP and TNOM\n");
*/
goto quit; goto quit;
} else if ((strcmp(token, ".op") == 0)) { } else if ((strcmp(token, ".op") == 0)) {
rtn = dot_op(line, ckt, tab, current, task, gnode, foo); rtn = dot_op(line, ckt, tab, current, task, gnode, foo);

2
src/spicelib/parser/inpdomod.c

@ -21,6 +21,7 @@ char *INPdomodel(void *ckt, card * image, INPtables * tab)
char *modname; char *modname;
int type = -1; int type = -1;
int lev; int lev;
char ver[100];
char *typename; char *typename;
char *err = (char *) NULL; char *err = (char *) NULL;
char *line; char *line;
@ -213,6 +214,7 @@ char *INPdomodel(void *ckt, card * image, INPtables * tab)
|| (strcmp(typename, "nsoi") == 0) || (strcmp(typename, "nsoi") == 0)
|| (strcmp(typename, "psoi") == 0)) { || (strcmp(typename, "psoi") == 0)) {
err = INPfindLev(line, &lev); err = INPfindLev(line, &lev);
err = INPfindVer(line, ver);
switch (lev) { switch (lev) {
case 0: case 0:
case 1: case 1:

38
src/spicelib/parser/inpfindv.c

@ -0,0 +1,38 @@
/* INPfindVer(line,version)
* find the 'version' parameter on the given line and return its
* return 'default' as version if not found
*
*/
#include "ngspice.h"
#include <stdio.h>
#include <string.h>
#include "inpdefs.h"
#include "inp.h"
char *INPfindVer(char *line, char *version)
{
char *where;
where = strstr(line, "version");
if (where != NULL) { /* found a version keyword on the line */
where += 7; /* skip the version keyword */
while ((*where == ' ') || (*where == '\t') || (*where == '=') ||
(*where == ',') || (*where == '(') || (*where == ')') ||
(*where == '+')) { /* legal white space - ignore */
where++;
}
/* now the magic string */
sscanf(where, "%s", version); /* We get the version number */
return ((char *) NULL);
}
else { /* no level on the line => default */
sprintf( version, "default" );
printf("Warning -- Version not specified on line \"%s\"\nSetting version to 'default'.\n", line);
return ((char *) NULL);
}
}

345
src/spicelib/parser/inpgmod.c

@ -34,152 +34,257 @@ static int INPfindParm( char *name, IFparm *table, int numParms );
extern INPmodel *modtab; extern INPmodel *modtab;
char *INPgetMod(void *ckt, char *name, INPmodel ** model, INPtables * tab)
/*
code moved from INPgetMod
*/
static int
create_model( void* ckt, INPmodel* modtmp, INPtables* tab )
{ {
INPmodel *modtmp;
IFvalue *val;
register int j;
char *line;
char *parm;
char *err = NULL;
char *temp;
int error;
IFvalue* val;
char* err = NULL;
char* line;
char* parm;
char* temp;
int error = 0;
int j;
#ifdef TRACE
/* SDB debug statement */
printf("In INPgetMod, examining model %s . . . \n", name);
#endif
/* not already defined, so create & give parameters */
error = (*(ft_sim->newModel))(ckt, (modtmp)->INPmodType, &((modtmp)->INPmodfast), (modtmp)->INPmodName);
for (modtmp = modtab; modtmp != (INPmodel *) NULL; modtmp =
((modtmp)->INPnextModel)) {
if (error) return error;
#ifdef TRACE
/* SDB debug statement */
printf("In INPgetMod, comparing against stored model %s . . . \n", (modtmp)->INPmodName);
#endif
/* parameter isolation, identification, binding */
if (strcmp((modtmp)->INPmodName, name) == 0) {
/* found the model in question - now instantiate if necessary */
/* and return an appropriate pointer to it */
#ifdef CIDER
/* begin cider integration */
/* Handle Numerical Models Differently */
if ( ((modtmp)->INPmodType == INPtypelook("NUMD")) ||
((modtmp)->INPmodType == INPtypelook("NBJT")) ||
((modtmp)->INPmodType == INPtypelook("NUMD2")) ||
((modtmp)->INPmodType == INPtypelook("NBJT2")) ||
((modtmp)->INPmodType == INPtypelook("NUMOS")) ) {
error = INPparseNumMod( ckt, modtmp, tab, &err );
if (error) return error;
} else {
/* It's an analytical model */
#endif /* CIDER */
if (modtmp->INPmodType < 0) { /* First check for illegal model type */
/* illegal device type, so can't handle */
*model = (INPmodel *) NULL;
err = (char *) MALLOC((35 + strlen(name)) * sizeof(char));
(void) sprintf(err,
"Unknown device type for model %s \n",
name);
line = ((modtmp)->INPmodLine)->line;
#ifdef TRACE #ifdef TRACE
/* SDB debug statement */
printf("In INPgetMod, illegal device type for model %s . . . \n", name);
/* SDB debug statement */
printf("In INPgetMod, inserting new model into table. line = %s . . . \n", line);
#endif #endif
return (err);
} /* end of checking for illegal model */
INPgetTok(&line, &parm, 1); /* throw away '.model' */
tfree(parm);
INPgetTok(&line, &parm, 1); /* throw away 'modname' */
tfree(parm);
while (*line != 0) {
INPgetTok(&line, &parm, 1);
if (!*parm)
continue;
for (j = 0; j < (* (*(ft_sim->devices)[(modtmp)->INPmodType]).numModelParms); j++) {
if (strcmp(parm, "txl") == 0) {
if (strcmp("cpl", ((*(ft_sim->devices) [ (modtmp)->INPmodType ]).modelParms[j].keyword)) == 0) {
strcpy(parm, "cpl");
}
}
if (strcmp(parm,((*(ft_sim->devices)[(modtmp)->INPmodType]).modelParms[j].keyword)) == 0) {
val = INPgetValue(ckt, &line, ((* (ft_sim->devices)[(modtmp)->INPmodType]).modelParms[j].dataType), tab);
error = (*(ft_sim->setModelParm)) (ckt, ((modtmp)->INPmodfast),
(* (ft_sim->devices)[(modtmp)->INPmodType]).modelParms[j].id,
val, (IFvalue *) NULL);
if (error)
return error;
break;
}
} /* end for(j = 0 . . .*/
if (strcmp(parm, "level") == 0) {
/* just grab the level number and throw away */
/* since we already have that info from pass1 */
val = INPgetValue(ckt, &line, IF_REAL, tab);
} else if (j >=
(*
(*(ft_sim->devices)
[(modtmp)->INPmodType]).numModelParms)) {
temp =
(char *) MALLOC((40 + strlen(parm)) *
sizeof(char));
(void) sprintf(temp,
"unrecognized parameter (%s) - ignored\n",
parm);
err = INPerrCat(err, temp);
}
FREE(parm);
}
#ifdef CIDER
} /* analytical vs. numerical model parsing */
#endif
(modtmp)->INPmodUsed = 1;
(modtmp)->INPmodLine->error = err;
if (!((modtmp)->INPmodUsed)) { /* Check if model is already defined */
/* not already defined, so create & give parameters */
error = (*(ft_sim->newModel)) (ckt, (modtmp)->INPmodType,
&((modtmp)->INPmodfast),
(modtmp)->INPmodName);
if (error)
return (INPerror(error));
/* parameter isolation, identification, binding */
return 0;
}
#ifdef CIDER
/* begin cider integration */
/* Handle Numerical Models Differently */
if ( ((modtmp)->INPmodType == INPtypelook("NUMD")) ||
((modtmp)->INPmodType == INPtypelook("NBJT")) ||
((modtmp)->INPmodType == INPtypelook("NUMD2")) ||
((modtmp)->INPmodType == INPtypelook("NBJT2")) ||
((modtmp)->INPmodType == INPtypelook("NUMOS")) ) {
error = INPparseNumMod( ckt, modtmp, tab, &err );
if (error) return(INPerror(error));
} else {
/* It's an analytical model */
#endif /* CIDER */
static bool
parse_line( char* line, char* tokens[], int num_tokens, double values[], bool found[] )
{
char* token;
int get_index = -1;
int i;
bool flag = TRUE;
int error;
for ( i = 0; i < num_tokens; i++ )
found[i] = FALSE;
while( *line != '\0' ) {
if ( get_index != -1 ) {
values[get_index] = INPevaluate( &line, &error, 1 );
found[get_index] = TRUE;
get_index = -1;
continue;
} else {
INPgetNetTok( &line, &token, 1 );
}
for ( i = 0; i < num_tokens; i++ )
if ( strcmp( tokens[i], token ) == 0 ) get_index = i;
}
for ( i = 0; i < num_tokens; i++ )
if ( found[i] == FALSE ) {
flag = FALSE;
break;
}
return flag;
}
static bool
is_equal( double result, double expectedResult )
{
//if (fabs(result - expectedResult) < 0.00001) return TRUE;
if (fabs(result - expectedResult) < 1e-15) return TRUE;
else return FALSE;
}
static bool
in_range( double value, double min, double max )
{
if ( (is_equal( value, min ) == TRUE) || (is_equal( value, max ) == TRUE) ||
(min < value && value < max) ) return TRUE;
else return FALSE;
}
char*
INPgetModBin( void* ckt, char* name, INPmodel** model, INPtables* tab, char* line )
{
INPmodel* modtmp;
double l, w, lmin, lmax, wmin, wmax;
double parse_values[4];
bool parse_found[4];
static char* instance_tokens[] = { "l", "w" };
static char* model_tokens[] = { "lmin", "lmax", "wmin", "wmax" };
int error;
double scale;
if ( !cp_getvar( "scale", CP_REAL, (double*) &scale ) ) scale = 1;
*model = NULL;
if ( parse_line( line, instance_tokens, 2, parse_values, parse_found ) != TRUE )
return NULL;
l = parse_values[0]*scale;
w = parse_values[1]*scale;
for ( modtmp = modtab; modtmp != (INPmodel*)NULL; modtmp = modtmp->INPnextModel ) {
if ( modtmp->INPmodType != INPtypelook( "BSIM3" ) && modtmp->INPmodType != INPtypelook( "BSIM4" ) &&
modtmp->INPmodType != INPtypelook( "BSIM4v5" ) && modtmp->INPmodType != INPtypelook( "BSIM4v6" ) )
continue;
if ( parse_line( modtmp->INPmodLine->line, model_tokens, 4, parse_values, parse_found ) != TRUE )
continue;
lmin = parse_values[0]; lmax = parse_values[1];
wmin = parse_values[2]; wmax = parse_values[3];
if ( strncmp( modtmp->INPmodName, name, strlen( name ) ) == 0 &&
in_range( l, lmin, lmax ) && in_range( w, wmin, wmax ) ) {
if ( !modtmp->INPmodUsed ) {
error = create_model( ckt, modtmp, tab );
if ( error ) return NULL;
}
*model = modtmp;
return NULL;
}
}
return NULL;
}
line = ((modtmp)->INPmodLine)->line;
char *INPgetMod(void *ckt, char *name, INPmodel ** model, INPtables * tab)
{
INPmodel *modtmp;
char *err = NULL;
int error;
#ifdef TRACE #ifdef TRACE
/* SDB debug statement */
printf("In INPgetMod, inserting new model into table. line = %s . . . \n", line);
/* SDB debug statement */
printf("In INPgetMod, examining model %s . . . \n", name);
#endif #endif
for (modtmp = modtab; modtmp != (INPmodel *) NULL; modtmp = ((modtmp)->INPnextModel)) {
INPgetTok(&line, &parm, 1); /* throw away '.model' */
tfree(parm);
INPgetTok(&line, &parm, 1); /* throw away 'modname' */
tfree(parm);
while (*line != 0) {
INPgetTok(&line, &parm, 1);
if (!*parm)
continue;
#ifdef TRACE
/* SDB debug statement */
printf("In INPgetMod, comparing against stored model %s . . . \n", (modtmp)->INPmodName);
#endif
for (j = 0; j < (* (*(ft_sim->devices)[(modtmp)->INPmodType]).numModelParms); j++) {
if (strcmp((modtmp)->INPmodName, name) == 0) {
/* found the model in question - now instantiate if necessary */
/* and return an appropriate pointer to it */
if (strcmp(parm, "txl") == 0) {
if (strcmp("cpl", ((*(ft_sim->devices) [ (modtmp)->INPmodType ]).modelParms[j].keyword)) == 0) {
strcpy(parm, "cpl");
}
}
if (strcmp(parm,((*(ft_sim->devices)[(modtmp)->INPmodType]).modelParms[j].keyword)) == 0) {
val = INPgetValue(ckt, &line, ((* (ft_sim->devices)[(modtmp)->INPmodType]).modelParms[j].dataType), tab);
error = (*(ft_sim->setModelParm)) (ckt, ((modtmp)->INPmodfast),
(* (ft_sim->devices)[(modtmp)->INPmodType]).modelParms[j].id,
val, (IFvalue *) NULL);
if (error)
return (INPerror(error));
break;
}
} /* end for(j = 0 . . .*/
if (strcmp(parm, "level") == 0) {
/* just grab the level number and throw away */
/* since we already have that info from pass1 */
val = INPgetValue(ckt, &line, IF_REAL, tab);
} else if (j >=
(*
(*(ft_sim->devices)
[(modtmp)->INPmodType]).numModelParms)) {
temp =
(char *) MALLOC((40 + strlen(parm)) *
sizeof(char));
(void) sprintf(temp,
"unrecognized parameter (%s) - ignored\n",
parm);
err = INPerrCat(err, temp);
}
FREE(parm);
}
#ifdef CIDER
} /* analytical vs. numerical model parsing */
if (modtmp->INPmodType < 0) { /* First check for illegal model type */
/* illegal device type, so can't handle */
*model = (INPmodel *) NULL;
err = (char *) MALLOC((35 + strlen(name)) * sizeof(char));
(void) sprintf(err,"Unknown device type for model %s \n", name);
#ifdef TRACE
/* SDB debug statement */
printf("In INPgetMod, illegal device type for model %s . . . \n", name);
#endif #endif
(modtmp)->INPmodUsed = 1;
(modtmp)->INPmodLine->error = err;
}
*model = modtmp;
return ((char *) NULL);
}
return (err);
} /* end of checking for illegal model */
if (!((modtmp)->INPmodUsed)) { /* Check if model is already defined */
error = create_model( ckt, modtmp, tab );
if ( error ) return INPerror(error);
}
*model = modtmp;
return ((char *) NULL);
} }
/* didn't find model - ERROR - return model */
*model = (INPmodel *) NULL;
err = (char *) MALLOC((60 + strlen(name)) * sizeof(char));
(void) sprintf(err,
" unable to find definition of model %s - default assumed \n",
name);
}
/* didn't find model - ERROR - return model */
*model = (INPmodel *) NULL;
err = (char *) MALLOC((60 + strlen(name)) * sizeof(char));
(void) sprintf(err," unable to find definition of model %s - default assumed \n", name);
#ifdef TRACE #ifdef TRACE
/* SDB debug statement */
printf("In INPgetMod, didn't find model for %s, using default . . . \n", name);
/* SDB debug statement */
printf("In INPgetMod, didn't find model for %s, using default . . . \n", name);
#endif #endif
return (err);
return (err);
} }
#ifdef CIDER #ifdef CIDER

Loading…
Cancel
Save