S parameter simulation
Command '.sp' arbitrary number of ports ports made with modified VSRC Patch provided by Alessio Cacciatori https://sourceforge.net/p/ngspice/discussion/127605/thread/7a2655c86f/
This commit is contained in:
parent
b774d03162
commit
2c10c4aebd
|
|
@ -0,0 +1,21 @@
|
|||
Example of VSRC as power ports
|
||||
*
|
||||
*
|
||||
V1 in 0 dc 0 ac 1 portnum 1 z0 100 pwr 0.001 freq 2.3e9
|
||||
*V1 in 0 dc 1 ac 1
|
||||
Rpt in x 100
|
||||
C1 x 0 1e-9
|
||||
*Vx x 0 0
|
||||
R2 x out 10
|
||||
V2 out 0 dc 0 ac 0 portnum 2 z0 50 pwr 0.002 freq 3.2e9
|
||||
*V2 out 0 dc 0 ac 0
|
||||
|
||||
.sp lin 100 1e8 1e9 1
|
||||
|
||||
.control
|
||||
run
|
||||
plot S_1_1 S_1_2 S_2_1
|
||||
plot S_2_2
|
||||
.endc
|
||||
|
||||
.end
|
||||
|
|
@ -305,6 +305,14 @@ struct comm spcp_coms[] = {
|
|||
NULL,
|
||||
"[.pss line args] : Do a periodic state analysis." } ,
|
||||
/* SP */
|
||||
#endif
|
||||
#ifdef RFSPICE
|
||||
/* SP: S parameter Analysis */
|
||||
{ "sp", com_sp, TRUE, TRUE,
|
||||
{ 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS,
|
||||
NULL,
|
||||
"[.sp line args] : Do a S parameter analysis." },
|
||||
/* SP */
|
||||
#endif
|
||||
{ "ac", com_ac, TRUE, TRUE,
|
||||
{ 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS,
|
||||
|
|
|
|||
|
|
@ -177,15 +177,22 @@ com_noise(wordlist *wl)
|
|||
|
||||
|
||||
#ifdef WITH_PSS
|
||||
/* SP: Steady State Analysis */
|
||||
/* Steady State Analysis */
|
||||
void
|
||||
com_pss(wordlist *wl)
|
||||
{
|
||||
dosim("pss", wl);
|
||||
}
|
||||
/* SP */
|
||||
#endif
|
||||
|
||||
#ifdef RFSPICE
|
||||
/* S parameter Analysis*/
|
||||
void
|
||||
com_sp(wordlist* wl)
|
||||
{
|
||||
dosim("sp", wl);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dosim(
|
||||
char *what, /* in: command
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ void com_sens(wordlist *wl);
|
|||
void com_disto(wordlist *wl);
|
||||
void com_noise(wordlist *wl);
|
||||
void com_run(wordlist *wl);
|
||||
#ifdef RFSPICE
|
||||
void com_sp(wordlist* wl);
|
||||
#endif
|
||||
|
||||
extern FILE *rawfileFp;
|
||||
extern bool rawfileBinary;
|
||||
|
|
|
|||
|
|
@ -314,6 +314,87 @@ if_sens_run(CKTcircuit *ckt, wordlist *args, INPtables *tab)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef RFSPICE
|
||||
if (strcmp(token, "sp") == 0) {
|
||||
JOB* spJob;
|
||||
which = ft_find_analysis("SP");
|
||||
if (which == -1) {
|
||||
current->error = INPerrCat
|
||||
(current->error,
|
||||
INPmkTemp("S-Param analysis unsupported\n"));
|
||||
return (0); /* temporary */
|
||||
}
|
||||
err = ft_sim->newAnalysis(ft_curckt->ci_ckt, which, "span",
|
||||
&spJob, ft_curckt->ci_specTask);
|
||||
if (err) {
|
||||
ft_sperror(err, "createSP"); /* or similar error message */
|
||||
return (0); /* temporary */
|
||||
}
|
||||
|
||||
INPgetTok(&line, &steptype, 1); /* get DEC, OCT, or LIN */
|
||||
ptemp.iValue = 1;
|
||||
error = INPapName(ckt, which, spJob, steptype, &ptemp);
|
||||
if (error)
|
||||
current->error = INPerrCat(current->error, INPerror(error));
|
||||
parm = INPgetValue(ckt, &line, IF_INTEGER, tab);/* number of points*/
|
||||
error = INPapName(ckt, which, spJob, "numsteps", parm);
|
||||
if (error)
|
||||
current->error = INPerrCat(current->error, INPerror(error));
|
||||
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstart */
|
||||
error = INPapName(ckt, which, spJob, "start", parm);
|
||||
if (error)
|
||||
current->error = INPerrCat(current->error, INPerror(error));
|
||||
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstop */
|
||||
error = INPapName(ckt, which, spJob, "stop", parm);
|
||||
if (error)
|
||||
current->error = INPerrCat(current->error, INPerror(error));
|
||||
parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* fstop */
|
||||
error = INPapName(ckt, which, spJob, "donoise", parm);
|
||||
if (error)
|
||||
current->error = INPerrCat(current->error, INPerror(error));
|
||||
}
|
||||
#ifdef WITH_HB
|
||||
if (strcmp(token, "hb") == 0) {
|
||||
JOB* spJob;
|
||||
which = ft_find_analysis("HB");
|
||||
if (which == -1) {
|
||||
current->error = INPerrCat
|
||||
(current->error,
|
||||
INPmkTemp("S-Param analysis unsupported\n"));
|
||||
return (0); /* temporary */
|
||||
}
|
||||
err = ft_sim->newAnalysis(ft_curckt->ci_ckt, which, "hban",
|
||||
&spJob, ft_curckt->ci_specTask);
|
||||
if (err) {
|
||||
ft_sperror(err, "createHB"); /* or similar error message */
|
||||
return (0); /* temporary */
|
||||
}
|
||||
|
||||
INPgetTok(&line, &steptype, 1); /* get DEC, OCT, or LIN */
|
||||
ptemp.iValue = 1;
|
||||
error = INPapName(ckt, which, spJob, steptype, &ptemp);
|
||||
if (error)
|
||||
current->error = INPerrCat(current->error, INPerror(error));
|
||||
parm = INPgetValue(ckt, &line, IF_INTEGER, tab);/* number of points*/
|
||||
error = INPapName(ckt, which, spJob, "numsteps", parm);
|
||||
if (error)
|
||||
current->error = INPerrCat(current->error, INPerror(error));
|
||||
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstart */
|
||||
error = INPapName(ckt, which, spJob, "start", parm);
|
||||
if (error)
|
||||
current->error = INPerrCat(current->error, INPerror(error));
|
||||
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstop */
|
||||
error = INPapName(ckt, which, spJob, "stop", parm);
|
||||
if (error)
|
||||
current->error = INPerrCat(current->error, INPerror(error));
|
||||
parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* fstop */
|
||||
error = INPapName(ckt, which, spJob, "donoise", parm);
|
||||
if (error)
|
||||
current->error = INPerrCat(current->error, INPerror(error));
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
next:
|
||||
while (*line) { /* read the entire line */
|
||||
|
||||
|
|
|
|||
|
|
@ -220,9 +220,14 @@ if_run(CKTcircuit *ckt, char *what, wordlist *args, INPtables *tab)
|
|||
eq(what, "tf") ||
|
||||
eq(what, "noise")
|
||||
#ifdef WITH_PSS
|
||||
/* SP: Steady State Analysis */
|
||||
/* Steady State Analysis */
|
||||
|| eq(what, "pss")
|
||||
/* SP */
|
||||
#endif
|
||||
#ifdef RFSPICE
|
||||
|| eq(what, "sp")
|
||||
#ifdef WITH_HB
|
||||
|| eq(what, "hb")
|
||||
#endif
|
||||
#endif
|
||||
)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,11 +25,21 @@ typedef struct {
|
|||
|
||||
/* available step types: XXX should be somewhere else */
|
||||
|
||||
#ifdef RFSPICE
|
||||
#ifndef ngspice_SPDEFS_H
|
||||
enum {
|
||||
DECADE = 1,
|
||||
OCTAVE,
|
||||
LINEAR,
|
||||
};
|
||||
#endif
|
||||
#else
|
||||
enum {
|
||||
DECADE = 1,
|
||||
OCTAVE,
|
||||
LINEAR,
|
||||
};
|
||||
#endif
|
||||
|
||||
enum {
|
||||
AC_DEC = 1,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@
|
|||
#include "ngspice/noisedef.h"
|
||||
#include "ngspice/hash.h"
|
||||
|
||||
#ifdef RFSPICE
|
||||
#include "../maths/dense/dense.h"
|
||||
#endif
|
||||
|
||||
|
||||
struct CKTnode {
|
||||
|
|
@ -187,6 +190,11 @@ struct CKTcircuit {
|
|||
#define MODEINITTRAN 0x1000
|
||||
#define MODEINITPRED 0x2000
|
||||
|
||||
#ifdef RFSPICE
|
||||
#define MODESP 0x4000
|
||||
#define MODESPNOISE 0x8000
|
||||
#endif
|
||||
|
||||
/* old 'nosolv' paramater */
|
||||
#define MODEUIC 0x10000l
|
||||
|
||||
|
|
@ -274,7 +282,17 @@ struct CKTcircuit {
|
|||
Enh_Ckt_Data_t *enh; /* data used by general enhancements */
|
||||
#endif
|
||||
/* gtri - evt - wbk - 5/20/91 - add event-driven and enhancements data */
|
||||
|
||||
#ifdef RFSPICE
|
||||
unsigned int CKTactivePort;/* Identify active port during S-Param analysis*/
|
||||
unsigned int CKTportCount; /* Number of RF ports */
|
||||
int CKTVSRCid; /* Place holder for VSRC Devices id*/
|
||||
GENinstance** CKTrfPorts; /* List of all RF ports (HB & SP) */
|
||||
CMat* CKTAmat;
|
||||
CMat* CKTBmat;
|
||||
CMat* CKTSmat;
|
||||
CMat* CKTYmat;
|
||||
CMat* CKTZmat;
|
||||
#endif
|
||||
#ifdef WITH_PSS
|
||||
/* SP: Periodic Steady State Analysis - 100609 */
|
||||
double CKTstabTime; /* PSS stab time */
|
||||
|
|
@ -356,6 +374,9 @@ extern int CKTmodAsk(CKTcircuit *, GENmodel *, int , IFvalue *, IFvalue *);
|
|||
extern int CKTmodCrt(CKTcircuit *, int , GENmodel **, IFuid);
|
||||
extern int CKTmodParam(CKTcircuit *, GENmodel *, int , IFvalue *, IFvalue *);
|
||||
extern int CKTnames(CKTcircuit *, int *, IFuid **);
|
||||
#ifdef RFSPICE
|
||||
extern int CKTSPnames(CKTcircuit*, int*, IFuid**);
|
||||
#endif
|
||||
extern int CKTdnames(CKTcircuit *);
|
||||
extern int CKTnewAnal(CKTcircuit *, int , IFuid , JOB **, TSKtask *);
|
||||
extern int CKTnewEq(CKTcircuit *, CKTnode **, IFuid);
|
||||
|
|
@ -423,12 +444,22 @@ extern int TRANsetParm(CKTcircuit *, JOB *, int , IFvalue *);
|
|||
extern int TRANinit(CKTcircuit *, JOB *);
|
||||
|
||||
#ifdef WITH_PSS
|
||||
/* SP: Steady State Analysis */
|
||||
/* Steady State Analysis */
|
||||
extern int PSSaskQuest(CKTcircuit *, JOB *, int , IFvalue *);
|
||||
extern int PSSsetParm(CKTcircuit *, JOB *, int , IFvalue *);
|
||||
extern int PSSinit(CKTcircuit *, JOB *);
|
||||
extern int DCpss(CKTcircuit *, int);
|
||||
/* SP */
|
||||
#endif
|
||||
|
||||
#ifdef RFSPICE
|
||||
extern int SPan(CKTcircuit*, int);
|
||||
extern int SPaskQuest(CKTcircuit*, JOB*, int, IFvalue*);
|
||||
extern int SPsetParm(CKTcircuit*, JOB*, int, IFvalue*);
|
||||
extern int CKTspDump(CKTcircuit*, double, runDesc*);
|
||||
extern int CKTspLoad(CKTcircuit*);
|
||||
extern unsigned int CKTmatrixIndex(CKTcircuit*, unsigned int, unsigned int);
|
||||
extern int CKTspCalcPowerWave(CKTcircuit* ckt);
|
||||
extern int CKTspCalcSMatrix(CKTcircuit* ckt);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -452,6 +483,10 @@ extern int NIreinit(CKTcircuit *);
|
|||
extern int NIsenReinit(CKTcircuit *);
|
||||
extern int NIdIter (CKTcircuit *);
|
||||
extern void NInzIter(CKTcircuit *, int, int);
|
||||
#ifdef RFSPICE
|
||||
extern int NIspPreload(CKTcircuit*);
|
||||
extern int NIspSolve(CKTcircuit*);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -112,6 +112,9 @@ typedef enum {
|
|||
IPC_ANAL_DCTRCURVE,
|
||||
IPC_ANAL_AC,
|
||||
IPC_ANAL_TRAN,
|
||||
#ifdef RFSPICE
|
||||
IPC_ANAL_SP
|
||||
#endif
|
||||
} Ipc_Anal_t;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1985 Thomas L. Quarles
|
||||
**********/
|
||||
|
||||
#ifndef ngspice_SPDEFS_H
|
||||
#define ngspice_SPDEFS_H
|
||||
|
||||
#include "ngspice/jobdefs.h"
|
||||
|
||||
#ifdef RFSPICE
|
||||
/* structure used to describe an AC analysis to be performed */
|
||||
|
||||
typedef struct {
|
||||
int JOBtype;
|
||||
JOB *JOBnextJob; /* pointer to next thing to do */
|
||||
char *JOBname; /* name of this job */
|
||||
double SPstartFreq;
|
||||
double SPstopFreq;
|
||||
double SPfreqDelta; /* multiplier for decade/octave stepping, */
|
||||
/* step for linear steps. */
|
||||
double SPsaveFreq; /* frequency at which we left off last time*/
|
||||
int SPstepType; /* values described below */
|
||||
int SPnumberSteps;
|
||||
|
||||
unsigned SPdoNoise : 1; /* Flag to indicate if SP noise must be calculated*/
|
||||
|
||||
unsigned int SPnoiseInput;
|
||||
unsigned int SPnoiseOutput;
|
||||
} SPAN;
|
||||
|
||||
/* available step types: XXX should be somewhere else */
|
||||
#ifndef ngspice_ACDEFS_H
|
||||
enum {
|
||||
DECADE = 1,
|
||||
OCTAVE,
|
||||
LINEAR,
|
||||
};
|
||||
#endif
|
||||
|
||||
enum {
|
||||
SP_DEC = 1,
|
||||
SP_OCT,
|
||||
SP_LIN,
|
||||
SP_START,
|
||||
SP_STOP,
|
||||
SP_STEPS,
|
||||
SP_DONOISE,
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,103 @@
|
|||
#ifndef ngspice_DENSE_MATRIX_H
|
||||
#define ngspice_DENSE_MATRIX_H
|
||||
|
||||
|
||||
typedef struct cplx
|
||||
{
|
||||
double re;
|
||||
double im;
|
||||
}cplx;
|
||||
|
||||
typedef struct Mat{
|
||||
double** d;
|
||||
int row;
|
||||
int col;
|
||||
}Mat;
|
||||
|
||||
typedef struct CMat {
|
||||
cplx** d;
|
||||
int row;
|
||||
int col;
|
||||
}CMat;
|
||||
|
||||
|
||||
typedef struct MatList{
|
||||
Mat* mat;
|
||||
struct MatList* next;
|
||||
}MatList;
|
||||
|
||||
extern void showmat(Mat* A);
|
||||
extern void showcmat(CMat* A);
|
||||
extern CMat* newcmat(int r, int c, double dr, double di);
|
||||
extern CMat* newcmatnoinit(int r, int c);
|
||||
extern Mat* newmat(int r, int c, double d);
|
||||
extern Mat* newmatnoinit(int r, int c);
|
||||
extern void freecmat(CMat* A);
|
||||
extern void freemat(Mat* A);
|
||||
extern CMat* ceye(int n);
|
||||
extern Mat* eye(int n);
|
||||
extern Mat* zeros(int r, int c);
|
||||
extern CMat* czeros(int r, int c);
|
||||
extern Mat* ones(int r, int c);
|
||||
extern CMat* cones(int r, int c);
|
||||
extern Mat* randm(int r, int c, double l, double u);
|
||||
extern CMat* randcm(int r, int c, double l, double u);
|
||||
extern double get(Mat* M, int r, int c);
|
||||
extern cplx getcplx(CMat* M, int r, int c);
|
||||
extern void set(Mat* M, int r, int c, double d);
|
||||
extern void setc(CMat* M, int r, int c, cplx d);
|
||||
extern Mat* scalarmultiply(Mat* M, double c);
|
||||
extern CMat* cscalarmultiply(CMat* M, double c);
|
||||
extern CMat* complexmultiply(CMat* M, cplx c);
|
||||
extern Mat* sum(Mat* A, Mat* B);
|
||||
extern CMat* csum(CMat* A, CMat* B);
|
||||
extern Mat* minus(Mat* A, Mat* B);
|
||||
extern CMat* cminus(CMat* A, CMat* B);
|
||||
extern 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);
|
||||
extern 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);
|
||||
extern Mat* multiply(Mat* A, Mat* B);
|
||||
extern CMat* cmultiply(CMat* A, CMat* B);
|
||||
extern Mat* removerow(Mat* A, int r);
|
||||
extern Mat* removecol(Mat* A, int c);
|
||||
extern void removerow2(Mat* A, Mat* B, int r);
|
||||
extern void removecol2(Mat* A, Mat* B, int c);
|
||||
extern CMat* cremoverow(CMat* A, int r);
|
||||
extern CMat* cremovecol(CMat* A, int c);
|
||||
extern void cremoverow2(CMat* A, CMat* B, int r);
|
||||
extern void cremovecol2(CMat* A, CMat* B, int c);
|
||||
extern Mat* transpose(Mat* A);
|
||||
extern CMat* ctranspose(CMat* A);
|
||||
extern double trace(Mat* A);
|
||||
extern cplx ctrace(CMat* A);
|
||||
extern Mat* adjoint(Mat* A);
|
||||
extern CMat* cadjoint(CMat* A);
|
||||
extern Mat* inverse(Mat* A);
|
||||
extern CMat* cinverse(CMat* A);
|
||||
extern Mat* copyvalue(Mat* A);
|
||||
extern CMat* copycvalue(CMat* A);
|
||||
extern Mat* copyvalue(Mat* A);
|
||||
extern CMat* copycvalue(CMat* A);
|
||||
extern Mat* triinverse(Mat* A);
|
||||
extern CMat* ctriinverse(CMat* A);
|
||||
extern Mat* rowechelon(Mat* A);
|
||||
extern CMat* crowechelon(CMat* A);
|
||||
extern Mat* hconcat(Mat* A, Mat* B);
|
||||
extern CMat* chconcat(CMat* A, CMat* B);
|
||||
extern Mat* vconcat(Mat* A, Mat* B);
|
||||
extern CMat* cvconcat(CMat* A, CMat* B);
|
||||
extern double norm(Mat* A);
|
||||
extern double cnorm(CMat* A);
|
||||
extern Mat* nullmat(Mat* A);
|
||||
extern MatList* lu(Mat* A);
|
||||
extern double innermultiply(Mat* a, Mat* b);
|
||||
extern MatList* qr(Mat* A);
|
||||
extern int complexmultiplydest(CMat* M, cplx c, CMat* dest);
|
||||
extern int cinversedest(CMat* A, CMat* dest);
|
||||
extern int copycvaluedest(CMat* A, CMat* dest);
|
||||
extern int cmultiplydest(CMat* A, CMat* B, CMat* dest);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -19,6 +19,82 @@ Modified 1999 Emmanuel Rouat
|
|||
#include "ngspice/cktdefs.h"
|
||||
#include "ngspice/sperror.h"
|
||||
|
||||
#ifdef RFSPICE
|
||||
// We don't need to reload the AC matrix for every port analysis
|
||||
// So we split the NIacIter in two functions
|
||||
int NIspPreload(CKTcircuit* ckt)
|
||||
{
|
||||
|
||||
int error;
|
||||
int ignore;
|
||||
double startTime;
|
||||
|
||||
retry:
|
||||
ckt->CKTnoncon = 0;
|
||||
|
||||
error = CKTacLoad(ckt);
|
||||
|
||||
if (error) return(error);
|
||||
|
||||
if (ckt->CKTniState & NIACSHOULDREORDER) {
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
error = SMPcReorder(ckt->CKTmatrix, ckt->CKTpivotAbsTol,
|
||||
ckt->CKTpivotRelTol, &ignore);
|
||||
ckt->CKTstat->STATreorderTime +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
ckt->CKTniState &= ~NIACSHOULDREORDER;
|
||||
if (error != 0) {
|
||||
/* either singular equations or no memory, in either case,
|
||||
* let caller handle problem
|
||||
*/
|
||||
return(error);
|
||||
}
|
||||
}
|
||||
else {
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
error = SMPcLUfac(ckt->CKTmatrix, ckt->CKTpivotAbsTol);
|
||||
ckt->CKTstat->STATdecompTime +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
if (error != 0) {
|
||||
if (error == E_SINGULAR) {
|
||||
/* the problem is that the matrix can't be solved with the
|
||||
* current LU factorization. Maybe if we reload and
|
||||
* try to reorder again it will help...
|
||||
*/
|
||||
ckt->CKTniState |= NIACSHOULDREORDER;
|
||||
goto retry;
|
||||
}
|
||||
return(error); /* can't handle E_BADMATRIX, so let caller */
|
||||
}
|
||||
}
|
||||
|
||||
return (OK);
|
||||
};
|
||||
|
||||
int NIspSolve(CKTcircuit* ckt)
|
||||
{
|
||||
double startTime;
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
SMPcSolve(ckt->CKTmatrix, ckt->CKTrhs,
|
||||
ckt->CKTirhs, ckt->CKTrhsSpare,
|
||||
ckt->CKTirhsSpare);
|
||||
ckt->CKTstat->STATsolveTime += SPfrontEnd->IFseconds() - startTime;
|
||||
|
||||
ckt->CKTrhs[0] = 0;
|
||||
ckt->CKTrhsSpare[0] = 0;
|
||||
ckt->CKTrhsOld[0] = 0;
|
||||
ckt->CKTirhs[0] = 0;
|
||||
ckt->CKTirhsSpare[0] = 0;
|
||||
ckt->CKTirhsOld[0] = 0;
|
||||
|
||||
SWAP(double*, ckt->CKTirhs, ckt->CKTirhsOld);
|
||||
|
||||
SWAP(double*, ckt->CKTrhs, ckt->CKTrhsOld);
|
||||
return (OK);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
NIacIter(CKTcircuit *ckt)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,15 @@ extern SPICEanalysis DISTOinfo;
|
|||
extern SPICEanalysis NOISEinfo;
|
||||
extern SPICEanalysis SENSinfo;
|
||||
|
||||
#ifdef RFSPICE
|
||||
extern SPICEanalysis SPinfo;
|
||||
|
||||
#ifdef WITH_HB
|
||||
extern SPICEanalysis HBinfo;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PSS
|
||||
extern SPICEanalysis PSSinfo;
|
||||
#endif
|
||||
|
|
@ -41,6 +50,12 @@ SPICEanalysis *analInfo[] = {
|
|||
#ifdef WANT_SENSE2
|
||||
&SEN2info,
|
||||
#endif
|
||||
#ifdef RFSPICE
|
||||
& SPinfo,
|
||||
#ifdef WITH_HB
|
||||
& HBinfo,
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -104,6 +104,16 @@ CKTdestroy(CKTcircuit *ckt)
|
|||
|
||||
nghash_free(ckt->DEVnameHash, NULL, NULL);
|
||||
nghash_free(ckt->MODnameHash, NULL, NULL);
|
||||
|
||||
#ifdef RFSPICE
|
||||
FREE(ckt->CKTrfPorts);
|
||||
freecmat(ckt->CKTAmat); ckt->CKTAmat = NULL;
|
||||
freecmat(ckt->CKTBmat); ckt->CKTBmat = NULL;
|
||||
freecmat(ckt->CKTSmat); ckt->CKTSmat = NULL;
|
||||
freecmat(ckt->CKTYmat); ckt->CKTYmat = NULL;
|
||||
freecmat(ckt->CKTZmat); ckt->CKTZmat = NULL;
|
||||
#endif
|
||||
|
||||
FREE(ckt);
|
||||
|
||||
#ifdef XSPICE
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1985 Thomas L. Quarles
|
||||
**********/
|
||||
|
||||
/* CKTspDump(ckt,freq,file)
|
||||
* this is a simple program to dump the complex rhs vector
|
||||
* into the rawfile.
|
||||
*/
|
||||
|
||||
#include "ngspice/ngspice.h"
|
||||
#include "ngspice/smpdefs.h"
|
||||
#include "ngspice/cktdefs.h"
|
||||
#include "ngspice/iferrmsg.h"
|
||||
#include "ngspice/ifsim.h"
|
||||
#include "vsrc/vsrcdefs.h"
|
||||
|
||||
unsigned int CKTmatrixIndex(CKTcircuit* ckt, unsigned int source, unsigned int dest)
|
||||
{
|
||||
return source * ckt->CKTportCount + dest;
|
||||
};
|
||||
|
||||
int CKTspCalcSMatrix(CKTcircuit* ckt)
|
||||
{
|
||||
CMat* Ainv = cinverse(ckt->CKTAmat);
|
||||
if (Ainv == NULL) return (E_NOMEM);
|
||||
cmultiplydest(ckt->CKTBmat, Ainv, ckt->CKTSmat);
|
||||
freecmat(Ainv);
|
||||
return (OK);
|
||||
}
|
||||
|
||||
int CKTspCalcPowerWave(CKTcircuit* ckt)
|
||||
{
|
||||
double* rhsold = ckt->CKTrhsOld;
|
||||
double* irhsold = ckt->CKTirhsOld;
|
||||
int col = ckt->CKTactivePort - 1;
|
||||
for (int port = 0; port < ckt->CKTportCount; port++)
|
||||
{
|
||||
VSRCinstance* pSrc = (VSRCinstance*)(ckt->CKTrfPorts[port]);
|
||||
int row = pSrc->VSRCportNum - 1;
|
||||
double zi = pSrc->VSRCportZ0;
|
||||
double iReal = -rhsold[pSrc->VSRCbranch];
|
||||
double iImag = -irhsold[pSrc->VSRCbranch];
|
||||
|
||||
double vReal = rhsold[pSrc->VSRCposNode] - rhsold[pSrc->VSRCnegNode];
|
||||
double vImag = irhsold[pSrc->VSRCposNode] - irhsold[pSrc->VSRCnegNode];
|
||||
// Forward wave (a) of i-th port, real (r) and imag (i)
|
||||
cplx a;
|
||||
a.re = pSrc->VSRCki * (vReal + zi * iReal);
|
||||
a.im = pSrc->VSRCki * (vImag + zi * iImag);
|
||||
|
||||
// Scattered wave (b) of i-th port, real (r) and imag (i)
|
||||
cplx b;
|
||||
b.re = pSrc->VSRCki * (vReal - zi * iReal);
|
||||
b.im = pSrc->VSRCki * (vImag - zi * iImag);
|
||||
|
||||
// fill in A and B matrices
|
||||
setc(ckt->CKTAmat, row, col, a);
|
||||
setc(ckt->CKTBmat, row, col, b);
|
||||
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
||||
int
|
||||
CKTspDump(CKTcircuit *ckt, double freq, runDesc *plot)
|
||||
{
|
||||
double *rhsold;
|
||||
double *irhsold;
|
||||
int i;
|
||||
IFcomplex *data;
|
||||
IFvalue freqData;
|
||||
IFvalue valueData;
|
||||
|
||||
rhsold = ckt->CKTrhsOld;
|
||||
irhsold = ckt->CKTirhsOld;
|
||||
freqData.rValue = freq;
|
||||
unsigned int extraSPdataCount = ckt->CKTportCount * ckt->CKTportCount;
|
||||
valueData.v.numValue = ckt->CKTmaxEqNum - 1 + extraSPdataCount;
|
||||
|
||||
data = TMALLOC(IFcomplex, ckt->CKTmaxEqNum - 1 + extraSPdataCount);
|
||||
valueData.v.vec.cVec = data;
|
||||
for (i=0;i<ckt->CKTmaxEqNum-1;i++) {
|
||||
data[i].real = rhsold[i+1];
|
||||
data[i].imag = irhsold[i+1];
|
||||
}
|
||||
|
||||
if (ckt->CKTrfPorts )
|
||||
{
|
||||
// Cycle thru all ports
|
||||
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 sij = ckt->CKTSmat->d[pdest][psource];
|
||||
data[nPlot].real = sij.re;
|
||||
data[nPlot].imag = sij.im;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SPfrontEnd->OUTpData(plot, &freqData, &valueData);
|
||||
|
||||
FREE(data);
|
||||
return(OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,736 @@
|
|||
/*
|
||||
****
|
||||
* Alessio Cacciatori 2021
|
||||
****
|
||||
*/
|
||||
#include "ngspice/ngspice.h"
|
||||
#include "ngspice/cktdefs.h"
|
||||
#include "ngspice/spdefs.h"
|
||||
#include "ngspice/devdefs.h"
|
||||
#include "ngspice/sperror.h"
|
||||
|
||||
#ifdef XSPICE
|
||||
#include "ngspice/evt.h"
|
||||
#include "ngspice/enh.h"
|
||||
/* gtri - add - wbk - 12/19/90 - Add headers */
|
||||
#include "ngspice/mif.h"
|
||||
#include "ngspice/evtproto.h"
|
||||
#include "ngspice/ipctiein.h"
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef RFSPICE
|
||||
#include "vsrc/vsrcext.h"
|
||||
#include "../maths/dense/dense.h"
|
||||
|
||||
#define INIT_STATS() \
|
||||
do { \
|
||||
startTime = SPfrontEnd->IFseconds(); \
|
||||
startdTime = ckt->CKTstat->STATdecompTime; \
|
||||
startsTime = ckt->CKTstat->STATsolveTime; \
|
||||
startlTime = ckt->CKTstat->STATloadTime; \
|
||||
startkTime = ckt->CKTstat->STATsyncTime; \
|
||||
} while(0)
|
||||
|
||||
#define UPDATE_STATS(analysis) \
|
||||
do { \
|
||||
ckt->CKTcurrentAnalysis = analysis; \
|
||||
ckt->CKTstat->STATacTime += SPfrontEnd->IFseconds() - startTime; \
|
||||
ckt->CKTstat->STATacDecompTime += ckt->CKTstat->STATdecompTime - startdTime; \
|
||||
ckt->CKTstat->STATacSolveTime += ckt->CKTstat->STATsolveTime - startsTime; \
|
||||
ckt->CKTstat->STATacLoadTime += ckt->CKTstat->STATloadTime - startlTime; \
|
||||
ckt->CKTstat->STATacSyncTime += ckt->CKTstat->STATsyncTime - startkTime; \
|
||||
} while(0)
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NInspIter(CKTcircuit * ckt, int posDrive, int negDrive)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* clear out the right hand side vector */
|
||||
|
||||
for (i = 0; i <= SMPmatSize(ckt->CKTmatrix); i++) {
|
||||
ckt->CKTrhs[i] = 0.0;
|
||||
ckt->CKTirhs[i] = 0.0;
|
||||
}
|
||||
|
||||
ckt->CKTrhs[posDrive] = 1.0; /* apply unit current excitation */
|
||||
ckt->CKTrhs[negDrive] = -1.0;
|
||||
SMPcaSolve(ckt->CKTmatrix, ckt->CKTrhs, ckt->CKTirhs, ckt->CKTrhsSpare,
|
||||
ckt->CKTirhsSpare);
|
||||
|
||||
ckt->CKTrhs[0] = 0.0;
|
||||
ckt->CKTirhs[0] = 0.0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
SPan(CKTcircuit *ckt, int restart)
|
||||
{
|
||||
|
||||
|
||||
SPAN *job = (SPAN *) ckt->CKTcurJob;
|
||||
|
||||
double freq;
|
||||
double freqTol; /* tolerence parameter for finding final frequency */
|
||||
double startdTime;
|
||||
double startsTime;
|
||||
double startlTime;
|
||||
double startkTime;
|
||||
double startTime;
|
||||
int error;
|
||||
int numNames;
|
||||
int i;
|
||||
IFuid *nameList; /* va: tmalloc'ed list of names */
|
||||
IFuid freqUid;
|
||||
static runDesc *spPlot = NULL;
|
||||
runDesc *plot = NULL;
|
||||
|
||||
double* rhswoPorts = NULL;
|
||||
double* irhswoPorts = NULL;
|
||||
int* portPosNodes = NULL;
|
||||
int* portNegNodes = NULL;
|
||||
|
||||
|
||||
if (ckt->CKTportCount == 0)
|
||||
{
|
||||
fprintf(stderr, "No RF Port is present\n");
|
||||
return (E_PARMVAL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */
|
||||
|
||||
/* Tell the beginPlot routine what mode we're in */
|
||||
|
||||
// For now, let's keep this as IPC_ANAL_AC (TBD)
|
||||
g_ipc.anal_type = IPC_ANAL_AC;
|
||||
|
||||
/* Tell the code models what mode we're in */
|
||||
g_mif_info.circuit.anal_type = MIF_DC;
|
||||
g_mif_info.circuit.anal_init = MIF_TRUE;
|
||||
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
/* start at beginning */
|
||||
if (job->SPsaveFreq == 0 || restart) {
|
||||
if (job->SPnumberSteps < 1)
|
||||
job->SPnumberSteps = 1;
|
||||
|
||||
switch (job->SPstepType) {
|
||||
|
||||
case DECADE:
|
||||
if (job->SPstartFreq <= 0) {
|
||||
fprintf(stderr, "ERROR: AC startfreq <= 0\n");
|
||||
return E_PARMVAL;
|
||||
}
|
||||
job->SPfreqDelta =
|
||||
exp(log(10.0)/job->SPnumberSteps);
|
||||
break;
|
||||
case OCTAVE:
|
||||
if (job->SPstartFreq <= 0) {
|
||||
fprintf(stderr, "ERROR: AC startfreq <= 0\n");
|
||||
return E_PARMVAL;
|
||||
}
|
||||
job->SPfreqDelta =
|
||||
exp(log(2.0)/job->SPnumberSteps);
|
||||
break;
|
||||
case LINEAR:
|
||||
if (job->SPnumberSteps-1 > 1)
|
||||
job->SPfreqDelta =
|
||||
(job->SPstopFreq -
|
||||
job->SPstartFreq) /
|
||||
(job->SPnumberSteps - 1);
|
||||
else
|
||||
/* Patch from: Richard McRoberts
|
||||
* This patch is for a rather pathological case:
|
||||
* a linear step with only one point */
|
||||
job->SPfreqDelta = 0;
|
||||
break;
|
||||
default:
|
||||
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
|
||||
fprintf(stdout,"\n Linear circuit, option noopac given: no OP analysis\n");
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Add IPC stuff */
|
||||
|
||||
/* Send the operating point results for Mspice compatibility */
|
||||
if(g_ipc.enabled)
|
||||
{
|
||||
/* 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
|
||||
|
||||
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG;
|
||||
error = CKTload(ckt);
|
||||
if(error) return(error);
|
||||
|
||||
error = CKTnames(ckt,&numNames,&nameList);
|
||||
if(error) return(error);
|
||||
|
||||
if (ckt->CKTkeepOpInfo) {
|
||||
/* Dump operating point. */
|
||||
error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob,
|
||||
"AC Operating Point",
|
||||
NULL, IF_REAL,
|
||||
numNames, nameList, IF_REAL,
|
||||
&plot);
|
||||
if(error) return(error);
|
||||
CKTdump(ckt, 0.0, plot);
|
||||
SPfrontEnd->OUTendPlot (plot);
|
||||
plot = NULL;
|
||||
}
|
||||
|
||||
unsigned int extraSPdataLength = ckt->CKTportCount * ckt->CKTportCount;
|
||||
nameList = (IFuid*)TREALLOC(IFuid, nameList, numNames + extraSPdataLength);
|
||||
|
||||
|
||||
// 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, "S_%d_%d", dest, j);
|
||||
|
||||
SPfrontEnd->IFnewUid(ckt, &(nameList[numNames++]), NULL, tmpBuf, 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);
|
||||
|
||||
|
||||
|
||||
tfree(nameList);
|
||||
if(error) return(error);
|
||||
|
||||
if (job->SPstepType != LINEAR) {
|
||||
SPfrontEnd->OUTattributes (spPlot, NULL, OUT_SCALE_LOG, NULL);
|
||||
}
|
||||
freq = job->SPstartFreq;
|
||||
|
||||
} else { /* continue previous analysis */
|
||||
freq = job->SPsaveFreq;
|
||||
job->SPsaveFreq = 0; /* clear the 'old' frequency */
|
||||
/* fix resume? saj, indeed !*/
|
||||
error = SPfrontEnd->OUTpBeginPlot (NULL, NULL,
|
||||
NULL,
|
||||
NULL, 0,
|
||||
666, NULL, 666,
|
||||
&spPlot);
|
||||
/* saj*/
|
||||
}
|
||||
|
||||
switch (job->SPstepType) {
|
||||
case DECADE:
|
||||
case OCTAVE:
|
||||
freqTol = job->SPfreqDelta *
|
||||
job->SPstopFreq * ckt->CKTreltol;
|
||||
break;
|
||||
case LINEAR:
|
||||
freqTol = job->SPfreqDelta * ckt->CKTreltol;
|
||||
break;
|
||||
default:
|
||||
return(E_BADPARM);
|
||||
}
|
||||
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Set anal_init and anal_type */
|
||||
|
||||
g_mif_info.circuit.anal_init = MIF_TRUE;
|
||||
|
||||
/* Tell the code models what mode we're in */
|
||||
g_mif_info.circuit.anal_type = MIF_AC;
|
||||
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
INIT_STATS();
|
||||
|
||||
ckt->CKTcurrentAnalysis = DOING_AC;
|
||||
|
||||
ckt->CKTactivePort = 0;
|
||||
/* main loop through all scheduled frequencies */
|
||||
while (freq <= job->SPstopFreq + freqTol) {
|
||||
|
||||
unsigned int activePort = 0;
|
||||
//
|
||||
if (SPfrontEnd->IFpauseTest()) {
|
||||
/* user asked us to pause via an interrupt */
|
||||
job->SPsaveFreq = freq;
|
||||
return(E_PAUSE);
|
||||
}
|
||||
ckt->CKTomega = 2.0 * M_PI * freq;
|
||||
|
||||
/* Update opertating point, if variable 'hertz' is given */
|
||||
if (ckt->CKTvarHertz) {
|
||||
#ifdef XSPICE
|
||||
/* 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
|
||||
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);
|
||||
}
|
||||
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG;
|
||||
error = CKTload(ckt);
|
||||
if (error) return(error);
|
||||
}
|
||||
// Let's sweep thru all available ports to build Y matrix
|
||||
// Y_ij = I_i / V_j | V_k!=j = 0
|
||||
// (we have only to modify rhs)
|
||||
|
||||
int vsrcLookupType = CKTtypelook("Vsource");
|
||||
int vsrcRoot = -1;
|
||||
|
||||
// Get VSRCs root model
|
||||
if (ckt->CKTVSRCid == -1)
|
||||
{
|
||||
for (i = 0; i < DEVmaxnum; i++) {
|
||||
if (DEVices[i] && DEVices[i]->DEVacLoad && ckt->CKThead[i] && ckt->CKThead[i]->GENmodType == vsrcLookupType) {
|
||||
|
||||
vsrcRoot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (vsrcRoot == -1)
|
||||
return (E_NOMOD);
|
||||
|
||||
ckt->CKTVSRCid = vsrcRoot;
|
||||
}
|
||||
else
|
||||
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).
|
||||
error = NIspPreload(ckt);
|
||||
if (error) return (error);
|
||||
|
||||
// error = VSRCsaveNPData(ckt->CKThead[vsrcRoot]);
|
||||
// if (error) return (error);
|
||||
|
||||
//Keep a backup copy
|
||||
memcpy(rhswoPorts, ckt->CKTrhs, ckt->CKTmaxEqNum * sizeof(double));
|
||||
memcpy(rhswoPorts, ckt->CKTirhs, ckt->CKTmaxEqNum * sizeof(double));
|
||||
|
||||
for (activePort = 1; activePort <= ckt->CKTportCount; activePort++)
|
||||
{
|
||||
// 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;
|
||||
|
||||
// Update only VSRCs
|
||||
error = VSRCspupdate(ckt->CKThead[vsrcRoot], ckt);
|
||||
if (error)
|
||||
{
|
||||
tfree(rhswoPorts);
|
||||
tfree(irhswoPorts);
|
||||
return(error);
|
||||
}
|
||||
|
||||
error = NIspSolve(ckt);
|
||||
if (error) {
|
||||
tfree(rhswoPorts);
|
||||
tfree(irhswoPorts);
|
||||
UPDATE_STATS(DOING_AC);
|
||||
return(error);
|
||||
}
|
||||
|
||||
|
||||
#ifdef WANT_SENSE2
|
||||
if (ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & ACSEN)) {
|
||||
long save;
|
||||
int save1;
|
||||
|
||||
save = ckt->CKTmode;
|
||||
ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG;
|
||||
save1 = ckt->CKTsenInfo->SENmode;
|
||||
ckt->CKTsenInfo->SENmode = ACSEN;
|
||||
if (freq == job->SPstartFreq) {
|
||||
ckt->CKTsenInfo->SENacpertflag = 1;
|
||||
}
|
||||
else {
|
||||
ckt->CKTsenInfo->SENacpertflag = 0;
|
||||
}
|
||||
error = CKTsenAC(ckt);
|
||||
if (error)
|
||||
return (error);
|
||||
ckt->CKTmode = save;
|
||||
ckt->CKTsenInfo->SENmode = save1;
|
||||
}
|
||||
#endif
|
||||
|
||||
// We have done 1 activated port.
|
||||
error = CKTspCalcPowerWave(ckt);
|
||||
|
||||
|
||||
} //active ports cycle
|
||||
|
||||
// Now we can calculate the full S-Matrix
|
||||
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, acPlot);
|
||||
#endif
|
||||
if (error) {
|
||||
UPDATE_STATS(DOING_AC);
|
||||
tfree(rhswoPorts);
|
||||
tfree(irhswoPorts);
|
||||
return(error);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Now go with noise cycle, if required
|
||||
*/
|
||||
|
||||
#ifdef NOISE_AVAILABLE
|
||||
|
||||
// To be completed
|
||||
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;
|
||||
|
||||
double realVal;
|
||||
double imagVal;
|
||||
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++)
|
||||
{
|
||||
/* the frequency will NOT be stored in array[0] as before; instead,
|
||||
* 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;
|
||||
|
||||
posOutNode = portPosNodes[activePort];
|
||||
negOutNode = portNegNodes[activePort];
|
||||
NInspIter(ckt, posOutNode, negOutNode); /* solve the adjoint system */
|
||||
|
||||
/* 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);
|
||||
return(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* increment frequency */
|
||||
|
||||
switch (job->SPstepType) {
|
||||
case DECADE:
|
||||
case OCTAVE:
|
||||
|
||||
/* inserted again 14.12.2001 */
|
||||
#ifdef HAS_PROGREP
|
||||
{
|
||||
double endfreq = job->SPstopFreq;
|
||||
double startfreq = job->SPstartFreq;
|
||||
endfreq = log(endfreq);
|
||||
if (startfreq == 0.0)
|
||||
startfreq = 1e-12;
|
||||
startfreq = log(startfreq);
|
||||
|
||||
if (freq > 0.0)
|
||||
SetAnalyse("sp", (int)((log(freq) - startfreq) * 1000.0 / (endfreq - startfreq)));
|
||||
}
|
||||
#endif
|
||||
|
||||
freq *= job->SPfreqDelta;
|
||||
if (job->SPfreqDelta == 1) goto endsweep;
|
||||
break;
|
||||
case LINEAR:
|
||||
|
||||
#ifdef HAS_PROGREP
|
||||
{
|
||||
double endfreq = job->SPstopFreq;
|
||||
double startfreq = job->SPstartFreq;
|
||||
SetAnalyse("sp", (int)((freq - startfreq) * 1000.0 / (endfreq - startfreq)));
|
||||
}
|
||||
#endif
|
||||
|
||||
freq += job->SPfreqDelta;
|
||||
if (job->SPfreqDelta == 0) goto endsweep;
|
||||
break;
|
||||
default:
|
||||
tfree(rhswoPorts);
|
||||
tfree(irhswoPorts);
|
||||
tfree(portPosNodes); tfree(portNegNodes);
|
||||
return(E_INTERN);
|
||||
|
||||
}
|
||||
}
|
||||
endsweep:
|
||||
SPfrontEnd->OUTendPlot (spPlot);
|
||||
spPlot = NULL;
|
||||
UPDATE_STATS(0);
|
||||
tfree(rhswoPorts);
|
||||
tfree(irhswoPorts);
|
||||
tfree(portPosNodes); tfree(portNegNodes);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1985 Thomas L. Quarles
|
||||
**********/
|
||||
/*
|
||||
*/
|
||||
|
||||
#include "ngspice/ngspice.h"
|
||||
#include "ngspice/ifsim.h"
|
||||
#include "ngspice/iferrmsg.h"
|
||||
#include "ngspice/spdefs.h"
|
||||
#include "ngspice/cktdefs.h"
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
SPaskQuest(CKTcircuit *ckt, JOB *anal, int which, IFvalue *value)
|
||||
{
|
||||
SPAN *job = (SPAN *) anal;
|
||||
|
||||
NG_IGNORE(ckt);
|
||||
|
||||
switch(which) {
|
||||
|
||||
case SP_START:
|
||||
value->rValue = job->SPstartFreq;
|
||||
break;
|
||||
|
||||
case SP_STOP:
|
||||
value->rValue = job->SPstopFreq ;
|
||||
break;
|
||||
|
||||
case SP_STEPS:
|
||||
value->iValue = job->SPnumberSteps;
|
||||
break;
|
||||
|
||||
case SP_DEC:
|
||||
if (job->SPstepType == DECADE) {
|
||||
value->iValue=1;
|
||||
} else {
|
||||
value->iValue=0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SP_OCT:
|
||||
if (job->SPstepType == OCTAVE) {
|
||||
value->iValue=1;
|
||||
} else {
|
||||
value->iValue=0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SP_LIN:
|
||||
if (job->SPstepType == LINEAR) {
|
||||
value->iValue=1;
|
||||
} else {
|
||||
value->iValue=0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SP_DONOISE:
|
||||
if (job->SPdoNoise)
|
||||
value->iValue = 1;
|
||||
else
|
||||
value->iValue = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return(E_BADPARM);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1985 Thomas L. Quarles
|
||||
**********/
|
||||
|
||||
#include "ngspice/ngspice.h"
|
||||
#include "ngspice/ifsim.h"
|
||||
#include "ngspice/iferrmsg.h"
|
||||
#include "ngspice/spdefs.h"
|
||||
#include "ngspice/cktdefs.h"
|
||||
|
||||
#include "analysis.h"
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
SPsetParm(CKTcircuit *ckt, JOB *anal, int which, IFvalue *value)
|
||||
{
|
||||
SPAN *job = (SPAN *) anal;
|
||||
|
||||
NG_IGNORE(ckt);
|
||||
|
||||
switch(which) {
|
||||
|
||||
case SP_START:
|
||||
if (value->rValue < 0.0) {
|
||||
errMsg = copy("Frequency of < 0 is invalid for AC start");
|
||||
job->SPstartFreq = 1.0;
|
||||
return(E_PARMVAL);
|
||||
}
|
||||
|
||||
job->SPstartFreq = value->rValue;
|
||||
break;
|
||||
|
||||
case SP_STOP:
|
||||
if (value->rValue < 0.0) {
|
||||
errMsg = copy("Frequency of < 0 is invalid for AC stop");
|
||||
job->SPstartFreq = 1.0;
|
||||
return(E_PARMVAL);
|
||||
}
|
||||
|
||||
job->SPstopFreq = value->rValue;
|
||||
break;
|
||||
|
||||
case SP_STEPS:
|
||||
job->SPnumberSteps = value->iValue;
|
||||
break;
|
||||
|
||||
case SP_DEC:
|
||||
if(value->iValue) {
|
||||
job->SPstepType = DECADE;
|
||||
} else {
|
||||
if (job->SPstepType == DECADE) {
|
||||
job->SPstepType = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SP_OCT:
|
||||
if(value->iValue) {
|
||||
job->SPstepType = OCTAVE;
|
||||
} else {
|
||||
if (job->SPstepType == OCTAVE) {
|
||||
job->SPstepType = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SP_LIN:
|
||||
if(value->iValue) {
|
||||
job->SPstepType = LINEAR;
|
||||
} else {
|
||||
if (job->SPstepType == LINEAR) {
|
||||
job->SPstepType = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SP_DONOISE:
|
||||
job->SPdoNoise = value->iValue == 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
return(E_BADPARM);
|
||||
}
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
static IFparm SPparms[] = {
|
||||
{ "start", SP_START, IF_SET|IF_ASK|IF_REAL, "starting frequency" },
|
||||
{ "stop", SP_STOP, IF_SET|IF_ASK|IF_REAL, "ending frequency" },
|
||||
{ "numsteps", SP_STEPS,IF_SET|IF_ASK|IF_INTEGER, "number of frequencies"},
|
||||
{ "dec", SP_DEC, IF_SET|IF_FLAG, "step by decades" },
|
||||
{ "oct", SP_OCT, IF_SET|IF_FLAG, "step by octaves" },
|
||||
{ "lin", SP_LIN, IF_SET|IF_FLAG, "step linearly" },
|
||||
{"donoise", SP_DONOISE, IF_SET | IF_FLAG | IF_INTEGER, "do SP noise"}
|
||||
};
|
||||
|
||||
SPICEanalysis SPinfo = {
|
||||
{
|
||||
"SP",
|
||||
"S-Parameters analysis",
|
||||
|
||||
NUMELEMS(SPparms),
|
||||
SPparms
|
||||
},
|
||||
sizeof(SPAN),
|
||||
FREQUENCYDOMAIN,
|
||||
1,
|
||||
SPsetParm,
|
||||
SPaskQuest,
|
||||
NULL,
|
||||
SPan
|
||||
};
|
||||
|
|
@ -134,5 +134,14 @@ CKTinit(CKTcircuit **ckt) /* new circuit to create */
|
|||
g_mif_info.auto_partial.local = MIF_FALSE;
|
||||
/* gtri - end - wbk - 01/12/91 */
|
||||
#endif
|
||||
|
||||
#ifdef RFSPICE
|
||||
sckt->CKTportCount = 0;
|
||||
sckt->CKTactivePort = 0;
|
||||
sckt->CKTVSRCid = -1;
|
||||
sckt->CKTrfPorts = NULL;
|
||||
sckt->CKTSmat = sckt->CKTAmat = sckt->CKTBmat = sckt->CKTYmat = sckt->CKTZmat = NULL;
|
||||
#endif
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@ IFparm VSRCpTable[] = { /* parameters */
|
|||
IOP ("trrandom", VSRC_TRRANDOM, IF_REALVEC,"random source description"),
|
||||
#ifdef SHARED_MODULE
|
||||
IOP ("external", VSRC_EXTERNAL, IF_STRING,"external source description"),
|
||||
#endif
|
||||
#ifdef RFSPICE
|
||||
IOP("portnum", VSRC_PORTNUM, IF_INTEGER,"Port index"),
|
||||
IOP("z0", VSRC_PORTZ0, IF_REAL, "Port impedance"),
|
||||
IOP("pwr", VSRC_PORTPWR, IF_REAL, "Port Power"),
|
||||
IOP("freq", VSRC_PORTFREQ, IF_REAL, "Port frequency"),
|
||||
IOP("phase", VSRC_PORTPHASE, IF_REAL, "Phase of the source"),
|
||||
#endif
|
||||
OPU ("pos_node",VSRC_POS_NODE, IF_INTEGER,"Positive node of source"),
|
||||
OPU ("neg_node",VSRC_NEG_NODE, IF_INTEGER,"Negative node of source"),
|
||||
|
|
|
|||
|
|
@ -9,40 +9,150 @@ Author: 1985 Thomas L. Quarles
|
|||
#include "ngspice/sperror.h"
|
||||
#include "ngspice/suffix.h"
|
||||
|
||||
#ifdef RFSPICE
|
||||
|
||||
int
|
||||
VSRCacLoad(GENmodel *inModel, CKTcircuit *ckt)
|
||||
int VSRCspupdate(GENmodel* inModel, CKTcircuit* ckt)
|
||||
{
|
||||
VSRCmodel *model = (VSRCmodel *) inModel;
|
||||
VSRCinstance *here;
|
||||
if (!(ckt->CKTmode & MODESP))
|
||||
return (OK);
|
||||
VSRCmodel* model = (VSRCmodel*)inModel;
|
||||
VSRCinstance* here;
|
||||
|
||||
for( ; model != NULL; model = VSRCnextModel(model)) {
|
||||
for (; model != NULL; model = VSRCnextModel(model)) {
|
||||
|
||||
/* loop through all the instances of the model */
|
||||
for (here = VSRCinstances(model); here != NULL ;
|
||||
here=VSRCnextInstance(here)) {
|
||||
for (here = VSRCinstances(model); here != NULL;
|
||||
here = VSRCnextInstance(here)) {
|
||||
|
||||
if (here->VSRCisPort)
|
||||
{
|
||||
double acReal = here->VSRCportNum == ckt->CKTactivePort ? 1.0 : 0.0;
|
||||
|
||||
*(ckt->CKTrhs + (here->VSRCbranch)) += acReal;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
||||
|
||||
int VSRCgetActivePortNodes(GENmodel* inModel, CKTcircuit* ckt, int* posNodes, int* negNodes)
|
||||
{
|
||||
if (!(ckt->CKTmode & MODESP))
|
||||
return (OK);
|
||||
for (int n = 0; n < ckt->CKTportCount; n++)
|
||||
posNodes[n] = negNodes[n] = 0;
|
||||
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 id = here->VSRCportNum - 1;
|
||||
posNodes[id] = here->VSRCposNode;
|
||||
negNodes[id] = here->VSRCnegNode;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
VSRCacLoad(GENmodel* inModel, CKTcircuit* ckt)
|
||||
{
|
||||
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)) {
|
||||
|
||||
double acReal, acImag;
|
||||
|
||||
if (ckt->CKTmode & MODEACNOISE) {
|
||||
if ((GENinstance *) here == ckt->noise_input) {
|
||||
#ifdef RFSPICE
|
||||
double g0;
|
||||
g0 = 0;
|
||||
acReal = 0.0;
|
||||
acImag = 0.0;
|
||||
/*
|
||||
* TBD: Verify that MODESPNOISE require also noise from source port
|
||||
* In any case, activate only the required noise input to build
|
||||
* noise matrix properly
|
||||
*/
|
||||
if ((ckt->CKTmode & MODEACNOISE) || (ckt->CKTmode & MODESPNOISE))
|
||||
{
|
||||
if ((GENinstance*)here == ckt->noise_input) {
|
||||
acReal = 1.0;
|
||||
acImag = 0.0;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
else
|
||||
if (ckt->CKTmode & MODESP) // In SP Analysis, shut down all AC sources off except the current port
|
||||
{
|
||||
// During SP load, no port must excite the circuit before the SPAN procedure.
|
||||
// They will be turned on & off in the inner cycle of SPAN.
|
||||
// Also, AC Source must be switched off (<--- Check this against ADS).
|
||||
{
|
||||
acReal = 0.0;
|
||||
acImag = 0.0;
|
||||
}
|
||||
}
|
||||
else // AC Analysis
|
||||
{
|
||||
/*
|
||||
* For AC analysis, AC mag is leading parameter for ports.
|
||||
*/
|
||||
acReal = here->VSRCacReal;
|
||||
acImag = here->VSRCacImag;
|
||||
};
|
||||
|
||||
*(here->VSRCposIbrPtr) += 1.0;
|
||||
*(here->VSRCnegIbrPtr) -= 1.0;
|
||||
*(here->VSRCibrPosPtr) += 1.0;
|
||||
*(here->VSRCibrNegPtr) -= 1.0;
|
||||
*(ckt->CKTrhs + (here->VSRCbranch)) += acReal;
|
||||
*(ckt->CKTirhs + (here->VSRCbranch)) += acImag;
|
||||
|
||||
if (here->VSRCisPort)
|
||||
{
|
||||
g0 = here->VSRCportY0;
|
||||
*(here->VSRCposPosPtr) += g0;
|
||||
*(here->VSRCnegNegPtr) += g0;
|
||||
*(here->VSRCposNegPtr) -= g0;
|
||||
*(here->VSRCnegPosPtr) -= g0;
|
||||
}
|
||||
#else
|
||||
if (ckt->CKTmode & MODEACNOISE) {
|
||||
if ((GENinstance*)here == ckt->noise_input) {
|
||||
acReal = 1.0;
|
||||
acImag = 0.0;
|
||||
}
|
||||
else {
|
||||
acReal = 0.0;
|
||||
acImag = 0.0;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
acReal = here->VSRCacReal;
|
||||
acImag = here->VSRCacImag;
|
||||
}
|
||||
|
||||
*(here->VSRCposIbrPtr) += 1.0 ;
|
||||
*(here->VSRCnegIbrPtr) -= 1.0 ;
|
||||
*(here->VSRCibrPosPtr) += 1.0 ;
|
||||
*(here->VSRCibrNegPtr) -= 1.0 ;
|
||||
*(here->VSRCposIbrPtr) += 1.0;
|
||||
*(here->VSRCnegIbrPtr) -= 1.0;
|
||||
*(here->VSRCibrPosPtr) += 1.0;
|
||||
*(here->VSRCibrNegPtr) -= 1.0;
|
||||
*(ckt->CKTrhs + (here->VSRCbranch)) += acReal;
|
||||
*(ckt->CKTirhs + (here->VSRCbranch)) += acImag;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -110,6 +110,23 @@ VSRCask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue *
|
|||
*(ckt->CKTrhsOld + here->VSRCbranch);
|
||||
}
|
||||
return(OK);
|
||||
#ifdef RFSPICE
|
||||
case VSRC_PORTNUM:
|
||||
value->rValue = here->VSRCportNum;
|
||||
return (OK);
|
||||
case VSRC_PORTZ0:
|
||||
value->rValue = here->VSRCportZ0;
|
||||
return (OK);
|
||||
case VSRC_PORTPWR:
|
||||
value->rValue = here->VSRCportPower;
|
||||
return (OK);
|
||||
case VSRC_PORTFREQ:
|
||||
value->rValue = here->VSRCportFreq;
|
||||
return (OK);
|
||||
case VSRC_PORTPHASE:
|
||||
value->rValue = here->VSRCportPhase;
|
||||
return (OK);
|
||||
#endif
|
||||
#ifdef SHARED_MODULE
|
||||
case VSRC_EXTERNAL:
|
||||
/* Don't do anything */
|
||||
|
|
|
|||
|
|
@ -32,6 +32,19 @@ typedef struct sVSRCinstance {
|
|||
const int VSRCposNode; /* number of positive node of source */
|
||||
const int VSRCnegNode; /* number of negative node of source */
|
||||
|
||||
#ifdef RFSPICE
|
||||
int VSRCresNode; /* number of internal node of source (ZSeries) */
|
||||
|
||||
double* VSRCposPosPtr; /* pointer to sparse matrix diagonal at
|
||||
* (positive,positive) */
|
||||
double* VSRCnegNegPtr; /* pointer to sparse matrix diagonal at
|
||||
* (negative,negative) */
|
||||
double* VSRCposNegPtr; /* pointer to sparse matrix offdiagonal at
|
||||
* (positive,negative) */
|
||||
double* VSRCnegPosPtr; /* pointer to sparse matrix offdiagonal at
|
||||
* (negative,positive) */
|
||||
#endif
|
||||
|
||||
int VSRCbranch; /* equation number of branch equation added for source */
|
||||
|
||||
int VSRCfunctionType; /* code number of function type for source */
|
||||
|
|
@ -77,6 +90,24 @@ typedef struct sVSRCinstance {
|
|||
unsigned VSRCdF1given :1 ; /* flag to indicate source is an f1 distortion input */
|
||||
unsigned VSRCdF2given :1 ; /* flag to indicate source is an f2 distortion input */
|
||||
unsigned VSRCrGiven :1 ; /* flag to indicate repeating pwl */
|
||||
#ifdef RFSPICE
|
||||
unsigned VSRCportNumGiven : 1; /* Flag to indicate Port Num is given */
|
||||
unsigned VSRCportZ0Given : 1; /* Flag to indicate Port Z0 is given */
|
||||
unsigned VSRCportPowerGiven : 1; /* Flag to indicate Port Power is given*/
|
||||
unsigned VSRCportFreqGiven : 1; /* Flag to indicate Port Frequency is given*/
|
||||
unsigned VSRCportPhaseGiven : 1; /* Flag to indicate Port Phase is given*/
|
||||
unsigned VSRCisPort : 1; /* Flag indicating if this is a port*/
|
||||
double VSRCVAmplitude; /* Support variable: Open Circuit Port Voltage */
|
||||
double VSRC2pifreq; /* Calculate 2*pi*freq once */
|
||||
unsigned int VSRCportNum; /* Port index*/
|
||||
double VSRCportZ0; /* Port internal impedance*/
|
||||
double VSRCportY0; /* Port internal admittance*/
|
||||
double VSRCportPower; /* Port power (W) for HB analysis */
|
||||
double VSRCportFreq; /* Port frequency */
|
||||
double VSRCportPhase; /* Port Initial Phase */
|
||||
double VSRCportPhaseRad; /* Port Initial Phase (rad) */
|
||||
double VSRCki; /* Normalization Factor for Kurosawa power wave*/
|
||||
#endif
|
||||
} VSRCinstance ;
|
||||
|
||||
|
||||
|
|
@ -105,7 +136,11 @@ enum {
|
|||
AM,
|
||||
TRNOISE,
|
||||
TRRANDOM,
|
||||
EXTERNAL,
|
||||
EXTERNAL
|
||||
#ifdef RFSPICE
|
||||
,
|
||||
PORT
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -136,6 +171,13 @@ enum {
|
|||
VSRC_AM,
|
||||
VSRC_R,
|
||||
VSRC_TD,
|
||||
#ifdef RFSPICE
|
||||
VSRC_PORTNUM,
|
||||
VSRC_PORTZ0,
|
||||
VSRC_PORTFREQ,
|
||||
VSRC_PORTPWR,
|
||||
VSRC_PORTPHASE,
|
||||
#endif
|
||||
VSRC_TRNOISE,
|
||||
VSRC_TRRANDOM,
|
||||
VSRC_EXTERNAL,
|
||||
|
|
|
|||
|
|
@ -16,3 +16,7 @@ extern int VSRCsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*);
|
|||
extern int VSRCunsetup(GENmodel*,CKTcircuit*);
|
||||
extern int VSRCpzSetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*);
|
||||
extern int VSRCtemp(GENmodel*,CKTcircuit*);
|
||||
#ifdef RFSPICE
|
||||
extern int VSRCspupdate(GENmodel*, CKTcircuit*);
|
||||
extern int VSRCgetActivePortNodes(GENmodel* inModel, CKTcircuit* ckt, int* posNodes, int* negNodes);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,10 +40,36 @@ VSRCload(GENmodel *inModel, CKTcircuit *ckt)
|
|||
for (here = VSRCinstances(model); here != NULL ;
|
||||
here=VSRCnextInstance(here)) {
|
||||
|
||||
*(here->VSRCposIbrPtr) += 1.0 ;
|
||||
*(here->VSRCnegIbrPtr) -= 1.0 ;
|
||||
*(here->VSRCibrPosPtr) += 1.0 ;
|
||||
*(here->VSRCibrNegPtr) -= 1.0 ;
|
||||
#ifndef RFSPICE
|
||||
*(here->VSRCposIbrPtr) += 1.0;
|
||||
*(here->VSRCnegIbrPtr) -= 1.0;
|
||||
*(here->VSRCibrPosPtr) += 1.0;
|
||||
*(here->VSRCibrNegPtr) -= 1.0;
|
||||
#else
|
||||
if (here->VSRCisPort)
|
||||
{
|
||||
// here->VSRCcurrent = (*(ckt->CKTrhs[Old] + (here->VSRCbranch))
|
||||
|
||||
*(here->VSRCposIbrPtr) += 1.0;
|
||||
*(here->VSRCnegIbrPtr) -= 1.0;
|
||||
*(here->VSRCibrPosPtr) += 1.0;
|
||||
*(here->VSRCibrNegPtr) -= 1.0;
|
||||
|
||||
double g0 = here->VSRCportY0;
|
||||
*(here->VSRCposPosPtr) += g0;
|
||||
*(here->VSRCnegNegPtr) += g0;
|
||||
*(here->VSRCposNegPtr) -= g0;
|
||||
*(here->VSRCnegPosPtr) -= g0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(here->VSRCposIbrPtr) += 1.0;
|
||||
*(here->VSRCnegIbrPtr) -= 1.0;
|
||||
*(here->VSRCibrPosPtr) += 1.0;
|
||||
*(here->VSRCibrNegPtr) -= 1.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( (ckt->CKTmode & (MODEDCOP | MODEDCTRANCURVE)) &&
|
||||
here->VSRCdcGiven ) {
|
||||
/* load using DC value */
|
||||
|
|
@ -367,6 +393,13 @@ VNoi3 3 0 DC 0 TRNOISE(0 0 0 0 15m 22u 50u) : generate RTS noise
|
|||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef RFSPICE
|
||||
case PORT:
|
||||
{
|
||||
value += here->VSRCVAmplitude * cos(time * here->VSRC2pifreq);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
} // switch
|
||||
} // else (line 48)
|
||||
|
|
|
|||
|
|
@ -288,7 +288,52 @@ VSRCparam(int param, IFvalue *value, GENinstance *inst, IFvalue *select)
|
|||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef RFSPICE
|
||||
/*
|
||||
* NB If either Freq or Power are given, the Function type is overridden
|
||||
* If not, we have a passive port: can be used for AC/SP/Noise but the time
|
||||
* domain value is given by preceding Function definition (if present).
|
||||
*/
|
||||
case VSRC_PORTNUM:
|
||||
{
|
||||
here->VSRCportNum = value->iValue;
|
||||
here->VSRCportNumGiven = TRUE;
|
||||
here->VSRCisPort = ((here->VSRCportNumGiven) & (here->VSRCportNum > 0) & (here->VSRCportZ0 > 0.0));
|
||||
break;
|
||||
}
|
||||
case VSRC_PORTZ0:
|
||||
{
|
||||
here->VSRCportZ0 = value->rValue;
|
||||
here->VSRCVAmplitude = sqrt(here->VSRCportPower * 4.0 * here->VSRCportZ0);
|
||||
here->VSRCisPort = ((here->VSRCportNumGiven) & (here->VSRCportNum > 0) & (here->VSRCportZ0 > 0.0));
|
||||
here->VSRCportZ0Given = TRUE;
|
||||
break;
|
||||
}
|
||||
case VSRC_PORTPWR:
|
||||
{
|
||||
here->VSRCportPower = value->rValue;
|
||||
here->VSRCportPowerGiven = TRUE;
|
||||
|
||||
here->VSRCfunctionType = PORT;
|
||||
|
||||
break;
|
||||
}
|
||||
case VSRC_PORTFREQ:
|
||||
{
|
||||
here->VSRCportFreq = value->rValue;
|
||||
here->VSRCportFreqGiven = TRUE;
|
||||
|
||||
here->VSRCfunctionType = PORT;
|
||||
|
||||
break;
|
||||
}
|
||||
case VSRC_PORTPHASE:
|
||||
{
|
||||
here->VSRCportPhase = value->rValue;
|
||||
here->VSRCportPhaseGiven = TRUE;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return(E_BADPARM);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,10 +49,47 @@ do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
|
|||
return(E_NOMEM);\
|
||||
} } while(0)
|
||||
|
||||
#ifdef RFSPICE
|
||||
if (here->VSRCisPort)
|
||||
{
|
||||
error = CKTmkVolt(ckt, &tmp, here->VSRCname, "res");
|
||||
if (error) return(error);
|
||||
here->VSRCresNode = tmp->number;
|
||||
if (ckt->CKTcopyNodesets) {
|
||||
CKTnode* tmpNode;
|
||||
IFuid tmpName;
|
||||
if (CKTinst2Node(ckt, here, 1, &tmpNode, &tmpName) == OK) {
|
||||
if (tmpNode->nsGiven) {
|
||||
tmp->nodeset = tmpNode->nodeset;
|
||||
tmp->nsGiven = tmpNode->nsGiven;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TSTALLOC(VSRCposPosPtr, VSRCposNode, VSRCposNode);
|
||||
TSTALLOC(VSRCnegNegPtr, VSRCresNode, VSRCresNode);
|
||||
TSTALLOC(VSRCposNegPtr, VSRCposNode, VSRCresNode);
|
||||
TSTALLOC(VSRCnegPosPtr, VSRCresNode, VSRCposNode);
|
||||
|
||||
TSTALLOC(VSRCposIbrPtr, VSRCresNode, VSRCbranch);
|
||||
TSTALLOC(VSRCnegIbrPtr, VSRCnegNode, VSRCbranch);
|
||||
TSTALLOC(VSRCibrNegPtr, VSRCbranch, VSRCnegNode);
|
||||
TSTALLOC(VSRCibrPosPtr, VSRCbranch, VSRCresNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
TSTALLOC(VSRCposIbrPtr, VSRCposNode, VSRCbranch);
|
||||
TSTALLOC(VSRCnegIbrPtr, VSRCnegNode, VSRCbranch);
|
||||
TSTALLOC(VSRCibrNegPtr, VSRCbranch, VSRCnegNode);
|
||||
TSTALLOC(VSRCibrPosPtr, VSRCbranch, VSRCposNode);
|
||||
}
|
||||
#else
|
||||
TSTALLOC(VSRCposIbrPtr, VSRCposNode, VSRCbranch);
|
||||
TSTALLOC(VSRCnegIbrPtr, VSRCnegNode, VSRCbranch);
|
||||
TSTALLOC(VSRCibrNegPtr, VSRCbranch, VSRCnegNode);
|
||||
TSTALLOC(VSRCibrPosPtr, VSRCbranch, VSRCposNode);
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
return(OK);
|
||||
|
|
@ -73,6 +110,12 @@ VSRCunsetup(GENmodel *inModel, CKTcircuit *ckt)
|
|||
if (here->VSRCbranch > 0)
|
||||
CKTdltNNum(ckt, here->VSRCbranch);
|
||||
here->VSRCbranch = 0;
|
||||
#ifdef RFSPICE
|
||||
if ((here->VSRCresNode > 0) & (here->VSRCisPort))
|
||||
CKTdltNNum(ckt, here->VSRCresNode);
|
||||
here->VSRCresNode = 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,12 @@ VSRCtemp(GENmodel *inModel, CKTcircuit *ckt)
|
|||
|
||||
NG_IGNORE(ckt);
|
||||
|
||||
#ifdef RFSPICE
|
||||
ckt->CKTportCount = 0;
|
||||
unsigned int* portIDs;
|
||||
unsigned int prevPort;
|
||||
#endif
|
||||
|
||||
/* loop through all the voltage source models */
|
||||
for( ; model != NULL; model = VSRCnextModel(model)) {
|
||||
|
||||
|
|
@ -50,8 +56,92 @@ VSRCtemp(GENmodel *inModel, CKTcircuit *ckt)
|
|||
radians = here->VSRCacPhase * M_PI / 180.0;
|
||||
here->VSRCacReal = here->VSRCacMag * cos(radians);
|
||||
here->VSRCacImag = here->VSRCacMag * sin(radians);
|
||||
#ifdef RFSPICE
|
||||
// To have a power port, we need to define its index value
|
||||
// AND a proper port impedance
|
||||
if (here->VSRCportNumGiven)
|
||||
{
|
||||
if (!here->VSRCportZ0Given)
|
||||
here->VSRCportZ0 = 50.0;
|
||||
|
||||
here->VSRCisPort = here->VSRCportZ0 > 0.0;
|
||||
}
|
||||
else
|
||||
here->VSRCisPort = FALSE;
|
||||
|
||||
if (here->VSRCisPort)
|
||||
{
|
||||
if (!here->VSRCportFreqGiven)
|
||||
here->VSRCportFreq = 1.0e9;
|
||||
if (!here->VSRCportPowerGiven)
|
||||
here->VSRCportPower = 0.001; // 1mW (0dBm) default RF power
|
||||
if (!here->VSRCportPhaseGiven)
|
||||
here->VSRCportPhase = 0.0;
|
||||
|
||||
here->VSRC2pifreq = 2.0 * M_PI * here->VSRCportFreq;
|
||||
here->VSRCVAmplitude = sqrt(here->VSRCportPower * 4.0 * here->VSRCportZ0);
|
||||
here->VSRCportY0 = 1.0 / here->VSRCportZ0;
|
||||
here->VSRCportPhaseRad = here->VSRCportPhase * M_PI / 180.0;
|
||||
here->VSRCki = 0.5 / sqrt(here->VSRCportZ0);
|
||||
|
||||
ckt->CKTportCount++;
|
||||
ckt->CKTrfPorts = (GENinstance**)TREALLOC(GENinstance*, ckt->CKTrfPorts, ckt->CKTportCount);
|
||||
ckt->CKTrfPorts[ckt->CKTportCount - 1] = (GENinstance*)here;
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RFSPICE
|
||||
portIDs = (unsigned int*)malloc(ckt->CKTportCount * sizeof(unsigned int));
|
||||
if (portIDs == NULL)
|
||||
return (E_NOMEM);
|
||||
|
||||
unsigned int curport = 0;
|
||||
|
||||
// Sweep thru all ports to check for correct indexing
|
||||
|
||||
/* loop through all the voltage source models */
|
||||
for (model = (VSRCmodel*)inModel; 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) continue;
|
||||
|
||||
unsigned int curId = here->VSRCportNum;
|
||||
// If port Index > port Count then we have either a duplicate number or a missing number
|
||||
if (curId > ckt->CKTportCount)
|
||||
{
|
||||
SPfrontEnd->IFerrorf(ERR_FATAL,
|
||||
"%s: incorrect port ordering",
|
||||
here->VSRCname);
|
||||
free(portIDs);
|
||||
return (E_BADPARM);
|
||||
}
|
||||
|
||||
|
||||
// Check if we have already defined the "curId"
|
||||
for (prevPort = 0; prevPort < curport; prevPort++)
|
||||
{
|
||||
if (portIDs[prevPort] == curId)
|
||||
{
|
||||
SPfrontEnd->IFerrorf(ERR_FATAL,
|
||||
"%s: duplicate port Index",
|
||||
here->VSRCname);
|
||||
free(portIDs);
|
||||
return (E_BADPARM);
|
||||
}
|
||||
}
|
||||
|
||||
portIDs[curport++] = curId;
|
||||
}
|
||||
}
|
||||
|
||||
free(portIDs);
|
||||
|
||||
#endif
|
||||
return(OK);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -614,6 +614,106 @@ dot_pss(char *line, void *ckt, INPtables *tab, struct card *current,
|
|||
/* SP */
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef RFSPICE
|
||||
/* S Parameter Analyis */
|
||||
static int
|
||||
dot_sp(char* line, void* ckt, INPtables* tab, struct card* current,
|
||||
void* task, void* gnode, JOB* foo)
|
||||
{
|
||||
int error; /* error code temporary */
|
||||
IFvalue ptemp; /* a value structure to package resistance into */
|
||||
IFvalue* parm; /* a pointer to a value struct for function returns */
|
||||
int which; /* which analysis we are performing */
|
||||
char* steptype; /* ac analysis, type of stepping function */
|
||||
|
||||
NG_IGNORE(gnode);
|
||||
|
||||
/* .ac {DEC OCT LIN} NP FSTART FSTOP */
|
||||
which = ft_find_analysis("SP");
|
||||
if (which == -1) {
|
||||
LITERR("S-Params analysis unsupported.\n");
|
||||
return (0);
|
||||
}
|
||||
IFC(newAnalysis, (ckt, which, "SP Analysis", &foo, task));
|
||||
INPgetTok(&line, &steptype, 1); /* get DEC, OCT, or LIN */
|
||||
ptemp.iValue = 1;
|
||||
GCA(INPapName, (ckt, which, foo, steptype, &ptemp));
|
||||
tfree(steptype);
|
||||
parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* number of points */
|
||||
GCA(INPapName, (ckt, which, foo, "numsteps", parm));
|
||||
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstart */
|
||||
GCA(INPapName, (ckt, which, foo, "start", parm));
|
||||
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* fstop */
|
||||
GCA(INPapName, (ckt, which, foo, "stop", parm));
|
||||
parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* fstop */
|
||||
GCA(INPapName, (ckt, which, foo, "donoise", parm));
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef WITH_HB
|
||||
/* HB */
|
||||
static int
|
||||
dot_hb(char* line, void* ckt, INPtables* tab, struct card* current,
|
||||
void* task, void* gnode, JOB* foo)
|
||||
{
|
||||
int error; /* error code temporary */
|
||||
IFvalue ptemp; /* a value structure to package resistance into */
|
||||
IFvalue* parm; /* a pointer to a value struct for function returns */
|
||||
char* nname; /* the oscNode name */
|
||||
CKTnode* nnode; /* the oscNode node */
|
||||
int which; /* which analysis we are performing */
|
||||
char* word; /* something to stick a word of input into */
|
||||
|
||||
NG_IGNORE(gnode);
|
||||
|
||||
/* .pss Fguess StabTime OscNode <UIC>*/
|
||||
which = ft_find_analysis("PSS");
|
||||
if (which == -1) {
|
||||
LITERR("Periodic steady state analysis unsupported.\n");
|
||||
return (0);
|
||||
}
|
||||
IFC(newAnalysis, (ckt, which, "Harmonic Balance State Analysis", &foo, task));
|
||||
|
||||
parm = INPgetValue(ckt, &line, IF_REALVEC, tab); /* Fguess */
|
||||
GCA(INPapName, (ckt, which, foo, "freq", parm));
|
||||
|
||||
parm = INPgetValue(ckt, &line, IF_INTVEC, tab); /* StabTime */
|
||||
GCA(INPapName, (ckt, which, foo, "harmonics", parm));
|
||||
|
||||
INPgetNetTok(&line, &nname, 0);
|
||||
INPtermInsert(ckt, &nname, tab, &nnode);
|
||||
ptemp.nValue = nnode;
|
||||
GCA(INPapName, (ckt, which, foo, "oscnode", &ptemp)); /* OscNode given as string */
|
||||
|
||||
parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* PSS points */
|
||||
GCA(INPapName, (ckt, which, foo, "points", parm));
|
||||
|
||||
parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* PSS harmonics */
|
||||
GCA(INPapName, (ckt, which, foo, "harmonics", parm));
|
||||
|
||||
parm = INPgetValue(ckt, &line, IF_INTEGER, tab); /* SC iterations */
|
||||
GCA(INPapName, (ckt, which, foo, "sc_iter", parm));
|
||||
|
||||
parm = INPgetValue(ckt, &line, IF_REAL, tab); /* Steady coefficient */
|
||||
GCA(INPapName, (ckt, which, foo, "steady_coeff", parm));
|
||||
|
||||
if (*line) {
|
||||
INPgetTok(&line, &word, 1); /* uic? */
|
||||
if (strcmp(word, "uic") == 0) {
|
||||
ptemp.iValue = 1;
|
||||
GCA(INPapName, (ckt, which, foo, "uic", &ptemp));
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Error: unknown parameter %s on .pss - ignored\n", word);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
static int
|
||||
dot_options(char *line, CKTcircuit *ckt, INPtables *tab, struct card *current,
|
||||
TSKtask *task, CKTnode *gnode, JOB *foo)
|
||||
|
|
@ -699,6 +799,20 @@ INP2dot(CKTcircuit *ckt, INPtables *tab, struct card *current, TSKtask *task, CK
|
|||
rtn = dot_pss(line, ckt, tab, current, task, gnode, foo);
|
||||
goto quit;
|
||||
/* SP */
|
||||
#endif
|
||||
#ifdef RFSPICE
|
||||
}
|
||||
else if ((strcmp(token, ".sp") == 0)) {
|
||||
rtn = dot_sp(line, ckt, tab, current, task, gnode, foo);
|
||||
goto quit;
|
||||
/* SP */
|
||||
#ifdef WITH_HB
|
||||
}
|
||||
else if ((strcmp(token, ".hb") == 0)) {
|
||||
rtn = dot_hb(line, ckt, tab, current, task, gnode, foo);
|
||||
goto quit;
|
||||
/* SP */
|
||||
#endif
|
||||
#endif
|
||||
} else if ((strcmp(token, ".subckt") == 0) ||
|
||||
(strcmp(token, ".ends") == 0)) {
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@
|
|||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\spicelib\parser;..\src\include;..\src\include\cppduals;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONFIG64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>RFSPICE;_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONFIG64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
|
|
@ -363,7 +363,7 @@
|
|||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<AdditionalIncludeDirectories>..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\spicelib\parser;..\src\include;..\src\include\cppduals;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONFIG64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>RFSPICE;_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONFIG64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
|
|
@ -511,7 +511,7 @@
|
|||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\spicelib\parser;..\src\include;..\src\include\cppduals;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONSOLE;CONFIG64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>RFSPICE;_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);NGDEBUG;CONSOLE;CONFIG64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
|
|
@ -563,7 +563,7 @@
|
|||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<AdditionalIncludeDirectories>..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\spicelib\parser;..\src\include;..\src\include\cppduals;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;CONFIG64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>RFSPICE;_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;CONFIG64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
|
|
@ -669,7 +669,7 @@
|
|||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<AdditionalIncludeDirectories>..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\spicelib\parser;..\src\include;..\src\include\cppduals;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);USE_OMP;CONFIG64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>RFSPICE;_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);USE_OMP;CONFIG64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
|
|
@ -778,7 +778,7 @@
|
|||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<AdditionalIncludeDirectories>..\src\maths\poly;..\src\frontend;..\src\spicelib\devices;tmp-bison;src\include;..\src\spicelib\parser;..\src\include;..\src\include\cppduals;.;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;CONFIG64;USE_OMP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>RFSPICE;_CRT_SECURE_NO_DEPRECATE;SIMULATOR;XSPICE;_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion);CONSOLE;CONFIG64;USE_OMP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ExceptionHandling>
|
||||
</ExceptionHandling>
|
||||
|
|
@ -952,6 +952,7 @@
|
|||
<ClInclude Include="..\src\include\ngspice\cmconstants.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\cmproto.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\cmtypes.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\spdefs.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\wincolornames.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\compatmode.h" />
|
||||
<ClInclude Include="..\src\include\ngspice\complex.h" />
|
||||
|
|
@ -1065,6 +1066,7 @@
|
|||
<ClInclude Include="..\src\maths\cmaths\cmath2.h" />
|
||||
<ClInclude Include="..\src\maths\cmaths\cmath3.h" />
|
||||
<ClInclude Include="..\src\maths\cmaths\cmath4.h" />
|
||||
<ClInclude Include="..\src\maths\dense\dense.h" />
|
||||
<ClInclude Include="..\src\maths\fft\fftlib.h" />
|
||||
<ClInclude Include="..\src\maths\fft\matlib.h" />
|
||||
<ClInclude Include="..\src\maths\misc\accuracy.h" />
|
||||
|
|
@ -1562,6 +1564,7 @@
|
|||
<ClCompile Include="..\src\maths\cmaths\cmath2.c" />
|
||||
<ClCompile Include="..\src\maths\cmaths\cmath3.c" />
|
||||
<ClCompile Include="..\src\maths\cmaths\cmath4.c" />
|
||||
<ClCompile Include="..\src\maths\dense\dense.c" />
|
||||
<ClCompile Include="..\src\maths\deriv\atander.c" />
|
||||
<ClCompile Include="..\src\maths\deriv\cosderiv.c" />
|
||||
<ClCompile Include="..\src\maths\deriv\cubeder.c" />
|
||||
|
|
@ -1682,6 +1685,7 @@
|
|||
<ClCompile Include="..\src\spicelib\analysis\cktsetup.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\cktsgen.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\cktsopt.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\cktspdum.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\ckttemp.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\cktterr.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\ckttroub.c" />
|
||||
|
|
@ -1715,6 +1719,9 @@
|
|||
<ClCompile Include="..\src\spicelib\analysis\pzsetp.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\sensaskq.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\senssetp.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\span.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\spaskq.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\spsetp.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\tfanal.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\tfaskq.c" />
|
||||
<ClCompile Include="..\src\spicelib\analysis\tfsetp.c" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue