From 53e52f4a5922ab09ca7a81b78892255c2b48af3d Mon Sep 17 00:00:00 2001 From: pnenzi Date: Mon, 8 Oct 2007 21:45:00 +0000 Subject: [PATCH] Model improvements from Phil Barker --- ChangeLog | 16 +- src/frontend/spiceif.c | 90 ++++++++- src/frontend/spiceif.h | 1 + src/frontend/subckt.c | 31 ++- src/include/fteext.h | 1 + src/include/inpdefs.h | 1 + src/main.c | 6 + src/spicelib/parser/inp.h | 1 + src/spicelib/parser/inp2dot.c | 4 +- src/spicelib/parser/inpdomod.c | 2 + src/spicelib/parser/inpfindv.c | 38 ++++ src/spicelib/parser/inpgmod.c | 345 +++++++++++++++++++++------------ 12 files changed, 403 insertions(+), 133 deletions(-) create mode 100644 src/spicelib/parser/inpfindv.c 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