From 56232ed6c70cfed8056f7d00f2f2671dd4ae2743 Mon Sep 17 00:00:00 2001 From: pnenzi Date: Sat, 20 Sep 2003 20:20:16 +0000 Subject: [PATCH] New resistor code. --- src/spicelib/devices/res/res.c | 53 +++++---- src/spicelib/devices/res/resask.c | 24 +++- src/spicelib/devices/res/resdefs.h | 77 +++++++----- src/spicelib/devices/res/resext.h | 1 + src/spicelib/devices/res/resinit.c | 2 +- src/spicelib/devices/res/resload.c | 41 +++++-- src/spicelib/devices/res/resmask.c | 14 +++ src/spicelib/devices/res/resmpar.c | 9 ++ src/spicelib/devices/res/resnoise.c | 178 +++++++++++++++++++--------- src/spicelib/devices/res/resparam.c | 10 +- src/spicelib/devices/res/respzld.c | 12 +- src/spicelib/devices/res/ressacl.c | 11 +- src/spicelib/devices/res/ressetup.c | 14 +++ src/spicelib/devices/res/ressload.c | 7 +- src/spicelib/devices/res/ressprt.c | 3 + src/spicelib/devices/res/ressset.c | 3 + src/spicelib/devices/res/restemp.c | 44 +++++-- 17 files changed, 360 insertions(+), 143 deletions(-) diff --git a/src/spicelib/devices/res/res.c b/src/spicelib/devices/res/res.c index 649026687..d2d8ecf8a 100644 --- a/src/spicelib/devices/res/res.c +++ b/src/spicelib/devices/res/res.c @@ -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[] = { diff --git a/src/spicelib/devices/res/resask.c b/src/spicelib/devices/res/resask.c index 08893b90a..051733ed1 100644 --- a/src/spicelib/devices/res/resask.c +++ b/src/spicelib/devices/res/resask.c @@ -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: diff --git a/src/spicelib/devices/res/resdefs.h b/src/spicelib/devices/res/resdefs.h index b6b3ccfbe..735750e8f 100644 --- a/src/spicelib/devices/res/resdefs.h +++ b/src/spicelib/devices/res/resdefs.h @@ -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 diff --git a/src/spicelib/devices/res/resext.h b/src/spicelib/devices/res/resext.h index ee4be5516..dd0cca1dc 100644 --- a/src/spicelib/devices/res/resext.h +++ b/src/spicelib/devices/res/resext.h @@ -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*); diff --git a/src/spicelib/devices/res/resinit.c b/src/spicelib/devices/res/resinit.c index bdc1d52a7..d56406629 100644 --- a/src/spicelib/devices/res/resinit.c +++ b/src/spicelib/devices/res/resinit.c @@ -58,7 +58,7 @@ SPICEdev RESinfo = { DEVask : RESask, DEVmodAsk : RESmodAsk, DEVpzLoad : RESpzLoad, - DEVconvTest : NULL, + DEVconvTest : RESconvTest, /* XXXX experimental */ DEVsenSetup : RESsSetup, DEVsenLoad : RESsLoad, DEVsenUpdate : NULL, diff --git a/src/spicelib/devices/res/resload.c b/src/spicelib/devices/res/resload.c index 2e3a1c38a..d63311058 100644 --- a/src/spicelib/devices/res/resload.c +++ b/src/spicelib/devices/res/resload.c @@ -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; } } } diff --git a/src/spicelib/devices/res/resmask.c b/src/spicelib/devices/res/resmask.c index 0cf52279e..baf3d33d1 100644 --- a/src/spicelib/devices/res/resmask.c +++ b/src/spicelib/devices/res/resmask.c @@ -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); } diff --git a/src/spicelib/devices/res/resmpar.c b/src/spicelib/devices/res/resmpar.c index b461d9f2f..6887be8ef 100644 --- a/src/spicelib/devices/res/resmpar.c +++ b/src/spicelib/devices/res/resmpar.c @@ -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 */ diff --git a/src/spicelib/devices/res/resnoise.c b/src/spicelib/devices/res/resnoise.c index 450f1c000..3393ff761 100644 --- a/src/spicelib/devices/res/resnoise.c +++ b/src/spicelib/devices/res/resnoise.c @@ -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) */ diff --git a/src/spicelib/devices/res/resparam.c b/src/spicelib/devices/res/resparam.c index 73eaf02ec..c908959db 100644 --- a/src/spicelib/devices/res/resparam.c +++ b/src/spicelib/devices/res/resparam.c @@ -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); } diff --git a/src/spicelib/devices/res/respzld.c b/src/spicelib/devices/res/respzld.c index 52968f235..618479de7 100644 --- a/src/spicelib/devices/res/respzld.c +++ b/src/spicelib/devices/res/respzld.c @@ -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); diff --git a/src/spicelib/devices/res/ressacl.c b/src/spicelib/devices/res/ressacl.c index 28a13c67a..9c00116a6 100644 --- a/src/spicelib/devices/res/ressacl.c +++ b/src/spicelib/devices/res/ressacl.c @@ -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] + diff --git a/src/spicelib/devices/res/ressetup.c b/src/spicelib/devices/res/ressetup.c index 2fafd9afe..bef6c8628 100644 --- a/src/spicelib/devices/res/ressetup.c +++ b/src/spicelib/devices/res/ressetup.c @@ -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){\ diff --git a/src/spicelib/devices/res/ressload.c b/src/spicelib/devices/res/ressload.c index 756c32567..a4379a3e6 100644 --- a/src/spicelib/devices/res/ressload.c +++ b/src/spicelib/devices/res/ressload.c @@ -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] + diff --git a/src/spicelib/devices/res/ressprt.c b/src/spicelib/devices/res/ressprt.c index 1c7d5fb54..720de72a8 100644 --- a/src/spicelib/devices/res/ressprt.c +++ b/src/spicelib/devices/res/ressprt.c @@ -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); diff --git a/src/spicelib/devices/res/ressset.c b/src/spicelib/devices/res/ressset.c index d00ebc47d..ee22d2685 100644 --- a/src/spicelib/devices/res/ressset.c +++ b/src/spicelib/devices/res/ressset.c @@ -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){ diff --git a/src/spicelib/devices/res/restemp.c b/src/spicelib/devices/res/restemp.c index efe779569..88453a7ae 100644 --- a/src/spicelib/devices/res/restemp.c +++ b/src/spicelib/devices/res/restemp.c @@ -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);