Added "r" option to vsrc, aliased some parameters on r and c, added safe floating point comparison (from Phil Barker)
This commit is contained in:
parent
6f3f195158
commit
a52a87ddd8
3
AUTHORS
3
AUTHORS
|
|
@ -11,7 +11,8 @@ The following people have contributed in some way:
|
||||||
Vera Albrecht <albrecht@danalyse.de>,
|
Vera Albrecht <albrecht@danalyse.de>,
|
||||||
Cecil Aswell <aswell@netcom.com>,
|
Cecil Aswell <aswell@netcom.com>,
|
||||||
Giles C. Billingsley,
|
Giles C. Billingsley,
|
||||||
Steven Borley <steven.borley@virgin.net>
|
Phil Barker <philb@intrinsity.com>,
|
||||||
|
Steven Borley <steven.borley@virgin.net>,
|
||||||
Stuart Brorson <sdb@cloud9.net>,
|
Stuart Brorson <sdb@cloud9.net>,
|
||||||
Mansun Chan,
|
Mansun Chan,
|
||||||
Wayne A. Christopher,
|
Wayne A. Christopher,
|
||||||
|
|
|
||||||
10
ChangeLog
10
ChangeLog
|
|
@ -9,6 +9,16 @@
|
||||||
* src/frontend/subckt.c: allow for .ic, .nodeset names to be embedded
|
* src/frontend/subckt.c: allow for .ic, .nodeset names to be embedded
|
||||||
in a subckt;enhanced subckt.c to created appropriate node names for
|
in a subckt;enhanced subckt.c to created appropriate node names for
|
||||||
flattened simulation netlist (Phil Barker).
|
flattened simulation netlist (Phil Barker).
|
||||||
|
* src/spicelib/devices/cap/cap.c: aliased capacitance parameter with "c"
|
||||||
|
and "cap" (patch from Phil Barker).
|
||||||
|
* src/spicelib/devices/res/res.c: aliased some parameters. Originally got
|
||||||
|
the patch from Phil Barker but used IOPR (redundant) instead of IOPZ.
|
||||||
|
* src/spicelib/devices/res/resparam.c: Added fix for zero valued
|
||||||
|
resistors (Phil Barker).
|
||||||
|
* src/spicelib/devices/vsrc/{vsrc.c, vsrcacct.c, vsrcask.c, vsrcdefs.h,
|
||||||
|
vsrcload.c, vsrcpar.c, vsrctemp.c}: Added "repeat" parameter to the
|
||||||
|
PWL model.
|
||||||
|
|
||||||
|
|
||||||
2007-10-08 Paolo Nenzi <p.nenzi@ieee.org>
|
2007-10-08 Paolo Nenzi <p.nenzi@ieee.org>
|
||||||
* src/main.c, src/frontend/{spiceif.c, spiceif.h, subckt.c},
|
* src/main.c, src/frontend/{spiceif.c, spiceif.h, subckt.c},
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ Modified: September 2003 - Paolo Nenzi
|
||||||
|
|
||||||
IFparm CAPpTable[] = { /* parameters */
|
IFparm CAPpTable[] = { /* parameters */
|
||||||
IOPAP("capacitance", CAP_CAP, IF_REAL, "Device capacitance"),
|
IOPAP("capacitance", CAP_CAP, IF_REAL, "Device capacitance"),
|
||||||
|
IOPAP("cap", CAP_CAP, IF_REAL, "Device capacitance"),
|
||||||
|
IOPAP("c", CAP_CAP, IF_REAL, "Device capacitance"),
|
||||||
IOPAU("ic", CAP_IC, IF_REAL, "Initial capacitor voltage"),
|
IOPAU("ic", CAP_IC, IF_REAL, "Initial capacitor voltage"),
|
||||||
IOPZU("temp", CAP_TEMP, IF_REAL, "Instance operating temperature"),
|
IOPZU("temp", CAP_TEMP, IF_REAL, "Instance operating temperature"),
|
||||||
IOPZ( "dtemp", CAP_DTEMP, IF_REAL,
|
IOPZ( "dtemp", CAP_DTEMP, IF_REAL,
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,13 @@ IFparm RESpTable[] = { /* parameters */
|
||||||
IFparm RESmPTable[] = { /* model parameters */
|
IFparm RESmPTable[] = { /* model parameters */
|
||||||
IOPQ( "rsh", RES_MOD_RSH, IF_REAL,"Sheet resistance"),
|
IOPQ( "rsh", RES_MOD_RSH, IF_REAL,"Sheet resistance"),
|
||||||
IOPZ( "narrow", RES_MOD_NARROW, IF_REAL,"Narrowing of resistor"),
|
IOPZ( "narrow", RES_MOD_NARROW, IF_REAL,"Narrowing of resistor"),
|
||||||
|
IOPZ( "dw", RES_MOD_NARROW, IF_REAL,"Narrowing of resistor"),
|
||||||
IOPZ( "short", RES_MOD_SHORT, IF_REAL,"Shortening of resistor"),
|
IOPZ( "short", RES_MOD_SHORT, IF_REAL,"Shortening of resistor"),
|
||||||
|
IOPZ( "dlr", RES_MOD_SHORT, IF_REAL,"Shortening of resistor"),
|
||||||
IOPQ( "tc1", RES_MOD_TC1, IF_REAL,"First order temp. coefficient"),
|
IOPQ( "tc1", RES_MOD_TC1, IF_REAL,"First order temp. coefficient"),
|
||||||
IOPQO( "tc2", RES_MOD_TC2, IF_REAL,"Second order temp. coefficient"),
|
IOPQO( "tc2", RES_MOD_TC2, IF_REAL,"Second order temp. coefficient"),
|
||||||
IOPX( "defw", RES_MOD_DEFWIDTH, IF_REAL,"Default device width"),
|
IOPX( "defw", RES_MOD_DEFWIDTH, IF_REAL,"Default device width"),
|
||||||
|
IOPX( "w", RES_MOD_DEFWIDTH, IF_REAL,"Default device width"),
|
||||||
IOPQ( "kf", RES_MOD_KF, IF_REAL,"Flicker noise coefficient"),
|
IOPQ( "kf", RES_MOD_KF, IF_REAL,"Flicker noise coefficient"),
|
||||||
IOPQ( "af", RES_MOD_AF, IF_REAL,"Flicker noise exponent"),
|
IOPQ( "af", RES_MOD_AF, IF_REAL,"Flicker noise exponent"),
|
||||||
IOPXU( "tnom", RES_MOD_TNOM, IF_REAL,"Parameter measurement temperature"),
|
IOPXU( "tnom", RES_MOD_TNOM, IF_REAL,"Parameter measurement temperature"),
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,29 @@ Author: 1985 Thomas L. Quarles
|
||||||
Modified: Apr 2000 - Paolo Nenzi
|
Modified: Apr 2000 - Paolo Nenzi
|
||||||
**********/
|
**********/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include "ngspice.h"
|
#include "ngspice.h"
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
#include "ifsim.h"
|
#include "ifsim.h"
|
||||||
#include "resdefs.h"
|
#include "resdefs.h"
|
||||||
#include "sperror.h"
|
#include "sperror.h"
|
||||||
|
|
||||||
|
// Initial AlmostEqualULPs version - fast and simple, but
|
||||||
|
// some limitations.
|
||||||
|
static bool AlmostEqualUlps(float A, float B, int maxUlps)
|
||||||
|
{
|
||||||
|
assert(sizeof(float) == sizeof(int));
|
||||||
|
|
||||||
|
if (A == B)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
int intDiff = abs(*(int*)&A - *(int*)&B);
|
||||||
|
|
||||||
|
if (intDiff <= maxUlps)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
RESparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
|
RESparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
|
||||||
|
|
@ -25,6 +42,10 @@ RESparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
|
||||||
here->RESdtempGiven = TRUE;
|
here->RESdtempGiven = TRUE;
|
||||||
break;
|
break;
|
||||||
case RES_RESIST:
|
case RES_RESIST:
|
||||||
|
/* 0 valued resistor causes ngspice to hang -- can't solve for initial voltage */
|
||||||
|
if ( AlmostEqualUlps( value->rValue, 0, 3 ) ) value->rValue = 0.001; /* 0.0001 should be sufficiently small */
|
||||||
|
/* it's the value that smartspice uses */
|
||||||
|
|
||||||
here->RESresist = value->rValue;
|
here->RESresist = value->rValue;
|
||||||
here->RESresGiven = TRUE;
|
here->RESresGiven = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,8 @@ IFparm VSRCpTable[] = { /* parameters */
|
||||||
OP ("i", VSRC_CURRENT, IF_REAL, "Voltage source current"),
|
OP ("i", VSRC_CURRENT, IF_REAL, "Voltage source current"),
|
||||||
OP ("p", VSRC_POWER, IF_REAL, "Instantaneous power"),
|
OP ("p", VSRC_POWER, IF_REAL, "Instantaneous power"),
|
||||||
IP ("distof1", VSRC_D_F1, IF_REALVEC,"f1 input for distortion"),
|
IP ("distof1", VSRC_D_F1, IF_REALVEC,"f1 input for distortion"),
|
||||||
IP ("distof2", VSRC_D_F2, IF_REALVEC,"f2 input for distortion")
|
IP ("distof2", VSRC_D_F2, IF_REALVEC,"f2 input for distortion"),
|
||||||
|
IP ("r", VSRC_R, IF_REAL, "pwl repeat value")
|
||||||
};
|
};
|
||||||
|
|
||||||
char *VSRCnames[] = {
|
char *VSRCnames[] = {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ Copyright 1990 Regents of the University of California. All rights reserved.
|
||||||
Author: 1985 Thomas L. Quarles
|
Author: 1985 Thomas L. Quarles
|
||||||
**********/
|
**********/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include "ngspice.h"
|
#include "ngspice.h"
|
||||||
#include "cktdefs.h"
|
#include "cktdefs.h"
|
||||||
#include "vsrcdefs.h"
|
#include "vsrcdefs.h"
|
||||||
|
|
@ -10,6 +11,27 @@ Author: 1985 Thomas L. Quarles
|
||||||
#include "sperror.h"
|
#include "sperror.h"
|
||||||
#include "suffix.h"
|
#include "suffix.h"
|
||||||
|
|
||||||
|
#define SAMETIME(a,b) (fabs((a)-(b))<= TIMETOL * PW)
|
||||||
|
#define TIMETOL 1e-7
|
||||||
|
|
||||||
|
// Initial AlmostEqualULPs version - fast and simple, but
|
||||||
|
// some limitations.
|
||||||
|
static bool AlmostEqualUlps(float A, float B, int maxUlps)
|
||||||
|
{
|
||||||
|
assert(sizeof(float) == sizeof(int));
|
||||||
|
|
||||||
|
if (A == B)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
int intDiff = abs(*(int*)&A - *(int*)&B);
|
||||||
|
|
||||||
|
if (intDiff <= maxUlps)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
||||||
/* set up the breakpoint table.
|
/* set up the breakpoint table.
|
||||||
|
|
@ -38,9 +60,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
||||||
|
|
||||||
case PULSE: {
|
case PULSE: {
|
||||||
|
|
||||||
#define SAMETIME(a,b) (fabs((a)-(b))<= TIMETOL * PW)
|
|
||||||
#define TIMETOL 1e-7
|
|
||||||
|
|
||||||
double TD, TR, TF, PW, PER;
|
double TD, TR, TF, PW, PER;
|
||||||
/* gtri - begin - wbk - add PHASE parameter */
|
/* gtri - begin - wbk - add PHASE parameter */
|
||||||
#ifdef XSPICE
|
#ifdef XSPICE
|
||||||
|
|
@ -170,14 +189,13 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(i=0;i<(here->VSRCfunctionOrder/2)-1;i++) {
|
for(i=0;i<(here->VSRCfunctionOrder/2)-1;i++) {
|
||||||
if((*(here->VSRCcoeffs+2*i)==ckt->CKTtime)) {
|
//if((*(here->VSRCcoeffs+2*i)==ckt->CKTtime)) {
|
||||||
if(ckt->CKTbreak) {
|
// if(ckt->CKTbreak) {
|
||||||
error = CKTsetBreak(ckt,
|
if ( ckt->CKTbreak && AlmostEqualUlps(*(here->VSRCcoeffs+2*i), ckt->CKTtime, 3 ) ) {
|
||||||
*(here->VSRCcoeffs+2*i+2));
|
error = CKTsetBreak(ckt, *(here->VSRCcoeffs+2*i+2));
|
||||||
if(error) return(error);
|
if(error) return(error);
|
||||||
}
|
goto bkptset;
|
||||||
goto bkptset;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,9 @@ VSRCask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue *
|
||||||
case VSRC_AC_IMAG:
|
case VSRC_AC_IMAG:
|
||||||
value->rValue = here->VSRCacImag;
|
value->rValue = here->VSRCacImag;
|
||||||
return (OK);
|
return (OK);
|
||||||
|
case VSRC_R:
|
||||||
|
value->rValue = here->VSRCr;
|
||||||
|
return (OK);
|
||||||
case VSRC_FCN_ORDER:
|
case VSRC_FCN_ORDER:
|
||||||
value->rValue = here->VSRCfunctionOrder;
|
value->rValue = here->VSRCfunctionOrder;
|
||||||
return (OK);
|
return (OK);
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ typedef struct sVSRCinstance {
|
||||||
|
|
||||||
int VSRCfunctionType; /* code number of function type for source */
|
int VSRCfunctionType; /* code number of function type for source */
|
||||||
int VSRCfunctionOrder; /* order of the function for the source */
|
int VSRCfunctionOrder; /* order of the function for the source */
|
||||||
|
int VSRCrBreakpt; /* pwl repeat breakpoint index */
|
||||||
double *VSRCcoeffs; /* pointer to array of coefficients */
|
double *VSRCcoeffs; /* pointer to array of coefficients */
|
||||||
|
|
||||||
double VSRCdcValue; /* DC and TRANSIENT value of source */
|
double VSRCdcValue; /* DC and TRANSIENT value of source */
|
||||||
|
|
@ -48,6 +49,7 @@ typedef struct sVSRCinstance {
|
||||||
double VSRCdF1phase; /* distortion f1 phase */
|
double VSRCdF1phase; /* distortion f1 phase */
|
||||||
double VSRCdF2phase; /* distortion f2 phase */
|
double VSRCdF2phase; /* distortion f2 phase */
|
||||||
|
|
||||||
|
double VSRCr; /* pwl repeat */
|
||||||
double *VSRCposIbrptr; /* pointer to sparse matrix element at
|
double *VSRCposIbrptr; /* pointer to sparse matrix element at
|
||||||
* (positive node, branch equation) */
|
* (positive node, branch equation) */
|
||||||
double *VSRCnegIbrptr; /* pointer to sparse matrix element at
|
double *VSRCnegIbrptr; /* pointer to sparse matrix element at
|
||||||
|
|
@ -64,9 +66,10 @@ typedef struct sVSRCinstance {
|
||||||
unsigned VSRCacPGiven :1 ; /* flag to indicate ac phase given */
|
unsigned VSRCacPGiven :1 ; /* flag to indicate ac phase given */
|
||||||
unsigned VSRCfuncTGiven :1 ; /* flag to indicate function type given */
|
unsigned VSRCfuncTGiven :1 ; /* flag to indicate function type given */
|
||||||
unsigned VSRCcoeffsGiven :1 ; /* flag to indicate function coeffs given */
|
unsigned VSRCcoeffsGiven :1 ; /* flag to indicate function coeffs given */
|
||||||
unsigned VSRCdGiven :1 ; /* flag to indicate source is a disto input */
|
unsigned VSRCdGiven :1 ; /* flag to indicate source is a disto input */
|
||||||
unsigned VSRCdF1given :1; /* flag to indicate source is an f1 dist input */
|
unsigned VSRCdF1given :1; /* flag to indicate source is an f1 dist input */
|
||||||
unsigned VSRCdF2given :1; /* flag to indicate source is an f2 dist input */
|
unsigned VSRCdF2given :1; /* flag to indicate source is an f2 dist input */
|
||||||
|
unsigned VSRCrGiven :1; /* flag to indicate repeating pwl */
|
||||||
} VSRCinstance ;
|
} VSRCinstance ;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -115,6 +118,7 @@ typedef struct sVSRCmodel {
|
||||||
#define VSRC_D_F2 21
|
#define VSRC_D_F2 21
|
||||||
|
|
||||||
#define VSRC_AM 22
|
#define VSRC_AM 22
|
||||||
|
#define VSRC_R 23
|
||||||
|
|
||||||
/* model parameters */
|
/* model parameters */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -286,32 +286,39 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PWL: {
|
case PWL: {
|
||||||
int i;
|
int i = 0, num_repeat = 0;
|
||||||
double foo;
|
double foo, repeat_time = 0, end_time, breakpt_time;
|
||||||
if(time < *(here->VSRCcoeffs)) {
|
if(time < *(here->VSRCcoeffs)) {
|
||||||
foo = *(here->VSRCcoeffs + 1) ;
|
foo = *(here->VSRCcoeffs + 1) ;
|
||||||
value = foo;
|
value = foo;
|
||||||
goto loadDone;
|
goto loadDone;
|
||||||
}
|
}
|
||||||
for(i=0;i<(here->VSRCfunctionOrder/2)-1;i++) {
|
|
||||||
if((*(here->VSRCcoeffs+2*i)==time)) {
|
do {
|
||||||
foo = *(here->VSRCcoeffs+2*i+1);
|
for( ; i<(here->VSRCfunctionOrder/2)-1; i++ ) {
|
||||||
value = foo;
|
|
||||||
goto loadDone;
|
if ( fabs( (*(here->VSRCcoeffs+2*i)+repeat_time) - time ) < 1e-20 ) {
|
||||||
} else if((*(here->VSRCcoeffs+2*i)<time) &&
|
foo = *(here->VSRCcoeffs+2*i+1);
|
||||||
(*(here->VSRCcoeffs+2*(i+1)) >time)) {
|
value = foo;
|
||||||
foo = *(here->VSRCcoeffs+2*i+1) +
|
goto loadDone;
|
||||||
(((time-*(here->VSRCcoeffs+2*i))/
|
} else if ( (*(here->VSRCcoeffs+2*i)+repeat_time < time) && (*(here->VSRCcoeffs+2*(i+1))+repeat_time > time) ) {
|
||||||
(*(here->VSRCcoeffs+2*(i+1)) -
|
foo = *(here->VSRCcoeffs+2*i+1) + (((time-(*(here->VSRCcoeffs+2*i)+repeat_time))/
|
||||||
*(here->VSRCcoeffs+2*i))) *
|
(*(here->VSRCcoeffs+2*(i+1)) - *(here->VSRCcoeffs+2*i))) *
|
||||||
(*(here->VSRCcoeffs+2*i+3) -
|
(*(here->VSRCcoeffs+2*i+3) - *(here->VSRCcoeffs+2*i+1)));
|
||||||
*(here->VSRCcoeffs+2*i+1)));
|
value = foo;
|
||||||
value = foo;
|
goto loadDone;
|
||||||
goto loadDone;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foo = *(here->VSRCcoeffs+ here->VSRCfunctionOrder-1) ;
|
foo = *(here->VSRCcoeffs+ here->VSRCfunctionOrder-1) ;
|
||||||
value = foo;
|
value = foo;
|
||||||
|
|
||||||
|
if ( !here->VSRCrGiven ) goto loadDone;
|
||||||
|
|
||||||
|
end_time = *(here->VSRCcoeffs + here->VSRCfunctionOrder-2);
|
||||||
|
breakpt_time = *(here->VSRCcoeffs + here->VSRCrBreakpt);
|
||||||
|
repeat_time = end_time + (end_time - breakpt_time)*num_repeat++ - breakpt_time;
|
||||||
|
i = here->VSRCrBreakpt - 1;
|
||||||
|
} while ( here->VSRCrGiven );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,21 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case VSRC_R:
|
||||||
|
here->VSRCr = value->rValue;
|
||||||
|
here->VSRCrGiven = TRUE;
|
||||||
|
|
||||||
|
for ( i = 0; i < here->VSRCfunctionOrder; i += 2 ) {
|
||||||
|
here->VSRCrBreakpt = i;
|
||||||
|
if ( here->VSRCr == *(here->VSRCcoeffs+i) ) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( here->VSRCr != *(here->VSRCcoeffs+here->VSRCrBreakpt) ) {
|
||||||
|
fprintf(stderr, "ERROR: repeat value %g for pwl voltage source does not match breakpoint!\n", here->VSRCr );
|
||||||
|
return ( E_PARMVAL );
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case VSRC_SFFM:
|
case VSRC_SFFM:
|
||||||
here->VSRCfunctionType = SFFM;
|
here->VSRCfunctionType = SFFM;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue