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