diff --git a/ChangeLog b/ChangeLog
index 1b304b7f6..d8ca40e6b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
2007-10-8 Paolo Nenzi
- *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
+ * 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
* src/frontend/{rawfile.c, outitf.c, runcoms.c}, src/include/ftedefs.h:
diff --git a/src/frontend/spiceif.c b/src/frontend/spiceif.c
index 473fad3ac..79654a83f 100644
--- a/src/frontend/spiceif.c
+++ b/src/frontend/spiceif.c
@@ -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;
diff --git a/src/frontend/spiceif.h b/src/frontend/spiceif.h
index 4195fba3d..bc7943e0f 100644
--- a/src/frontend/spiceif.h
+++ b/src/frontend/spiceif.h
@@ -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);
diff --git a/src/frontend/subckt.c b/src/frontend/subckt.c
index 2d7e9521d..ab3967a69 100644
--- a/src/frontend/subckt.c
+++ b/src/frontend/subckt.c
@@ -1315,6 +1315,31 @@ gettrans(char *name)
return (NULL);
}
+/*
+ check if current token matches model bin name -- .[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 . . . . */
diff --git a/src/include/fteext.h b/src/include/fteext.h
index 7c9fc15ce..c84908ee2 100644
--- a/src/include/fteext.h
+++ b/src/include/fteext.h
@@ -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();
diff --git a/src/include/inpdefs.h b/src/include/inpdefs.h
index 232e5b908..ccaf2c6c2 100644
--- a/src/include/inpdefs.h
+++ b/src/include/inpdefs.h
@@ -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*);
diff --git a/src/main.c b/src/main.c
index b3395af4d..72a5a1545 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
diff --git a/src/spicelib/parser/inp.h b/src/spicelib/parser/inp.h
index 7de4abcde..30e008647 100644
--- a/src/spicelib/parser/inp.h
+++ b/src/spicelib/parser/inp.h
@@ -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);
diff --git a/src/spicelib/parser/inp2dot.c b/src/spicelib/parser/inp2dot.c
index f3e3f395c..1c6ceedd9 100644
--- a/src/spicelib/parser/inp2dot.c
+++ b/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 */
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);
diff --git a/src/spicelib/parser/inpdomod.c b/src/spicelib/parser/inpdomod.c
index 939375383..81d0c4a39 100644
--- a/src/spicelib/parser/inpdomod.c
+++ b/src/spicelib/parser/inpdomod.c
@@ -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:
diff --git a/src/spicelib/parser/inpfindv.c b/src/spicelib/parser/inpfindv.c
new file mode 100644
index 000000000..0c75d82bd
--- /dev/null
+++ b/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
+#include
+#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);
+ }
+}
diff --git a/src/spicelib/parser/inpgmod.c b/src/spicelib/parser/inpgmod.c
index f331d5183..812bfdc49 100644
--- a/src/spicelib/parser/inpgmod.c
+++ b/src/spicelib/parser/inpgmod.c
@@ -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
+ /* 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
- /* 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
- 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
- /* 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
+ 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
- (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
- /* 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
- return (err);
+ return (err);
}
#ifdef CIDER