diff --git a/src/spicelib/devices/res/res.c b/src/spicelib/devices/res/res.c index 3617d95cf..e3cf3e317 100644 --- a/src/spicelib/devices/res/res.c +++ b/src/spicelib/devices/res/res.c @@ -23,6 +23,7 @@ IFparm RESpTable[] = { /* parameters */ 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( "tce", RES_TCE, IF_REAL, "exponential temp. coefficient"), IOP( "bv_max", RES_BV_MAX, IF_REAL, "maximum voltage over resistor"), IOPU( "scale", RES_SCALE, IF_REAL, "Scale factor"), IOP( "noisy", RES_NOISY, IF_INTEGER, "Resistor generate noise"), @@ -51,6 +52,7 @@ IFparm RESmPTable[] = { /* model parameters */ IOPR( "tc1r", RES_MOD_TC1, IF_REAL,"First order temp. coefficient"), IOPQO( "tc2", RES_MOD_TC2, IF_REAL,"Second order temp. coefficient"), IOPR( "tc2r", RES_MOD_TC2, IF_REAL,"Second order temp. coefficient"), + IOPQ( "tce", RES_MOD_TCE, IF_REAL,"exponential temp. coefficient"), IOPX( "defw", RES_MOD_DEFWIDTH, IF_REAL,"Default device width"), IOPR( "w", RES_MOD_DEFWIDTH, IF_REAL,"Default device width"), IOPX( "l", RES_MOD_DEFLENGTH,IF_REAL,"Default device length"), diff --git a/src/spicelib/devices/res/resask.c b/src/spicelib/devices/res/resask.c index 5c00d9a28..6c60301fe 100644 --- a/src/spicelib/devices/res/resask.c +++ b/src/spicelib/devices/res/resask.c @@ -70,6 +70,9 @@ RESask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, case RES_TC2: value->rValue = fast->REStc2; return(OK); + case RES_TCE: + value->rValue = fast->REStce; + return(OK); case RES_BV_MAX: value->rValue = fast->RESbv_max; return(OK); diff --git a/src/spicelib/devices/res/resdefs.h b/src/spicelib/devices/res/resdefs.h index a8f0578a2..8b8f4d54a 100644 --- a/src/spicelib/devices/res/resdefs.h +++ b/src/spicelib/devices/res/resdefs.h @@ -42,6 +42,7 @@ typedef struct sRESinstance { double RESm; /* Multiplicity factor for this instance */ double REStc1; /* first temperature coefficient of resistors */ double REStc2; /* second temperature coefficient of resistors */ + double REStce; /* exponential temperature coefficient of resistors */ double RESbv_max; /* Maximum resistor voltage */ int RESnoisy; /* Set if the resistor generates noise */ double RESeffNoiseArea; /* effective resistor area for noise calculation */ @@ -64,6 +65,7 @@ typedef struct sRESinstance { unsigned RESmGiven : 1; /* indicates M parameter specified */ unsigned REStc1Given : 1; /* indicates tc1 parameter specified */ unsigned REStc2Given : 1; /* indicates tc2 parameter specified */ + unsigned REStceGiven : 1; /* indicates tce parameter specified */ unsigned RESnoisyGiven : 1; /* indicates if noisy is specified */ unsigned RESbv_maxGiven : 1; /* flags indicates maximum voltage is given */ int RESsenParmNo; /* parameter # for sensitivity use; @@ -102,6 +104,7 @@ typedef struct sRESmodel { /* model structure for a resistor */ double REStnom; /* temperature at which resistance measured */ double REStempCoeff1; /* first temperature coefficient of resistors */ double REStempCoeff2; /* second temperature coefficient of resistors */ + double REStempCoeffe; /* exponential temperature coefficient of resistors */ double RESsheetRes; /* sheet resistance of devices in ohms/square */ double RESdefWidth; /* default width of a resistor */ double RESdefLength; /* default length of a resistor */ @@ -117,6 +120,7 @@ typedef struct sRESmodel { /* model structure for a resistor */ 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 REStceGiven :1; /* flag to indicate tce was specified */ unsigned RESsheetResGiven :1; /* flag to indicate sheet resistance given*/ unsigned RESdefWidthGiven :1; /* flag to indicate default width given */ unsigned RESdefLengthGiven :1; /* flag to indicate default length given */ @@ -151,6 +155,7 @@ typedef struct sRESmodel { /* model structure for a resistor */ #define RES_TC1 16 #define RES_TC2 17 #define RES_BV_MAX 18 +#define RES_TCE 19 /* model parameters */ #define RES_MOD_TC1 101 @@ -168,6 +173,7 @@ typedef struct sRESmodel { /* model structure for a resistor */ #define RES_MOD_LF 113 #define RES_MOD_WF 114 #define RES_MOD_EF 115 +#define RES_MOD_TCE 116 /* device questions */ #define RES_QUEST_SENS_REAL 201 diff --git a/src/spicelib/devices/res/resmask.c b/src/spicelib/devices/res/resmask.c index 46c6ad262..0cd011fed 100644 --- a/src/spicelib/devices/res/resmask.c +++ b/src/spicelib/devices/res/resmask.c @@ -33,6 +33,9 @@ RESmodAsk(CKTcircuit *ckt, GENmodel *inModel, int which, IFvalue *value) case RES_MOD_TC2: value->rValue = model->REStempCoeff2; return(OK); + case RES_MOD_TCE: + value->rValue = model->REStempCoeffe; + return(OK); case RES_MOD_RSH: value->rValue = model->RESsheetRes; return(OK); diff --git a/src/spicelib/devices/res/resmpar.c b/src/spicelib/devices/res/resmpar.c index 478805149..8166b6bff 100644 --- a/src/spicelib/devices/res/resmpar.c +++ b/src/spicelib/devices/res/resmpar.c @@ -30,6 +30,10 @@ RESmParam(int param, IFvalue *value, GENmodel *inModel) model->REStempCoeff2 = value->rValue; model->REStc2Given = TRUE; break; + case RES_MOD_TCE: + model->REStempCoeffe = value->rValue; + model->REStceGiven = TRUE; + break; case RES_MOD_RSH: model->RESsheetRes = value->rValue; model->RESsheetResGiven = TRUE; diff --git a/src/spicelib/devices/res/resparam.c b/src/spicelib/devices/res/resparam.c index a5900ab33..5f55e347a 100644 --- a/src/spicelib/devices/res/resparam.c +++ b/src/spicelib/devices/res/resparam.c @@ -70,6 +70,10 @@ RESparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select) here->REStc2 = value->rValue; here->REStc2Given = TRUE; break; + case RES_TCE: + here->REStce = value->rValue; + here->REStceGiven = TRUE; + break; case RES_NOISY: here->RESnoisy = value->iValue; here->RESnoisyGiven = TRUE; diff --git a/src/spicelib/devices/res/ressetup.c b/src/spicelib/devices/res/ressetup.c index 25150a831..426fdcd83 100644 --- a/src/spicelib/devices/res/ressetup.c +++ b/src/spicelib/devices/res/ressetup.c @@ -32,6 +32,7 @@ RESsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit*ckt, int *state) if(!model->RESdefLengthGiven) model->RESdefLength = 10e-6; if(!model->REStc1Given) model->REStempCoeff1 = 0.0; if(!model->REStc2Given) model->REStempCoeff2 = 0.0; + if(!model->REStceGiven) model->REStempCoeffe = 0.0; if(!model->RESnarrowGiven) model->RESnarrow = 0.0; if(!model->RESshortGiven) model->RESshort = 0.0; if(!model->RESfNcoefGiven) model->RESfNcoef = 0.0; diff --git a/src/spicelib/devices/res/restemp.c b/src/spicelib/devices/res/restemp.c index 64afc6201..4d3651fb3 100644 --- a/src/spicelib/devices/res/restemp.c +++ b/src/spicelib/devices/res/restemp.c @@ -23,7 +23,7 @@ REStemp(GENmodel *inModel, CKTcircuit *ckt) RESinstance *here; double factor; double difference; - double tc1, tc2; + double tc1, tc2, tce; /* loop through all the resistor models */ @@ -61,8 +61,8 @@ REStemp(GENmodel *inModel, CKTcircuit *ckt) difference = (here->REStemp + here->RESdtemp) - model->REStnom; - /* instance parameters tc1 and tc2 will override - model parameters tc1 and tc2 */ + /* instance parameters tc1,tc2 and tce will override + model parameters tc1,tc2 and tce */ if (here->REStc1Given) tc1 = here->REStc1; /* instance */ else @@ -73,8 +73,13 @@ REStemp(GENmodel *inModel, CKTcircuit *ckt) else tc2 = model->REStempCoeff2; - factor = 1.0 + tc1*difference + - tc2*difference*difference; + if (here->REStceGiven) + tce = here->REStce; + else + tce = model->REStempCoeffe; + + factor = ((((tc2 * difference) + tc1) * difference) + 1.0) * + pow(1.01, tce * difference); here -> RESconduct = (1.0/(here->RESresist * factor * here->RESscale)); diff --git a/tests/regression/temper/Makefile.am b/tests/regression/temper/Makefile.am index bdcda61b4..fb32354a2 100644 --- a/tests/regression/temper/Makefile.am +++ b/tests/regression/temper/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in -TESTS = temper-1.cir temper-2.cir temper-3.cir +TESTS = temper-1.cir temper-2.cir temper-3.cir temper-res-1.cir TESTS_ENVIRONMENT = ngspice_vpath=$(srcdir) $(SHELL) $(top_srcdir)/tests/bin/check.sh $(top_builddir)/src/ngspice diff --git a/tests/regression/temper/temper-res-1.cir b/tests/regression/temper/temper-res-1.cir new file mode 100644 index 000000000..b80041ee2 --- /dev/null +++ b/tests/regression/temper/temper-res-1.cir @@ -0,0 +1,55 @@ +regression test temper-res-1.cir, TC1 TC2 and TCE + +* check res model TC1 TC2, and TCE parameter + +.model rtest r r=1000 tc1=2m tc2=30u tce=5m + +v1 1 0 dc 5v +r1 1 0 rtest + +v2 2 0 dc 5v +r2 2 0 1k tc1=2m tc2=30u tce=5m + +.control + +let success_count = 0 + +dc temp 10 100 10.0 + +let tc1 = 2m +let tc2 = 30u +let tce = 5m + +let val1 = -v(1)/i(v1) +let val2 = -v(2)/i(v2) + +let tdif = "temp-sweep" - 27.0 +let gold = 1000.0 * ((tc2 * tdif + tc1) * tdif + 1) * (1.01^(tce * tdif)) + +* plot val1 +* plot val1/gold - 1 +* plot val2 +* plot val2/gold - 1 + +let err1 = vecmax(abs(val1/gold - 1)) +let err2 = vecmax(abs(val2/gold - 1)) + +echo "Note: err1 =" $&err1 +echo "Note: err2 =" $&err2 + +if err1 > 1e-14 or err2 > 1e-14 + echo "ERROR: test failed" +else + echo "INFO: success" + let success_count = success_count + 1 +end + +if success_count ne 1 + quit 1 +else + quit 0 +end + +.endc + +.end diff --git a/tests/regression/temper/temper-res-1.out b/tests/regression/temper/temper-res-1.out new file mode 100644 index 000000000..8e9036969 --- /dev/null +++ b/tests/regression/temper/temper-res-1.out @@ -0,0 +1 @@ +INFO: success