Browse Source
S-parameters in ngspice
S-parameters in ngspice
With this commit the patch provided by Alessio Cacchiatori the S-parameter is completed: Noise simulation added with C matrix output Y and Z matrix output enabled To allow compiling with gcc, the dense.h inline functions have been put into denseinlines.hpre-master-46
committed by
Holger Vogt
25 changed files with 1368 additions and 449 deletions
-
5src/frontend/commands.c
-
2src/frontend/runcoms.c
-
7src/include/ngspice/cktdefs.h
-
20src/include/ngspice/noisedef.h
-
0src/include/ngspice/spardefs.h
-
3src/include/ngspice/tskdefs.h
-
119src/maths/dense/dense.c
-
291src/maths/dense/dense.h
-
144src/maths/dense/denseinlines.h
-
1src/maths/ni/niaciter.c
-
2src/spicelib/analysis/Makefile.am
-
2src/spicelib/analysis/cktdest.c
-
117src/spicelib/analysis/cktspdum.c
-
154src/spicelib/analysis/cktspnoise.c
-
180src/spicelib/analysis/nevalsrc.c
-
683src/spicelib/analysis/span.c
-
2src/spicelib/analysis/spaskq.c
-
2src/spicelib/analysis/spsetp.c
-
3src/spicelib/devices/cktinit.c
-
40src/spicelib/devices/vsrc/vsrcacld.c
-
5src/spicelib/devices/vsrc/vsrcext.h
-
4src/spicelib/devices/vsrc/vsrcload.c
-
21src/spicelib/devices/vsrc/vsrctemp.c
-
5src/spicelib/parser/inp2dot.c
-
5visualc/vngspice.vcxproj
@ -0,0 +1,144 @@ |
|||
|
|||
#include <math.h> |
|||
|
|||
inline void setcplx(cplx* d, double r, double i); |
|||
inline void cmultc(cplx* res, cplx a, cplx b); |
|||
inline cplx cmultco(cplx a, cplx b); |
|||
inline cplx cmultdo(cplx a, double d); |
|||
inline void cmultd(cplx* res, cplx a, double d); |
|||
inline void caddc(cplx* res, cplx a, cplx b); |
|||
inline cplx caddco(cplx a, cplx b); |
|||
inline void caddd(cplx* res, cplx a, double d); |
|||
inline void csubc(cplx* res, cplx a, cplx b); |
|||
inline cplx csubco(cplx a, cplx b); |
|||
inline void csubd(cplx* res, cplx a, double d); |
|||
inline double cmodinv(cplx a); |
|||
inline double cmodsqr(cplx a); |
|||
|
|||
inline int ciszero(cplx a); |
|||
inline cplx cinv(cplx a); |
|||
inline cplx conju(cplx a); |
|||
|
|||
inline double cmodu(cplx a); |
|||
inline cplx cdivco(cplx a, cplx b); |
|||
|
|||
inline void setcplx(cplx* d, double r, double i) |
|||
{ |
|||
d->re = r; d->im = i; |
|||
} |
|||
|
|||
inline void cmultc(cplx* res, cplx a, cplx b) |
|||
{ |
|||
res->re = a.re * b.re - a.im * b.im; |
|||
res->im = a.im * b.re + a.re * b.im; |
|||
} |
|||
|
|||
inline cplx cmultco(cplx a, cplx b) |
|||
{ |
|||
cplx res; |
|||
res.re = a.re * b.re - a.im * b.im; |
|||
res.im = a.im * b.re + a.re * b.im; |
|||
return res; |
|||
} |
|||
|
|||
|
|||
|
|||
inline cplx cdivco(cplx a, cplx b) |
|||
{ |
|||
cplx res; |
|||
double dmod = cmodinv(b); |
|||
|
|||
res.re = (a.re * b.re + a.im * b.im) * dmod; |
|||
res.im = (a.im * b.re - a.re * b.im) * dmod; |
|||
return res; |
|||
} |
|||
|
|||
|
|||
inline cplx cmultdo(cplx a, double d) |
|||
{ |
|||
cplx res; |
|||
res.re = a.re * d; |
|||
res.im = a.im * d; |
|||
return res; |
|||
} |
|||
inline void cmultd(cplx* res, cplx a, double d) |
|||
{ |
|||
res->re = a.re * d; |
|||
res->im = a.im * d; |
|||
} |
|||
|
|||
inline void caddc(cplx* res, cplx a, cplx b) |
|||
{ |
|||
res->re = a.re + b.re; |
|||
res->im = a.im + b.im; |
|||
} |
|||
|
|||
inline cplx caddco(cplx a, cplx b) |
|||
{ |
|||
cplx res; |
|||
res.re = a.re + b.re; |
|||
res.im = a.im + b.im; |
|||
return res; |
|||
} |
|||
|
|||
|
|||
inline void caddd(cplx* res, cplx a, double d) |
|||
{ |
|||
res->re = a.re + d; |
|||
} |
|||
|
|||
inline void csubc(cplx* res, cplx a, cplx b) |
|||
{ |
|||
res->re = a.re - b.re; |
|||
res->im = a.im - b.im; |
|||
} |
|||
|
|||
inline cplx csubco(cplx a, cplx b) |
|||
{ |
|||
cplx res; |
|||
res.re = a.re - b.re; |
|||
res.im = a.im - b.im; |
|||
return res; |
|||
} |
|||
|
|||
inline void csubd(cplx* res, cplx a, double d) |
|||
{ |
|||
res->re = a.re - d; |
|||
} |
|||
|
|||
inline double cmodinv(cplx a) |
|||
{ |
|||
return 1.0 / cmodsqr(a); |
|||
} |
|||
|
|||
inline double cmodsqr(cplx a) |
|||
{ |
|||
return (a.re * a.re + a.im * a.im); |
|||
} |
|||
|
|||
inline double cmodu(cplx a) |
|||
{ |
|||
return sqrt(cmodsqr(a)); |
|||
} |
|||
inline int ciszero(cplx a) |
|||
{ |
|||
return (a.re == 0) && (a.im == 0); |
|||
} |
|||
inline cplx cinv(cplx a) |
|||
{ |
|||
cplx res; |
|||
double cpmod = cmodinv(a); |
|||
res.re = a.re * cpmod; |
|||
res.im = -a.im * cpmod; |
|||
return res; |
|||
} |
|||
|
|||
inline cplx conju(cplx a) |
|||
{ |
|||
cplx res; |
|||
res.re = a.re; |
|||
res.im = -a.im; |
|||
return res; |
|||
} |
|||
|
|||
|
|||
@ -0,0 +1,154 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Gary W. Ng |
|||
**********/ |
|||
|
|||
/* |
|||
* CKTnoise (ckt, mode, operation, data) |
|||
* |
|||
* This routine is responsible for naming and evaluating all of the |
|||
* noise sources in the circuit. It uses a series of subroutines to |
|||
* name and evaluate the sources associated with each model, and then |
|||
* it evaluates the noise for the entire circuit. |
|||
*/ |
|||
|
|||
#include "ngspice/ngspice.h" |
|||
#include "ngspice/cktdefs.h" |
|||
#include "ngspice/devdefs.h" |
|||
#include "ngspice/iferrmsg.h" |
|||
#include "ngspice/noisedef.h" |
|||
#include "ngspice/sperror.h" |
|||
|
|||
#ifdef RFSPICE |
|||
|
|||
// Derived from CKTnoise |
|||
|
|||
|
|||
int |
|||
CKTSPnoise (CKTcircuit *ckt, int mode, int operation, Ndata *data) |
|||
{ |
|||
NOISEAN *job = (NOISEAN *) ckt->CKTcurJob; |
|||
|
|||
double outNdens; |
|||
int i; |
|||
IFvalue outData; /* output variable (points to list of outputs)*/ |
|||
IFvalue refVal; /* reference variable (always 0)*/ |
|||
int error; |
|||
|
|||
outNdens = 0.0; |
|||
|
|||
/* let each device decide how many and what type of noise sources it has */ |
|||
|
|||
for (i=0; i < DEVmaxnum; i++) { |
|||
if ( DEVices[i] && DEVices[i]->DEVnoise && ckt->CKThead[i] ) { |
|||
error = DEVices[i]->DEVnoise (mode, operation, ckt->CKThead[i], |
|||
ckt,data, &outNdens); |
|||
if (error) return (error); |
|||
} |
|||
} |
|||
|
|||
switch (operation) { |
|||
|
|||
case N_OPEN: |
|||
|
|||
/* take care of the noise for the circuit as a whole */ |
|||
|
|||
switch (mode) { |
|||
|
|||
case N_DENS: |
|||
|
|||
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); |
|||
|
|||
SPfrontEnd->IFnewUid (ckt, &(data->namelist[data->numPlots++]), |
|||
NULL, "onoise_spectrum", UID_OTHER, NULL); |
|||
|
|||
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); |
|||
|
|||
SPfrontEnd->IFnewUid (ckt, &(data->namelist[data->numPlots++]), |
|||
NULL, "inoise_spectrum", UID_OTHER, NULL); |
|||
|
|||
/* we've added two more plots */ |
|||
|
|||
data->outpVector = |
|||
TMALLOC(double, data->numPlots); |
|||
data->squared_value = |
|||
data->squared ? NULL : TMALLOC(char, data->numPlots); |
|||
break; |
|||
|
|||
case INT_NOIZ: |
|||
|
|||
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); |
|||
SPfrontEnd->IFnewUid (ckt, &(data->namelist[data->numPlots++]), |
|||
NULL, "onoise_total", UID_OTHER, NULL); |
|||
|
|||
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); |
|||
SPfrontEnd->IFnewUid (ckt, &(data->namelist[data->numPlots++]), |
|||
NULL, "inoise_total", UID_OTHER, NULL); |
|||
/* we've added two more plots */ |
|||
|
|||
data->outpVector = |
|||
TMALLOC(double, data->numPlots); |
|||
data->squared_value = |
|||
data->squared ? NULL : TMALLOC(char, data->numPlots); |
|||
break; |
|||
|
|||
default: |
|||
return (E_INTERN); |
|||
} |
|||
|
|||
break; |
|||
|
|||
case N_CALC: |
|||
|
|||
switch (mode) { |
|||
|
|||
case N_DENS: |
|||
if ((job->NStpsSm == 0) |
|||
|| data->prtSummary) |
|||
{ |
|||
data->outpVector[data->outNumber++] = outNdens; |
|||
data->outpVector[data->outNumber++] = |
|||
(outNdens * data->GainSqInv); |
|||
|
|||
refVal.rValue = data->freq; /* the reference is the freq */ |
|||
if (!data->squared) |
|||
for (i = 0; i < data->outNumber; i++) |
|||
if (data->squared_value[i]) |
|||
data->outpVector[i] = sqrt(data->outpVector[i]); |
|||
outData.v.numValue = data->outNumber; /* vector number */ |
|||
outData.v.vec.rVec = data->outpVector; /* vector of outputs */ |
|||
SPfrontEnd->OUTpData (data->NplotPtr, &refVal, &outData); |
|||
} |
|||
break; |
|||
|
|||
case INT_NOIZ: |
|||
data->outpVector[data->outNumber++] = data->outNoiz; |
|||
data->outpVector[data->outNumber++] = data->inNoise; |
|||
if (!data->squared) |
|||
for (i = 0; i < data->outNumber; i++) |
|||
if (data->squared_value[i]) |
|||
data->outpVector[i] = sqrt(data->outpVector[i]); |
|||
outData.v.vec.rVec = data->outpVector; /* vector of outputs */ |
|||
outData.v.numValue = data->outNumber; /* vector number */ |
|||
SPfrontEnd->OUTpData (data->NplotPtr, &refVal, &outData); |
|||
break; |
|||
|
|||
default: |
|||
return (E_INTERN); |
|||
} |
|||
break; |
|||
|
|||
case N_CLOSE: |
|||
SPfrontEnd->OUTendPlot (data->NplotPtr); |
|||
FREE(data->namelist); |
|||
FREE(data->outpVector); |
|||
FREE(data->squared_value); |
|||
break; |
|||
|
|||
default: |
|||
return (E_INTERN); |
|||
} |
|||
return (OK); |
|||
} |
|||
|
|||
#endif |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue