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>,
|
||||
Cecil Aswell <aswell@netcom.com>,
|
||||
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>,
|
||||
Mansun Chan,
|
||||
Wayne A. Christopher,
|
||||
|
|
|
|||
10
ChangeLog
10
ChangeLog
|
|
@ -9,6 +9,16 @@
|
|||
* src/frontend/subckt.c: allow for .ic, .nodeset names to be embedded
|
||||
in a subckt;enhanced subckt.c to created appropriate node names for
|
||||
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>
|
||||
* src/main.c, src/frontend/{spiceif.c, spiceif.h, subckt.c},
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ Modified: September 2003 - Paolo Nenzi
|
|||
|
||||
IFparm CAPpTable[] = { /* parameters */
|
||||
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"),
|
||||
IOPZU("temp", CAP_TEMP, IF_REAL, "Instance operating temperature"),
|
||||
IOPZ( "dtemp", CAP_DTEMP, IF_REAL,
|
||||
|
|
|
|||
|
|
@ -41,10 +41,13 @@ IFparm RESpTable[] = { /* parameters */
|
|||
IFparm RESmPTable[] = { /* model parameters */
|
||||
IOPQ( "rsh", RES_MOD_RSH, IF_REAL,"Sheet resistance"),
|
||||
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( "dlr", 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"),
|
||||
IOPX( "w", 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"),
|
||||
|
|
|
|||
|
|
@ -4,12 +4,29 @@ Author: 1985 Thomas L. Quarles
|
|||
Modified: Apr 2000 - Paolo Nenzi
|
||||
**********/
|
||||
|
||||
#include <assert.h>
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "resdefs.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
|
||||
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;
|
||||
break;
|
||||
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->RESresGiven = TRUE;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ IFparm VSRCpTable[] = { /* parameters */
|
|||
OP ("i", VSRC_CURRENT, IF_REAL, "Voltage source current"),
|
||||
OP ("p", VSRC_POWER, IF_REAL, "Instantaneous power"),
|
||||
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[] = {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ Copyright 1990 Regents of the University of California. All rights reserved.
|
|||
Author: 1985 Thomas L. Quarles
|
||||
**********/
|
||||
|
||||
#include <assert.h>
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "vsrcdefs.h"
|
||||
|
|
@ -10,6 +11,27 @@ Author: 1985 Thomas L. Quarles
|
|||
#include "sperror.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
|
||||
VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
||||
/* set up the breakpoint table.
|
||||
|
|
@ -38,9 +60,6 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
|
||||
case PULSE: {
|
||||
|
||||
#define SAMETIME(a,b) (fabs((a)-(b))<= TIMETOL * PW)
|
||||
#define TIMETOL 1e-7
|
||||
|
||||
double TD, TR, TF, PW, PER;
|
||||
/* gtri - begin - wbk - add PHASE parameter */
|
||||
#ifdef XSPICE
|
||||
|
|
@ -170,14 +189,13 @@ VSRCaccept(CKTcircuit *ckt, GENmodel *inModel)
|
|||
}
|
||||
}
|
||||
for(i=0;i<(here->VSRCfunctionOrder/2)-1;i++) {
|
||||
if((*(here->VSRCcoeffs+2*i)==ckt->CKTtime)) {
|
||||
if(ckt->CKTbreak) {
|
||||
error = CKTsetBreak(ckt,
|
||||
*(here->VSRCcoeffs+2*i+2));
|
||||
if(error) return(error);
|
||||
}
|
||||
goto bkptset;
|
||||
}
|
||||
//if((*(here->VSRCcoeffs+2*i)==ckt->CKTtime)) {
|
||||
// if(ckt->CKTbreak) {
|
||||
if ( ckt->CKTbreak && AlmostEqualUlps(*(here->VSRCcoeffs+2*i), ckt->CKTtime, 3 ) ) {
|
||||
error = CKTsetBreak(ckt, *(here->VSRCcoeffs+2*i+2));
|
||||
if(error) return(error);
|
||||
goto bkptset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,9 @@ VSRCask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue *
|
|||
case VSRC_AC_IMAG:
|
||||
value->rValue = here->VSRCacImag;
|
||||
return (OK);
|
||||
case VSRC_R:
|
||||
value->rValue = here->VSRCr;
|
||||
return (OK);
|
||||
case VSRC_FCN_ORDER:
|
||||
value->rValue = here->VSRCfunctionOrder;
|
||||
return (OK);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ typedef struct sVSRCinstance {
|
|||
|
||||
int VSRCfunctionType; /* code number of function type for source */
|
||||
int VSRCfunctionOrder; /* order of the function for the source */
|
||||
int VSRCrBreakpt; /* pwl repeat breakpoint index */
|
||||
double *VSRCcoeffs; /* pointer to array of coefficients */
|
||||
|
||||
double VSRCdcValue; /* DC and TRANSIENT value of source */
|
||||
|
|
@ -48,6 +49,7 @@ typedef struct sVSRCinstance {
|
|||
double VSRCdF1phase; /* distortion f1 phase */
|
||||
double VSRCdF2phase; /* distortion f2 phase */
|
||||
|
||||
double VSRCr; /* pwl repeat */
|
||||
double *VSRCposIbrptr; /* pointer to sparse matrix element at
|
||||
* (positive node, branch equation) */
|
||||
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 VSRCfuncTGiven :1 ; /* flag to indicate function type given */
|
||||
unsigned VSRCcoeffsGiven :1 ; /* flag to indicate function coeffs given */
|
||||
unsigned VSRCdGiven :1 ; /* flag to indicate source is a disto 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 VSRCdGiven :1 ; /* flag to indicate source is a disto 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 VSRCrGiven :1; /* flag to indicate repeating pwl */
|
||||
} VSRCinstance ;
|
||||
|
||||
|
||||
|
|
@ -115,6 +118,7 @@ typedef struct sVSRCmodel {
|
|||
#define VSRC_D_F2 21
|
||||
|
||||
#define VSRC_AM 22
|
||||
#define VSRC_R 23
|
||||
|
||||
/* model parameters */
|
||||
|
||||
|
|
|
|||
|
|
@ -286,32 +286,39 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
}
|
||||
break;
|
||||
case PWL: {
|
||||
int i;
|
||||
double foo;
|
||||
int i = 0, num_repeat = 0;
|
||||
double foo, repeat_time = 0, end_time, breakpt_time;
|
||||
if(time < *(here->VSRCcoeffs)) {
|
||||
foo = *(here->VSRCcoeffs + 1) ;
|
||||
value = foo;
|
||||
goto loadDone;
|
||||
}
|
||||
for(i=0;i<(here->VSRCfunctionOrder/2)-1;i++) {
|
||||
if((*(here->VSRCcoeffs+2*i)==time)) {
|
||||
foo = *(here->VSRCcoeffs+2*i+1);
|
||||
value = foo;
|
||||
goto loadDone;
|
||||
} else if((*(here->VSRCcoeffs+2*i)<time) &&
|
||||
(*(here->VSRCcoeffs+2*(i+1)) >time)) {
|
||||
foo = *(here->VSRCcoeffs+2*i+1) +
|
||||
(((time-*(here->VSRCcoeffs+2*i))/
|
||||
(*(here->VSRCcoeffs+2*(i+1)) -
|
||||
*(here->VSRCcoeffs+2*i))) *
|
||||
(*(here->VSRCcoeffs+2*i+3) -
|
||||
*(here->VSRCcoeffs+2*i+1)));
|
||||
value = foo;
|
||||
goto loadDone;
|
||||
|
||||
do {
|
||||
for( ; i<(here->VSRCfunctionOrder/2)-1; i++ ) {
|
||||
|
||||
if ( fabs( (*(here->VSRCcoeffs+2*i)+repeat_time) - time ) < 1e-20 ) {
|
||||
foo = *(here->VSRCcoeffs+2*i+1);
|
||||
value = foo;
|
||||
goto loadDone;
|
||||
} else if ( (*(here->VSRCcoeffs+2*i)+repeat_time < time) && (*(here->VSRCcoeffs+2*(i+1))+repeat_time > time) ) {
|
||||
foo = *(here->VSRCcoeffs+2*i+1) + (((time-(*(here->VSRCcoeffs+2*i)+repeat_time))/
|
||||
(*(here->VSRCcoeffs+2*(i+1)) - *(here->VSRCcoeffs+2*i))) *
|
||||
(*(here->VSRCcoeffs+2*i+3) - *(here->VSRCcoeffs+2*i+1)));
|
||||
value = foo;
|
||||
goto loadDone;
|
||||
}
|
||||
}
|
||||
foo = *(here->VSRCcoeffs+ here->VSRCfunctionOrder-1) ;
|
||||
value = foo;
|
||||
}
|
||||
foo = *(here->VSRCcoeffs+ here->VSRCfunctionOrder-1) ;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
case VSRC_SFFM:
|
||||
here->VSRCfunctionType = SFFM;
|
||||
|
|
|
|||
Loading…
Reference in New Issue