From 1facfd764d9d02db854ba51642a36dedfc24d936 Mon Sep 17 00:00:00 2001 From: sjborley Date: Mon, 9 May 2005 20:20:18 +0000 Subject: [PATCH] Added new syntax to the the resistor card to support HSpice style temperature dependence (from Hitoshi Tanaka ) --- ChangeLog | 11 +++ src/frontend/outitf.c | 8 ++ src/frontend/plotting/plotit.c | 4 + src/frontend/typesdef.c | 8 +- src/include/sim.h | 4 +- src/spicelib/devices/res/res.c | 3 + src/spicelib/devices/res/resask.c | 6 ++ src/spicelib/devices/res/resdefs.h | 10 ++- src/spicelib/devices/res/resload.c | 47 ++++++++---- src/spicelib/devices/res/resparam.c | 12 ++- src/spicelib/devices/res/restemp.c | 7 +- src/spicelib/parser/inp2r.c | 113 ++++++++++++++++++++++++++-- 12 files changed, 201 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index a88cca790..61c38a1c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2005-05-09 Steven Borley + + * Added new syntax to the the resistor card to support HSpice style + temperature dependence (from Hitoshi Tanaka ). + Syntax forms now include: + Rxxx n2> TC= + Rxxx n2> TC1= + Rxxx n2> TC1= TC2= + Rxxx n2> TC= + The the first pair are equivalent, and the last pair are equivalent. + 2005-05-07 Steven Borley * Added support for the BSD licensed editline library diff --git a/src/frontend/outitf.c b/src/frontend/outitf.c index 9414e0690..92c714c6c 100644 --- a/src/frontend/outitf.c +++ b/src/frontend/outitf.c @@ -754,6 +754,10 @@ fileInit_pass2(runDesc *run) type = SV_TIME; else if (cieq(name, "frequency")) type = SV_FREQUENCY; + else if (cieq(name, "temp-sweep")) /* Added by H.T */ + type = SV_TEMP; + else if (cieq(name, "res-sweep")) /* Added by H.T */ + type = SV_RES; else type = SV_VOLTAGE; @@ -899,6 +903,10 @@ plotInit(runDesc *run) v->v_type = SV_TIME; else if (cieq(v->v_name, "frequency")) v->v_type = SV_FREQUENCY; + else if (cieq(v->v_name, "temp-sweep")) /* Added by H.T */ + v->v_type = SV_TEMP; + else if (cieq(v->v_name, "res-sweep")) /* Added by H.T */ + v->v_type = SV_RES; else v->v_type = SV_VOLTAGE; v->v_length = 0; diff --git a/src/frontend/plotting/plotit.c b/src/frontend/plotting/plotit.c index f0c92137e..82c98ef8d 100644 --- a/src/frontend/plotting/plotit.c +++ b/src/frontend/plotting/plotit.c @@ -616,6 +616,10 @@ plotit(wordlist *wl, char *hcopy, char *devname) d->v_scale = d; } + /* The following line displays the unit at the time of + temp-sweep and res-sweep. This may not be a so good solution. by H.T */ + if(!strcmp(vecs->v_scale->v_name,"temp-sweep")) vecs->v_scale->v_type=14; + if(!strcmp(vecs->v_scale->v_name,"res-sweep")) vecs->v_scale->v_type=15; /* See if the log flag is set anywhere... */ if (!gfound) { diff --git a/src/frontend/typesdef.c b/src/frontend/typesdef.c index 8b74a23af..5f7d586b4 100644 --- a/src/frontend/typesdef.c +++ b/src/frontend/typesdef.c @@ -45,6 +45,10 @@ struct type types[NUMTYPES] = { { "pole", NULL } , { "zero", NULL } , { "s-param", NULL } , + { "temp-sweep", "Celsius" } ,/* Added by HT */ + + { "res-sweep", "Ohm" } ,/* Added by HT */ + } ; /* The stuff for plot names. */ @@ -73,8 +77,8 @@ struct plotab plotabs[NUMPLOTTYPES] = { { "spect", "spect" }, } ; -int notypes = 14; -int noplotabs = 18; +int notypes = 15;/* change 14 to 15 by H.T*/ +int noplotabs = 20;/* change 18 to 20 by H.T*/ /* A command to define types for vectors and plots. This will generally * be used in the Command: field of the rawfile. diff --git a/src/include/sim.h b/src/include/sim.h index 67c5f1400..09379e294 100644 --- a/src/include/sim.h +++ b/src/include/sim.h @@ -13,7 +13,9 @@ enum simulation_types { SV_INPUT_NOISE, SV_POLE, SV_ZERO, - SV_SPARAM + SV_SPARAM, + SV_TEMP, + SV_RES }; #endif diff --git a/src/spicelib/devices/res/res.c b/src/spicelib/devices/res/res.c index d2d8ecf8a..8e635602e 100644 --- a/src/spicelib/devices/res/res.c +++ b/src/spicelib/devices/res/res.c @@ -19,6 +19,9 @@ IFparm RESpTable[] = { /* parameters */ IOPQU( "l", RES_LENGTH, IF_REAL, "Length"), IOPZU( "w", RES_WIDTH, IF_REAL, "Width"), IOPU( "m", RES_M, IF_REAL, "Multiplication factor"), + IOPU( "tc", RES_TC1, IF_REAL, "First order temp. coefficient"), + IOPU( "tc1", RES_TC1, IF_REAL, "First order temp. coefficient"), + IOPU( "tc2", RES_TC2, IF_REAL, "Second order temp. coefficient"), IOPU( "scale", RES_SCALE, IF_REAL, "Scale factor"), IOP( "noisy", RES_NOISY, IF_INTEGER, "Resistor generate noise"), IP( "sens_resist", RES_RESIST_SENS, IF_FLAG, diff --git a/src/spicelib/devices/res/resask.c b/src/spicelib/devices/res/resask.c index 051733ed1..70c5ce48b 100644 --- a/src/spicelib/devices/res/resask.c +++ b/src/spicelib/devices/res/resask.c @@ -64,6 +64,12 @@ RESask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, case RES_M: value->rValue = fast->RESm; return(OK); + case RES_TC1: + value->rValue = fast->REStc1; + return(OK); + case RES_TC2: + value->rValue = fast->REStc2; + return(OK); case RES_NOISY: value->iValue = fast->RESnoisy; return(OK); diff --git a/src/spicelib/devices/res/resdefs.h b/src/spicelib/devices/res/resdefs.h index 735750e8f..1e913589c 100644 --- a/src/spicelib/devices/res/resdefs.h +++ b/src/spicelib/devices/res/resdefs.h @@ -41,6 +41,8 @@ typedef struct sRESinstance { double RESlength; /* length of the resistor */ double RESscale; /* Scale factor */ double RESm; /* Multiplicity factor for this instance */ + double REStc1; /* first temperature coefficient of resistors */ + double REStc2; /* second temperature coefficient of resistors */ int RESnoisy; /* Set if the resistor generates noise */ double *RESposPosptr; /* pointer to sparse matrix diagonal at * (positive,positive) */ @@ -59,6 +61,8 @@ typedef struct sRESinstance { /* serban */ unsigned RESacresGiven : 1; /* indicates AC value specified */ unsigned RESmGiven : 1; /* indicates M parameter specified */ + unsigned REStc1Given : 1; /* indicates tc1 parameter specified */ + unsigned REStc2Given : 1; /* indicates tc2 parameter specified */ unsigned RESnoisyGiven : 1; /* indicates if noisy is specified */ int RESsenParmNo; /* parameter # for sensitivity use; * set equal to 0 if not a design parameter*/ @@ -75,7 +79,7 @@ typedef struct sRESinstance { #ifndef NONOISE double RESnVar[NSTATVARS][RESNSRCS]; #else /* NONOISE */ - double **RESnVar; + double **RESnVar; #endif /* NONOISE */ } RESinstance ; @@ -127,7 +131,9 @@ typedef struct sRESmodel { /* model structure for a resistor */ #define RES_SCALE 13 /* pn */ #define RES_DTEMP 14 /* pn */ #define RES_NOISY 15 /* pn */ - +/* tanaka */ +#define RES_TC1 16 +#define RES_TC2 17 /* model parameters */ #define RES_MOD_TC1 101 diff --git a/src/spicelib/devices/res/resload.c b/src/spicelib/devices/res/resload.c index d63311058..0f8efd573 100644 --- a/src/spicelib/devices/res/resload.c +++ b/src/spicelib/devices/res/resload.c @@ -17,7 +17,8 @@ RESload(GENmodel *inModel, CKTcircuit *ckt) { RESmodel *model = (RESmodel *)inModel; double m; - + double difference; + double factor; /* loop through all the resistor models */ @@ -26,19 +27,27 @@ RESload(GENmodel *inModel, CKTcircuit *ckt) /* loop through all the instances of the model */ for (here = model->RESinstances; here != NULL ; - here = here->RESnextInstance) { - - if (here->RESowner != ARCHme) continue; - - here->REScurrent = (*(ckt->CKTrhsOld+here->RESposNode) - - *(ckt->CKTrhsOld+here->RESnegNode)) * here->RESconduct; - - m = here->RESm; + here = here->RESnextInstance) { - *(here->RESposPosptr) += m * here->RESconduct; - *(here->RESnegNegptr) += m * here->RESconduct; - *(here->RESposNegptr) -= m * here->RESconduct; - *(here->RESnegPosptr) -= m * here->RESconduct; + if(!here->REStc1Given) here->REStc1 = 0.0; + if(!here->REStc2Given) here->REStc2 = 0.0; + if(!here->RESmGiven) here->RESm = 1.0; + + if (here->RESowner != ARCHme) continue; + + here->REScurrent = (*(ckt->CKTrhsOld+here->RESposNode) - + *(ckt->CKTrhsOld+here->RESnegNode)) * here->RESconduct; + + difference = (here->REStemp + here->RESdtemp) - 300.15; + factor = 1.0 + (here->REStc1)*difference + + (here->REStc2)*difference*difference; + + m = (here->RESm)/factor; + + *(here->RESposPosptr) += m * here->RESconduct; + *(here->RESnegNegptr) += m * here->RESconduct; + *(here->RESposNegptr) -= m * here->RESconduct; + *(here->RESnegPosptr) -= m * here->RESconduct; } } return(OK); @@ -52,6 +61,8 @@ RESacload(GENmodel *inModel, CKTcircuit *ckt) { RESmodel *model = (RESmodel *)inModel; double m; + double difference; + double factor; /* loop through all the resistor models */ for( ; model != NULL; model = model->RESnextModel ) { @@ -60,10 +71,18 @@ RESacload(GENmodel *inModel, CKTcircuit *ckt) /* loop through all the instances of the model */ for (here = model->RESinstances; here != NULL ; here = here->RESnextInstance) { + + if(!here->REStc1Given) here->REStc1 = 0.0; + if(!here->REStc2Given) here->REStc2 = 0.0; + if(!here->RESmGiven) here->RESm = 1.0; if (here->RESowner != ARCHme) continue; - m = here->RESm; + difference = (here->REStemp + here->RESdtemp) - 300.15; + factor = 1.0 + (here->REStc1)*difference + + (here->REStc2)*difference*difference; + + m = (here->RESm)/factor; if(here->RESacresGiven) { *(here->RESposPosptr) += m * here->RESacConduct; diff --git a/src/spicelib/devices/res/resparam.c b/src/spicelib/devices/res/resparam.c index ad9e74a91..1c19c6d17 100644 --- a/src/spicelib/devices/res/resparam.c +++ b/src/spicelib/devices/res/resparam.c @@ -26,10 +26,6 @@ RESparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) break; case RES_RESIST: here->RESresist = value->rValue; - if (!here->RESmGiven) - here->RESm = 1.0; - if (!here->RESacresGiven) - here->RESacResist = value->rValue; here->RESresGiven = TRUE; break; case RES_ACRESIST: @@ -55,6 +51,14 @@ RESparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) here->RESm = value->rValue; here->RESmGiven = TRUE; break; + case RES_TC1: + here->REStc1 = value->rValue; + here->REStc1Given = TRUE; + break; + case RES_TC2: + here->REStc2 = value->rValue; + here->REStc2Given = TRUE; + break; case RES_NOISY: here->RESnoisy = value->iValue; here->RESnoisyGiven = TRUE; diff --git a/src/spicelib/devices/res/restemp.c b/src/spicelib/devices/res/restemp.c index 36dbe2097..cbd59784c 100644 --- a/src/spicelib/devices/res/restemp.c +++ b/src/spicelib/devices/res/restemp.c @@ -9,7 +9,7 @@ Modified: 2000 AlanSfixes #include "cktdefs.h" #include "resdefs.h" #include "sperror.h" - +extern int fbreak; int REStemp(GENmodel *inModel, CKTcircuit *ckt) @@ -28,7 +28,10 @@ REStemp(GENmodel *inModel, CKTcircuit *ckt) /* loop through all the resistor models */ for( ; model != NULL; model = model->RESnextModel ) { - +#ifdef WIN32 + WaitForIdle(); + if(fbreak) break; +#endif /* Default Value Processing for Resistor Models */ if(!model->REStnomGiven) model->REStnom = ckt->CKTnomTemp; if(!model->RESsheetResGiven) model->RESsheetRes = 0.0; diff --git a/src/spicelib/parser/inp2r.c b/src/spicelib/parser/inp2r.c index fe9a686d0..9f5d23a2a 100644 --- a/src/spicelib/parser/inp2r.c +++ b/src/spicelib/parser/inp2r.c @@ -15,13 +15,16 @@ Remarks: This code is based on a version written by Serban Popescu which #include "fteext.h" #include "inp.h" +/* undefine to add tracing to this file */ +/*#define TRACE*/ + void INP2R(void *ckt, INPtables * tab, card * current) { /* parse a resistor card */ /* Rname [][][w=][l=][ac=] */ int mytype; /* the type we determine resistors are */ - int type = 0; /* the type the model says it is */ + int type = 0; /* the type the model says it is */ char *line; /* the part of the current line left to parse */ char *saveline; /* ... just in case we need to go back... */ char *name; /* the resistor's name */ @@ -41,25 +44,120 @@ void INP2R(void *ckt, INPtables * tab, card * current) double leadval; /* actual value of unlabeled number */ IFuid uid; /* uid for default model */ + char *s,*t;/* Temporary buffer and pointer for translation */ + int i; + +#ifdef TRACE + printf("In INP2R()\n"); + printf(" Current line: %s\n",current->line); +#endif + mytype = INPtypelook("Resistor"); if (mytype < 0) { LITERR("Device type Resistor not supported by this binary\n"); return; } line = current->line; - INPgetTok(&line, &name, 1); + INPgetTok(&line, &name, 1); /* Rname */ INPinsert(&name, tab); - INPgetNetTok(&line, &nname1, 1); + INPgetNetTok(&line, &nname1, 1); /* */ INPtermInsert(ckt, &nname1, tab, &node1); - INPgetNetTok(&line, &nname2, 1); + INPgetNetTok(&line, &nname2, 1); /* */ INPtermInsert(ckt, &nname2, tab, &node2); - val = INPevaluate(&line, &error1, 1); + val = INPevaluate(&line, &error1, 1); /* [] */ /* either not a number -> model, or * follows a number, so must be a model name * -> MUST be a model name (or null) */ - + saveline = line; /* save then old pointer */ + +#ifdef TRACE + printf("Begining tc=xxx yyyy search and translation in '%s'\n", line); +#endif /* TRACE */ + + /* This routine translates "tc=xxx yyy" to "tc=xxx tc2=yyy". + This is a re-write of the routine originally proposed by Hitoshi tanaka. + In my version we simply look for the first occurence of 'tc' followed + by '=' followed by two numbers. If we find it then we splice in "tc2=". + sjb - 2005-05-09 */ + for(s=line; *s; s++) { /* scan the remainder of the line */ + + /* reject anything other than "tc" */ + if(*s!='t') continue; + s++; + if(*s!='c') continue; + s++; + + /* skip any white space */ + while(isspace(*s)) s++; + + /* reject if not '=' */ + if(*s!='=') continue; + s++; + + /* skip any white space */ + while(isspace(*s)) s++; + + /* if we now have +, - or a decimal digit then assume we have a number, + otherwise reject */ + if((*s!='+') && (*s!='-') && !isdigit(*s)) continue; + s++; + + /* look for next white space or null */ + while(!isspace(*s) && *s) s++; + + /* reject whole line if null (i.e not white space) */ + if(*s==0) break; + s++; + + /* remember this location in the line. + Note that just before this location is a white space character. */ + t = s; + + /* skip any additional white space */ + while(isspace(*s)) s++; + + /* if we now have +, - or a decimal digit then assume we have the + second number, otherwise reject */ + if((*s!='+') && (*s!='-') && !isdigit(*s)) continue; + + /* if we get this far we have met all are criterea, + so now we splice in a "tc2=" at the location remembered above. */ + + /* first alocate memory for the new longer line */ + i = strlen(current->line); /* length of existing line */ + line = tmalloc(i + 4 + 1); /* alocate enough for "tc2=" & terminating NULL */ + if(line == NULL) { + /* failed to allocate memory so we recover rather crudely + by rejecting the translation */ + line = saveline; + break; + } + + /* copy first part of line */ + i -= strlen(t); + strncpy(line,current->line,i); + line[i]=0; /* terminate */ + + /* add "tc2=" */ + strcat(line, "tc2="); + + /* add rest of line */ + strcat(line, t); + + /* calculate our saveline position in the new line */ + saveline = line + (saveline - current->line); + + /* replace old line with new */ + tfree(current->line); + current->line = line; + line = saveline; + } + +#ifdef TRACE + printf("(Translated) Res line: %s\n",current->line); +#endif INPgetTok(&line, &model, 1); @@ -72,7 +170,7 @@ void INP2R(void *ckt, INPtables * tab, card * current) current->error = INPgetMod(ckt, model, &thismodel, tab); if (thismodel != NULL) { if (mytype != thismodel->INPmodType) { - LITERR("incorrect model type"); + LITERR("incorrect model type for resistor"); return; } mdfast = thismodel->INPmodfast; @@ -116,5 +214,6 @@ void INP2R(void *ckt, INPtables * tab, card * current) ptemp.rValue = leadval; GCA(INPpName, ("resistance", &ptemp, ckt, type, fast)); } + return; }