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:
pnenzi 2007-10-09 08:44:49 +00:00
parent 6f3f195158
commit a52a87ddd8
11 changed files with 121 additions and 36 deletions

View File

@ -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,

View File

@ -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},

View File

@ -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,

View File

@ -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"),

View File

@ -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;

View File

@ -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[] = {

View File

@ -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;
}

View File

@ -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);

View File

@ -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 */

View File

@ -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;
}
}

View File

@ -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;