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.h
This commit is contained in:
parent
86132f445d
commit
abd5b5ea04
|
|
@ -307,12 +307,11 @@ struct comm spcp_coms[] = {
|
||||||
/* SP */
|
/* SP */
|
||||||
#endif
|
#endif
|
||||||
#ifdef RFSPICE
|
#ifdef RFSPICE
|
||||||
/* SP: S parameter Analysis */
|
/* S parameter Analysis */
|
||||||
{ "sp", com_sp, TRUE, TRUE,
|
{ "sp", com_sp, TRUE, TRUE,
|
||||||
{ 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS,
|
{ 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS,
|
||||||
NULL,
|
NULL,
|
||||||
"[.sp line args] : Do a S parameter analysis." },
|
"[.sp line args] : Do an S-parameter analysis." },
|
||||||
/* SP */
|
|
||||||
#endif
|
#endif
|
||||||
{ "ac", com_ac, TRUE, TRUE,
|
{ "ac", com_ac, TRUE, TRUE,
|
||||||
{ 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS,
|
{ 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS,
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ com_pss(wordlist *wl)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef RFSPICE
|
#ifdef RFSPICE
|
||||||
/* S parameter Analysis*/
|
/* S-parameter Analysis*/
|
||||||
void
|
void
|
||||||
com_sp(wordlist* wl)
|
com_sp(wordlist* wl)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,11 @@ struct CKTcircuit {
|
||||||
CMat* CKTSmat;
|
CMat* CKTSmat;
|
||||||
CMat* CKTYmat;
|
CMat* CKTYmat;
|
||||||
CMat* CKTZmat;
|
CMat* CKTZmat;
|
||||||
|
// Data for RF Noise Calculations
|
||||||
|
double* CKTportY;
|
||||||
|
CMat* CKTNoiseCYmat;
|
||||||
|
unsigned int CKTnoiseSourceCount;
|
||||||
|
CMat* CKTadjointRHS; // Matrix where Znj are stored. Znj = impedance from j-th noise source to n-th port
|
||||||
#endif
|
#endif
|
||||||
#ifdef WITH_PSS
|
#ifdef WITH_PSS
|
||||||
/* SP: Periodic Steady State Analysis - 100609 */
|
/* SP: Periodic Steady State Analysis - 100609 */
|
||||||
|
|
@ -455,7 +460,7 @@ extern int DCpss(CKTcircuit *, int);
|
||||||
extern int SPan(CKTcircuit*, int);
|
extern int SPan(CKTcircuit*, int);
|
||||||
extern int SPaskQuest(CKTcircuit*, JOB*, int, IFvalue*);
|
extern int SPaskQuest(CKTcircuit*, JOB*, int, IFvalue*);
|
||||||
extern int SPsetParm(CKTcircuit*, JOB*, int, IFvalue*);
|
extern int SPsetParm(CKTcircuit*, JOB*, int, IFvalue*);
|
||||||
extern int CKTspDump(CKTcircuit*, double, runDesc*);
|
extern int CKTspDump(CKTcircuit*, double, runDesc*, unsigned int);
|
||||||
extern int CKTspLoad(CKTcircuit*);
|
extern int CKTspLoad(CKTcircuit*);
|
||||||
extern unsigned int CKTmatrixIndex(CKTcircuit*, unsigned int, unsigned int);
|
extern unsigned int CKTmatrixIndex(CKTcircuit*, unsigned int, unsigned int);
|
||||||
extern int CKTspCalcPowerWave(CKTcircuit* ckt);
|
extern int CKTspCalcPowerWave(CKTcircuit* ckt);
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,25 @@ typedef struct {
|
||||||
|
|
||||||
|
|
||||||
/* misc constants */
|
/* misc constants */
|
||||||
|
#ifdef RFSPICE
|
||||||
|
|
||||||
|
#define NOISE_ADD_OUTVAR(ckt, data, fmt, aname, bname) \
|
||||||
|
if (ckt->CKTcurrentAnalysis & DOING_SP) { \
|
||||||
|
ckt->CKTnoiseSourceCount++; \
|
||||||
|
} \
|
||||||
|
else\
|
||||||
|
do { \
|
||||||
|
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); \
|
||||||
|
if (!data->namelist) \
|
||||||
|
return E_NOMEM; \
|
||||||
|
char *name = tprintf(fmt, aname, bname); \
|
||||||
|
if (!name) \
|
||||||
|
return E_NOMEM; \
|
||||||
|
SPfrontEnd->IFnewUid(ckt, &(data->namelist[data->numPlots++]), \
|
||||||
|
NULL, name, UID_OTHER, NULL); \
|
||||||
|
tfree(name); \
|
||||||
|
} while(0)
|
||||||
|
#else
|
||||||
#define NOISE_ADD_OUTVAR(ckt, data, fmt, aname, bname) \
|
#define NOISE_ADD_OUTVAR(ckt, data, fmt, aname, bname) \
|
||||||
do { \
|
do { \
|
||||||
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); \
|
data->namelist = TREALLOC(IFuid, data->namelist, data->numPlots + 1); \
|
||||||
|
|
@ -131,7 +149,7 @@ typedef struct {
|
||||||
NULL, name, UID_OTHER, NULL); \
|
NULL, name, UID_OTHER, NULL); \
|
||||||
tfree(name); \
|
tfree(name); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
void NevalSrc (double *noise, double *lnNoise, CKTcircuit *ckt, int type, int node1, int node2, double param);
|
void NevalSrc (double *noise, double *lnNoise, CKTcircuit *ckt, int type, int node1, int node2, double param);
|
||||||
void NevalSrc2 (double *, double *, CKTcircuit *, int, int, int, double, int, int, double, double);
|
void NevalSrc2 (double *, double *, CKTcircuit *, int, int, int, double, int, int, double, double);
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,9 @@ struct TSKtask {
|
||||||
#define DOING_TRCV 2
|
#define DOING_TRCV 2
|
||||||
#define DOING_AC 4
|
#define DOING_AC 4
|
||||||
#define DOING_TRAN 8
|
#define DOING_TRAN 8
|
||||||
|
#ifdef RFSPICE
|
||||||
|
#define DOING_SP 16
|
||||||
|
#endif
|
||||||
|
|
||||||
int TSKbypass;
|
int TSKbypass;
|
||||||
int TSKdcMaxIter; /* iteration limit for dc op. (itl1) */
|
int TSKdcMaxIter; /* iteration limit for dc op. (itl1) */
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
|
||||||
#include "dense.h"
|
#include "dense.h"
|
||||||
|
#include "denseinlines.h"
|
||||||
#include "ngspice/ngspice.h"
|
#include "ngspice/ngspice.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
@ -7,124 +8,6 @@
|
||||||
#include "ngspice/bool.h"
|
#include "ngspice/bool.h"
|
||||||
#include "ngspice/iferrmsg.h"
|
#include "ngspice/iferrmsg.h"
|
||||||
|
|
||||||
inline double cmod(cplx a);
|
|
||||||
|
|
||||||
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 = cmod(b);
|
|
||||||
dmod *= dmod;
|
|
||||||
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 / cmod(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline double cmod(cplx a)
|
|
||||||
{
|
|
||||||
return (a.re * a.re + a.im * a.im);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void showmat(Mat* A) {
|
void showmat(Mat* A) {
|
||||||
if (A->row > 0 && A->col > 0) {
|
if (A->row > 0 && A->col > 0) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef ngspice_DENSE_MATRIX_H
|
#ifndef ngspice_DENSE_MATRIX_H
|
||||||
#define ngspice_DENSE_MATRIX_H
|
#define ngspice_DENSE_MATRIX_H
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
typedef struct cplx
|
typedef struct cplx
|
||||||
{
|
{
|
||||||
|
|
@ -26,78 +27,222 @@ typedef struct MatList{
|
||||||
struct MatList* next;
|
struct MatList* next;
|
||||||
}MatList;
|
}MatList;
|
||||||
|
|
||||||
extern void showmat(Mat* A);
|
void showmat(Mat* A);
|
||||||
extern void showcmat(CMat* A);
|
void showcmat(CMat* A);
|
||||||
extern CMat* newcmat(int r, int c, double dr, double di);
|
CMat* newcmat(int r, int c, double dr, double di);
|
||||||
extern CMat* newcmatnoinit(int r, int c);
|
CMat* newcmatnoinit(int r, int c);
|
||||||
extern Mat* newmat(int r, int c, double d);
|
Mat* newmat(int r, int c, double d);
|
||||||
extern Mat* newmatnoinit(int r, int c);
|
Mat* newmatnoinit(int r, int c);
|
||||||
extern void freecmat(CMat* A);
|
void freecmat(CMat* A);
|
||||||
extern void freemat(Mat* A);
|
void freemat(Mat* A);
|
||||||
extern CMat* ceye(int n);
|
CMat* ceye(int n);
|
||||||
extern Mat* eye(int n);
|
Mat* eye(int n);
|
||||||
extern Mat* zeros(int r, int c);
|
Mat* zeros(int r, int c);
|
||||||
extern CMat* czeros(int r, int c);
|
CMat* czeros(int r, int c);
|
||||||
extern Mat* ones(int r, int c);
|
Mat* ones(int r, int c);
|
||||||
extern CMat* cones(int r, int c);
|
CMat* cones(int r, int c);
|
||||||
extern Mat* randm(int r, int c, double l, double u);
|
Mat* randm(int r, int c, double l, double u);
|
||||||
extern CMat* randcm(int r, int c, double l, double u);
|
CMat* randcm(int r, int c, double l, double u);
|
||||||
extern double get(Mat* M, int r, int c);
|
double get(Mat* M, int r, int c);
|
||||||
extern cplx getcplx(CMat* M, int r, int c);
|
cplx getcplx(CMat* M, int r, int c);
|
||||||
extern void set(Mat* M, int r, int c, double d);
|
void set(Mat* M, int r, int c, double d);
|
||||||
extern void setc(CMat* M, int r, int c, cplx d);
|
void setc(CMat* M, int r, int c, cplx d);
|
||||||
extern Mat* scalarmultiply(Mat* M, double c);
|
Mat* scalarmultiply(Mat* M, double c);
|
||||||
extern CMat* cscalarmultiply(CMat* M, double c);
|
CMat* cscalarmultiply(CMat* M, double c);
|
||||||
extern CMat* complexmultiply(CMat* M, cplx c);
|
CMat* complexmultiply(CMat* M, cplx c);
|
||||||
extern Mat* sum(Mat* A, Mat* B);
|
Mat* sum(Mat* A, Mat* B);
|
||||||
extern CMat* csum(CMat* A, CMat* B);
|
CMat* csum(CMat* A, CMat* B);
|
||||||
extern Mat* minus(Mat* A, Mat* B);
|
Mat* minus(Mat* A, Mat* B);
|
||||||
extern CMat* cminus(CMat* A, CMat* B);
|
CMat* cminus(CMat* A, CMat* B);
|
||||||
extern Mat* submat(Mat* A, int r1, int r2, int c1, int c2);
|
Mat* submat(Mat* A, int r1, int r2, int c1, int c2);
|
||||||
extern void submat2(Mat* A, Mat* B, int r1, int r2, int c1, int c2);
|
void submat2(Mat* A, Mat* B, int r1, int r2, int c1, int c2);
|
||||||
extern CMat* subcmat(CMat* A, int r1, int r2, int c1, int c2);
|
CMat* subcmat(CMat* A, int r1, int r2, int c1, int c2);
|
||||||
extern void subcmat2(CMat* A, CMat* B, int r1, int r2, int c1, int c2);
|
void subcmat2(CMat* A, CMat* B, int r1, int r2, int c1, int c2);
|
||||||
extern Mat* multiply(Mat* A, Mat* B);
|
Mat* multiply(Mat* A, Mat* B);
|
||||||
extern CMat* cmultiply(CMat* A, CMat* B);
|
CMat* cmultiply(CMat* A, CMat* B);
|
||||||
extern Mat* removerow(Mat* A, int r);
|
Mat* removerow(Mat* A, int r);
|
||||||
extern Mat* removecol(Mat* A, int c);
|
Mat* removecol(Mat* A, int c);
|
||||||
extern void removerow2(Mat* A, Mat* B, int r);
|
void removerow2(Mat* A, Mat* B, int r);
|
||||||
extern void removecol2(Mat* A, Mat* B, int c);
|
void removecol2(Mat* A, Mat* B, int c);
|
||||||
extern CMat* cremoverow(CMat* A, int r);
|
CMat* cremoverow(CMat* A, int r);
|
||||||
extern CMat* cremovecol(CMat* A, int c);
|
CMat* cremovecol(CMat* A, int c);
|
||||||
extern void cremoverow2(CMat* A, CMat* B, int r);
|
void cremoverow2(CMat* A, CMat* B, int r);
|
||||||
extern void cremovecol2(CMat* A, CMat* B, int c);
|
void cremovecol2(CMat* A, CMat* B, int c);
|
||||||
extern Mat* transpose(Mat* A);
|
Mat* transpose(Mat* A);
|
||||||
extern CMat* ctranspose(CMat* A);
|
CMat* ctranspose(CMat* A);
|
||||||
extern double trace(Mat* A);
|
double trace(Mat* A);
|
||||||
extern cplx ctrace(CMat* A);
|
cplx ctrace(CMat* A);
|
||||||
extern Mat* adjoint(Mat* A);
|
Mat* adjoint(Mat* A);
|
||||||
extern CMat* cadjoint(CMat* A);
|
CMat* cadjoint(CMat* A);
|
||||||
extern CMat* ctransposeconj(CMat* source);
|
CMat* ctransposeconj(CMat* source);
|
||||||
extern Mat* inverse(Mat* A);
|
Mat* inverse(Mat* A);
|
||||||
extern CMat* cinverse(CMat* A);
|
CMat* cinverse(CMat* A);
|
||||||
extern Mat* copyvalue(Mat* A);
|
Mat* copyvalue(Mat* A);
|
||||||
extern CMat* copycvalue(CMat* A);
|
CMat* copycvalue(CMat* A);
|
||||||
extern Mat* triinverse(Mat* A);
|
Mat* copyvalue(Mat* A);
|
||||||
extern CMat* ctriinverse(CMat* A);
|
CMat* copycvalue(CMat* A);
|
||||||
extern Mat* rowechelon(Mat* A);
|
Mat* triinverse(Mat* A);
|
||||||
extern CMat* crowechelon(CMat* A);
|
CMat* ctriinverse(CMat* A);
|
||||||
extern Mat* hconcat(Mat* A, Mat* B);
|
Mat* rowechelon(Mat* A);
|
||||||
extern CMat* chconcat(CMat* A, CMat* B);
|
CMat* crowechelon(CMat* A);
|
||||||
extern Mat* vconcat(Mat* A, Mat* B);
|
Mat* hconcat(Mat* A, Mat* B);
|
||||||
extern CMat* cvconcat(CMat* A, CMat* B);
|
CMat* chconcat(CMat* A, CMat* B);
|
||||||
extern double norm(Mat* A);
|
Mat* vconcat(Mat* A, Mat* B);
|
||||||
extern double cnorm(CMat* A);
|
CMat* cvconcat(CMat* A, CMat* B);
|
||||||
extern Mat* nullmat(Mat* A);
|
double norm(Mat* A);
|
||||||
extern MatList* lu(Mat* A);
|
double cnorm(CMat* A);
|
||||||
extern double innermultiply(Mat* a, Mat* b);
|
Mat* nullmat(Mat* A);
|
||||||
extern MatList* qr(Mat* A);
|
MatList* lu(Mat* A);
|
||||||
extern int complexmultiplydest(CMat* M, cplx c, CMat* dest);
|
double innermultiply(Mat* a, Mat* b);
|
||||||
extern void cinversedest(CMat* A, CMat* dest);
|
MatList* qr(Mat* A);
|
||||||
extern int copycvaluedest(CMat* A, CMat* dest);
|
int complexmultiplydest(CMat* M, cplx c, CMat* dest);
|
||||||
extern int cmultiplydest(CMat* A, CMat* B, CMat* dest);
|
void cinversedest(CMat* A, CMat* dest);
|
||||||
extern void init(Mat* A, double d);
|
int copycvaluedest(CMat* A, CMat* dest);
|
||||||
extern void cinit(CMat* A, double dr, double di);
|
int cmultiplydest(CMat* A, CMat* B, CMat* dest);
|
||||||
extern void resizemat(Mat* A, int r, int c);
|
void init(Mat* A, double d);
|
||||||
|
void cinit(CMat* A, double dr, double di);
|
||||||
|
void resizemat(Mat* A, int r, int c);
|
||||||
|
/*
|
||||||
|
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);
|
||||||
|
|
||||||
|
extern inline double cmodu(cplx a);
|
||||||
|
extern 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;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -95,7 +95,6 @@ int NIspSolve(CKTcircuit* ckt)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
NIacIter(CKTcircuit *ckt)
|
NIacIter(CKTcircuit *ckt)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ libckt_la_SOURCES = \
|
||||||
cktsetup.c \
|
cktsetup.c \
|
||||||
cktsgen.c \
|
cktsgen.c \
|
||||||
cktsopt.c \
|
cktsopt.c \
|
||||||
|
cktspnoise.c \
|
||||||
ckttemp.c \
|
ckttemp.c \
|
||||||
cktterr.c \
|
cktterr.c \
|
||||||
ckttroub.c \
|
ckttroub.c \
|
||||||
|
|
@ -83,6 +84,7 @@ libckt_la_SOURCES = \
|
||||||
nevalsrc.c \
|
nevalsrc.c \
|
||||||
ninteg.c \
|
ninteg.c \
|
||||||
noisean.c \
|
noisean.c \
|
||||||
|
noisesp.c \
|
||||||
nsetparm.c \
|
nsetparm.c \
|
||||||
optran.c \
|
optran.c \
|
||||||
com_optran.h \
|
com_optran.h \
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,8 @@ CKTdestroy(CKTcircuit *ckt)
|
||||||
freecmat(ckt->CKTSmat); ckt->CKTSmat = NULL;
|
freecmat(ckt->CKTSmat); ckt->CKTSmat = NULL;
|
||||||
freecmat(ckt->CKTYmat); ckt->CKTYmat = NULL;
|
freecmat(ckt->CKTYmat); ckt->CKTYmat = NULL;
|
||||||
freecmat(ckt->CKTZmat); ckt->CKTZmat = NULL;
|
freecmat(ckt->CKTZmat); ckt->CKTZmat = NULL;
|
||||||
|
freecmat(ckt->CKTNoiseCYmat); ckt->CKTNoiseCYmat = NULL;
|
||||||
|
freecmat(ckt->CKTadjointRHS); ckt->CKTadjointRHS = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FREE(ckt);
|
FREE(ckt);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,16 @@ Author: 1985 Thomas L. Quarles
|
||||||
#include "ngspice/ifsim.h"
|
#include "ngspice/ifsim.h"
|
||||||
#include "vsrc/vsrcdefs.h"
|
#include "vsrc/vsrcdefs.h"
|
||||||
|
|
||||||
#ifdef RFSPICE
|
extern CMat* eyem;
|
||||||
|
extern CMat* zref;
|
||||||
|
extern CMat* gn;
|
||||||
|
extern CMat* gninv;
|
||||||
|
|
||||||
|
extern double NF;
|
||||||
|
extern double Rn;
|
||||||
|
extern cplx Sopt;
|
||||||
|
extern double Fmin;
|
||||||
|
|
||||||
|
|
||||||
unsigned int CKTmatrixIndex(CKTcircuit* ckt, unsigned int source, unsigned int dest)
|
unsigned int CKTmatrixIndex(CKTcircuit* ckt, unsigned int source, unsigned int dest)
|
||||||
{
|
{
|
||||||
|
|
@ -28,6 +37,25 @@ int CKTspCalcSMatrix(CKTcircuit* ckt)
|
||||||
if (Ainv == NULL) return (E_NOMEM);
|
if (Ainv == NULL) return (E_NOMEM);
|
||||||
cmultiplydest(ckt->CKTBmat, Ainv, ckt->CKTSmat);
|
cmultiplydest(ckt->CKTBmat, Ainv, ckt->CKTSmat);
|
||||||
freecmat(Ainv);
|
freecmat(Ainv);
|
||||||
|
// Calculate Y matrix
|
||||||
|
CMat* temp = cmultiply(ckt->CKTSmat, zref);
|
||||||
|
CMat* temp2 = csum(temp, zref);
|
||||||
|
CMat* temp3 = cmultiply(temp2, gn);
|
||||||
|
|
||||||
|
CMat* temp4 = cminus(eyem, ckt->CKTSmat);
|
||||||
|
CMat* temp5 = cinverse(temp4);
|
||||||
|
|
||||||
|
cmultiplydest(temp5, temp3, temp);
|
||||||
|
cmultiplydest(gninv, temp, ckt->CKTZmat);
|
||||||
|
|
||||||
|
cinversedest(ckt->CKTZmat, ckt->CKTYmat);
|
||||||
|
|
||||||
|
freecmat(temp);
|
||||||
|
freecmat(temp2);
|
||||||
|
freecmat(temp3);
|
||||||
|
freecmat(temp4);
|
||||||
|
freecmat(temp5);
|
||||||
|
|
||||||
return (OK);
|
return (OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,8 +92,9 @@ int CKTspCalcPowerWave(CKTcircuit* ckt)
|
||||||
return (OK);
|
return (OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
CKTspDump(CKTcircuit *ckt, double freq, runDesc *plot)
|
CKTspDump(CKTcircuit *ckt, double freq, runDesc *plot, unsigned int doNoise)
|
||||||
{
|
{
|
||||||
double *rhsold;
|
double *rhsold;
|
||||||
double *irhsold;
|
double *irhsold;
|
||||||
|
|
@ -77,10 +106,20 @@ CKTspDump(CKTcircuit *ckt, double freq, runDesc *plot)
|
||||||
rhsold = ckt->CKTrhsOld;
|
rhsold = ckt->CKTrhsOld;
|
||||||
irhsold = ckt->CKTirhsOld;
|
irhsold = ckt->CKTirhsOld;
|
||||||
freqData.rValue = freq;
|
freqData.rValue = freq;
|
||||||
unsigned int extraSPdataCount = ckt->CKTportCount * ckt->CKTportCount;
|
unsigned int extraSPdataCount = 3* ckt->CKTportCount * ckt->CKTportCount;
|
||||||
valueData.v.numValue = ckt->CKTmaxEqNum - 1 + extraSPdataCount;
|
valueData.v.numValue = ckt->CKTmaxEqNum - 1 + extraSPdataCount;
|
||||||
|
|
||||||
data = TMALLOC(IFcomplex, ckt->CKTmaxEqNum - 1 + extraSPdataCount);
|
unsigned int datasize = ckt->CKTmaxEqNum - 1 + extraSPdataCount;
|
||||||
|
|
||||||
|
// Add Cy matrix, NF, Rn, SOpt, NFmin
|
||||||
|
if (doNoise)
|
||||||
|
{
|
||||||
|
datasize += ckt->CKTportCount * ckt->CKTportCount;
|
||||||
|
if (ckt->CKTportCount == 2) // account for NF, Sopt, NFmin, Rn
|
||||||
|
datasize += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = TMALLOC(IFcomplex, datasize);
|
||||||
valueData.v.vec.cVec = data;
|
valueData.v.vec.cVec = data;
|
||||||
for (i=0;i<ckt->CKTmaxEqNum-1;i++) {
|
for (i=0;i<ckt->CKTmaxEqNum-1;i++) {
|
||||||
data[i].real = rhsold[i+1];
|
data[i].real = rhsold[i+1];
|
||||||
|
|
@ -89,23 +128,89 @@ CKTspDump(CKTcircuit *ckt, double freq, runDesc *plot)
|
||||||
|
|
||||||
if (ckt->CKTrfPorts )
|
if (ckt->CKTrfPorts )
|
||||||
{
|
{
|
||||||
|
unsigned int nPlot = ckt->CKTmaxEqNum - 1 ;
|
||||||
// Cycle thru all ports
|
// Cycle thru all ports
|
||||||
for (unsigned int pdest = 0; pdest < ckt->CKTportCount; pdest++)
|
for (unsigned int pdest = 0; pdest < ckt->CKTportCount; pdest++)
|
||||||
{
|
{
|
||||||
for (unsigned int psource = 0; psource < ckt->CKTportCount; psource++)
|
for (unsigned int psource = 0; psource < ckt->CKTportCount; psource++)
|
||||||
{
|
{
|
||||||
unsigned int nPlot = ckt->CKTmaxEqNum - 1 + CKTmatrixIndex(ckt, pdest, psource);
|
|
||||||
cplx sij = ckt->CKTSmat->d[pdest][psource];
|
cplx sij = ckt->CKTSmat->d[pdest][psource];
|
||||||
data[nPlot].real = sij.re;
|
data[nPlot].real = sij.re;
|
||||||
data[nPlot].imag = sij.im;
|
data[nPlot].imag = sij.im;
|
||||||
|
nPlot++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Put Y data
|
||||||
|
for (unsigned int pdest = 0; pdest < ckt->CKTportCount; pdest++)
|
||||||
|
{
|
||||||
|
for (unsigned int psource = 0; psource < ckt->CKTportCount; psource++)
|
||||||
|
{
|
||||||
|
//unsigned int nPlot = ckt->CKTmaxEqNum - 1 + CKTmatrixIndex(ckt, pdest, psource);
|
||||||
|
cplx yij = ckt->CKTYmat->d[pdest][psource];
|
||||||
|
data[nPlot].real = yij.re;
|
||||||
|
data[nPlot].imag = yij.im;
|
||||||
|
nPlot++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put Z data
|
||||||
|
for (unsigned int pdest = 0; pdest < ckt->CKTportCount; pdest++)
|
||||||
|
{
|
||||||
|
for (unsigned int psource = 0; psource < ckt->CKTportCount; psource++)
|
||||||
|
{
|
||||||
|
//unsigned int nPlot = ckt->CKTmaxEqNum - 1 + CKTmatrixIndex(ckt, pdest, psource);
|
||||||
|
cplx zij = ckt->CKTZmat->d[pdest][psource];
|
||||||
|
data[nPlot].real = zij.re;
|
||||||
|
data[nPlot].imag = zij.im;
|
||||||
|
nPlot++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doNoise)
|
||||||
|
{
|
||||||
|
// Put Cy data
|
||||||
|
for (unsigned int pdest = 0; pdest < ckt->CKTportCount; pdest++)
|
||||||
|
{
|
||||||
|
for (unsigned int psource = 0; psource < ckt->CKTportCount; psource++)
|
||||||
|
{
|
||||||
|
//unsigned int nPlot = ckt->CKTmaxEqNum - 1 + CKTmatrixIndex(ckt, pdest, psource);
|
||||||
|
cplx CYij = ckt->CKTNoiseCYmat->d[pdest][psource];
|
||||||
|
data[nPlot].real = CYij.re;
|
||||||
|
data[nPlot].imag = CYij.im;
|
||||||
|
nPlot++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ckt->CKTportCount == 2)
|
||||||
|
{
|
||||||
|
// If we have two ports, put also NF, Sopt, NFmin, Rn
|
||||||
|
data[nPlot].real = NF;
|
||||||
|
data[nPlot].imag = 0.0;
|
||||||
|
nPlot++;
|
||||||
|
|
||||||
|
data[nPlot].real = Sopt.re;
|
||||||
|
data[nPlot].imag = Sopt.im;
|
||||||
|
nPlot++;
|
||||||
|
|
||||||
|
data[nPlot].real = Fmin;
|
||||||
|
data[nPlot].imag = 0.0;
|
||||||
|
nPlot++;
|
||||||
|
|
||||||
|
data[nPlot].real = Rn;
|
||||||
|
data[nPlot].imag = 0.0;
|
||||||
|
nPlot++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SPfrontEnd->OUTpData(plot, &freqData, &valueData);
|
SPfrontEnd->OUTpData(plot, &freqData, &valueData);
|
||||||
|
|
||||||
FREE(data);
|
FREE(data);
|
||||||
return(OK);
|
return(OK);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -15,15 +15,81 @@ Author: 1987 Gary W. Ng
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Modified by Alessio Cacciatori: S-Params noise is calculated as noise current
|
||||||
|
correlation matrix. Per each noise source, the noise voltage at RF ports is converted
|
||||||
|
as an input noise current source by using (already availalble) Y matrix.
|
||||||
|
Outside RFSPICE declaration, code is legacy NGSPICE code.
|
||||||
|
*/
|
||||||
|
|
||||||
#include "ngspice/ngspice.h"
|
#include "ngspice/ngspice.h"
|
||||||
#include "ngspice/cktdefs.h"
|
#include "ngspice/cktdefs.h"
|
||||||
#include "ngspice/const.h"
|
#include "ngspice/const.h"
|
||||||
#include "ngspice/noisedef.h"
|
#include "ngspice/noisedef.h"
|
||||||
|
|
||||||
|
#ifdef RFSPICE
|
||||||
|
#include "../maths/dense/denseinlines.h"
|
||||||
|
|
||||||
|
extern CMat* eyem;
|
||||||
|
extern CMat* zref;
|
||||||
|
extern CMat* gn;
|
||||||
|
extern CMat* gninv;
|
||||||
|
extern CMat* vNoise;
|
||||||
|
extern CMat* iNoise;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
NevalSrc (double *noise, double *lnNoise, CKTcircuit *ckt, int type, int node1, int node2, double param)
|
NevalSrc (double *noise, double *lnNoise, CKTcircuit *ckt, int type, int node1, int node2, double param)
|
||||||
{
|
{
|
||||||
|
#ifdef RFSPICE
|
||||||
|
if (ckt->CKTcurrentAnalysis & DOING_SP)
|
||||||
|
{
|
||||||
|
double inoise = 0.0;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
|
||||||
|
case SHOTNOISE:
|
||||||
|
inoise = 2 * CHARGE * fabs(param); /* param is the dc current in a semiconductor */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case THERMNOISE:
|
||||||
|
inoise = 4 * CONSTboltz * ckt->CKTtemp * param; /* param is the conductance of a resistor */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case N_GAIN:
|
||||||
|
inoise = 0.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
inoise = sqrt(inoise);
|
||||||
|
// Calculate input equivalent noise current source (we have port impedance attached)
|
||||||
|
for (unsigned int s = 0; s < ckt->CKTportCount; s++)
|
||||||
|
vNoise->d[0][s] = cmultdo(csubco(ckt->CKTadjointRHS->d[s][node1], ckt->CKTadjointRHS->d[s][node2]), inoise);
|
||||||
|
|
||||||
|
for (unsigned int d = 0; d < ckt->CKTportCount; d++)
|
||||||
|
{
|
||||||
|
cplx in;
|
||||||
|
double yport = 1.0 / zref->d[d][d].re;
|
||||||
|
|
||||||
|
in.re = vNoise->d[0][d].re * yport;
|
||||||
|
in.im = vNoise->d[0][d].im * yport;
|
||||||
|
|
||||||
|
for (unsigned int s = 0; s < ckt->CKTportCount; s++)
|
||||||
|
caddc(&in, in, cmultco(ckt->CKTYmat->d[d][s], vNoise->d[0][s]));
|
||||||
|
|
||||||
|
iNoise->d[0][d] = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (unsigned int d = 0; d < ckt->CKTportCount; d++)
|
||||||
|
for (unsigned int s = 0; s < ckt->CKTportCount; s++)
|
||||||
|
ckt->CKTNoiseCYmat->d[d][s] = caddco(ckt->CKTNoiseCYmat->d[d][s], cmultco(iNoise->d[0][d], conju(iNoise->d[0][s])));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
double realVal;
|
double realVal;
|
||||||
double imagVal;
|
double imagVal;
|
||||||
double gain;
|
double gain;
|
||||||
|
|
@ -87,6 +153,69 @@ double phi21) /* Phase of signal 2 relative to signal 1 */
|
||||||
double realOut, imagOut, param_gain;
|
double realOut, imagOut, param_gain;
|
||||||
double T0, T1, T2, T3;
|
double T0, T1, T2, T3;
|
||||||
|
|
||||||
|
#ifdef RFSPICE
|
||||||
|
if (ckt->CKTcurrentAnalysis & DOING_SP)
|
||||||
|
{
|
||||||
|
|
||||||
|
double knoise = 0.0;
|
||||||
|
|
||||||
|
T0 = sqrt(param1);
|
||||||
|
T1 = sqrt(param2);
|
||||||
|
cplx cfact;
|
||||||
|
cfact.re = cos(phi21);
|
||||||
|
cfact.im = sin(phi21);
|
||||||
|
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
|
||||||
|
case SHOTNOISE:
|
||||||
|
knoise = 2 * CHARGE; /* param is the dc current in a semiconductor */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case THERMNOISE:
|
||||||
|
knoise = 4 * CONSTboltz * ckt->CKTtemp; /* param is the conductance of a resistor */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case N_GAIN:
|
||||||
|
knoise = 0.0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
knoise = sqrt(knoise);
|
||||||
|
// Calculate input equivalent noise current source (we have port impedance attached)
|
||||||
|
for (unsigned int s = 0; s < ckt->CKTportCount; s++)
|
||||||
|
{
|
||||||
|
cplx vNoiseA = cmultdo(csubco(ckt->CKTadjointRHS->d[s][node1], ckt->CKTadjointRHS->d[s][node2]), knoise * sqrt(param1) );
|
||||||
|
cplx vNoiseB = cmultco(cmultdo(csubco(ckt->CKTadjointRHS->d[s][node3], ckt->CKTadjointRHS->d[s][node4]), knoise * sqrt(param1)), cfact);
|
||||||
|
|
||||||
|
vNoise->d[0][s] = caddco(vNoiseA, vNoiseB);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int d = 0; d < ckt->CKTportCount; d++)
|
||||||
|
{
|
||||||
|
double yport = 1.0 / zref->d[d][d].re;
|
||||||
|
|
||||||
|
cplx in;
|
||||||
|
in.re = vNoise->d[0][d].re * yport;
|
||||||
|
in.im = vNoise->d[0][d].im * yport;
|
||||||
|
|
||||||
|
for (unsigned int s = 0; s < ckt->CKTportCount; s++)
|
||||||
|
caddc(&in, in, cmultco(ckt->CKTYmat->d[d][s], vNoise->d[0][s]));
|
||||||
|
|
||||||
|
iNoise->d[0][d] = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (unsigned int d = 0; d < ckt->CKTportCount; d++)
|
||||||
|
for (unsigned int s = 0; s < ckt->CKTportCount; s++)
|
||||||
|
ckt->CKTNoiseCYmat->d[d][s] = caddco(ckt->CKTNoiseCYmat->d[d][s], cmultco(iNoise->d[0][d], conju(iNoise->d[0][s])));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
realVal1 = ckt->CKTrhs [node1] - ckt->CKTrhs [node2];
|
realVal1 = ckt->CKTrhs [node1] - ckt->CKTrhs [node2];
|
||||||
imagVal1 = ckt->CKTirhs [node1] - ckt->CKTirhs [node2];
|
imagVal1 = ckt->CKTirhs [node1] - ckt->CKTirhs [node2];
|
||||||
realVal2 = ckt->CKTrhs [node3] - ckt->CKTrhs [node4];
|
realVal2 = ckt->CKTrhs [node3] - ckt->CKTrhs [node4];
|
||||||
|
|
@ -130,10 +259,59 @@ void
|
||||||
NevalSrcInstanceTemp (double *noise, double *lnNoise, CKTcircuit *ckt, int type,
|
NevalSrcInstanceTemp (double *noise, double *lnNoise, CKTcircuit *ckt, int type,
|
||||||
int node1, int node2, double param, double param2)
|
int node1, int node2, double param, double param2)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef RFSPICE
|
||||||
|
if (ckt->CKTcurrentAnalysis & DOING_SP)
|
||||||
|
{
|
||||||
|
double inoise = 0.0;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
|
||||||
|
case SHOTNOISE:
|
||||||
|
inoise = 2 * CHARGE * fabs(param); /* param is the dc current in a semiconductor */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case THERMNOISE:
|
||||||
|
inoise = 4.0 *CONSTboltz* (ckt->CKTtemp + param2)* param; /* param is the conductance of a resistor */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case N_GAIN:
|
||||||
|
inoise = 0.0;
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inoise = sqrt(inoise);
|
||||||
|
// Calculate input equivalent noise current source (we have port impedance attached)
|
||||||
|
for (unsigned int s = 0; s < ckt->CKTportCount; s++)
|
||||||
|
vNoise->d[0][s] = cmultdo(csubco(ckt->CKTadjointRHS->d[s][node1], ckt->CKTadjointRHS->d[s][node2]),inoise);
|
||||||
|
|
||||||
|
for (unsigned int d = 0; d < ckt->CKTportCount; d++)
|
||||||
|
{
|
||||||
|
cplx in;
|
||||||
|
double yport = 1.0 / zref->d[d][d].re;
|
||||||
|
|
||||||
|
in.re = vNoise->d[0][d].re * yport;
|
||||||
|
in.im = vNoise->d[0][d].im * yport;
|
||||||
|
|
||||||
|
for (unsigned int s = 0; s < ckt->CKTportCount; s++)
|
||||||
|
caddc(&in, in, cmultco(ckt->CKTYmat->d[d][s], vNoise->d[0][s]));
|
||||||
|
|
||||||
|
iNoise->d[0][d] = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (unsigned int d = 0; d < ckt->CKTportCount; d++)
|
||||||
|
for (unsigned int s = 0; s < ckt->CKTportCount; s++)
|
||||||
|
ckt->CKTNoiseCYmat->d[d][s] = caddco(ckt->CKTNoiseCYmat->d[d][s], cmultco(iNoise->d[0][d], conju(iNoise->d[0][s])));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
double realVal;
|
double realVal;
|
||||||
double imagVal;
|
double imagVal;
|
||||||
double gain;
|
double gain;
|
||||||
|
|
||||||
realVal = ckt->CKTrhs [node1] - ckt->CKTrhs [node2];
|
realVal = ckt->CKTrhs [node1] - ckt->CKTrhs [node2];
|
||||||
imagVal = ckt->CKTirhs [node1] - ckt->CKTirhs [node2];
|
imagVal = ckt->CKTirhs [node1] - ckt->CKTirhs [node2];
|
||||||
gain = (realVal*realVal) + (imagVal*imagVal);
|
gain = (realVal*realVal) + (imagVal*imagVal);
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
#include "ngspice/ngspice.h"
|
#include "ngspice/ngspice.h"
|
||||||
#include "ngspice/cktdefs.h"
|
#include "ngspice/cktdefs.h"
|
||||||
#include "ngspice/spdefs.h"
|
#include "ngspice/spardefs.h"
|
||||||
#include "ngspice/devdefs.h"
|
#include "ngspice/devdefs.h"
|
||||||
#include "ngspice/sperror.h"
|
#include "ngspice/sperror.h"
|
||||||
|
|
||||||
|
|
@ -19,12 +19,16 @@
|
||||||
/* gtri - end - wbk */
|
/* gtri - end - wbk */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SQR(x) ((x) * (x))
|
||||||
|
|
||||||
|
|
||||||
#ifdef RFSPICE
|
#ifdef RFSPICE
|
||||||
|
#include "vsrc/vsrcdefs.h"
|
||||||
#include "vsrc/vsrcext.h"
|
#include "vsrc/vsrcext.h"
|
||||||
#include "../maths/dense/dense.h"
|
#include "../maths/dense/dense.h"
|
||||||
|
#include "../maths/dense/denseinlines.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define INIT_STATS() \
|
#define INIT_STATS() \
|
||||||
do { \
|
do { \
|
||||||
|
|
@ -45,7 +49,23 @@ do { \
|
||||||
ckt->CKTstat->STATacSyncTime += ckt->CKTstat->STATsyncTime - startkTime; \
|
ckt->CKTstat->STATacSyncTime += ckt->CKTstat->STATsyncTime - startkTime; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
/*----------------------------------
|
||||||
|
* Auxiliary data for S-Y-Z matrix
|
||||||
|
* conversion
|
||||||
|
*-----------------------------------
|
||||||
|
*/
|
||||||
|
CMat* eyem = NULL;
|
||||||
|
CMat* zref = NULL;
|
||||||
|
CMat* gn = NULL;
|
||||||
|
CMat* gninv = NULL;
|
||||||
|
CMat* vNoise = NULL;
|
||||||
|
CMat* iNoise = NULL;
|
||||||
|
// Aux data for Noise Calculation
|
||||||
|
double NF = 0;
|
||||||
|
double Rn = 0;
|
||||||
|
cplx Sopt;
|
||||||
|
double Fmin = 0;
|
||||||
|
double refPortY0;
|
||||||
|
|
||||||
int
|
int
|
||||||
CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data)
|
CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data)
|
||||||
|
|
@ -54,16 +74,21 @@ CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data)
|
||||||
|
|
||||||
double outNdens;
|
double outNdens;
|
||||||
int i;
|
int i;
|
||||||
|
#ifdef LEGACY
|
||||||
IFvalue outData; /* output variable (points to list of outputs)*/
|
IFvalue outData; /* output variable (points to list of outputs)*/
|
||||||
IFvalue refVal; /* reference variable (always 0)*/
|
IFvalue refVal; /* reference variable (always 0)*/
|
||||||
|
#endif
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
outNdens = 0.0;
|
outNdens = 0.0;
|
||||||
|
job->NStpsSm = 1;
|
||||||
|
|
||||||
/* let each device decide how many and what type of noise sources it has */
|
/* let each device decide how many and what type of noise sources it has */
|
||||||
|
|
||||||
for (i = 0; i < DEVmaxnum; i++) {
|
for (i = 0; i < DEVmaxnum; i++) {
|
||||||
if (DEVices[i] && DEVices[i]->DEVnoise && ckt->CKThead[i]) {
|
if (DEVices[i] && DEVices[i]->DEVnoise && ckt->CKThead[i]) {
|
||||||
|
int a = 0;
|
||||||
|
a++;
|
||||||
|
if (a == 0) a = 2;
|
||||||
error = DEVices[i]->DEVnoise(mode, operation, ckt->CKThead[i],
|
error = DEVices[i]->DEVnoise(mode, operation, ckt->CKThead[i],
|
||||||
ckt, data, &outNdens);
|
ckt, data, &outNdens);
|
||||||
if (error) return (error);
|
if (error) return (error);
|
||||||
|
|
@ -73,56 +98,51 @@ CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data)
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
|
|
||||||
case N_OPEN:
|
case N_OPEN:
|
||||||
|
// Init all matrices
|
||||||
/* take care of the noise for the circuit as a whole */
|
cinit(ckt->CKTNoiseCYmat, 0.0, 0.0);
|
||||||
|
cinit(ckt->CKTadjointRHS, 0.0, 0.0);
|
||||||
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;
|
break;
|
||||||
|
|
||||||
case N_CALC:
|
case N_CALC:
|
||||||
|
{
|
||||||
|
|
||||||
|
// We have the Cy noise matrix,
|
||||||
|
|
||||||
|
// Equations from Stephen Maas 'Noise'
|
||||||
|
double knorm = 4.0 * CONSTboltz * (ckt->CKTtemp);
|
||||||
|
CMat* tempCy = cscalarmultiply(ckt->CKTNoiseCYmat, 1.0/knorm); // cmultiply(, YConj);
|
||||||
|
|
||||||
|
|
||||||
|
if (ckt->CKTportCount == 2)
|
||||||
|
{
|
||||||
|
|
||||||
|
double Y21mod = cmodsqr(ckt->CKTYmat->d[1][0]);
|
||||||
|
Rn = (tempCy->d[1][1].re / Y21mod) ;
|
||||||
|
cplx Ycor = csubco(ckt->CKTYmat->d[0][0],
|
||||||
|
cmultco(
|
||||||
|
cdivco(tempCy->d[0][1], tempCy->d[1][1]),
|
||||||
|
tempCy->d[1][0]
|
||||||
|
));
|
||||||
|
double Y11_Ycor = cmodsqr(csubco(ckt->CKTYmat->d[0][0], Ycor));
|
||||||
|
|
||||||
|
double Gu = tempCy->d[0][0].re - Rn * Y11_Ycor;
|
||||||
|
|
||||||
|
cplx Ysopt; Ysopt.re = sqrt(SQR(Ycor.re) + Gu / Rn); Ysopt.im = -Ycor.im;
|
||||||
|
cplx Y0; Y0.re = refPortY0; Y0.im = 0.0;
|
||||||
|
Sopt = cdivco(csubco(Y0, Ysopt),
|
||||||
|
caddco(Y0, Ysopt));
|
||||||
|
Fmin = 1.0 + 2.0 * Rn * (Ycor.re + Ysopt.re);
|
||||||
|
double Ysoptmod = cmodu(csubco(Y0, Ysopt));
|
||||||
|
NF = Fmin + (Rn / Ysopt.re) * SQR(Ysoptmod);
|
||||||
|
Fmin = 10.0 * log10(Fmin);
|
||||||
|
NF = 10.0 * log10(NF);
|
||||||
|
}
|
||||||
|
|
||||||
|
freecmat(tempCy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LEGACY
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
|
||||||
case N_DENS:
|
case N_DENS:
|
||||||
|
|
@ -159,6 +179,7 @@ CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data)
|
||||||
default:
|
default:
|
||||||
return (E_INTERN);
|
return (E_INTERN);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case N_CLOSE:
|
case N_CLOSE:
|
||||||
|
|
@ -166,6 +187,10 @@ CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data)
|
||||||
FREE(data->namelist);
|
FREE(data->namelist);
|
||||||
FREE(data->outpVector);
|
FREE(data->outpVector);
|
||||||
FREE(data->squared_value);
|
FREE(data->squared_value);
|
||||||
|
freecmat(ckt->CKTNoiseCYmat);
|
||||||
|
freecmat(ckt->CKTadjointRHS);
|
||||||
|
ckt->CKTNoiseCYmat = NULL;
|
||||||
|
ckt->CKTadjointRHS = NULL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -175,8 +200,8 @@ CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
int
|
||||||
NInspIter(CKTcircuit * ckt, int posDrive, int negDrive)
|
NInspIter(CKTcircuit * ckt, VSRCinstance* port)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
@ -187,15 +212,130 @@ NInspIter(CKTcircuit * ckt, int posDrive, int negDrive)
|
||||||
ckt->CKTirhs[i] = 0.0;
|
ckt->CKTirhs[i] = 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ckt->CKTrhs[posDrive] = 1.0; /* apply unit current excitation */
|
ckt->CKTrhs[port->VSRCposNode] = 1.0; /* apply unit current excitation */
|
||||||
ckt->CKTrhs[negDrive] = -1.0;
|
ckt->CKTrhs[port->VSRCnegNode] = -1.0;
|
||||||
SMPcaSolve(ckt->CKTmatrix, ckt->CKTrhs, ckt->CKTirhs, ckt->CKTrhsSpare,
|
SMPcaSolve(ckt->CKTmatrix, ckt->CKTrhs, ckt->CKTirhs, ckt->CKTrhsSpare,
|
||||||
ckt->CKTirhsSpare);
|
ckt->CKTirhsSpare);
|
||||||
|
|
||||||
ckt->CKTrhs[0] = 0.0;
|
ckt->CKTrhs[0] = 0.0;
|
||||||
ckt->CKTirhs[0] = 0.0;
|
ckt->CKTirhs[0] = 0.0;
|
||||||
|
|
||||||
|
return (OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int initSPmatrix(CKTcircuit* ckt, int doNoise)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ckt->CKTAmat != NULL) freecmat(ckt->CKTAmat);
|
||||||
|
if (ckt->CKTBmat != NULL) freecmat(ckt->CKTBmat);
|
||||||
|
if (ckt->CKTSmat != NULL) freecmat(ckt->CKTSmat);
|
||||||
|
if (ckt->CKTYmat != NULL) freecmat(ckt->CKTYmat);
|
||||||
|
if (ckt->CKTZmat != NULL) freecmat(ckt->CKTZmat);
|
||||||
|
if (eyem != NULL) freecmat(eyem);
|
||||||
|
if (zref != NULL) freecmat(zref);
|
||||||
|
if (gn != NULL) freecmat(gn);
|
||||||
|
if (gninv != NULL) freecmat(gninv);
|
||||||
|
|
||||||
|
|
||||||
|
ckt->CKTAmat = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0);
|
||||||
|
if (ckt->CKTAmat == NULL)
|
||||||
|
return (E_NOMEM);
|
||||||
|
ckt->CKTBmat = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0);
|
||||||
|
if (ckt->CKTBmat == NULL)
|
||||||
|
return (3);
|
||||||
|
|
||||||
|
ckt->CKTSmat = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0);
|
||||||
|
if (ckt->CKTSmat == NULL)
|
||||||
|
return (E_NOMEM);
|
||||||
|
|
||||||
|
ckt->CKTYmat = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0);
|
||||||
|
if (ckt->CKTYmat == NULL)
|
||||||
|
return (E_NOMEM);
|
||||||
|
|
||||||
|
ckt->CKTZmat = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0);
|
||||||
|
if (ckt->CKTZmat == NULL)
|
||||||
|
return (E_NOMEM);
|
||||||
|
|
||||||
|
eyem = ceye(ckt->CKTportCount);
|
||||||
|
if (eyem == NULL)
|
||||||
|
return (E_NOMEM);
|
||||||
|
|
||||||
|
zref = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0);
|
||||||
|
if (zref == NULL)
|
||||||
|
return (E_NOMEM);
|
||||||
|
|
||||||
|
gn = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0);
|
||||||
|
if (gn == NULL)
|
||||||
|
return (E_NOMEM);
|
||||||
|
|
||||||
|
gninv = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0);
|
||||||
|
if (gninv == NULL)
|
||||||
|
return (E_NOMEM);
|
||||||
|
|
||||||
|
// Now that we have found the model, we may init the Zref and Gn ports
|
||||||
|
if (ckt->CKTVSRCid>=0)
|
||||||
|
VSRCspinit(ckt->CKThead[ckt->CKTVSRCid], ckt, zref, gn, gninv);
|
||||||
|
|
||||||
|
if (doNoise)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Allocate matrices and vector
|
||||||
|
if (ckt->CKTNoiseCYmat != NULL) freecmat(ckt->CKTNoiseCYmat);
|
||||||
|
ckt->CKTNoiseCYmat = newcmatnoinit(ckt->CKTportCount, ckt->CKTportCount);
|
||||||
|
if (ckt->CKTNoiseCYmat == NULL) return (E_NOMEM);
|
||||||
|
|
||||||
|
// Use CKTadjointRHS as a convenience storage for all solutions (each solution per each
|
||||||
|
// port excitation)
|
||||||
|
if (ckt->CKTadjointRHS != NULL) freecmat(ckt->CKTadjointRHS);
|
||||||
|
ckt->CKTadjointRHS = newcmatnoinit(ckt->CKTportCount, ckt->CKTmaxEqNum);
|
||||||
|
if (ckt->CKTadjointRHS == NULL) return (E_NOMEM);
|
||||||
|
|
||||||
|
if (vNoise != NULL) freecmat(vNoise);
|
||||||
|
if (iNoise != NULL) freecmat(iNoise);
|
||||||
|
|
||||||
|
vNoise = newcmatnoinit(1, ckt->CKTportCount);
|
||||||
|
iNoise = newcmatnoinit(1, ckt->CKTportCount);
|
||||||
|
|
||||||
|
VSRCinstance* refPort = (VSRCinstance*)(ckt->CKTrfPorts[0]);
|
||||||
|
refPortY0 = refPort->VSRCportY0;
|
||||||
|
|
||||||
|
}
|
||||||
|
return (OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deleteSPmatrix(CKTcircuit* ckt)
|
||||||
|
{
|
||||||
|
if (ckt->CKTAmat != NULL) freecmat(ckt->CKTAmat);
|
||||||
|
if (ckt->CKTBmat != NULL) freecmat(ckt->CKTBmat);
|
||||||
|
if (ckt->CKTSmat != NULL) freecmat(ckt->CKTSmat);
|
||||||
|
if (ckt->CKTYmat != NULL) freecmat(ckt->CKTYmat);
|
||||||
|
if (ckt->CKTZmat != NULL) freecmat(ckt->CKTZmat);
|
||||||
|
if (eyem != NULL) freecmat(eyem);
|
||||||
|
if (zref != NULL) freecmat(zref);
|
||||||
|
if (gn != NULL) freecmat(gn);
|
||||||
|
if (gninv != NULL) freecmat(gninv);
|
||||||
|
eyem = NULL;
|
||||||
|
zref = NULL;
|
||||||
|
gn = NULL;
|
||||||
|
gninv = NULL;
|
||||||
|
|
||||||
|
ckt->CKTAmat = NULL;
|
||||||
|
ckt->CKTBmat = NULL;
|
||||||
|
ckt->CKTSmat = NULL;
|
||||||
|
ckt->CKTZmat = NULL;
|
||||||
|
ckt->CKTYmat = NULL;
|
||||||
|
|
||||||
|
if (ckt->CKTNoiseCYmat != NULL) freecmat(ckt->CKTNoiseCYmat);
|
||||||
|
if (ckt->CKTadjointRHS != NULL) freecmat(ckt->CKTadjointRHS);
|
||||||
|
if (vNoise != NULL) freecmat(vNoise);
|
||||||
|
if (iNoise != NULL) freecmat(iNoise);
|
||||||
|
|
||||||
|
|
||||||
|
vNoise = NULL;
|
||||||
|
iNoise = NULL;
|
||||||
|
ckt->CKTNoiseCYmat = NULL;
|
||||||
|
ckt->CKTadjointRHS = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
SPan(CKTcircuit *ckt, int restart)
|
SPan(CKTcircuit *ckt, int restart)
|
||||||
|
|
@ -221,8 +361,14 @@ SPan(CKTcircuit *ckt, int restart)
|
||||||
|
|
||||||
double* rhswoPorts = NULL;
|
double* rhswoPorts = NULL;
|
||||||
double* irhswoPorts = NULL;
|
double* irhswoPorts = NULL;
|
||||||
int* portPosNodes = NULL;
|
|
||||||
int* portNegNodes = NULL;
|
/* variable must be static, for continuation of interrupted (Ctrl-C),
|
||||||
|
longer lasting noise anlysis */
|
||||||
|
static Ndata* data=NULL;
|
||||||
|
if (job->SPdoNoise)
|
||||||
|
{
|
||||||
|
data = TMALLOC(Ndata, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (ckt->CKTportCount == 0)
|
if (ckt->CKTportCount == 0)
|
||||||
|
|
@ -233,21 +379,6 @@ SPan(CKTcircuit *ckt, int restart)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (ckt->CKTAmat != NULL) freecmat(ckt->CKTAmat);
|
|
||||||
if (ckt->CKTBmat != NULL) freecmat(ckt->CKTBmat);
|
|
||||||
if (ckt->CKTSmat != NULL) freecmat(ckt->CKTSmat);
|
|
||||||
|
|
||||||
ckt->CKTAmat = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0);
|
|
||||||
if (ckt->CKTAmat == NULL)
|
|
||||||
return (E_NOMEM);
|
|
||||||
ckt->CKTBmat = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0);
|
|
||||||
if (ckt->CKTBmat == NULL)
|
|
||||||
return (3);
|
|
||||||
|
|
||||||
ckt->CKTSmat = newcmat(ckt->CKTportCount, ckt->CKTportCount, 0.0, 0.0);
|
|
||||||
if (ckt->CKTSmat == NULL)
|
|
||||||
return (E_NOMEM);
|
|
||||||
|
|
||||||
#ifdef XSPICE
|
#ifdef XSPICE
|
||||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */
|
/* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */
|
||||||
|
|
||||||
|
|
@ -276,7 +407,7 @@ SPan(CKTcircuit *ckt, int restart)
|
||||||
return E_PARMVAL;
|
return E_PARMVAL;
|
||||||
}
|
}
|
||||||
job->SPfreqDelta =
|
job->SPfreqDelta =
|
||||||
exp(log(10.0)/job->SPnumberSteps);
|
exp(log(10.0) / job->SPnumberSteps);
|
||||||
break;
|
break;
|
||||||
case OCTAVE:
|
case OCTAVE:
|
||||||
if (job->SPstartFreq <= 0) {
|
if (job->SPstartFreq <= 0) {
|
||||||
|
|
@ -284,108 +415,122 @@ SPan(CKTcircuit *ckt, int restart)
|
||||||
return E_PARMVAL;
|
return E_PARMVAL;
|
||||||
}
|
}
|
||||||
job->SPfreqDelta =
|
job->SPfreqDelta =
|
||||||
exp(log(2.0)/job->SPnumberSteps);
|
exp(log(2.0) / job->SPnumberSteps);
|
||||||
break;
|
break;
|
||||||
case LINEAR:
|
case LINEAR:
|
||||||
if (job->SPnumberSteps-1 > 1)
|
if (job->SPnumberSteps - 1 > 1)
|
||||||
job->SPfreqDelta =
|
job->SPfreqDelta =
|
||||||
(job->SPstopFreq -
|
(job->SPstopFreq -
|
||||||
job->SPstartFreq) /
|
job->SPstartFreq) /
|
||||||
(job->SPnumberSteps - 1);
|
(job->SPnumberSteps - 1);
|
||||||
else
|
else
|
||||||
/* Patch from: Richard McRoberts
|
/* Patch from: Richard McRoberts
|
||||||
* This patch is for a rather pathological case:
|
* This patch is for a rather pathological case:
|
||||||
* a linear step with only one point */
|
* a linear step with only one point */
|
||||||
job->SPfreqDelta = 0;
|
job->SPfreqDelta = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return(E_BADPARM);
|
return(E_BADPARM);
|
||||||
}
|
|
||||||
#ifdef XSPICE
|
|
||||||
/* gtri - begin - wbk - Call EVTop if event-driven instances exist */
|
|
||||||
|
|
||||||
if(ckt->evt->counts.num_insts != 0) {
|
|
||||||
error = EVTop(ckt,
|
|
||||||
(ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT,
|
|
||||||
(ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT,
|
|
||||||
ckt->CKTdcMaxIter,
|
|
||||||
MIF_TRUE);
|
|
||||||
EVTdump(ckt, IPC_ANAL_DCOP, 0.0);
|
|
||||||
EVTop_save(ckt, MIF_TRUE, 0.0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
/* If no event-driven instances, do what SPICE normally does */
|
|
||||||
if (!ckt->CKTnoopac) { /* skip OP if option NOOPAC is set and circuit is linear */
|
|
||||||
error = CKTop(ckt,
|
|
||||||
(ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT,
|
|
||||||
(ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT,
|
|
||||||
ckt->CKTdcMaxIter);
|
|
||||||
|
|
||||||
if(error){
|
|
||||||
fprintf(stdout,"\nAC operating point failed -\n");
|
|
||||||
CKTncDump(ckt);
|
|
||||||
return(error);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
if (job->SPdoNoise)
|
||||||
fprintf(stdout,"\n Linear circuit, option noopac given: no OP analysis\n");
|
{
|
||||||
|
data->lstFreq = job->SPstartFreq - 1;
|
||||||
|
data->delFreq = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef XSPICE
|
#ifdef XSPICE
|
||||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff */
|
/* gtri - begin - wbk - Call EVTop if event-driven instances exist */
|
||||||
|
|
||||||
/* Send the operating point results for Mspice compatibility */
|
if (ckt->evt->counts.num_insts != 0) {
|
||||||
if(g_ipc.enabled)
|
error = EVTop(ckt,
|
||||||
{
|
(ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT,
|
||||||
/* Call CKTnames to get names of nodes/branches used by
|
(ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT,
|
||||||
BeginPlot */
|
ckt->CKTdcMaxIter,
|
||||||
/* Probably should free nameList after this block since
|
MIF_TRUE);
|
||||||
called again... */
|
EVTdump(ckt, IPC_ANAL_DCOP, 0.0);
|
||||||
error = CKTnames(ckt,&numNames,&nameList);
|
EVTop_save(ckt, MIF_TRUE, 0.0);
|
||||||
if(error) return(error);
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
/* If no event-driven instances, do what SPICE normally does */
|
||||||
|
if (!ckt->CKTnoopac) { /* skip OP if option NOOPAC is set and circuit is linear */
|
||||||
|
error = CKTop(ckt,
|
||||||
|
(ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT,
|
||||||
|
(ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT,
|
||||||
|
ckt->CKTdcMaxIter);
|
||||||
|
|
||||||
/* We have to do a beginPlot here since the data to return is
|
if (error) {
|
||||||
* different for the DCOP than it is for the AC analysis.
|
fprintf(stdout, "\nAC operating point failed -\n");
|
||||||
* Moreover the begin plot has not even been done yet at this
|
CKTncDump(ckt);
|
||||||
* point...
|
return(error);
|
||||||
*/
|
}
|
||||||
SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob,
|
}
|
||||||
ckt->CKTcurJob->JOBname,
|
else
|
||||||
NULL, IF_REAL,
|
fprintf(stdout, "\n Linear circuit, option noopac given: no OP analysis\n");
|
||||||
numNames, nameList, IF_REAL,
|
|
||||||
&spPlot);
|
|
||||||
txfree(nameList);
|
|
||||||
|
|
||||||
ipc_send_dcop_prefix();
|
#ifdef XSPICE
|
||||||
CKTdump(ckt, 0.0, spPlot);
|
/* gtri - add - wbk - 12/19/90 - Add IPC stuff */
|
||||||
ipc_send_dcop_suffix();
|
|
||||||
|
|
||||||
SPfrontEnd->OUTendPlot (spPlot);
|
/* Send the operating point results for Mspice compatibility */
|
||||||
}
|
if (g_ipc.enabled)
|
||||||
/* gtri - end - wbk */
|
{
|
||||||
|
/* Call CKTnames to get names of nodes/branches used by
|
||||||
|
BeginPlot */
|
||||||
|
/* Probably should free nameList after this block since
|
||||||
|
called again... */
|
||||||
|
error = CKTnames(ckt, &numNames, &nameList);
|
||||||
|
if (error) return(error);
|
||||||
|
|
||||||
|
/* We have to do a beginPlot here since the data to return is
|
||||||
|
* different for the DCOP than it is for the AC analysis.
|
||||||
|
* Moreover the begin plot has not even been done yet at this
|
||||||
|
* point...
|
||||||
|
*/
|
||||||
|
SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob,
|
||||||
|
ckt->CKTcurJob->JOBname,
|
||||||
|
NULL, IF_REAL,
|
||||||
|
numNames, nameList, IF_REAL,
|
||||||
|
&spPlot);
|
||||||
|
txfree(nameList);
|
||||||
|
|
||||||
|
ipc_send_dcop_prefix();
|
||||||
|
CKTdump(ckt, 0.0, spPlot);
|
||||||
|
ipc_send_dcop_suffix();
|
||||||
|
|
||||||
|
SPfrontEnd->OUTendPlot(spPlot);
|
||||||
|
}
|
||||||
|
/* gtri - end - wbk */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG;
|
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG;
|
||||||
error = CKTload(ckt);
|
error = CKTload(ckt);
|
||||||
if(error) return(error);
|
if (error) return(error);
|
||||||
|
|
||||||
error = CKTnames(ckt,&numNames,&nameList);
|
error = CKTnames(ckt, &numNames, &nameList);
|
||||||
if(error) return(error);
|
if (error) return(error);
|
||||||
|
|
||||||
if (ckt->CKTkeepOpInfo) {
|
if (ckt->CKTkeepOpInfo) {
|
||||||
/* Dump operating point. */
|
/* Dump operating point. */
|
||||||
error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob,
|
error = SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob,
|
||||||
"AC Operating Point",
|
"AC Operating Point",
|
||||||
NULL, IF_REAL,
|
NULL, IF_REAL,
|
||||||
numNames, nameList, IF_REAL,
|
numNames, nameList, IF_REAL,
|
||||||
&plot);
|
&plot);
|
||||||
if(error) return(error);
|
if (error) return(error);
|
||||||
CKTdump(ckt, 0.0, plot);
|
CKTdump(ckt, 0.0, plot);
|
||||||
SPfrontEnd->OUTendPlot (plot);
|
SPfrontEnd->OUTendPlot(plot);
|
||||||
plot = NULL;
|
plot = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int extraSPdataLength = 3 * ckt->CKTportCount * ckt->CKTportCount;
|
||||||
|
if (job->SPdoNoise)
|
||||||
|
{
|
||||||
|
extraSPdataLength += ckt->CKTportCount * ckt->CKTportCount; // Add Cy
|
||||||
|
if (ckt->CKTportCount == 2)
|
||||||
|
extraSPdataLength += 4;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int extraSPdataLength = ckt->CKTportCount * ckt->CKTportCount;
|
|
||||||
nameList = (IFuid*)TREALLOC(IFuid, nameList, numNames + extraSPdataLength);
|
nameList = (IFuid*)TREALLOC(IFuid, nameList, numNames + extraSPdataLength);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -399,12 +544,57 @@ SPan(CKTcircuit *ckt, int restart)
|
||||||
SPfrontEnd->IFnewUid(ckt, &(nameList[numNames++]), NULL, tmpBuf, UID_OTHER, NULL);
|
SPfrontEnd->IFnewUid(ckt, &(nameList[numNames++]), NULL, tmpBuf, UID_OTHER, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
SPfrontEnd->IFnewUid (ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL);
|
// Create UIDs
|
||||||
error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob,
|
for (unsigned int dest = 1; dest <= ckt->CKTportCount; dest++)
|
||||||
ckt->CKTcurJob->JOBname,
|
for (unsigned int j = 1; j <= ckt->CKTportCount; j++)
|
||||||
freqUid, IF_REAL,
|
{
|
||||||
numNames, nameList, IF_COMPLEX,
|
char tmpBuf[32];
|
||||||
&spPlot);
|
sprintf(tmpBuf, "Y_%d_%d", dest, j);
|
||||||
|
|
||||||
|
SPfrontEnd->IFnewUid(ckt, &(nameList[numNames++]), NULL, tmpBuf, UID_OTHER, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create UIDs
|
||||||
|
for (unsigned int dest = 1; dest <= ckt->CKTportCount; dest++)
|
||||||
|
for (unsigned int j = 1; j <= ckt->CKTportCount; j++)
|
||||||
|
{
|
||||||
|
char tmpBuf[32];
|
||||||
|
sprintf(tmpBuf, "Z_%d_%d", dest, j);
|
||||||
|
|
||||||
|
SPfrontEnd->IFnewUid(ckt, &(nameList[numNames++]), NULL, tmpBuf, UID_OTHER, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add noise related output, if needed
|
||||||
|
if (job->SPdoNoise)
|
||||||
|
{
|
||||||
|
// Create UIDs
|
||||||
|
for (unsigned int dest = 1; dest <= ckt->CKTportCount; dest++)
|
||||||
|
for (unsigned int j = 1; j <= ckt->CKTportCount; j++)
|
||||||
|
{
|
||||||
|
char tmpBuf[32];
|
||||||
|
sprintf(tmpBuf, "Cy_%d_%d", dest, j);
|
||||||
|
|
||||||
|
SPfrontEnd->IFnewUid(ckt, &(nameList[numNames++]), NULL, tmpBuf, UID_OTHER, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add NFMin, SOpt, Rn (related to port 1)
|
||||||
|
if (ckt->CKTportCount == 2)
|
||||||
|
{
|
||||||
|
SPfrontEnd->IFnewUid(ckt, &(nameList[numNames++]), NULL, "NF", UID_OTHER, NULL);
|
||||||
|
SPfrontEnd->IFnewUid(ckt, &(nameList[numNames++]), NULL, "SOpt", UID_OTHER, NULL);
|
||||||
|
SPfrontEnd->IFnewUid(ckt, &(nameList[numNames++]), NULL, "NFmin", UID_OTHER, NULL);
|
||||||
|
SPfrontEnd->IFnewUid(ckt, &(nameList[numNames++]), NULL, "Rn", UID_OTHER, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SPfrontEnd->IFnewUid(ckt, &freqUid, NULL, "frequency", UID_OTHER, NULL);
|
||||||
|
error = SPfrontEnd->OUTpBeginPlot(ckt, ckt->CKTcurJob,
|
||||||
|
ckt->CKTcurJob->JOBname,
|
||||||
|
freqUid, IF_REAL,
|
||||||
|
numNames, nameList, IF_COMPLEX,
|
||||||
|
&spPlot);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -455,7 +645,20 @@ SPan(CKTcircuit *ckt, int restart)
|
||||||
|
|
||||||
INIT_STATS();
|
INIT_STATS();
|
||||||
|
|
||||||
ckt->CKTcurrentAnalysis = DOING_AC;
|
ckt->CKTcurrentAnalysis = DOING_AC | DOING_SP;
|
||||||
|
|
||||||
|
if (initSPmatrix(ckt, job->SPdoNoise))
|
||||||
|
return (E_NOMEM);
|
||||||
|
|
||||||
|
// Create Noise UID, if needed
|
||||||
|
|
||||||
|
if (job->SPdoNoise)
|
||||||
|
{
|
||||||
|
|
||||||
|
data->numPlots = 0; /* we don't have any plots yet */
|
||||||
|
error = CKTspnoise(ckt, N_DENS, N_OPEN, data);
|
||||||
|
if (error) return(error);
|
||||||
|
}
|
||||||
|
|
||||||
ckt->CKTactivePort = 0;
|
ckt->CKTactivePort = 0;
|
||||||
/* main loop through all scheduled frequencies */
|
/* main loop through all scheduled frequencies */
|
||||||
|
|
@ -499,8 +702,33 @@ SPan(CKTcircuit *ckt, int restart)
|
||||||
}
|
}
|
||||||
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG;
|
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG;
|
||||||
error = CKTload(ckt);
|
error = CKTload(ckt);
|
||||||
if (error) return(error);
|
if (error) {
|
||||||
|
tfree(data); return(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store previous rhs
|
||||||
|
if (rhswoPorts == NULL)
|
||||||
|
rhswoPorts = (double*)TMALLOC(double, ckt->CKTmaxEqNum);
|
||||||
|
else
|
||||||
|
rhswoPorts = (double*)TREALLOC(double, rhswoPorts, ckt->CKTmaxEqNum);
|
||||||
|
|
||||||
|
if (rhswoPorts == NULL) {
|
||||||
|
tfree(data); return (E_NOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irhswoPorts == NULL)
|
||||||
|
irhswoPorts = (double*)TMALLOC(double, ckt->CKTmaxEqNum);
|
||||||
|
else
|
||||||
|
irhswoPorts = (double*)TREALLOC(double, irhswoPorts, ckt->CKTmaxEqNum);
|
||||||
|
|
||||||
|
if (irhswoPorts == NULL) {
|
||||||
|
tfree(rhswoPorts);
|
||||||
|
tfree(data); return (E_NOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODESP;
|
||||||
|
|
||||||
// Let's sweep thru all available ports to build Y matrix
|
// Let's sweep thru all available ports to build Y matrix
|
||||||
// Y_ij = I_i / V_j | V_k!=j = 0
|
// Y_ij = I_i / V_j | V_k!=j = 0
|
||||||
// (we have only to modify rhs)
|
// (we have only to modify rhs)
|
||||||
|
|
@ -522,16 +750,14 @@ SPan(CKTcircuit *ckt, int restart)
|
||||||
return (E_NOMOD);
|
return (E_NOMOD);
|
||||||
|
|
||||||
ckt->CKTVSRCid = vsrcRoot;
|
ckt->CKTVSRCid = vsrcRoot;
|
||||||
|
|
||||||
|
// Now that we have found the model, we may init the Zref and Gn ports
|
||||||
|
VSRCspinit(ckt->CKThead[vsrcRoot], ckt, zref, gn, gninv);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vsrcRoot = ckt->CKTVSRCid;
|
vsrcRoot = ckt->CKTVSRCid;
|
||||||
|
|
||||||
if (rhswoPorts == NULL)
|
|
||||||
rhswoPorts = (double*)TREALLOC(double, rhswoPorts, ckt->CKTmaxEqNum);
|
|
||||||
if (irhswoPorts == NULL)
|
|
||||||
irhswoPorts = (double*)TREALLOC(double, irhswoPorts, ckt->CKTmaxEqNum);
|
|
||||||
|
|
||||||
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODESP;
|
|
||||||
// Pre-load everything but RF Ports (these will be updated in the next cycle).
|
// Pre-load everything but RF Ports (these will be updated in the next cycle).
|
||||||
error = NIspPreload(ckt);
|
error = NIspPreload(ckt);
|
||||||
if (error) return (error);
|
if (error) return (error);
|
||||||
|
|
@ -556,6 +782,8 @@ SPan(CKTcircuit *ckt, int restart)
|
||||||
{
|
{
|
||||||
tfree(rhswoPorts);
|
tfree(rhswoPorts);
|
||||||
tfree(irhswoPorts);
|
tfree(irhswoPorts);
|
||||||
|
tfree(data);
|
||||||
|
deleteSPmatrix(ckt);
|
||||||
return(error);
|
return(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -563,6 +791,8 @@ SPan(CKTcircuit *ckt, int restart)
|
||||||
if (error) {
|
if (error) {
|
||||||
tfree(rhswoPorts);
|
tfree(rhswoPorts);
|
||||||
tfree(irhswoPorts);
|
tfree(irhswoPorts);
|
||||||
|
tfree(data);
|
||||||
|
deleteSPmatrix(ckt);
|
||||||
UPDATE_STATS(DOING_AC);
|
UPDATE_STATS(DOING_AC);
|
||||||
return(error);
|
return(error);
|
||||||
}
|
}
|
||||||
|
|
@ -600,83 +830,78 @@ SPan(CKTcircuit *ckt, int restart)
|
||||||
// Now we can calculate the full S-Matrix
|
// Now we can calculate the full S-Matrix
|
||||||
CKTspCalcSMatrix(ckt);
|
CKTspCalcSMatrix(ckt);
|
||||||
|
|
||||||
#ifdef XSPICE
|
|
||||||
/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
|
|
||||||
|
|
||||||
if (g_ipc.enabled)
|
|
||||||
ipc_send_data_prefix(freq);
|
|
||||||
|
|
||||||
error = CKTspDump(ckt, freq, spPlot);
|
|
||||||
|
|
||||||
if (g_ipc.enabled)
|
|
||||||
ipc_send_data_suffix();
|
|
||||||
|
|
||||||
/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
|
|
||||||
#else
|
|
||||||
error = CKTspDump(ckt, freq, spPlot);
|
|
||||||
#endif
|
|
||||||
if (error) {
|
|
||||||
UPDATE_STATS(DOING_AC);
|
|
||||||
tfree(rhswoPorts);
|
|
||||||
tfree(irhswoPorts);
|
|
||||||
return(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now go with noise cycle, if required
|
* Now go with noise cycle, if required
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef NOISE_AVAILABLE
|
|
||||||
|
|
||||||
// To be completed
|
|
||||||
if (job->SPdoNoise)
|
if (job->SPdoNoise)
|
||||||
{
|
{
|
||||||
if (portPosNodes == NULL)
|
|
||||||
{
|
|
||||||
portPosNodes = TMALLOC(int, ckt->CKTportCount);
|
|
||||||
portNegNodes = TMALLOC(int, ckt->CKTportCount);
|
|
||||||
VSRCgetActivePortNodes(ckt->CKThead[vsrcRoot], ckt, portPosNodes, portNegNodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Ndata* data;
|
data->delFreq = freq - data->lstFreq;
|
||||||
|
data->freq = freq;
|
||||||
|
|
||||||
double realVal;
|
|
||||||
double imagVal;
|
cinit(ckt->CKTNoiseCYmat, 0.0, 0.0);
|
||||||
int error;
|
|
||||||
int posOutNode;
|
|
||||||
int negOutNode;
|
|
||||||
//Keep a backup copy
|
|
||||||
memcpy(rhswoPorts, ckt->CKTrhs, ckt->CKTmaxEqNum * sizeof(double));
|
|
||||||
memcpy(rhswoPorts, ckt->CKTirhs, ckt->CKTmaxEqNum * sizeof(double));
|
|
||||||
|
|
||||||
for (activePort = 0; activePort < ckt->CKTportCount; activePort++)
|
for (activePort = 0; activePort < ckt->CKTportCount; activePort++)
|
||||||
{
|
{
|
||||||
/* the frequency will NOT be stored in array[0] as before; instead,
|
/* the frequency will NOT be stored in array[0] as before; instead,
|
||||||
* it will be given in refVal.rValue (see later)
|
* it will be given in refVal.rValue (see later)
|
||||||
*/
|
*/
|
||||||
// Copy the backup RHS into CKT's RHS
|
|
||||||
memcpy(ckt->CKTrhs, rhswoPorts, ckt->CKTmaxEqNum * sizeof(double));
|
|
||||||
memcpy(ckt->CKTirhs, irhswoPorts, ckt->CKTmaxEqNum * sizeof(double));
|
|
||||||
ckt->CKTactivePort = activePort+1;
|
ckt->CKTactivePort = activePort+1;
|
||||||
|
|
||||||
posOutNode = portPosNodes[activePort];
|
NInspIter(ckt, (VSRCinstance*)(ckt->CKTrfPorts[activePort])); /* solve the adjoint system */
|
||||||
negOutNode = portNegNodes[activePort];
|
/* put the solution of the current adjoint system into the storage matrix*/
|
||||||
NInspIter(ckt, posOutNode, negOutNode); /* solve the adjoint system */
|
int j;
|
||||||
|
for (j = 0; j < ckt->CKTmaxEqNum; j++)
|
||||||
/* now we use the adjoint system to calculate the noise
|
|
||||||
* contributions of each generator in the circuit
|
|
||||||
*/
|
|
||||||
|
|
||||||
error = CKTspnoise(ckt, N_DENS, N_CALC, data);
|
|
||||||
if (error)
|
|
||||||
{
|
{
|
||||||
tfree(portPosNodes); tfree(portNegNodes);
|
cplx temp;
|
||||||
return(error);
|
temp.re = ckt->CKTrhs[j];
|
||||||
|
temp.im = ckt->CKTirhs[j];
|
||||||
|
|
||||||
|
ckt->CKTadjointRHS->d[activePort][j] = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
now we have all the solutions of the adjoint system, we may look into actual
|
||||||
|
noise sourches
|
||||||
|
*/
|
||||||
|
|
||||||
|
error = CKTspnoise(ckt, N_DENS, N_CALC, data);
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
tfree(data);
|
||||||
|
tfree(rhswoPorts);
|
||||||
|
tfree(irhswoPorts);
|
||||||
|
deleteSPmatrix(ckt);
|
||||||
|
return(error);
|
||||||
|
}
|
||||||
|
data->lstFreq = freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef XSPICE
|
||||||
|
/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
|
||||||
|
|
||||||
|
if (g_ipc.enabled)
|
||||||
|
ipc_send_data_prefix(freq);
|
||||||
|
|
||||||
|
error = CKTspDump(ckt, freq, spPlot, job->SPdoNoise);
|
||||||
|
|
||||||
|
if (g_ipc.enabled)
|
||||||
|
ipc_send_data_suffix();
|
||||||
|
|
||||||
|
/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
|
||||||
|
#else
|
||||||
|
error = CKTspDump(ckt, freq, acPlot, job->SPdoNoise));
|
||||||
#endif
|
#endif
|
||||||
|
if (error) {
|
||||||
|
UPDATE_STATS(DOING_AC);
|
||||||
|
tfree(rhswoPorts);
|
||||||
|
tfree(irhswoPorts);
|
||||||
|
tfree(data);
|
||||||
|
deleteSPmatrix(ckt);
|
||||||
|
return(error);
|
||||||
|
}
|
||||||
/* increment frequency */
|
/* increment frequency */
|
||||||
|
|
||||||
switch (job->SPstepType) {
|
switch (job->SPstepType) {
|
||||||
|
|
@ -717,7 +942,8 @@ SPan(CKTcircuit *ckt, int restart)
|
||||||
default:
|
default:
|
||||||
tfree(rhswoPorts);
|
tfree(rhswoPorts);
|
||||||
tfree(irhswoPorts);
|
tfree(irhswoPorts);
|
||||||
tfree(portPosNodes); tfree(portNegNodes);
|
tfree(data);
|
||||||
|
deleteSPmatrix(ckt);
|
||||||
return(E_INTERN);
|
return(E_INTERN);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -728,7 +954,8 @@ endsweep:
|
||||||
UPDATE_STATS(0);
|
UPDATE_STATS(0);
|
||||||
tfree(rhswoPorts);
|
tfree(rhswoPorts);
|
||||||
tfree(irhswoPorts);
|
tfree(irhswoPorts);
|
||||||
tfree(portPosNodes); tfree(portNegNodes);
|
deleteSPmatrix(ckt);
|
||||||
|
tfree(data);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ Author: 1985 Thomas L. Quarles
|
||||||
#include "ngspice/ngspice.h"
|
#include "ngspice/ngspice.h"
|
||||||
#include "ngspice/ifsim.h"
|
#include "ngspice/ifsim.h"
|
||||||
#include "ngspice/iferrmsg.h"
|
#include "ngspice/iferrmsg.h"
|
||||||
#include "ngspice/spdefs.h"
|
#include "ngspice/spardefs.h"
|
||||||
#include "ngspice/cktdefs.h"
|
#include "ngspice/cktdefs.h"
|
||||||
|
|
||||||
#ifdef RFSPICE
|
#ifdef RFSPICE
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ Author: 1985 Thomas L. Quarles
|
||||||
#include "ngspice/ngspice.h"
|
#include "ngspice/ngspice.h"
|
||||||
#include "ngspice/ifsim.h"
|
#include "ngspice/ifsim.h"
|
||||||
#include "ngspice/iferrmsg.h"
|
#include "ngspice/iferrmsg.h"
|
||||||
#include "ngspice/spdefs.h"
|
#include "ngspice/spardefs.h"
|
||||||
#include "ngspice/cktdefs.h"
|
#include "ngspice/cktdefs.h"
|
||||||
|
|
||||||
#include "analysis.h"
|
#include "analysis.h"
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,9 @@ CKTinit(CKTcircuit **ckt) /* new circuit to create */
|
||||||
sckt->CKTVSRCid = -1;
|
sckt->CKTVSRCid = -1;
|
||||||
sckt->CKTrfPorts = NULL;
|
sckt->CKTrfPorts = NULL;
|
||||||
sckt->CKTSmat = sckt->CKTAmat = sckt->CKTBmat = sckt->CKTYmat = sckt->CKTZmat = NULL;
|
sckt->CKTSmat = sckt->CKTAmat = sckt->CKTBmat = sckt->CKTYmat = sckt->CKTZmat = NULL;
|
||||||
|
sckt->CKTNoiseCYmat = NULL;
|
||||||
|
sckt->CKTadjointRHS = NULL;
|
||||||
|
sckt->CKTnoiseSourceCount = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,32 @@ Author: 1985 Thomas L. Quarles
|
||||||
|
|
||||||
#ifdef RFSPICE
|
#ifdef RFSPICE
|
||||||
|
|
||||||
|
|
||||||
|
int VSRCspinit(GENmodel* inModel, CKTcircuit* ckt, CMat* zref, CMat* gn, CMat* gninv)
|
||||||
|
{
|
||||||
|
if (!(ckt->CKTmode & MODESP) && !(ckt->CKTcurrentAnalysis & DOING_SP))
|
||||||
|
return (OK);
|
||||||
|
VSRCmodel* model = (VSRCmodel*)inModel;
|
||||||
|
VSRCinstance* here;
|
||||||
|
|
||||||
|
for (; model != NULL; model = VSRCnextModel(model)) {
|
||||||
|
|
||||||
|
/* loop through all the instances of the model */
|
||||||
|
for (here = VSRCinstances(model); here != NULL;
|
||||||
|
here = VSRCnextInstance(here)) {
|
||||||
|
|
||||||
|
if (here->VSRCisPort)
|
||||||
|
{
|
||||||
|
int i = here->VSRCportNum - 1;
|
||||||
|
zref->d[i][i].re = here->VSRCportZ0;
|
||||||
|
gn->d[i][i].re = 2.0 * here->VSRCki;
|
||||||
|
gninv->d[i][i].re = 1.0 / gn->d[i][i].re;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (OK);
|
||||||
|
}
|
||||||
|
|
||||||
int VSRCspupdate(GENmodel* inModel, CKTcircuit* ckt)
|
int VSRCspupdate(GENmodel* inModel, CKTcircuit* ckt)
|
||||||
{
|
{
|
||||||
if (!(ckt->CKTmode & MODESP))
|
if (!(ckt->CKTmode & MODESP))
|
||||||
|
|
@ -36,12 +62,14 @@ int VSRCspupdate(GENmodel* inModel, CKTcircuit* ckt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int VSRCgetActivePortNodes(GENmodel* inModel, CKTcircuit* ckt, int* posNodes, int* negNodes)
|
|
||||||
|
int VSRCgetActivePorts(GENmodel* inModel, CKTcircuit* ckt, VSRCinstance** ports)
|
||||||
{
|
{
|
||||||
if (!(ckt->CKTmode & MODESP))
|
if (!(ckt->CKTmode & MODESP))
|
||||||
return (OK);
|
return (OK);
|
||||||
for (unsigned int n = 0; n < ckt->CKTportCount; n++)
|
for (unsigned int n = 0; n < ckt->CKTportCount; n++)
|
||||||
posNodes[n] = negNodes[n] = 0;
|
ports[n] = NULL;
|
||||||
|
|
||||||
VSRCmodel* model = (VSRCmodel*)inModel;
|
VSRCmodel* model = (VSRCmodel*)inModel;
|
||||||
VSRCinstance* here;
|
VSRCinstance* here;
|
||||||
|
|
||||||
|
|
@ -54,9 +82,7 @@ int VSRCgetActivePortNodes(GENmodel* inModel, CKTcircuit* ckt, int* posNodes, in
|
||||||
if (here->VSRCisPort)
|
if (here->VSRCisPort)
|
||||||
{
|
{
|
||||||
int id = here->VSRCportNum - 1;
|
int id = here->VSRCportNum - 1;
|
||||||
posNodes[id] = here->VSRCposNode;
|
ports[id] = here;
|
||||||
negNodes[id] = here->VSRCnegNode;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -78,9 +104,9 @@ VSRCacLoad(GENmodel* inModel, CKTcircuit* ckt)
|
||||||
|
|
||||||
double acReal, acImag;
|
double acReal, acImag;
|
||||||
|
|
||||||
|
|
||||||
#ifdef RFSPICE
|
#ifdef RFSPICE
|
||||||
double g0;
|
double g0 = 0;
|
||||||
g0 = 0;
|
|
||||||
acReal = 0.0;
|
acReal = 0.0;
|
||||||
acImag = 0.0;
|
acImag = 0.0;
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -18,5 +18,8 @@ extern int VSRCpzSetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*);
|
||||||
extern int VSRCtemp(GENmodel*,CKTcircuit*);
|
extern int VSRCtemp(GENmodel*,CKTcircuit*);
|
||||||
#ifdef RFSPICE
|
#ifdef RFSPICE
|
||||||
extern int VSRCspupdate(GENmodel*, CKTcircuit*);
|
extern int VSRCspupdate(GENmodel*, CKTcircuit*);
|
||||||
extern int VSRCgetActivePortNodes(GENmodel* inModel, CKTcircuit* ckt, int* posNodes, int* negNodes);
|
#include "vsrcdefs.h"
|
||||||
|
|
||||||
|
extern int VSRCgetActivePorts(GENmodel* inModel, CKTcircuit* ckt, VSRCinstance** ports);
|
||||||
|
extern int VSRCspinit(GENmodel* inModel, CKTcircuit* ckt, CMat* zref, CMat* gn, CMat* gninv);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
here=VSRCnextInstance(here)) {
|
here=VSRCnextInstance(here)) {
|
||||||
|
|
||||||
#ifndef RFSPICE
|
#ifndef RFSPICE
|
||||||
*(here->VSRCposIbrPtr) += 1.0;
|
* (here->VSRCposIbrPtr) += 1.0;
|
||||||
*(here->VSRCnegIbrPtr) -= 1.0;
|
*(here->VSRCnegIbrPtr) -= 1.0;
|
||||||
*(here->VSRCibrPosPtr) += 1.0;
|
*(here->VSRCibrPosPtr) += 1.0;
|
||||||
*(here->VSRCibrNegPtr) -= 1.0;
|
*(here->VSRCibrNegPtr) -= 1.0;
|
||||||
|
|
@ -60,7 +60,7 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
*(here->VSRCnegNegPtr) += g0;
|
*(here->VSRCnegNegPtr) += g0;
|
||||||
*(here->VSRCposNegPtr) -= g0;
|
*(here->VSRCposNegPtr) -= g0;
|
||||||
*(here->VSRCnegPosPtr) -= g0;
|
*(here->VSRCnegPosPtr) -= g0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*(here->VSRCposIbrPtr) += 1.0;
|
*(here->VSRCposIbrPtr) += 1.0;
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,26 @@ VSRCtemp(GENmodel *inModel, CKTcircuit *ckt)
|
||||||
ckt->CKTrfPorts = (GENinstance**)TREALLOC(GENinstance*, ckt->CKTrfPorts, ckt->CKTportCount);
|
ckt->CKTrfPorts = (GENinstance**)TREALLOC(GENinstance*, ckt->CKTrfPorts, ckt->CKTportCount);
|
||||||
ckt->CKTrfPorts[ckt->CKTportCount - 1] = (GENinstance*)here;
|
ckt->CKTrfPorts[ckt->CKTportCount - 1] = (GENinstance*)here;
|
||||||
|
|
||||||
|
// Reorder ports according to their PortNum
|
||||||
|
unsigned int done = 0;
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
int nMax = ckt->CKTportCount - 1;
|
||||||
|
done = 1;
|
||||||
|
for (int n = 0; n < nMax; n++)
|
||||||
|
{
|
||||||
|
VSRCinstance* a = (VSRCinstance*)ckt->CKTrfPorts[n];
|
||||||
|
VSRCinstance* b = (VSRCinstance*)ckt->CKTrfPorts[n + 1];
|
||||||
|
if (a->VSRCportNum > b->VSRCportNum)
|
||||||
|
{
|
||||||
|
// Swap a and b. Restart
|
||||||
|
done = 0;
|
||||||
|
ckt->CKTrfPorts[n] = (GENinstance*)b;
|
||||||
|
ckt->CKTrfPorts[n + 1] = (GENinstance*)a;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -616,7 +616,7 @@ dot_pss(char *line, void *ckt, INPtables *tab, struct card *current,
|
||||||
|
|
||||||
|
|
||||||
#ifdef RFSPICE
|
#ifdef RFSPICE
|
||||||
/* S Parameter Analyis */
|
/* S-Parameter Analyis */
|
||||||
static int
|
static int
|
||||||
dot_sp(char* line, void* ckt, INPtables* tab, struct card* current,
|
dot_sp(char* line, void* ckt, INPtables* tab, struct card* current,
|
||||||
void* task, void* gnode, JOB* foo)
|
void* task, void* gnode, JOB* foo)
|
||||||
|
|
@ -652,7 +652,7 @@ dot_sp(char* line, void* ckt, INPtables* tab, struct card* current,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_HB
|
#ifdef WITH_HB
|
||||||
/* HB */
|
/*SP: Steady State Analyis */
|
||||||
static int
|
static int
|
||||||
dot_hb(char* line, void* ckt, INPtables* tab, struct card* current,
|
dot_hb(char* line, void* ckt, INPtables* tab, struct card* current,
|
||||||
void* task, void* gnode, JOB* foo)
|
void* task, void* gnode, JOB* foo)
|
||||||
|
|
@ -714,6 +714,7 @@ dot_hb(char* line, void* ckt, INPtables* tab, struct card* current,
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dot_options(char *line, CKTcircuit *ckt, INPtables *tab, struct card *current,
|
dot_options(char *line, CKTcircuit *ckt, INPtables *tab, struct card *current,
|
||||||
TSKtask *task, CKTnode *gnode, JOB *foo)
|
TSKtask *task, CKTnode *gnode, JOB *foo)
|
||||||
|
|
|
||||||
|
|
@ -952,7 +952,7 @@
|
||||||
<ClInclude Include="..\src\include\ngspice\cmconstants.h" />
|
<ClInclude Include="..\src\include\ngspice\cmconstants.h" />
|
||||||
<ClInclude Include="..\src\include\ngspice\cmproto.h" />
|
<ClInclude Include="..\src\include\ngspice\cmproto.h" />
|
||||||
<ClInclude Include="..\src\include\ngspice\cmtypes.h" />
|
<ClInclude Include="..\src\include\ngspice\cmtypes.h" />
|
||||||
<ClInclude Include="..\src\include\ngspice\spdefs.h" />
|
<ClInclude Include="..\src\include\ngspice\spardefs.h" />
|
||||||
<ClInclude Include="..\src\include\ngspice\wincolornames.h" />
|
<ClInclude Include="..\src\include\ngspice\wincolornames.h" />
|
||||||
<ClInclude Include="..\src\include\ngspice\compatmode.h" />
|
<ClInclude Include="..\src\include\ngspice\compatmode.h" />
|
||||||
<ClInclude Include="..\src\include\ngspice\complex.h" />
|
<ClInclude Include="..\src\include\ngspice\complex.h" />
|
||||||
|
|
@ -1067,6 +1067,7 @@
|
||||||
<ClInclude Include="..\src\maths\cmaths\cmath3.h" />
|
<ClInclude Include="..\src\maths\cmaths\cmath3.h" />
|
||||||
<ClInclude Include="..\src\maths\cmaths\cmath4.h" />
|
<ClInclude Include="..\src\maths\cmaths\cmath4.h" />
|
||||||
<ClInclude Include="..\src\maths\dense\dense.h" />
|
<ClInclude Include="..\src\maths\dense\dense.h" />
|
||||||
|
<ClInclude Include="..\src\maths\dense\denseinlines.h" />
|
||||||
<ClInclude Include="..\src\maths\fft\fftlib.h" />
|
<ClInclude Include="..\src\maths\fft\fftlib.h" />
|
||||||
<ClInclude Include="..\src\maths\fft\matlib.h" />
|
<ClInclude Include="..\src\maths\fft\matlib.h" />
|
||||||
<ClInclude Include="..\src\maths\misc\accuracy.h" />
|
<ClInclude Include="..\src\maths\misc\accuracy.h" />
|
||||||
|
|
@ -1686,6 +1687,7 @@
|
||||||
<ClCompile Include="..\src\spicelib\analysis\cktsgen.c" />
|
<ClCompile Include="..\src\spicelib\analysis\cktsgen.c" />
|
||||||
<ClCompile Include="..\src\spicelib\analysis\cktsopt.c" />
|
<ClCompile Include="..\src\spicelib\analysis\cktsopt.c" />
|
||||||
<ClCompile Include="..\src\spicelib\analysis\cktspdum.c" />
|
<ClCompile Include="..\src\spicelib\analysis\cktspdum.c" />
|
||||||
|
<ClCompile Include="..\src\spicelib\analysis\cktspnoise.c" />
|
||||||
<ClCompile Include="..\src\spicelib\analysis\ckttemp.c" />
|
<ClCompile Include="..\src\spicelib\analysis\ckttemp.c" />
|
||||||
<ClCompile Include="..\src\spicelib\analysis\cktterr.c" />
|
<ClCompile Include="..\src\spicelib\analysis\cktterr.c" />
|
||||||
<ClCompile Include="..\src\spicelib\analysis\ckttroub.c" />
|
<ClCompile Include="..\src\spicelib\analysis\ckttroub.c" />
|
||||||
|
|
@ -1709,6 +1711,7 @@
|
||||||
<ClCompile Include="..\src\spicelib\analysis\nevalsrc.c" />
|
<ClCompile Include="..\src\spicelib\analysis\nevalsrc.c" />
|
||||||
<ClCompile Include="..\src\spicelib\analysis\ninteg.c" />
|
<ClCompile Include="..\src\spicelib\analysis\ninteg.c" />
|
||||||
<ClCompile Include="..\src\spicelib\analysis\noisean.c" />
|
<ClCompile Include="..\src\spicelib\analysis\noisean.c" />
|
||||||
|
<ClCompile Include="..\src\spicelib\analysis\noisesp.c" />
|
||||||
<ClCompile Include="..\src\spicelib\analysis\nsetparm.c" />
|
<ClCompile Include="..\src\spicelib\analysis\nsetparm.c" />
|
||||||
<ClCompile Include="..\src\spicelib\analysis\optran.c" />
|
<ClCompile Include="..\src\spicelib\analysis\optran.c" />
|
||||||
<ClCompile Include="..\src\spicelib\analysis\pssaskq.c" />
|
<ClCompile Include="..\src\spicelib\analysis\pssaskq.c" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue