Model improvements from Phil Barker
This commit is contained in:
parent
936cd7a4fc
commit
53e52f4a59
16
ChangeLog
16
ChangeLog
|
|
@ -1,5 +1,15 @@
|
|||
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
|
||||
several improvements mad by Phil Barker:
|
||||
- .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
|
||||
- changed the flattened netlist names created in 'subckt.c' to match other
|
||||
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>
|
||||
* src/frontend/{rawfile.c, outitf.c, runcoms.c}, src/include/ftedefs.h:
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ if_inpdeck(struct line *deck, INPtables **tab)
|
|||
INPpas1((void *) ckt, (card *) deck->li_next,(INPtables *)*tab);
|
||||
INPpas2((void *) ckt, (card *) deck->li_next,
|
||||
(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
|
||||
* 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));
|
||||
}
|
||||
|
||||
/* 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
|
||||
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);
|
||||
*modptr = (void *)NULL;
|
||||
return(-1);
|
||||
|
||||
}
|
||||
|
||||
/* get an analysis parameter by name instead of id */
|
||||
|
|
@ -1165,7 +1245,7 @@ do {\
|
|||
if(__i) {\
|
||||
if(name)\
|
||||
tfree(name);\
|
||||
name = tmalloc(__i);\
|
||||
name = (type *)tmalloc(__i);\
|
||||
fread(name,1,__i,file);\
|
||||
} else {\
|
||||
fprintf(cp_err, "size for vector " #name " is 0\n");\
|
||||
|
|
@ -1196,7 +1276,7 @@ do {\
|
|||
|
||||
_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 */
|
||||
((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)->jobs,TRANan,1);
|
||||
_foo(((TRANan *)((TSKtask *)ft_curckt->ci_curTask)->jobs),TRANan,1);
|
||||
((TSKtask *)ft_curckt->ci_curTask)->jobs->JOBname = NULL;
|
||||
ckt->CKTcurJob = (JOB *)((TSKtask *)ft_curckt->ci_curTask)->jobs;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ void if_dump(void *ckt, FILE *file);
|
|||
void if_cktfree(void *ckt, char *tab);
|
||||
char * if_errstring(int code);
|
||||
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);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1315,6 +1315,31 @@ gettrans(char *name)
|
|||
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
|
||||
|
|
@ -1375,9 +1400,11 @@ numnodes(char *name)
|
|||
txfree(gettok(&s)); /* Skip component name */
|
||||
while ((i < n) && (*s) && !gotit) {
|
||||
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;
|
||||
}
|
||||
i++;
|
||||
tfree(t);
|
||||
} /* while . . . . */
|
||||
|
|
|
|||
|
|
@ -452,6 +452,7 @@ extern void if_cktfree();
|
|||
extern void if_dump();
|
||||
extern int if_option();
|
||||
extern void if_setndnames();
|
||||
extern void if_setparam_model();
|
||||
extern void if_setparam();
|
||||
extern struct variable *if_getstat();
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ char *INPerror(int);
|
|||
double INPevaluate(char**,int*,int);
|
||||
char * INPfindLev(char*,int*);
|
||||
char * INPgetMod(void*,char*,INPmodel**,INPtables*);
|
||||
char * INPgetModBin(void*,char*,INPmodel**,INPtables*,char*);
|
||||
int INPgetTok(char**,char**,int);
|
||||
int INPgetNetTok(char**,char**,int);
|
||||
void INPgetTree(char**,INPparseTree**,void*,INPtables*);
|
||||
|
|
|
|||
|
|
@ -247,6 +247,10 @@ if_errstring(int code)
|
|||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
void
|
||||
if_setparam_model(char *ckt, char *name, struct variable *val)
|
||||
{}
|
||||
|
||||
void
|
||||
if_setparam(char *ckt, char *name, char *param, struct variable *val)
|
||||
{}
|
||||
|
|
@ -785,6 +789,8 @@ main(int argc, char **argv)
|
|||
|
||||
case 'o': /* Output file */
|
||||
if (optarg) {
|
||||
/* turn off buffering for stdout */
|
||||
setbuf(stdout, NULL);
|
||||
#ifdef PARALLEL_ARCH
|
||||
sprintf (buf, "%s%03d", optarg, ARCHme);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ char * INPerrCat(char *a, char *b);
|
|||
char * INPerror(int type);
|
||||
double INPevaluate(char **line, int *error, int gobble);
|
||||
char * INPfindLev(char *line, int *level);
|
||||
char * INPfindVer(char *line, char *version);
|
||||
char * INPgetMod(void *ckt, char *name, INPmodel **model, INPtables *tab);
|
||||
int INPgetStr(char **line, char **token, int gobble);
|
||||
int INPgetTitle(void **ckt, card **data);
|
||||
|
|
|
|||
|
|
@ -642,7 +642,7 @@ INP2dot(void *ckt, INPtables *tab, card *current, void *task, void *gnode)
|
|||
/* the part of the current line left to parse */
|
||||
char *line = current->line;
|
||||
int rtn = 0;
|
||||
|
||||
|
||||
INPgetTok(&line, &token, 1);
|
||||
if (strcmp(token, ".model") == 0) {
|
||||
/* 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)) {
|
||||
/* .temp temp1 temp2 temp3 temp4 ..... */
|
||||
/* not yet implemented - warn & ignore */
|
||||
/*
|
||||
LITERR(" Warning: .TEMP card obsolete - use .options TEMP and TNOM\n");
|
||||
*/
|
||||
goto quit;
|
||||
} else if ((strcmp(token, ".op") == 0)) {
|
||||
rtn = dot_op(line, ckt, tab, current, task, gnode, foo);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ char *INPdomodel(void *ckt, card * image, INPtables * tab)
|
|||
char *modname;
|
||||
int type = -1;
|
||||
int lev;
|
||||
char ver[100];
|
||||
char *typename;
|
||||
char *err = (char *) NULL;
|
||||
char *line;
|
||||
|
|
@ -213,6 +214,7 @@ char *INPdomodel(void *ckt, card * image, INPtables * tab)
|
|||
|| (strcmp(typename, "nsoi") == 0)
|
||||
|| (strcmp(typename, "psoi") == 0)) {
|
||||
err = INPfindLev(line, &lev);
|
||||
err = INPfindVer(line, ver);
|
||||
switch (lev) {
|
||||
case 0:
|
||||
case 1:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -34,152 +34,257 @@ static int INPfindParm( char *name, IFparm *table, int numParms );
|
|||
|
||||
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
|
||||
|
||||
if (strcmp((modtmp)->INPmodName, name) == 0) {
|
||||
/* found the model in question - now instantiate if necessary */
|
||||
/* and return an appropriate pointer to it */
|
||||
|
||||
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
|
||||
|
||||
return (err);
|
||||
} /* end of checking for illegal model */
|
||||
|
||||
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 */
|
||||
/* parameter isolation, identification, binding */
|
||||
|
||||
#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 */
|
||||
/* 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 */
|
||||
|
||||
line = ((modtmp)->INPmodLine)->line;
|
||||
|
||||
#ifdef TRACE
|
||||
/* SDB debug statement */
|
||||
printf("In INPgetMod, inserting new model into table. line = %s . . . \n", line);
|
||||
#endif
|
||||
|
||||
|
||||
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 (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 */
|
||||
#endif
|
||||
(modtmp)->INPmodUsed = 1;
|
||||
(modtmp)->INPmodLine->error = err;
|
||||
}
|
||||
*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);
|
||||
line = ((modtmp)->INPmodLine)->line;
|
||||
|
||||
#ifdef TRACE
|
||||
/* SDB debug statement */
|
||||
printf("In INPgetMod, didn't find model for %s, using default . . . \n", name);
|
||||
printf("In INPgetMod, inserting new model into table. line = %s . . . \n", line);
|
||||
#endif
|
||||
|
||||
return (err);
|
||||
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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
char *INPgetMod(void *ckt, char *name, INPmodel ** model, INPtables * tab)
|
||||
{
|
||||
INPmodel *modtmp;
|
||||
char *err = NULL;
|
||||
int error;
|
||||
|
||||
#ifdef TRACE
|
||||
/* SDB debug statement */
|
||||
printf("In INPgetMod, examining model %s . . . \n", name);
|
||||
#endif
|
||||
|
||||
for (modtmp = modtab; modtmp != (INPmodel *) NULL; modtmp = ((modtmp)->INPnextModel)) {
|
||||
|
||||
#ifdef TRACE
|
||||
/* SDB debug statement */
|
||||
printf("In INPgetMod, comparing against stored model %s . . . \n", (modtmp)->INPmodName);
|
||||
#endif
|
||||
|
||||
if (strcmp((modtmp)->INPmodName, name) == 0) {
|
||||
/* found the model in question - now instantiate if necessary */
|
||||
/* and return an appropriate pointer to it */
|
||||
|
||||
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
|
||||
|
||||
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);
|
||||
|
||||
#ifdef TRACE
|
||||
/* SDB debug statement */
|
||||
printf("In INPgetMod, didn't find model for %s, using default . . . \n", name);
|
||||
#endif
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
#ifdef CIDER
|
||||
|
|
|
|||
Loading…
Reference in New Issue