Patch to avoid false reads and writes due to inconsitent
structs SPAN and NOISEAN. Prevent using non-initialized variables.
This commit is contained in:
parent
e31d6a3c1c
commit
744eaece69
|
|
@ -15,12 +15,12 @@ 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.
|
||||
*/
|
||||
/*
|
||||
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/cktdefs.h"
|
||||
|
|
@ -28,20 +28,17 @@ Outside RFSPICE declaration, code is legacy NGSPICE code.
|
|||
#include "ngspice/noisedef.h"
|
||||
|
||||
#ifdef RFSPICE
|
||||
#include "../maths/dense/dense.h"
|
||||
#include "../maths/dense/denseinlines.h"
|
||||
|
||||
extern CMat* eyem;
|
||||
extern CMat* zref;
|
||||
extern CMat* gn;
|
||||
extern CMat* gninv;
|
||||
extern CMat* vNoise;
|
||||
extern CMat* iNoise;
|
||||
|
||||
#include "../../maths/dense/denseinlines.h"
|
||||
#endif
|
||||
|
||||
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)
|
||||
|
|
@ -51,15 +48,21 @@ NevalSrc (double *noise, double *lnNoise, CKTcircuit *ckt, int type, int node1,
|
|||
switch (type) {
|
||||
|
||||
case SHOTNOISE:
|
||||
inoise = 2 * CHARGE * fabs(param); /* param is the dc current in a semiconductor */
|
||||
inoise = 2 * CHARGE * fabs(param); /* param is the dc current in a semiconductor */
|
||||
*noise = inoise;
|
||||
*lnNoise = log(MAX(*noise, N_MINLOG));
|
||||
break;
|
||||
|
||||
case THERMNOISE:
|
||||
inoise = 4 * CONSTboltz * ckt->CKTtemp * param; /* param is the conductance of a resistor */
|
||||
inoise = 4 * CONSTboltz * ckt->CKTtemp * param; /* param is the conductance of a resistor */
|
||||
*noise = inoise;
|
||||
*lnNoise = log(MAX(*noise, N_MINLOG));
|
||||
break;
|
||||
|
||||
case N_GAIN:
|
||||
inoise = 0.0;
|
||||
*noise = cmodu(csubco(ckt->CKTadjointRHS->d[0][node1], ckt->CKTadjointRHS->d[0][node2]));
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
|
@ -95,19 +98,19 @@ NevalSrc (double *noise, double *lnNoise, CKTcircuit *ckt, int type, int node1,
|
|||
double imagVal;
|
||||
double gain;
|
||||
|
||||
realVal = ckt->CKTrhs [node1] - ckt->CKTrhs [node2];
|
||||
imagVal = ckt->CKTirhs [node1] - ckt->CKTirhs [node2];
|
||||
gain = (realVal*realVal) + (imagVal*imagVal);
|
||||
realVal = ckt->CKTrhs[node1] - ckt->CKTrhs[node2];
|
||||
imagVal = ckt->CKTirhs[node1] - ckt->CKTirhs[node2];
|
||||
gain = (realVal * realVal) + (imagVal * imagVal);
|
||||
switch (type) {
|
||||
|
||||
case SHOTNOISE:
|
||||
*noise = gain * 2 * CHARGE * fabs(param); /* param is the dc current in a semiconductor */
|
||||
*lnNoise = log( MAX(*noise,N_MINLOG) );
|
||||
*lnNoise = log(MAX(*noise, N_MINLOG));
|
||||
break;
|
||||
|
||||
case THERMNOISE:
|
||||
*noise = gain * 4 * CONSTboltz * ckt->CKTtemp * param; /* param is the conductance of a resistor */
|
||||
*lnNoise = log( MAX(*noise,N_MINLOG) );
|
||||
*lnNoise = log(MAX(*noise, N_MINLOG));
|
||||
break;
|
||||
|
||||
case N_GAIN:
|
||||
|
|
@ -131,22 +134,22 @@ NevalSrc (double *noise, double *lnNoise, CKTcircuit *ckt, int type, int node1,
|
|||
* "case by case" basis. What we CAN provide, though, is the noise
|
||||
* gain associated with the 1/f source.
|
||||
*/
|
||||
/* Modified by Darsen Lu for BSIM4 tnoiMod=2 10/10/2010
|
||||
*/
|
||||
/* Modified by Darsen Lu for BSIM4 tnoiMod=2 10/10/2010
|
||||
*/
|
||||
|
||||
void
|
||||
NevalSrc2 (
|
||||
double *noise,
|
||||
double *lnNoise,
|
||||
CKTcircuit *ckt,
|
||||
int type,
|
||||
int node1,
|
||||
int node2,
|
||||
double param1,
|
||||
int node3,
|
||||
int node4,
|
||||
double param2,
|
||||
double phi21) /* Phase of signal 2 relative to signal 1 */
|
||||
NevalSrc2(
|
||||
double* noise,
|
||||
double* lnNoise,
|
||||
CKTcircuit* ckt,
|
||||
int type,
|
||||
int node1,
|
||||
int node2,
|
||||
double param1,
|
||||
int node3,
|
||||
int node4,
|
||||
double param2,
|
||||
double phi21) /* Phase of signal 2 relative to signal 1 */
|
||||
|
||||
{
|
||||
double realVal1, imagVal1;
|
||||
|
|
@ -159,10 +162,10 @@ double phi21) /* Phase of signal 2 relative to signal 1 */
|
|||
{
|
||||
|
||||
double knoise = 0.0;
|
||||
|
||||
|
||||
T0 = sqrt(param1);
|
||||
T1 = sqrt(param2);
|
||||
cplx cfact;
|
||||
cplx cfact;
|
||||
cfact.re = cos(phi21);
|
||||
cfact.im = sin(phi21);
|
||||
|
||||
|
|
@ -171,14 +174,20 @@ double phi21) /* Phase of signal 2 relative to signal 1 */
|
|||
|
||||
case SHOTNOISE:
|
||||
knoise = 2 * CHARGE; /* param is the dc current in a semiconductor */
|
||||
*noise = knoise;
|
||||
*lnNoise = log(MAX(*noise, N_MINLOG));
|
||||
break;
|
||||
|
||||
case THERMNOISE:
|
||||
knoise = 4 * CONSTboltz * ckt->CKTtemp; /* param is the conductance of a resistor */
|
||||
// For this simulation we are not collecting any statistics on output nodes. Force noise to 0
|
||||
*noise = knoise;
|
||||
*lnNoise = log(MAX(*noise, N_MINLOG));
|
||||
break;
|
||||
|
||||
case N_GAIN:
|
||||
knoise = 0.0;
|
||||
*noise = cmodu(csubco(ckt->CKTadjointRHS->d[0][node1], ckt->CKTadjointRHS->d[0][node2]));
|
||||
break;
|
||||
|
||||
}
|
||||
|
|
@ -187,7 +196,7 @@ double phi21) /* Phase of signal 2 relative to signal 1 */
|
|||
// 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 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);
|
||||
|
|
@ -217,27 +226,27 @@ double phi21) /* Phase of signal 2 relative to signal 1 */
|
|||
#endif
|
||||
|
||||
|
||||
realVal1 = ckt->CKTrhs [node1] - ckt->CKTrhs [node2];
|
||||
imagVal1 = ckt->CKTirhs [node1] - ckt->CKTirhs [node2];
|
||||
realVal2 = ckt->CKTrhs [node3] - ckt->CKTrhs [node4];
|
||||
imagVal2 = ckt->CKTirhs [node3] - ckt->CKTirhs [node4];
|
||||
realVal1 = ckt->CKTrhs[node1] - ckt->CKTrhs[node2];
|
||||
imagVal1 = ckt->CKTirhs[node1] - ckt->CKTirhs[node2];
|
||||
realVal2 = ckt->CKTrhs[node3] - ckt->CKTrhs[node4];
|
||||
imagVal2 = ckt->CKTirhs[node3] - ckt->CKTirhs[node4];
|
||||
T0 = sqrt(param1);
|
||||
T1 = sqrt(param2);
|
||||
T2 = T1 * cos(phi21);
|
||||
T3 = T1 * sin(phi21);
|
||||
realOut = T0 * realVal1 + T2 * realVal2 - T3 * imagVal2;
|
||||
imagOut = T0 * imagVal1 + T2 * imagVal2 + T3 * realVal2;
|
||||
param_gain = (realOut*realOut) + (imagOut*imagOut);
|
||||
param_gain = (realOut * realOut) + (imagOut * imagOut);
|
||||
switch (type) {
|
||||
|
||||
case SHOTNOISE:
|
||||
*noise = 2.0 * CHARGE * fabs(param_gain); /* param is the dc current in a semiconductor */
|
||||
*lnNoise = log( MAX(*noise,N_MINLOG) );
|
||||
*lnNoise = log(MAX(*noise, N_MINLOG));
|
||||
break;
|
||||
|
||||
case THERMNOISE:
|
||||
*noise = 4.0 * CONSTboltz * ckt->CKTtemp * param_gain; /* param is the conductance of a resistor */
|
||||
*lnNoise = log( MAX(*noise,N_MINLOG) );
|
||||
*lnNoise = log(MAX(*noise, N_MINLOG));
|
||||
break;
|
||||
|
||||
case N_GAIN:
|
||||
|
|
@ -257,12 +266,14 @@ will implement dtemp feature.
|
|||
*/
|
||||
|
||||
void
|
||||
NevalSrcInstanceTemp (double *noise, double *lnNoise, CKTcircuit *ckt, int type,
|
||||
int node1, int node2, double param, double param2)
|
||||
NevalSrcInstanceTemp(double* noise, double* lnNoise, CKTcircuit* ckt, int type,
|
||||
int node1, int node2, double param, double param2)
|
||||
{
|
||||
|
||||
|
||||
#ifdef RFSPICE
|
||||
// For this simulation we are not collecting any statistics on output nodes. Force noise to 0
|
||||
|
||||
if (ckt->CKTcurrentAnalysis & DOING_SP)
|
||||
{
|
||||
double inoise = 0.0;
|
||||
|
|
@ -271,14 +282,21 @@ NevalSrcInstanceTemp (double *noise, double *lnNoise, CKTcircuit *ckt, int type,
|
|||
|
||||
case SHOTNOISE:
|
||||
inoise = 2 * CHARGE * fabs(param); /* param is the dc current in a semiconductor */
|
||||
// For this simulation we are not collecting any statistics on output nodes. Force noise to 0
|
||||
*noise = inoise;
|
||||
*lnNoise = log(MAX(*noise, N_MINLOG));
|
||||
break;
|
||||
|
||||
case THERMNOISE:
|
||||
inoise = 4.0 *CONSTboltz* (ckt->CKTtemp + param2)* param; /* param is the conductance of a resistor */
|
||||
inoise = 4.0 * CONSTboltz * (ckt->CKTtemp + param2) * param; /* param is the conductance of a resistor */
|
||||
// For this simulation we are not collecting any statistics on output nodes. Force noise to 0
|
||||
*noise = inoise;
|
||||
*lnNoise = log(MAX(*noise, N_MINLOG));
|
||||
break;
|
||||
|
||||
case N_GAIN:
|
||||
inoise = 0.0;
|
||||
*noise = cmodu(csubco(ckt->CKTadjointRHS->d[0][node1], ckt->CKTadjointRHS->d[0][node2]));
|
||||
return;
|
||||
|
||||
}
|
||||
|
|
@ -286,7 +304,7 @@ NevalSrcInstanceTemp (double *noise, double *lnNoise, CKTcircuit *ckt, int type,
|
|||
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);
|
||||
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++)
|
||||
{
|
||||
|
|
@ -313,20 +331,20 @@ NevalSrcInstanceTemp (double *noise, double *lnNoise, CKTcircuit *ckt, int type,
|
|||
double realVal;
|
||||
double imagVal;
|
||||
double gain;
|
||||
realVal = ckt->CKTrhs [node1] - ckt->CKTrhs [node2];
|
||||
imagVal = ckt->CKTirhs [node1] - ckt->CKTirhs [node2];
|
||||
gain = (realVal*realVal) + (imagVal*imagVal);
|
||||
realVal = ckt->CKTrhs[node1] - ckt->CKTrhs[node2];
|
||||
imagVal = ckt->CKTirhs[node1] - ckt->CKTirhs[node2];
|
||||
gain = (realVal * realVal) + (imagVal * imagVal);
|
||||
switch (type) {
|
||||
|
||||
case SHOTNOISE:
|
||||
*noise = gain * 2 * CHARGE * fabs(param); /* param is the dc current in a semiconductor */
|
||||
*lnNoise = log( MAX(*noise,N_MINLOG) );
|
||||
*lnNoise = log(MAX(*noise, N_MINLOG));
|
||||
break;
|
||||
|
||||
case THERMNOISE:
|
||||
*noise = gain * 4 * CONSTboltz * (ckt->CKTtemp + param2) /* param2 is the instance temperature difference */
|
||||
* param; /* param is the conductance of a resistor */
|
||||
*lnNoise = log( MAX(*noise,N_MINLOG) );
|
||||
* param; /* param is the conductance of a resistor */
|
||||
*lnNoise = log(MAX(*noise, N_MINLOG));
|
||||
break;
|
||||
|
||||
case N_GAIN:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
****
|
||||
****
|
||||
* Alessio Cacciatori 2021
|
||||
****
|
||||
*/
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
#ifdef XSPICE
|
||||
#include "ngspice/evt.h"
|
||||
#include "ngspice/enh.h"
|
||||
/* gtri - add - wbk - 12/19/90 - Add headers */
|
||||
/* gtri - add - wbk - 12/19/90 - Add headers */
|
||||
#include "ngspice/mif.h"
|
||||
#include "ngspice/evtproto.h"
|
||||
#include "ngspice/ipctiein.h"
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
|
||||
|
||||
|
||||
#define INIT_STATS() \
|
||||
do { \
|
||||
startTime = SPfrontEnd->IFseconds(); \
|
||||
|
|
@ -68,19 +69,17 @@ double Fmin = 0;
|
|||
double refPortY0;
|
||||
|
||||
int
|
||||
CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data)
|
||||
CKTspnoise(CKTcircuit* ckt, int mode, int operation, Ndata* data, NOISEAN* noisean)
|
||||
{
|
||||
NOISEAN* job = (NOISEAN*)ckt->CKTcurJob;
|
||||
// Temporarily assign current job as a (dummy) NOISEAN analysis
|
||||
// This is needed to avoid
|
||||
SPAN* oldJob = (SPAN*)ckt->CKTcurJob;
|
||||
ckt->CKTcurJob = (JOB*)noisean;
|
||||
|
||||
double outNdens;
|
||||
int i;
|
||||
#ifdef LEGACY
|
||||
IFvalue outData; /* output variable (points to list of outputs)*/
|
||||
IFvalue refVal; /* reference variable (always 0)*/
|
||||
#endif
|
||||
int error;
|
||||
outNdens = 0.0;
|
||||
job->NStpsSm = 1;
|
||||
|
||||
/* let each device decide how many and what type of noise sources it has */
|
||||
|
||||
|
|
@ -91,7 +90,11 @@ CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data)
|
|||
if (a == 0) a = 2;
|
||||
error = DEVices[i]->DEVnoise(mode, operation, ckt->CKThead[i],
|
||||
ckt, data, &outNdens);
|
||||
if (error) return (error);
|
||||
if (error)
|
||||
{
|
||||
ckt->CKTcurJob = (JOB*)oldJob;
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -107,17 +110,17 @@ CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data)
|
|||
{
|
||||
|
||||
// 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);
|
||||
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) ;
|
||||
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]),
|
||||
|
|
@ -137,50 +140,11 @@ CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data)
|
|||
Fmin = 10.0 * log10(Fmin);
|
||||
NF = 10.0 * log10(NF);
|
||||
}
|
||||
|
||||
|
||||
freecmat(tempCy);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef LEGACY
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
break;
|
||||
|
||||
case N_CLOSE:
|
||||
SPfrontEnd->OUTendPlot(data->NplotPtr);
|
||||
|
|
@ -194,14 +158,16 @@ CKTspnoise(CKTcircuit * ckt, int mode, int operation, Ndata * data)
|
|||
break;
|
||||
|
||||
default:
|
||||
ckt->CKTcurJob = (JOB*)oldJob;
|
||||
return (E_INTERN);
|
||||
}
|
||||
ckt->CKTcurJob = (JOB*)oldJob;
|
||||
return (OK);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NInspIter(CKTcircuit * ckt, VSRCinstance* port)
|
||||
NInspIter(CKTcircuit* ckt, VSRCinstance* port)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -273,7 +239,7 @@ int initSPmatrix(CKTcircuit* ckt, int doNoise)
|
|||
return (E_NOMEM);
|
||||
|
||||
// Now that we have found the model, we may init the Zref and Gn ports
|
||||
if (ckt->CKTVSRCid>=0)
|
||||
if (ckt->CKTVSRCid >= 0)
|
||||
VSRCspinit(ckt->CKThead[ckt->CKTVSRCid], ckt, zref, gn, gninv);
|
||||
|
||||
if (doNoise)
|
||||
|
|
@ -284,7 +250,7 @@ int initSPmatrix(CKTcircuit* ckt, int doNoise)
|
|||
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
|
||||
// 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);
|
||||
|
|
@ -337,12 +303,32 @@ void deleteSPmatrix(CKTcircuit* ckt)
|
|||
ckt->CKTadjointRHS = NULL;
|
||||
}
|
||||
|
||||
|
||||
NOISEAN* SPcreateNoiseAnalysys(CKTcircuit* ckt)
|
||||
{
|
||||
NOISEAN* internalNoiseAN = TMALLOC(NOISEAN, 1);
|
||||
if (internalNoiseAN==NULL) return NULL;
|
||||
SPAN* span = (SPAN*)ckt->CKTcurJob;
|
||||
|
||||
internalNoiseAN->NstartFreq = span->SPstartFreq;
|
||||
internalNoiseAN->NstopFreq = span->SPstopFreq;
|
||||
internalNoiseAN->NStpsSm = 1; // Force to output noise at every freq step
|
||||
internalNoiseAN->JOBnextJob = NULL;
|
||||
internalNoiseAN->JOBtype = span->JOBtype;
|
||||
internalNoiseAN->JOBname = NULL;
|
||||
internalNoiseAN->NfreqDelta = span->SPfreqDelta;
|
||||
internalNoiseAN->NstpType = span->SPstepType;
|
||||
internalNoiseAN->NnumSteps = span->SPnumberSteps;
|
||||
return internalNoiseAN;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
SPan(CKTcircuit *ckt, int restart)
|
||||
SPan(CKTcircuit* ckt, int restart)
|
||||
{
|
||||
|
||||
|
||||
SPAN *job = (SPAN *) ckt->CKTcurJob;
|
||||
SPAN* job = (SPAN*)ckt->CKTcurJob;
|
||||
|
||||
double freq;
|
||||
double freqTol; /* tolerence parameter for finding final frequency */
|
||||
|
|
@ -354,17 +340,22 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
int error;
|
||||
int numNames;
|
||||
int i;
|
||||
IFuid *nameList; /* va: tmalloc'ed list of names */
|
||||
IFuid* nameList; /* va: tmalloc'ed list of names */
|
||||
IFuid freqUid;
|
||||
static runDesc *spPlot = NULL;
|
||||
runDesc *plot = NULL;
|
||||
static runDesc* spPlot = NULL;
|
||||
runDesc* plot = NULL;
|
||||
|
||||
double* rhswoPorts = NULL;
|
||||
double* irhswoPorts = NULL;
|
||||
|
||||
NOISEAN* internalNoiseAN = NULL;
|
||||
// Noise analysis is performed at each freq of the SP Analysis
|
||||
// A temporary dummy job is therefore created
|
||||
|
||||
|
||||
/* variable must be static, for continuation of interrupted (Ctrl-C),
|
||||
longer lasting noise anlysis */
|
||||
static Ndata* data=NULL;
|
||||
static Ndata* data = NULL;
|
||||
if (job->SPdoNoise)
|
||||
{
|
||||
data = TMALLOC(Ndata, 1);
|
||||
|
|
@ -380,18 +371,18 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
|
||||
|
||||
#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 */
|
||||
|
||||
/* Tell the beginPlot routine what mode we're in */
|
||||
/* Tell the beginPlot routine what mode we're in */
|
||||
|
||||
// For now, let's keep this as IPC_ANAL_AC (TBD)
|
||||
// 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 */
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
/* start at beginning */
|
||||
|
|
@ -436,7 +427,7 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
if (job->SPdoNoise)
|
||||
{
|
||||
data->lstFreq = job->SPstartFreq - 1;
|
||||
data->delFreq = 1.0;
|
||||
data->delFreq = 0.0;
|
||||
}
|
||||
|
||||
#ifdef XSPICE
|
||||
|
|
@ -452,7 +443,7 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
EVTop_save(ckt, MIF_TRUE, 0.0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#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,
|
||||
|
|
@ -598,26 +589,27 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
|
||||
|
||||
|
||||
tfree(nameList);
|
||||
if(error) return(error);
|
||||
tfree(nameList);
|
||||
if (error) return(error);
|
||||
|
||||
if (job->SPstepType != LINEAR) {
|
||||
SPfrontEnd->OUTattributes (spPlot, NULL, OUT_SCALE_LOG, NULL);
|
||||
}
|
||||
SPfrontEnd->OUTattributes(spPlot, NULL, OUT_SCALE_LOG, NULL);
|
||||
}
|
||||
freq = job->SPstartFreq;
|
||||
|
||||
} else { /* continue previous analysis */
|
||||
}
|
||||
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*/
|
||||
/* fix resume? saj, indeed !*/
|
||||
error = SPfrontEnd->OUTpBeginPlot(NULL, NULL,
|
||||
NULL,
|
||||
NULL, 0,
|
||||
666, NULL, 666,
|
||||
&spPlot);
|
||||
/* saj*/
|
||||
}
|
||||
|
||||
|
||||
switch (job->SPstepType) {
|
||||
case DECADE:
|
||||
case OCTAVE:
|
||||
|
|
@ -633,14 +625,14 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - add - wbk - 12/19/90 - Set anal_init and anal_type */
|
||||
/* 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 */
|
||||
/* gtri - end - wbk */
|
||||
#endif
|
||||
|
||||
INIT_STATS();
|
||||
|
|
@ -651,13 +643,22 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
return (E_NOMEM);
|
||||
|
||||
// Create Noise UID, if needed
|
||||
|
||||
if (job->SPdoNoise)
|
||||
{
|
||||
internalNoiseAN = SPcreateNoiseAnalysys(ckt);
|
||||
if (internalNoiseAN == NULL)
|
||||
return (E_NOMEM);
|
||||
|
||||
data->numPlots = 0; /* we don't have any plots yet */
|
||||
error = CKTspnoise(ckt, N_DENS, N_OPEN, data);
|
||||
if (error) return(error);
|
||||
data->freq = freq;
|
||||
|
||||
|
||||
error = CKTspnoise(ckt, N_DENS, N_OPEN, data, internalNoiseAN);
|
||||
|
||||
if (error) {
|
||||
tfree(internalNoiseAN);
|
||||
return(error);
|
||||
}
|
||||
}
|
||||
|
||||
ckt->CKTactivePort = 0;
|
||||
|
|
@ -688,7 +689,7 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
EVTop_save(ckt, MIF_TRUE, 0.0);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
// If no event-driven instances, do what SPICE normally does
|
||||
error = CKTop(ckt,
|
||||
(ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT,
|
||||
|
|
@ -707,7 +708,7 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
}
|
||||
}
|
||||
|
||||
// Store previous rhs
|
||||
// Store previous rhs
|
||||
if (rhswoPorts == NULL)
|
||||
rhswoPorts = (double*)TMALLOC(double, ckt->CKTmaxEqNum);
|
||||
else
|
||||
|
|
@ -735,7 +736,7 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
|
||||
int vsrcLookupType = CKTtypelook("Vsource");
|
||||
int vsrcRoot = -1;
|
||||
|
||||
|
||||
// Get VSRCs root model
|
||||
if (ckt->CKTVSRCid == -1)
|
||||
{
|
||||
|
|
@ -761,12 +762,12 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
// 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));
|
||||
// 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++)
|
||||
|
|
@ -836,7 +837,7 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
if (job->SPdoNoise)
|
||||
{
|
||||
|
||||
data->delFreq = freq - data->lstFreq;
|
||||
|
||||
data->freq = freq;
|
||||
|
||||
|
||||
|
|
@ -847,7 +848,7 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
/* the frequency will NOT be stored in array[0] as before; instead,
|
||||
* it will be given in refVal.rValue (see later)
|
||||
*/
|
||||
ckt->CKTactivePort = activePort+1;
|
||||
ckt->CKTactivePort = activePort + 1;
|
||||
|
||||
NInspIter(ckt, (VSRCinstance*)(ckt->CKTrfPorts[activePort])); /* solve the adjoint system */
|
||||
/* put the solution of the current adjoint system into the storage matrix*/
|
||||
|
|
@ -861,15 +862,16 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
ckt->CKTadjointRHS->d[activePort][j] = temp;
|
||||
}
|
||||
}
|
||||
/*
|
||||
now we have all the solutions of the adjoint system, we may look into actual
|
||||
noise sourches
|
||||
*/
|
||||
/*
|
||||
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);
|
||||
error = CKTspnoise(ckt, N_DENS, N_CALC, data, internalNoiseAN);
|
||||
if (error)
|
||||
{
|
||||
tfree(data);
|
||||
tfree(internalNoiseAN);
|
||||
tfree(data);
|
||||
tfree(rhswoPorts);
|
||||
tfree(irhswoPorts);
|
||||
deleteSPmatrix(ckt);
|
||||
|
|
@ -878,7 +880,7 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
data->lstFreq = freq;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef XSPICE
|
||||
/* gtri - modify - wbk - 12/19/90 - Send IPC stuff */
|
||||
|
||||
|
|
@ -893,9 +895,10 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
/* 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(internalNoiseAN);
|
||||
tfree(rhswoPorts);
|
||||
tfree(irhswoPorts);
|
||||
tfree(data);
|
||||
|
|
@ -940,6 +943,7 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
if (job->SPfreqDelta == 0) goto endsweep;
|
||||
break;
|
||||
default:
|
||||
tfree(internalNoiseAN);
|
||||
tfree(rhswoPorts);
|
||||
tfree(irhswoPorts);
|
||||
tfree(data);
|
||||
|
|
@ -949,9 +953,10 @@ SPan(CKTcircuit *ckt, int restart)
|
|||
}
|
||||
}
|
||||
endsweep:
|
||||
SPfrontEnd->OUTendPlot (spPlot);
|
||||
SPfrontEnd->OUTendPlot(spPlot);
|
||||
spPlot = NULL;
|
||||
UPDATE_STATS(0);
|
||||
tfree(internalNoiseAN);
|
||||
tfree(rhswoPorts);
|
||||
tfree(irhswoPorts);
|
||||
deleteSPmatrix(ckt);
|
||||
|
|
|
|||
Loading…
Reference in New Issue