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