Added new syntax to the the resistor card to support HSpice style temperature dependence (from Hitoshi Tanaka <HDA01055@nifty.com>)

This commit is contained in:
sjborley 2005-05-09 20:20:18 +00:00
parent d96ec87987
commit 1facfd764d
12 changed files with 201 additions and 32 deletions

View File

@ -1,3 +1,14 @@
2005-05-09 Steven Borley <steven.borley@virgin.net>
* Added new syntax to the the resistor card to support HSpice style
temperature dependence (from Hitoshi Tanaka <HDA01055@nifty.com>).
Syntax forms now include:
Rxxx <n1> n2> <val> TC=<val1>
Rxxx <n1> n2> <val> TC1=<val1>
Rxxx <n1> n2> <val> TC1=<val1> TC2=<val2>
Rxxx <n1> n2> <val> TC=<val1> <val2>
The the first pair are equivalent, and the last pair are equivalent.
2005-05-07 Steven Borley <steven.borley@virgin.net>
* Added support for the BSD licensed editline library

View File

@ -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;

View File

@ -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) {

View File

@ -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.

View File

@ -13,7 +13,9 @@ enum simulation_types {
SV_INPUT_NOISE,
SV_POLE,
SV_ZERO,
SV_SPARAM
SV_SPARAM,
SV_TEMP,
SV_RES
};
#endif

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 <node> <node> [<val>][<mname>][w=<val>][l=<val>][ac=<val>] */
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); /* <node> */
INPtermInsert(ckt, &nname1, tab, &node1);
INPgetNetTok(&line, &nname2, 1);
INPgetNetTok(&line, &nname2, 1); /* <node> */
INPtermInsert(ckt, &nname2, tab, &node2);
val = INPevaluate(&line, &error1, 1);
val = INPevaluate(&line, &error1, 1); /* [<val>] */
/* 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;
}