New resistor code.

This commit is contained in:
pnenzi 2003-09-20 20:20:16 +00:00
parent 5e124c6a60
commit 56232ed6c7
17 changed files with 360 additions and 143 deletions

View File

@ -11,36 +11,41 @@ Modified: 2000 AlansFixes
#include "ifsim.h"
IFparm RESpTable[] = { /* parameters */
IOPP( "resistance", RES_RESIST, IF_REAL,"Resistance"),
IOPAA( "ac", RES_ACRESIST, IF_REAL, "AC resistance value"),
IOPZU( "temp", RES_TEMP, IF_REAL,"Instance operating temperature"),
IOPQU( "l", RES_LENGTH, IF_REAL,"Length"),
IOPZU( "w", RES_WIDTH, IF_REAL,"Width"),
IOPU( "m", RES_M, IF_REAL, "Multiplication factor"),
IOPU( "scale", RES_SCALE, IF_REAL, "Scale factor"),
IP( "sens_resist", RES_RESIST_SENS, IF_FLAG,
IOPP( "resistance", RES_RESIST, IF_REAL, "Resistance"),
IOPAA( "ac", RES_ACRESIST, IF_REAL, "AC resistance value"),
IOPZU( "temp", RES_TEMP, IF_REAL, "Instance operating temperature"),
IOPZ( "dtemp", RES_DTEMP, IF_REAL,
"Instance temperature difference with the rest of the circuit"),
IOPQU( "l", RES_LENGTH, IF_REAL, "Length"),
IOPZU( "w", RES_WIDTH, IF_REAL, "Width"),
IOPU( "m", RES_M, IF_REAL, "Multiplication factor"),
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,
"flag to request sensitivity WRT resistance"),
OP( "i", RES_CURRENT,IF_REAL,"Current"),
OP( "p", RES_POWER, IF_REAL,"Power"),
OPU( "sens_dc", RES_QUEST_SENS_DC, IF_REAL, "dc sensitivity "),
OPU( "sens_real",RES_QUEST_SENS_REAL,IF_REAL,
OP( "i", RES_CURRENT, IF_REAL, "Current"),
OP( "p", RES_POWER, IF_REAL, "Power"),
OPU( "sens_dc", RES_QUEST_SENS_DC, IF_REAL, "dc sensitivity "),
OPU( "sens_real", RES_QUEST_SENS_REAL, IF_REAL,
"dc sensitivity and real part of ac sensitivity"),
OPU( "sens_imag",RES_QUEST_SENS_IMAG,IF_REAL,
OPU( "sens_imag", RES_QUEST_SENS_IMAG, IF_REAL,
"dc sensitivity and imag part of ac sensitivity"),
OPU( "sens_mag", RES_QUEST_SENS_MAG, IF_REAL, "ac sensitivity of magnitude"),
OPU( "sens_ph", RES_QUEST_SENS_PH, IF_REAL, "ac sensitivity of phase"),
OPU( "sens_cplx",RES_QUEST_SENS_CPLX,IF_COMPLEX, "ac sensitivity")
} ;
OPU( "sens_mag", RES_QUEST_SENS_MAG, IF_REAL, "ac sensitivity of magnitude"),
OPU( "sens_ph", RES_QUEST_SENS_PH, IF_REAL, "ac sensitivity of phase"),
OPU( "sens_cplx", RES_QUEST_SENS_CPLX, IF_COMPLEX, "ac sensitivity")
};
IFparm RESmPTable[] = { /* model parameters */
IOPQ( "rsh", RES_MOD_RSH, IF_REAL,"Sheet resistance"),
IOPZ( "narrow", RES_MOD_NARROW, IF_REAL,"Narrowing of resistor"),
IOPZ( "short", RES_MOD_SHORT, IF_REAL,"Shortening of resistor"),
IOPQ( "tc1", RES_MOD_TC1, IF_REAL,"First order temp. coefficient"),
IOPQ( "rsh", RES_MOD_RSH, IF_REAL,"Sheet resistance"),
IOPZ( "narrow", RES_MOD_NARROW, IF_REAL,"Narrowing of resistor"),
IOPZ( "short", RES_MOD_SHORT, IF_REAL,"Shortening of resistor"),
IOPQ( "tc1", RES_MOD_TC1, IF_REAL,"First order temp. coefficient"),
IOPQO( "tc2", RES_MOD_TC2, IF_REAL,"Second order temp. coefficient"),
IOPX( "defw", RES_MOD_DEFWIDTH, IF_REAL,"Default device width"),
IOPXU("tnom", RES_MOD_TNOM, IF_REAL,"Parameter measurement temperature"),
IP( "r", RES_MOD_R, IF_FLAG,"Device is a resistor model")
IOPX( "defw", RES_MOD_DEFWIDTH, IF_REAL,"Default device width"),
IOPQ( "kf", RES_MOD_KF, IF_REAL,"Flicker noise coefficient"),
IOPQ( "af", RES_MOD_AF, IF_REAL,"Flicker noise exponent"),
IOPXU( "tnom", RES_MOD_TNOM, IF_REAL,"Parameter measurement temperature"),
IP( "r", RES_MOD_R, IF_FLAG,"Device is a resistor model")
};
char *RESnames[] = {

View File

@ -12,9 +12,14 @@ Modified: Apr 2000 - Paolo Nenzi
#include "sperror.h"
/* TODO : there are "double" value compared with 0 (eg: vm == 0)
* Need to substitute this check with a suitable eps.
* PN 2003
*/
int
RESask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value,
IFvalue *select)
IFvalue *select)
{
RESinstance *fast = (RESinstance *)inst;
double vr;
@ -23,21 +28,29 @@ RESask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value,
double si;
double vm;
static char *msg = "Current and power not available for ac analysis";
switch(which) {
case RES_TEMP:
value->rValue = fast->REStemp-CONSTCtoK;
value->rValue = fast->REStemp - CONSTCtoK;
return(OK);
case RES_DTEMP:
value->rValue = fast->RESdtemp;
return(OK);
case RES_CONDUCT:
value->rValue = fast->RESconduct;
value->rValue *= fast->RESm;
return(OK);
case RES_RESIST:
value->rValue = fast->RESresist;
value->rValue /= fast->RESm;
return(OK);
case RES_ACCONDUCT:
value->rValue = fast->RESacConduct;
value->rValue *= fast->RESm;
return (OK);
case RES_ACRESIST:
value->rValue = fast->RESacResist;
value->rValue /= fast->RESm;
return(OK);
case RES_LENGTH:
value->rValue = fast->RESlength;
@ -51,6 +64,9 @@ RESask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value,
case RES_M:
value->rValue = fast->RESm;
return(OK);
case RES_NOISY:
value->iValue = fast->RESnoisy;
return(OK);
case RES_QUEST_SENS_DC:
if(ckt->CKTsenInfo){
value->rValue = *(ckt->CKTsenInfo->SEN_Sap[select->iValue + 1]+
@ -120,7 +136,8 @@ RESask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value,
} else {
value->rValue = (*(ckt->CKTrhsOld + fast->RESposNode) -
*(ckt->CKTrhsOld + fast->RESnegNode))
*fast->RESconduct;
*fast->RESconduct;
value->rValue *= fast->RESm;
}
return(OK);
case RES_POWER:
@ -135,6 +152,7 @@ RESask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value,
fast->RESconduct *
(*(ckt->CKTrhsOld + fast->RESposNode) -
*(ckt->CKTrhsOld + fast->RESnegNode));
value->rValue *= fast->RESm;
}
return(OK);
default:

View File

@ -19,48 +19,63 @@ Modified: 2000 AlansFixes
/* information used to describe a single instance */
typedef struct sRESinstance {
struct sRESmodel *RESmodPtr; /* backpointer to model */
struct sRESmodel *RESmodPtr; /* backpointer to model */
struct sRESinstance *RESnextInstance; /* pointer to next instance of
* current model*/
IFuid RESname; /* pointer to character string naming this instance */
int RESowner; /* number of owner process */
int RESstate; /* not used */
int RESposNode; /* number of positive node of resistor */
int RESnegNode; /* number of negative node of resistor */
IFuid RESname; /* pointer to character string naming this instance */
int RESowner; /* number of owner process */
int RESstate; /* not used but needed for sructure consistency */
int RESposNode; /* number of positive node of resistor */
int RESnegNode; /* number of negative node of resistor */
double REStemp; /* temperature at which this resistor operates */
double RESdtemp; /* delta-temperature of a particular instance */
double RESconduct; /* conductance at current analysis temperature */
double RESresist; /* resistance at temperature Tnom */
double REScurrent; /* The dc current in the resistor */
/* serban */
double RESacResist; /* AC resistance, useful for fancy .ac analyses */
double RESacConduct; /* AC conductance */
double RESwidth; /* width of the resistor */
double RESlength; /* length of the resistor */
double RESscale; /* Scale factor */
double RESm; /* Multiplicity factor for this instance */
double *RESposPosptr; /* pointer to sparse matrix diagonal at
* (positive,positive) */
double *RESnegNegptr; /* pointer to sparse matrix diagonal at
* (negative,negative) */
double *RESposNegptr; /* pointer to sparse matrix offdiagonal at
* (positive,negative) */
double *RESnegPosptr; /* pointer to sparse matrix offdiagonal at
* (negative,positive) */
double RESacResist; /* AC resistance, useful for fancy .ac analyses */
double RESacConduct; /* AC conductance */
double RESwidth; /* width of the resistor */
double RESlength; /* length of the resistor */
double RESscale; /* Scale factor */
double RESm; /* Multiplicity factor for this instance */
int RESnoisy; /* Set if the resistor generates noise */
double *RESposPosptr; /* pointer to sparse matrix diagonal at
* (positive,positive) */
double *RESnegNegptr; /* pointer to sparse matrix diagonal at
* (negative,negative) */
double *RESposNegptr; /* pointer to sparse matrix offdiagonal at
* (positive,negative) */
double *RESnegPosptr; /* pointer to sparse matrix offdiagonal at
* (negative,positive) */
unsigned RESresGiven : 1; /* flag to indicate resistance was specified */
unsigned RESwidthGiven : 1; /* flag to indicate width given */
unsigned RESlengthGiven : 1; /* flag to indicate length given */
unsigned RESscaleGiven : 1; /* flag to indicate scale given */
unsigned REStempGiven : 1; /* indicates temperature specified */
unsigned RESdtempGiven : 1; /* indicates delta-temp specified */
/* serban */
unsigned RESacresGiven : 1; /* indicates AC value specified */
unsigned RESmGiven : 1; /* indicates M parameter specified */
int RESsenParmNo; /* parameter # for sensitivity use;
set equal to 0 if not a design parameter*/
unsigned RESnoisyGiven : 1; /* indicates if noisy is specified */
int RESsenParmNo; /* parameter # for sensitivity use;
* set equal to 0 if not a design parameter*/
/* indices to array of RES noise sources */
#define RESTHNOIZ 0 /* Thermal noise source */
#define RESFLNOIZ 1 /* Flicker noise source */
#define RESTOTNOIZ 2 /* Total noise */
#define RESNSRCS 3 /* the number of RES noise sources */
#ifndef NONOISE
double RESnVar[NSTATVARS];
double RESnVar[NSTATVARS][RESNSRCS];
#else /* NONOISE */
double *RESnVar;
double **RESnVar;
#endif /* NONOISE */
} RESinstance ;
@ -83,13 +98,17 @@ typedef struct sRESmodel { /* model structure for a resistor */
double RESdefWidth; /* default width of a resistor */
double RESnarrow; /* amount by which device is narrower than drawn */
double RESshort; /* amount by which device is shorter than drawn */
unsigned REStnomGiven: 1; /* flag to indicate nominal temp. was given */
unsigned REStc1Given : 1; /* flag to indicate tc1 was specified */
unsigned REStc2Given : 1; /* flag to indicate tc2 was specified */
double RESfNcoef; /* Flicker noise coefficient */
double RESfNexp; /* Flicker noise exponent */
unsigned REStnomGiven :1; /* flag to indicate nominal temp. was given */
unsigned REStc1Given :1; /* flag to indicate tc1 was specified */
unsigned REStc2Given :1; /* flag to indicate tc2 was specified */
unsigned RESsheetResGiven :1; /* flag to indicate sheet resistance given*/
unsigned RESdefWidthGiven :1; /* flag to indicate default width given */
unsigned RESnarrowGiven :1; /* flag to indicate narrow effect given */
unsigned RESshortGiven :1; /* flag to indicate short effect given */
unsigned RESfNcoefGiven :1; /* flag to indicate kf given */
unsigned RESfNexpGiven :1; /* flag to indicate af given */
} RESmodel;
/* device parameters */
@ -106,6 +125,8 @@ typedef struct sRESmodel { /* model structure for a resistor */
#define RES_ACCONDUCT 11
#define RES_M 12 /* pn */
#define RES_SCALE 13 /* pn */
#define RES_DTEMP 14 /* pn */
#define RES_NOISY 15 /* pn */
/* model parameters */
@ -117,6 +138,8 @@ typedef struct sRESmodel { /* model structure for a resistor */
#define RES_MOD_R 106
#define RES_MOD_TNOM 107
#define RES_MOD_SHORT 108
#define RES_MOD_KF 109
#define RES_MOD_AF 110
/* device questions */
#define RES_QUEST_SENS_REAL 201

View File

@ -4,6 +4,7 @@ Author: 1985 Thomas L. Quarles
**********/
extern int RESask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*);
extern int RESconvTest(GENmodel*, CKTcircuit*);
extern int RESdelete(GENmodel*,IFuid,GENinstance**);
extern void RESdestroy(GENmodel**);
extern int RESload(GENmodel*,CKTcircuit*);

View File

@ -58,7 +58,7 @@ SPICEdev RESinfo = {
DEVask : RESask,
DEVmodAsk : RESmodAsk,
DEVpzLoad : RESpzLoad,
DEVconvTest : NULL,
DEVconvTest : RESconvTest, /* XXXX experimental */
DEVsenSetup : RESsSetup,
DEVsenLoad : RESsLoad,
DEVsenUpdate : NULL,

View File

@ -16,19 +16,29 @@ int
RESload(GENmodel *inModel, CKTcircuit *ckt)
{
RESmodel *model = (RESmodel *)inModel;
double m;
/* loop through all the resistor models */
for( ; model != NULL; model = model->RESnextModel ) {
RESinstance *here;
/* loop through all the instances of the model */
for (here = model->RESinstances; here != NULL ;
here = here->RESnextInstance) {
here = here->RESnextInstance) {
if (here->RESowner != ARCHme) continue;
*(here->RESposPosptr) += here->RESconduct;
*(here->RESnegNegptr) += here->RESconduct;
*(here->RESposNegptr) -= here->RESconduct;
*(here->RESnegPosptr) -= here->RESconduct;
here->REScurrent = (*(ckt->CKTrhsOld+here->RESposNode) -
*(ckt->CKTrhsOld+here->RESnegNode)) * here->RESconduct;
m = here->RESm;
*(here->RESposPosptr) += m * here->RESconduct;
*(here->RESnegNegptr) += m * here->RESconduct;
*(here->RESposNegptr) -= m * here->RESconduct;
*(here->RESnegPosptr) -= m * here->RESconduct;
}
}
return(OK);
@ -41,6 +51,7 @@ int
RESacload(GENmodel *inModel, CKTcircuit *ckt)
{
RESmodel *model = (RESmodel *)inModel;
double m;
/* loop through all the resistor models */
for( ; model != NULL; model = model->RESnextModel ) {
@ -50,16 +61,20 @@ RESacload(GENmodel *inModel, CKTcircuit *ckt)
for (here = model->RESinstances; here != NULL ;
here = here->RESnextInstance) {
if (here->RESowner != ARCHme) continue;
m = here->RESm;
if(here->RESacresGiven) {
*(here->RESposPosptr) += here->RESacConduct;
*(here->RESnegNegptr) += here->RESacConduct;
*(here->RESposNegptr) -= here->RESacConduct;
*(here->RESnegPosptr) -= here->RESacConduct;
*(here->RESposPosptr) += m * here->RESacConduct;
*(here->RESnegNegptr) += m * here->RESacConduct;
*(here->RESposNegptr) -= m * here->RESacConduct;
*(here->RESnegPosptr) -= m * here->RESacConduct;
} else {
*(here->RESposPosptr) += here->RESconduct;
*(here->RESnegNegptr) += here->RESconduct;
*(here->RESposNegptr) -= here->RESconduct;
*(here->RESnegPosptr) -= here->RESconduct;
*(here->RESposPosptr) += m * here->RESconduct;
*(here->RESnegNegptr) += m * here->RESconduct;
*(here->RESposNegptr) -= m * here->RESconduct;
*(here->RESnegPosptr) -= m * here->RESconduct;
}
}
}

View File

@ -18,7 +18,9 @@ Modified: 2000 AlansFixes
int
RESmodAsk(CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value)
{
RESmodel *model = (RESmodel *)inModel;
switch(which) {
case RES_MOD_TNOM:
value->rValue = model->REStnom-CONSTCtoK;
@ -41,6 +43,18 @@ RESmodAsk(CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value)
case RES_MOD_SHORT:
value->rValue = model->RESshort;
return(OK);
case RES_MOD_KF:
if (model->RESfNcoefGiven)
value->rValue = model->RESfNcoef;
else
value->rValue = 0.0;
return(OK);
case RES_MOD_AF:
if (model->RESfNexpGiven)
value->rValue = model->RESfNexp;
else
value->rValue = 0.0;
return(OK);
default:
return(E_BADPARM);
}

View File

@ -46,6 +46,15 @@ RESmParam(int param, IFvalue *value, GENmodel *inModel)
model->RESshort = value->rValue;
model->RESshortGiven = TRUE;
break;
case RES_MOD_KF:
model->RESfNcoef = value->rValue;
model->RESfNcoefGiven = TRUE;
break;
case RES_MOD_AF:
model->RESfNexp = value->rValue;
model->RESfNexpGiven = TRUE;
break;
case RES_MOD_R:
/* just being reassured by user that this is a resistor model */
/* no-op */

View File

@ -17,14 +17,20 @@ Modified: Apr 2000 - Paolo Nenzi
* and traverses all of its instances. It then proceeds to any other
* models on the linked list. The total output noise density
* generated by all the resistors is summed in the variable "OnDens".
*
* Paolo Nenzi 2003:
* Added flicker noise (Kf-Af) calculation to simulate
* carbon resistors.
*
* Added "noisy" switch to simulate noiseless resistors.
*/
extern void NevalSrc();
extern void NevalSrc2();
extern double Nintegrate();
int
RESnoise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt,
Ndata *data, double *OnDens)
Ndata *data, double *OnDens)
{
RESmodel *firstModel = (RESmodel *) genmodel;
RESmodel *model;
@ -32,61 +38,87 @@ RESnoise (int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt,
char name[N_MXVLNTH];
double tempOutNoise;
double tempInNoise;
double noizDens;
double lnNdens;
double noizDens[RESNSRCS];
double lnNdens[RESNSRCS];
int i;
/* define the names of the noise sources */
for (model=firstModel; model != NULL; model=model->RESnextModel) {
for (inst=model->RESinstances; inst != NULL; inst=inst->RESnextInstance) {
static char *RESnNames[RESNSRCS] = {
/* Note that we have to keep the order consistent with the
* strchr definitions in RESdefs.h */
"_thermal", /* Thermal noise */
"_1overf", /* flicker (1/f) noise */
"" /* total resistor noise */
};
for (model = firstModel; model != NULL; model = model->RESnextModel) {
for (inst = model->RESinstances; inst != NULL;
inst = inst->RESnextInstance) {
if (inst->RESowner != ARCHme) continue;
if(!inst->RESnoisy) continue; /* Quiet resistors are skipped */
switch (operation) {
case N_OPEN:
/* see if we have to to produce a summary report */
/* if so, name the noise generator */
/*
* See if we have to to produce a summary report
* if so, name the noise generator
*/
if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) {
switch (mode) {
case N_DENS:
(void)sprintf(name,"onoise_%s",inst->RESname);
for (i=0; i < RESNSRCS; i++) {
(void)sprintf(name,"onoise_%s%s",
inst->RESname, RESnNames[i]);
data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid));
if (!data->namelist) return(E_NOMEM);
(*(SPfrontEnd->IFnewUid))(ckt,
&(data->namelist[data->numPlots++]),
(IFuid)NULL,name,UID_OTHER,(void **)NULL);
data->namelist = (IFuid *)
trealloc((char *)data->namelist,
(data->numPlots + 1)*sizeof(IFuid));
if (!data->namelist) return(E_NOMEM);
(*(SPfrontEnd->IFnewUid))(ckt,
&(data->namelist[data->numPlots++]),
(IFuid)NULL,name,UID_OTHER,(void **)NULL);
/* we've added one more plot */
}
break;
case INT_NOIZ:
(void)sprintf(name,"onoise_total_%s",inst->RESname);
for (i=0; i < RESNSRCS; i++) {
(void)sprintf(name,"onoise_total_%s%s",
inst->RESname, RESnNames[i]);
data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid));
if (!data->namelist) return(E_NOMEM);
(*(SPfrontEnd->IFnewUid))(ckt,
&(data->namelist[data->numPlots++]),
(IFuid)NULL,name,UID_OTHER,(void **)NULL);
data->namelist = (IFuid *)
trealloc((char *)data->namelist,
(data->numPlots + 1)*sizeof(IFuid));
if (!data->namelist) return(E_NOMEM);
(*(SPfrontEnd->IFnewUid))(ckt,
&(data->namelist[data->numPlots++]),
(IFuid)NULL,name,UID_OTHER,(void **)NULL);
/* we've added one more plot */
(void)sprintf(name,"inoise_total_%s",inst->RESname);
(void)sprintf(name,"inoise_total_%s%s",
inst->RESname,RESnNames[i]);
data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid));
if (!data->namelist) return(E_NOMEM);
(*(SPfrontEnd->IFnewUid))(ckt,
&(data->namelist[data->numPlots++]),
(IFuid)NULL,name,UID_OTHER,(void **)NULL);
data->namelist = (IFuid *)
trealloc((char *)data->namelist,
(data->numPlots + 1)*sizeof(IFuid));
if (!data->namelist) return(E_NOMEM);
(*(SPfrontEnd->IFnewUid))(ckt,
&(data->namelist[data->numPlots++]),
(IFuid)NULL,name,UID_OTHER,(void **)NULL);
/* we've added one more plot */
}
break;
}
}
@ -96,46 +128,86 @@ if (!data->namelist) return(E_NOMEM);
switch (mode) {
case N_DENS:
NevalSrc(&noizDens,&lnNdens,ckt,THERMNOISE,
inst->RESposNode,inst->RESnegNode,inst->RESconduct);
NevalSrc2(&noizDens[RESTHNOIZ],&lnNdens[RESTHNOIZ],
ckt,THERMNOISE, inst->RESposNode,inst->RESnegNode,
inst->RESconduct * inst->RESm, inst->RESdtemp);
*OnDens += noizDens;
NevalSrc2(&noizDens[RESFLNOIZ],(double*)NULL, ckt,
N_GAIN,inst->RESposNode, inst->RESnegNode,
(double)0.0, (double)0.0);
#if 0
printf("DC current in resistor %s: %e\n",inst->RESname, inst->REScurrent);
#endif
noizDens[RESFLNOIZ] *= inst->RESm * model->RESfNcoef * exp(model->RESfNexp *
log(MAX(fabs(inst->REScurrent),
N_MINLOG))) / data->freq;
lnNdens[RESFLNOIZ] = log(MAX(noizDens[RESFLNOIZ],N_MINLOG));
noizDens[RESTOTNOIZ] = noizDens[RESTHNOIZ] + noizDens[RESFLNOIZ];
lnNdens[RESTOTNOIZ] = log(noizDens[RESTOTNOIZ]);
*OnDens += noizDens[RESTOTNOIZ];
if (data->delFreq == 0.0) {
/* if we haven't done any previous integration, we need to */
/* initialize our "history" variables */
inst->RESnVar[LNLSTDENS] = lnNdens;
for (i=0; i < RESNSRCS; i++) {
inst->RESnVar[LNLSTDENS][i] = lnNdens[i];
}
/* clear out our integration variable if it's the first pass */
if (data->freq == ((NOISEAN*)ckt->CKTcurJob)->NstartFreq) {
inst->RESnVar[OUTNOIZ] = 0.0;
inst->RESnVar[INNOIZ] = 0.0; /* Clear input noise */
for (i=0; i < RESNSRCS; i++) {
inst->RESnVar[OUTNOIZ][i] = 0.0; /* Clear output noise */
inst->RESnVar[INNOIZ][i] = 0.0; /* Clear input noise */
}
}
} else { /* data->delFreq != 0.0 (we have to integrate) */
tempOutNoise = Nintegrate(noizDens, lnNdens,
inst->RESnVar[LNLSTDENS], data);
tempInNoise = Nintegrate(noizDens *
data->GainSqInv ,lnNdens + data->lnGainInv,
inst->RESnVar[LNLSTDENS] + data->lnGainInv,
data);
inst->RESnVar[OUTNOIZ] += tempOutNoise;
inst->RESnVar[INNOIZ] += tempInNoise;
data->outNoiz += tempOutNoise;
data->inNoise += tempInNoise;
inst->RESnVar[LNLSTDENS] = lnNdens;
}
if (data->prtSummary) {
data->outpVector[data->outNumber++] = noizDens;
/* In order to get the best curve fit, we have to integrate each component separately */
for (i = 0; i < RESNSRCS; i++) {
if (i != RESTOTNOIZ) {
tempOutNoise = Nintegrate(noizDens[i], lnNdens[i],
inst->RESnVar[LNLSTDENS][i], data);
tempInNoise = Nintegrate(noizDens[i] *
data->GainSqInv ,lnNdens[i]
+ data->lnGainInv,
inst->RESnVar[LNLSTDENS][i]
+ data->lnGainInv,
data);
inst->RESnVar[LNLSTDENS][i] = lnNdens[i];
data->outNoiz += tempOutNoise;
data->inNoise += tempInNoise;
if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) {
inst->RESnVar[OUTNOIZ][i] += tempOutNoise;
inst->RESnVar[OUTNOIZ][RESTOTNOIZ] += tempOutNoise;
inst->RESnVar[INNOIZ][i] += tempInNoise;
inst->RESnVar[INNOIZ][RESTOTNOIZ] += tempInNoise;
}
}
}
}
if (data->prtSummary) {
for (i=0; i < RESNSRCS; i++) { /* print a summary report */
data->outpVector[data->outNumber++] = noizDens[i];
}
}
break;
case INT_NOIZ: /* already calculated, just output */
if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) {
data->outpVector[data->outNumber++] = inst->RESnVar[OUTNOIZ];
data->outpVector[data->outNumber++] = inst->RESnVar[INNOIZ];
for (i=0; i < RESNSRCS; i++) {
data->outpVector[data->outNumber++] = inst->RESnVar[OUTNOIZ][i];
data->outpVector[data->outNumber++] = inst->RESnVar[INNOIZ][i];
}
} /* if */
break;
} /* switch (mode) */

View File

@ -17,9 +17,13 @@ RESparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
RESinstance *here = (RESinstance *)inst;
switch(param) {
case RES_TEMP:
here->REStemp = value->rValue+CONSTCtoK;
here->REStemp = value->rValue + CONSTCtoK;
here->REStempGiven = TRUE;
break;
case RES_DTEMP:
here->RESdtemp = value->rValue;
here->RESdtempGiven = TRUE;
break;
case RES_RESIST:
here->RESresist = value->rValue;
here->RESresGiven = TRUE;
@ -47,6 +51,10 @@ RESparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
here->RESm = value->rValue;
here->RESmGiven = TRUE;
break;
case RES_NOISY:
here->RESnoisy = value->iValue;
here->RESnoisyGiven = TRUE;
break;
default:
return(E_BADPARM);
}

View File

@ -21,6 +21,7 @@ RESpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
{
RESmodel *model = (RESmodel *)inModel;
RESinstance *here;
double m;
/* loop through all the resistor models */
for( ; model != NULL; model = model->RESnextModel ) {
@ -28,12 +29,15 @@ RESpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s)
/* loop through all the instances of the model */
for (here = model->RESinstances; here != NULL ;
here=here->RESnextInstance) {
if (here->RESowner != ARCHme) continue;
*(here->RESposPosptr) += here->RESconduct;
*(here->RESnegNegptr) += here->RESconduct;
*(here->RESposNegptr) -= here->RESconduct;
*(here->RESnegPosptr) -= here->RESconduct;
m = here->RESm;
*(here->RESposPosptr) += m * here->RESconduct;
*(here->RESnegNegptr) += m * here->RESconduct;
*(here->RESposNegptr) -= m * here->RESconduct;
*(here->RESnegPosptr) -= m * here->RESconduct;
}
}
return(OK);

View File

@ -2,6 +2,8 @@
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
Modified: Apr 2000 - Paolo Nenzi
This function is obsolete (was used by an old sensitivity analysis)
**********/
#include "ngspice.h"
@ -14,7 +16,8 @@ int
RESsAcLoad(GENmodel *inModel, CKTcircuit *ckt)
/* actually load the current ac sensitivity info into the
* array previously provided
*/
*/
{
RESmodel *model = (RESmodel *)inModel;
RESinstance *here;
@ -36,8 +39,10 @@ RESsAcLoad(GENmodel *inModel, CKTcircuit *ckt)
*(ckt->CKTrhsOld+here->RESnegNode);
ivres = *(ckt->CKTirhsOld+here->RESposNode) -
*(ckt->CKTirhsOld+here->RESnegNode);
value = vres * here->RESconduct * here->RESconduct;
ivalue = ivres * here->RESconduct * here->RESconduct;
value = vres * here->RESacConduct * here->RESacConduct;
value = value * here->RESm * here->RESm;
ivalue = ivres * here->RESacConduct * here->RESacConduct;
ivalue = ivalue * here->RESm * here->RESm;
/* load the RHS matrix */
*(ckt->CKTsenInfo->SEN_RHS[here->RESposNode] +

View File

@ -19,6 +19,7 @@ RESsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit*ckt, int *state)
RESmodel *model = (RESmodel *)inModel;
RESinstance *here;
/* loop through all the resistor models */
for( ; model != NULL; model = model->RESnextModel ) {
@ -26,6 +27,19 @@ RESsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit*ckt, int *state)
for (here = model->RESinstances; here != NULL ;
here=here->RESnextInstance) {
/*
* Paolo Nenzi 2003
* The following lines are needed if I will move the defualting code
* from REStemp to RESsetup, as in other (more recent ?) spice devices
*
* if (here->RESowner != ARCHme)
* goto matrixpointers;
*
* matrixpointers:
*
* put here instance parameter defaulting.
*/
/* macro to make elements with built in test for out of memory */
#define TSTALLOC(ptr,first,second) \
if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\

View File

@ -2,6 +2,8 @@
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
Modified: Apr 2000 - Paolo Nenzi
This function is obsolete (was used by an old sensitivity analysis)
**********/
@ -14,7 +16,7 @@ Modified: Apr 2000 - Paolo Nenzi
int
RESsLoad(GENmodel *inModel, CKTcircuit *ckt)
/* actually load the current resistance sensitivity value into
* the array previously provided
* the array previously provided.
*/
{
RESmodel *model = (RESmodel *)inModel;
@ -28,11 +30,14 @@ RESsLoad(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;
if(here->RESsenParmNo){
vres = *(ckt->CKTrhsOld+here->RESposNode) -
*(ckt->CKTrhsOld+here->RESnegNode);
value = vres * here->RESconduct * here->RESconduct;
value = value * here->RESm * here->RESm;
/* load the RHS matrix */
*(ckt->CKTsenInfo->SEN_RHS[here->RESposNode] +

View File

@ -2,6 +2,8 @@
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
Modified: Apr 2002 - Paolo Nenzi
This function is obsolete (was used by an old sensitivity analysis)
**********/
/* Pretty print the sensitivity info for all
@ -29,6 +31,7 @@ RESsPrint(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;
printf(" Instance name:%s\n",here->RESname);

View File

@ -2,6 +2,8 @@
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
Modified: Apr 2000 - Paolo Nenzi
This function is obsolete (was used by an old sensitivity analysis)
**********/
#include "ngspice.h"
@ -26,6 +28,7 @@ RESsSetup(SENstruct *info, GENmodel *inModel)
/* loop through all the instances of the model */
for (here = model->RESinstances; here != NULL ;
here=here->RESnextInstance) {
if (here->RESowner != ARCHme) continue;
if(here->RESsenParmNo){

View File

@ -31,24 +31,37 @@ REStemp(GENmodel *inModel, CKTcircuit *ckt)
/* Default Value Processing for Resistor Models */
if(!model->REStnomGiven) model->REStnom = ckt->CKTnomTemp;
if(!model->RESsheetResGiven) model->RESsheetRes = 0;
if(!model->RESsheetResGiven) model->RESsheetRes = 0.0;
if(!model->RESdefWidthGiven) model->RESdefWidth = 10.e-6; /*M*/
if(!model->REStc1Given) model->REStempCoeff1 = 0;
if(!model->REStc2Given) model->REStempCoeff2 = 0;
if(!model->RESnarrowGiven) model->RESnarrow = 0;
if(!model->RESshortGiven) model->RESshort = 0;
if(!model->REStc1Given) model->REStempCoeff1 = 0.0;
if(!model->REStc2Given) model->REStempCoeff2 = 0.0;
if(!model->RESnarrowGiven) model->RESnarrow = 0.0;
if(!model->RESshortGiven) model->RESshort = 0.0;
if(!model->RESfNcoefGiven) model->RESfNcoef = 0.0;
if(!model->RESfNexpGiven) model->RESfNexp = 0.0;
/* loop through all the instances of the model */
for (here = model->RESinstances; here != NULL ;
here=here->RESnextInstance) {
if (here->RESowner != ARCHme) continue;
/* Default Value Processing for Resistor Instance */
if(!here->REStempGiven) here->REStemp = ckt->CKTtemp;
if(!here->RESwidthGiven) here->RESwidth = model->RESdefWidth;
if(!here->REStempGiven) {
here->REStemp = ckt->CKTtemp;
if(!here->RESdtempGiven) here->RESdtemp = 0.0;
} else { /* REStempGiven */
here->RESdtemp = 0.0;
if (here->RESdtempGiven)
printf("%s: You specified instance temperature, dtemp ignored\n", here->RESname);
}
if(!here->RESwidthGiven) here->RESwidth = model->RESdefWidth;
if(!here->RESlengthGiven) here->RESlength = 0.0;
if(!here->RESscaleGiven) here->RESscale = 1.0;
if(!here->RESmGiven) here->RESm = 1.0;
if(!here->RESnoisyGiven) here->RESnoisy = 1;
if(!here->RESresGiven) {
if(model->RESsheetResGiven && (model->RESsheetRes != 0) &&
(here->RESlength != 0)) {
@ -56,21 +69,26 @@ REStemp(GENmodel *inModel, CKTcircuit *ckt)
model->RESshort) / (here->RESwidth - model->RESnarrow);
} else {
(*(SPfrontEnd->IFerror))(ERR_WARNING,
"%s: resistance=0, set to 1000",&(here->RESname));
"%s: resistance = 0 ohm, set to 1000 ohm",&(here->RESname));
here->RESresist=1000;
}
}
difference = here->REStemp - model->REStnom;
factor = 1.0 + (model->REStempCoeff1)*difference +
difference = (here->REStemp + here->RESdtemp) - model->REStnom;
factor = 1.0 + (model->REStempCoeff1)*difference +
(model->REStempCoeff2)*difference*difference;
here -> RESconduct = here->RESm*(1.0/(here->RESresist * factor * here->RESscale));
here -> RESacConduct = here -> RESconduct; /* default value */
here -> RESconduct = (1.0/(here->RESresist * factor * here->RESscale));
/* Paolo Nenzi: AC value */
if(here->RESacresGiven)
here->RESacConduct = here->RESm*(1.0/(here->RESacResist * factor * here->RESscale));
here->RESacConduct = (1.0/(here->RESacResist * factor * here->RESscale));
else {
here -> RESacConduct = here -> RESconduct;
here -> RESacResist = here -> RESresist;
}
}
}
return(OK);