Jspice3
mesnoise.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3f2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1987 Gary W. Ng
5  1993 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 #include "spice.h"
9 #include <stdio.h>
10 #include <math.h>
11 #include "mesdefs.h"
12 #include "noisedef.h"
13 #include "fteconst.h"
14 #include "iferrmsg.h"
15 #include "util.h"
16 
17 /*
18  * MESnoise (mode, operation, firstModel, ckt, data, OnDens)
19  * This routine names and evaluates all of the noise sources
20  * associated with MESFET's. It starts with the model *firstModel and
21  * traverses all of its insts. It then proceeds to any other models
22  * on the linked list. The total output noise density generated by
23  * all of the MESFET's is summed with the variable "OnDens".
24  */
25 
26 /* define the names of the noise sources */
27 static char *MESnNames[MESNSRCS] = {
28  /* Note that we have to keep the order
29  * consistent with the index definitions
30  * in MESdefs.h
31  */
32  ".rd", /* noise due to rd */
33  ".rs", /* noise due to rs */
34  ".id", /* noise due to id */
35  ".1overf", /* flicker (1/f) noise */
36  "" /* total transistor noise */
37 };
38 
39 
40 int
41 MESnoise (mode, operation, genmodel, ckt, dataptr, OnDens)
42 
43 int mode;
44 int operation;
45 GENmodel *genmodel;
46 CKTcircuit *ckt;
47 GENERIC *dataptr;
48 double *OnDens;
49 {
50  Ndata *data = (Ndata*)dataptr;
51  MESmodel *model = (MESmodel *) genmodel;
52  MESinstance *inst;
53  char name[N_MXVLNTH];
54  double tempOnoise;
55  double tempInoise;
56  double noizDens[MESNSRCS];
57  double lnNdens[MESNSRCS];
58  int error;
59  int i;
60 
61 
62  if (operation == N_OPEN) {
63 
64  /* see if we have to to produce a summary report
65  * if so, name all the noise generators
66  */
67  if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm == 0)
68  return (OK);
69 
70  if (mode == N_DENS) {
71 
72  for ( ; model; model = model->MESnextModel) {
73  for (inst = model->MESinstances; inst;
74  inst = inst->MESnextInstance) {
75 
76  for (i = 0; i < MESNSRCS; i++) {
77  (void)sprintf(name,
78  "onoise.%s%s",inst->MESname,MESnNames[i]);
79 
80  data->namelist = (IFuid *)
81  trealloc((char *)data->namelist,
82  (data->numPlots + 1)*sizeof(IFuid));
83 
84  if (!data->namelist)
85  return (E_NOMEM);
86 
87  (*(SPfrontEnd->IFnewUid))(ckt,
88  &(data->namelist[data->numPlots++]),
89  (IFuid)NULL,name,UID_OTHER,(GENERIC **)NULL);
90  /* we've added one more plot */
91  }
92  }
93  }
94  return (OK);
95  }
96 
97  if (mode == INT_NOIZ) {
98 
99  for ( ; model; model = model->MESnextModel) {
100  for (inst = model->MESinstances; inst;
101  inst = inst->MESnextInstance) {
102 
103  for (i = 0; i < MESNSRCS; i++) {
104  (void)sprintf(name,
105  "onoise_total.%s%s",inst->MESname,MESnNames[i]);
106 
107  data->namelist = (IFuid *)
108  trealloc((char *)data->namelist,
109  (data->numPlots + 1)*sizeof(IFuid));
110 
111  if (!data->namelist)
112  return (E_NOMEM);
113 
114  (*(SPfrontEnd->IFnewUid))(ckt,
115  &(data->namelist[data->numPlots++]),
116  (IFuid)NULL,name,UID_OTHER,(GENERIC **)NULL);
117  /* we've added one more plot */
118 
119  (void)sprintf(name,
120  "inoise_total.%s%s",inst->MESname,MESnNames[i]);
121 
122  data->namelist = (IFuid *)
123  trealloc((char *)data->namelist,
124  (data->numPlots + 1)*sizeof(IFuid));
125 
126  if (!data->namelist)
127  return (E_NOMEM);
128 
129  (*(SPfrontEnd->IFnewUid))(ckt,
130  &(data->namelist[data->numPlots++]),
131  (IFuid)NULL,name,UID_OTHER,(GENERIC **)NULL);
132  /* we've added one more plot */
133  }
134  }
135  }
136  }
137  return (OK);
138  }
139 
140  if (operation == N_CALC) {
141 
142  if (mode == N_DENS) {
143 
144  for ( ; model; model = model->MESnextModel) {
145  for (inst = model->MESinstances; inst;
146  inst = inst->MESnextInstance) {
147 
148  NevalSrc(&noizDens[MESRDNOIZ],&lnNdens[MESRDNOIZ],
149  ckt,THERMNOISE,inst->MESdrainPrimeNode,
150  inst->MESdrainNode,
151  model->MESdrainConduct * inst->MESarea);
152 
153  NevalSrc(&noizDens[MESRSNOIZ],&lnNdens[MESRSNOIZ],
154  ckt,THERMNOISE,inst->MESsourcePrimeNode,
155  inst->MESsourceNode,
156  model->MESsourceConduct * inst->MESarea);
157 
158  NevalSrc(&noizDens[MESIDNOIZ],&lnNdens[MESIDNOIZ],
159  ckt,THERMNOISE,inst->MESdrainPrimeNode,
160  inst->MESsourcePrimeNode,
161  (2.0/3.0 * FABS(*(ckt->CKTstate0 + inst->MESgm))));
162 
163  NevalSrc(&noizDens[MESFLNOIZ],(double*)NULL,ckt,
165  inst->MESsourcePrimeNode,(double)0.0);
166 
167  noizDens[MESFLNOIZ] *= model->MESfNcoef *
168  exp(model->MESfNexp *
169  log(MAX(FABS(*(ckt->CKTstate0 +
170  inst->MEScd)),N_MINLOG))) / data->freq;
171 
172  lnNdens[MESFLNOIZ] =
173  log(MAX(noizDens[MESFLNOIZ],N_MINLOG));
174 
175  noizDens[MESTOTNOIZ] = noizDens[MESRDNOIZ] +
176  noizDens[MESRSNOIZ] + noizDens[MESIDNOIZ] +
177  noizDens[MESFLNOIZ];
178 
179  lnNdens[MESTOTNOIZ] =
180  log(MAX(noizDens[MESTOTNOIZ], N_MINLOG));
181 
182  *OnDens += noizDens[MESTOTNOIZ];
183 
184  if (data->delFreq == 0.0) {
185 
186  /* if we haven't done any previous integration,
187  * we need to initialize our "history" variables
188  */
189 
190  for (i = 0; i < MESNSRCS; i++) {
191  inst->MESnVar[LNLSTDENS][i] = lnNdens[i];
192  }
193 
194  /* clear out our integration variables if it's
195  * the first pass
196  */
197 
198  if (data->freq ==
199  ((NOISEAN*)ckt->CKTcurJob)->AC.fstart) {
200 
201  for (i = 0; i < MESNSRCS; i++) {
202  inst->MESnVar[OUTNOIZ][i] = 0.0;
203  inst->MESnVar[INNOIZ][i] = 0.0;
204  }
205  }
206  }
207  else {
208  /* data->delFreq != 0.0 (we have to integrate) */
209 
210  for (i = 0; i < MESNSRCS; i++) {
211  if (i != MESTOTNOIZ) {
212 
213  tempOnoise =
214  Nintegrate(noizDens[i], lnNdens[i],
215  inst->MESnVar[LNLSTDENS][i], data);
216  tempInoise =
217  Nintegrate(noizDens[i] * data->GainSqInv,
218  lnNdens[i] + data->lnGainInv,
219  inst->MESnVar[LNLSTDENS][i] +
220  data->lnGainInv,data);
221  inst->MESnVar[LNLSTDENS][i] = lnNdens[i];
222  data->outNoiz += tempOnoise;
223  data->inNoise += tempInoise;
224  if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm
225  != 0) {
226  inst->MESnVar[OUTNOIZ][i] += tempOnoise;
227  inst->MESnVar[OUTNOIZ][MESTOTNOIZ] +=
228  tempOnoise;
229  inst->MESnVar[INNOIZ][i] += tempInoise;
230  inst->MESnVar[INNOIZ][MESTOTNOIZ] +=
231  tempInoise;
232  }
233  }
234  }
235  }
236  if (data->prtSummary) {
237  /* print a summary report */
238  for (i = 0; i < MESNSRCS; i++) {
239  data->outpVector[data->outNumber++] =
240  noizDens[i];
241  }
242  }
243  }
244  }
245  return (OK);
246  }
247 
248  if (mode == INT_NOIZ) {
249  /* already calculated, just output */
250 
251  if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm == 0)
252  return (OK);
253 
254  for ( ; model; model = model->MESnextModel) {
255  for (inst = model->MESinstances; inst;
256  inst = inst->MESnextInstance) {
257 
258  for (i = 0; i < MESNSRCS; i++) {
259  data->outpVector[data->outNumber++] =
260  inst->MESnVar[OUTNOIZ][i];
261  data->outpVector[data->outNumber++] =
262  inst->MESnVar[INNOIZ][i];
263  }
264  }
265  }
266  }
267  }
268 
269  return (OK);
270 }
271 
272 
#define N_MXVLNTH
Definition: noisedef.h:124
#define N_GAIN
Definition: noisedef.h:90
#define N_OPEN
Definition: noisedef.h:85
IFuid MESname
Definition: mesdefs.h:24
double * outpVector
Definition: noisedef.h:33
int MESnoise(int mode, int operation, GENmodel *genmodel, CKTcircuit *ckt, GENERIC *dataptr, double *OnDens)
Definition: mesnoise.c:41
double MESnVar[NSTATVARS][MESNSRCS]
Definition: mesdefs.h:135
#define MAX(a, b)
Definition: spdefs.h:135
#define LNLSTDENS
Definition: noisedef.h:62
double MESfNexp
Definition: mesdefs.h:181
IFuid * namelist
Definition: noisedef.h:35
void NevalSrc()
MESinstance * MESinstances
Definition: mesdefs.h:163
IFfrontEnd * SPfrontEnd
Definition: main.c:917
#define MESNSRCS
Definition: mesdefs.h:132
double lnGainInv
Definition: noisedef.h:25
double MESdrainConduct
Definition: mesdefs.h:183
struct sMESmodel * MESnextModel
Definition: mesdefs.h:161
#define INNOIZ
Definition: noisedef.h:64
#define MESRDNOIZ
Definition: mesdefs.h:126
#define N_MINLOG
Definition: noisedef.h:95
double MESsourceConduct
Definition: mesdefs.h:184
struct sMESinstance * MESnextInstance
Definition: mesdefs.h:22
#define OK
Definition: iferrmsg.h:17
GENERIC * IFuid
Definition: ifsim.h:72
unsigned int prtSummary
Definition: noisedef.h:32
#define NULL
Definition: spdefs.h:121
#define INT_NOIZ
Definition: noisedef.h:84
#define E_NOMEM
Definition: iferrmsg.h:27
#define N_DENS
Definition: noisedef.h:83
int MESdrainPrimeNode
Definition: mesdefs.h:30
#define MESFLNOIZ
Definition: mesdefs.h:129
double Nintegrate()
double MESarea
Definition: mesdefs.h:32
double GainSqInv
Definition: noisedef.h:24
static char * MESnNames[MESNSRCS]
Definition: mesnoise.c:27
#define MESIDNOIZ
Definition: mesdefs.h:128
static char model[32]
Definition: subckt.c:76
int MESsourceNode
Definition: mesdefs.h:29
#define FABS(a)
Definition: util.h:41
#define MESRSNOIZ
Definition: mesdefs.h:127
int outNumber
Definition: noisedef.h:29
#define THERMNOISE
Definition: noisedef.h:89
#define UID_OTHER
Definition: ifsim.h:85
int numPlots
Definition: noisedef.h:30
int MESdrainNode
Definition: mesdefs.h:27
double delFreq
Definition: noisedef.h:21
double outNoiz
Definition: noisedef.h:22
double inNoise
Definition: noisedef.h:23
double freq
Definition: noisedef.h:19
#define N_CALC
Definition: noisedef.h:86
#define MESTOTNOIZ
Definition: mesdefs.h:130
int MESsourcePrimeNode
Definition: mesdefs.h:31
JOB * CKTcurJob
Definition: cktdefs.h:216
#define OUTNOIZ
Definition: noisedef.h:63
char * trealloc()
double MESfNcoef
Definition: mesdefs.h:180
char GENERIC
Definition: ifsim.h:27
Definition: noisedef.h:18