100 changed files with 10551 additions and 0 deletions
-
30src/spicelib/devices/nbjt/Makefile.am
-
69src/spicelib/devices/nbjt/nbjt.c
-
100src/spicelib/devices/nbjt/nbjtacld.c
-
212src/spicelib/devices/nbjt/nbjtask.c
-
167src/spicelib/devices/nbjt/nbjtdefs.h
-
40src/spicelib/devices/nbjt/nbjtdel.c
-
40src/spicelib/devices/nbjt/nbjtdest.c
-
177src/spicelib/devices/nbjt/nbjtdump.c
-
27src/spicelib/devices/nbjt/nbjtext.h
-
83src/spicelib/devices/nbjt/nbjtinit.c
-
13src/spicelib/devices/nbjt/nbjtinit.h
-
12src/spicelib/devices/nbjt/nbjtitf.h
-
517src/spicelib/devices/nbjt/nbjtload.c
-
43src/spicelib/devices/nbjt/nbjtmdel.c
-
32src/spicelib/devices/nbjt/nbjtmpar.c
-
49src/spicelib/devices/nbjt/nbjtparm.c
-
92src/spicelib/devices/nbjt/nbjtpzld.c
-
255src/spicelib/devices/nbjt/nbjtset.c
-
160src/spicelib/devices/nbjt/nbjttemp.c
-
54src/spicelib/devices/nbjt/nbjttrun.c
-
30src/spicelib/devices/nbjt2/Makefile.am
-
170src/spicelib/devices/nbjt2/nbjt2def.h
-
27src/spicelib/devices/nbjt2/nbjt2ext.h
-
10src/spicelib/devices/nbjt2/nbjt2itf.h
-
71src/spicelib/devices/nbjt2/nbt2.c
-
103src/spicelib/devices/nbjt2/nbt2acld.c
-
216src/spicelib/devices/nbjt2/nbt2ask.c
-
41src/spicelib/devices/nbjt2/nbt2del.c
-
40src/spicelib/devices/nbjt2/nbt2dest.c
-
178src/spicelib/devices/nbjt2/nbt2dump.c
-
83src/spicelib/devices/nbjt2/nbt2init.c
-
13src/spicelib/devices/nbjt2/nbt2init.h
-
509src/spicelib/devices/nbjt2/nbt2load.c
-
43src/spicelib/devices/nbjt2/nbt2mdel.c
-
32src/spicelib/devices/nbjt2/nbt2mpar.c
-
53src/spicelib/devices/nbjt2/nbt2parm.c
-
79src/spicelib/devices/nbjt2/nbt2pzld.c
-
274src/spicelib/devices/nbjt2/nbt2set.c
-
130src/spicelib/devices/nbjt2/nbt2temp.c
-
57src/spicelib/devices/nbjt2/nbt2trun.c
-
29src/spicelib/devices/numd/Makefile.am
-
53src/spicelib/devices/numd/numd.c
-
77src/spicelib/devices/numd/numdacld.c
-
121src/spicelib/devices/numd/numdask.c
-
135src/spicelib/devices/numd/numddefs.h
-
36src/spicelib/devices/numd/numddel.c
-
39src/spicelib/devices/numd/numddest.c
-
164src/spicelib/devices/numd/numddump.c
-
27src/spicelib/devices/numd/numdext.h
-
83src/spicelib/devices/numd/numdinit.c
-
13src/spicelib/devices/numd/numdinit.h
-
10src/spicelib/devices/numd/numditf.h
-
393src/spicelib/devices/numd/numdload.c
-
43src/spicelib/devices/numd/numdmdel.c
-
32src/spicelib/devices/numd/numdmpar.c
-
45src/spicelib/devices/numd/numdparm.c
-
63src/spicelib/devices/numd/numdpzld.c
-
235src/spicelib/devices/numd/numdset.c
-
133src/spicelib/devices/numd/numdtemp.c
-
49src/spicelib/devices/numd/numdtrun.c
-
30src/spicelib/devices/numd2/Makefile.am
-
59src/spicelib/devices/numd2/nud2.c
-
80src/spicelib/devices/numd2/nud2acld.c
-
121src/spicelib/devices/numd2/nud2ask.c
-
34src/spicelib/devices/numd2/nud2del.c
-
40src/spicelib/devices/numd2/nud2dest.c
-
165src/spicelib/devices/numd2/nud2dump.c
-
408src/spicelib/devices/numd2/nud2load.c
-
44src/spicelib/devices/numd2/nud2mdel.c
-
32src/spicelib/devices/numd2/nud2mpar.c
-
49src/spicelib/devices/numd2/nud2parm.c
-
67src/spicelib/devices/numd2/nud2pzld.c
-
266src/spicelib/devices/numd2/nud2set.c
-
127src/spicelib/devices/numd2/nud2temp.c
-
50src/spicelib/devices/numd2/nud2trun.c
-
138src/spicelib/devices/numd2/numd2def.h
-
28src/spicelib/devices/numd2/numd2ext.h
-
83src/spicelib/devices/numd2/numd2init.c
-
13src/spicelib/devices/numd2/numd2init.h
-
10src/spicelib/devices/numd2/numd2itf.h
-
30src/spicelib/devices/numos/Makefile.am
-
93src/spicelib/devices/numos/numm.c
-
158src/spicelib/devices/numos/nummacld.c
-
359src/spicelib/devices/numos/nummask.c
-
41src/spicelib/devices/numos/nummdel.c
-
39src/spicelib/devices/numos/nummdest.c
-
179src/spicelib/devices/numos/nummdump.c
-
639src/spicelib/devices/numos/nummload.c
-
43src/spicelib/devices/numos/nummmdel.c
-
32src/spicelib/devices/numos/nummmpar.c
-
57src/spicelib/devices/numos/nummparm.c
-
113src/spicelib/devices/numos/nummpzld.c
-
278src/spicelib/devices/numos/nummset.c
-
128src/spicelib/devices/numos/nummtemp.c
-
56src/spicelib/devices/numos/nummtrun.c
-
218src/spicelib/devices/numos/numosdef.h
-
27src/spicelib/devices/numos/numosext.h
-
83src/spicelib/devices/numos/numosinit.c
-
13src/spicelib/devices/numos/numosinit.h
-
10src/spicelib/devices/numos/numositf.h
@ -0,0 +1,30 @@ |
|||
## Process this file with automake to produce Makefile.in
|
|||
|
|||
noinst_LIBRARIES = libnbjt.a |
|||
|
|||
libnbjt_a_SOURCES = \
|
|||
nbjt.c \
|
|||
nbjtacld.c \
|
|||
nbjtask.c \
|
|||
nbjtdefs.h \
|
|||
nbjtdel.c \
|
|||
nbjtdest.c \
|
|||
nbjtdump.c \
|
|||
nbjtext.h \
|
|||
nbjtinit.c \
|
|||
nbjtinit.h \
|
|||
nbjtitf.h \
|
|||
nbjtload.c \
|
|||
nbjtmdel.c \
|
|||
nbjtmpar.c \
|
|||
nbjtparm.c \
|
|||
nbjtpzld.c \
|
|||
nbjtset.c \
|
|||
nbjttemp.c \
|
|||
nbjttrun.c |
|||
|
|||
|
|||
|
|||
INCLUDES = -I$(top_srcdir)/src/include |
|||
|
|||
MAINTAINERCLEANFILES = Makefile.in |
|||
@ -0,0 +1,69 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "devdefs.h" |
|||
#include "nbjtdefs.h" |
|||
#include "suffix.h" |
|||
|
|||
/* |
|||
* This file defines the Numerical BJT data structures that are available to |
|||
* the next level(s) up the calling hierarchy |
|||
*/ |
|||
|
|||
IFparm NBJTpTable[] = { /* parameters */ |
|||
IP("off", NBJT_OFF, IF_FLAG, "Device initially off"), |
|||
IP("ic.file", NBJT_IC_FILE, IF_STRING, "Initial condition file"), |
|||
IOP("area", NBJT_AREA, IF_REAL, "Area factor"), |
|||
IP("save", NBJT_PRINT, IF_REAL, "Save Solutions"), |
|||
IP("print", NBJT_PRINT, IF_REAL, "Print Solutions"), |
|||
OP("g11", NBJT_G11, IF_REAL, "Conductance"), |
|||
OP("c11", NBJT_C11, IF_REAL, "Capacitance"), |
|||
OP("y11", NBJT_Y11, IF_COMPLEX, "Admittance"), |
|||
OP("g12", NBJT_G12, IF_REAL, "Conductance"), |
|||
OP("c12", NBJT_C12, IF_REAL, "Capacitance"), |
|||
OP("y12", NBJT_Y12, IF_COMPLEX, "Admittance"), |
|||
OPU("g13", NBJT_G13, IF_REAL, "Conductance"), |
|||
OPU("c13", NBJT_C13, IF_REAL, "Capacitance"), |
|||
OPU("y13", NBJT_Y13, IF_COMPLEX, "Admittance"), |
|||
OP("g21", NBJT_G21, IF_REAL, "Conductance"), |
|||
OP("c21", NBJT_C21, IF_REAL, "Capacitance"), |
|||
OP("y21", NBJT_Y21, IF_COMPLEX, "Admittance"), |
|||
OP("g22", NBJT_G22, IF_REAL, "Conductance"), |
|||
OP("c22", NBJT_C22, IF_REAL, "Capacitance"), |
|||
OP("y22", NBJT_Y22, IF_COMPLEX, "Admittance"), |
|||
OPU("g23", NBJT_G23, IF_REAL, "Conductance"), |
|||
OPU("c23", NBJT_C23, IF_REAL, "Capacitance"), |
|||
OPU("y23", NBJT_Y23, IF_COMPLEX, "Admittance"), |
|||
OPU("g31", NBJT_G31, IF_REAL, "Conductance"), |
|||
OPU("c31", NBJT_C31, IF_REAL, "Capacitance"), |
|||
OPU("y31", NBJT_Y31, IF_COMPLEX, "Admittance"), |
|||
OPU("g32", NBJT_G32, IF_REAL, "Conductance"), |
|||
OPU("c32", NBJT_C32, IF_REAL, "Capacitance"), |
|||
OPU("y32", NBJT_Y32, IF_COMPLEX, "Admittance"), |
|||
OPU("g33", NBJT_G33, IF_REAL, "Conductance"), |
|||
OPU("c33", NBJT_C33, IF_REAL, "Capacitance"), |
|||
OPU("y33", NBJT_Y33, IF_COMPLEX, "Admittance"), |
|||
IOP("temp", NBJT_TEMP, IF_REAL, "Instance Temperature") |
|||
}; |
|||
|
|||
IFparm NBJTmPTable[] = { /* model parameters */ |
|||
/* numerical-device models no longer have parameters */ |
|||
/* one is left behind to keep the table from being empty */ |
|||
IP("nbjt", NBJT_MOD_NBJT, IF_FLAG, "Numerical BJT Model") |
|||
}; |
|||
|
|||
char *NBJTnames[] = { |
|||
"Collector", |
|||
"Base", |
|||
"Emitter", |
|||
"Substrate" |
|||
}; |
|||
|
|||
int NBJTnSize = NUMELEMS(NBJTnames); |
|||
int NBJTpTSize = NUMELEMS(NBJTpTable); |
|||
int NBJTmPTSize = NUMELEMS(NBJTmPTable); |
|||
int NBJTiSize = sizeof(NBJTinstance); |
|||
int NBJTmSize = sizeof(NBJTmodel); |
|||
@ -0,0 +1,100 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* Function to load the COMPLEX circuit matrix using the small signal |
|||
* parameters saved during a previous DC operating point analysis. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "nbjtdefs.h" |
|||
#include "sperror.h" |
|||
#include "complex.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "numglobs.h" |
|||
#include "suffix.h" |
|||
|
|||
/* External Declarations */ |
|||
extern int ONEacDebug; |
|||
|
|||
int |
|||
NBJTacLoad(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
|
|||
{ |
|||
register NBJTmodel *model = (NBJTmodel *) inModel; |
|||
register NBJTinstance *inst; |
|||
SPcomplex yIeVce, yIeVbe; |
|||
SPcomplex yIcVce, yIcVbe; |
|||
double startTime; |
|||
|
|||
for (; model != NULL; model = model->NBJTnextModel) { |
|||
FieldDepMobility = model->NBJTmodels->MODLfieldDepMobility; |
|||
Srh = model->NBJTmodels->MODLsrh; |
|||
Auger = model->NBJTmodels->MODLauger; |
|||
AvalancheGen = model->NBJTmodels->MODLavalancheGen; |
|||
AcAnalysisMethod = model->NBJTmethods->METHacAnalysisMethod; |
|||
MobDeriv = model->NBJTmethods->METHmobDeriv; |
|||
ONEacDebug = model->NBJToutputs->OUTPacDebug; |
|||
|
|||
for (inst = model->NBJTinstances; inst != NULL; |
|||
inst = inst->NBJTnextInstance) { |
|||
if (inst->NBJTowner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NBJTglobals)); |
|||
|
|||
model->NBJTmethods->METHacAnalysisMethod = |
|||
NBJTadmittance(inst->NBJTpDevice, ckt->CKTomega, |
|||
&yIeVce, &yIcVce, &yIeVbe, &yIcVbe); |
|||
|
|||
*(inst->NBJTcolColPtr) += yIcVce.real; |
|||
*(inst->NBJTcolColPtr + 1) += yIcVce.imag; |
|||
*(inst->NBJTcolBasePtr) += yIcVbe.real; |
|||
*(inst->NBJTcolBasePtr + 1) += yIcVbe.imag; |
|||
*(inst->NBJTcolEmitPtr) -= yIcVbe.real + yIcVce.real; |
|||
*(inst->NBJTcolEmitPtr + 1) -= yIcVbe.imag + yIcVce.imag; |
|||
*(inst->NBJTbaseColPtr) -= yIcVce.real - yIeVce.real; |
|||
*(inst->NBJTbaseColPtr + 1) -= yIcVce.imag - yIeVce.imag; |
|||
*(inst->NBJTbaseBasePtr) -= yIcVbe.real - yIeVbe.real; |
|||
*(inst->NBJTbaseBasePtr + 1) -= yIcVbe.imag - yIeVbe.imag; |
|||
*(inst->NBJTbaseEmitPtr) += yIcVbe.real + yIcVce.real - yIeVbe.real - yIeVce.real; |
|||
*(inst->NBJTbaseEmitPtr + 1) += yIcVbe.imag + yIcVce.imag - yIeVbe.imag - yIeVce.imag; |
|||
*(inst->NBJTemitColPtr) -= yIeVce.real; |
|||
*(inst->NBJTemitColPtr + 1) -= yIeVce.imag; |
|||
*(inst->NBJTemitBasePtr) -= yIeVbe.real; |
|||
*(inst->NBJTemitBasePtr + 1) -= yIeVbe.imag; |
|||
*(inst->NBJTemitEmitPtr) += yIeVbe.real + yIeVce.real; |
|||
*(inst->NBJTemitEmitPtr + 1) += yIeVbe.imag + yIeVce.imag; |
|||
if (ckt->CKTomega != 0.0) { |
|||
inst->NBJTc11 = yIcVce.imag / ckt->CKTomega; |
|||
inst->NBJTc12 = yIcVbe.imag / ckt->CKTomega; |
|||
inst->NBJTc21 = (yIeVce.imag - yIcVce.imag) / ckt->CKTomega; |
|||
inst->NBJTc22 = (yIeVbe.imag - yIcVbe.imag) / ckt->CKTomega; |
|||
} else { |
|||
inst->NBJTc11 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NBJTc12 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NBJTc21 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NBJTc22 = 0.0; /* XXX What else can be done?! */ |
|||
} |
|||
inst->NBJTy11r = yIcVce.real; |
|||
inst->NBJTy11i = yIcVce.imag; |
|||
inst->NBJTy12r = yIcVbe.real; |
|||
inst->NBJTy12i = yIcVbe.imag; |
|||
inst->NBJTy21r = yIeVce.real - yIcVce.real; |
|||
inst->NBJTy21i = yIeVce.imag - yIcVce.imag; |
|||
inst->NBJTy22r = yIeVbe.real - yIcVbe.real; |
|||
inst->NBJTy22i = yIeVbe.imag - yIcVbe.imag; |
|||
inst->NBJTsmSigAvail = TRUE; |
|||
inst->NBJTpDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,212 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Thomas L. Quarles |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "devdefs.h" |
|||
#include "nbjtdefs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
/* Check out this one */ |
|||
extern int NBJTinitSmSig(NBJTinstance *); |
|||
|
|||
|
|||
/* ARGSUSED */ |
|||
int |
|||
NBJTask(ckt, inInst, which, value, select) |
|||
CKTcircuit *ckt; |
|||
GENinstance *inInst; |
|||
int which; |
|||
IFvalue *value; |
|||
IFvalue *select; |
|||
{ |
|||
NBJTinstance *inst = (NBJTinstance *) inInst; |
|||
switch (which) { |
|||
case NBJT_AREA: |
|||
value->rValue = inst->NBJTarea; |
|||
return (OK); |
|||
case NBJT_TEMP: |
|||
value->rValue = inst->NBJTtemp - CONSTCtoK; |
|||
return (OK); |
|||
case NBJT_G11: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NBJTdIcDVce); |
|||
return (OK); |
|||
case NBJT_G12: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NBJTdIcDVbe); |
|||
return (OK); |
|||
case NBJT_G13: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NBJTdIcDVce) |
|||
- *(ckt->CKTstate0 + inst->NBJTdIcDVbe); |
|||
return (OK); |
|||
case NBJT_G21: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NBJTdIeDVce) |
|||
- *(ckt->CKTstate0 + inst->NBJTdIcDVce); |
|||
return (OK); |
|||
case NBJT_G22: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NBJTdIeDVbe) |
|||
- *(ckt->CKTstate0 + inst->NBJTdIcDVbe); |
|||
return (OK); |
|||
case NBJT_G23: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NBJTdIeDVce) |
|||
+ *(ckt->CKTstate0 + inst->NBJTdIcDVce) /* XXX there was a ;*/ |
|||
-*(ckt->CKTstate0 + inst->NBJTdIeDVbe) |
|||
+ *(ckt->CKTstate0 + inst->NBJTdIcDVbe); |
|||
return (OK); |
|||
case NBJT_G31: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NBJTdIeDVce); |
|||
return (OK); |
|||
case NBJT_G32: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NBJTdIeDVbe); |
|||
return (OK); |
|||
case NBJT_G33: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NBJTdIeDVce) |
|||
+ *(ckt->CKTstate0 + inst->NBJTdIeDVbe); |
|||
return (OK); |
|||
case NBJT_C11: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NBJTc11; |
|||
return (OK); |
|||
case NBJT_C12: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NBJTc12; |
|||
return (OK); |
|||
case NBJT_C13: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NBJTc11 - inst->NBJTc12; |
|||
return (OK); |
|||
case NBJT_C21: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NBJTc21; |
|||
return (OK); |
|||
case NBJT_C22: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NBJTc22; |
|||
return (OK); |
|||
case NBJT_C23: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NBJTc21 - inst->NBJTc22; |
|||
return (OK); |
|||
case NBJT_C31: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NBJTc11 - inst->NBJTc21; |
|||
return (OK); |
|||
case NBJT_C32: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NBJTc12 - inst->NBJTc22; |
|||
return (OK); |
|||
case NBJT_C33: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NBJTc11 + inst->NBJTc21 |
|||
+ inst->NBJTc12 + inst->NBJTc22; |
|||
return (OK); |
|||
case NBJT_Y11: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NBJTy11r; |
|||
value->cValue.imag = inst->NBJTy11i; |
|||
return (OK); |
|||
case NBJT_Y12: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NBJTy12r; |
|||
value->cValue.imag = inst->NBJTy12i; |
|||
return (OK); |
|||
case NBJT_Y13: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NBJTy11r - inst->NBJTy12r; |
|||
value->cValue.imag = -inst->NBJTy11i - inst->NBJTy12i; |
|||
return (OK); |
|||
case NBJT_Y21: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NBJTy21r; |
|||
value->cValue.imag = inst->NBJTy21i; |
|||
return (OK); |
|||
case NBJT_Y22: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NBJTy22r; |
|||
value->cValue.imag = inst->NBJTy22i; |
|||
return (OK); |
|||
case NBJT_Y23: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NBJTy21r - inst->NBJTy22r; |
|||
value->cValue.imag = -inst->NBJTy21i - inst->NBJTy22i; |
|||
return (OK); |
|||
case NBJT_Y31: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NBJTy11r - inst->NBJTy21r; |
|||
value->cValue.imag = -inst->NBJTy11i - inst->NBJTy21i; |
|||
return (OK); |
|||
case NBJT_Y32: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NBJTy12r - inst->NBJTy22r; |
|||
value->cValue.imag = -inst->NBJTy12i - inst->NBJTy22i; |
|||
return (OK); |
|||
case NBJT_Y33: |
|||
if (!inst->NBJTsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJTinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NBJTy11r + inst->NBJTy21r |
|||
+ inst->NBJTy12r + inst->NBJTy22r; |
|||
value->cValue.imag = inst->NBJTy11i + inst->NBJTy21i |
|||
+ inst->NBJTy12i + inst->NBJTy22i; |
|||
return (OK); |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
/* NOTREACHED */ |
|||
} |
|||
@ -0,0 +1,167 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Authors: 1987 Karti Mayaram, 1991 David Gates |
|||
**********/ |
|||
|
|||
#ifndef NBJT_H |
|||
#define NBJT_H |
|||
|
|||
/* data structures used to describe 1D Numerical BJTs */ |
|||
|
|||
/* circuit level includes */ |
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "gendefs.h" |
|||
|
|||
/* device level includes */ |
|||
#include "onemesh.h" |
|||
#include "onedev.h" |
|||
#include "profile.h" |
|||
#include "numglobs.h" |
|||
#include "carddefs.h" |
|||
|
|||
/* information needed per instance */ |
|||
typedef struct sNBJTinstance { |
|||
struct sNBJTmodel *NBJTmodPtr;/* back pointer to model */ |
|||
struct sNBJTinstance *NBJTnextInstance; /* pointer to next instance |
|||
* of current model */ |
|||
IFuid NBJTname; /* pointer to character string naming this |
|||
* instance */ |
|||
int NBJTowner; /* number of owner process */ |
|||
int NBJTstate; /* pointer to start of state vector for bjt */ |
|||
|
|||
/* entries in the state vector for bjt: */ |
|||
#define NBJTvbe NBJTstate |
|||
#define NBJTvce NBJTstate+1 |
|||
#define NBJTic NBJTstate+2 |
|||
#define NBJTie NBJTstate+3 |
|||
#define NBJTdIeDVce NBJTstate+4 |
|||
#define NBJTdIeDVbe NBJTstate+5 |
|||
#define NBJTdIcDVce NBJTstate+6 |
|||
#define NBJTdIcDVbe NBJTstate+7 |
|||
#define NBJTnumStates 8 |
|||
|
|||
int NBJTcolNode; /* number of collector node of bjt */ |
|||
int NBJTbaseNode; /* number of base node of bjt */ |
|||
int NBJTemitNode; /* number of emitter node of bjt */ |
|||
ONEdevice *NBJTpDevice; |
|||
GLOBvalues NBJTglobals; /* Temp.-Dep. Global Parameters */ |
|||
int NBJTtype; |
|||
double NBJTarea; /* area factor of the BJT */ |
|||
double NBJTtemp; /* Instance Temperature */ |
|||
double NBJTc11; /* small-signal capacitance */ |
|||
double NBJTy11r; /* small-signal admittance, real part */ |
|||
double NBJTy11i; /* small-signal admittance, imag part */ |
|||
double NBJTc12; /* small-signal capacitance */ |
|||
double NBJTy12r; /* small-signal admittance, real part */ |
|||
double NBJTy12i; /* small-signal admittance, imag part */ |
|||
double NBJTc21; /* small-signal capacitance */ |
|||
double NBJTy21r; /* small-signal admittance, real part */ |
|||
double NBJTy21i; /* small-signal admittance, imag part */ |
|||
double NBJTc22; /* small-signal capacitance */ |
|||
double NBJTy22r; /* small-signal admittance, real part */ |
|||
double NBJTy22i; /* small-signal admittance, imag part */ |
|||
int NBJTprint; |
|||
char *NBJTicFile; /* Name of initial condition file */ |
|||
double *NBJTcolColPtr; /* pointer to sparse matrix at |
|||
* (collector,collector) */ |
|||
double *NBJTbaseBasePtr; /* pointer to sparse matrix at (base,base) */ |
|||
double *NBJTemitEmitPtr; /* pointer to sparse matrix at |
|||
* (emitter,emitter) */ |
|||
double *NBJTcolBasePtr; /* pointer to sparse matrix at |
|||
* (collector,base) */ |
|||
double *NBJTcolEmitPtr; /* pointer to sparse matrix at |
|||
* (collector,emitter) */ |
|||
double *NBJTbaseColPtr; /* pointer to sparse matrix at |
|||
* (base,collector) */ |
|||
double *NBJTbaseEmitPtr; /* pointer to sparse matrix at (base,emitter) */ |
|||
double *NBJTemitColPtr; /* pointer to sparse matrix at |
|||
* (emitter,collector) */ |
|||
double *NBJTemitBasePtr; /* pointer to sparse matrix at (emitter,base) */ |
|||
int NBJToff; /* 'off' flag for bjt */ |
|||
unsigned NBJTsmSigAvail:1; /* flag to indicate small-signal done */ |
|||
unsigned NBJTareaGiven:1; /* flag to indicate area was specified */ |
|||
unsigned NBJTicFileGiven:1; /* flag to indicate init. cond. file given */ |
|||
unsigned NBJTprintGiven:1; /* flag to indicate if print was given */ |
|||
unsigned NBJTtempGiven:1; /* flag to indicate if temp was given */ |
|||
} NBJTinstance; |
|||
|
|||
/* per model data */ |
|||
typedef struct sNBJTmodel { /* model structure for a bjt */ |
|||
int NBJTmodType; /* type index of this device type */ |
|||
struct sNBJTmodel *NBJTnextModel; /* pointer to next possible model in |
|||
* linked list */ |
|||
NBJTinstance *NBJTinstances; /* pointer to list of instances that have |
|||
* this model */ |
|||
IFuid NBJTmodName; /* pointer to character string naming this |
|||
* model */ |
|||
/* Everything below here is numerical-device-specific */ |
|||
MESHcard *NBJTxMeshes; /* list of xmesh cards */ |
|||
MESHcard *NBJTyMeshes; /* list of ymesh cards */ |
|||
DOMNcard *NBJTdomains; /* list of domain cards */ |
|||
BDRYcard *NBJTboundaries; /* list of boundary cards */ |
|||
DOPcard *NBJTdopings; /* list of doping cards */ |
|||
ELCTcard *NBJTelectrodes; /* list of electrode cards */ |
|||
CONTcard *NBJTcontacts; /* list of contact cards */ |
|||
MODLcard *NBJTmodels; /* list of model cards */ |
|||
MATLcard *NBJTmaterials; /* list of material cards */ |
|||
MOBcard *NBJTmobility; /* list of mobility cards */ |
|||
METHcard *NBJTmethods; /* list of method cards */ |
|||
OPTNcard *NBJToptions; /* list of option cards */ |
|||
OUTPcard *NBJToutputs; /* list of output cards */ |
|||
ONEtranInfo *NBJTpInfo; /* transient analysis information */ |
|||
DOPprofile *NBJTprofiles; /* expanded list of doping profiles */ |
|||
DOPtable *NBJTdopTables; /* list of tables used by profiles */ |
|||
ONEmaterial *NBJTmatlInfo; /* list of material info structures */ |
|||
} NBJTmodel; |
|||
|
|||
/* type of BJT */ |
|||
#define NPN 1 |
|||
#define PNP -1 |
|||
|
|||
/* device parameters */ |
|||
#define NBJT_AREA 1 |
|||
#define NBJT_OFF 2 |
|||
#define NBJT_IC_FILE 3 |
|||
#define NBJT_PRINT 4 |
|||
#define NBJT_TEMP 5 |
|||
|
|||
#define NBJT_G11 8 |
|||
#define NBJT_C11 9 |
|||
#define NBJT_Y11 10 |
|||
#define NBJT_G12 11 |
|||
#define NBJT_C12 12 |
|||
#define NBJT_Y12 13 |
|||
#define NBJT_G13 14 |
|||
#define NBJT_C13 15 |
|||
#define NBJT_Y13 16 |
|||
#define NBJT_G21 17 |
|||
#define NBJT_C21 18 |
|||
#define NBJT_Y21 19 |
|||
#define NBJT_G22 20 |
|||
#define NBJT_C22 21 |
|||
#define NBJT_Y22 22 |
|||
#define NBJT_G23 23 |
|||
#define NBJT_C23 24 |
|||
#define NBJT_Y23 25 |
|||
#define NBJT_G31 26 |
|||
#define NBJT_C31 27 |
|||
#define NBJT_Y31 28 |
|||
#define NBJT_G32 29 |
|||
#define NBJT_C32 30 |
|||
#define NBJT_Y32 31 |
|||
#define NBJT_G33 32 |
|||
#define NBJT_C33 33 |
|||
#define NBJT_Y33 34 |
|||
|
|||
/* model parameters */ |
|||
/* NOTE: all true model parameters have been moved to IFcardInfo structures */ |
|||
#define NBJT_MOD_NBJT 101 |
|||
|
|||
/* device questions */ |
|||
|
|||
/* model questions */ |
|||
|
|||
#include "nbjtext.h" |
|||
|
|||
#endif /* NBJT_H */ |
|||
@ -0,0 +1,40 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine deletes a NBJT instance from the circuit and frees the |
|||
* storage it was using. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "nbjtdefs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NBJTdelete(inModel, name, kill) |
|||
GENmodel *inModel; |
|||
IFuid name; |
|||
GENinstance **kill; |
|||
|
|||
{ |
|||
NBJTmodel *model = (NBJTmodel *) inModel; |
|||
NBJTinstance **fast = (NBJTinstance **) kill; |
|||
NBJTinstance **prev = NULL; |
|||
NBJTinstance *inst; |
|||
|
|||
for (; model; model = model->NBJTnextModel) { |
|||
prev = &(model->NBJTinstances); |
|||
for (inst = *prev; inst; inst = *prev) { |
|||
if (inst->NBJTname == name || (fast && inst == *fast)) { |
|||
*prev = inst->NBJTnextInstance; |
|||
FREE(inst); |
|||
return (OK); |
|||
} |
|||
prev = &(inst->NBJTnextInstance); |
|||
} |
|||
} |
|||
return (E_NODEV); |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine deletes all NBJTs from the circuit and frees all storage they |
|||
* were using. The current implementation has memory leaks. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "nbjtdefs.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
void |
|||
NBJTdestroy(inModel) |
|||
GENmodel **inModel; |
|||
|
|||
{ |
|||
|
|||
NBJTmodel **model = (NBJTmodel **) inModel; |
|||
NBJTmodel *mod, *nextMod; |
|||
NBJTinstance *inst, *nextInst; |
|||
|
|||
|
|||
for (mod = *model; mod;) { |
|||
for (inst = mod->NBJTinstances; inst;) { |
|||
ONEdestroy(inst->NBJTpDevice); |
|||
nextInst = inst->NBJTnextInstance; |
|||
FREE(inst); |
|||
inst = nextInst; |
|||
} |
|||
nextMod = mod->NBJTnextModel; |
|||
FREE(mod); |
|||
mod = nextMod; |
|||
} |
|||
*model = NULL; |
|||
} |
|||
@ -0,0 +1,177 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This is a simple routine to dump the internal device states. It produces |
|||
* states for .OP, .DC, & .TRAN simulations. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "nbjtdefs.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
/* Forward Declarations */ |
|||
static void NBJTputHeader(FILE *, CKTcircuit *, NBJTinstance *); |
|||
|
|||
/* State Counter */ |
|||
static int state_numOP = 0; |
|||
static int state_numDC = 0; |
|||
static int state_numTR = 0; |
|||
|
|||
void |
|||
NBJTdump(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
register NBJTmodel *model = (NBJTmodel *) inModel; |
|||
register NBJTinstance *inst; |
|||
OUTPcard *output; |
|||
FILE *fpState; |
|||
char fileName[BSIZE_SP]; |
|||
char description[BSIZE_SP]; |
|||
char *prefix; |
|||
int *state_num; |
|||
int anyOutput = 0; |
|||
|
|||
if (ckt->CKTmode & MODEDCOP) { |
|||
prefix = "OP"; |
|||
state_num = &state_numOP; |
|||
sprintf(description, "..."); |
|||
} else if (ckt->CKTmode & MODEDCTRANCURVE) { |
|||
prefix = "DC"; |
|||
state_num = &state_numDC; |
|||
sprintf(description, "sweep = % e", ckt->CKTtime); |
|||
} else if (ckt->CKTmode & MODETRAN) { |
|||
prefix = "TR"; |
|||
state_num = &state_numTR; |
|||
sprintf(description, "time = % e", ckt->CKTtime); |
|||
} else { |
|||
/* Not a recognized CKT mode. */ |
|||
return; |
|||
} |
|||
|
|||
for (; model != NULL; model = model->NBJTnextModel) { |
|||
output = model->NBJToutputs; |
|||
for (inst = model->NBJTinstances; inst != NULL; |
|||
inst = inst->NBJTnextInstance) { |
|||
if (inst->NBJTowner != ARCHme) continue; |
|||
|
|||
if (inst->NBJTprintGiven) { |
|||
if ((ckt->CKTmode & MODETRAN) && |
|||
((ckt->CKTstat->STATaccepted - 1) % inst->NBJTprint != 0)) { |
|||
continue; |
|||
} |
|||
anyOutput = 1; |
|||
sprintf(fileName, "%s%s.%d.%s", output->OUTProotFile, prefix, |
|||
*state_num, inst->NBJTname); |
|||
if (!(fpState = fopen(fileName, "w"))) { |
|||
perror(fileName); |
|||
} else { |
|||
NBJTputHeader(fpState, ckt, inst); |
|||
ONEprnSolution(fpState, inst->NBJTpDevice, |
|||
model->NBJToutputs); |
|||
fclose(fpState); |
|||
LOGmakeEntry(fileName, description); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if (anyOutput) { |
|||
(*state_num)++; |
|||
} |
|||
} |
|||
|
|||
#define NBJTnumOutputs 9 |
|||
|
|||
static |
|||
void |
|||
NBJTputHeader(file, ckt, inst) |
|||
FILE *file; |
|||
CKTcircuit *ckt; |
|||
NBJTinstance *inst; |
|||
{ |
|||
char *reference; |
|||
double refVal = 0.0; |
|||
int numVars = NBJTnumOutputs; |
|||
|
|||
if (ckt->CKTmode & MODEDCOP) { |
|||
reference = NULL; |
|||
} else if (ckt->CKTmode & MODEDCTRANCURVE) { |
|||
reference = "sweep"; |
|||
refVal = ckt->CKTtime; |
|||
numVars++; |
|||
} else if (ckt->CKTmode & MODETRAN) { |
|||
reference = "time"; |
|||
refVal = ckt->CKTtime; |
|||
numVars++; |
|||
} else { |
|||
reference = NULL; |
|||
} |
|||
fprintf(file, "Title: Device %s external state\n", inst->NBJTname); |
|||
fprintf(file, "Plotname: Device Operating Point\n"); |
|||
fprintf(file, "Command: deftype v conductance S\n"); |
|||
fprintf(file, "Flags: real\n"); |
|||
fprintf(file, "No. Variables: %d\n", numVars); |
|||
fprintf(file, "No. Points: 1\n"); |
|||
numVars = 0; |
|||
fprintf(file, "Variables:\n"); |
|||
if (reference) { |
|||
fprintf(file, "\t%d %s unknown\n", numVars++, reference); |
|||
} |
|||
fprintf(file, "\t%d v13 voltage\n", numVars++); |
|||
fprintf(file, "\t%d v23 voltage\n", numVars++); |
|||
fprintf(file, "\t%d i1 current\n", numVars++); |
|||
fprintf(file, "\t%d i2 current\n", numVars++); |
|||
fprintf(file, "\t%d i3 current\n", numVars++); |
|||
fprintf(file, "\t%d g22 conductance\n", numVars++); |
|||
fprintf(file, "\t%d g21 conductance\n", numVars++); |
|||
fprintf(file, "\t%d g12 conductance\n", numVars++); |
|||
fprintf(file, "\t%d g11 conductance\n", numVars++); |
|||
fprintf(file, "Values:\n0"); |
|||
if (reference) { |
|||
fprintf(file, "\t% e\n", refVal); |
|||
} |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTvce)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTvbe)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTic)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTie) |
|||
- *(ckt->CKTstate0 + inst->NBJTic)); |
|||
fprintf(file, "\t% e\n", -*(ckt->CKTstate0 + inst->NBJTie)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTdIeDVbe) |
|||
- *(ckt->CKTstate0 + inst->NBJTdIcDVbe)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTdIeDVce) |
|||
- *(ckt->CKTstate0 + inst->NBJTdIcDVce)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTdIcDVbe)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTdIcDVce)); |
|||
} |
|||
|
|||
void |
|||
NBJTacct(inModel, ckt, file) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
FILE *file; |
|||
{ |
|||
register NBJTmodel *model = (NBJTmodel *) inModel; |
|||
register NBJTinstance *inst; |
|||
OUTPcard *output; |
|||
|
|||
for (; model != NULL; model = model->NBJTnextModel) { |
|||
output = model->NBJToutputs; |
|||
for (inst = model->NBJTinstances; inst != NULL; |
|||
inst = inst->NBJTnextInstance) { |
|||
if (inst->NBJTowner != ARCHme) continue; |
|||
|
|||
if (output->OUTPstats) { |
|||
ONEmemStats(file, inst->NBJTpDevice); |
|||
ONEcpuStats(file, inst->NBJTpDevice); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Karti Mayaram |
|||
**********/ |
|||
|
|||
#ifndef __NBJT_H |
|||
#define __NBJT_H |
|||
|
|||
extern int NBJTacLoad(GENmodel *, CKTcircuit *); |
|||
extern int NBJTask(CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *); |
|||
extern int NBJTdelete(GENmodel *, IFuid, GENinstance **); |
|||
extern void NBJTdestroy(GENmodel **); |
|||
extern int NBJTgetic(GENmodel *, CKTcircuit *); |
|||
extern int NBJTload(GENmodel *, CKTcircuit *); |
|||
extern int NBJTmDelete(GENmodel **, IFuid, GENmodel *); |
|||
extern int NBJTmParam(int, IFvalue *, GENmodel *); |
|||
extern int NBJTparam(int, IFvalue *, GENinstance *, IFvalue *); |
|||
extern int NBJTpzLoad(GENmodel *, CKTcircuit *, SPcomplex *); |
|||
extern int NBJTsetup(SMPmatrix *, GENmodel *, CKTcircuit *, int *); |
|||
extern int NBJTtemp(GENmodel *, CKTcircuit *); |
|||
extern int NBJTtrunc(GENmodel *, CKTcircuit *, double *); |
|||
|
|||
extern void NBJTdump(GENmodel *, CKTcircuit *); |
|||
extern void NBJTacct(GENmodel *, CKTcircuit *, FILE *); |
|||
|
|||
|
|||
#endif /* NBJT_H */ |
|||
@ -0,0 +1,83 @@ |
|||
#include <config.h> |
|||
|
|||
#include <devdefs.h> |
|||
|
|||
#include "nbjtitf.h" |
|||
#include "nbjtext.h" |
|||
#include "nbjtinit.h" |
|||
|
|||
|
|||
SPICEdev NBJTinfo = { |
|||
{ |
|||
"NBJT", |
|||
"1D Numerical Bipolar Junction Transistor model", |
|||
|
|||
&NBJTnSize, |
|||
&NBJTnSize, |
|||
NBJTnames, |
|||
|
|||
&NBJTpTSize, |
|||
NBJTpTable, |
|||
|
|||
&NBJTmPTSize, |
|||
NBJTmPTable, |
|||
|
|||
#ifdef XSPICE |
|||
/*---- Fixed by SDB 5.2.2003 to enable XSPICE/tclspice integration -----*/ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
/*--------------------------- End of SDB fix -------------------------*/ |
|||
#endif |
|||
|
|||
DEV_DEFAULT |
|||
}, |
|||
|
|||
DEVparam : NBJTparam, |
|||
DEVmodParam : NBJTmParam, |
|||
DEVload : NBJTload, |
|||
DEVsetup : NBJTsetup, |
|||
DEVunsetup : NULL, |
|||
DEVpzSetup : NBJTsetup, |
|||
DEVtemperature: NBJTtemp, |
|||
DEVtrunc : NBJTtrunc, |
|||
DEVfindBranch : NULL, |
|||
DEVacLoad : NBJTacLoad, |
|||
DEVaccept : NULL, |
|||
DEVdestroy : NBJTdestroy, |
|||
DEVmodDelete : NBJTmDelete, |
|||
DEVdelete : NBJTdelete, |
|||
DEVsetic : NULL, |
|||
DEVask : NBJTask, |
|||
DEVmodAsk : NULL, |
|||
DEVpzLoad : NBJTpzLoad, |
|||
DEVconvTest : NULL, |
|||
DEVsenSetup : NULL, |
|||
DEVsenLoad : NULL, |
|||
DEVsenUpdate : NULL, |
|||
DEVsenAcLoad : NULL, |
|||
DEVsenPrint : NULL, |
|||
DEVsenTrunc : NULL, |
|||
DEVdisto : NULL, |
|||
DEVnoise : NULL, |
|||
DEVdump : NBJTdump, |
|||
DEVacct : NBJTacct, |
|||
|
|||
DEVinstSize : &NBJTiSize, |
|||
DEVmodSize : &NBJTmSize |
|||
|
|||
}; |
|||
|
|||
|
|||
SPICEdev * |
|||
get_nbjt_info(void) |
|||
{ |
|||
return &NBJTinfo; |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
#ifndef _NBJTINIT_H |
|||
#define _NBJTINIT_H |
|||
|
|||
extern IFparm NBJTpTable[ ]; |
|||
extern IFparm NBJTmPTable[ ]; |
|||
extern char *NBJTnames[ ]; |
|||
extern int NBJTpTSize; |
|||
extern int NBJTmPTSize; |
|||
extern int NBJTnSize; |
|||
extern int NBJTiSize; |
|||
extern int NBJTmSize; |
|||
|
|||
#endif |
|||
@ -0,0 +1,12 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
**********/ |
|||
|
|||
#ifndef DEV_NBJT |
|||
#define DEV_NBJT |
|||
|
|||
extern SPICEdev *get_nbjt_info(void); |
|||
|
|||
|
|||
#endif |
|||
|
|||
@ -0,0 +1,517 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This is the function called each iteration to evaluate the numerical BJTs |
|||
* in the circuit and load them into the matrix as appropriate |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "devdefs.h" |
|||
#include "cktdefs.h" |
|||
#include "nbjtdefs.h" |
|||
#include "trandefs.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
/* Forward declarations */ |
|||
int NBJTinitSmSig(NBJTinstance *); |
|||
|
|||
/* External Declarations */ |
|||
extern int ONEdcDebug; |
|||
extern int ONEtranDebug; |
|||
extern int ONEacDebug; |
|||
|
|||
|
|||
int |
|||
NBJTload(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
register NBJTmodel *model = (NBJTmodel *) inModel; |
|||
register NBJTinstance *inst; |
|||
register ONEdevice *pDevice; |
|||
double startTime, startTime2, totalTime, totalTime2; |
|||
double tol; |
|||
double ic, ie; |
|||
double iceq, ieeq; |
|||
double ichat = 0.0, iehat = 0.0; |
|||
double delVce, delVbe; |
|||
double vce, vbe, vbc; |
|||
double dIeDVce, dIeDVbe; |
|||
double dIcDVce, dIcDVbe; |
|||
double xfact; |
|||
int icheck; |
|||
int icheck1; |
|||
int i; |
|||
double deltaNorm[7]; |
|||
int devConverged = 0; |
|||
int numDevNonCon; |
|||
int deviceType; |
|||
int doInitSolve; |
|||
int doVoltPred; |
|||
char *initStateName; |
|||
|
|||
/* loop through all the models */ |
|||
for (; model != NULL; model = model->NBJTnextModel) { |
|||
FieldDepMobility = model->NBJTmodels->MODLfieldDepMobility; |
|||
Srh = model->NBJTmodels->MODLsrh; |
|||
Auger = model->NBJTmodels->MODLauger; |
|||
AvalancheGen = model->NBJTmodels->MODLavalancheGen; |
|||
MobDeriv = model->NBJTmethods->METHmobDeriv; |
|||
MaxIterations = model->NBJTmethods->METHitLim; |
|||
ONEdcDebug = model->NBJToutputs->OUTPdcDebug; |
|||
ONEtranDebug = model->NBJToutputs->OUTPtranDebug; |
|||
ONEacDebug = model->NBJToutputs->OUTPacDebug; |
|||
deviceType = model->NBJToptions->OPTNdeviceType; |
|||
doVoltPred = model->NBJTmethods->METHvoltPred; |
|||
|
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
/* compute normalized deltas and predictor coeff */ |
|||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) { |
|||
model->NBJTpInfo->order = ckt->CKTorder; |
|||
model->NBJTpInfo->method = ckt->CKTintegrateMethod; |
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NBJTpInfo->intCoeff, deltaNorm); |
|||
computePredCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NBJTpInfo->predCoeff, deltaNorm); |
|||
} |
|||
} else if (ckt->CKTmode & MODEINITTRAN) { |
|||
model->NBJTpInfo->order = ckt->CKTorder; |
|||
model->NBJTpInfo->method = ckt->CKTintegrateMethod; |
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NBJTpInfo->intCoeff, deltaNorm); |
|||
} |
|||
/* loop through all the instances of the model */ |
|||
for (inst = model->NBJTinstances; inst != NULL; |
|||
inst = inst->NBJTnextInstance) { |
|||
if (inst->NBJTowner != ARCHme) continue; |
|||
|
|||
pDevice = inst->NBJTpDevice; |
|||
|
|||
totalTime = 0.0; |
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NBJTglobals)); |
|||
|
|||
/* |
|||
* initialization |
|||
*/ |
|||
|
|||
pDevice->devStates = ckt->CKTstates; |
|||
icheck = 1; |
|||
doInitSolve = FALSE; |
|||
initStateName = NULL; |
|||
if (ckt->CKTmode & MODEINITSMSIG) { |
|||
vbe = *(ckt->CKTstate0 + inst->NBJTvbe); |
|||
vce = *(ckt->CKTstate0 + inst->NBJTvce); |
|||
delVbe = 0.0; |
|||
delVce = 0.0; |
|||
NBJTsetBCs(pDevice, vce, vbe); |
|||
} else if (ckt->CKTmode & MODEINITTRAN) { |
|||
*(ckt->CKTstate0 + inst->NBJTvbe) = |
|||
*(ckt->CKTstate1 + inst->NBJTvbe); |
|||
*(ckt->CKTstate0 + inst->NBJTvce) = |
|||
*(ckt->CKTstate1 + inst->NBJTvce); |
|||
vbe = *(ckt->CKTstate1 + inst->NBJTvbe); |
|||
vce = *(ckt->CKTstate1 + inst->NBJTvce); |
|||
ONEsaveState(pDevice); |
|||
delVbe = 0.0; |
|||
delVce = 0.0; |
|||
} else if ((ckt->CKTmode & MODEINITJCT) && |
|||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) { |
|||
doInitSolve = TRUE; |
|||
initStateName = inst->NBJTicFile; |
|||
vbe = 0.0; |
|||
vce = 0.0; |
|||
delVbe = vbe; |
|||
delVce = vce; |
|||
} else if ((ckt->CKTmode & MODEINITJCT) && (inst->NBJToff == 0)) { |
|||
doInitSolve = TRUE; |
|||
initStateName = inst->NBJTicFile; |
|||
vbe = inst->NBJTtype * 0.6; |
|||
vce = inst->NBJTtype * 1.0; |
|||
delVbe = vbe; |
|||
delVce = vce; |
|||
} else if (ckt->CKTmode & MODEINITJCT) { |
|||
doInitSolve = TRUE; |
|||
vbe = 0.0; |
|||
vce = 0.0; |
|||
delVbe = vbe; |
|||
delVce = vce; |
|||
} else if ((ckt->CKTmode & MODEINITFIX) && inst->NBJToff) { |
|||
vbe = 0.0; |
|||
vce = 0.0; |
|||
delVbe = vbe; |
|||
delVce = vce; |
|||
} else { |
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
*(ckt->CKTstate0 + inst->NBJTvbe) = |
|||
*(ckt->CKTstate1 + inst->NBJTvbe); |
|||
*(ckt->CKTstate0 + inst->NBJTvce) = |
|||
*(ckt->CKTstate1 + inst->NBJTvce); |
|||
*(ckt->CKTstate0 + inst->NBJTic) = |
|||
*(ckt->CKTstate1 + inst->NBJTic); |
|||
*(ckt->CKTstate0 + inst->NBJTie) = |
|||
*(ckt->CKTstate1 + inst->NBJTie); |
|||
*(ckt->CKTstate0 + inst->NBJTdIeDVce) = |
|||
*(ckt->CKTstate1 + inst->NBJTdIeDVce); |
|||
*(ckt->CKTstate0 + inst->NBJTdIeDVbe) = |
|||
*(ckt->CKTstate1 + inst->NBJTdIeDVbe); |
|||
*(ckt->CKTstate0 + inst->NBJTdIcDVce) = |
|||
*(ckt->CKTstate1 + inst->NBJTdIcDVce); |
|||
*(ckt->CKTstate0 + inst->NBJTdIcDVbe) = |
|||
*(ckt->CKTstate1 + inst->NBJTdIcDVbe); |
|||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) { |
|||
/* no linear prediction on device voltages */ |
|||
vbe = *(ckt->CKTstate1 + inst->NBJTvbe); |
|||
vce = *(ckt->CKTstate1 + inst->NBJTvce); |
|||
ONEpredict(pDevice, model->NBJTpInfo); |
|||
} else { |
|||
if (doVoltPred) { |
|||
/* linear prediction */ |
|||
xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1]; |
|||
vbe = (1+xfact) * (*(ckt->CKTstate1 + inst->NBJTvbe)) |
|||
- (xfact) * (*(ckt->CKTstate2 + inst->NBJTvbe)); |
|||
vce = (1+xfact) * (*(ckt->CKTstate1 + inst->NBJTvce)) |
|||
- (xfact) * (*(ckt->CKTstate2 + inst->NBJTvce)); |
|||
} else { |
|||
vbe = *(ckt->CKTstate1 + inst->NBJTvbe); |
|||
vce = *(ckt->CKTstate1 + inst->NBJTvce); |
|||
} |
|||
} |
|||
} else { |
|||
/* |
|||
* compute new nonlinear branch voltages |
|||
*/ |
|||
vbe = *(ckt->CKTrhsOld + inst->NBJTbaseNode) - |
|||
*(ckt->CKTrhsOld + inst->NBJTemitNode); |
|||
vce = *(ckt->CKTrhsOld + inst->NBJTcolNode) - |
|||
*(ckt->CKTrhsOld + inst->NBJTemitNode); |
|||
} |
|||
delVbe = vbe - *(ckt->CKTstate0 + inst->NBJTvbe); |
|||
delVce = vce - *(ckt->CKTstate0 + inst->NBJTvce); |
|||
ichat = *(ckt->CKTstate0 + inst->NBJTic) - |
|||
*(ckt->CKTstate0 + inst->NBJTdIcDVbe) * delVbe - |
|||
*(ckt->CKTstate0 + inst->NBJTdIcDVce) * delVce; |
|||
iehat = *(ckt->CKTstate0 + inst->NBJTie) - |
|||
*(ckt->CKTstate0 + inst->NBJTdIeDVbe) * delVbe - |
|||
*(ckt->CKTstate0 + inst->NBJTdIeDVce) * delVce; |
|||
|
|||
#ifndef NOBYPASS |
|||
/* |
|||
* bypass if solution has not changed |
|||
*/ |
|||
/* |
|||
* the following collections of if's would be just one if the average |
|||
* compiler could handle it, but many find the expression too |
|||
* complicated, thus the split. |
|||
*/ |
|||
if ((ckt->CKTbypass) && pDevice->converged && |
|||
(!(ckt->CKTmode & MODEINITPRED)) && |
|||
(fabs(delVbe) < (ckt->CKTreltol * MAX(fabs(vbe), |
|||
fabs(*(ckt->CKTstate0 + inst->NBJTvbe))) + |
|||
ckt->CKTvoltTol))) |
|||
if ((fabs(delVce) < ckt->CKTreltol * MAX(fabs(vce), |
|||
fabs(*(ckt->CKTstate0 + inst->NBJTvce))) + |
|||
ckt->CKTvoltTol)) |
|||
if ((fabs(ichat - *(ckt->CKTstate0 + inst->NBJTic)) < |
|||
ckt->CKTreltol * MAX(fabs(ichat), |
|||
fabs(*(ckt->CKTstate0 + inst->NBJTic))) + |
|||
ckt->CKTabstol)) |
|||
if ((fabs(iehat - *(ckt->CKTstate0 + inst->NBJTie)) < |
|||
ckt->CKTreltol * MAX(fabs(iehat), |
|||
fabs(*(ckt->CKTstate0 + inst->NBJTie))) + |
|||
ckt->CKTabstol)) { |
|||
/* |
|||
* bypassing.... |
|||
*/ |
|||
vbe = *(ckt->CKTstate0 + inst->NBJTvbe); |
|||
vce = *(ckt->CKTstate0 + inst->NBJTvce); |
|||
ic = *(ckt->CKTstate0 + inst->NBJTic); |
|||
ie = *(ckt->CKTstate0 + inst->NBJTie); |
|||
dIeDVce = *(ckt->CKTstate0 + inst->NBJTdIeDVce); |
|||
dIeDVbe = *(ckt->CKTstate0 + inst->NBJTdIeDVbe); |
|||
dIcDVce = *(ckt->CKTstate0 + inst->NBJTdIcDVce); |
|||
dIcDVbe = *(ckt->CKTstate0 + inst->NBJTdIcDVbe); |
|||
goto load; |
|||
} |
|||
#endif /* NOBYPASS */ |
|||
/* |
|||
* limit nonlinear branch voltages |
|||
*/ |
|||
icheck1 = 1; |
|||
vbe = inst->NBJTtype * limitVbe(inst->NBJTtype * vbe, |
|||
inst->NBJTtype * *(ckt->CKTstate0 + inst->NBJTvbe), &icheck); |
|||
/* |
|||
vbc = vbe - vce; |
|||
vbc = inst->NBJTtype * limitVbe(inst->NBJTtype * vbc, |
|||
inst->NBJTtype * (*(ckt->CKTstate0 + inst->NBJTvbe) |
|||
- *(ckt->CKTstate0 + inst->NBJTvce)), &icheck1); |
|||
vce = vbe - vbc; |
|||
*/ |
|||
vce = inst->NBJTtype * limitVce(inst->NBJTtype * vce, |
|||
inst->NBJTtype * *(ckt->CKTstate0 + inst->NBJTvce), &icheck1); |
|||
if (icheck1 == 1) |
|||
icheck = 1; |
|||
delVbe = vbe - *(ckt->CKTstate0 + inst->NBJTvbe); |
|||
delVce = vce - *(ckt->CKTstate0 + inst->NBJTvce); |
|||
} |
|||
if (doInitSolve) { |
|||
if (ONEdcDebug) { |
|||
printVoltages(stdout, |
|||
model->NBJTmodName, inst->NBJTname, |
|||
deviceType, 2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); |
|||
} |
|||
startTime2 = SPfrontEnd->IFseconds(); |
|||
ONEequilSolve(pDevice); |
|||
totalTime2 = SPfrontEnd->IFseconds() - startTime2; |
|||
pDevice->pStats->totalTime[STAT_SETUP] += totalTime2; |
|||
pDevice->pStats->totalTime[STAT_DC] -= totalTime2; |
|||
|
|||
ONEbiasSolve(pDevice, MaxIterations, FALSE, NULL); |
|||
|
|||
*(ckt->CKTstate0 + inst->NBJTvbe) = 0.0; |
|||
*(ckt->CKTstate0 + inst->NBJTvce) = 0.0; |
|||
|
|||
if (initStateName != NULL) { |
|||
if (ONEreadState(pDevice, initStateName, 2, &vce, &vbe ) < 0) { |
|||
fprintf(stderr, |
|||
"NBJTload: trouble reading state-file %s\n", initStateName); |
|||
} else { |
|||
NBJTsetBCs(pDevice, vce, vbe); |
|||
delVce = delVbe = 0.0; |
|||
} |
|||
} |
|||
} |
|||
/* |
|||
* determine dc current and derivatives using the numerical routines |
|||
*/ |
|||
if (ckt->CKTmode & (MODEDCOP | MODETRANOP | MODEDCTRANCURVE | MODEINITSMSIG)) { |
|||
|
|||
numDevNonCon = 0; |
|||
inst->NBJTc11 = inst->NBJTy11r = inst->NBJTy11i = 0.0; |
|||
inst->NBJTc12 = inst->NBJTy12r = inst->NBJTy12i = 0.0; |
|||
inst->NBJTc21 = inst->NBJTy21r = inst->NBJTy21i = 0.0; |
|||
inst->NBJTc22 = inst->NBJTy22r = inst->NBJTy22i = 0.0; |
|||
inst->NBJTsmSigAvail = FALSE; |
|||
devNonCon: |
|||
NBJTproject(pDevice, delVce, delVbe, vbe); |
|||
if (ONEdcDebug) { |
|||
printVoltages(stdout, |
|||
model->NBJTmodName, inst->NBJTname, |
|||
deviceType, 2, vce, delVce, vbe, delVbe, 0.0, 0.0); |
|||
} |
|||
ONEbiasSolve(pDevice, MaxIterations, FALSE, model->NBJTpInfo); |
|||
|
|||
devConverged = pDevice->converged; |
|||
if (devConverged && finite(pDevice->rhsNorm)) { |
|||
/* compute the currents */ |
|||
NBJTcurrent(pDevice, FALSE, (double *) NULL, |
|||
&ie, &ic); |
|||
NBJTconductance(pDevice, FALSE, (double *) NULL, |
|||
&dIeDVce, &dIcDVce, &dIeDVbe, &dIcDVbe); |
|||
/* |
|||
* Add Gmin terms to everything in case we are operating at |
|||
* abnormally low current levels |
|||
*/ |
|||
ie += ckt->CKTgmin * (vce + vbe); |
|||
dIeDVce += ckt->CKTgmin; |
|||
dIeDVbe += ckt->CKTgmin; |
|||
ic += ckt->CKTgmin * (2.0 * vce - vbe); |
|||
dIcDVce += 2.0 * ckt->CKTgmin; |
|||
dIcDVbe -= ckt->CKTgmin; |
|||
|
|||
} else { |
|||
/* reduce the voltage step until converged */ |
|||
/* restore the boundary potential to previous value */ |
|||
NBJTsetBCs(pDevice, vce - delVce, vbe - delVbe); |
|||
ONEstoreInitialGuess(pDevice); |
|||
ONEresetJacobian(pDevice); |
|||
delVbe *= 0.5; |
|||
delVce *= 0.5; |
|||
vbe = delVbe + *(ckt->CKTstate0 + inst->NBJTvbe); |
|||
vce = delVce + *(ckt->CKTstate0 + inst->NBJTvce); |
|||
numDevNonCon++; |
|||
icheck = 1; |
|||
if (numDevNonCon > 10) { |
|||
printVoltages(stderr, |
|||
model->NBJTmodName, inst->NBJTname, |
|||
deviceType, 2, vce, delVce, vbe, delVbe, 0.0, 0.0); |
|||
fprintf(stderr, |
|||
"*** Non-convergence during load ***\n"); |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
return (E_BADMATRIX); |
|||
} else { |
|||
goto devNonCon; |
|||
} |
|||
} |
|||
|
|||
} |
|||
if ((ckt->CKTmode & (MODETRAN | MODEAC)) || |
|||
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) || |
|||
(ckt->CKTmode & MODEINITSMSIG)) { |
|||
/* |
|||
* store small-signal parameters |
|||
*/ |
|||
if ((!(ckt->CKTmode & MODETRANOP)) || |
|||
(!(ckt->CKTmode & MODEUIC))) { |
|||
if (ckt->CKTmode & MODEINITSMSIG) { |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
startTime2 = SPfrontEnd->IFseconds(); |
|||
NBJTinitSmSig(inst); |
|||
pDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime2; |
|||
continue; |
|||
} else { |
|||
inst->NBJTsmSigAvail = FALSE; |
|||
} |
|||
/* |
|||
* transient analysis |
|||
*/ |
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
NBJTsetBCs(pDevice, vce, vbe); |
|||
ONEstoreInitialGuess(pDevice); |
|||
} else { |
|||
NBJTupdate(pDevice, delVce, delVbe, vbe, TRUE); |
|||
} |
|||
if (ONEtranDebug) { |
|||
printVoltages(stdout, |
|||
model->NBJTmodName, inst->NBJTname, |
|||
deviceType, 2, vce, delVce, vbe, delVbe, 0.0, 0.0); |
|||
} |
|||
ONEbiasSolve(pDevice, 0, TRUE, model->NBJTpInfo); |
|||
if (!finite(pDevice->rhsNorm)) { |
|||
/* Timestep took us to never-never land. */ |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
return (E_BADMATRIX); |
|||
} |
|||
devConverged = ONEdeviceConverged(pDevice); |
|||
pDevice->converged = devConverged; |
|||
|
|||
/* compute the currents */ |
|||
NBJTcurrent(pDevice, TRUE, |
|||
model->NBJTpInfo->intCoeff, &ie, &ic); |
|||
NBJTconductance(pDevice, TRUE, |
|||
model->NBJTpInfo->intCoeff, |
|||
&dIeDVce, &dIcDVce, &dIeDVbe, &dIcDVbe); |
|||
|
|||
/* |
|||
* Add Gmin terms to everything in case we are operating at |
|||
* abnormally low current levels |
|||
*/ |
|||
ie += ckt->CKTgmin * (vce + vbe); |
|||
dIeDVce += ckt->CKTgmin; |
|||
dIeDVbe += ckt->CKTgmin; |
|||
ic += ckt->CKTgmin * (2.0 * vce - vbe); |
|||
dIcDVce += 2.0 * ckt->CKTgmin; |
|||
dIcDVbe -= ckt->CKTgmin; |
|||
} |
|||
} |
|||
/* |
|||
* check convergence |
|||
*/ |
|||
if ((!(ckt->CKTmode & MODEINITFIX)) || (!(inst->NBJToff))) { |
|||
if (icheck == 1 || !devConverged) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} else { |
|||
tol = ckt->CKTreltol * MAX(fabs(ichat), fabs(ic)) + ckt->CKTabstol; |
|||
if (fabs(ichat - ic) > tol) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} else { |
|||
tol = ckt->CKTreltol * MAX(fabs(iehat), fabs(ie)) + |
|||
ckt->CKTabstol; |
|||
if (fabs(iehat - ie) > tol) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
*(ckt->CKTstate0 + inst->NBJTvbe) = vbe; |
|||
*(ckt->CKTstate0 + inst->NBJTvce) = vce; |
|||
*(ckt->CKTstate0 + inst->NBJTic) = ic; |
|||
*(ckt->CKTstate0 + inst->NBJTie) = ie; |
|||
*(ckt->CKTstate0 + inst->NBJTdIeDVce) = dIeDVce; |
|||
*(ckt->CKTstate0 + inst->NBJTdIeDVbe) = dIeDVbe; |
|||
*(ckt->CKTstate0 + inst->NBJTdIcDVce) = dIcDVce; |
|||
*(ckt->CKTstate0 + inst->NBJTdIcDVbe) = dIcDVbe; |
|||
|
|||
load: |
|||
/* |
|||
* load current excitation vector |
|||
*/ |
|||
iceq = ic - dIcDVce * vce - dIcDVbe * vbe; |
|||
ieeq = ie - dIeDVce * vce - dIeDVbe * vbe; |
|||
*(ckt->CKTrhs + inst->NBJTcolNode) -= iceq; |
|||
*(ckt->CKTrhs + inst->NBJTbaseNode) -= ieeq - iceq; |
|||
*(ckt->CKTrhs + inst->NBJTemitNode) += ieeq; |
|||
|
|||
/* |
|||
* load y matrix |
|||
*/ |
|||
*(inst->NBJTcolColPtr) += dIcDVce; |
|||
*(inst->NBJTcolBasePtr) += dIcDVbe; |
|||
*(inst->NBJTcolEmitPtr) -= dIcDVbe + dIcDVce; |
|||
*(inst->NBJTbaseColPtr) -= dIcDVce - dIeDVce; |
|||
*(inst->NBJTbaseBasePtr) -= dIcDVbe - dIeDVbe; |
|||
*(inst->NBJTbaseEmitPtr) += dIcDVbe + dIcDVce - dIeDVbe - dIeDVce; |
|||
*(inst->NBJTemitColPtr) -= dIeDVce; |
|||
*(inst->NBJTemitBasePtr) -= dIeDVbe; |
|||
*(inst->NBJTemitEmitPtr) += dIeDVbe + dIeDVce; |
|||
|
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
if (ckt->CKTmode & MODETRAN) { |
|||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime; |
|||
} else { |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
} |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
|
|||
int |
|||
NBJTinitSmSig(inst) |
|||
NBJTinstance *inst; |
|||
{ |
|||
SPcomplex yIeVce, yIeVbe; |
|||
SPcomplex yIcVce, yIcVbe; |
|||
double omega = inst->NBJTmodPtr->NBJTmethods->METHomega; |
|||
|
|||
AcAnalysisMethod = SOR_ONLY; |
|||
(void) NBJTadmittance(inst->NBJTpDevice, omega, |
|||
&yIeVce, &yIcVce, &yIeVbe, &yIcVbe); |
|||
inst->NBJTc11 = yIcVce.imag / omega; |
|||
inst->NBJTc12 = yIcVbe.imag / omega; |
|||
inst->NBJTc21 = (yIeVce.imag - yIcVce.imag) / omega; |
|||
inst->NBJTc22 = (yIeVbe.imag - yIcVbe.imag) / omega; |
|||
inst->NBJTy11r = yIcVce.real; |
|||
inst->NBJTy11i = yIcVce.imag; |
|||
inst->NBJTy12r = yIcVbe.real; |
|||
inst->NBJTy12i = yIcVbe.imag; |
|||
inst->NBJTy21r = yIeVce.real - yIcVce.real; |
|||
inst->NBJTy21i = yIeVce.imag - yIcVce.imag; |
|||
inst->NBJTy22r = yIeVbe.real - yIcVbe.real; |
|||
inst->NBJTy22i = yIeVbe.imag - yIcVbe.imag; |
|||
inst->NBJTsmSigAvail = TRUE; |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine deletes a NBJT model from the circuit and frees the storage |
|||
* it was using. returns an error if the model has instances |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "nbjtdefs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NBJTmDelete(inModel, modname, kill) |
|||
GENmodel **inModel; |
|||
IFuid modname; |
|||
GENmodel *kill; |
|||
|
|||
{ |
|||
|
|||
NBJTmodel **model = (NBJTmodel **) inModel; |
|||
NBJTmodel *modfast = (NBJTmodel *) kill; |
|||
NBJTmodel **oldmod; |
|||
oldmod = model; |
|||
for (; *model; model = &((*model)->NBJTnextModel)) { |
|||
if ((*model)->NBJTmodName == modname || |
|||
(modfast && *model == modfast)) |
|||
goto delgot; |
|||
oldmod = model; |
|||
} |
|||
return (E_NOMOD); |
|||
|
|||
delgot: |
|||
if ((*model)->NBJTinstances) |
|||
return (E_NOTEMPTY); |
|||
*oldmod = (*model)->NBJTnextModel; /* cut deleted device out of list */ |
|||
FREE(*model); |
|||
return (OK); |
|||
|
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine sets model parameters for NBJTs in the circuit. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "nbjtdefs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NBJTmParam(param, value, inModel) |
|||
int param; |
|||
IFvalue *value; |
|||
GENmodel *inModel; |
|||
{ |
|||
switch (param) { |
|||
case NBJT_MOD_NBJT: |
|||
/* no action - already know it is a numerical bjt, but this */ |
|||
/* makes life easier for spice-2 like parsers */ |
|||
break; |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine sets instance parameters for NBJTs in the circuit. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "nbjtdefs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NBJTparam(param, value, inInst, select) |
|||
int param; |
|||
IFvalue *value; |
|||
GENinstance *inInst; |
|||
IFvalue *select; |
|||
{ |
|||
register NBJTinstance *inst = (NBJTinstance *) inInst; |
|||
switch (param) { |
|||
case NBJT_AREA: |
|||
inst->NBJTarea = value->rValue; |
|||
inst->NBJTareaGiven = TRUE; |
|||
break; |
|||
case NBJT_OFF: |
|||
inst->NBJToff = TRUE; |
|||
break; |
|||
case NBJT_IC_FILE: |
|||
inst->NBJTicFile = value->sValue; |
|||
inst->NBJTicFileGiven = TRUE; |
|||
break; |
|||
case NBJT_PRINT: |
|||
inst->NBJTprint = value->rValue; |
|||
inst->NBJTprintGiven = TRUE; |
|||
break; |
|||
case NBJT_TEMP: |
|||
inst->NBJTtemp = value->rValue + CONSTCtoK; |
|||
inst->NBJTtempGiven = TRUE; |
|||
break; |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,92 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* Function to load the COMPLEX circuit matrix using the small signal |
|||
* parameters saved during a previous DC operating point analysis. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "nbjtdefs.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "sperror.h" |
|||
#include "complex.h" |
|||
#include "suffix.h" |
|||
|
|||
/* External Declarations */ |
|||
extern int ONEacDebug; |
|||
|
|||
int |
|||
NBJTpzLoad(inModel, ckt, s) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
SPcomplex *s; |
|||
|
|||
{ |
|||
register NBJTmodel *model = (NBJTmodel *) inModel; |
|||
register NBJTinstance *inst; |
|||
SPcomplex yIeVce, yIeVbe; |
|||
SPcomplex yIcVce, yIcVbe; |
|||
double startTime; |
|||
|
|||
for (; model != NULL; model = model->NBJTnextModel) { |
|||
FieldDepMobility = model->NBJTmodels->MODLfieldDepMobility; |
|||
Srh = model->NBJTmodels->MODLsrh; |
|||
Auger = model->NBJTmodels->MODLauger; |
|||
AvalancheGen = model->NBJTmodels->MODLavalancheGen; |
|||
AcAnalysisMethod = model->NBJTmethods->METHacAnalysisMethod; |
|||
MobDeriv = model->NBJTmethods->METHmobDeriv; |
|||
ONEacDebug = model->NBJToutputs->OUTPacDebug; |
|||
|
|||
for (inst = model->NBJTinstances; inst != NULL; |
|||
inst = inst->NBJTnextInstance) { |
|||
if (inst->NBJTowner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NBJTglobals)); |
|||
|
|||
NBJTys(inst->NBJTpDevice, s, |
|||
&yIeVce, &yIcVce, &yIeVbe, &yIcVbe); |
|||
|
|||
if (ONEacDebug) { |
|||
fprintf(stdout, "BJT admittances: %s:%s at s = % .5g, % .5g\n", |
|||
model->NBJTmodName, inst->NBJTname, s->real, s->imag); |
|||
fprintf(stdout, "Ycc: % .5g,% .5g\n", |
|||
yIcVce.real, yIcVce.imag); |
|||
fprintf(stdout, "Ycb: % .5g,% .5g\n", |
|||
yIcVbe.real, yIcVbe.imag); |
|||
fprintf(stdout, "Ybc: % .5g,% .5g\n", |
|||
yIeVce.real - yIcVce.real, yIeVce.imag - yIcVce.imag); |
|||
fprintf(stdout, "Ybb: % .5g,% .5g\n", |
|||
yIeVbe.real - yIcVbe.real, yIeVbe.imag - yIcVbe.imag); |
|||
} |
|||
*(inst->NBJTcolColPtr) += yIcVce.real; |
|||
*(inst->NBJTcolColPtr + 1) += yIcVce.imag; |
|||
*(inst->NBJTcolBasePtr) += yIcVbe.real; |
|||
*(inst->NBJTcolBasePtr + 1) += yIcVbe.imag; |
|||
*(inst->NBJTcolEmitPtr) -= yIcVbe.real + yIcVce.real; |
|||
*(inst->NBJTcolEmitPtr + 1) -= yIcVbe.imag + yIcVce.imag; |
|||
*(inst->NBJTbaseColPtr) -= yIcVce.real - yIeVce.real; |
|||
*(inst->NBJTbaseColPtr + 1) -= yIcVce.imag - yIeVce.imag; |
|||
*(inst->NBJTbaseBasePtr) -= yIcVbe.real - yIeVbe.real; |
|||
*(inst->NBJTbaseBasePtr + 1) -= yIcVbe.imag - yIeVbe.imag; |
|||
*(inst->NBJTbaseEmitPtr) += yIcVbe.real + yIcVce.real - yIeVbe.real - yIeVce.real; |
|||
*(inst->NBJTbaseEmitPtr + 1) += yIcVbe.imag + yIcVce.imag - yIeVbe.imag - yIeVce.imag; |
|||
*(inst->NBJTemitColPtr) -= yIeVce.real; |
|||
*(inst->NBJTemitColPtr + 1) -= yIeVce.imag; |
|||
*(inst->NBJTemitBasePtr) -= yIeVbe.real; |
|||
*(inst->NBJTemitBasePtr + 1) -= yIeVbe.imag; |
|||
*(inst->NBJTemitEmitPtr) += yIeVbe.real + yIeVce.real; |
|||
*(inst->NBJTemitEmitPtr + 1) += yIeVbe.imag + yIeVce.imag; |
|||
|
|||
inst->NBJTpDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,255 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "smpdefs.h" |
|||
#include "nbjtdefs.h" |
|||
#include "numconst.h" |
|||
#include "numenum.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "ciderinp.h" |
|||
#include "suffix.h" |
|||
|
|||
#define NIL(type) ((type *)0) |
|||
#define TSCALLOC(var, size, type)\ |
|||
if (size && (!(var =(type *)calloc(1, (unsigned)(size)*sizeof(type))))) {\ |
|||
return(E_NOMEM);\ |
|||
} |
|||
|
|||
int |
|||
NBJTsetup(matrix, inModel, ckt, states) |
|||
register SMPmatrix *matrix; |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
int *states; |
|||
/* |
|||
* load the diode structure with those pointers needed later for fast matrix |
|||
* loading |
|||
*/ |
|||
{ |
|||
register NBJTmodel *model = (NBJTmodel *) inModel; |
|||
register NBJTinstance *inst; |
|||
METHcard *methods; |
|||
MODLcard *models; |
|||
OPTNcard *options; |
|||
OUTPcard *outputs; |
|||
char *icFileName = NULL; |
|||
int nameLen; |
|||
int error; |
|||
int xMeshSize; |
|||
ONEdevice *pDevice; |
|||
ONEcoord *xCoordList = NIL(ONEcoord); |
|||
ONEdomain *domainList = NIL(ONEdomain); |
|||
DOPprofile *profileList = NIL(DOPprofile); |
|||
DOPtable *dopTableList = NIL(DOPtable); |
|||
ONEmaterial *pM, *pMaterial = NULL, *materialList = NIL(ONEmaterial); |
|||
double startTime; |
|||
|
|||
|
|||
/* loop through all the diode models */ |
|||
for (; model != NULL; model = model->NBJTnextModel) { |
|||
if (!model->NBJTpInfo) { |
|||
TSCALLOC(model->NBJTpInfo, 1, ONEtranInfo); |
|||
} |
|||
methods = model->NBJTmethods; |
|||
if (!methods) { |
|||
TSCALLOC(methods, 1, METHcard); |
|||
model->NBJTmethods = methods; |
|||
} |
|||
models = model->NBJTmodels; |
|||
if (!models) { |
|||
TSCALLOC(models, 1, MODLcard); |
|||
model->NBJTmodels = models; |
|||
} |
|||
options = model->NBJToptions; |
|||
if (!options) { |
|||
TSCALLOC(options, 1, OPTNcard); |
|||
model->NBJToptions = options; |
|||
} |
|||
outputs = model->NBJToutputs; |
|||
if (!outputs) { |
|||
TSCALLOC(outputs, 1, OUTPcard); |
|||
model->NBJToutputs = outputs; |
|||
} |
|||
if (!methods->METHvoltPredGiven) { |
|||
methods->METHvoltPred = FALSE; |
|||
} |
|||
if (!methods->METHmobDerivGiven) { |
|||
methods->METHmobDeriv = TRUE; |
|||
} |
|||
if (!methods->METHoneCarrierGiven) { |
|||
methods->METHoneCarrier = FALSE; |
|||
} |
|||
if (!methods->METHacAnalysisMethodGiven) { |
|||
methods->METHacAnalysisMethod = SOR; |
|||
} |
|||
if (!methods->METHdabstolGiven) { |
|||
methods->METHdabstol = DABSTOL1D; |
|||
} |
|||
if (!methods->METHdreltolGiven) { |
|||
methods->METHdreltol = ckt->CKTreltol; |
|||
} |
|||
if (!methods->METHitLimGiven) { |
|||
methods->METHitLim = 20; |
|||
} |
|||
if (!methods->METHomegaGiven || methods->METHomega <= 0.0) { |
|||
methods->METHomega = 2.0 * M_PI /* radians/sec */ ; |
|||
} |
|||
if (!options->OPTNdefaGiven || options->OPTNdefa <= 0.0) { |
|||
options->OPTNdefa = 1.0e4 /* cm^2 */ ; |
|||
} |
|||
if (!options->OPTNbaseLengthGiven) { |
|||
options->OPTNbaseLength = 0.0; |
|||
} |
|||
if (!options->OPTNbaseAreaGiven) { |
|||
options->OPTNbaseArea = 1.0; |
|||
} |
|||
if (!options->OPTNdeviceTypeGiven) { |
|||
options->OPTNdeviceType = OPTN_BIPOLAR; |
|||
} |
|||
if (!options->OPTNicFileGiven) { |
|||
options->OPTNicFile = NULL; |
|||
options->OPTNunique = FALSE; /* Can't form a unique name. */ |
|||
} |
|||
if (!options->OPTNuniqueGiven) { |
|||
options->OPTNunique = FALSE; |
|||
} |
|||
|
|||
/* Set up the rest of the card lists */ |
|||
if ((error = MODLsetup(model->NBJTmodels))) |
|||
return (error); |
|||
BandGapNarrowing = models->MODLbandGapNarrowing; |
|||
ConcDepLifetime = models->MODLconcDepLifetime; |
|||
TempDepMobility = models->MODLtempDepMobility; |
|||
ConcDepMobility = models->MODLconcDepMobility; |
|||
|
|||
if ((error = OUTPsetup(model->NBJToutputs))) |
|||
return (error); |
|||
if ((error = MATLsetup(model->NBJTmaterials, &materialList))) |
|||
return (error); |
|||
if ((error = MOBsetup(model->NBJTmobility, materialList))) |
|||
return (error); |
|||
if ((error = MESHsetup('x', model->NBJTxMeshes, &xCoordList, &xMeshSize))) |
|||
return (error); |
|||
if ((error = DOMNsetup(model->NBJTdomains, &domainList, |
|||
xCoordList, NIL(ONEcoord), materialList))) |
|||
return (error); |
|||
if ((error = BDRYsetup(model->NBJTboundaries, |
|||
xCoordList, NIL(ONEcoord), domainList))) |
|||
return (error); |
|||
if ((error = CONTsetup(model->NBJTcontacts, NULL))) |
|||
return (error); |
|||
if ((error = DOPsetup(model->NBJTdopings, &profileList, |
|||
&dopTableList, xCoordList, NIL(ONEcoord)))) |
|||
return (error); |
|||
model->NBJTmatlInfo = materialList; |
|||
model->NBJTprofiles = profileList; |
|||
model->NBJTdopTables = dopTableList; |
|||
|
|||
/* loop through all the instances of the model */ |
|||
for (inst = model->NBJTinstances; inst != NULL; |
|||
inst = inst->NBJTnextInstance) { |
|||
if (inst->NBJTowner != ARCHme) goto matrixpointers; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
if (!inst->NBJTprintGiven) { |
|||
inst->NBJTprint = 0; |
|||
} else if (inst->NBJTprint <= 0) { |
|||
inst->NBJTprint = 1; |
|||
} |
|||
if (!inst->NBJTicFileGiven) { |
|||
if (options->OPTNunique) { |
|||
nameLen = strlen(options->OPTNicFile) + strlen(inst->NBJTname) + 1; |
|||
TSCALLOC(icFileName, nameLen+1, char); |
|||
sprintf(icFileName, "%s.%s", options->OPTNicFile, inst->NBJTname); |
|||
icFileName[nameLen] = '\0'; |
|||
inst->NBJTicFile = icFileName; |
|||
} else if (options->OPTNicFile != NULL) { |
|||
nameLen = strlen(options->OPTNicFile); |
|||
TSCALLOC(icFileName, nameLen+1, char); |
|||
icFileName = strcpy(icFileName, options->OPTNicFile); |
|||
inst->NBJTicFile = icFileName; |
|||
} else { |
|||
inst->NBJTicFile = NULL; |
|||
} |
|||
} |
|||
inst->NBJTstate = *states; |
|||
*states += NBJTnumStates; |
|||
|
|||
if (!inst->NBJTpDevice) { |
|||
/* Assign the mesh info to each instance. */ |
|||
TSCALLOC(pDevice, 1, ONEdevice); |
|||
TSCALLOC(pDevice->pStats, 1, ONEstats); |
|||
pDevice->name = inst->NBJTname; |
|||
pDevice->solverType = SLV_NONE; |
|||
pDevice->numNodes = xMeshSize; |
|||
pDevice->abstol = methods->METHdabstol; |
|||
pDevice->reltol = methods->METHdreltol; |
|||
pDevice->rhsImag = NIL(double); |
|||
TSCALLOC(pDevice->elemArray, pDevice->numNodes, ONEelem *); |
|||
|
|||
/* Create a copy of material data that can change with temperature. */ |
|||
pDevice->pMaterials = NIL(ONEmaterial); |
|||
for (pM = materialList; pM != NIL(ONEmaterial); pM = pM->next) { |
|||
if (pDevice->pMaterials == NIL(ONEmaterial)) { |
|||
TSCALLOC(pMaterial, 1, ONEmaterial); |
|||
pDevice->pMaterials = pMaterial; |
|||
} else { |
|||
TSCALLOC(pMaterial->next, 1, ONEmaterial); |
|||
pMaterial = pMaterial->next; |
|||
} |
|||
/* Copy everything, then fix the incorrect pointer. */ |
|||
bcopy((char *) pM, (char *) pMaterial, sizeof(ONEmaterial)); |
|||
pMaterial->next = NIL(ONEmaterial); |
|||
} |
|||
|
|||
/* generate the mesh structure for the device */ |
|||
ONEbuildMesh(pDevice, xCoordList, domainList, pDevice->pMaterials); |
|||
|
|||
if (options->OPTNbaseDepthGiven) { |
|||
/* The base contact depth has been specified in the input. */ |
|||
pDevice->baseIndex = MESHlocate(xCoordList, options->OPTNbaseDepth); |
|||
} else { |
|||
pDevice->baseIndex = -1; /* Invalid index acts as a flag */ |
|||
} |
|||
/* store the device info in the instance */ |
|||
inst->NBJTpDevice = pDevice; |
|||
} |
|||
/* Now update the state pointers. */ |
|||
ONEgetStatePointers(inst->NBJTpDevice, states); |
|||
|
|||
/* Wipe out statistics from previous runs (if any). */ |
|||
bzero((char *) inst->NBJTpDevice->pStats, sizeof(ONEstats)); |
|||
|
|||
inst->NBJTpDevice->pStats->totalTime[STAT_SETUP] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
|
|||
/* macro to make elements with built in test for out of memory */ |
|||
#define TSTALLOC(ptr,first,second) \ |
|||
if ((inst->ptr = SMPmakeElt(matrix,inst->first,inst->second))==(double *)NULL){\ |
|||
return(E_NOMEM);\ |
|||
} |
|||
|
|||
matrixpointers: |
|||
TSTALLOC(NBJTcolColPtr, NBJTcolNode, NBJTcolNode) |
|||
TSTALLOC(NBJTbaseBasePtr, NBJTbaseNode, NBJTbaseNode) |
|||
TSTALLOC(NBJTemitEmitPtr, NBJTemitNode, NBJTemitNode) |
|||
TSTALLOC(NBJTcolBasePtr, NBJTcolNode, NBJTbaseNode) |
|||
TSTALLOC(NBJTcolEmitPtr, NBJTcolNode, NBJTemitNode) |
|||
TSTALLOC(NBJTbaseColPtr, NBJTbaseNode, NBJTcolNode) |
|||
TSTALLOC(NBJTbaseEmitPtr, NBJTbaseNode, NBJTemitNode) |
|||
TSTALLOC(NBJTemitColPtr, NBJTemitNode, NBJTcolNode) |
|||
TSTALLOC(NBJTemitBasePtr, NBJTemitNode, NBJTbaseNode) |
|||
} |
|||
/* Clean up lists */ |
|||
killCoordInfo(xCoordList); |
|||
killDomainInfo(domainList); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,160 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
Author: 1992 David A. Gates, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "nbjtdefs.h" |
|||
#include "numenum.h" |
|||
#include "carddefs.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
#define NIL(type) ((type *)0) |
|||
extern int ONEdcDebug; |
|||
extern double LNorm; |
|||
|
|||
int |
|||
NBJTtemp(inModel, ckt) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
/* |
|||
* perform the temperature update to the bjt |
|||
*/ |
|||
{ |
|||
register NBJTmodel *model = (NBJTmodel *) inModel; |
|||
register NBJTinstance *inst; |
|||
METHcard *methods; |
|||
MODLcard *models; |
|||
OPTNcard *options; |
|||
OUTPcard *outputs; |
|||
ONEmaterial *pM, *pMaterial, *pNextMaterial; |
|||
ONEdevice *pDevice; |
|||
double startTime; |
|||
int baseIndex, indexBE, indexBC; |
|||
|
|||
|
|||
/* loop through all the bjt models */ |
|||
for (; model != NULL; model = model->NBJTnextModel) { |
|||
methods = model->NBJTmethods; |
|||
models = model->NBJTmodels; |
|||
options = model->NBJToptions; |
|||
outputs = model->NBJToutputs; |
|||
|
|||
if (!options->OPTNtnomGiven) { |
|||
options->OPTNtnom = ckt->CKTnomTemp; |
|||
} |
|||
for (pM = model->NBJTmatlInfo; pM != NIL(ONEmaterial); pM = pM->next) { |
|||
pM->tnom = options->OPTNtnom; |
|||
} |
|||
|
|||
BandGapNarrowing = models->MODLbandGapNarrowing; |
|||
ConcDepLifetime = models->MODLconcDepLifetime; |
|||
TempDepMobility = models->MODLtempDepMobility; |
|||
ConcDepMobility = models->MODLconcDepMobility; |
|||
|
|||
for (inst = model->NBJTinstances; inst != NULL; |
|||
inst = inst->NBJTnextInstance) { |
|||
if (inst->NBJTowner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
if (!inst->NBJTtempGiven) { |
|||
inst->NBJTtemp = ckt->CKTtemp; |
|||
} |
|||
if (!inst->NBJTareaGiven || inst->NBJTarea <= 0.0) { |
|||
inst->NBJTarea = 1.0; |
|||
} |
|||
inst->NBJTpDevice->area = inst->NBJTarea * options->OPTNdefa; |
|||
|
|||
/* Compute and save globals for this instance. */ |
|||
GLOBcomputeGlobals(&(inst->NBJTglobals), inst->NBJTtemp); |
|||
|
|||
/* Calculate new sets of material parameters. */ |
|||
pM = model->NBJTmatlInfo; |
|||
pMaterial = inst->NBJTpDevice->pMaterials; |
|||
for (; pM != NULL; pM = pM->next, pMaterial = pMaterial->next) { |
|||
|
|||
/* Copy the original values, then fix the incorrect pointer. */ |
|||
pNextMaterial = pMaterial->next; |
|||
bcopy((char *) pM, (char *) pMaterial, sizeof(ONEmaterial)); |
|||
pMaterial->next = pNextMaterial; |
|||
|
|||
/* Now do the temperature dependence. */ |
|||
MATLtempDep(pMaterial, pMaterial->tnom); |
|||
if (outputs->OUTPmaterial) { |
|||
printMaterialInfo(pMaterial); |
|||
} |
|||
} |
|||
|
|||
/* Assign doping to the mesh. */ |
|||
ONEsetDoping(inst->NBJTpDevice, model->NBJTprofiles, |
|||
model->NBJTdopTables); |
|||
|
|||
/* Assign other physical parameters to the mesh. */ |
|||
ONEsetup(inst->NBJTpDevice); |
|||
|
|||
/* Assign boundary condition parameters. */ |
|||
ONEsetBCparams(inst->NBJTpDevice, model->NBJTboundaries, |
|||
model->NBJTcontacts); |
|||
|
|||
/* Normalize everything. */ |
|||
ONEnormalize(inst->NBJTpDevice); |
|||
|
|||
/* Find the device's type. */ |
|||
if (inst->NBJTpDevice->elemArray[1]->pNodes[0]->netConc < 0.0) { |
|||
inst->NBJTtype = PNP; |
|||
} else { |
|||
inst->NBJTtype = NPN; |
|||
} |
|||
|
|||
/* Find the location of the base index. */ |
|||
pDevice = inst->NBJTpDevice; |
|||
baseIndex = pDevice->baseIndex; |
|||
if (baseIndex <= 0) { |
|||
if (options->OPTNbaseDepthGiven) { |
|||
printf("Warning: base contact not on node -- adjusting contact\n"); |
|||
} |
|||
NBJTjunctions(pDevice, &indexBE, &indexBC); |
|||
pDevice->baseIndex = 0.5 * (indexBE + indexBC); |
|||
} |
|||
if (inst->NBJTtype == PNP) { |
|||
pDevice->elemArray[pDevice->baseIndex]->pNodes[0]->baseType = N_TYPE; |
|||
} else if (inst->NBJTtype == NPN) { |
|||
pDevice->elemArray[pDevice->baseIndex]->pNodes[0]->baseType = P_TYPE; |
|||
} else { |
|||
printf("NBJTtemp: unknown BJT type \n"); |
|||
} |
|||
if (baseIndex <= 0 && !options->OPTNbaseDepthGiven) { |
|||
ONEdcDebug = FALSE; |
|||
ONEequilSolve(pDevice); |
|||
adjustBaseContact(pDevice, indexBE, indexBC); |
|||
} |
|||
printf("BJT: base contact depth is %g um at node %d\n", |
|||
pDevice->elemArray[pDevice->baseIndex]->pNodes[0]->x * 1e4, |
|||
pDevice->baseIndex); |
|||
|
|||
/* Find, normalize and convert to reciprocal-form the base length. */ |
|||
pDevice->baseLength = options->OPTNbaseLength; |
|||
if (pDevice->baseLength > 0.0) { |
|||
pDevice->baseLength /= LNorm; |
|||
pDevice->baseLength = 1.0 / pDevice->baseLength; |
|||
} else if (pDevice->elemArray[pDevice->baseIndex]->evalNodes[0]) { |
|||
pDevice->baseLength = pDevice->elemArray[pDevice->baseIndex]->rDx; |
|||
} else { |
|||
pDevice->baseLength = pDevice->elemArray[pDevice->baseIndex - 1]->rDx; |
|||
} |
|||
/* Adjust reciprocal base length to account for base area factor */ |
|||
pDevice->baseLength *= options->OPTNbaseArea; |
|||
|
|||
inst->NBJTpDevice->pStats->totalTime[STAT_SETUP] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
|
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine performs truncation error calculations for NBJTs in the |
|||
* circuit. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "nbjtdefs.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
int |
|||
NBJTtrunc(inModel, ckt, timeStep) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
double *timeStep; |
|||
|
|||
{ |
|||
register NBJTmodel *model = (NBJTmodel *) inModel; |
|||
register NBJTinstance *inst; |
|||
double deltaNew; |
|||
double deltaNorm[7]; |
|||
double startTime; |
|||
int i; |
|||
|
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
for (; model != NULL; model = model->NBJTnextModel) { |
|||
model->NBJTpInfo->order = ckt->CKTorder; |
|||
model->NBJTpInfo->delta = deltaNorm; |
|||
model->NBJTpInfo->lteCoeff = computeLTECoeff(model->NBJTpInfo); |
|||
for (inst = model->NBJTinstances; inst != NULL; |
|||
inst = inst->NBJTnextInstance) { |
|||
if (inst->NBJTowner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
deltaNew = ONEtrunc(inst->NBJTpDevice, model->NBJTpInfo, |
|||
ckt->CKTdelta); |
|||
*timeStep = MIN(*timeStep, deltaNew); |
|||
inst->NBJTpDevice->pStats->totalTime[STAT_TRAN] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
## Process this file with automake to produce Makefile.in
|
|||
|
|||
noinst_LIBRARIES = libnbjt2.a |
|||
|
|||
libnbjt2_a_SOURCES = \
|
|||
nbt2.c \
|
|||
nbt2acld.c \
|
|||
nbt2ask.c \
|
|||
nbjt2defs.h \
|
|||
nbt2del.c \
|
|||
nbt2dest.c \
|
|||
nbt2dump.c \
|
|||
nbjt2ext.h \
|
|||
nbt2init.c \
|
|||
nbt2init.h \
|
|||
nbjt2itf.h \
|
|||
nbt2load.c \
|
|||
nbt2mdel.c \
|
|||
nbt2mpar.c \
|
|||
nbt2parm.c \
|
|||
nbt2pzld.c \
|
|||
nbt2set.c \
|
|||
nbt2temp.c \
|
|||
nbt2trun.c |
|||
|
|||
|
|||
|
|||
INCLUDES = -I$(top_srcdir)/src/include |
|||
|
|||
MAINTAINERCLEANFILES = Makefile.in |
|||
@ -0,0 +1,170 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Authors: 1987 Karti Mayaram, 1991 David Gates |
|||
**********/ |
|||
|
|||
#ifndef NBJT2_H |
|||
#define NBJT2_H "NBJT2defs.h $Revision$ on $Date$ " |
|||
|
|||
/* structures to describe 2d Numerical Bipolar Junction Transistors */ |
|||
|
|||
/* circuit level includes */ |
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "gendefs.h" |
|||
|
|||
/* device level includes */ |
|||
#include "twomesh.h" |
|||
#include "twodev.h" |
|||
#include "profile.h" |
|||
#include "numglobs.h" |
|||
#include "carddefs.h" |
|||
|
|||
/* information needed per instance */ |
|||
typedef struct sNBJT2instance { |
|||
struct sNBJT2model *NBJT2modPtr; /* back pointer to model */ |
|||
struct sNBJT2instance *NBJT2nextInstance; /* pointer to next instance |
|||
* of current model */ |
|||
IFuid NBJT2name; /* pointer to character string naming this |
|||
* instance */ |
|||
int NBJT2owner; /* number of owner process */ |
|||
int NBJT2state; /* pointer to start of state vector for bjt */ |
|||
|
|||
/* entries in the state vector for bjt: */ |
|||
#define NBJT2vbe NBJT2state |
|||
#define NBJT2vce NBJT2state+1 |
|||
#define NBJT2ic NBJT2state+2 |
|||
#define NBJT2ie NBJT2state+3 |
|||
#define NBJT2dIeDVce NBJT2state+4 |
|||
#define NBJT2dIeDVbe NBJT2state+5 |
|||
#define NBJT2dIcDVce NBJT2state+6 |
|||
#define NBJT2dIcDVbe NBJT2state+7 |
|||
#define NBJT2numStates 8 |
|||
|
|||
int NBJT2colNode; /* number of collector node of bjt */ |
|||
int NBJT2baseNode; /* number of base node of bjt */ |
|||
int NBJT2emitNode; /* number of emitter node of bjt */ |
|||
double NBJT2width; /* width factor for the bjt */ |
|||
double NBJT2area; /* area factor for the bjt */ |
|||
TWOdevice *NBJT2pDevice; |
|||
GLOBvalues NBJT2globals; /* Temp.-Dep. Global Parameters */ |
|||
int NBJT2type; |
|||
double NBJT2temp; /* Instance Temperature */ |
|||
double NBJT2c11; /* small-signal capacitance */ |
|||
double NBJT2y11r; /* small-signal admittance, real part */ |
|||
double NBJT2y11i; /* small-signal admittance, imag part */ |
|||
double NBJT2c12; /* small-signal capacitance */ |
|||
double NBJT2y12r; /* small-signal admittance, real part */ |
|||
double NBJT2y12i; /* small-signal admittance, imag part */ |
|||
double NBJT2c21; /* small-signal capacitance */ |
|||
double NBJT2y21r; /* small-signal admittance, real part */ |
|||
double NBJT2y21i; /* small-signal admittance, imag part */ |
|||
double NBJT2c22; /* small-signal capacitance */ |
|||
double NBJT2y22r; /* small-signal admittance, real part */ |
|||
double NBJT2y22i; /* small-signal admittance, imag part */ |
|||
int NBJT2print; |
|||
char *NBJT2icFile; /* Name of initial condition file */ |
|||
double *NBJT2colColPtr; /* pointer to sparse matrix at |
|||
* (collector,collector) */ |
|||
double *NBJT2baseBasePtr; /* pointer to sparse matrix at (base,base) */ |
|||
double *NBJT2emitEmitPtr; /* pointer to sparse matrix at |
|||
* (emitter,emitter) */ |
|||
double *NBJT2colBasePtr; /* pointer to sparse matrix at |
|||
* (collector,base) */ |
|||
double *NBJT2colEmitPtr; /* pointer to sparse matrix at |
|||
* (collector,emitter) */ |
|||
double *NBJT2baseColPtr; /* pointer to sparse matrix at |
|||
* (base,collector) */ |
|||
double *NBJT2baseEmitPtr; /* pointer to sparse matrix at (base,emitter) */ |
|||
double *NBJT2emitColPtr; /* pointer to sparse matrix at |
|||
* (emitter,collector) */ |
|||
double *NBJT2emitBasePtr; /* pointer to sparse matrix at (emitter,base) */ |
|||
int NBJT2off; /* 'off' flag for bjt */ |
|||
unsigned NBJT2smSigAvail:1; /* flag to indicate small-signal done */ |
|||
unsigned NBJT2widthGiven:1; /* flag to indicate width was specified */ |
|||
unsigned NBJT2areaGiven:1; /* flag to indicate area was specified */ |
|||
unsigned NBJT2icFileGiven:1; /* flag to indicate init. cond. file given */ |
|||
unsigned NBJT2printGiven:1; /* flag to indicate print given */ |
|||
unsigned NBJT2tempGiven:1; /* flag to indicate temp given */ |
|||
} NBJT2instance; |
|||
|
|||
/* per model data */ |
|||
typedef struct sNBJT2model { /* model structure for a bjt */ |
|||
int NBJT2modType; /* type index of this device type */ |
|||
struct sNBJT2model *NBJT2nextModel; /* pointer to next possible model in |
|||
* linked list */ |
|||
NBJT2instance *NBJT2instances;/* pointer to list of instances that have |
|||
* this model */ |
|||
IFuid NBJT2modName; /* pointer to character string naming this |
|||
* model */ |
|||
/* Everything below here is numerical-device-specific */ |
|||
MESHcard *NBJT2xMeshes; /* list of xmesh cards */ |
|||
MESHcard *NBJT2yMeshes; /* list of ymesh cards */ |
|||
DOMNcard *NBJT2domains; /* list of domain cards */ |
|||
BDRYcard *NBJT2boundaries; /* list of boundary cards */ |
|||
DOPcard *NBJT2dopings; /* list of doping cards */ |
|||
ELCTcard *NBJT2electrodes; /* list of electrode cards */ |
|||
CONTcard *NBJT2contacts; /* list of contact cards */ |
|||
MODLcard *NBJT2models; /* list of model cards */ |
|||
MATLcard *NBJT2materials; /* list of material cards */ |
|||
MOBcard *NBJT2mobility; /* list of mobility cards */ |
|||
METHcard *NBJT2methods; /* list of method cards */ |
|||
OPTNcard *NBJT2options; /* list of option cards */ |
|||
OUTPcard *NBJT2outputs; /* list of output cards */ |
|||
TWOtranInfo *NBJT2pInfo; /* transient analysis information */ |
|||
DOPprofile *NBJT2profiles; /* expanded list of doping profiles */ |
|||
DOPtable *NBJT2dopTables; /* list of tables used by profiles */ |
|||
TWOmaterial *NBJT2matlInfo; /* list of material info structures */ |
|||
} NBJT2model; |
|||
|
|||
/* type of 2D BJT */ |
|||
#define NPN 1 |
|||
#define PNP -1 |
|||
|
|||
/* device parameters */ |
|||
#define NBJT2_WIDTH 1 |
|||
#define NBJT2_AREA 2 |
|||
#define NBJT2_OFF 3 |
|||
#define NBJT2_IC_FILE 4 |
|||
#define NBJT2_PRINT 7 |
|||
#define NBJT2_TEMP 8 |
|||
|
|||
#define NBJT2_G11 9 |
|||
#define NBJT2_C11 10 |
|||
#define NBJT2_Y11 11 |
|||
#define NBJT2_G12 12 |
|||
#define NBJT2_C12 13 |
|||
#define NBJT2_Y12 14 |
|||
#define NBJT2_G13 15 |
|||
#define NBJT2_C13 16 |
|||
#define NBJT2_Y13 17 |
|||
#define NBJT2_G21 18 |
|||
#define NBJT2_C21 19 |
|||
#define NBJT2_Y21 20 |
|||
#define NBJT2_G22 21 |
|||
#define NBJT2_C22 22 |
|||
#define NBJT2_Y22 23 |
|||
#define NBJT2_G23 24 |
|||
#define NBJT2_C23 25 |
|||
#define NBJT2_Y23 26 |
|||
#define NBJT2_G31 27 |
|||
#define NBJT2_C31 28 |
|||
#define NBJT2_Y31 29 |
|||
#define NBJT2_G32 30 |
|||
#define NBJT2_C32 31 |
|||
#define NBJT2_Y32 32 |
|||
#define NBJT2_G33 33 |
|||
#define NBJT2_C33 34 |
|||
#define NBJT2_Y33 35 |
|||
|
|||
/* model parameters */ |
|||
/* NOTE: all true model parameters have been moved to IFcardInfo structures */ |
|||
#define NBJT2_MOD_NBJT 1 |
|||
|
|||
/* device questions */ |
|||
|
|||
/* model questions */ |
|||
|
|||
#include "nbjt2ext.h" |
|||
|
|||
#endif /* NBJT2_H */ |
|||
@ -0,0 +1,27 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Karti Mayaram |
|||
**********/ |
|||
|
|||
#ifndef NBJT2EXT_H |
|||
#define NBJT2EXT_H |
|||
|
|||
|
|||
extern int NBJT2acLoad(GENmodel *, CKTcircuit *); |
|||
extern int NBJT2ask(CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *); |
|||
extern int NBJT2delete(GENmodel *, IFuid, GENinstance **); |
|||
extern void NBJT2destroy(GENmodel **); |
|||
extern int NBJT2getic(GENmodel *, CKTcircuit *); |
|||
extern int NBJT2load(GENmodel *, CKTcircuit *); |
|||
extern int NBJT2mDelete(GENmodel **, IFuid, GENmodel *); |
|||
extern int NBJT2mParam(int, IFvalue *, GENmodel *); |
|||
extern int NBJT2param(int, IFvalue *, GENinstance *, IFvalue *); |
|||
extern int NBJT2pzLoad(GENmodel *, CKTcircuit *, SPcomplex *); |
|||
extern int NBJT2setup(SMPmatrix *, GENmodel *, CKTcircuit *, int *); |
|||
extern int NBJT2temp(GENmodel *, CKTcircuit *); |
|||
extern int NBJT2trunc(GENmodel *, CKTcircuit *, double *); |
|||
|
|||
extern void NBJT2dump(GENmodel *, CKTcircuit *); |
|||
extern void NBJT2acct(GENmodel *, CKTcircuit *, FILE *); |
|||
|
|||
#endif /* NBJT2EXT_H */ |
|||
@ -0,0 +1,10 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
**********/ |
|||
|
|||
#ifndef DEV_NBJT2 |
|||
#define DEV_NBJT2 |
|||
|
|||
extern SPICEdev *get_nbjt2_info(void); |
|||
|
|||
#endif |
|||
@ -0,0 +1,71 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "devdefs.h" |
|||
#include "nbjt2def.h" |
|||
#include "suffix.h" |
|||
|
|||
/* |
|||
* This file defines the 2d Numerical BJT data structures that are available |
|||
* to the next level(s) up the calling hierarchy |
|||
*/ |
|||
|
|||
IFparm NBJT2pTable[] = { /* parameters */ |
|||
IP("off", NBJT2_OFF, IF_FLAG, "Device initially off"), |
|||
IP("ic.file", NBJT2_IC_FILE, IF_STRING, "Initial condition file"), |
|||
IOP("w", NBJT2_WIDTH, IF_REAL, "Width factor"), |
|||
IOP("area", NBJT2_AREA, IF_REAL, "Area factor"), |
|||
IP("save", NBJT2_PRINT, IF_REAL, "Save solutions"), |
|||
IP("print", NBJT2_PRINT, IF_REAL, "Print solutions"), |
|||
OP("g11", NBJT2_G11, IF_REAL, "Conductance"), |
|||
OP("c11", NBJT2_C11, IF_REAL, "Capacitance"), |
|||
OP("y11", NBJT2_Y11, IF_COMPLEX, "Admittance"), |
|||
OP("g12", NBJT2_G12, IF_REAL, "Conductance"), |
|||
OP("c12", NBJT2_C12, IF_REAL, "Capacitance"), |
|||
OP("y12", NBJT2_Y12, IF_COMPLEX, "Admittance"), |
|||
OPU("g13", NBJT2_G13, IF_REAL, "Conductance"), |
|||
OPU("c13", NBJT2_C13, IF_REAL, "Capacitance"), |
|||
OPU("y13", NBJT2_Y13, IF_COMPLEX, "Admittance"), |
|||
OP("g21", NBJT2_G21, IF_REAL, "Conductance"), |
|||
OP("c21", NBJT2_C21, IF_REAL, "Capacitance"), |
|||
OP("y21", NBJT2_Y21, IF_COMPLEX, "Admittance"), |
|||
OP("g22", NBJT2_G22, IF_REAL, "Conductance"), |
|||
OP("c22", NBJT2_C22, IF_REAL, "Capacitance"), |
|||
OP("y22", NBJT2_Y22, IF_COMPLEX, "Admittance"), |
|||
OPU("g23", NBJT2_G23, IF_REAL, "Conductance"), |
|||
OPU("c23", NBJT2_C23, IF_REAL, "Capacitance"), |
|||
OPU("y23", NBJT2_Y23, IF_COMPLEX, "Admittance"), |
|||
OPU("g31", NBJT2_G31, IF_REAL, "Conductance"), |
|||
OPU("c31", NBJT2_C31, IF_REAL, "Capacitance"), |
|||
OPU("y31", NBJT2_Y31, IF_COMPLEX, "Admittance"), |
|||
OPU("g32", NBJT2_G32, IF_REAL, "Conductance"), |
|||
OPU("c32", NBJT2_C32, IF_REAL, "Capacitance"), |
|||
OPU("y32", NBJT2_Y32, IF_COMPLEX, "Admittance"), |
|||
OPU("g33", NBJT2_G33, IF_REAL, "Conductance"), |
|||
OPU("c33", NBJT2_C33, IF_REAL, "Capacitance"), |
|||
OPU("y33", NBJT2_Y33, IF_COMPLEX, "Admittance"), |
|||
IOP("temp", NBJT2_TEMP, IF_REAL, "Instance Temperature") |
|||
}; |
|||
|
|||
IFparm NBJT2mPTable[] = { /* model parameters */ |
|||
/* numerical-device models no longer have parameters */ |
|||
/* one is left behind to keep the table from being empty */ |
|||
IP("nbjt", NBJT2_MOD_NBJT, IF_FLAG, "Numerical BJT Model") |
|||
}; |
|||
|
|||
|
|||
char *NBJT2names[] = { |
|||
"Collector", |
|||
"Base", |
|||
"Emitter", |
|||
"Substrate" |
|||
}; |
|||
|
|||
int NBJT2nSize = NUMELEMS(NBJT2names); |
|||
int NBJT2pTSize = NUMELEMS(NBJT2pTable); |
|||
int NBJT2mPTSize = NUMELEMS(NBJT2mPTable); |
|||
int NBJT2iSize = sizeof(NBJT2instance); |
|||
int NBJT2mSize = sizeof(NBJT2model); |
|||
@ -0,0 +1,103 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* Function to load the COMPLEX circuit matrix using the small signal |
|||
* parameters saved during a previous DC operating point analysis. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "nbjt2def.h" |
|||
#include "sperror.h" |
|||
#include "complex.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
/* External Declarations */ |
|||
extern int TWOacDebug; |
|||
|
|||
int |
|||
NBJT2acLoad(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
|
|||
{ |
|||
register NBJT2model *model = (NBJT2model *) inModel; |
|||
register NBJT2instance *inst; |
|||
SPcomplex yIeVce, yIeVbe; |
|||
SPcomplex yIcVce, yIcVbe; |
|||
double startTime; |
|||
|
|||
for (; model != NULL; model = model->NBJT2nextModel) { |
|||
FieldDepMobility = model->NBJT2models->MODLfieldDepMobility; |
|||
TransDepMobility = model->NBJT2models->MODLtransDepMobility; |
|||
SurfaceMobility = model->NBJT2models->MODLsurfaceMobility; |
|||
Srh = model->NBJT2models->MODLsrh; |
|||
Auger = model->NBJT2models->MODLauger; |
|||
AvalancheGen = model->NBJT2models->MODLavalancheGen; |
|||
OneCarrier = model->NBJT2methods->METHoneCarrier; |
|||
AcAnalysisMethod = model->NBJT2methods->METHacAnalysisMethod; |
|||
MobDeriv = model->NBJT2methods->METHmobDeriv; |
|||
TWOacDebug = model->NBJT2outputs->OUTPacDebug; |
|||
|
|||
for (inst = model->NBJT2instances; inst != NULL; |
|||
inst = inst->NBJT2nextInstance) { |
|||
if (inst->NBJT2owner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NBJT2globals)); |
|||
|
|||
model->NBJT2methods->METHacAnalysisMethod = |
|||
NBJT2admittance(inst->NBJT2pDevice, ckt->CKTomega, |
|||
&yIeVce, &yIcVce, &yIeVbe, &yIcVbe); |
|||
|
|||
*(inst->NBJT2colColPtr) += yIcVce.real; |
|||
*(inst->NBJT2colColPtr + 1) += yIcVce.imag; |
|||
*(inst->NBJT2colBasePtr) += yIcVbe.real; |
|||
*(inst->NBJT2colBasePtr + 1) += yIcVbe.imag; |
|||
*(inst->NBJT2colEmitPtr) -= yIcVbe.real + yIcVce.real; |
|||
*(inst->NBJT2colEmitPtr + 1) -= yIcVbe.imag + yIcVce.imag; |
|||
*(inst->NBJT2baseColPtr) -= yIcVce.real + yIeVce.real; |
|||
*(inst->NBJT2baseColPtr + 1) -= yIcVce.imag + yIeVce.imag; |
|||
*(inst->NBJT2baseBasePtr) -= yIcVbe.real + yIeVbe.real; |
|||
*(inst->NBJT2baseBasePtr + 1) -= yIcVbe.imag + yIeVbe.imag; |
|||
*(inst->NBJT2baseEmitPtr) += yIcVbe.real + yIcVce.real + yIeVbe.real + yIeVce.real; |
|||
*(inst->NBJT2baseEmitPtr + 1) += yIcVbe.imag + yIcVce.imag + yIeVbe.imag + yIeVce.imag; |
|||
*(inst->NBJT2emitColPtr) += yIeVce.real; |
|||
*(inst->NBJT2emitColPtr + 1) += yIeVce.imag; |
|||
*(inst->NBJT2emitBasePtr) += yIeVbe.real; |
|||
*(inst->NBJT2emitBasePtr + 1) += yIeVbe.imag; |
|||
*(inst->NBJT2emitEmitPtr) -= yIeVbe.real + yIeVce.real; |
|||
*(inst->NBJT2emitEmitPtr + 1) -= yIeVbe.imag + yIeVce.imag; |
|||
if (ckt->CKTomega != 0.0) { |
|||
inst->NBJT2c11 = yIcVce.imag / ckt->CKTomega; |
|||
inst->NBJT2c12 = yIcVbe.imag / ckt->CKTomega; |
|||
inst->NBJT2c21 = (yIeVce.imag - yIcVce.imag) / ckt->CKTomega; |
|||
inst->NBJT2c22 = (yIeVbe.imag - yIcVbe.imag) / ckt->CKTomega; |
|||
} else { |
|||
inst->NBJT2c11 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NBJT2c12 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NBJT2c21 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NBJT2c22 = 0.0; /* XXX What else can be done?! */ |
|||
} |
|||
inst->NBJT2y11r = yIcVce.real; |
|||
inst->NBJT2y11i = yIcVce.imag; |
|||
inst->NBJT2y12r = yIcVbe.real; |
|||
inst->NBJT2y12i = yIcVbe.imag; |
|||
inst->NBJT2y21r = yIeVce.real - yIcVce.real; |
|||
inst->NBJT2y21i = yIeVce.imag - yIcVce.imag; |
|||
inst->NBJT2y22r = yIeVbe.real - yIcVbe.real; |
|||
inst->NBJT2y22i = yIeVbe.imag - yIcVbe.imag; |
|||
inst->NBJT2smSigAvail = TRUE; |
|||
inst->NBJT2pDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,216 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Thomas L. Quarles |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "devdefs.h" |
|||
#include "nbjt2def.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
/* Check out this one */ |
|||
extern int NBJT2initSmSig(NBJT2instance *); |
|||
|
|||
|
|||
/* ARGSUSED */ |
|||
int |
|||
NBJT2ask(ckt, inInst, which, value, select) |
|||
CKTcircuit *ckt; |
|||
GENinstance *inInst; |
|||
int which; |
|||
IFvalue *value; |
|||
IFvalue *select; |
|||
{ |
|||
NBJT2instance *inst = (NBJT2instance *) inInst; |
|||
switch (which) { |
|||
case NBJT2_WIDTH: |
|||
value->rValue = inst->NBJT2width; |
|||
return (OK); |
|||
case NBJT2_AREA: |
|||
value->rValue = inst->NBJT2area; |
|||
return (OK); |
|||
case NBJT2_TEMP: |
|||
value->rValue = inst->NBJT2temp - CONSTCtoK; |
|||
return (OK); |
|||
case NBJT2_G11: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NBJT2dIcDVce); |
|||
return (OK); |
|||
case NBJT2_G12: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NBJT2dIcDVbe); |
|||
return (OK); |
|||
case NBJT2_G13: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NBJT2dIcDVce) |
|||
- *(ckt->CKTstate0 + inst->NBJT2dIcDVbe); |
|||
return (OK); |
|||
case NBJT2_G21: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NBJT2dIeDVce) |
|||
- *(ckt->CKTstate0 + inst->NBJT2dIcDVce); |
|||
return (OK); |
|||
case NBJT2_G22: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NBJT2dIeDVbe) |
|||
- *(ckt->CKTstate0 + inst->NBJT2dIcDVbe); |
|||
return (OK); |
|||
case NBJT2_G23: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NBJT2dIeDVce) |
|||
+ *(ckt->CKTstate0 + inst->NBJT2dIcDVce) |
|||
-*(ckt->CKTstate0 + inst->NBJT2dIeDVbe) |
|||
+ *(ckt->CKTstate0 + inst->NBJT2dIcDVbe); |
|||
return (OK); |
|||
case NBJT2_G31: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NBJT2dIeDVce); |
|||
return (OK); |
|||
case NBJT2_G32: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NBJT2dIeDVbe); |
|||
return (OK); |
|||
case NBJT2_G33: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NBJT2dIeDVce) |
|||
+ *(ckt->CKTstate0 + inst->NBJT2dIeDVbe); |
|||
return (OK); |
|||
case NBJT2_C11: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->rValue = inst->NBJT2c11; |
|||
return (OK); |
|||
case NBJT2_C12: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->rValue = inst->NBJT2c12; |
|||
return (OK); |
|||
case NBJT2_C13: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NBJT2c11 - inst->NBJT2c12; |
|||
return (OK); |
|||
case NBJT2_C21: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->rValue = inst->NBJT2c21; |
|||
return (OK); |
|||
case NBJT2_C22: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->rValue = inst->NBJT2c22; |
|||
return (OK); |
|||
case NBJT2_C23: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NBJT2c21 - inst->NBJT2c22; |
|||
return (OK); |
|||
case NBJT2_C31: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NBJT2c11 - inst->NBJT2c21; |
|||
return (OK); |
|||
case NBJT2_C32: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NBJT2c12 - inst->NBJT2c22; |
|||
return (OK); |
|||
case NBJT2_C33: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->rValue = inst->NBJT2c11 + inst->NBJT2c21 |
|||
+ inst->NBJT2c12 + inst->NBJT2c22; |
|||
return (OK); |
|||
case NBJT2_Y11: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NBJT2y11r; |
|||
value->cValue.imag = inst->NBJT2y11i; |
|||
return (OK); |
|||
case NBJT2_Y12: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NBJT2y12r; |
|||
value->cValue.imag = inst->NBJT2y12i; |
|||
return (OK); |
|||
case NBJT2_Y13: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NBJT2y11r - inst->NBJT2y12r; |
|||
value->cValue.imag = -inst->NBJT2y11i - inst->NBJT2y12i; |
|||
return (OK); |
|||
case NBJT2_Y21: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NBJT2y21r; |
|||
value->cValue.imag = inst->NBJT2y21i; |
|||
return (OK); |
|||
case NBJT2_Y22: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NBJT2y22r; |
|||
value->cValue.imag = inst->NBJT2y22i; |
|||
return (OK); |
|||
case NBJT2_Y23: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NBJT2y21r - inst->NBJT2y22r; |
|||
value->cValue.imag = -inst->NBJT2y21i - inst->NBJT2y22i; |
|||
return (OK); |
|||
case NBJT2_Y31: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NBJT2y11r - inst->NBJT2y21r; |
|||
value->cValue.imag = -inst->NBJT2y11i - inst->NBJT2y21i; |
|||
return (OK); |
|||
case NBJT2_Y32: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NBJT2y12r - inst->NBJT2y22r; |
|||
value->cValue.imag = -inst->NBJT2y12i - inst->NBJT2y22i; |
|||
return (OK); |
|||
case NBJT2_Y33: |
|||
if (!inst->NBJT2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NBJT2initSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NBJT2y11r + inst->NBJT2y21r |
|||
+ inst->NBJT2y12r + inst->NBJT2y22r; |
|||
value->cValue.imag = inst->NBJT2y11i + inst->NBJT2y21i |
|||
+ inst->NBJT2y12i + inst->NBJT2y22i; |
|||
return (OK); |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
/* NOTREACHED */ |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine deletes a NBJT2 instance from the circuit and frees the |
|||
* storage it was using. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "nbjt2def.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NBJT2delete(inModel, name, kill) |
|||
GENmodel *inModel; |
|||
IFuid name; |
|||
GENinstance **kill; |
|||
|
|||
{ |
|||
|
|||
NBJT2model *model = (NBJT2model *) inModel; |
|||
NBJT2instance **fast = (NBJT2instance **) kill; |
|||
NBJT2instance **prev = NULL; |
|||
NBJT2instance *inst; |
|||
|
|||
for (; model; model = model->NBJT2nextModel) { |
|||
prev = &(model->NBJT2instances); |
|||
for (inst = *prev; inst; inst = *prev) { |
|||
if (inst->NBJT2name == name || (fast && inst == *fast)) { |
|||
*prev = inst->NBJT2nextInstance; |
|||
FREE(inst); |
|||
return (OK); |
|||
} |
|||
prev = &(inst->NBJT2nextInstance); |
|||
} |
|||
} |
|||
return (E_NODEV); |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine deletes all NBJT2s from the circuit and frees all storage |
|||
* they were using. The current implementation has memory leaks. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "nbjt2def.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "suffix.h" |
|||
|
|||
void |
|||
NBJT2destroy(inModel) |
|||
GENmodel **inModel; |
|||
|
|||
{ |
|||
|
|||
NBJT2model **model = (NBJT2model **) inModel; |
|||
NBJT2model *mod, *nextMod; |
|||
NBJT2instance *inst, *nextInst; |
|||
|
|||
|
|||
for (mod = *model; mod;) { |
|||
for (inst = mod->NBJT2instances; inst;) { |
|||
TWOdestroy(inst->NBJT2pDevice); |
|||
nextInst = inst->NBJT2nextInstance; |
|||
FREE(inst); |
|||
inst = nextInst; |
|||
} |
|||
nextMod = mod->NBJT2nextModel; |
|||
FREE(mod); |
|||
mod = nextMod; |
|||
} |
|||
*model = NULL; |
|||
} |
|||
@ -0,0 +1,178 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This is a simple routine to dump the internal device states. It produces |
|||
* states for .OP, .DC, & .TRAN simulations. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "nbjt2def.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
/* Forward Declarations */ |
|||
static void NBJT2putHeader(FILE *, CKTcircuit *, NBJT2instance *); |
|||
|
|||
/* State Counter */ |
|||
static int state_numOP = 0; |
|||
static int state_numDC = 0; |
|||
static int state_numTR = 0; |
|||
|
|||
void |
|||
NBJT2dump(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
register NBJT2model *model = (NBJT2model *) inModel; |
|||
register NBJT2instance *inst; |
|||
OUTPcard *output; |
|||
FILE *fpState; |
|||
char fileName[BSIZE_SP]; |
|||
char description[BSIZE_SP]; |
|||
char *prefix; |
|||
int *state_num; |
|||
int anyOutput = 0; |
|||
|
|||
if (ckt->CKTmode & MODEDCOP) { |
|||
prefix = "OP"; |
|||
state_num = &state_numOP; |
|||
sprintf(description, "..."); |
|||
} else if (ckt->CKTmode & MODEDCTRANCURVE) { |
|||
prefix = "DC"; |
|||
state_num = &state_numDC; |
|||
sprintf(description, "sweep = % e", ckt->CKTtime); |
|||
} else if (ckt->CKTmode & MODETRAN) { |
|||
prefix = "TR"; |
|||
state_num = &state_numTR; |
|||
sprintf(description, "time = % e", ckt->CKTtime); |
|||
} else { |
|||
/* Not a recognized CKT mode. */ |
|||
return; |
|||
} |
|||
|
|||
for (; model != NULL; model = model->NBJT2nextModel) { |
|||
output = model->NBJT2outputs; |
|||
for (inst = model->NBJT2instances; inst != NULL; |
|||
inst = inst->NBJT2nextInstance) { |
|||
if (inst->NBJT2owner != ARCHme) continue; |
|||
|
|||
if (inst->NBJT2printGiven) { |
|||
if ((ckt->CKTmode & MODETRAN) && |
|||
((ckt->CKTstat->STATaccepted - 1) % inst->NBJT2print != 0)) { |
|||
continue; |
|||
} |
|||
anyOutput = 1; |
|||
sprintf(fileName, "%s%s.%d.%s", output->OUTProotFile, prefix, |
|||
*state_num, inst->NBJT2name); |
|||
if (!(fpState = fopen(fileName, "w"))) { |
|||
perror(fileName); |
|||
} else { |
|||
NBJT2putHeader(fpState, ckt, inst); |
|||
TWOprnSolution(fpState, inst->NBJT2pDevice, |
|||
model->NBJT2outputs); |
|||
fclose(fpState); |
|||
LOGmakeEntry(fileName, description); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if (anyOutput) { |
|||
(*state_num)++; |
|||
} |
|||
} |
|||
|
|||
#define NBJT2numOutputs 9 |
|||
|
|||
static |
|||
void |
|||
NBJT2putHeader(file, ckt, inst) |
|||
FILE *file; |
|||
CKTcircuit *ckt; |
|||
NBJT2instance *inst; |
|||
{ |
|||
char *reference; |
|||
double refVal = 0.0; |
|||
int numVars = NBJT2numOutputs; |
|||
|
|||
if (ckt->CKTmode & MODEDCOP) { |
|||
reference = NULL; |
|||
} else if (ckt->CKTmode & MODEDCTRANCURVE) { |
|||
reference = "sweep"; |
|||
refVal = ckt->CKTtime; |
|||
numVars++; |
|||
} else if (ckt->CKTmode & MODETRAN) { |
|||
reference = "time"; |
|||
refVal = ckt->CKTtime; |
|||
numVars++; |
|||
} else { |
|||
reference = NULL; |
|||
} |
|||
fprintf(file, "Title: Device %s external state\n", inst->NBJT2name); |
|||
fprintf(file, "Plotname: Device Operating Point\n"); |
|||
fprintf(file, "Command: deftype v conductance S\n"); |
|||
fprintf(file, "Flags: real\n"); |
|||
fprintf(file, "No. Variables: %d\n", numVars); |
|||
fprintf(file, "No. Points: 1\n"); |
|||
numVars = 0; |
|||
fprintf(file, "Variables:\n"); |
|||
if (reference) { |
|||
fprintf(file, "\t%d %s unknown\n", numVars++, reference); |
|||
} |
|||
fprintf(file, "\t%d v13 voltage\n", numVars++); |
|||
fprintf(file, "\t%d v23 voltage\n", numVars++); |
|||
fprintf(file, "\t%d i1 current\n", numVars++); |
|||
fprintf(file, "\t%d i2 current\n", numVars++); |
|||
fprintf(file, "\t%d i3 current\n", numVars++); |
|||
fprintf(file, "\t%d g22 conductance\n", numVars++); |
|||
fprintf(file, "\t%d g21 conductance\n", numVars++); |
|||
fprintf(file, "\t%d g12 conductance\n", numVars++); |
|||
fprintf(file, "\t%d g11 conductance\n", numVars++); |
|||
fprintf(file, "Values:\n0"); |
|||
if (reference) { |
|||
fprintf(file, "\t% e\n", refVal); |
|||
} |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2vce)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2vbe)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2ic)); |
|||
fprintf(file, "\t% e\n", - *(ckt->CKTstate0 + inst->NBJT2ie) |
|||
- *(ckt->CKTstate0 + inst->NBJT2ic)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2ie)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2dIeDVbe) |
|||
- *(ckt->CKTstate0 + inst->NBJT2dIcDVbe)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2dIeDVce) |
|||
- *(ckt->CKTstate0 + inst->NBJT2dIcDVce)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2dIcDVbe)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2dIcDVce)); |
|||
} |
|||
|
|||
void |
|||
NBJT2acct(inModel, ckt, file) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
FILE *file; |
|||
{ |
|||
register NBJT2model *model = (NBJT2model *) inModel; |
|||
register NBJT2instance *inst; |
|||
OUTPcard *output; |
|||
|
|||
for (; model != NULL; model = model->NBJT2nextModel) { |
|||
output = model->NBJT2outputs; |
|||
for (inst = model->NBJT2instances; inst != NULL; |
|||
inst = inst->NBJT2nextInstance) { |
|||
if (inst->NBJT2owner != ARCHme) continue; |
|||
|
|||
if (output->OUTPstats) { |
|||
TWOmemStats(file, inst->NBJT2pDevice); |
|||
TWOcpuStats(file, inst->NBJT2pDevice); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,83 @@ |
|||
#include <config.h> |
|||
|
|||
#include <devdefs.h> |
|||
|
|||
#include "nbjt2itf.h" |
|||
#include "nbjt2ext.h" |
|||
#include "nbt2init.h" |
|||
|
|||
|
|||
SPICEdev NBJT2info = { |
|||
{ |
|||
"NBJT2", |
|||
"2D Numerical Bipolar Junction Transistor model", |
|||
|
|||
&NBJT2nSize, |
|||
&NBJT2nSize, |
|||
NBJT2names, |
|||
|
|||
&NBJT2pTSize, |
|||
NBJT2pTable, |
|||
|
|||
&NBJT2mPTSize, |
|||
NBJT2mPTable, |
|||
|
|||
#ifdef XSPICE |
|||
/*---- Fixed by SDB 5.2.2003 to enable XSPICE/tclspice integration -----*/ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
/*--------------------------- End of SDB fix -------------------------*/ |
|||
#endif |
|||
|
|||
DEV_DEFAULT |
|||
}, |
|||
|
|||
DEVparam : NBJT2param, |
|||
DEVmodParam : NBJT2mParam, |
|||
DEVload : NBJT2load, |
|||
DEVsetup : NBJT2setup, |
|||
DEVunsetup : NULL, |
|||
DEVpzSetup : NBJT2setup, |
|||
DEVtemperature: NBJT2temp, |
|||
DEVtrunc : NBJT2trunc, |
|||
DEVfindBranch : NULL, |
|||
DEVacLoad : NBJT2acLoad, |
|||
DEVaccept : NULL, |
|||
DEVdestroy : NBJT2destroy, |
|||
DEVmodDelete : NBJT2mDelete, |
|||
DEVdelete : NBJT2delete, |
|||
DEVsetic : NULL, |
|||
DEVask : NBJT2ask, |
|||
DEVmodAsk : NULL, |
|||
DEVpzLoad : NBJT2pzLoad, |
|||
DEVconvTest : NULL, |
|||
DEVsenSetup : NULL, |
|||
DEVsenLoad : NULL, |
|||
DEVsenUpdate : NULL, |
|||
DEVsenAcLoad : NULL, |
|||
DEVsenPrint : NULL, |
|||
DEVsenTrunc : NULL, |
|||
DEVdisto : NULL, |
|||
DEVnoise : NULL, |
|||
DEVdump : NBJT2dump, |
|||
DEVacct : NBJT2acct, |
|||
|
|||
DEVinstSize : &NBJT2iSize, |
|||
DEVmodSize : &NBJT2mSize |
|||
|
|||
}; |
|||
|
|||
|
|||
SPICEdev * |
|||
get_nbjt2_info(void) |
|||
{ |
|||
return &NBJT2info; |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
#ifndef _NBJT2INIT_H |
|||
#define _NBJT2INIT_H |
|||
|
|||
extern IFparm NBJT2pTable[ ]; |
|||
extern IFparm NBJT2mPTable[ ]; |
|||
extern char *NBJT2names[ ]; |
|||
extern int NBJT2pTSize; |
|||
extern int NBJT2mPTSize; |
|||
extern int NBJT2nSize; |
|||
extern int NBJT2iSize; |
|||
extern int NBJT2mSize; |
|||
|
|||
#endif |
|||
@ -0,0 +1,509 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This is the function called each iteration to evaluate the 2d numerical |
|||
* BJTs in the circuit and load them into the matrix as appropriate |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "devdefs.h" |
|||
#include "cktdefs.h" |
|||
#include "nbjt2def.h" |
|||
#include "trandefs.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
/* External Declarations */ |
|||
|
|||
/* Check out this one */ |
|||
extern int NBJT2initSmSig(NBJT2instance *); |
|||
|
|||
extern int TWOdcDebug; |
|||
extern int TWOtranDebug; |
|||
extern int TWOacDebug; |
|||
|
|||
|
|||
|
|||
int |
|||
NBJT2load(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
register NBJT2model *model = (NBJT2model *) inModel; |
|||
register NBJT2instance *inst; |
|||
register TWOdevice *pDevice; |
|||
double startTime, startTime2, totalTime, totalTime2; |
|||
double tol; |
|||
double ic, ie; |
|||
double iceq, ieeq; |
|||
double ichat = 0.0, iehat = 0.0; |
|||
double delVce, delVbe; |
|||
double vce, vbe; |
|||
double dIeDVce, dIeDVbe; |
|||
double dIcDVce, dIcDVbe; |
|||
double xfact; |
|||
int icheck; |
|||
int icheck1; |
|||
int i; |
|||
double deltaNorm[7]; |
|||
int devConverged = 0; |
|||
int numDevNonCon; |
|||
int deviceType; |
|||
int doInitSolve; |
|||
int doVoltPred; |
|||
char *initStateName; |
|||
|
|||
/* loop through all the models */ |
|||
for (; model != NULL; model = model->NBJT2nextModel) { |
|||
FieldDepMobility = model->NBJT2models->MODLfieldDepMobility; |
|||
TransDepMobility = model->NBJT2models->MODLtransDepMobility; |
|||
SurfaceMobility = model->NBJT2models->MODLsurfaceMobility; |
|||
Srh = model->NBJT2models->MODLsrh; |
|||
Auger = model->NBJT2models->MODLauger; |
|||
AvalancheGen = model->NBJT2models->MODLavalancheGen; |
|||
OneCarrier = model->NBJT2methods->METHoneCarrier; |
|||
MobDeriv = model->NBJT2methods->METHmobDeriv; |
|||
MaxIterations = model->NBJT2methods->METHitLim; |
|||
TWOdcDebug = model->NBJT2outputs->OUTPdcDebug; |
|||
TWOtranDebug = model->NBJT2outputs->OUTPtranDebug; |
|||
TWOacDebug = model->NBJT2outputs->OUTPacDebug; |
|||
deviceType = model->NBJT2options->OPTNdeviceType; |
|||
doVoltPred = model->NBJT2methods->METHvoltPred; |
|||
|
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
/* compute normalized deltas and predictor coeff */ |
|||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) { |
|||
model->NBJT2pInfo->order = ckt->CKTorder; |
|||
model->NBJT2pInfo->method = ckt->CKTintegrateMethod; |
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NBJT2pInfo->intCoeff, deltaNorm); |
|||
computePredCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NBJT2pInfo->predCoeff, deltaNorm); |
|||
} |
|||
} else if (ckt->CKTmode & MODEINITTRAN) { |
|||
model->NBJT2pInfo->order = ckt->CKTorder; |
|||
model->NBJT2pInfo->method = ckt->CKTintegrateMethod; |
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NBJT2pInfo->intCoeff, deltaNorm); |
|||
} |
|||
/* loop through all the instances of the model */ |
|||
for (inst = model->NBJT2instances; inst != NULL; |
|||
inst = inst->NBJT2nextInstance) { |
|||
if (inst->NBJT2owner != ARCHme) continue; |
|||
|
|||
pDevice = inst->NBJT2pDevice; |
|||
|
|||
totalTime = 0.0; |
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NBJT2globals)); |
|||
|
|||
/* |
|||
* initialization |
|||
*/ |
|||
pDevice->devStates = ckt->CKTstates; |
|||
icheck = 1; |
|||
doInitSolve = FALSE; |
|||
initStateName = NULL; |
|||
if (ckt->CKTmode & MODEINITSMSIG) { |
|||
vbe = *(ckt->CKTstate0 + inst->NBJT2vbe); |
|||
vce = *(ckt->CKTstate0 + inst->NBJT2vce); |
|||
delVbe = 0.0; |
|||
delVce = 0.0; |
|||
NBJT2setBCs(pDevice, vce, vbe); |
|||
} else if (ckt->CKTmode & MODEINITTRAN) { |
|||
*(ckt->CKTstate0 + inst->NBJT2vbe) = |
|||
*(ckt->CKTstate1 + inst->NBJT2vbe); |
|||
*(ckt->CKTstate0 + inst->NBJT2vce) = |
|||
*(ckt->CKTstate1 + inst->NBJT2vce); |
|||
vbe = *(ckt->CKTstate1 + inst->NBJT2vbe); |
|||
vce = *(ckt->CKTstate1 + inst->NBJT2vce); |
|||
TWOsaveState(pDevice); |
|||
delVbe = 0.0; |
|||
delVce = 0.0; |
|||
} else if ((ckt->CKTmode & MODEINITJCT) && |
|||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) { |
|||
doInitSolve = TRUE; |
|||
initStateName = inst->NBJT2icFile; |
|||
vbe = 0.0; |
|||
vce = 0.0; |
|||
delVbe = vbe; |
|||
delVce = vce; |
|||
} else if ((ckt->CKTmode & MODEINITJCT) && (inst->NBJT2off == 0)) { |
|||
doInitSolve = TRUE; |
|||
initStateName = inst->NBJT2icFile; |
|||
if (deviceType == OPTN_JFET) { |
|||
vbe = 0.0; |
|||
vce = inst->NBJT2type * 0.5; |
|||
} else { |
|||
vbe = inst->NBJT2type * 0.6; |
|||
vce = inst->NBJT2type * 1.0; |
|||
} |
|||
delVbe = vbe; |
|||
delVce = vce; |
|||
} else if (ckt->CKTmode & MODEINITJCT) { |
|||
doInitSolve = TRUE; |
|||
vbe = 0.0; |
|||
vce = 0.0; |
|||
delVbe = vbe; |
|||
delVce = vce; |
|||
} else if ((ckt->CKTmode & MODEINITFIX) && inst->NBJT2off) { |
|||
vbe = 0.0; |
|||
vce = 0.0; |
|||
delVbe = vbe; |
|||
delVce = vce; |
|||
} else { |
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
*(ckt->CKTstate0 + inst->NBJT2vbe) = |
|||
*(ckt->CKTstate1 + inst->NBJT2vbe); |
|||
*(ckt->CKTstate0 + inst->NBJT2vce) = |
|||
*(ckt->CKTstate1 + inst->NBJT2vce); |
|||
*(ckt->CKTstate0 + inst->NBJT2ic) = |
|||
*(ckt->CKTstate1 + inst->NBJT2ic); |
|||
*(ckt->CKTstate0 + inst->NBJT2ie) = |
|||
*(ckt->CKTstate1 + inst->NBJT2ie); |
|||
*(ckt->CKTstate0 + inst->NBJT2dIeDVce) = |
|||
*(ckt->CKTstate1 + inst->NBJT2dIeDVce); |
|||
*(ckt->CKTstate0 + inst->NBJT2dIeDVbe) = |
|||
*(ckt->CKTstate1 + inst->NBJT2dIeDVbe); |
|||
*(ckt->CKTstate0 + inst->NBJT2dIcDVce) = |
|||
*(ckt->CKTstate1 + inst->NBJT2dIcDVce); |
|||
*(ckt->CKTstate0 + inst->NBJT2dIcDVbe) = |
|||
*(ckt->CKTstate1 + inst->NBJT2dIcDVbe); |
|||
/* compute normalized deltas and predictor coeff */ |
|||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) { |
|||
/* no linear prediction on device voltages */ |
|||
vbe = *(ckt->CKTstate1 + inst->NBJT2vbe); |
|||
vce = *(ckt->CKTstate1 + inst->NBJT2vce); |
|||
TWOpredict(pDevice, model->NBJT2pInfo); |
|||
} else { |
|||
if (doVoltPred) { |
|||
/* linear prediction */ |
|||
xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1]; |
|||
vbe = (1+xfact) * (*(ckt->CKTstate1 + inst->NBJT2vbe)) |
|||
- (xfact) * (*(ckt->CKTstate2 + inst->NBJT2vbe)); |
|||
vce = (1+xfact) * (*(ckt->CKTstate1 + inst->NBJT2vce)) |
|||
- (xfact) * (*(ckt->CKTstate2 + inst->NBJT2vce)); |
|||
} else { |
|||
vbe = *(ckt->CKTstate1 + inst->NBJT2vbe); |
|||
vce = *(ckt->CKTstate1 + inst->NBJT2vce); |
|||
} |
|||
} |
|||
} else { |
|||
/* |
|||
* compute new nonlinear branch voltages |
|||
*/ |
|||
vbe = *(ckt->CKTrhsOld + inst->NBJT2baseNode) - |
|||
*(ckt->CKTrhsOld + inst->NBJT2emitNode); |
|||
vce = *(ckt->CKTrhsOld + inst->NBJT2colNode) - |
|||
*(ckt->CKTrhsOld + inst->NBJT2emitNode); |
|||
} |
|||
delVbe = vbe - *(ckt->CKTstate0 + inst->NBJT2vbe); |
|||
delVce = vce - *(ckt->CKTstate0 + inst->NBJT2vce); |
|||
ichat = *(ckt->CKTstate0 + inst->NBJT2ic) + |
|||
*(ckt->CKTstate0 + inst->NBJT2dIcDVbe) * delVbe + |
|||
*(ckt->CKTstate0 + inst->NBJT2dIcDVce) * delVce; |
|||
iehat = *(ckt->CKTstate0 + inst->NBJT2ie) + |
|||
*(ckt->CKTstate0 + inst->NBJT2dIeDVbe) * delVbe + |
|||
*(ckt->CKTstate0 + inst->NBJT2dIeDVce) * delVce; |
|||
|
|||
|
|||
#ifndef NOBYPASS |
|||
/* |
|||
* bypass if solution has not changed |
|||
*/ |
|||
/* |
|||
* the following collections of if's would be just one if the average |
|||
* compiler could handle it, but many find the expression too |
|||
* complicated, thus the split. |
|||
*/ |
|||
if ((ckt->CKTbypass) && pDevice->converged && |
|||
(!(ckt->CKTmode & MODEINITPRED)) && |
|||
(fabs(delVbe) < (ckt->CKTreltol * MAX(fabs(vbe), |
|||
fabs(*(ckt->CKTstate0 + inst->NBJT2vbe))) + |
|||
ckt->CKTvoltTol))) |
|||
if ((fabs(delVce) < ckt->CKTreltol * MAX(fabs(vce), |
|||
fabs(*(ckt->CKTstate0 + inst->NBJT2vce))) + |
|||
ckt->CKTvoltTol)) |
|||
if ((fabs(ichat - *(ckt->CKTstate0 + inst->NBJT2ic)) < |
|||
ckt->CKTreltol * MAX(fabs(ichat), |
|||
fabs(*(ckt->CKTstate0 + inst->NBJT2ic))) + |
|||
ckt->CKTabstol)) |
|||
if ((fabs(iehat - *(ckt->CKTstate0 + inst->NBJT2ie)) < |
|||
ckt->CKTreltol * MAX(fabs(iehat), |
|||
fabs(*(ckt->CKTstate0 + inst->NBJT2ie))) + |
|||
ckt->CKTabstol)) { |
|||
/* |
|||
* bypassing.... |
|||
*/ |
|||
vbe = *(ckt->CKTstate0 + inst->NBJT2vbe); |
|||
vce = *(ckt->CKTstate0 + inst->NBJT2vce); |
|||
ic = *(ckt->CKTstate0 + inst->NBJT2ic); |
|||
ie = *(ckt->CKTstate0 + inst->NBJT2ie); |
|||
dIeDVce = *(ckt->CKTstate0 + inst->NBJT2dIeDVce); |
|||
dIeDVbe = *(ckt->CKTstate0 + inst->NBJT2dIeDVbe); |
|||
dIcDVce = *(ckt->CKTstate0 + inst->NBJT2dIcDVce); |
|||
dIcDVbe = *(ckt->CKTstate0 + inst->NBJT2dIcDVbe); |
|||
goto load; |
|||
} |
|||
#endif /* NOBYPASS */ |
|||
/* |
|||
* limit nonlinear branch voltages |
|||
*/ |
|||
icheck1 = 1; |
|||
if (deviceType == OPTN_JFET) { |
|||
double vbc, vbc0; |
|||
vbe = inst->NBJT2type * limitJunctionVoltage(inst->NBJT2type * vbe, |
|||
inst->NBJT2type * *(ckt->CKTstate0 + inst->NBJT2vbe), &icheck); |
|||
vbc = vbe - vce; |
|||
vbc0 = *(ckt->CKTstate0 + inst->NBJT2vbe) - |
|||
*(ckt->CKTstate0 + inst->NBJT2vce); |
|||
vbc = inst->NBJT2type * limitJunctionVoltage(inst->NBJT2type * vbc, |
|||
inst->NBJT2type * vbc0, &icheck); |
|||
if (icheck1 == 1) |
|||
icheck = 1; |
|||
vce = vbe - vbc; |
|||
} else { |
|||
vbe = inst->NBJT2type * limitJunctionVoltage(inst->NBJT2type * vbe, |
|||
inst->NBJT2type * *(ckt->CKTstate0 + inst->NBJT2vbe), &icheck); |
|||
vce = inst->NBJT2type * limitVce(inst->NBJT2type * vce, |
|||
inst->NBJT2type * *(ckt->CKTstate0 + inst->NBJT2vce), &icheck1); |
|||
if (icheck1 == 1) |
|||
icheck = 1; |
|||
} |
|||
delVbe = vbe - *(ckt->CKTstate0 + inst->NBJT2vbe); |
|||
delVce = vce - *(ckt->CKTstate0 + inst->NBJT2vce); |
|||
NBJT2setBCs(pDevice, vce - delVce, vbe - delVbe); |
|||
} |
|||
|
|||
if (doInitSolve) { |
|||
if (TWOdcDebug) { |
|||
printVoltages(stdout, model->NBJT2modName, inst->NBJT2name, |
|||
deviceType, 2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); |
|||
} |
|||
startTime2 = SPfrontEnd->IFseconds(); |
|||
TWOequilSolve(pDevice); |
|||
totalTime2 = SPfrontEnd->IFseconds() - startTime2; |
|||
pDevice->pStats->totalTime[STAT_SETUP] += totalTime2; |
|||
pDevice->pStats->totalTime[STAT_DC] -= totalTime2; |
|||
|
|||
TWObiasSolve(pDevice, MaxIterations, FALSE, NULL); |
|||
|
|||
*(ckt->CKTstate0 + inst->NBJT2vbe) = 0.0; |
|||
*(ckt->CKTstate0 + inst->NBJT2vce) = 0.0; |
|||
|
|||
if (initStateName != NULL) { |
|||
if (TWOreadState(pDevice, initStateName, 2, &vce, &vbe, NULL ) < 0) { |
|||
fprintf(stderr, |
|||
"NBJT2load: trouble reading state-file %s\n", initStateName); |
|||
} else { |
|||
NBJT2setBCs(pDevice, vce, vbe); |
|||
delVce = delVbe = 0.0; |
|||
} |
|||
} |
|||
} |
|||
/* |
|||
* determine dc current and derivatives using the numerical routines |
|||
*/ |
|||
if (ckt->CKTmode & (MODEDCOP | MODETRANOP | MODEDCTRANCURVE | MODEINITSMSIG)) { |
|||
|
|||
numDevNonCon = 0; |
|||
inst->NBJT2c11 = inst->NBJT2y11r = inst->NBJT2y11i = 0.0; |
|||
inst->NBJT2c12 = inst->NBJT2y12r = inst->NBJT2y12i = 0.0; |
|||
inst->NBJT2c21 = inst->NBJT2y21r = inst->NBJT2y21i = 0.0; |
|||
inst->NBJT2c22 = inst->NBJT2y22r = inst->NBJT2y22i = 0.0; |
|||
inst->NBJT2smSigAvail = FALSE; |
|||
devNonCon: |
|||
NBJT2project(pDevice, delVce, delVbe); |
|||
if (TWOdcDebug) { |
|||
printVoltages(stdout, model->NBJT2modName, inst->NBJT2name, |
|||
deviceType, 2, vce, delVce, vbe, delVbe, 0.0, 0.0); |
|||
} |
|||
TWObiasSolve(pDevice, MaxIterations, FALSE, model->NBJT2pInfo); |
|||
|
|||
devConverged = pDevice->converged; |
|||
if (devConverged && finite(pDevice->rhsNorm)) { |
|||
/* compute the currents */ |
|||
NBJT2current(pDevice, FALSE, (double *) NULL, &ie, &ic); |
|||
NBJT2conductance(pDevice, FALSE, (double *) NULL, |
|||
&dIeDVce, &dIcDVce, &dIeDVbe, &dIcDVbe); |
|||
|
|||
} else { |
|||
/* reduce the voltage step until converged */ |
|||
/* restore boundary nodes to previous potential */ |
|||
NBJT2setBCs(pDevice, vce - delVce, vbe - delVbe); |
|||
TWOstoreInitialGuess(pDevice); |
|||
TWOresetJacobian(pDevice); |
|||
delVbe *= 0.5; |
|||
delVce *= 0.5; |
|||
vbe = delVbe + *(ckt->CKTstate0 + inst->NBJT2vbe); |
|||
vce = delVce + *(ckt->CKTstate0 + inst->NBJT2vce); |
|||
numDevNonCon++; |
|||
icheck = 1; |
|||
if (numDevNonCon > 10) { |
|||
printVoltages(stderr, model->NBJT2modName, inst->NBJT2name, |
|||
deviceType, 2, vce, delVce, vbe, delVbe, 0.0, 0.0); |
|||
fprintf(stderr, "*** Non-convergence during load ***\n"); |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
return (E_BADMATRIX); |
|||
} else { |
|||
goto devNonCon; |
|||
} |
|||
} |
|||
} |
|||
if ((ckt->CKTmode & (MODETRAN | MODEAC)) || |
|||
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) || |
|||
(ckt->CKTmode & MODEINITSMSIG)) { |
|||
/* |
|||
* store small-signal parameters |
|||
*/ |
|||
if ((!(ckt->CKTmode & MODETRANOP)) || |
|||
(!(ckt->CKTmode & MODEUIC))) { |
|||
if (ckt->CKTmode & MODEINITSMSIG) { |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
startTime2 = SPfrontEnd->IFseconds(); |
|||
NBJT2initSmSig(inst); |
|||
pDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime2; |
|||
continue; |
|||
} else { |
|||
inst->NBJT2smSigAvail = FALSE; |
|||
} |
|||
/* |
|||
* transient analysis |
|||
*/ |
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
NBJT2setBCs(pDevice, vce, vbe); |
|||
TWOstoreInitialGuess(pDevice); |
|||
} else { |
|||
NBJT2update(pDevice, delVce, delVbe, TRUE); |
|||
} |
|||
if (TWOtranDebug) { |
|||
printVoltages(stdout, model->NBJT2modName, inst->NBJT2name, |
|||
deviceType, 2, vce, delVce, vbe, delVbe, 0.0, 0.0); |
|||
} |
|||
TWObiasSolve(pDevice, 0, TRUE, model->NBJT2pInfo); |
|||
if (!finite(pDevice->rhsNorm)) { |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
return (E_BADMATRIX); |
|||
} |
|||
devConverged = TWOdeviceConverged(pDevice); |
|||
pDevice->converged = devConverged; |
|||
|
|||
/* compute the currents */ |
|||
NBJT2current(pDevice, TRUE, |
|||
model->NBJT2pInfo->intCoeff, &ie, &ic); |
|||
NBJT2conductance(pDevice, TRUE, |
|||
model->NBJT2pInfo->intCoeff, |
|||
&dIeDVce, &dIcDVce, &dIeDVbe, &dIcDVbe); |
|||
} |
|||
} |
|||
/* |
|||
* check convergence |
|||
*/ |
|||
if ((!(ckt->CKTmode & MODEINITFIX)) || (!(inst->NBJT2off))) { |
|||
if (icheck == 1 || !devConverged) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} else { |
|||
tol = ckt->CKTreltol * MAX(fabs(ichat), fabs(ic)) + ckt->CKTabstol; |
|||
if (fabs(ichat - ic) > tol) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} else { |
|||
tol = ckt->CKTreltol * MAX(fabs(iehat), fabs(ie)) + |
|||
ckt->CKTabstol; |
|||
if (fabs(iehat - ie) > tol) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
*(ckt->CKTstate0 + inst->NBJT2vbe) = vbe; |
|||
*(ckt->CKTstate0 + inst->NBJT2vce) = vce; |
|||
*(ckt->CKTstate0 + inst->NBJT2ic) = ic; |
|||
*(ckt->CKTstate0 + inst->NBJT2ie) = ie; |
|||
*(ckt->CKTstate0 + inst->NBJT2dIeDVce) = dIeDVce; |
|||
*(ckt->CKTstate0 + inst->NBJT2dIeDVbe) = dIeDVbe; |
|||
*(ckt->CKTstate0 + inst->NBJT2dIcDVce) = dIcDVce; |
|||
*(ckt->CKTstate0 + inst->NBJT2dIcDVbe) = dIcDVbe; |
|||
|
|||
load: |
|||
/* |
|||
* load current excitation vector |
|||
*/ |
|||
|
|||
iceq = ic - dIcDVce * vce - dIcDVbe * vbe; |
|||
ieeq = ie - dIeDVce * vce - dIeDVbe * vbe; |
|||
*(ckt->CKTrhs + inst->NBJT2colNode) -= iceq; |
|||
*(ckt->CKTrhs + inst->NBJT2baseNode) += ieeq + iceq; |
|||
*(ckt->CKTrhs + inst->NBJT2emitNode) -= ieeq; |
|||
/* |
|||
* load y matrix |
|||
*/ |
|||
*(inst->NBJT2colColPtr) += dIcDVce; |
|||
*(inst->NBJT2colBasePtr) += dIcDVbe; |
|||
*(inst->NBJT2colEmitPtr) -= dIcDVbe + dIcDVce; |
|||
*(inst->NBJT2baseColPtr) -= dIcDVce + dIeDVce; |
|||
*(inst->NBJT2baseBasePtr) -= dIcDVbe + dIeDVbe; |
|||
*(inst->NBJT2baseEmitPtr) += dIcDVbe + dIcDVce + dIeDVbe + dIeDVce; |
|||
*(inst->NBJT2emitColPtr) += dIeDVce; |
|||
*(inst->NBJT2emitBasePtr) += dIeDVbe; |
|||
*(inst->NBJT2emitEmitPtr) -= dIeDVbe + dIeDVce; |
|||
|
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
if (ckt->CKTmode & MODETRAN) { |
|||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime; |
|||
} else { |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
} |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
|
|||
int |
|||
NBJT2initSmSig(inst) |
|||
NBJT2instance *inst; |
|||
{ |
|||
SPcomplex yIeVce, yIeVbe; |
|||
SPcomplex yIcVce, yIcVbe; |
|||
double omega = inst->NBJT2modPtr->NBJT2methods->METHomega; |
|||
|
|||
AcAnalysisMethod = SOR_ONLY; |
|||
(void) NBJT2admittance(inst->NBJT2pDevice, omega, |
|||
&yIeVce, &yIcVce, &yIeVbe, &yIcVbe); |
|||
inst->NBJT2c11 = yIcVce.imag / omega; |
|||
inst->NBJT2c12 = yIcVbe.imag / omega; |
|||
inst->NBJT2c21 = (yIeVce.imag - yIcVce.imag) / omega; |
|||
inst->NBJT2c22 = (yIeVbe.imag - yIcVbe.imag) / omega; |
|||
inst->NBJT2y11r = yIcVce.real; |
|||
inst->NBJT2y11i = yIcVce.imag; |
|||
inst->NBJT2y12r = yIcVbe.real; |
|||
inst->NBJT2y12i = yIcVbe.imag; |
|||
inst->NBJT2y21r = yIeVce.real - yIcVce.real; |
|||
inst->NBJT2y21i = yIeVce.imag - yIcVce.imag; |
|||
inst->NBJT2y22r = yIeVbe.real - yIcVbe.real; |
|||
inst->NBJT2y22i = yIeVbe.imag - yIcVbe.imag; |
|||
inst->NBJT2smSigAvail = TRUE; |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine deletes a NBJT2 model from the circuit and frees the storage |
|||
* it was using. returns an error if the model has instances |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "nbjt2def.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NBJT2mDelete(inModel, modname, kill) |
|||
GENmodel **inModel; |
|||
IFuid modname; |
|||
GENmodel *kill; |
|||
|
|||
{ |
|||
|
|||
NBJT2model **model = (NBJT2model **) inModel; |
|||
NBJT2model *modfast = (NBJT2model *) kill; |
|||
NBJT2model **oldmod; |
|||
oldmod = model; |
|||
for (; *model; model = &((*model)->NBJT2nextModel)) { |
|||
if ((*model)->NBJT2modName == modname || |
|||
(modfast && *model == modfast)) |
|||
goto delgot; |
|||
oldmod = model; |
|||
} |
|||
return (E_NOMOD); |
|||
|
|||
delgot: |
|||
if ((*model)->NBJT2instances) |
|||
return (E_NOTEMPTY); |
|||
*oldmod = (*model)->NBJT2nextModel; /* cut deleted device out of list */ |
|||
FREE(*model); |
|||
return (OK); |
|||
|
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine sets model parameters for NBJT2s in the circuit. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "nbjt2def.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NBJT2mParam(param, value, inModel) |
|||
int param; |
|||
IFvalue *value; |
|||
GENmodel *inModel; |
|||
{ |
|||
switch (param) { |
|||
case NBJT2_MOD_NBJT: |
|||
/* no action - already know it is a 2d-numerical bjt, but this */ |
|||
/* makes life easier for spice-2 like parsers */ |
|||
break; |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine sets instance parameters for NBJT2s in the circuit. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "nbjt2def.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NBJT2param(param, value, inInst, select) |
|||
int param; |
|||
IFvalue *value; |
|||
GENinstance *inInst; |
|||
IFvalue *select; |
|||
{ |
|||
register NBJT2instance *inst = (NBJT2instance *) inInst; |
|||
switch (param) { |
|||
case NBJT2_WIDTH: |
|||
inst->NBJT2width = value->rValue; |
|||
inst->NBJT2widthGiven = TRUE; |
|||
break; |
|||
case NBJT2_AREA: |
|||
inst->NBJT2area = value->rValue; |
|||
inst->NBJT2areaGiven = TRUE; |
|||
break; |
|||
case NBJT2_OFF: |
|||
inst->NBJT2off = TRUE; |
|||
break; |
|||
case NBJT2_IC_FILE: |
|||
inst->NBJT2icFile = value->sValue; |
|||
inst->NBJT2icFileGiven = TRUE; |
|||
break; |
|||
case NBJT2_PRINT: |
|||
inst->NBJT2print = value->rValue; |
|||
inst->NBJT2printGiven = TRUE; |
|||
break; |
|||
case NBJT2_TEMP: |
|||
inst->NBJT2temp = value->rValue + CONSTCtoK; |
|||
inst->NBJT2tempGiven = TRUE; |
|||
break; |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "complex.h" |
|||
#include "nbjt2def.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
/* External Declarations */ |
|||
extern int TWOacDebug; |
|||
|
|||
int |
|||
NBJT2pzLoad(inModel, ckt, s) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
SPcomplex *s; |
|||
{ |
|||
register NBJT2model *model = (NBJT2model *) inModel; |
|||
register NBJT2instance *inst; |
|||
SPcomplex yIeVce, yIeVbe; |
|||
SPcomplex yIcVce, yIcVbe; |
|||
double startTime; |
|||
|
|||
for (; model != NULL; model = model->NBJT2nextModel) { |
|||
FieldDepMobility = model->NBJT2models->MODLfieldDepMobility; |
|||
TransDepMobility = model->NBJT2models->MODLtransDepMobility; |
|||
SurfaceMobility = model->NBJT2models->MODLsurfaceMobility; |
|||
Srh = model->NBJT2models->MODLsrh; |
|||
Auger = model->NBJT2models->MODLauger; |
|||
AvalancheGen = model->NBJT2models->MODLavalancheGen; |
|||
OneCarrier = model->NBJT2methods->METHoneCarrier; |
|||
AcAnalysisMethod = model->NBJT2methods->METHacAnalysisMethod; |
|||
MobDeriv = model->NBJT2methods->METHmobDeriv; |
|||
TWOacDebug = model->NBJT2outputs->OUTPacDebug; |
|||
|
|||
for (inst = model->NBJT2instances; inst != NULL; |
|||
inst = inst->NBJT2nextInstance) { |
|||
if (inst->NBJT2owner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NBJT2globals)); |
|||
|
|||
NBJT2ys(inst->NBJT2pDevice, s, |
|||
&yIeVce, &yIcVce, &yIeVbe, &yIcVbe); |
|||
|
|||
*(inst->NBJT2colColPtr) += yIcVce.real; |
|||
*(inst->NBJT2colColPtr + 1) += yIcVce.imag; |
|||
*(inst->NBJT2colBasePtr) += yIcVbe.real; |
|||
*(inst->NBJT2colBasePtr + 1) += yIcVbe.imag; |
|||
*(inst->NBJT2colEmitPtr) -= yIcVbe.real + yIcVce.real; |
|||
*(inst->NBJT2colEmitPtr + 1) -= yIcVbe.imag + yIcVce.imag; |
|||
*(inst->NBJT2baseColPtr) -= yIcVce.real + yIeVce.real; |
|||
*(inst->NBJT2baseColPtr + 1) -= yIcVce.imag + yIeVce.imag; |
|||
*(inst->NBJT2baseBasePtr) -= yIcVbe.real + yIeVbe.real; |
|||
*(inst->NBJT2baseBasePtr + 1) -= yIcVbe.imag + yIeVbe.imag; |
|||
*(inst->NBJT2baseEmitPtr) += yIcVbe.real + yIcVce.real + yIeVbe.real + yIeVce.real; |
|||
*(inst->NBJT2baseEmitPtr + 1) += yIcVbe.imag + yIcVce.imag + yIeVbe.imag + yIeVce.imag; |
|||
*(inst->NBJT2emitColPtr) += yIeVce.real; |
|||
*(inst->NBJT2emitColPtr + 1) += yIeVce.imag; |
|||
*(inst->NBJT2emitBasePtr) += yIeVbe.real; |
|||
*(inst->NBJT2emitBasePtr + 1) += yIeVbe.imag; |
|||
*(inst->NBJT2emitEmitPtr) -= yIeVbe.real + yIeVce.real; |
|||
*(inst->NBJT2emitEmitPtr + 1) -= yIeVbe.imag + yIeVce.imag; |
|||
|
|||
inst->NBJT2pDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,274 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "smpdefs.h" |
|||
#include "nbjt2def.h" |
|||
#include "numconst.h" |
|||
#include "numenum.h" |
|||
#include "meshext.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "ciderinp.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
#define NIL(type) ((type *)0) |
|||
#define TSCALLOC(var, size, type)\ |
|||
if (size && (!(var =(type *)calloc(1, (unsigned)(size)*sizeof(type))))) {\ |
|||
return(E_NOMEM);\ |
|||
} |
|||
|
|||
int |
|||
NBJT2setup(matrix, inModel, ckt, states) |
|||
register SMPmatrix *matrix; |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
int *states; |
|||
/* |
|||
* load the structure with those pointers needed later for fast matrix |
|||
* loading |
|||
*/ |
|||
{ |
|||
register NBJT2model *model = (NBJT2model *) inModel; |
|||
register NBJT2instance *inst; |
|||
METHcard *methods; |
|||
MODLcard *models; |
|||
OPTNcard *options; |
|||
OUTPcard *outputs; |
|||
char *icFileName = NULL; |
|||
int nameLen; |
|||
int error, xIndex, yIndex; |
|||
int xMeshSize, yMeshSize; |
|||
TWOdevice *pDevice; |
|||
TWOcoord *xCoordList = NIL(TWOcoord); |
|||
TWOcoord *yCoordList = NIL(TWOcoord); |
|||
TWOdomain *domainList = NIL(TWOdomain); |
|||
TWOelectrode *electrodeList = NIL(TWOelectrode); |
|||
TWOmaterial *pM, *pMaterial = NIL(TWOmaterial), *materialList = NIL(TWOmaterial); |
|||
DOPprofile *profileList = NIL(DOPprofile); |
|||
DOPtable *dopTableList = NIL(DOPtable); |
|||
double startTime; |
|||
|
|||
|
|||
|
|||
/* loop through all the models */ |
|||
for (; model != NULL; model = model->NBJT2nextModel) { |
|||
if (!model->NBJT2pInfo) { |
|||
TSCALLOC(model->NBJT2pInfo, 1, TWOtranInfo); |
|||
} |
|||
methods = model->NBJT2methods; |
|||
if (!methods) { |
|||
TSCALLOC(methods, 1, METHcard); |
|||
model->NBJT2methods = methods; |
|||
} |
|||
models = model->NBJT2models; |
|||
if (!models) { |
|||
TSCALLOC(models, 1, MODLcard); |
|||
model->NBJT2models = models; |
|||
} |
|||
options = model->NBJT2options; |
|||
if (!options) { |
|||
TSCALLOC(options, 1, OPTNcard); |
|||
model->NBJT2options = options; |
|||
} |
|||
outputs = model->NBJT2outputs; |
|||
if (!outputs) { |
|||
TSCALLOC(outputs, 1, OUTPcard); |
|||
model->NBJT2outputs = outputs; |
|||
} |
|||
if (!methods->METHvoltPredGiven) { |
|||
methods->METHvoltPred = FALSE; |
|||
} |
|||
if (!methods->METHmobDerivGiven) { |
|||
methods->METHmobDeriv = TRUE; |
|||
} |
|||
if (!methods->METHoneCarrierGiven) { |
|||
methods->METHoneCarrier = FALSE; |
|||
} |
|||
if (!methods->METHacAnalysisMethodGiven) { |
|||
methods->METHacAnalysisMethod = SOR; |
|||
} |
|||
if (!methods->METHdabstolGiven) { |
|||
methods->METHdabstol = DABSTOL2D; |
|||
} |
|||
if (!methods->METHdreltolGiven) { |
|||
methods->METHdreltol = ckt->CKTreltol; |
|||
} |
|||
if (!methods->METHitLimGiven) { |
|||
methods->METHitLim = 50; |
|||
} |
|||
if (!methods->METHomegaGiven || methods->METHomega <= 0.0) { |
|||
methods->METHomega = 2.0 * M_PI /* radians/sec */ ; |
|||
} |
|||
if (!options->OPTNdefaGiven || options->OPTNdefa <= 0.0) { |
|||
options->OPTNdefa = 1.0e4 /* cm^2 */ ; |
|||
} |
|||
if (!options->OPTNdeflGiven || options->OPTNdefl <= 0.0) { |
|||
options->OPTNdefl = 1.0e2 /* cm */ ; |
|||
} |
|||
if (!options->OPTNdefwGiven && options->OPTNdefaGiven) { |
|||
options->OPTNdefw = options->OPTNdefa / options->OPTNdefl; |
|||
} else if (!options->OPTNdefwGiven || options->OPTNdefw <= 0.0) { |
|||
options->OPTNdefw = 1.0e2 /* cm */ ; |
|||
} |
|||
if (!options->OPTNdeviceTypeGiven) { |
|||
options->OPTNdeviceType = OPTN_BIPOLAR; |
|||
} |
|||
if (!options->OPTNicFileGiven) { |
|||
options->OPTNicFile = NULL; |
|||
options->OPTNunique = FALSE; /* Can't form a unique name. */ |
|||
} |
|||
if (!options->OPTNuniqueGiven) { |
|||
options->OPTNunique = FALSE; |
|||
} |
|||
OneCarrier = methods->METHoneCarrier; |
|||
|
|||
/* Set up the rest of the card lists */ |
|||
if ((error = MODLsetup(model->NBJT2models))) |
|||
return (error); |
|||
BandGapNarrowing = models->MODLbandGapNarrowing; |
|||
ConcDepLifetime = models->MODLconcDepLifetime; |
|||
TempDepMobility = models->MODLtempDepMobility; |
|||
ConcDepMobility = models->MODLconcDepMobility; |
|||
SurfaceMobility = models->MODLsurfaceMobility; |
|||
|
|||
if ((error = OUTPsetup(model->NBJT2outputs))) |
|||
return (error); |
|||
if ((error = MATLsetup(model->NBJT2materials, &materialList))) |
|||
return (error); |
|||
if ((error = MOBsetup(model->NBJT2mobility, materialList))) |
|||
return (error); |
|||
if ((error = MESHsetup('x', model->NBJT2xMeshes, &xCoordList, &xMeshSize))) |
|||
return (error); |
|||
if ((error = MESHsetup('y', model->NBJT2yMeshes, &yCoordList, &yMeshSize))) |
|||
return (error); |
|||
if ((error = DOMNsetup(model->NBJT2domains, &domainList, |
|||
xCoordList, yCoordList, materialList))) |
|||
return (error); |
|||
if ((error = BDRYsetup(model->NBJT2boundaries, |
|||
xCoordList, yCoordList, domainList))) |
|||
return (error); |
|||
if ((error = ELCTsetup(model->NBJT2electrodes, &electrodeList, |
|||
xCoordList, yCoordList))) |
|||
return (error); |
|||
/* Make sure electrodes are OK. */ |
|||
checkElectrodes(electrodeList, 3); /* NBJT2 has 3 electrodes */ |
|||
|
|||
if ((error = CONTsetup(model->NBJT2contacts, electrodeList))) |
|||
return (error); |
|||
if ((error = DOPsetup(model->NBJT2dopings, &profileList, |
|||
&dopTableList, xCoordList, yCoordList))) |
|||
return (error); |
|||
model->NBJT2matlInfo = materialList; |
|||
model->NBJT2profiles = profileList; |
|||
model->NBJT2dopTables = dopTableList; |
|||
|
|||
/* loop through all the instances of the model */ |
|||
for (inst = model->NBJT2instances; inst != NULL; |
|||
inst = inst->NBJT2nextInstance) { |
|||
if (inst->NBJT2owner != ARCHme) goto matrixpointers; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
if (!inst->NBJT2printGiven) { |
|||
inst->NBJT2print = 0; |
|||
} else if (inst->NBJT2print <= 0) { |
|||
inst->NBJT2print = 1; |
|||
} |
|||
if (!inst->NBJT2icFileGiven) { |
|||
if (options->OPTNunique) { |
|||
nameLen = strlen(options->OPTNicFile) + strlen(inst->NBJT2name) + 1; |
|||
TSCALLOC(icFileName, nameLen+1, char); |
|||
sprintf(icFileName, "%s.%s", options->OPTNicFile, inst->NBJT2name); |
|||
icFileName[nameLen] = '\0'; |
|||
inst->NBJT2icFile = icFileName; |
|||
} else if (options->OPTNicFile != NULL) { |
|||
nameLen = strlen(options->OPTNicFile); |
|||
TSCALLOC(icFileName, nameLen+1, char); |
|||
icFileName = strcpy(icFileName, options->OPTNicFile); |
|||
inst->NBJT2icFile = icFileName; |
|||
} else { |
|||
inst->NBJT2icFile = NULL; |
|||
} |
|||
} |
|||
inst->NBJT2state = *states; |
|||
*states += NBJT2numStates; |
|||
|
|||
if (!inst->NBJT2pDevice) { |
|||
/* Assign the mesh and profile info to each instance. */ |
|||
TSCALLOC(pDevice, 1, TWOdevice); |
|||
TSCALLOC(pDevice->pStats, 1, TWOstats); |
|||
pDevice->name = inst->NBJT2name; |
|||
pDevice->solverType = SLV_NONE; |
|||
pDevice->numXNodes = xMeshSize; |
|||
pDevice->numYNodes = yMeshSize; |
|||
pDevice->xScale = MESHmkArray(xCoordList, xMeshSize); |
|||
pDevice->yScale = MESHmkArray(yCoordList, yMeshSize); |
|||
pDevice->abstol = methods->METHdabstol; |
|||
pDevice->reltol = methods->METHdreltol; |
|||
pDevice->rhsImag = NIL(double); |
|||
TSCALLOC(pDevice->elemArray, pDevice->numXNodes, TWOelem **); |
|||
for (xIndex = 1; xIndex < pDevice->numXNodes; xIndex++) { |
|||
TSCALLOC(pDevice->elemArray[xIndex], pDevice->numYNodes, TWOelem *); |
|||
} |
|||
|
|||
/* Create a copy of material data that can change with temperature. */ |
|||
pDevice->pMaterials = NIL(TWOmaterial); |
|||
for (pM = materialList; pM != NIL(TWOmaterial); pM = pM->next) { |
|||
if (pDevice->pMaterials == NIL(TWOmaterial)) { |
|||
TSCALLOC(pMaterial, 1, TWOmaterial); |
|||
pDevice->pMaterials = pMaterial; |
|||
} else { |
|||
TSCALLOC(pMaterial->next, 1, TWOmaterial); |
|||
pMaterial = pMaterial->next; |
|||
} |
|||
/* Copy everything, then fix the incorrect pointer. */ |
|||
bcopy((char *) pM, (char *) pMaterial, sizeof(TWOmaterial)); |
|||
pMaterial->next = NIL(TWOmaterial); |
|||
} |
|||
|
|||
/* Generate the mesh structure for the device. */ |
|||
TWObuildMesh(pDevice, domainList, electrodeList, pDevice->pMaterials); |
|||
|
|||
/* Store the device info in the instance. */ |
|||
inst->NBJT2pDevice = pDevice; |
|||
} |
|||
/* Now update the state pointers. */ |
|||
TWOgetStatePointers(inst->NBJT2pDevice, states); |
|||
|
|||
/* Wipe out statistics from previous runs (if any). */ |
|||
bzero((char *) inst->NBJT2pDevice->pStats, sizeof(TWOstats)); |
|||
|
|||
inst->NBJT2pDevice->pStats->totalTime[STAT_SETUP] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
|
|||
/* macro to make elements with built in test for out of memory */ |
|||
#define TSTALLOC(ptr,first,second) \ |
|||
if ((inst->ptr = SMPmakeElt(matrix,inst->first,inst->second))==(double *)NULL){\ |
|||
return(E_NOMEM);\ |
|||
} |
|||
|
|||
matrixpointers: |
|||
TSTALLOC(NBJT2colColPtr, NBJT2colNode, NBJT2colNode) |
|||
TSTALLOC(NBJT2colBasePtr, NBJT2colNode, NBJT2baseNode) |
|||
TSTALLOC(NBJT2colEmitPtr, NBJT2colNode, NBJT2emitNode) |
|||
TSTALLOC(NBJT2baseColPtr, NBJT2baseNode, NBJT2colNode) |
|||
TSTALLOC(NBJT2baseBasePtr, NBJT2baseNode, NBJT2baseNode) |
|||
TSTALLOC(NBJT2baseEmitPtr, NBJT2baseNode, NBJT2emitNode) |
|||
TSTALLOC(NBJT2emitColPtr, NBJT2emitNode, NBJT2colNode) |
|||
TSTALLOC(NBJT2emitBasePtr, NBJT2emitNode, NBJT2baseNode) |
|||
TSTALLOC(NBJT2emitEmitPtr, NBJT2emitNode, NBJT2emitNode) |
|||
} |
|||
/* Clean up lists */ |
|||
killCoordInfo(xCoordList); |
|||
killCoordInfo(yCoordList); |
|||
killDomainInfo(domainList); |
|||
killElectrodeInfo(electrodeList); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,130 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
Author: 1992 David A. Gates, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "nbjt2def.h" |
|||
#include "numenum.h" |
|||
#include "carddefs.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
#define NIL(type) ((type *)0) |
|||
|
|||
int |
|||
NBJT2temp(inModel, ckt) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
/* |
|||
* perform the temperature update |
|||
*/ |
|||
{ |
|||
register NBJT2model *model = (NBJT2model *) inModel; |
|||
register NBJT2instance *inst; |
|||
METHcard *methods; |
|||
MODLcard *models; |
|||
OPTNcard *options; |
|||
OUTPcard *outputs; |
|||
TWOmaterial *pM, *pMaterial, *pNextMaterial; |
|||
double startTime; |
|||
|
|||
|
|||
/* loop through all the models */ |
|||
for (; model != NULL; model = model->NBJT2nextModel) { |
|||
methods = model->NBJT2methods; |
|||
models = model->NBJT2models; |
|||
options = model->NBJT2options; |
|||
outputs = model->NBJT2outputs; |
|||
|
|||
if (!options->OPTNtnomGiven) { |
|||
options->OPTNtnom = ckt->CKTnomTemp; |
|||
} |
|||
for (pM = model->NBJT2matlInfo; pM != NIL(TWOmaterial); |
|||
pM = pM->next) { |
|||
pM->tnom = options->OPTNtnom; |
|||
} |
|||
|
|||
BandGapNarrowing = models->MODLbandGapNarrowing; |
|||
ConcDepLifetime = models->MODLconcDepLifetime; |
|||
TempDepMobility = models->MODLtempDepMobility; |
|||
ConcDepMobility = models->MODLconcDepMobility; |
|||
SurfaceMobility = models->MODLsurfaceMobility; |
|||
MatchingMobility = models->MODLmatchingMobility; |
|||
OneCarrier = methods->METHoneCarrier; |
|||
|
|||
for (inst = model->NBJT2instances; inst != NULL; |
|||
inst = inst->NBJT2nextInstance) { |
|||
if (inst->NBJT2owner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
if (!inst->NBJT2tempGiven) { |
|||
inst->NBJT2temp = ckt->CKTtemp; |
|||
} |
|||
if (!inst->NBJT2areaGiven || inst->NBJT2area <= 0.0) { |
|||
inst->NBJT2area = 1.0; |
|||
} |
|||
if (!inst->NBJT2widthGiven || inst->NBJT2width <= 0.0) { |
|||
inst->NBJT2width = 1.0; |
|||
} |
|||
inst->NBJT2pDevice->width = |
|||
inst->NBJT2area * inst->NBJT2width * options->OPTNdefw; |
|||
|
|||
/* Compute and save globals for this instance. */ |
|||
GLOBcomputeGlobals(&(inst->NBJT2globals), inst->NBJT2temp); |
|||
|
|||
/* Calculate new sets of material parameters. */ |
|||
pM = model->NBJT2matlInfo; |
|||
pMaterial = inst->NBJT2pDevice->pMaterials; |
|||
for (; pM != NULL; pM = pM->next, pMaterial = pMaterial->next) { |
|||
|
|||
/* Copy everything, then fix the incorrect pointer. */ |
|||
pNextMaterial = pMaterial->next; |
|||
bcopy((char *) pM, (char *) pMaterial, sizeof(TWOmaterial)); |
|||
pMaterial->next = pNextMaterial; |
|||
|
|||
/* Now do the temperature dependence. */ |
|||
MATLtempDep(pMaterial, pMaterial->tnom); |
|||
if (outputs->OUTPmaterial) { |
|||
printMaterialInfo(pMaterial); |
|||
} |
|||
} |
|||
|
|||
/* Assign doping to the mesh. */ |
|||
TWOsetDoping(inst->NBJT2pDevice, model->NBJT2profiles, |
|||
model->NBJT2dopTables); |
|||
|
|||
/* Assign physical parameters to the mesh. */ |
|||
TWOsetup(inst->NBJT2pDevice); |
|||
|
|||
/* Assign boundary condition parameters. */ |
|||
TWOsetBCparams(inst->NBJT2pDevice, model->NBJT2boundaries); |
|||
|
|||
/* Normalize everything. */ |
|||
TWOnormalize(inst->NBJT2pDevice); |
|||
|
|||
/* Find the device's type. */ |
|||
if (inst->NBJT2pDevice->pFirstContact->pNodes[0]->netConc < 0.0) { |
|||
inst->NBJT2type = PNP; |
|||
if (OneCarrier) { |
|||
methods->METHoneCarrier = P_TYPE; |
|||
} |
|||
} else { |
|||
inst->NBJT2type = NPN; |
|||
if (OneCarrier) { |
|||
methods->METHoneCarrier = N_TYPE; |
|||
} |
|||
} |
|||
|
|||
inst->NBJT2pDevice->pStats->totalTime[STAT_SETUP] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine performs truncation error calculations for NBJT2s in the |
|||
* circuit. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "nbjt2def.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
int |
|||
NBJT2trunc(inModel, ckt, timeStep) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
double *timeStep; |
|||
|
|||
{ |
|||
register NBJT2model *model = (NBJT2model *) inModel; |
|||
register NBJT2instance *inst; |
|||
double deltaNew; |
|||
double deltaNorm[7]; |
|||
double startTime; |
|||
int i; |
|||
|
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
|
|||
for (; model != NULL; model = model->NBJT2nextModel) { |
|||
OneCarrier = model->NBJT2methods->METHoneCarrier; |
|||
model->NBJT2pInfo->order = ckt->CKTorder; |
|||
model->NBJT2pInfo->delta = deltaNorm; |
|||
model->NBJT2pInfo->lteCoeff = computeLTECoeff(model->NBJT2pInfo); |
|||
for (inst = model->NBJT2instances; inst != NULL; |
|||
inst = inst->NBJT2nextInstance) { |
|||
if (inst->NBJT2owner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
deltaNew = TWOtrunc(inst->NBJT2pDevice, model->NBJT2pInfo, |
|||
ckt->CKTdelta); |
|||
*timeStep = MIN(*timeStep, deltaNew); |
|||
inst->NBJT2pDevice->pStats->totalTime[STAT_TRAN] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
## Process this file with automake to produce Makefile.in
|
|||
|
|||
noinst_LIBRARIES = libnumd.a |
|||
|
|||
libnumd_a_SOURCES = \
|
|||
numd.c \
|
|||
numdacld.c \
|
|||
numdask.c \
|
|||
numddefs.h \
|
|||
numddel.c \
|
|||
numddest.c \
|
|||
numddump.c \
|
|||
numdext.h \
|
|||
numdinit.c \
|
|||
numdinit.h \
|
|||
numditf.h \
|
|||
numdload.c \
|
|||
numdmdel.c \
|
|||
numdmpar.c \
|
|||
numdparm.c \
|
|||
numdpzld.c \
|
|||
numdset.c \
|
|||
numdtemp.c \
|
|||
numdtrun.c |
|||
|
|||
|
|||
INCLUDES = -I$(top_srcdir)/src/include |
|||
|
|||
MAINTAINERCLEANFILES = Makefile.in |
|||
@ -0,0 +1,53 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "devdefs.h" |
|||
#include "numddefs.h" |
|||
#include "suffix.h" |
|||
|
|||
IFparm NUMDpTable[] = { /* parameters */ |
|||
IP("off", NUMD_OFF, IF_FLAG, "Initially off"), |
|||
IP("ic.file", NUMD_IC_FILE, IF_REAL, "Initial conditions file"), |
|||
IOP("area", NUMD_AREA, IF_REAL, "Area factor"), |
|||
IP("save", NUMD_PRINT, IF_REAL, "Save Solutions"), |
|||
IP("print", NUMD_PRINT, IF_REAL, "Print Solutions"), |
|||
OP("vd", NUMD_VD, IF_REAL, "Voltage"), |
|||
OP("id", NUMD_ID, IF_REAL, "Current"), |
|||
OP("g11", NUMD_G11, IF_REAL, "Conductance"), |
|||
OP("c11", NUMD_C11, IF_REAL, "Capacitance"), |
|||
OP("y11", NUMD_Y11, IF_COMPLEX, "Admittance"), |
|||
OPU("g12", NUMD_G12, IF_REAL, "Conductance"), |
|||
OPU("c12", NUMD_C12, IF_REAL, "Capacitance"), |
|||
OPU("y12", NUMD_Y12, IF_COMPLEX, "Admittance"), |
|||
OPU("g21", NUMD_G21, IF_REAL, "Conductance"), |
|||
OPU("c21", NUMD_C21, IF_REAL, "Capacitance"), |
|||
OPU("y21", NUMD_Y21, IF_COMPLEX, "Admittance"), |
|||
OPU("g22", NUMD_G22, IF_REAL, "Conductance"), |
|||
OPU("c22", NUMD_C22, IF_REAL, "Capacitance"), |
|||
OPU("y22", NUMD_Y22, IF_COMPLEX, "Admittance"), |
|||
OPR("voltage", NUMD_VD, IF_REAL, "Voltage"), |
|||
OPR("current", NUMD_ID, IF_REAL, "Current"), |
|||
OPR("conductance", NUMD_G11, IF_REAL, "Conductance"), |
|||
OPR("capacitance", NUMD_C11, IF_REAL, "Capacitance"), |
|||
IOP("temp", NUMD_TEMP, IF_REAL, "Instance Temperature") |
|||
}; |
|||
|
|||
IFparm NUMDmPTable[] = { /* model parameters */ |
|||
/* numerical-device models no longer have parameters */ |
|||
/* one is left behind to keep the table from being empty */ |
|||
IP("numd", NUMD_MOD_NUMD, IF_REAL, "Numerical Diode") |
|||
}; |
|||
|
|||
char *NUMDnames[] = { |
|||
"D+", |
|||
"D-" |
|||
}; |
|||
|
|||
int NUMDnSize = NUMELEMS(NUMDnames); |
|||
int NUMDpTSize = NUMELEMS(NUMDpTable); |
|||
int NUMDmPTSize = NUMELEMS(NUMDmPTable); |
|||
int NUMDiSize = sizeof(NUMDinstance); |
|||
int NUMDmSize = sizeof(NUMDmodel); |
|||
@ -0,0 +1,77 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* Function to load the COMPLEX circuit matrix using the small signal |
|||
* parameters saved during a previous DC operating point analysis. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "numddefs.h" |
|||
#include "sperror.h" |
|||
#include "complex.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "numglobs.h" |
|||
#include "suffix.h" |
|||
|
|||
/* External Declarations */ |
|||
extern int ONEacDebug; |
|||
|
|||
int |
|||
NUMDacLoad(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
register NUMDmodel *model = (NUMDmodel *) inModel; |
|||
register NUMDinstance *inst; |
|||
SPcomplex y; |
|||
double startTime; |
|||
|
|||
/* loop through all the diode models */ |
|||
for (; model != NULL; model = model->NUMDnextModel) { |
|||
FieldDepMobility = model->NUMDmodels->MODLfieldDepMobility; |
|||
Srh = model->NUMDmodels->MODLsrh; |
|||
Auger = model->NUMDmodels->MODLauger; |
|||
AvalancheGen = model->NUMDmodels->MODLavalancheGen; |
|||
AcAnalysisMethod = model->NUMDmethods->METHacAnalysisMethod; |
|||
MobDeriv = model->NUMDmethods->METHmobDeriv; |
|||
ONEacDebug = model->NUMDoutputs->OUTPacDebug; |
|||
|
|||
for (inst = model->NUMDinstances; inst != NULL; |
|||
inst = inst->NUMDnextInstance) { |
|||
if (inst->NUMDowner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NUMDglobals)); |
|||
|
|||
model->NUMDmethods->METHacAnalysisMethod = |
|||
NUMDadmittance(inst->NUMDpDevice, |
|||
ckt->CKTomega, &y); |
|||
|
|||
*(inst->NUMDposPosPtr) += y.real; |
|||
*(inst->NUMDposPosPtr + 1) += y.imag; |
|||
*(inst->NUMDnegNegPtr) += y.real; |
|||
*(inst->NUMDnegNegPtr + 1) += y.imag; |
|||
*(inst->NUMDnegPosPtr) -= y.real; |
|||
*(inst->NUMDnegPosPtr + 1) -= y.imag; |
|||
*(inst->NUMDposNegPtr) -= y.real; |
|||
*(inst->NUMDposNegPtr + 1) -= y.imag; |
|||
if (ckt->CKTomega != 0.0) { |
|||
inst->NUMDc11 = y.imag / ckt->CKTomega; |
|||
} else { |
|||
inst->NUMDc11 = 0.0; /* XXX What else can be done?! */ |
|||
} |
|||
inst->NUMDy11r = y.real; |
|||
inst->NUMDy11i = y.imag; |
|||
inst->NUMDsmSigAvail = TRUE; |
|||
inst->NUMDpDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,121 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Thomas L. Quarles |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "devdefs.h" |
|||
#include "numddefs.h" |
|||
#include "complex.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
/* Check out this one */ |
|||
extern int NUMDinitSmSig(NUMDinstance *); |
|||
|
|||
|
|||
/* ARGSUSED */ |
|||
int |
|||
NUMDask(ckt, inInst, which, value, select) |
|||
CKTcircuit *ckt; |
|||
GENinstance *inInst; |
|||
int which; |
|||
IFvalue *value; |
|||
IFvalue *select; |
|||
{ |
|||
NUMDinstance *inst = (NUMDinstance *) inInst; |
|||
SPcomplex yd; |
|||
|
|||
switch (which) { |
|||
case NUMD_AREA: |
|||
value->rValue = inst->NUMDarea; |
|||
return (OK); |
|||
case NUMD_TEMP: |
|||
value->rValue = inst->NUMDtemp - CONSTCtoK; |
|||
return (OK); |
|||
case NUMD_VD: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMDvoltage); |
|||
return (OK); |
|||
case NUMD_ID: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMDid); |
|||
return (OK); |
|||
case NUMD_G11: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMDconduct); |
|||
return (OK); |
|||
case NUMD_G12: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NUMDconduct); |
|||
return (OK); |
|||
case NUMD_G21: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NUMDconduct); |
|||
return (OK); |
|||
case NUMD_G22: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMDconduct); |
|||
return (OK); |
|||
case NUMD_C11: |
|||
if (!inst->NUMDsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMDinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMDc11; |
|||
return (OK); |
|||
case NUMD_C12: |
|||
if (!inst->NUMDsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMDinitSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NUMDc11; |
|||
return (OK); |
|||
case NUMD_C21: |
|||
if (!inst->NUMDsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMDinitSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NUMDc11; |
|||
return (OK); |
|||
case NUMD_C22: |
|||
if (!inst->NUMDsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMDinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMDc11; |
|||
return (OK); |
|||
case NUMD_Y11: |
|||
if (!inst->NUMDsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMDinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMDy11r; |
|||
value->cValue.imag = inst->NUMDy11i; |
|||
return (OK); |
|||
case NUMD_Y12: |
|||
if (!inst->NUMDsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMDinitSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NUMDy11r; |
|||
value->cValue.imag = -inst->NUMDy11i; |
|||
return (OK); |
|||
case NUMD_Y21: |
|||
if (!inst->NUMDsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMDinitSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NUMDy11r; |
|||
value->cValue.imag = -inst->NUMDy11i; |
|||
return (OK); |
|||
case NUMD_Y22: |
|||
if (!inst->NUMDsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMDinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMDy11r; |
|||
value->cValue.imag = inst->NUMDy11i; |
|||
return (OK); |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
/* NOTREACHED */ |
|||
} |
|||
@ -0,0 +1,135 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Authors: 1987 Karti Mayaram, 1991 David Gates |
|||
**********/ |
|||
|
|||
#ifndef NUMD_H |
|||
#define NUMD_H |
|||
|
|||
/* data structures used to describe 1D numerical diodes */ |
|||
|
|||
/* circuit level includes */ |
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "gendefs.h" |
|||
|
|||
/* device level includes */ |
|||
#include "onemesh.h" |
|||
#include "onedev.h" |
|||
#include "profile.h" |
|||
#include "numglobs.h" |
|||
#include "carddefs.h" |
|||
|
|||
/* information needed per instance */ |
|||
typedef struct sNUMDinstance { |
|||
struct sNUMDmodel *NUMDmodPtr;/* back pointer to model */ |
|||
struct sNUMDinstance *NUMDnextInstance; /* pointer to next instance |
|||
* of current model */ |
|||
IFuid NUMDname; /* pointer to character string naming this |
|||
* instance */ |
|||
int NUMDowner; /* number of owner process */ |
|||
int NUMDstate; /* pointer to start of state vector for diode */ |
|||
|
|||
#define NUMDvoltage NUMDstate |
|||
#define NUMDid NUMDstate+1 |
|||
#define NUMDconduct NUMDstate+2 |
|||
#define NUMDnumStates 3 |
|||
|
|||
int NUMDposNode; /* number of positive node of diode */ |
|||
int NUMDnegNode; /* number of negative node of diode */ |
|||
ONEdevice *NUMDpDevice; |
|||
GLOBvalues NUMDglobals; /* Temp.-Dep. Global Parameters */ |
|||
int NUMDtype; /* device type pn or np */ |
|||
double NUMDarea; /* area factor for the diode */ |
|||
double NUMDtemp; /* instance temperature */ |
|||
double NUMDc11; /* small-signal capacitance */ |
|||
double NUMDy11r; /* small-signal admittance, real part */ |
|||
double NUMDy11i; /* small-signal admittance, imag part */ |
|||
int NUMDprint; /* number of timesteps after which print |
|||
* internal */ |
|||
char *NUMDicFile; /* Name of initial condition file */ |
|||
double *NUMDnegPosPtr; /* pointer to sparse matrix at |
|||
* (negative,positive) */ |
|||
double *NUMDposNegPtr; /* pointer to sparse matrix at |
|||
* (positive,negative) */ |
|||
double *NUMDposPosPtr; /* pointer to sparse matrix at |
|||
* (positive,positive) */ |
|||
double *NUMDnegNegPtr; /* pointer to sparse matrix at |
|||
* (negative,negative) */ |
|||
|
|||
int NUMDoff; /* 'off' flag for diode */ |
|||
unsigned NUMDsmSigAvail:1; /* flag to indicate small-signal done */ |
|||
unsigned NUMDareaGiven:1; /* flag to indicate area was specified */ |
|||
unsigned NUMDicFileGiven:1; /* flag to indicate init. cond. file given */ |
|||
unsigned NUMDtempGiven:1; /* flag to indicate temp was specified */ |
|||
unsigned NUMDprintGiven:1; /* flag to indicate if print was specified */ |
|||
} NUMDinstance; |
|||
|
|||
|
|||
/* per model data */ |
|||
|
|||
typedef struct sNUMDmodel { /* model structure for a diode */ |
|||
int NUMDmodType; /* type index of this device type */ |
|||
struct sNUMDmodel *NUMDnextModel; /* pointer to next possible model in |
|||
* linked list */ |
|||
NUMDinstance *NUMDinstances; /* pointer to list of instances that have |
|||
* this model */ |
|||
IFuid NUMDmodName; /* pointer to character string naming this |
|||
* model */ |
|||
/* Everything below here is numerical-device-specific */ |
|||
MESHcard *NUMDxMeshes; /* list of xmesh cards */ |
|||
MESHcard *NUMDyMeshes; /* list of ymesh cards */ |
|||
DOMNcard *NUMDdomains; /* list of domain cards */ |
|||
BDRYcard *NUMDboundaries; /* list of boundary cards */ |
|||
DOPcard *NUMDdopings; /* list of doping cards */ |
|||
ELCTcard *NUMDelectrodes; /* list of electrode cards */ |
|||
CONTcard *NUMDcontacts; /* list of contact cards */ |
|||
MODLcard *NUMDmodels; /* list of model cards */ |
|||
MATLcard *NUMDmaterials; /* list of material cards */ |
|||
MOBcard *NUMDmobility; /* list of mobility cards */ |
|||
METHcard *NUMDmethods; /* list of method cards */ |
|||
OPTNcard *NUMDoptions; /* list of option cards */ |
|||
OUTPcard *NUMDoutputs; /* list of output cards */ |
|||
ONEtranInfo *NUMDpInfo; /* transient analysis information */ |
|||
DOPprofile *NUMDprofiles; /* expanded list of doping profiles */ |
|||
DOPtable *NUMDdopTables; /* list of tables used by profiles */ |
|||
ONEmaterial *NUMDmatlInfo; /* list of material info structures */ |
|||
} NUMDmodel; |
|||
|
|||
/* type of 1D diode */ |
|||
#define PN 1 |
|||
#define NP -1 |
|||
|
|||
/* device parameters */ |
|||
#define NUMD_AREA 1 |
|||
#define NUMD_IC_FILE 2 |
|||
#define NUMD_OFF 3 |
|||
#define NUMD_PRINT 4 |
|||
#define NUMD_TEMP 5 |
|||
#define NUMD_VD 6 |
|||
#define NUMD_ID 7 |
|||
|
|||
#define NUMD_G11 8 |
|||
#define NUMD_C11 9 |
|||
#define NUMD_Y11 10 |
|||
#define NUMD_G12 11 |
|||
#define NUMD_C12 12 |
|||
#define NUMD_Y12 13 |
|||
#define NUMD_G21 14 |
|||
#define NUMD_C21 15 |
|||
#define NUMD_Y21 16 |
|||
#define NUMD_G22 17 |
|||
#define NUMD_C22 18 |
|||
#define NUMD_Y22 19 |
|||
|
|||
/* model parameters */ |
|||
/* NOTE: all true model parameters have been moved to IFcardInfo structures */ |
|||
#define NUMD_MOD_NUMD 101 |
|||
|
|||
/* device questions */ |
|||
|
|||
/* model questions */ |
|||
|
|||
#include "numdext.h" |
|||
|
|||
#endif /* NUMD_H */ |
|||
@ -0,0 +1,36 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "numddefs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NUMDdelete(inModel, name, kill) |
|||
GENmodel *inModel; |
|||
IFuid name; |
|||
GENinstance **kill; |
|||
|
|||
{ |
|||
|
|||
NUMDmodel *model = (NUMDmodel *) inModel; |
|||
NUMDinstance **fast = (NUMDinstance **) kill; |
|||
NUMDinstance **prev = NULL; |
|||
NUMDinstance *inst; |
|||
|
|||
for (; model; model = model->NUMDnextModel) { |
|||
prev = &(model->NUMDinstances); |
|||
for (inst = *prev; inst; inst = *prev) { |
|||
if (inst->NUMDname == name || (fast && inst == *fast)) { |
|||
*prev = inst->NUMDnextInstance; |
|||
FREE(inst); |
|||
return (OK); |
|||
} |
|||
prev = &(inst->NUMDnextInstance); |
|||
} |
|||
} |
|||
return (E_NODEV); |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine deletes all NUMDs from the circuit and frees all storage they |
|||
* were using. The current implementation has memory leaks. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "numddefs.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
void |
|||
NUMDdestroy(inModel) |
|||
GENmodel **inModel; |
|||
{ |
|||
|
|||
NUMDmodel **model = (NUMDmodel **) inModel; |
|||
NUMDmodel *mod, *nextMod; |
|||
NUMDinstance *inst, *nextInst; |
|||
|
|||
|
|||
for (mod = *model; mod;) { |
|||
for (inst = mod->NUMDinstances; inst;) { |
|||
ONEdestroy(inst->NUMDpDevice); |
|||
nextInst = inst->NUMDnextInstance; |
|||
FREE(inst); |
|||
inst = nextInst; |
|||
} |
|||
nextMod = mod->NUMDnextModel; |
|||
FREE(mod); |
|||
mod = nextMod; |
|||
} |
|||
*model = NULL; |
|||
} |
|||
@ -0,0 +1,164 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This is a simple routine to dump the internal device states. It produces |
|||
* states for .OP, .DC, & .TRAN simulations. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "numddefs.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
/* Forward Declarations */ |
|||
static void NUMDputHeader(FILE *, CKTcircuit *, NUMDinstance *); |
|||
|
|||
/* State Counter */ |
|||
static int state_numOP = 0; |
|||
static int state_numDC = 0; |
|||
static int state_numTR = 0; |
|||
|
|||
void |
|||
NUMDdump(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
register NUMDmodel *model = (NUMDmodel *) inModel; |
|||
register NUMDinstance *inst; |
|||
OUTPcard *output; |
|||
FILE *fpState; |
|||
char fileName[BSIZE_SP]; |
|||
char description[BSIZE_SP]; |
|||
char *prefix; |
|||
int *state_num; |
|||
int anyOutput = 0; |
|||
|
|||
if (ckt->CKTmode & MODEDCOP) { |
|||
prefix = "OP"; |
|||
state_num = &state_numOP; |
|||
sprintf(description, "..."); |
|||
} else if (ckt->CKTmode & MODEDCTRANCURVE) { |
|||
prefix = "DC"; |
|||
state_num = &state_numDC; |
|||
sprintf(description, "sweep = % e", ckt->CKTtime); |
|||
} else if (ckt->CKTmode & MODETRAN) { |
|||
prefix = "TR"; |
|||
state_num = &state_numTR; |
|||
sprintf(description, "time = % e", ckt->CKTtime); |
|||
} else { |
|||
/* Not a recognized CKT mode. */ |
|||
return; |
|||
} |
|||
|
|||
for (; model != NULL; model = model->NUMDnextModel) { |
|||
output = model->NUMDoutputs; |
|||
for (inst = model->NUMDinstances; inst != NULL; |
|||
inst = inst->NUMDnextInstance) { |
|||
if (inst->NUMDowner != ARCHme) continue; |
|||
|
|||
if (inst->NUMDprintGiven) { |
|||
if ((ckt->CKTmode & MODETRAN) && |
|||
((ckt->CKTstat->STATaccepted - 1) % inst->NUMDprint != 0)) { |
|||
continue; |
|||
} |
|||
anyOutput = 1; |
|||
sprintf(fileName, "%s%s.%d.%s", output->OUTProotFile, prefix, |
|||
*state_num, inst->NUMDname); |
|||
if (!(fpState = fopen(fileName, "w"))) { |
|||
perror(fileName); |
|||
} else { |
|||
NUMDputHeader(fpState, ckt, inst); |
|||
ONEprnSolution(fpState, inst->NUMDpDevice, |
|||
model->NUMDoutputs); |
|||
fclose(fpState); |
|||
LOGmakeEntry(fileName, description); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if (anyOutput) { |
|||
(*state_num)++; |
|||
} |
|||
} |
|||
|
|||
#define NUMDnumOutputs 4 |
|||
|
|||
static |
|||
void |
|||
NUMDputHeader(file, ckt, inst) |
|||
FILE *file; |
|||
CKTcircuit *ckt; |
|||
NUMDinstance *inst; |
|||
{ |
|||
char *reference; |
|||
double refVal = 0.0; |
|||
int numVars = NUMDnumOutputs; |
|||
|
|||
if (ckt->CKTmode & MODEDCOP) { |
|||
reference = NULL; |
|||
} else if (ckt->CKTmode & MODEDCTRANCURVE) { |
|||
reference = "sweep"; |
|||
refVal = ckt->CKTtime; |
|||
numVars++; |
|||
} else if (ckt->CKTmode & MODETRAN) { |
|||
reference = "time"; |
|||
refVal = ckt->CKTtime; |
|||
numVars++; |
|||
} else { |
|||
reference = NULL; |
|||
} |
|||
fprintf(file, "Title: Device %s external state\n", inst->NUMDname); |
|||
fprintf(file, "Plotname: Device Operating Point\n"); |
|||
fprintf(file, "Command: deftype v conductance S\n"); |
|||
fprintf(file, "Flags: real\n"); |
|||
fprintf(file, "No. Variables: %d\n", numVars); |
|||
fprintf(file, "No. Points: 1\n"); |
|||
numVars = 0; |
|||
fprintf(file, "Variables:\n"); |
|||
if (reference) { |
|||
fprintf(file, "\t%d %s unknown\n", numVars++, reference); |
|||
} |
|||
fprintf(file, "\t%d v12 voltage\n", numVars++); |
|||
fprintf(file, "\t%d i1 current\n", numVars++); |
|||
fprintf(file, "\t%d i2 current\n", numVars++); |
|||
fprintf(file, "\t%d g11 conductance\n", numVars++); |
|||
fprintf(file, "Values:\n0"); |
|||
if (reference) { |
|||
fprintf(file, "\t% e\n", refVal); |
|||
} |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMDvoltage)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMDid)); |
|||
fprintf(file, "\t% e\n", - *(ckt->CKTstate0 + inst->NUMDid)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMDconduct)); |
|||
} |
|||
|
|||
void |
|||
NUMDacct(inModel, ckt, file) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
FILE *file; |
|||
{ |
|||
register NUMDmodel *model = (NUMDmodel *) inModel; |
|||
register NUMDinstance *inst; |
|||
OUTPcard *output; |
|||
|
|||
for (; model != NULL; model = model->NUMDnextModel) { |
|||
output = model->NUMDoutputs; |
|||
for (inst = model->NUMDinstances; inst != NULL; |
|||
inst = inst->NUMDnextInstance) { |
|||
if (inst->NUMDowner != ARCHme) continue; |
|||
|
|||
if (output->OUTPstats) { |
|||
ONEmemStats(file, inst->NUMDpDevice); |
|||
ONEcpuStats(file, inst->NUMDpDevice); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Karti Mayaram |
|||
**********/ |
|||
|
|||
#ifndef NUMDEXT_H |
|||
#define NUMDEXT_H |
|||
|
|||
|
|||
extern int NUMDacLoad(GENmodel *, CKTcircuit *); |
|||
extern int NUMDask(CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *); |
|||
extern int NUMDdelete(GENmodel *, IFuid, GENinstance **); |
|||
extern void NUMDdestroy(GENmodel **); |
|||
extern int NUMDgetic(GENmodel *, CKTcircuit *); |
|||
extern int NUMDload(GENmodel *, CKTcircuit *); |
|||
extern int NUMDmDelete(GENmodel **, IFuid, GENmodel *); |
|||
extern int NUMDmParam(int, IFvalue *, GENmodel *); |
|||
extern int NUMDparam(int, IFvalue *, GENinstance *, IFvalue *); |
|||
extern int NUMDpzLoad(GENmodel *, CKTcircuit *, SPcomplex *); |
|||
extern int NUMDsetup(SMPmatrix *, GENmodel *, CKTcircuit *, int *); |
|||
extern int NUMDtemp(GENmodel *, CKTcircuit *); |
|||
extern int NUMDtrunc(GENmodel *, CKTcircuit *, double *); |
|||
|
|||
extern void NUMDdump(GENmodel *, CKTcircuit *); |
|||
extern void NUMDacct(GENmodel *, CKTcircuit *, FILE *); |
|||
|
|||
#endif /* NUMDEXT_H */ |
|||
@ -0,0 +1,83 @@ |
|||
#include <config.h> |
|||
|
|||
#include <devdefs.h> |
|||
|
|||
#include "numditf.h" |
|||
#include "numdext.h" |
|||
#include "numdinit.h" |
|||
|
|||
|
|||
SPICEdev NUMDinfo = { |
|||
{ |
|||
"NUMD", |
|||
"1D Numerical Junction Diode model", |
|||
|
|||
&NUMDnSize, |
|||
&NUMDnSize, |
|||
NUMDnames, |
|||
|
|||
&NUMDpTSize, |
|||
NUMDpTable, |
|||
|
|||
&NUMDmPTSize, |
|||
NUMDmPTable, |
|||
|
|||
#ifdef XSPICE |
|||
/*---- Fixed by SDB 5.2.2003 to enable XSPICE/tclspice integration -----*/ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
/*--------------------------- End of SDB fix -------------------------*/ |
|||
#endif |
|||
|
|||
DEV_DEFAULT |
|||
}, |
|||
|
|||
DEVparam : NUMDparam, |
|||
DEVmodParam : NUMDmParam, |
|||
DEVload : NUMDload, |
|||
DEVsetup : NUMDsetup, |
|||
DEVunsetup : NULL, |
|||
DEVpzSetup : NUMDsetup, |
|||
DEVtemperature: NUMDtemp, |
|||
DEVtrunc : NUMDtrunc, |
|||
DEVfindBranch : NULL, |
|||
DEVacLoad : NUMDacLoad, |
|||
DEVaccept : NULL, |
|||
DEVdestroy : NUMDdestroy, |
|||
DEVmodDelete : NUMDmDelete, |
|||
DEVdelete : NUMDdelete, |
|||
DEVsetic : NULL, |
|||
DEVask : NUMDask, |
|||
DEVmodAsk : NULL, |
|||
DEVpzLoad : NUMDpzLoad, |
|||
DEVconvTest : NULL, |
|||
DEVsenSetup : NULL, |
|||
DEVsenLoad : NULL, |
|||
DEVsenUpdate : NULL, |
|||
DEVsenAcLoad : NULL, |
|||
DEVsenPrint : NULL, |
|||
DEVsenTrunc : NULL, |
|||
DEVdisto : NULL, |
|||
DEVnoise : NULL, |
|||
DEVdump : NUMDdump, |
|||
DEVacct : NUMDacct, |
|||
|
|||
DEVinstSize : &NUMDiSize, |
|||
DEVmodSize : &NUMDmSize |
|||
|
|||
}; |
|||
|
|||
|
|||
SPICEdev * |
|||
get_numd_info(void) |
|||
{ |
|||
return &NUMDinfo; |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
#ifndef _NUMDINIT_H |
|||
#define _NUMDINIT_H |
|||
|
|||
extern IFparm NUMDpTable[ ]; |
|||
extern IFparm NUMDmPTable[ ]; |
|||
extern char *NUMDnames[ ]; |
|||
extern int NUMDpTSize; |
|||
extern int NUMDmPTSize; |
|||
extern int NUMDnSize; |
|||
extern int NUMDiSize; |
|||
extern int NUMDmSize; |
|||
|
|||
#endif |
|||
@ -0,0 +1,10 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
**********/ |
|||
|
|||
#ifndef DEV_NUMD |
|||
#define DEV_NUMD |
|||
|
|||
extern SPICEdev *get_numd_info(void); |
|||
|
|||
#endif |
|||
@ -0,0 +1,393 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "devdefs.h" |
|||
#include "cktdefs.h" |
|||
#include "numddefs.h" |
|||
#include "numenum.h" |
|||
#include "trandefs.h" |
|||
#include "complex.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
|
|||
/* Forward declarations */ |
|||
int NUMDinitSmSig(NUMDinstance *); |
|||
|
|||
/* External Declarations */ |
|||
extern int ONEdcDebug; |
|||
extern int ONEtranDebug; |
|||
extern int ONEacDebug; |
|||
|
|||
|
|||
int |
|||
NUMDload(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
register NUMDmodel *model = (NUMDmodel *) inModel; |
|||
register NUMDinstance *inst; |
|||
register ONEdevice *pDevice; |
|||
double startTime, startTime2, totalTime, totalTime2; |
|||
double tol; /* temporary for tolerance calculations */ |
|||
double id; |
|||
double ideq; |
|||
double idhat = 0.0; |
|||
double delVd; |
|||
double vd; /* current diode voltage */ |
|||
double gd; |
|||
double xfact; |
|||
int check; |
|||
int i; |
|||
double deltaNorm[7]; |
|||
int devConverged = FALSE; |
|||
int numDevNonCon; |
|||
int deviceType; |
|||
int doInitSolve; |
|||
int doVoltPred; |
|||
char *initStateName; |
|||
|
|||
/* loop through all the diode models */ |
|||
for (; model != NULL; model = model->NUMDnextModel) { |
|||
/* Do model things */ |
|||
FieldDepMobility = model->NUMDmodels->MODLfieldDepMobility; |
|||
Srh = model->NUMDmodels->MODLsrh; |
|||
Auger = model->NUMDmodels->MODLauger; |
|||
AvalancheGen = model->NUMDmodels->MODLavalancheGen; |
|||
MobDeriv = model->NUMDmethods->METHmobDeriv; |
|||
MaxIterations = model->NUMDmethods->METHitLim; |
|||
ONEdcDebug = model->NUMDoutputs->OUTPdcDebug; |
|||
ONEtranDebug = model->NUMDoutputs->OUTPtranDebug; |
|||
ONEacDebug = model->NUMDoutputs->OUTPacDebug; |
|||
deviceType = model->NUMDoptions->OPTNdeviceType; |
|||
doVoltPred = model->NUMDmethods->METHvoltPred; |
|||
|
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
/* compute normalized deltas and predictor coeff */ |
|||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) { |
|||
model->NUMDpInfo->order = ckt->CKTorder; |
|||
model->NUMDpInfo->method = ckt->CKTintegrateMethod; |
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NUMDpInfo->intCoeff, deltaNorm); |
|||
computePredCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NUMDpInfo->predCoeff, deltaNorm); |
|||
} |
|||
} else if (ckt->CKTmode & MODEINITTRAN) { |
|||
model->NUMDpInfo->order = ckt->CKTorder; |
|||
model->NUMDpInfo->method = ckt->CKTintegrateMethod; |
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NUMDpInfo->intCoeff, deltaNorm); |
|||
} |
|||
/* Now do instance things */ |
|||
for (inst = model->NUMDinstances; inst != NULL; |
|||
inst = inst->NUMDnextInstance) { |
|||
if (inst->NUMDowner != ARCHme) continue; |
|||
|
|||
pDevice = inst->NUMDpDevice; |
|||
|
|||
totalTime = 0.0; |
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NUMDglobals)); |
|||
|
|||
/* |
|||
* this routine loads diodes for dc and transient analyses. |
|||
*/ |
|||
pDevice->devStates = ckt->CKTstates; |
|||
/* |
|||
* initialization |
|||
*/ |
|||
check = 1; |
|||
doInitSolve = FALSE; |
|||
initStateName = NULL; |
|||
if (ckt->CKTmode & MODEINITSMSIG) { |
|||
vd = *(ckt->CKTstate0 + inst->NUMDvoltage); |
|||
delVd = 0.0; |
|||
NUMDsetBCs(pDevice, vd); |
|||
} else if (ckt->CKTmode & MODEINITTRAN) { |
|||
*(ckt->CKTstate0 + inst->NUMDvoltage) = |
|||
*(ckt->CKTstate1 + inst->NUMDvoltage); |
|||
vd = *(ckt->CKTstate1 + inst->NUMDvoltage); |
|||
ONEsaveState(pDevice); |
|||
delVd = 0.0; |
|||
} else if ((ckt->CKTmode & MODEINITJCT) && |
|||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) { |
|||
doInitSolve = TRUE; |
|||
initStateName = inst->NUMDicFile; |
|||
vd = 0.0; |
|||
delVd = vd; |
|||
} else if ((ckt->CKTmode & MODEINITJCT) && inst->NUMDoff) { |
|||
doInitSolve = TRUE; |
|||
vd = 0.0; |
|||
delVd = vd; |
|||
} else if (ckt->CKTmode & MODEINITJCT) { |
|||
doInitSolve = TRUE; |
|||
initStateName = inst->NUMDicFile; |
|||
if (deviceType == OPTN_DIODE) { |
|||
vd = inst->NUMDtype * 0.5; |
|||
} else if (deviceType == OPTN_MOSCAP) { |
|||
vd = inst->NUMDtype * 0.8; |
|||
} else { |
|||
vd = 0.0; |
|||
} |
|||
delVd = vd; |
|||
} else if (ckt->CKTmode & MODEINITFIX && inst->NUMDoff) { |
|||
vd = 0.0; |
|||
delVd = vd; |
|||
} else { |
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
*(ckt->CKTstate0 + inst->NUMDvoltage) = |
|||
*(ckt->CKTstate1 + inst->NUMDvoltage); |
|||
*(ckt->CKTstate0 + inst->NUMDid) = |
|||
*(ckt->CKTstate1 + inst->NUMDid); |
|||
*(ckt->CKTstate0 + inst->NUMDconduct) = |
|||
*(ckt->CKTstate1 + inst->NUMDconduct); |
|||
/* compute the normalized deltas */ |
|||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) { |
|||
/* no linear prediction on device voltages */ |
|||
vd = *(ckt->CKTstate1 + inst->NUMDvoltage); |
|||
ONEpredict(pDevice, model->NUMDpInfo); |
|||
} else { |
|||
if (doVoltPred) { |
|||
/* linear prediction */ |
|||
xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1]; |
|||
vd = (1+xfact) * (*(ckt->CKTstate1 + inst->NUMDvoltage)) |
|||
- (xfact) * (*(ckt->CKTstate2 + inst->NUMDvoltage)); |
|||
} else { |
|||
vd = *(ckt->CKTstate1 + inst->NUMDvoltage); |
|||
} |
|||
} |
|||
} else { |
|||
vd = *(ckt->CKTrhsOld + inst->NUMDposNode) - |
|||
*(ckt->CKTrhsOld + inst->NUMDnegNode); |
|||
} |
|||
delVd = vd - *(ckt->CKTstate0 + inst->NUMDvoltage); |
|||
idhat = *(ckt->CKTstate0 + inst->NUMDid) + |
|||
*(ckt->CKTstate0 + inst->NUMDconduct) * delVd; |
|||
/* |
|||
* bypass if solution has not changed |
|||
*/ |
|||
if ((ckt->CKTbypass) && pDevice->converged && |
|||
!(ckt->CKTmode & MODEINITPRED)) { |
|||
tol = ckt->CKTvoltTol + ckt->CKTreltol * |
|||
MAX(fabs(vd), fabs(*(ckt->CKTstate0 + inst->NUMDvoltage))); |
|||
if (fabs(delVd) < tol) { |
|||
tol = ckt->CKTreltol * |
|||
MAX(fabs(idhat), fabs(*(ckt->CKTstate0 + inst->NUMDid))) + |
|||
ckt->CKTabstol; |
|||
if (fabs(idhat - *(ckt->CKTstate0 + inst->NUMDid)) |
|||
< tol) { |
|||
vd = *(ckt->CKTstate0 + inst->NUMDvoltage); |
|||
id = *(ckt->CKTstate0 + inst->NUMDid); |
|||
gd = *(ckt->CKTstate0 + inst->NUMDconduct); |
|||
goto load; |
|||
} |
|||
} |
|||
} |
|||
/* |
|||
* limit new junction voltage |
|||
*/ |
|||
if (deviceType == OPTN_DIODE) { |
|||
vd = inst->NUMDtype * limitJunctionVoltage(inst->NUMDtype * vd, |
|||
inst->NUMDtype * *(ckt->CKTstate0 + inst->NUMDvoltage), &check); |
|||
} else if (deviceType == OPTN_MOSCAP) { |
|||
vd = inst->NUMDtype * limitVgb(inst->NUMDtype * vd, |
|||
inst->NUMDtype * *(ckt->CKTstate0 + inst->NUMDvoltage), &check); |
|||
} else { |
|||
vd = inst->NUMDtype * limitResistorVoltage(inst->NUMDtype * vd, |
|||
inst->NUMDtype * *(ckt->CKTstate0 + inst->NUMDvoltage), &check); |
|||
} |
|||
delVd = vd - *(ckt->CKTstate0 + inst->NUMDvoltage); |
|||
} |
|||
if (doInitSolve) { |
|||
if (ONEdcDebug) { |
|||
printVoltages(stdout, model->NUMDmodName, inst->NUMDname, |
|||
deviceType, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); |
|||
} |
|||
startTime2 = SPfrontEnd->IFseconds(); |
|||
ONEequilSolve(pDevice); |
|||
totalTime2 = SPfrontEnd->IFseconds() - startTime2; |
|||
pDevice->pStats->totalTime[STAT_SETUP] += totalTime2; |
|||
pDevice->pStats->totalTime[STAT_DC] -= totalTime2; |
|||
|
|||
ONEbiasSolve(pDevice, MaxIterations, FALSE, NULL); |
|||
|
|||
*(ckt->CKTstate0 + inst->NUMDvoltage) = 0.0; |
|||
|
|||
if (initStateName != NULL) { |
|||
if (ONEreadState(pDevice, initStateName, 1, &vd, NULL ) < 0) { |
|||
fprintf(stderr, |
|||
"NUMDload: trouble reading state-file %s\n", initStateName); |
|||
} else { |
|||
NUMDsetBCs(pDevice, vd); |
|||
delVd = 0.0; |
|||
} |
|||
} |
|||
} |
|||
/* |
|||
* compute dc current and derivatives |
|||
*/ |
|||
/* use the routines for numerical simulation */ |
|||
|
|||
if (ckt->CKTmode & (MODEDCOP | MODETRANOP | MODEDCTRANCURVE | MODEINITSMSIG)) { |
|||
numDevNonCon = 0; |
|||
inst->NUMDc11 = inst->NUMDy11r = inst->NUMDy11i = 0.0; |
|||
inst->NUMDsmSigAvail = FALSE; |
|||
devNonCon: |
|||
NUMDproject(pDevice, delVd); |
|||
if (ONEdcDebug) { |
|||
printVoltages(stdout, model->NUMDmodName, inst->NUMDname, |
|||
deviceType, 1, vd, delVd, 0.0, 0.0, 0.0, 0.0); |
|||
} |
|||
ONEbiasSolve(pDevice, MaxIterations, FALSE, NULL); |
|||
devConverged = pDevice->converged; |
|||
if (devConverged && finite(pDevice->rhsNorm)) { |
|||
/* Get the current and conductance information. */ |
|||
NUMDcurrent(pDevice, FALSE, (double *) NULL, &id); |
|||
NUMDconductance(pDevice, FALSE, (double *) NULL, &gd); |
|||
} else { |
|||
/* reduce the voltage step until converged */ |
|||
/* restore the boundary potential to previous value */ |
|||
NUMDsetBCs(pDevice, vd - delVd); |
|||
ONEstoreInitialGuess(pDevice); |
|||
ONEresetJacobian(pDevice); |
|||
delVd *= 0.5; |
|||
vd = delVd + *(ckt->CKTstate0 + inst->NUMDvoltage); |
|||
numDevNonCon++; |
|||
check = 1; |
|||
if (numDevNonCon > 10) { |
|||
printVoltages(stderr, model->NUMDmodName, inst->NUMDname, |
|||
deviceType, 1, vd, delVd, 0.0, 0.0, 0.0, 0.0); |
|||
fprintf(stderr, "*** Non-convergence during load ***\n"); |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
return (E_BADMATRIX); |
|||
} else { |
|||
goto devNonCon; |
|||
} |
|||
} |
|||
} |
|||
if ((ckt->CKTmode & (MODETRAN | MODEAC | MODEINITSMSIG)) || |
|||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) { |
|||
/* |
|||
* store small-signal parameters |
|||
*/ |
|||
if ((!(ckt->CKTmode & MODETRANOP)) || (!(ckt->CKTmode & MODEUIC))) { |
|||
if (ckt->CKTmode & MODEINITSMSIG) { |
|||
totalTime = SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
startTime2 = SPfrontEnd->IFseconds(); |
|||
NUMDinitSmSig(inst); |
|||
pDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime2; |
|||
continue; |
|||
} else { |
|||
inst->NUMDsmSigAvail = FALSE; |
|||
} |
|||
/* |
|||
* transient analysis |
|||
*/ |
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
NUMDsetBCs(pDevice, vd); |
|||
ONEstoreInitialGuess(pDevice); |
|||
} else { |
|||
NUMDupdate(pDevice, delVd, TRUE); |
|||
} |
|||
if (ONEtranDebug) { |
|||
printVoltages(stdout, model->NUMDmodName, inst->NUMDname, |
|||
deviceType, 1, vd, delVd, 0.0, 0.0, 0.0, 0.0); |
|||
} |
|||
|
|||
ONEbiasSolve(pDevice, 0, TRUE, model->NUMDpInfo); |
|||
|
|||
if (!finite(pDevice->rhsNorm)) { |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
return (E_BADMATRIX); |
|||
} |
|||
|
|||
pDevice->converged = devConverged = ONEdeviceConverged(pDevice); |
|||
|
|||
/* extract the current and conductance information */ |
|||
NUMDcurrent(pDevice, TRUE, model->NUMDpInfo->intCoeff, &id); |
|||
NUMDconductance(pDevice, TRUE, model->NUMDpInfo->intCoeff, &gd); |
|||
} |
|||
} |
|||
/* |
|||
* check convergence |
|||
*/ |
|||
if ((!(ckt->CKTmode & MODEINITFIX)) || (!(inst->NUMDoff))) { |
|||
if (check == 1 || !devConverged) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} else { |
|||
tol = ckt->CKTreltol * MAX(fabs(idhat), fabs(id)) + ckt->CKTabstol; |
|||
if (fabs(idhat - id) > tol) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} |
|||
} |
|||
} |
|||
*(ckt->CKTstate0 + inst->NUMDvoltage) = vd; |
|||
*(ckt->CKTstate0 + inst->NUMDid) = id; |
|||
*(ckt->CKTstate0 + inst->NUMDconduct) = gd; |
|||
|
|||
load: |
|||
|
|||
/* |
|||
* load current vector |
|||
*/ |
|||
|
|||
ideq = id - gd * vd; |
|||
*(ckt->CKTrhs + inst->NUMDnegNode) += ideq; |
|||
*(ckt->CKTrhs + inst->NUMDposNode) -= ideq; |
|||
|
|||
/* |
|||
* load matrix |
|||
*/ |
|||
*(inst->NUMDposPosPtr) += gd; |
|||
*(inst->NUMDnegNegPtr) += gd; |
|||
*(inst->NUMDnegPosPtr) -= gd; |
|||
*(inst->NUMDposNegPtr) -= gd; |
|||
|
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
if (ckt->CKTmode & MODETRAN) { |
|||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime; |
|||
} else { |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
} |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
|
|||
int |
|||
NUMDinitSmSig(inst) |
|||
NUMDinstance *inst; |
|||
{ |
|||
SPcomplex yd; |
|||
double omega = inst->NUMDmodPtr->NUMDmethods->METHomega; |
|||
|
|||
AcAnalysisMethod = SOR_ONLY; |
|||
(void) NUMDadmittance(inst->NUMDpDevice, omega, &yd); |
|||
inst->NUMDc11 = yd.imag / omega; |
|||
inst->NUMDy11r = yd.real; |
|||
inst->NUMDy11i = yd.imag; |
|||
inst->NUMDsmSigAvail = TRUE; |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "numddefs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NUMDmDelete(inModel, modname, kill) |
|||
GENmodel **inModel; |
|||
IFuid modname; |
|||
GENmodel *kill; |
|||
{ |
|||
|
|||
NUMDmodel **model = (NUMDmodel **) inModel; |
|||
NUMDmodel *modfast = (NUMDmodel *) kill; |
|||
NUMDinstance *inst; |
|||
NUMDinstance *prev = NULL; |
|||
NUMDmodel **oldmod; |
|||
oldmod = model; |
|||
for (; *model; model = &((*model)->NUMDnextModel)) { |
|||
if ((*model)->NUMDmodName == modname || |
|||
(modfast && *model == modfast)) |
|||
goto delgot; |
|||
oldmod = model; |
|||
} |
|||
return (E_NOMOD); |
|||
|
|||
delgot: |
|||
*oldmod = (*model)->NUMDnextModel; /* cut deleted device out of list */ |
|||
for (inst = (*model)->NUMDinstances; inst; inst = inst->NUMDnextInstance) { |
|||
if (prev) |
|||
FREE(prev); |
|||
prev = inst; |
|||
} |
|||
if (prev) |
|||
FREE(prev); |
|||
FREE(*model); |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine sets model parameters for NUMDs in the circuit. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "numddefs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NUMDmParam(param, value, inModel) |
|||
int param; |
|||
IFvalue *value; |
|||
GENmodel *inModel; |
|||
{ |
|||
switch (param) { |
|||
case NUMD_MOD_NUMD: |
|||
/* no action - already know it is a 1d-numerical diode, but this */ |
|||
/* makes life easier for spice-2 like parsers */ |
|||
break; |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "ifsim.h" |
|||
#include "const.h" |
|||
#include "numddefs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NUMDparam(param, value, inInst, select) |
|||
int param; |
|||
IFvalue *value; |
|||
GENinstance *inInst; |
|||
IFvalue *select; |
|||
{ |
|||
NUMDinstance *inst = (NUMDinstance *) inInst; |
|||
switch (param) { |
|||
case NUMD_AREA: |
|||
inst->NUMDarea = value->rValue; |
|||
inst->NUMDareaGiven = TRUE; |
|||
break; |
|||
case NUMD_OFF: |
|||
inst->NUMDoff = TRUE; |
|||
break; |
|||
case NUMD_IC_FILE: |
|||
inst->NUMDicFile = value->sValue; |
|||
inst->NUMDicFileGiven = TRUE; |
|||
break; |
|||
case NUMD_PRINT: |
|||
inst->NUMDprint = value->rValue; |
|||
inst->NUMDprintGiven = TRUE; |
|||
break; |
|||
case NUMD_TEMP: |
|||
inst->NUMDtemp = value->rValue + CONSTCtoK; |
|||
inst->NUMDtempGiven = TRUE; |
|||
break; |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "complex.h" |
|||
#include "sperror.h" |
|||
#include "numddefs.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
/* External Declarations */ |
|||
extern int ONEacDebug; |
|||
|
|||
int |
|||
NUMDpzLoad(inModel, ckt, s) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
SPcomplex *s; |
|||
{ |
|||
register NUMDmodel *model = (NUMDmodel *) inModel; |
|||
register NUMDinstance *inst; |
|||
SPcomplex y; |
|||
double startTime; |
|||
|
|||
/* loop through all the diode models */ |
|||
for (; model != NULL; model = model->NUMDnextModel) { |
|||
FieldDepMobility = model->NUMDmodels->MODLfieldDepMobility; |
|||
Srh = model->NUMDmodels->MODLsrh; |
|||
Auger = model->NUMDmodels->MODLauger; |
|||
AvalancheGen = model->NUMDmodels->MODLavalancheGen; |
|||
AcAnalysisMethod = model->NUMDmethods->METHacAnalysisMethod; |
|||
MobDeriv = model->NUMDmethods->METHmobDeriv; |
|||
ONEacDebug = model->NUMDoutputs->OUTPacDebug; |
|||
|
|||
for (inst = model->NUMDinstances; inst != NULL; |
|||
inst = inst->NUMDnextInstance) { |
|||
if (inst->NUMDowner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NUMDglobals)); |
|||
|
|||
NUMDys(inst->NUMDpDevice, s, &y); |
|||
|
|||
*(inst->NUMDposPosPtr) += y.real; |
|||
*(inst->NUMDposPosPtr + 1) += y.imag; |
|||
*(inst->NUMDnegNegPtr) += y.real; |
|||
*(inst->NUMDnegNegPtr + 1) += y.imag; |
|||
*(inst->NUMDnegPosPtr) -= y.real; |
|||
*(inst->NUMDnegPosPtr + 1) -= y.imag; |
|||
*(inst->NUMDposNegPtr) -= y.real; |
|||
*(inst->NUMDposNegPtr + 1) -= y.imag; |
|||
|
|||
inst->NUMDpDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,235 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "smpdefs.h" |
|||
#include "numddefs.h" |
|||
#include "numconst.h" |
|||
#include "numenum.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "ciderinp.h" |
|||
#include "suffix.h" |
|||
|
|||
#define NIL(type) ((type *)0) |
|||
#define TSCALLOC(var, size, type)\ |
|||
if (size && (!(var =(type *)calloc(1, (unsigned)(size)*sizeof(type))))) {\ |
|||
return(E_NOMEM);\ |
|||
} |
|||
|
|||
|
|||
int |
|||
NUMDsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) |
|||
/* |
|||
* load the structure with those pointers needed later for fast matrix |
|||
* loading |
|||
*/ |
|||
{ |
|||
register NUMDmodel *model = (NUMDmodel *) inModel; |
|||
register NUMDinstance *inst; |
|||
METHcard *methods; |
|||
MODLcard *models; |
|||
OPTNcard *options; |
|||
OUTPcard *outputs; |
|||
char *icFileName = NULL; |
|||
int nameLen; |
|||
int error; |
|||
int xMeshSize; |
|||
ONEdevice *pDevice; |
|||
ONEcoord *xCoordList = NIL(ONEcoord); |
|||
ONEdomain *domainList = NIL(ONEdomain); |
|||
ONEmaterial *pM, *pMaterial = NIL(ONEmaterial), *materialList = NIL(ONEmaterial); |
|||
DOPprofile *profileList = NIL(DOPprofile); |
|||
DOPtable *dopTableList = NIL(DOPtable); |
|||
double startTime; |
|||
|
|||
|
|||
/* loop through all the models */ |
|||
for (; model != NULL; model = model->NUMDnextModel) { |
|||
if (!model->NUMDpInfo) { |
|||
TSCALLOC(model->NUMDpInfo, 1, ONEtranInfo); |
|||
} |
|||
methods = model->NUMDmethods; |
|||
if (!methods) { |
|||
TSCALLOC(methods, 1, METHcard); |
|||
model->NUMDmethods = methods; |
|||
} |
|||
models = model->NUMDmodels; |
|||
if (!models) { |
|||
TSCALLOC(models, 1, MODLcard); |
|||
model->NUMDmodels = models; |
|||
} |
|||
options = model->NUMDoptions; |
|||
if (!options) { |
|||
TSCALLOC(options, 1, OPTNcard); |
|||
model->NUMDoptions = options; |
|||
} |
|||
outputs = model->NUMDoutputs; |
|||
if (!outputs) { |
|||
TSCALLOC(outputs, 1, OUTPcard); |
|||
model->NUMDoutputs = outputs; |
|||
} |
|||
if (!methods->METHvoltPredGiven) { |
|||
methods->METHvoltPred = FALSE; |
|||
} |
|||
if (!methods->METHmobDerivGiven) { |
|||
methods->METHmobDeriv = TRUE; |
|||
} |
|||
if (!methods->METHoneCarrierGiven) { |
|||
methods->METHoneCarrier = FALSE; |
|||
} |
|||
if (!methods->METHacAnalysisMethodGiven) { |
|||
methods->METHacAnalysisMethod = SOR; |
|||
} |
|||
if (!methods->METHdabstolGiven) { |
|||
methods->METHdabstol = DABSTOL1D; |
|||
} |
|||
if (!methods->METHdreltolGiven) { |
|||
methods->METHdreltol = ckt->CKTreltol; |
|||
} |
|||
if (!methods->METHitLimGiven) { |
|||
methods->METHitLim = 20; |
|||
} |
|||
if (!methods->METHomegaGiven || methods->METHomega <= 0.0) { |
|||
methods->METHomega = 2.0 * M_PI /* radians/sec */ ; |
|||
} |
|||
if (!options->OPTNdefaGiven || options->OPTNdefa <= 0.0) { |
|||
options->OPTNdefa = 1.0e4 /* cm^2 */ ; |
|||
} |
|||
if (!options->OPTNdeviceTypeGiven) { |
|||
options->OPTNdeviceType = OPTN_DIODE; |
|||
} |
|||
if (!options->OPTNicFileGiven) { |
|||
options->OPTNicFile = NULL; |
|||
options->OPTNunique = FALSE; /* Can't form a unique name. */ |
|||
} |
|||
if (!options->OPTNuniqueGiven) { |
|||
options->OPTNunique = FALSE; |
|||
} |
|||
|
|||
/* Set up the rest of the card lists */ |
|||
if ((error = MODLsetup(model->NUMDmodels))) |
|||
return (error); |
|||
BandGapNarrowing = models->MODLbandGapNarrowing; |
|||
ConcDepLifetime = models->MODLconcDepLifetime; |
|||
TempDepMobility = models->MODLtempDepMobility; |
|||
ConcDepMobility = models->MODLconcDepMobility; |
|||
|
|||
if ((error = OUTPsetup(model->NUMDoutputs))) |
|||
return (error); |
|||
if ((error = MATLsetup(model->NUMDmaterials, &materialList))) |
|||
return (error); |
|||
if ((error = MOBsetup(model->NUMDmobility, materialList))) |
|||
return (error); |
|||
if ((error = MESHsetup('x', model->NUMDxMeshes, &xCoordList, &xMeshSize))) |
|||
return (error); |
|||
if ((error = DOMNsetup(model->NUMDdomains, &domainList, |
|||
xCoordList, NIL(ONEcoord), materialList))) |
|||
return (error); |
|||
if ((error = BDRYsetup(model->NUMDboundaries, |
|||
xCoordList, NIL(ONEcoord), domainList))) |
|||
return (error); |
|||
if ((error = CONTsetup(model->NUMDcontacts, NULL))) |
|||
return (error); |
|||
if ((error = DOPsetup(model->NUMDdopings, &profileList, |
|||
&dopTableList, xCoordList, NIL(ONEcoord)))) |
|||
return (error); |
|||
model->NUMDmatlInfo = materialList; |
|||
model->NUMDprofiles = profileList; |
|||
model->NUMDdopTables = dopTableList; |
|||
|
|||
/* loop through all the instances of the model */ |
|||
for (inst = model->NUMDinstances; inst != NULL; |
|||
inst = inst->NUMDnextInstance) { |
|||
if ((inst->NUMDowner != ARCHme)) goto matrixpointers; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
if ((!inst->NUMDprintGiven)) { |
|||
inst->NUMDprint = 0; |
|||
} else if (inst->NUMDprint <= 0) { |
|||
inst->NUMDprint = 1; |
|||
} |
|||
if ((!inst->NUMDicFileGiven)) { |
|||
if (options->OPTNunique) { |
|||
nameLen = strlen(options->OPTNicFile) + strlen(inst->NUMDname) + 1; |
|||
TSCALLOC(icFileName, nameLen+1, char); |
|||
sprintf(icFileName, "%s.%s", options->OPTNicFile, inst->NUMDname); |
|||
icFileName[nameLen] = '\0'; |
|||
inst->NUMDicFile = icFileName; |
|||
} else if (options->OPTNicFile != NULL) { |
|||
nameLen = strlen(options->OPTNicFile); |
|||
TSCALLOC(icFileName, nameLen+1, char); |
|||
icFileName = strcpy(icFileName, options->OPTNicFile); |
|||
inst->NUMDicFile = icFileName; |
|||
} else { |
|||
inst->NUMDicFile = NULL; |
|||
} |
|||
} |
|||
inst->NUMDstate = *states; |
|||
*states += NUMDnumStates; |
|||
|
|||
if (!inst->NUMDpDevice) { |
|||
/* Assign the mesh info to each instance. */ |
|||
TSCALLOC(pDevice, 1, ONEdevice); |
|||
TSCALLOC(pDevice->pStats, 1, ONEstats); |
|||
pDevice->name = inst->NUMDname; |
|||
pDevice->solverType = SLV_NONE; |
|||
pDevice->numNodes = xMeshSize; |
|||
pDevice->abstol = methods->METHdabstol; |
|||
pDevice->reltol = methods->METHdreltol; |
|||
pDevice->rhsImag = NIL(double); |
|||
TSCALLOC(pDevice->elemArray, pDevice->numNodes, ONEelem *); |
|||
|
|||
/* Create a copy of material data that can change with temperature. */ |
|||
pDevice->pMaterials = NIL(ONEmaterial); |
|||
for (pM = materialList; pM != NIL(ONEmaterial); pM = pM->next) { |
|||
if (pDevice->pMaterials == NIL(ONEmaterial)) { |
|||
TSCALLOC(pMaterial, 1, ONEmaterial); |
|||
pDevice->pMaterials = pMaterial; |
|||
} else { |
|||
TSCALLOC(pMaterial->next, 1, ONEmaterial); |
|||
pMaterial = pMaterial->next; |
|||
} |
|||
/* Copy everything, then fix the incorrect pointer. */ |
|||
bcopy((void *) pM, (void *) pMaterial, sizeof(ONEmaterial)); |
|||
pMaterial->next = NIL(ONEmaterial); |
|||
} |
|||
|
|||
/* generate the mesh structure for the device */ |
|||
ONEbuildMesh(pDevice, xCoordList, domainList, pDevice->pMaterials); |
|||
|
|||
/* store the device info in the instance */ |
|||
inst->NUMDpDevice = pDevice; |
|||
} |
|||
/* Now update the state pointers. */ |
|||
ONEgetStatePointers(inst->NUMDpDevice, states); |
|||
|
|||
/* Wipe out statistics from previous runs (if any). */ |
|||
bzero((void *) inst->NUMDpDevice->pStats, sizeof(ONEstats)); |
|||
|
|||
inst->NUMDpDevice->pStats->totalTime[STAT_SETUP] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
|
|||
/* macro to make elements with built in test for out of memory */ |
|||
#define TSTALLOC(ptr,first,second) \ |
|||
if ((inst->ptr = SMPmakeElt(matrix,inst->first,inst->second))==(double *)NULL){\ |
|||
return(E_NOMEM);\ |
|||
} |
|||
|
|||
matrixpointers: |
|||
TSTALLOC(NUMDposPosPtr, NUMDposNode, NUMDposNode) |
|||
TSTALLOC(NUMDnegNegPtr, NUMDnegNode, NUMDnegNode) |
|||
TSTALLOC(NUMDnegPosPtr, NUMDnegNode, NUMDposNode) |
|||
TSTALLOC(NUMDposNegPtr, NUMDposNode, NUMDnegNode) |
|||
} |
|||
/* Clean up lists */ |
|||
killCoordInfo(xCoordList); |
|||
killDomainInfo(domainList); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,133 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
Author: 1992 David A. Gates, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "numddefs.h" |
|||
#include "numenum.h" |
|||
#include "carddefs.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
#define NIL(type) ((type *)0) |
|||
|
|||
int |
|||
NUMDtemp(inModel, ckt) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
/* |
|||
* perform the temperature update to the diode |
|||
*/ |
|||
{ |
|||
register NUMDmodel *model = (NUMDmodel *) inModel; |
|||
register NUMDinstance *inst; |
|||
METHcard *methods; |
|||
MODLcard *models; |
|||
OPTNcard *options; |
|||
OUTPcard *outputs; |
|||
ONEmaterial *pM, *pMaterial, *pNextMaterial; |
|||
double startTime; |
|||
|
|||
|
|||
/* loop through all the diode models */ |
|||
for (; model != NULL; model = model->NUMDnextModel) { |
|||
methods = model->NUMDmethods; |
|||
models = model->NUMDmodels; |
|||
options = model->NUMDoptions; |
|||
outputs = model->NUMDoutputs; |
|||
|
|||
if (!options->OPTNtnomGiven) { |
|||
options->OPTNtnom = ckt->CKTnomTemp; |
|||
} |
|||
for (pM = model->NUMDmatlInfo; pM != NIL(ONEmaterial); pM = pM->next) { |
|||
pM->tnom = options->OPTNtnom; |
|||
} |
|||
|
|||
BandGapNarrowing = models->MODLbandGapNarrowing; |
|||
ConcDepLifetime = models->MODLconcDepLifetime; |
|||
TempDepMobility = models->MODLtempDepMobility; |
|||
ConcDepMobility = models->MODLconcDepMobility; |
|||
|
|||
for (inst = model->NUMDinstances; inst != NULL; |
|||
inst = inst->NUMDnextInstance) { |
|||
if (inst->NUMDowner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
if (!inst->NUMDtempGiven) { |
|||
inst->NUMDtemp = ckt->CKTtemp; |
|||
} |
|||
if (!inst->NUMDareaGiven || inst->NUMDarea <= 0.0) { |
|||
inst->NUMDarea = 1.0; |
|||
} |
|||
inst->NUMDpDevice->area = inst->NUMDarea * options->OPTNdefa; |
|||
|
|||
/* Compute and save globals for this instance. */ |
|||
GLOBcomputeGlobals(&(inst->NUMDglobals), inst->NUMDtemp); |
|||
if (outputs->OUTPglobals) { |
|||
GLOBprnGlobals(stdout, &(inst->NUMDglobals)); |
|||
} |
|||
/* Calculate new sets of material parameters. */ |
|||
pM = model->NUMDmatlInfo; |
|||
pMaterial = inst->NUMDpDevice->pMaterials; |
|||
for (; pM != NULL; pM = pM->next, pMaterial = pMaterial->next) { |
|||
|
|||
/* Copy the original values, then fix the incorrect pointer. */ |
|||
pNextMaterial = pMaterial->next; |
|||
bcopy((char *) pM, (char *) pMaterial, sizeof(ONEmaterial)); |
|||
pMaterial->next = pNextMaterial; |
|||
|
|||
/* Now do the temperature dependence. */ |
|||
MATLtempDep(pMaterial, pMaterial->tnom); |
|||
if (outputs->OUTPmaterial) { |
|||
printMaterialInfo(pMaterial); |
|||
} |
|||
} |
|||
|
|||
/* Assign doping to the mesh. */ |
|||
ONEsetDoping(inst->NUMDpDevice, model->NUMDprofiles, |
|||
model->NUMDdopTables); |
|||
|
|||
/* Assign other physical parameters to the mesh. */ |
|||
ONEsetup(inst->NUMDpDevice); |
|||
|
|||
/* Assign boundary condition parameters. */ |
|||
ONEsetBCparams(inst->NUMDpDevice, model->NUMDboundaries, |
|||
model->NUMDcontacts); |
|||
|
|||
/* Normalize everything. */ |
|||
ONEnormalize(inst->NUMDpDevice); |
|||
|
|||
/* Find the device's polarity type. */ |
|||
switch (options->OPTNdeviceType) { |
|||
case OPTN_DIODE: |
|||
if (inst->NUMDpDevice->elemArray[1] |
|||
->pNodes[0]->netConc < 0.0) { |
|||
inst->NUMDtype = PN; |
|||
} else { |
|||
inst->NUMDtype = NP; |
|||
} |
|||
break; |
|||
case OPTN_MOSCAP: |
|||
if (inst->NUMDpDevice->elemArray[inst->NUMDpDevice->numNodes - 1] |
|||
->pNodes[1]->netConc < 0.0) { |
|||
inst->NUMDtype = PN; |
|||
} else { |
|||
inst->NUMDtype = NP; |
|||
} |
|||
break; |
|||
default: |
|||
inst->NUMDtype = PN; |
|||
break; |
|||
} |
|||
inst->NUMDpDevice->pStats->totalTime[STAT_SETUP] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "numddefs.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/oned/onedext.h" |
|||
#include "suffix.h" |
|||
#include "cidersupt.h" |
|||
|
|||
|
|||
|
|||
int |
|||
NUMDtrunc(inModel, ckt, timeStep) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
double *timeStep; |
|||
|
|||
{ |
|||
register NUMDmodel *model = (NUMDmodel *) inModel; |
|||
register NUMDinstance *inst; |
|||
double deltaNew; |
|||
double deltaNorm[7]; |
|||
double startTime; |
|||
int i; |
|||
|
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
for (; model != NULL; model = model->NUMDnextModel) { |
|||
model->NUMDpInfo->order = ckt->CKTorder; |
|||
model->NUMDpInfo->delta = deltaNorm; |
|||
model->NUMDpInfo->lteCoeff = computeLTECoeff(model->NUMDpInfo); |
|||
for (inst = model->NUMDinstances; inst != NULL; |
|||
inst = inst->NUMDnextInstance) { |
|||
if (inst->NUMDowner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
deltaNew = ONEtrunc(inst->NUMDpDevice, model->NUMDpInfo, ckt->CKTdelta); |
|||
*timeStep = MIN(*timeStep, deltaNew); |
|||
inst->NUMDpDevice->pStats->totalTime[STAT_TRAN] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
## Process this file with automake to produce Makefile.in
|
|||
|
|||
noinst_LIBRARIES = libnumd2.a |
|||
|
|||
libnumd2_a_SOURCES = \
|
|||
nud2.c \
|
|||
nud2acld.c \
|
|||
nud2ask.c \
|
|||
numd2defs.h \
|
|||
nud2del.c \
|
|||
nud2dest.c \
|
|||
nud2dump.c \
|
|||
numd2ext.h \
|
|||
numd2init.c \
|
|||
numd2init.h \
|
|||
numd2itf.h \
|
|||
nud2load.c \
|
|||
nud2mdel.c \
|
|||
nud2mpar.c \
|
|||
nud2parm.c \
|
|||
nud2pzld.c \
|
|||
nud2set.c \
|
|||
nud2temp.c \
|
|||
nud2trun.c |
|||
|
|||
|
|||
|
|||
INCLUDES = -I$(top_srcdir)/src/include |
|||
|
|||
MAINTAINERCLEANFILES = Makefile.in |
|||
@ -0,0 +1,59 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "devdefs.h" |
|||
#include "numd2def.h" |
|||
#include "suffix.h" |
|||
|
|||
/* |
|||
* This file defines the 2d Numerical Diode data structures that are |
|||
* available to the next level(s) up the calling hierarchy |
|||
*/ |
|||
|
|||
IFparm NUMD2pTable[] = { /* parameters */ |
|||
IP("off", NUMD2_OFF, IF_FLAG, "Initially off"), |
|||
IP("ic.file", NUMD2_IC_FILE, IF_STRING, "Initial condition file"), |
|||
IOP("w", NUMD2_WIDTH, IF_REAL, "Width factor"), |
|||
IOP("area", NUMD2_AREA, IF_REAL, "Area factor"), |
|||
IP("save", NUMD2_PRINT, IF_REAL, "Save solutions"), |
|||
IP("print", NUMD2_PRINT, IF_REAL, "Print solutions"), |
|||
OP("vd", NUMD2_VD, IF_REAL, "Voltage"), |
|||
OP("id", NUMD2_ID, IF_REAL, "Current"), |
|||
OP("g11", NUMD2_G11, IF_REAL, "Conductance"), |
|||
OP("c11", NUMD2_C11, IF_REAL, "Capacitance"), |
|||
OP("y11", NUMD2_Y11, IF_COMPLEX, "Admittance"), |
|||
OPU("g12", NUMD2_G12, IF_REAL, "Conductance"), |
|||
OPU("c12", NUMD2_C12, IF_REAL, "Capacitance"), |
|||
OPU("y12", NUMD2_Y12, IF_COMPLEX, "Admittance"), |
|||
OPU("g21", NUMD2_G21, IF_REAL, "Conductance"), |
|||
OPU("c21", NUMD2_C21, IF_REAL, "Capacitance"), |
|||
OPU("y21", NUMD2_Y21, IF_COMPLEX, "Admittance"), |
|||
OPU("g22", NUMD2_G22, IF_REAL, "Conductance"), |
|||
OPU("c22", NUMD2_C22, IF_REAL, "Capacitance"), |
|||
OPU("y22", NUMD2_Y22, IF_COMPLEX, "Admittance"), |
|||
OPR("voltage", NUMD2_VD, IF_REAL, "Voltage"), |
|||
OPR("current", NUMD2_ID, IF_REAL, "Current"), |
|||
OPR("conductance", NUMD2_G11, IF_REAL, "Conductance"), |
|||
OPR("capacitance", NUMD2_C11, IF_REAL, "Capacitance"), |
|||
IOP("temp", NUMD2_TEMP, IF_REAL, "Instance Temperature") |
|||
}; |
|||
|
|||
IFparm NUMD2mPTable[] = { /* model parameters */ |
|||
/* numerical-device models no longer have parameters */ |
|||
/* one is left behind to keep the table from being empty */ |
|||
IP("numd", NUMD2_MOD_NUMD, IF_FLAG, "Numerical 2d-Diode Model") |
|||
}; |
|||
|
|||
char *NUMD2names[] = { |
|||
"Anode", |
|||
"Cathode" |
|||
}; |
|||
|
|||
int NUMD2nSize = NUMELEMS(NUMD2names); |
|||
int NUMD2pTSize = NUMELEMS(NUMD2pTable); |
|||
int NUMD2mPTSize = NUMELEMS(NUMD2mPTable); |
|||
int NUMD2iSize = sizeof(NUMD2instance); |
|||
int NUMD2mSize = sizeof(NUMD2model); |
|||
@ -0,0 +1,80 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* Function to load the COMPLEX circuit matrix using the small signal |
|||
* parameters saved during a previous DC operating point analysis. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "numd2def.h" |
|||
#include "sperror.h" |
|||
#include "complex.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "numglobs.h" |
|||
#include "suffix.h" |
|||
|
|||
/* External Declarations */ |
|||
extern int TWOacDebug; |
|||
|
|||
int |
|||
NUMD2acLoad(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
register NUMD2model *model = (NUMD2model *) inModel; |
|||
register NUMD2instance *inst; |
|||
SPcomplex y; |
|||
double startTime; |
|||
|
|||
/* loop through all the diode models */ |
|||
for (; model != NULL; model = model->NUMD2nextModel) { |
|||
FieldDepMobility = model->NUMD2models->MODLfieldDepMobility; |
|||
TransDepMobility = model->NUMD2models->MODLtransDepMobility; |
|||
SurfaceMobility = model->NUMD2models->MODLsurfaceMobility; |
|||
Srh = model->NUMD2models->MODLsrh; |
|||
Auger = model->NUMD2models->MODLauger; |
|||
AvalancheGen = model->NUMD2models->MODLavalancheGen; |
|||
OneCarrier = model->NUMD2methods->METHoneCarrier; |
|||
AcAnalysisMethod = model->NUMD2methods->METHacAnalysisMethod; |
|||
MobDeriv = model->NUMD2methods->METHmobDeriv; |
|||
TWOacDebug = model->NUMD2outputs->OUTPacDebug; |
|||
|
|||
for (inst = model->NUMD2instances; inst != NULL; |
|||
inst = inst->NUMD2nextInstance) { |
|||
if (inst->NUMD2owner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NUMD2globals)); |
|||
|
|||
model->NUMD2methods->METHacAnalysisMethod = |
|||
NUMD2admittance(inst->NUMD2pDevice, ckt->CKTomega, &y); |
|||
|
|||
*(inst->NUMD2posPosPtr) += y.real; |
|||
*(inst->NUMD2posPosPtr + 1) += y.imag; |
|||
*(inst->NUMD2negNegPtr) += y.real; |
|||
*(inst->NUMD2negNegPtr + 1) += y.imag; |
|||
*(inst->NUMD2negPosPtr) -= y.real; |
|||
*(inst->NUMD2negPosPtr + 1) -= y.imag; |
|||
*(inst->NUMD2posNegPtr) -= y.real; |
|||
*(inst->NUMD2posNegPtr + 1) -= y.imag; |
|||
if (ckt->CKTomega != 0.0) { |
|||
inst->NUMD2c11 = y.imag / ckt->CKTomega; |
|||
} else { |
|||
inst->NUMD2c11 = 0.0; /* XXX What else can be done?! */ |
|||
} |
|||
inst->NUMD2y11r = y.real; |
|||
inst->NUMD2y11i = y.imag; |
|||
inst->NUMD2smSigAvail = TRUE; |
|||
inst->NUMD2pDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,121 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Thomas L. Quarles |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "devdefs.h" |
|||
#include "numd2def.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
/* Check out this one */ |
|||
extern int NUMD2initSmSig(NUMD2instance *); |
|||
|
|||
/* ARGSUSED */ |
|||
int |
|||
NUMD2ask(ckt, inInst, which, value, select) |
|||
CKTcircuit *ckt; |
|||
GENinstance *inInst; |
|||
int which; |
|||
IFvalue *value; |
|||
IFvalue *select; |
|||
{ |
|||
NUMD2instance *inst = (NUMD2instance *) inInst; |
|||
switch (which) { |
|||
case NUMD2_WIDTH: |
|||
value->rValue = inst->NUMD2width; |
|||
return (OK); |
|||
case NUMD2_AREA: |
|||
value->rValue = inst->NUMD2area; |
|||
break; |
|||
case NUMD2_TEMP: |
|||
value->rValue = inst->NUMD2temp - CONSTCtoK; |
|||
return (OK); |
|||
case NUMD2_VD: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMD2voltage); |
|||
return (OK); |
|||
case NUMD2_ID: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMD2id); |
|||
return (OK); |
|||
case NUMD2_G11: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMD2conduct); |
|||
return (OK); |
|||
case NUMD2_G12: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NUMD2conduct); |
|||
return (OK); |
|||
case NUMD2_G21: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NUMD2conduct); |
|||
return (OK); |
|||
case NUMD2_G22: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMD2conduct); |
|||
return (OK); |
|||
case NUMD2_C11: |
|||
if (!inst->NUMD2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMD2initSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMD2c11; |
|||
return (OK); |
|||
case NUMD2_C12: |
|||
if (!inst->NUMD2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMD2initSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NUMD2c11; |
|||
return (OK); |
|||
case NUMD2_C21: |
|||
if (!inst->NUMD2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMD2initSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NUMD2c11; |
|||
return (OK); |
|||
case NUMD2_C22: |
|||
if (!inst->NUMD2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMD2initSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMD2c11; |
|||
return (OK); |
|||
case NUMD2_Y11: |
|||
if (!inst->NUMD2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMD2initSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMD2y11r; |
|||
value->cValue.imag = inst->NUMD2y11i; |
|||
return (OK); |
|||
case NUMD2_Y12: |
|||
if (!inst->NUMD2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMD2initSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NUMD2y11r; |
|||
value->cValue.imag = -inst->NUMD2y11i; |
|||
return (OK); |
|||
case NUMD2_Y21: |
|||
if (!inst->NUMD2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMD2initSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NUMD2y11r; |
|||
value->cValue.imag = -inst->NUMD2y11i; |
|||
return (OK); |
|||
case NUMD2_Y22: |
|||
if (!inst->NUMD2smSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMD2initSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMD2y11r; |
|||
value->cValue.imag = inst->NUMD2y11i; |
|||
return (OK); |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
/* NOTREACHED */ |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "numd2def.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NUMD2delete(inModel, name, kill) |
|||
GENmodel *inModel; |
|||
IFuid name; |
|||
GENinstance **kill; |
|||
{ |
|||
NUMD2model *model = (NUMD2model *) inModel; |
|||
NUMD2instance **fast = (NUMD2instance **) kill; |
|||
NUMD2instance **prev = NULL; |
|||
NUMD2instance *inst; |
|||
|
|||
for (; model; model = model->NUMD2nextModel) { |
|||
prev = &(model->NUMD2instances); |
|||
for (inst = *prev; inst; inst = *prev) { |
|||
if (inst->NUMD2name == name || (fast && inst == *fast)) { |
|||
*prev = inst->NUMD2nextInstance; |
|||
FREE(inst); |
|||
return (OK); |
|||
} |
|||
prev = &(inst->NUMD2nextInstance); |
|||
} |
|||
} |
|||
return (E_NODEV); |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine deletes all NUMD2s from the circuit and frees all storage |
|||
* they were using. The current implementation has memory leaks. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "numd2def.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
void |
|||
NUMD2destroy(inModel) |
|||
GENmodel **inModel; |
|||
{ |
|||
|
|||
NUMD2model **model = (NUMD2model **) inModel; |
|||
NUMD2model *mod, *nextMod; |
|||
NUMD2instance *inst, *nextInst; |
|||
|
|||
|
|||
for (mod = *model; mod;) { |
|||
for (inst = mod->NUMD2instances; inst;) { |
|||
TWOdestroy(inst->NUMD2pDevice); |
|||
nextInst = inst->NUMD2nextInstance; |
|||
FREE(inst); |
|||
inst = nextInst; |
|||
} |
|||
nextMod = mod->NUMD2nextModel; |
|||
FREE(mod); |
|||
mod = nextMod; |
|||
} |
|||
*model = NULL; |
|||
} |
|||
@ -0,0 +1,165 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This is a simple routine to dump the internal device states. It produces |
|||
* states for .OP, .DC, & .TRAN simulations. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "numd2def.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
/* Forward Declarations */ |
|||
static void NUMD2putHeader(FILE *, CKTcircuit *, NUMD2instance *); |
|||
|
|||
/* State Counter */ |
|||
static int state_numOP = 0; |
|||
static int state_numDC = 0; |
|||
static int state_numTR = 0; |
|||
|
|||
void |
|||
NUMD2dump(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
register NUMD2model *model = (NUMD2model *) inModel; |
|||
register NUMD2instance *inst; |
|||
OUTPcard *output; |
|||
FILE *fpState; |
|||
char fileName[BSIZE_SP]; |
|||
char description[BSIZE_SP]; |
|||
char *prefix; |
|||
int *state_num; |
|||
int anyOutput = 0; |
|||
|
|||
if (ckt->CKTmode & MODEDCOP) { |
|||
prefix = "OP"; |
|||
state_num = &state_numOP; |
|||
sprintf(description, "..."); |
|||
} else if (ckt->CKTmode & MODEDCTRANCURVE) { |
|||
prefix = "DC"; |
|||
state_num = &state_numDC; |
|||
sprintf(description, "sweep = % e", ckt->CKTtime); |
|||
} else if (ckt->CKTmode & MODETRAN) { |
|||
prefix = "TR"; |
|||
state_num = &state_numTR; |
|||
sprintf(description, "time = % e", ckt->CKTtime); |
|||
} else { |
|||
/* Not a recognized CKT mode. */ |
|||
return; |
|||
} |
|||
|
|||
for (; model != NULL; model = model->NUMD2nextModel) { |
|||
output = model->NUMD2outputs; |
|||
for (inst = model->NUMD2instances; inst != NULL; |
|||
inst = inst->NUMD2nextInstance) { |
|||
if (inst->NUMD2owner != ARCHme) continue; |
|||
|
|||
if (inst->NUMD2printGiven) { |
|||
if ((ckt->CKTmode & MODETRAN) && |
|||
((ckt->CKTstat->STATaccepted - 1) % inst->NUMD2print != 0)) { |
|||
continue; |
|||
} |
|||
anyOutput = 1; |
|||
sprintf(fileName, "%s%s.%d.%s", output->OUTProotFile, prefix, |
|||
*state_num, inst->NUMD2name); |
|||
if (!(fpState = fopen(fileName, "w"))) { |
|||
perror(fileName); |
|||
} else { |
|||
NUMD2putHeader(fpState, ckt, inst); |
|||
TWOprnSolution(fpState, inst->NUMD2pDevice, |
|||
model->NUMD2outputs); |
|||
fclose(fpState); |
|||
LOGmakeEntry(fileName, description); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if (anyOutput) { |
|||
(*state_num)++; |
|||
} |
|||
} |
|||
|
|||
#define NUMD2numOutputs 4 |
|||
|
|||
static |
|||
void |
|||
NUMD2putHeader(file, ckt, inst) |
|||
FILE *file; |
|||
CKTcircuit *ckt; |
|||
NUMD2instance *inst; |
|||
{ |
|||
char *reference; |
|||
double refVal = 0.0; |
|||
int numVars = NUMD2numOutputs; |
|||
|
|||
if (ckt->CKTmode & MODEDCOP) { |
|||
reference = NULL; |
|||
} else if (ckt->CKTmode & MODEDCTRANCURVE) { |
|||
reference = "sweep"; |
|||
refVal = ckt->CKTtime; |
|||
numVars++; |
|||
} else if (ckt->CKTmode & MODETRAN) { |
|||
reference = "time"; |
|||
refVal = ckt->CKTtime; |
|||
numVars++; |
|||
} else { |
|||
reference = NULL; |
|||
} |
|||
fprintf(file, "Title: Device %s external state\n", inst->NUMD2name); |
|||
fprintf(file, "Plotname: Device Operating Point\n"); |
|||
fprintf(file, "Command: deftype v conductance S\n"); |
|||
fprintf(file, "Flags: real\n"); |
|||
fprintf(file, "No. Variables: %d\n", numVars); |
|||
fprintf(file, "No. Points: 1\n"); |
|||
numVars = 0; |
|||
fprintf(file, "Variables:\n"); |
|||
if (reference) { |
|||
fprintf(file, "\t%d %s unknown\n", numVars++, reference); |
|||
} |
|||
fprintf(file, "\t%d v12 voltage\n", numVars++); |
|||
fprintf(file, "\t%d i1 current\n", numVars++); |
|||
fprintf(file, "\t%d i2 current\n", numVars++); |
|||
fprintf(file, "\t%d g11 conductance\n", numVars++); |
|||
fprintf(file, "Values:\n0"); |
|||
if (reference) { |
|||
fprintf(file, "\t% e\n", refVal); |
|||
} |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMD2voltage)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMD2id)); |
|||
fprintf(file, "\t% e\n", - *(ckt->CKTstate0 + inst->NUMD2id)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMD2conduct)); |
|||
} |
|||
|
|||
void |
|||
NUMD2acct(inModel, ckt, file) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
FILE *file; |
|||
{ |
|||
register NUMD2model *model = (NUMD2model *) inModel; |
|||
register NUMD2instance *inst; |
|||
OUTPcard *output; |
|||
|
|||
for (; model != NULL; model = model->NUMD2nextModel) { |
|||
output = model->NUMD2outputs; |
|||
for (inst = model->NUMD2instances; inst != NULL; |
|||
inst = inst->NUMD2nextInstance) { |
|||
if (inst->NUMD2owner != ARCHme) continue; |
|||
|
|||
if (output->OUTPstats) { |
|||
TWOmemStats(file, inst->NUMD2pDevice); |
|||
TWOcpuStats(file, inst->NUMD2pDevice); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,408 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This is the function called each iteration to evaluate the 2d numerical |
|||
* Diodes in the circuit and load them into the matrix as appropriate |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "devdefs.h" |
|||
#include "cktdefs.h" |
|||
#include "numd2def.h" |
|||
#include "trandefs.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
/* Forward declarations */ |
|||
int NUMD2initSmSig(NUMD2instance *); |
|||
|
|||
/* External Declarations */ |
|||
extern int TWOdcDebug; |
|||
extern int TWOtranDebug; |
|||
extern int TWOacDebug; |
|||
|
|||
int |
|||
NUMD2load(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
|
|||
{ |
|||
register NUMD2model *model = (NUMD2model *) inModel; |
|||
register NUMD2instance *inst; |
|||
register TWOdevice *pDevice; |
|||
double startTime, startTime2, totalTime, totalTime2; |
|||
double id; |
|||
double idhat = 0.0; |
|||
double ideq; |
|||
double gd; |
|||
double xfact; |
|||
double tol; /* temporary for tolerance calculations */ |
|||
double vd; /* current diode voltage */ |
|||
double delVd; |
|||
int Check; |
|||
int error; |
|||
double deltaNorm[7]; |
|||
int devConverged = FALSE; |
|||
int i; |
|||
int numDevNonCon; |
|||
int deviceType; |
|||
int doInitSolve; |
|||
int doVoltPred; |
|||
char *initStateName; |
|||
|
|||
/* loop through all the diode models */ |
|||
for (; model != NULL; model = model->NUMD2nextModel) { |
|||
FieldDepMobility = model->NUMD2models->MODLfieldDepMobility; |
|||
TransDepMobility = model->NUMD2models->MODLtransDepMobility; |
|||
SurfaceMobility = model->NUMD2models->MODLsurfaceMobility; |
|||
Srh = model->NUMD2models->MODLsrh; |
|||
Auger = model->NUMD2models->MODLauger; |
|||
AvalancheGen = model->NUMD2models->MODLavalancheGen; |
|||
OneCarrier = model->NUMD2methods->METHoneCarrier; |
|||
MobDeriv = model->NUMD2methods->METHmobDeriv; |
|||
MaxIterations = model->NUMD2methods->METHitLim; |
|||
TWOdcDebug = model->NUMD2outputs->OUTPdcDebug; |
|||
TWOtranDebug = model->NUMD2outputs->OUTPtranDebug; |
|||
TWOacDebug = model->NUMD2outputs->OUTPacDebug; |
|||
deviceType = model->NUMD2options->OPTNdeviceType; |
|||
doVoltPred = model->NUMD2methods->METHvoltPred; |
|||
|
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
/* compute normalized deltas and predictor coeff */ |
|||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) { |
|||
model->NUMD2pInfo->order = ckt->CKTorder; |
|||
model->NUMD2pInfo->method = ckt->CKTintegrateMethod; |
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NUMD2pInfo->intCoeff, deltaNorm); |
|||
computePredCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NUMD2pInfo->predCoeff, deltaNorm); |
|||
} |
|||
} else if (ckt->CKTmode & MODEINITTRAN) { |
|||
model->NUMD2pInfo->order = ckt->CKTorder; |
|||
model->NUMD2pInfo->method = GEAR; |
|||
model->NUMD2pInfo->method = ckt->CKTintegrateMethod; |
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NUMD2pInfo->intCoeff, deltaNorm); |
|||
} |
|||
/* loop through all the instances of the model */ |
|||
for (inst = model->NUMD2instances; inst != NULL; |
|||
inst = inst->NUMD2nextInstance) { |
|||
if (inst->NUMD2owner != ARCHme) continue; |
|||
|
|||
pDevice = inst->NUMD2pDevice; |
|||
|
|||
totalTime = 0.0; |
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NUMD2globals)); |
|||
|
|||
pDevice->devStates = ckt->CKTstates; |
|||
/* |
|||
* initialization |
|||
*/ |
|||
Check = 1; |
|||
doInitSolve = FALSE; |
|||
initStateName = NULL; |
|||
if (ckt->CKTmode & MODEINITSMSIG) { |
|||
vd = *(ckt->CKTstate0 + inst->NUMD2voltage); |
|||
delVd = 0.0; |
|||
NUMD2setBCs(pDevice, vd); |
|||
} else if (ckt->CKTmode & MODEINITTRAN) { |
|||
*(ckt->CKTstate0 + inst->NUMD2voltage) = |
|||
*(ckt->CKTstate1 + inst->NUMD2voltage); |
|||
vd = *(ckt->CKTstate1 + inst->NUMD2voltage); |
|||
TWOsaveState(pDevice); |
|||
delVd = 0.0; |
|||
} else if ((ckt->CKTmode & MODEINITJCT) && |
|||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) { |
|||
doInitSolve = TRUE; |
|||
initStateName = inst->NUMD2icFile; |
|||
vd = 0.0; |
|||
delVd = vd; |
|||
} else if ((ckt->CKTmode & MODEINITJCT) && inst->NUMD2off) { |
|||
doInitSolve = TRUE; |
|||
vd = 0.0; |
|||
delVd = vd; |
|||
} else if (ckt->CKTmode & MODEINITJCT) { |
|||
doInitSolve = TRUE; |
|||
initStateName = inst->NUMD2icFile; |
|||
if (deviceType == OPTN_DIODE) { |
|||
vd = inst->NUMD2type * 0.6; |
|||
} else if (deviceType == OPTN_MOSCAP) { |
|||
vd = inst->NUMD2type * 0.8; |
|||
} else { |
|||
vd = 0.0; |
|||
} |
|||
delVd = vd; |
|||
} else if (ckt->CKTmode & MODEINITFIX && inst->NUMD2off) { |
|||
vd = 0.0; |
|||
delVd = vd; |
|||
} else { |
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
*(ckt->CKTstate0 + inst->NUMD2voltage) = |
|||
*(ckt->CKTstate1 + inst->NUMD2voltage); |
|||
*(ckt->CKTstate0 + inst->NUMD2id) = |
|||
*(ckt->CKTstate1 + inst->NUMD2id); |
|||
*(ckt->CKTstate0 + inst->NUMD2conduct) = |
|||
*(ckt->CKTstate1 + inst->NUMD2conduct); |
|||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) { |
|||
/* no linear prediction on device voltages */ |
|||
vd = *(ckt->CKTstate1 + inst->NUMD2voltage); |
|||
TWOpredict(pDevice, model->NUMD2pInfo); |
|||
} else { |
|||
if (doVoltPred) { |
|||
/* linear prediction */ |
|||
xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1]; |
|||
vd = (1+xfact) * (*(ckt->CKTstate1 + inst->NUMD2voltage)) |
|||
- (xfact) * (*(ckt->CKTstate2 + inst->NUMD2voltage)); |
|||
} else { |
|||
vd = *(ckt->CKTstate1 + inst->NUMD2voltage); |
|||
} |
|||
} |
|||
} else { |
|||
vd = *(ckt->CKTrhsOld + inst->NUMD2posNode) - |
|||
*(ckt->CKTrhsOld + inst->NUMD2negNode); |
|||
} |
|||
delVd = vd - *(ckt->CKTstate0 + inst->NUMD2voltage); |
|||
idhat = *(ckt->CKTstate0 + inst->NUMD2id) + |
|||
*(ckt->CKTstate0 + inst->NUMD2conduct) * delVd; |
|||
/* |
|||
* bypass if solution has not changed |
|||
*/ |
|||
if ((ckt->CKTbypass) && pDevice->converged && |
|||
!(ckt->CKTmode & MODEINITPRED)) { |
|||
tol = ckt->CKTvoltTol + ckt->CKTreltol * |
|||
MAX(fabs(vd), fabs(*(ckt->CKTstate0 + inst->NUMD2voltage))); |
|||
if (fabs(delVd) < tol) { |
|||
tol = ckt->CKTreltol * |
|||
MAX(fabs(idhat), fabs(*(ckt->CKTstate0 + inst->NUMD2id))) + |
|||
ckt->CKTabstol; |
|||
if (fabs(idhat - *(ckt->CKTstate0 + inst->NUMD2id)) |
|||
< tol) { |
|||
vd = *(ckt->CKTstate0 + inst->NUMD2voltage); |
|||
id = *(ckt->CKTstate0 + inst->NUMD2id); |
|||
gd = *(ckt->CKTstate0 + inst->NUMD2conduct); |
|||
goto load; |
|||
} |
|||
} |
|||
} |
|||
/* |
|||
* limit new junction voltage |
|||
*/ |
|||
if (deviceType == OPTN_DIODE) { |
|||
vd = inst->NUMD2type * limitJunctionVoltage( |
|||
inst->NUMD2type * vd, |
|||
inst->NUMD2type * *(ckt->CKTstate0 + inst->NUMD2voltage), |
|||
&Check); |
|||
} else if (deviceType == OPTN_MOSCAP) { |
|||
vd = inst->NUMD2type * limitVgb( |
|||
inst->NUMD2type * vd, |
|||
inst->NUMD2type * *(ckt->CKTstate0 + inst->NUMD2voltage), |
|||
&Check); |
|||
} else { |
|||
vd = inst->NUMD2type * limitResistorVoltage( |
|||
inst->NUMD2type * vd, |
|||
inst->NUMD2type * *(ckt->CKTstate0 + inst->NUMD2voltage), |
|||
&Check); |
|||
} |
|||
delVd = vd - *(ckt->CKTstate0 + inst->NUMD2voltage); |
|||
NUMD2setBCs(pDevice, vd - delVd); |
|||
} |
|||
if (doInitSolve) { |
|||
if (TWOdcDebug) { |
|||
printVoltages(stdout, |
|||
model->NUMD2modName, inst->NUMD2name, |
|||
deviceType, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); |
|||
} |
|||
startTime2 = SPfrontEnd->IFseconds(); |
|||
TWOequilSolve(pDevice); |
|||
totalTime2 = SPfrontEnd->IFseconds() - startTime2; |
|||
pDevice->pStats->totalTime[STAT_SETUP] += totalTime2; |
|||
pDevice->pStats->totalTime[STAT_DC] -= totalTime2; |
|||
|
|||
TWObiasSolve(pDevice, MaxIterations, FALSE, NULL); |
|||
|
|||
*(ckt->CKTstate0 + inst->NUMD2voltage) = 0.0; |
|||
|
|||
if (initStateName != NULL) { |
|||
if (TWOreadState(pDevice, initStateName, 1, &vd, NULL, NULL ) < 0) { |
|||
fprintf(stderr, |
|||
"NUMD2load: trouble reading state-file %s\n", initStateName); |
|||
} else { |
|||
*(ckt->CKTstate0 + inst->NUMD2voltage) = vd; |
|||
NUMD2setBCs(pDevice, vd); |
|||
delVd = 0.0; |
|||
} |
|||
} |
|||
} |
|||
/* |
|||
* compute dc current and derivitives |
|||
*/ |
|||
/* use the routines for numerical simulation */ |
|||
|
|||
if (ckt->CKTmode & (MODEDCOP | MODETRANOP | MODEDCTRANCURVE | MODEINITSMSIG)) { |
|||
numDevNonCon = 0; |
|||
inst->NUMD2c11 = inst->NUMD2y11r = inst->NUMD2y11i = 0.0; |
|||
inst->NUMD2smSigAvail = FALSE; |
|||
devNonCon: |
|||
NUMD2project(pDevice, delVd); |
|||
if (TWOdcDebug) { |
|||
printVoltages(stdout, |
|||
model->NUMD2modName, inst->NUMD2name, |
|||
deviceType, 1, vd, delVd, 0.0, 0.0, 0.0, 0.0); |
|||
} |
|||
TWObiasSolve(pDevice, MaxIterations, FALSE, model->NUMD2pInfo); |
|||
devConverged = pDevice->converged; |
|||
|
|||
if (devConverged && finite(pDevice->rhsNorm)) { |
|||
/* extract the current and conductance information */ |
|||
NUMD2current(pDevice, FALSE, (double *) NULL, &id); |
|||
NUMD2conductance(pDevice, FALSE, (double *) NULL, &gd); |
|||
} else { |
|||
/* do voltage step backtracking */ |
|||
/* restore the boundary nodes to the previous value */ |
|||
NUMD2setBCs(pDevice, vd - delVd); |
|||
TWOstoreInitialGuess(pDevice); |
|||
TWOresetJacobian(pDevice); |
|||
delVd *= 0.5; |
|||
vd = delVd + *(ckt->CKTstate0 + inst->NUMD2voltage); |
|||
numDevNonCon++; |
|||
Check = 1; |
|||
if (numDevNonCon > 10) { |
|||
printVoltages(stderr, |
|||
model->NUMD2modName, inst->NUMD2name, |
|||
deviceType, 1, vd, delVd, 0.0, 0.0, 0.0, 0.0); |
|||
fprintf(stderr, |
|||
"*** Non-convergence during load ***\n"); |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
return (E_BADMATRIX); |
|||
} else { |
|||
goto devNonCon; |
|||
} |
|||
} |
|||
} |
|||
if ((ckt->CKTmode & (MODETRAN | MODEAC | MODEINITSMSIG)) || |
|||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) { |
|||
/* |
|||
* store small-signal parameters |
|||
*/ |
|||
if ((!(ckt->CKTmode & MODETRANOP)) || |
|||
(!(ckt->CKTmode & MODEUIC))) { |
|||
if (ckt->CKTmode & MODEINITSMSIG) { |
|||
totalTime = SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
startTime2 = SPfrontEnd->IFseconds(); |
|||
NUMD2initSmSig(inst); |
|||
pDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime2; |
|||
continue; |
|||
} else { |
|||
inst->NUMD2smSigAvail = FALSE; |
|||
} |
|||
/* |
|||
* transient analysis |
|||
*/ |
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
NUMD2setBCs(pDevice, vd); |
|||
TWOstoreInitialGuess(pDevice); |
|||
} else { |
|||
NUMD2update(pDevice, delVd, TRUE); |
|||
} |
|||
if (TWOtranDebug) { |
|||
printVoltages(stdout, |
|||
model->NUMD2modName, inst->NUMD2name, |
|||
deviceType, 1, vd, delVd, 0.0, 0.0, 0.0, 0.0); |
|||
} |
|||
TWObiasSolve(pDevice, 0, TRUE, model->NUMD2pInfo); |
|||
|
|||
if (!finite(pDevice->rhsNorm)) { |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
return (E_BADMATRIX); |
|||
} |
|||
devConverged = TWOdeviceConverged(pDevice); |
|||
pDevice->converged = devConverged; |
|||
|
|||
/* extract the current and conductance information */ |
|||
NUMD2current(pDevice, TRUE, model->NUMD2pInfo->intCoeff, &id); |
|||
NUMD2conductance(pDevice, TRUE, model->NUMD2pInfo->intCoeff, &gd); |
|||
} |
|||
} |
|||
/* |
|||
* check convergence |
|||
*/ |
|||
if ((!(ckt->CKTmode & MODEINITFIX)) || (!(inst->NUMD2off))) { |
|||
if (Check == 1 || !devConverged) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} else { |
|||
tol = ckt->CKTreltol * MAX(fabs(idhat), fabs(id)) + ckt->CKTabstol; |
|||
if (fabs(idhat - id) > tol) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} |
|||
} |
|||
} |
|||
*(ckt->CKTstate0 + inst->NUMD2voltage) = vd; |
|||
*(ckt->CKTstate0 + inst->NUMD2id) = id; |
|||
*(ckt->CKTstate0 + inst->NUMD2conduct) = gd; |
|||
|
|||
load: |
|||
|
|||
/* |
|||
* load current vector |
|||
*/ |
|||
ideq = id - gd * vd; |
|||
*(ckt->CKTrhs + inst->NUMD2negNode) += ideq; |
|||
*(ckt->CKTrhs + inst->NUMD2posNode) -= ideq; |
|||
/* |
|||
* load matrix |
|||
*/ |
|||
*(inst->NUMD2posPosPtr) += gd; |
|||
*(inst->NUMD2negNegPtr) += gd; |
|||
*(inst->NUMD2negPosPtr) -= gd; |
|||
*(inst->NUMD2posNegPtr) -= gd; |
|||
|
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
if (ckt->CKTmode & MODETRAN) { |
|||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime; |
|||
} else { |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
} |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
|
|||
int |
|||
NUMD2initSmSig(inst) |
|||
NUMD2instance *inst; |
|||
{ |
|||
SPcomplex yd; |
|||
double omega = inst->NUMD2modPtr->NUMD2methods->METHomega; |
|||
|
|||
AcAnalysisMethod = SOR_ONLY; |
|||
(void) NUMD2admittance(inst->NUMD2pDevice, omega, &yd); |
|||
inst->NUMD2c11 = yd.imag / omega; |
|||
inst->NUMD2y11r = yd.real; |
|||
inst->NUMD2y11i = yd.imag; |
|||
inst->NUMD2smSigAvail = TRUE; |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "numd2def.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NUMD2mDelete(inModel, modname, kill) |
|||
GENmodel **inModel; |
|||
IFuid modname; |
|||
GENmodel *kill; |
|||
|
|||
{ |
|||
NUMD2model **model = (NUMD2model **) inModel; |
|||
NUMD2model *modfast = (NUMD2model *) kill; |
|||
NUMD2instance *inst; |
|||
NUMD2instance *prev = NULL; |
|||
NUMD2model **oldmod; |
|||
oldmod = model; |
|||
for (; *model; model = &((*model)->NUMD2nextModel)) { |
|||
if ((*model)->NUMD2modName == modname || |
|||
(modfast && *model == modfast)) |
|||
goto delgot; |
|||
oldmod = model; |
|||
} |
|||
return (E_NOMOD); |
|||
|
|||
delgot: |
|||
*oldmod = (*model)->NUMD2nextModel; /* cut deleted device out of list */ |
|||
for (inst = (*model)->NUMD2instances; inst; inst = inst->NUMD2nextInstance) { |
|||
if (prev) |
|||
FREE(prev); |
|||
prev = inst; |
|||
} |
|||
if (prev) |
|||
FREE(prev); |
|||
FREE(*model); |
|||
return (OK); |
|||
|
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine sets model parameters for NUMD2s in the circuit. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "numd2def.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NUMD2mParam(param, value, inModel) |
|||
int param; |
|||
IFvalue *value; |
|||
GENmodel *inModel; |
|||
{ |
|||
switch (param) { |
|||
case NUMD2_MOD_NUMD: |
|||
/* no action - already know it is a 2d-numerical diode, but this */ |
|||
/* makes life easier for spice-2 like parsers */ |
|||
break; |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,49 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "numd2def.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NUMD2param(param, value, inInst, select) |
|||
int param; |
|||
IFvalue *value; |
|||
GENinstance *inInst; |
|||
IFvalue *select; |
|||
{ |
|||
NUMD2instance *inst = (NUMD2instance *) inInst; |
|||
switch (param) { |
|||
case NUMD2_WIDTH: |
|||
inst->NUMD2width = value->rValue; |
|||
inst->NUMD2widthGiven = TRUE; |
|||
break; |
|||
case NUMD2_AREA: |
|||
inst->NUMD2area = value->rValue; |
|||
inst->NUMD2areaGiven = TRUE; |
|||
break; |
|||
case NUMD2_OFF: |
|||
inst->NUMD2off = TRUE; |
|||
break; |
|||
case NUMD2_IC_FILE: |
|||
inst->NUMD2icFile = value->sValue; |
|||
inst->NUMD2icFileGiven = TRUE; |
|||
break; |
|||
case NUMD2_PRINT: |
|||
inst->NUMD2print = value->rValue; |
|||
inst->NUMD2printGiven = TRUE; |
|||
break; |
|||
case NUMD2_TEMP: |
|||
inst->NUMD2temp = value->rValue + CONSTCtoK; |
|||
inst->NUMD2tempGiven = TRUE; |
|||
break; |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,67 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "complex.h" |
|||
#include "sperror.h" |
|||
#include "numd2def.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
/* External Declarations */ |
|||
extern int TWOacDebug; |
|||
|
|||
int |
|||
NUMD2pzLoad(inModel, ckt, s) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
SPcomplex *s; |
|||
{ |
|||
register NUMD2model *model = (NUMD2model *) inModel; |
|||
register NUMD2instance *inst; |
|||
SPcomplex y; |
|||
double startTime; |
|||
|
|||
/* loop through all the diode models */ |
|||
for (; model != NULL; model = model->NUMD2nextModel) { |
|||
FieldDepMobility = model->NUMD2models->MODLfieldDepMobility; |
|||
TransDepMobility = model->NUMD2models->MODLtransDepMobility; |
|||
SurfaceMobility = model->NUMD2models->MODLsurfaceMobility; |
|||
Srh = model->NUMD2models->MODLsrh; |
|||
Auger = model->NUMD2models->MODLauger; |
|||
AvalancheGen = model->NUMD2models->MODLavalancheGen; |
|||
OneCarrier = model->NUMD2methods->METHoneCarrier; |
|||
AcAnalysisMethod = model->NUMD2methods->METHacAnalysisMethod; |
|||
MobDeriv = model->NUMD2methods->METHmobDeriv; |
|||
TWOacDebug = model->NUMD2outputs->OUTPacDebug; |
|||
|
|||
for (inst = model->NUMD2instances; inst != NULL; |
|||
inst = inst->NUMD2nextInstance) { |
|||
if (inst->NUMD2owner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NUMD2globals)); |
|||
|
|||
NUMD2ys(inst->NUMD2pDevice, s, &y); |
|||
|
|||
*(inst->NUMD2posPosPtr) += y.real; |
|||
*(inst->NUMD2posPosPtr + 1) += y.imag; |
|||
*(inst->NUMD2negNegPtr) += y.real; |
|||
*(inst->NUMD2negNegPtr + 1) += y.imag; |
|||
*(inst->NUMD2negPosPtr) -= y.real; |
|||
*(inst->NUMD2negPosPtr + 1) -= y.imag; |
|||
*(inst->NUMD2posNegPtr) -= y.real; |
|||
*(inst->NUMD2posNegPtr + 1) -= y.imag; |
|||
|
|||
inst->NUMD2pDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,266 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "smpdefs.h" |
|||
#include "numd2def.h" |
|||
#include "numconst.h" |
|||
#include "numenum.h" |
|||
#include "meshext.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "ciderinp.h" |
|||
#include "suffix.h" |
|||
|
|||
#define NIL(type) ((type *)0) |
|||
#define TSCALLOC(var, size, type)\ |
|||
if (size && (!(var =(type *)calloc(1, (unsigned)(size)*sizeof(type))))) {\ |
|||
return(E_NOMEM);\ |
|||
} |
|||
|
|||
int |
|||
NUMD2setup(matrix, inModel, ckt, states) |
|||
register SMPmatrix *matrix; |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
int *states; |
|||
/* |
|||
* load the structure with those pointers needed later for fast matrix |
|||
* loading |
|||
*/ |
|||
{ |
|||
register NUMD2model *model = (NUMD2model *) inModel; |
|||
register NUMD2instance *inst; |
|||
METHcard *methods; |
|||
MODLcard *models; |
|||
OPTNcard *options; |
|||
OUTPcard *outputs; |
|||
char *icFileName = NULL; |
|||
int nameLen; |
|||
int error, xIndex, yIndex; |
|||
int xMeshSize, yMeshSize; |
|||
TWOdevice *pDevice; |
|||
TWOcoord *xCoordList = NIL(TWOcoord); |
|||
TWOcoord *yCoordList = NIL(TWOcoord); |
|||
TWOdomain *domainList = NIL(TWOdomain); |
|||
TWOelectrode *electrodeList = NIL(TWOelectrode); |
|||
TWOmaterial *pM, *pMaterial = NIL(TWOmaterial), *materialList = NIL(TWOmaterial); |
|||
DOPprofile *profileList = NIL(DOPprofile); |
|||
DOPtable *dopTableList = NIL(DOPtable); |
|||
double startTime; |
|||
|
|||
|
|||
/* loop through all the models */ |
|||
for (; model != NULL; model = model->NUMD2nextModel) { |
|||
if (!model->NUMD2pInfo) { |
|||
TSCALLOC(model->NUMD2pInfo, 1, TWOtranInfo); |
|||
} |
|||
methods = model->NUMD2methods; |
|||
if (!methods) { |
|||
TSCALLOC(methods, 1, METHcard); |
|||
model->NUMD2methods = methods; |
|||
} |
|||
models = model->NUMD2models; |
|||
if (!models) { |
|||
TSCALLOC(models, 1, MODLcard); |
|||
model->NUMD2models = models; |
|||
} |
|||
options = model->NUMD2options; |
|||
if (!options) { |
|||
TSCALLOC(options, 1, OPTNcard); |
|||
model->NUMD2options = options; |
|||
} |
|||
outputs = model->NUMD2outputs; |
|||
if (!outputs) { |
|||
TSCALLOC(outputs, 1, OUTPcard); |
|||
model->NUMD2outputs = outputs; |
|||
} |
|||
if (!methods->METHvoltPredGiven) { |
|||
methods->METHvoltPred = FALSE; |
|||
} |
|||
if (!methods->METHmobDerivGiven) { |
|||
methods->METHmobDeriv = TRUE; |
|||
} |
|||
if (!methods->METHoneCarrierGiven) { |
|||
methods->METHoneCarrier = FALSE; |
|||
} |
|||
if (!methods->METHacAnalysisMethodGiven) { |
|||
methods->METHacAnalysisMethod = SOR; |
|||
} |
|||
if (!methods->METHdabstolGiven) { |
|||
methods->METHdabstol = DABSTOL2D; |
|||
} |
|||
if (!methods->METHdreltolGiven) { |
|||
methods->METHdreltol = ckt->CKTreltol; |
|||
} |
|||
if (!methods->METHitLimGiven) { |
|||
methods->METHitLim = 50; |
|||
} |
|||
if (!methods->METHomegaGiven || methods->METHomega <= 0.0) { |
|||
methods->METHomega = 2.0 * M_PI /* radians/sec */ ; |
|||
} |
|||
if (!options->OPTNdefaGiven || options->OPTNdefa <= 0.0) { |
|||
options->OPTNdefa = 1.0e4 /* cm^2 */ ; |
|||
} |
|||
if (!options->OPTNdeflGiven || options->OPTNdefl <= 0.0) { |
|||
options->OPTNdefl = 1.0e2 /* cm */ ; |
|||
} |
|||
if (!options->OPTNdefwGiven && options->OPTNdefaGiven) { |
|||
options->OPTNdefw = options->OPTNdefa / options->OPTNdefl; |
|||
} else if (!options->OPTNdefwGiven || options->OPTNdefw <= 0.0) { |
|||
options->OPTNdefw = 1.0e2 /* cm */ ; |
|||
} |
|||
if (!options->OPTNdeviceTypeGiven) { |
|||
options->OPTNdeviceType = OPTN_DIODE; |
|||
} |
|||
if (!options->OPTNicFileGiven) { |
|||
options->OPTNicFile = NULL; |
|||
options->OPTNunique = FALSE; /* Can't form a unique name. */ |
|||
} |
|||
if (!options->OPTNuniqueGiven) { |
|||
options->OPTNunique = FALSE; |
|||
} |
|||
OneCarrier = methods->METHoneCarrier; |
|||
|
|||
/* Set up the rest of the card lists */ |
|||
if ((error = MODLsetup(model->NUMD2models))) |
|||
return (error); |
|||
BandGapNarrowing = models->MODLbandGapNarrowing; |
|||
ConcDepLifetime = models->MODLconcDepLifetime; |
|||
TempDepMobility = models->MODLtempDepMobility; |
|||
ConcDepMobility = models->MODLconcDepMobility; |
|||
SurfaceMobility = models->MODLsurfaceMobility; |
|||
|
|||
if ((error = OUTPsetup(model->NUMD2outputs))) |
|||
return (error); |
|||
if ((error = MATLsetup(model->NUMD2materials, &materialList))) |
|||
return (error); |
|||
if ((error = MOBsetup(model->NUMD2mobility, materialList))) |
|||
return (error); |
|||
if ((error = MESHsetup('x', model->NUMD2xMeshes, &xCoordList, &xMeshSize))) |
|||
return (error); |
|||
if ((error = MESHsetup('y', model->NUMD2yMeshes, &yCoordList, &yMeshSize))) |
|||
return (error); |
|||
if ((error = DOMNsetup(model->NUMD2domains, &domainList, |
|||
xCoordList, yCoordList, materialList))) |
|||
return (error); |
|||
if ((error = BDRYsetup(model->NUMD2boundaries, |
|||
xCoordList, yCoordList, domainList))) |
|||
return (error); |
|||
if ((error = ELCTsetup(model->NUMD2electrodes, &electrodeList, |
|||
xCoordList, yCoordList))) |
|||
return (error); |
|||
/* Make sure electrodes are OK. */ |
|||
checkElectrodes(electrodeList, 2); /* NUMD2 has 4 electrodes */ |
|||
|
|||
if ((error = CONTsetup(model->NUMD2contacts, electrodeList))) |
|||
return (error); |
|||
if ((error = DOPsetup(model->NUMD2dopings, &profileList, |
|||
&dopTableList, xCoordList, yCoordList))) |
|||
return (error); |
|||
model->NUMD2matlInfo = materialList; |
|||
model->NUMD2profiles = profileList; |
|||
model->NUMD2dopTables = dopTableList; |
|||
|
|||
/* loop through all the instances of the model */ |
|||
for (inst = model->NUMD2instances; inst != NULL; |
|||
inst = inst->NUMD2nextInstance) { |
|||
if (inst->NUMD2owner != ARCHme) goto matrixpointers; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
if (!inst->NUMD2printGiven) { |
|||
inst->NUMD2print = 0; |
|||
} else if (inst->NUMD2print <= 0) { |
|||
inst->NUMD2print = 1; |
|||
} |
|||
if (!inst->NUMD2icFileGiven) { |
|||
if (options->OPTNunique) { |
|||
nameLen = strlen(options->OPTNicFile) + strlen(inst->NUMD2name) + 1; |
|||
TSCALLOC(icFileName, nameLen+1, char); |
|||
sprintf(icFileName, "%s.%s", options->OPTNicFile, inst->NUMD2name); |
|||
icFileName[nameLen] = '\0'; |
|||
inst->NUMD2icFile = icFileName; |
|||
} else if (options->OPTNicFile != NULL) { |
|||
nameLen = strlen(options->OPTNicFile); |
|||
TSCALLOC(icFileName, nameLen+1, char); |
|||
icFileName = strcpy(icFileName, options->OPTNicFile); |
|||
inst->NUMD2icFile = icFileName; |
|||
} else { |
|||
inst->NUMD2icFile = NULL; |
|||
} |
|||
} |
|||
inst->NUMD2state = *states; |
|||
*states += NUMD2numStates; |
|||
|
|||
if (!inst->NUMD2pDevice) { |
|||
/* Assign the mesh and profile info to each instance. */ |
|||
TSCALLOC(pDevice, 1, TWOdevice); |
|||
TSCALLOC(pDevice->pStats, 1, TWOstats); |
|||
pDevice->name = inst->NUMD2name; |
|||
pDevice->solverType = SLV_NONE; |
|||
pDevice->numXNodes = xMeshSize; |
|||
pDevice->numYNodes = yMeshSize; |
|||
pDevice->xScale = MESHmkArray(xCoordList, xMeshSize); |
|||
pDevice->yScale = MESHmkArray(yCoordList, yMeshSize); |
|||
pDevice->abstol = methods->METHdabstol; |
|||
pDevice->reltol = methods->METHdreltol; |
|||
TSCALLOC(pDevice->elemArray, pDevice->numXNodes, TWOelem **); |
|||
for (xIndex = 1; xIndex < pDevice->numXNodes; xIndex++) { |
|||
TSCALLOC(pDevice->elemArray[xIndex], pDevice->numYNodes, TWOelem *); |
|||
} |
|||
|
|||
/* Create a copy of material data that can change with temperature. */ |
|||
pDevice->pMaterials = NIL(TWOmaterial); |
|||
for (pM = materialList; pM != NIL(TWOmaterial); pM = pM->next) { |
|||
if (pDevice->pMaterials == NIL(TWOmaterial)) { |
|||
TSCALLOC(pMaterial, 1, TWOmaterial); |
|||
pDevice->pMaterials = pMaterial; |
|||
} else { |
|||
TSCALLOC(pMaterial->next, 1, TWOmaterial); |
|||
pMaterial = pMaterial->next; |
|||
} |
|||
/* Copy everything, then fix the incorrect pointer. */ |
|||
bcopy((char *) pM, (char *) pMaterial, sizeof(TWOmaterial)); |
|||
pMaterial->next = NIL(TWOmaterial); |
|||
} |
|||
|
|||
/* Generate the mesh structure for the device. */ |
|||
TWObuildMesh(pDevice, domainList, electrodeList, pDevice->pMaterials); |
|||
|
|||
/* Store the device info in the instance. */ |
|||
inst->NUMD2pDevice = pDevice; |
|||
} |
|||
/* Now update the state pointers. */ |
|||
TWOgetStatePointers(inst->NUMD2pDevice, states); |
|||
|
|||
/* Wipe out statistics from previous runs (if any). */ |
|||
bzero((char *) inst->NUMD2pDevice->pStats, sizeof(TWOstats)); |
|||
|
|||
inst->NUMD2pDevice->pStats->totalTime[STAT_SETUP] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
|
|||
/* macro to make elements with built in test for out of memory */ |
|||
#define TSTALLOC(ptr,first,second) \ |
|||
if ((inst->ptr = SMPmakeElt(matrix,inst->first,inst->second))==(double *)NULL){\ |
|||
return(E_NOMEM);\ |
|||
} |
|||
matrixpointers: |
|||
TSTALLOC(NUMD2posPosPtr, NUMD2posNode, NUMD2posNode) |
|||
TSTALLOC(NUMD2negNegPtr, NUMD2negNode, NUMD2negNode) |
|||
TSTALLOC(NUMD2negPosPtr, NUMD2negNode, NUMD2posNode) |
|||
TSTALLOC(NUMD2posNegPtr, NUMD2posNode, NUMD2negNode) |
|||
} |
|||
/* Clean up lists */ |
|||
killCoordInfo(xCoordList); |
|||
killCoordInfo(yCoordList); |
|||
killDomainInfo(domainList); |
|||
killElectrodeInfo(electrodeList); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,127 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
Author: 1992 David A. Gates, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "numd2def.h" |
|||
#include "numenum.h" |
|||
#include "carddefs.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
#define NIL(type) ((type *)0) |
|||
|
|||
int |
|||
NUMD2temp(inModel, ckt) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
/* |
|||
* perform the temperature update |
|||
*/ |
|||
{ |
|||
register NUMD2model *model = (NUMD2model *) inModel; |
|||
register NUMD2instance *inst; |
|||
METHcard *methods; |
|||
MODLcard *models; |
|||
OPTNcard *options; |
|||
OUTPcard *outputs; |
|||
TWOmaterial *pM, *pMaterial, *pNextMaterial; |
|||
double startTime; |
|||
|
|||
/* loop through all the models */ |
|||
for (; model != NULL; model = model->NUMD2nextModel) { |
|||
methods = model->NUMD2methods; |
|||
models = model->NUMD2models; |
|||
options = model->NUMD2options; |
|||
outputs = model->NUMD2outputs; |
|||
|
|||
if (!options->OPTNtnomGiven) { |
|||
options->OPTNtnom = ckt->CKTnomTemp; |
|||
} |
|||
for (pM = model->NUMD2matlInfo; pM != NIL(TWOmaterial); |
|||
pM = pM->next) { |
|||
pM->tnom = options->OPTNtnom; |
|||
} |
|||
BandGapNarrowing = models->MODLbandGapNarrowing; |
|||
ConcDepLifetime = models->MODLconcDepLifetime; |
|||
TempDepMobility = models->MODLtempDepMobility; |
|||
ConcDepMobility = models->MODLconcDepMobility; |
|||
SurfaceMobility = models->MODLsurfaceMobility; |
|||
MatchingMobility = models->MODLmatchingMobility; |
|||
OneCarrier = methods->METHoneCarrier; |
|||
|
|||
for (inst = model->NUMD2instances; inst != NULL; |
|||
inst = inst->NUMD2nextInstance) { |
|||
if (inst->NUMD2owner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
if (!inst->NUMD2tempGiven) { |
|||
inst->NUMD2temp = ckt->CKTtemp; |
|||
} |
|||
if (!inst->NUMD2areaGiven || inst->NUMD2area <= 0.0) { |
|||
inst->NUMD2area = 1.0; |
|||
} |
|||
if (!inst->NUMD2widthGiven || inst->NUMD2width <= 0.0) { |
|||
inst->NUMD2width = 1.0; |
|||
} |
|||
inst->NUMD2pDevice->width = |
|||
inst->NUMD2area * inst->NUMD2width * options->OPTNdefw; |
|||
|
|||
/* Compute and save globals for this instance. */ |
|||
GLOBcomputeGlobals(&(inst->NUMD2globals), inst->NUMD2temp); |
|||
|
|||
/* Calculate new sets of material parameters. */ |
|||
pM = model->NUMD2matlInfo; |
|||
pMaterial = inst->NUMD2pDevice->pMaterials; |
|||
for (; pM != NULL; pM = pM->next, pMaterial = pMaterial->next) { |
|||
|
|||
/* Copy everything, then fix the incorrect pointer. */ |
|||
pNextMaterial = pMaterial->next; |
|||
bcopy((char *) pM, (char *) pMaterial, sizeof(TWOmaterial)); |
|||
pMaterial->next = pNextMaterial; |
|||
|
|||
/* Now do the temperature dependence. */ |
|||
MATLtempDep(pMaterial, pMaterial->tnom); |
|||
if (outputs->OUTPmaterial) { |
|||
printMaterialInfo(pMaterial); |
|||
} |
|||
} |
|||
|
|||
/* Assign doping to the mesh. */ |
|||
TWOsetDoping(inst->NUMD2pDevice, model->NUMD2profiles, |
|||
model->NUMD2dopTables); |
|||
|
|||
/* Assign physical parameters to the mesh. */ |
|||
TWOsetup(inst->NUMD2pDevice); |
|||
|
|||
/* Assign boundary condition parameters. */ |
|||
TWOsetBCparams(inst->NUMD2pDevice, model->NUMD2boundaries); |
|||
|
|||
/* Normalize everything. */ |
|||
TWOnormalize(inst->NUMD2pDevice); |
|||
|
|||
/* Find the device's type. */ |
|||
if (inst->NUMD2pDevice->pFirstContact->pNodes[0]->netConc < 0.0) { |
|||
inst->NUMD2type = PN; |
|||
if (OneCarrier) { |
|||
methods->METHoneCarrier = P_TYPE; |
|||
} |
|||
} else { |
|||
inst->NUMD2type = NP; |
|||
if (OneCarrier) { |
|||
methods->METHoneCarrier = N_TYPE; |
|||
} |
|||
} |
|||
inst->NUMD2pDevice->pStats->totalTime[STAT_SETUP] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "numd2def.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "suffix.h" |
|||
#include "cidersupt.h" |
|||
|
|||
int |
|||
NUMD2trunc(inModel, ckt, timeStep) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
double *timeStep; |
|||
{ |
|||
register NUMD2model *model = (NUMD2model *) inModel; |
|||
register NUMD2instance *inst; |
|||
double deltaNew; |
|||
double deltaNorm[7]; |
|||
double startTime; |
|||
int i; |
|||
|
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
|
|||
for (; model != NULL; model = model->NUMD2nextModel) { |
|||
OneCarrier = model->NUMD2methods->METHoneCarrier; |
|||
model->NUMD2pInfo->order = ckt->CKTorder; |
|||
model->NUMD2pInfo->delta = deltaNorm; |
|||
model->NUMD2pInfo->lteCoeff = computeLTECoeff(model->NUMD2pInfo); |
|||
for (inst = model->NUMD2instances; inst != NULL; |
|||
inst = inst->NUMD2nextInstance) { |
|||
if (inst->NUMD2owner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
deltaNew = TWOtrunc(inst->NUMD2pDevice, model->NUMD2pInfo, |
|||
ckt->CKTdelta); |
|||
*timeStep = MIN(*timeStep, deltaNew); |
|||
inst->NUMD2pDevice->pStats->totalTime[STAT_TRAN] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,138 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Authors: 1987 Karti Mayaram, 1991 David Gates |
|||
**********/ |
|||
|
|||
#ifndef NUMD2_H |
|||
#define NUMD2_H "NUMD2defs.h $Revision$ on $Date$ " |
|||
|
|||
/* data structures used to describe 2D numerical diodes */ |
|||
|
|||
/* circuit level includes */ |
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "gendefs.h" |
|||
|
|||
/* device level includes */ |
|||
#include "twomesh.h" |
|||
#include "twodev.h" |
|||
#include "profile.h" |
|||
#include "numglobs.h" |
|||
#include "carddefs.h" |
|||
|
|||
/* information needed per instance */ |
|||
typedef struct sNUMD2instance { |
|||
struct sNUMD2model *NUMD2modPtr; /* back pointer to model */ |
|||
struct sNUMD2instance *NUMD2nextInstance; /* pointer to next instance |
|||
* of current model */ |
|||
IFuid NUMD2name; /* pointer to character string naming this |
|||
* instance */ |
|||
int NUMD2owner; /* number of owner process */ |
|||
int NUMD2state; /* pointer to start of state vector for diode */ |
|||
|
|||
#define NUMD2voltage NUMD2state |
|||
#define NUMD2id NUMD2state+1 |
|||
#define NUMD2conduct NUMD2state+2 |
|||
#define NUMD2numStates 3 |
|||
|
|||
int NUMD2posNode; /* number of positive node of diode */ |
|||
int NUMD2negNode; /* number of negative node of diode */ |
|||
TWOdevice *NUMD2pDevice; |
|||
GLOBvalues NUMD2globals; /* Temp.-Dep. Global Parameters */ |
|||
int NUMD2type; /* device type pn or np */ |
|||
double NUMD2width; /* width factor for the diode */ |
|||
double NUMD2area; /* area factor for the diode */ |
|||
double NUMD2temp; /* instance temperature */ |
|||
double NUMD2c11; /* small-signal capacitance */ |
|||
double NUMD2y11r; /* small-signal admittance, real part */ |
|||
double NUMD2y11i; /* small-signal admittance, imag part */ |
|||
int NUMD2print; /* number of timesteps after which print |
|||
* internal */ |
|||
char *NUMD2icFile; /* Name of initial condition file */ |
|||
double *NUMD2negPosPtr; /* pointer to sparse matrix at |
|||
* (negative,positive) */ |
|||
double *NUMD2posNegPtr; /* pointer to sparse matrix at |
|||
* (positive,negative) */ |
|||
double *NUMD2posPosPtr; /* pointer to sparse matrix at |
|||
* (positive,positive) */ |
|||
double *NUMD2negNegPtr; /* pointer to sparse matrix at |
|||
* (negative,negative) */ |
|||
|
|||
int NUMD2off; /* 'off' flag for diode */ |
|||
unsigned NUMD2smSigAvail:1; /* flag to indicate small-signal done */ |
|||
unsigned NUMD2widthGiven:1; /* flag to indicate width was specified */ |
|||
unsigned NUMD2areaGiven:1; /* flag to indicate area was specified */ |
|||
unsigned NUMD2icFileGiven:1; /* flag to indicate init. cond. file given */ |
|||
unsigned NUMD2tempGiven:1; /* flag to indicate temp was specified */ |
|||
unsigned NUMD2printGiven:1; /* flag to indicate if print was specified */ |
|||
} NUMD2instance; |
|||
|
|||
|
|||
/* per model data */ |
|||
|
|||
typedef struct sNUMD2model { /* model structure for a diode */ |
|||
int NUMD2modType; /* type index of this device type */ |
|||
struct sNUMD2model *NUMD2nextModel; /* pointer to next possible model in |
|||
* linked list */ |
|||
NUMD2instance *NUMD2instances;/* pointer to list of instances that have |
|||
* this model */ |
|||
IFuid NUMD2modName; /* pointer to character string naming this |
|||
* model */ |
|||
/* Everything below here is numerical-device-specific */ |
|||
MESHcard *NUMD2xMeshes; /* list of xmesh cards */ |
|||
MESHcard *NUMD2yMeshes; /* list of ymesh cards */ |
|||
DOMNcard *NUMD2domains; /* list of domain cards */ |
|||
BDRYcard *NUMD2boundaries; /* list of boundary cards */ |
|||
DOPcard *NUMD2dopings; /* list of doping cards */ |
|||
ELCTcard *NUMD2electrodes; /* list of electrode cards */ |
|||
CONTcard *NUMD2contacts; /* list of contact cards */ |
|||
MODLcard *NUMD2models; /* list of model cards */ |
|||
MATLcard *NUMD2materials; /* list of material cards */ |
|||
MOBcard *NUMD2mobility; /* list of mobility cards */ |
|||
METHcard *NUMD2methods; /* list of method cards */ |
|||
OPTNcard *NUMD2options; /* list of option cards */ |
|||
OUTPcard *NUMD2outputs; /* list of output cards */ |
|||
TWOtranInfo *NUMD2pInfo; /* transient analysis information */ |
|||
DOPprofile *NUMD2profiles; /* expanded list of doping profiles */ |
|||
DOPtable *NUMD2dopTables; /* list of tables used by profiles */ |
|||
TWOmaterial *NUMD2matlInfo; /* list of material info structures */ |
|||
} NUMD2model; |
|||
|
|||
/* type of 2D diode */ |
|||
#define PN 1 |
|||
#define NP -1 |
|||
|
|||
/* device parameters */ |
|||
#define NUMD2_WIDTH 1 |
|||
#define NUMD2_AREA 2 |
|||
#define NUMD2_IC_FILE 3 |
|||
#define NUMD2_OFF 4 |
|||
#define NUMD2_PRINT 5 |
|||
#define NUMD2_TEMP 6 |
|||
#define NUMD2_VD 7 |
|||
#define NUMD2_ID 8 |
|||
|
|||
#define NUMD2_G11 9 |
|||
#define NUMD2_C11 10 |
|||
#define NUMD2_Y11 11 |
|||
#define NUMD2_G12 12 |
|||
#define NUMD2_C12 13 |
|||
#define NUMD2_Y12 14 |
|||
#define NUMD2_G21 15 |
|||
#define NUMD2_C21 16 |
|||
#define NUMD2_Y21 17 |
|||
#define NUMD2_G22 18 |
|||
#define NUMD2_C22 19 |
|||
#define NUMD2_Y22 20 |
|||
|
|||
/* model parameters */ |
|||
/* NOTE: all true model parameters have been moved to IFcardInfo structures */ |
|||
#define NUMD2_MOD_NUMD 101 |
|||
|
|||
/* device questions */ |
|||
|
|||
/* model questions */ |
|||
|
|||
#include "numd2ext.h" |
|||
|
|||
#endif /* NUMD2_H */ |
|||
@ -0,0 +1,28 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Karti Mayaram |
|||
**********/ |
|||
|
|||
#ifndef NUMD2EXT_H |
|||
#define NUMD2EXT_H |
|||
|
|||
|
|||
extern int NUMD2acLoad(GENmodel *, CKTcircuit *); |
|||
extern int NUMD2ask(CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *); |
|||
extern int NUMD2delete(GENmodel *, IFuid, GENinstance **); |
|||
extern void NUMD2destroy(GENmodel **); |
|||
extern int NUMD2getic(GENmodel *, CKTcircuit *); |
|||
extern int NUMD2load(GENmodel *, CKTcircuit *); |
|||
extern int NUMD2mDelete(GENmodel **, IFuid, GENmodel *); |
|||
extern int NUMD2mParam(int, IFvalue *, GENmodel *); |
|||
extern int NUMD2param(int, IFvalue *, GENinstance *, IFvalue *); |
|||
extern int NUMD2pzLoad(GENmodel *, CKTcircuit *, SPcomplex *); |
|||
extern int NUMD2setup(SMPmatrix *, GENmodel *, CKTcircuit *, int *); |
|||
extern int NUMD2temp(GENmodel *, CKTcircuit *); |
|||
extern int NUMD2trunc(GENmodel *, CKTcircuit *, double *); |
|||
|
|||
extern void NUMD2dump(GENmodel *, CKTcircuit *); |
|||
extern void NUMD2acct(GENmodel *, CKTcircuit *, FILE *); |
|||
|
|||
|
|||
#endif /* NUMD2EXT_H */ |
|||
@ -0,0 +1,83 @@ |
|||
#include <config.h> |
|||
|
|||
#include <devdefs.h> |
|||
|
|||
#include "numd2itf.h" |
|||
#include "numd2ext.h" |
|||
#include "numd2init.h" |
|||
|
|||
|
|||
SPICEdev NUMD2info = { |
|||
{ |
|||
"NUMD2", |
|||
"2D Numerical Junction Diode model", |
|||
|
|||
&NUMD2nSize, |
|||
&NUMD2nSize, |
|||
NUMD2names, |
|||
|
|||
&NUMD2pTSize, |
|||
NUMD2pTable, |
|||
|
|||
&NUMD2mPTSize, |
|||
NUMD2mPTable, |
|||
|
|||
#ifdef XSPICE |
|||
/*---- Fixed by SDB 5.2.2003 to enable XSPICE/tclspice integration -----*/ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
/*--------------------------- End of SDB fix -------------------------*/ |
|||
#endif |
|||
|
|||
DEV_DEFAULT |
|||
}, |
|||
|
|||
DEVparam : NUMD2param, |
|||
DEVmodParam : NUMD2mParam, |
|||
DEVload : NUMD2load, |
|||
DEVsetup : NUMD2setup, |
|||
DEVunsetup : NULL, |
|||
DEVpzSetup : NUMD2setup, |
|||
DEVtemperature: NUMD2temp, |
|||
DEVtrunc : NUMD2trunc, |
|||
DEVfindBranch : NULL, |
|||
DEVacLoad : NUMD2acLoad, |
|||
DEVaccept : NULL, |
|||
DEVdestroy : NUMD2destroy, |
|||
DEVmodDelete : NUMD2mDelete, |
|||
DEVdelete : NUMD2delete, |
|||
DEVsetic : NULL, |
|||
DEVask : NUMD2ask, |
|||
DEVmodAsk : NULL, |
|||
DEVpzLoad : NUMD2pzLoad, |
|||
DEVconvTest : NULL, |
|||
DEVsenSetup : NULL, |
|||
DEVsenLoad : NULL, |
|||
DEVsenUpdate : NULL, |
|||
DEVsenAcLoad : NULL, |
|||
DEVsenPrint : NULL, |
|||
DEVsenTrunc : NULL, |
|||
DEVdisto : NULL, |
|||
DEVnoise : NULL, |
|||
DEVdump : NUMD2dump, |
|||
DEVacct : NUMD2acct, |
|||
|
|||
DEVinstSize : &NUMD2iSize, |
|||
DEVmodSize : &NUMD2mSize |
|||
|
|||
}; |
|||
|
|||
|
|||
SPICEdev * |
|||
get_numd2_info(void) |
|||
{ |
|||
return &NUMD2info; |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
#ifndef _NUMD2INIT_H |
|||
#define _NUMD2INIT_H |
|||
|
|||
extern IFparm NUMD2pTable[ ]; |
|||
extern IFparm NUMD2mPTable[ ]; |
|||
extern char *NUMD2names[ ]; |
|||
extern int NUMD2pTSize; |
|||
extern int NUMD2mPTSize; |
|||
extern int NUMD2nSize; |
|||
extern int NUMD2iSize; |
|||
extern int NUMD2mSize; |
|||
|
|||
#endif |
|||
@ -0,0 +1,10 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
**********/ |
|||
|
|||
#ifndef DEV_NUMD2 |
|||
#define DEV_NUMD2 |
|||
|
|||
extern SPICEdev *get_numd2_info(void); |
|||
|
|||
#endif |
|||
@ -0,0 +1,30 @@ |
|||
## Process this file with automake to produce Makefile.in
|
|||
|
|||
noinst_LIBRARIES = libnumos.a |
|||
|
|||
libnumos_a_SOURCES = \
|
|||
numm.c \
|
|||
nummacld.c \
|
|||
nummask.c \
|
|||
numosdef.h \
|
|||
nummdel.c \
|
|||
nummdest.c \
|
|||
nummdump.c \
|
|||
numosext.h \
|
|||
numosinit.c \
|
|||
numosinit.h \
|
|||
numositf.h \
|
|||
nummload.c \
|
|||
nummmdel.c \
|
|||
nummmpar.c \
|
|||
nummparm.c \
|
|||
nummpzld.c \
|
|||
nummset.c \
|
|||
nummtemp.c \
|
|||
nummtrun.c |
|||
|
|||
|
|||
|
|||
INCLUDES = -I$(top_srcdir)/src/include |
|||
|
|||
MAINTAINERCLEANFILES = Makefile.in |
|||
@ -0,0 +1,93 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "devdefs.h" |
|||
#include "numosdef.h" |
|||
#include "suffix.h" |
|||
|
|||
/* |
|||
* This file defines the 2d Numerical MOSFET data structures that are |
|||
* available to the next level(s) up the calling hierarchy |
|||
*/ |
|||
|
|||
IFparm NUMOSpTable[] = { /* parameters */ |
|||
IP("off", NUMOS_OFF, IF_FLAG, "Device initially off"), |
|||
IP("ic.file", NUMOS_IC_FILE, IF_STRING, "Initial condition file"), |
|||
IOP("area", NUMOS_AREA, IF_REAL, "Area factor"), |
|||
IOP("w", NUMOS_WIDTH, IF_REAL, "Width factor"), |
|||
IOP("l", NUMOS_LENGTH, IF_REAL, "Length factor"), |
|||
IP("save", NUMOS_PRINT, IF_REAL, "Save solutions"), |
|||
IP("print", NUMOS_PRINT, IF_REAL, "Print solutions"), |
|||
OP("g11", NUMOS_G11, IF_REAL, "Conductance"), |
|||
OP("c11", NUMOS_C11, IF_REAL, "Capacitance"), |
|||
OP("y11", NUMOS_Y11, IF_COMPLEX, "Admittance"), |
|||
OP("g12", NUMOS_G12, IF_REAL, "Conductance"), |
|||
OP("c12", NUMOS_C12, IF_REAL, "Capacitance"), |
|||
OP("y12", NUMOS_Y12, IF_COMPLEX, "Admittance"), |
|||
OP("g13", NUMOS_G13, IF_REAL, "Conductance"), |
|||
OP("c13", NUMOS_C13, IF_REAL, "Capacitance"), |
|||
OP("y13", NUMOS_Y13, IF_COMPLEX, "Admittance"), |
|||
OPU("g14", NUMOS_G14, IF_REAL, "Conductance"), |
|||
OPU("c14", NUMOS_C14, IF_REAL, "Capacitance"), |
|||
OPU("y14", NUMOS_Y14, IF_COMPLEX, "Admittance"), |
|||
OP("g21", NUMOS_G21, IF_REAL, "Conductance"), |
|||
OP("c21", NUMOS_C21, IF_REAL, "Capacitance"), |
|||
OP("y21", NUMOS_Y21, IF_COMPLEX, "Admittance"), |
|||
OP("g22", NUMOS_G22, IF_REAL, "Conductance"), |
|||
OP("c22", NUMOS_C22, IF_REAL, "Capacitance"), |
|||
OP("y22", NUMOS_Y22, IF_COMPLEX, "Admittance"), |
|||
OP("g23", NUMOS_G23, IF_REAL, "Conductance"), |
|||
OP("c23", NUMOS_C23, IF_REAL, "Capacitance"), |
|||
OP("y23", NUMOS_Y23, IF_COMPLEX, "Admittance"), |
|||
OPU("g24", NUMOS_G24, IF_REAL, "Conductance"), |
|||
OPU("c24", NUMOS_C24, IF_REAL, "Capacitance"), |
|||
OPU("y24", NUMOS_Y24, IF_COMPLEX, "Admittance"), |
|||
OP("g31", NUMOS_G31, IF_REAL, "Conductance"), |
|||
OP("c31", NUMOS_C31, IF_REAL, "Capacitance"), |
|||
OP("y31", NUMOS_Y31, IF_COMPLEX, "Admittance"), |
|||
OP("g32", NUMOS_G32, IF_REAL, "Conductance"), |
|||
OP("c32", NUMOS_C32, IF_REAL, "Capacitance"), |
|||
OP("y32", NUMOS_Y32, IF_COMPLEX, "Admittance"), |
|||
OP("g33", NUMOS_G33, IF_REAL, "Conductance"), |
|||
OP("c33", NUMOS_C33, IF_REAL, "Capacitance"), |
|||
OP("y33", NUMOS_Y33, IF_COMPLEX, "Admittance"), |
|||
OPU("g34", NUMOS_G34, IF_REAL, "Conductance"), |
|||
OPU("c34", NUMOS_C34, IF_REAL, "Capacitance"), |
|||
OPU("y34", NUMOS_Y34, IF_COMPLEX, "Admittance"), |
|||
OPU("g41", NUMOS_G41, IF_REAL, "Conductance"), |
|||
OPU("c41", NUMOS_C41, IF_REAL, "Capacitance"), |
|||
OPU("y41", NUMOS_Y41, IF_COMPLEX, "Admittance"), |
|||
OPU("g42", NUMOS_G42, IF_REAL, "Conductance"), |
|||
OPU("c42", NUMOS_C42, IF_REAL, "Capacitance"), |
|||
OPU("y42", NUMOS_Y42, IF_COMPLEX, "Admittance"), |
|||
OPU("g43", NUMOS_G43, IF_REAL, "Conductance"), |
|||
OPU("c43", NUMOS_C43, IF_REAL, "Capacitance"), |
|||
OPU("y43", NUMOS_Y43, IF_COMPLEX, "Admittance"), |
|||
OPU("g44", NUMOS_G44, IF_REAL, "Conductance"), |
|||
OPU("c44", NUMOS_C44, IF_REAL, "Capacitance"), |
|||
OPU("y44", NUMOS_Y44, IF_COMPLEX, "Admittance"), |
|||
IOP("temp", NUMOS_TEMP, IF_REAL, "Instance temperature") |
|||
}; |
|||
|
|||
IFparm NUMOSmPTable[] = { /* model parameters */ |
|||
/* numerical-device models no longer have parameters */ |
|||
/* one is left behind to keep the table from being empty */ |
|||
IP("numos", NUMOS_MOD_NUMOS, IF_FLAG, "Numerical MOSFET"), |
|||
}; |
|||
|
|||
char *NUMOSnames[] = { |
|||
"Drain", |
|||
"Gate", |
|||
"Source", |
|||
"Substrate" |
|||
}; |
|||
|
|||
int NUMOSnSize = NUMELEMS(NUMOSnames); |
|||
int NUMOSpTSize = NUMELEMS(NUMOSpTable); |
|||
int NUMOSmPTSize = NUMELEMS(NUMOSmPTable); |
|||
int NUMOSiSize = sizeof(NUMOSinstance); |
|||
int NUMOSmSize = sizeof(NUMOSmodel); |
|||
@ -0,0 +1,158 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* Function to load the COMPLEX circuit matrix using the small signal |
|||
* parameters saved during a previous DC operating point analysis. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "numosdef.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
#include "complex.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
|
|||
/* External Declarations */ |
|||
extern int TWOacDebug; |
|||
|
|||
int |
|||
NUMOSacLoad(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
register NUMOSmodel *model = (NUMOSmodel *) inModel; |
|||
register NUMOSinstance *inst; |
|||
struct mosAdmittances yAc; |
|||
double startTime; |
|||
|
|||
for (; model != NULL; model = model->NUMOSnextModel) { |
|||
FieldDepMobility = model->NUMOSmodels->MODLfieldDepMobility; |
|||
TransDepMobility = model->NUMOSmodels->MODLtransDepMobility; |
|||
SurfaceMobility = model->NUMOSmodels->MODLsurfaceMobility; |
|||
Srh = model->NUMOSmodels->MODLsrh; |
|||
Auger = model->NUMOSmodels->MODLauger; |
|||
AvalancheGen = model->NUMOSmodels->MODLavalancheGen; |
|||
OneCarrier = model->NUMOSmethods->METHoneCarrier; |
|||
AcAnalysisMethod = model->NUMOSmethods->METHacAnalysisMethod; |
|||
MobDeriv = model->NUMOSmethods->METHmobDeriv; |
|||
TWOacDebug = model->NUMOSoutputs->OUTPacDebug; |
|||
|
|||
for (inst = model->NUMOSinstances; inst != NULL; |
|||
inst = inst->NUMOSnextInstance) { |
|||
if (inst->NUMOSowner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NUMOSglobals)); |
|||
|
|||
model->NUMOSmethods->METHacAnalysisMethod = |
|||
NUMOSadmittance(inst->NUMOSpDevice, |
|||
ckt->CKTomega, &yAc); |
|||
|
|||
*(inst->NUMOSdrainDrainPtr) += yAc.yIdVdb.real; |
|||
*(inst->NUMOSdrainDrainPtr + 1) += yAc.yIdVdb.imag; |
|||
*(inst->NUMOSdrainSourcePtr) += yAc.yIdVsb.real; |
|||
*(inst->NUMOSdrainSourcePtr + 1) += yAc.yIdVsb.imag; |
|||
*(inst->NUMOSdrainGatePtr) += yAc.yIdVgb.real; |
|||
*(inst->NUMOSdrainGatePtr + 1) += yAc.yIdVgb.imag; |
|||
*(inst->NUMOSdrainBulkPtr) -= |
|||
yAc.yIdVdb.real + yAc.yIdVsb.real + yAc.yIdVgb.real; |
|||
*(inst->NUMOSdrainBulkPtr + 1) -= |
|||
yAc.yIdVdb.imag + yAc.yIdVsb.imag + yAc.yIdVgb.imag; |
|||
|
|||
*(inst->NUMOSsourceDrainPtr) += yAc.yIsVdb.real; |
|||
*(inst->NUMOSsourceDrainPtr + 1) += yAc.yIsVdb.imag; |
|||
*(inst->NUMOSsourceSourcePtr) += yAc.yIsVsb.real; |
|||
*(inst->NUMOSsourceSourcePtr + 1) += yAc.yIsVsb.imag; |
|||
*(inst->NUMOSsourceGatePtr) += yAc.yIsVgb.real; |
|||
*(inst->NUMOSsourceGatePtr + 1) += yAc.yIsVgb.imag; |
|||
*(inst->NUMOSsourceBulkPtr) -= |
|||
yAc.yIsVdb.real + yAc.yIsVsb.real + yAc.yIsVgb.real; |
|||
*(inst->NUMOSsourceBulkPtr + 1) -= |
|||
yAc.yIsVdb.imag + yAc.yIsVsb.imag + yAc.yIsVgb.imag; |
|||
|
|||
*(inst->NUMOSgateDrainPtr) += yAc.yIgVdb.real; |
|||
*(inst->NUMOSgateDrainPtr + 1) += yAc.yIgVdb.imag; |
|||
*(inst->NUMOSgateSourcePtr) += yAc.yIgVsb.real; |
|||
*(inst->NUMOSgateSourcePtr + 1) += yAc.yIgVsb.imag; |
|||
*(inst->NUMOSgateGatePtr) += yAc.yIgVgb.real; |
|||
*(inst->NUMOSgateGatePtr + 1) += yAc.yIgVgb.imag; |
|||
*(inst->NUMOSgateBulkPtr) -= |
|||
yAc.yIgVdb.real + yAc.yIgVsb.real + yAc.yIgVgb.real; |
|||
*(inst->NUMOSgateBulkPtr + 1) -= |
|||
yAc.yIgVdb.imag + yAc.yIgVsb.imag + yAc.yIgVgb.imag; |
|||
|
|||
*(inst->NUMOSbulkDrainPtr) -= |
|||
yAc.yIdVdb.real + yAc.yIsVdb.real + yAc.yIgVdb.real; |
|||
*(inst->NUMOSbulkDrainPtr + 1) -= |
|||
yAc.yIdVdb.imag + yAc.yIsVdb.imag + yAc.yIgVdb.imag; |
|||
*(inst->NUMOSbulkSourcePtr) -= |
|||
yAc.yIdVsb.real + yAc.yIsVsb.real + yAc.yIgVsb.real; |
|||
*(inst->NUMOSbulkSourcePtr + 1) -= |
|||
yAc.yIdVsb.imag + yAc.yIsVsb.imag + yAc.yIgVsb.imag; |
|||
*(inst->NUMOSbulkGatePtr) -= |
|||
yAc.yIdVgb.real + yAc.yIsVgb.real + yAc.yIgVgb.real; |
|||
*(inst->NUMOSbulkGatePtr + 1) -= |
|||
yAc.yIdVgb.imag + yAc.yIsVgb.imag + yAc.yIgVgb.imag; |
|||
*(inst->NUMOSbulkBulkPtr) += yAc.yIdVdb.real + yAc.yIdVsb.real + |
|||
yAc.yIdVgb.real + yAc.yIsVdb.real + |
|||
yAc.yIsVsb.real + yAc.yIsVgb.real + |
|||
yAc.yIgVdb.real + yAc.yIgVsb.real + |
|||
yAc.yIgVgb.real; |
|||
*(inst->NUMOSbulkBulkPtr + 1) -= yAc.yIdVdb.imag + yAc.yIdVsb.imag + |
|||
yAc.yIdVgb.imag + yAc.yIsVdb.imag + |
|||
yAc.yIsVsb.imag + yAc.yIsVgb.imag + |
|||
yAc.yIgVdb.imag + yAc.yIgVsb.imag + |
|||
yAc.yIgVgb.imag; |
|||
if (ckt->CKTomega != 0.0) { |
|||
inst->NUMOSc11 = yAc.yIdVdb.imag / ckt->CKTomega; |
|||
inst->NUMOSc12 = yAc.yIdVgb.imag / ckt->CKTomega; |
|||
inst->NUMOSc13 = yAc.yIdVsb.imag / ckt->CKTomega; |
|||
inst->NUMOSc21 = yAc.yIgVdb.imag / ckt->CKTomega; |
|||
inst->NUMOSc22 = yAc.yIgVgb.imag / ckt->CKTomega; |
|||
inst->NUMOSc23 = yAc.yIgVsb.imag / ckt->CKTomega; |
|||
inst->NUMOSc31 = yAc.yIsVdb.imag / ckt->CKTomega; |
|||
inst->NUMOSc32 = yAc.yIsVgb.imag / ckt->CKTomega; |
|||
inst->NUMOSc33 = yAc.yIsVsb.imag / ckt->CKTomega; |
|||
} else { |
|||
inst->NUMOSc11 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NUMOSc12 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NUMOSc13 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NUMOSc21 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NUMOSc22 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NUMOSc23 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NUMOSc31 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NUMOSc32 = 0.0; /* XXX What else can be done?! */ |
|||
inst->NUMOSc33 = 0.0; /* XXX What else can be done?! */ |
|||
} |
|||
inst->NUMOSy11r = yAc.yIdVdb.real; |
|||
inst->NUMOSy11i = yAc.yIdVdb.imag; |
|||
inst->NUMOSy12r = yAc.yIdVgb.real; |
|||
inst->NUMOSy12i = yAc.yIdVgb.imag; |
|||
inst->NUMOSy13r = yAc.yIdVsb.real; |
|||
inst->NUMOSy13i = yAc.yIdVsb.imag; |
|||
inst->NUMOSy21r = yAc.yIgVdb.real; |
|||
inst->NUMOSy21i = yAc.yIgVdb.imag; |
|||
inst->NUMOSy22r = yAc.yIgVgb.real; |
|||
inst->NUMOSy22i = yAc.yIgVgb.imag; |
|||
inst->NUMOSy23r = yAc.yIgVsb.real; |
|||
inst->NUMOSy23i = yAc.yIgVsb.imag; |
|||
inst->NUMOSy31r = yAc.yIsVdb.real; |
|||
inst->NUMOSy31i = yAc.yIsVdb.imag; |
|||
inst->NUMOSy32r = yAc.yIsVgb.real; |
|||
inst->NUMOSy32i = yAc.yIsVgb.imag; |
|||
inst->NUMOSy33r = yAc.yIsVsb.real; |
|||
inst->NUMOSy33i = yAc.yIsVsb.imag; |
|||
inst->NUMOSsmSigAvail = TRUE; |
|||
inst->NUMOSpDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,359 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Thomas L. Quarles |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "devdefs.h" |
|||
#include "numosdef.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
/* Externals Declarations */ |
|||
extern int NUMOSinitSmSig(NUMOSinstance *); |
|||
|
|||
/* ARGSUSED */ |
|||
int |
|||
NUMOSask(ckt, inInst, which, value, select) |
|||
CKTcircuit *ckt; |
|||
GENinstance *inInst; |
|||
int which; |
|||
IFvalue *value; |
|||
IFvalue *select; |
|||
{ |
|||
NUMOSinstance *inst = (NUMOSinstance *) inInst; |
|||
switch (which) { |
|||
case NUMOS_AREA: |
|||
value->rValue = inst->NUMOSarea; |
|||
return (OK); |
|||
case NUMOS_WIDTH: |
|||
value->rValue = inst->NUMOSwidth; |
|||
return (OK); |
|||
case NUMOS_LENGTH: |
|||
value->rValue = inst->NUMOSlength; |
|||
return (OK); |
|||
case NUMOS_TEMP: |
|||
value->rValue = inst->NUMOStemp - CONSTCtoK; |
|||
return (OK); |
|||
case NUMOS_G11: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIdDVdb); |
|||
return (OK); |
|||
case NUMOS_G12: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIdDVgb); |
|||
return (OK); |
|||
case NUMOS_G13: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIdDVsb); |
|||
return (OK); |
|||
case NUMOS_G14: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NUMOSdIdDVdb) |
|||
- *(ckt->CKTstate0 + inst->NUMOSdIdDVgb) |
|||
- *(ckt->CKTstate0 + inst->NUMOSdIdDVsb); |
|||
return (OK); |
|||
case NUMOS_G21: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIgDVdb); |
|||
return (OK); |
|||
case NUMOS_G22: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIgDVgb); |
|||
return (OK); |
|||
case NUMOS_G23: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIgDVsb); |
|||
return (OK); |
|||
case NUMOS_G24: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NUMOSdIgDVdb) |
|||
- *(ckt->CKTstate0 + inst->NUMOSdIgDVgb) |
|||
- *(ckt->CKTstate0 + inst->NUMOSdIgDVsb); |
|||
return (OK); |
|||
case NUMOS_G31: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIsDVdb); |
|||
return (OK); |
|||
case NUMOS_G32: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIsDVgb); |
|||
return (OK); |
|||
case NUMOS_G33: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIsDVsb); |
|||
return (OK); |
|||
case NUMOS_G34: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NUMOSdIsDVdb) |
|||
- *(ckt->CKTstate0 + inst->NUMOSdIsDVgb) |
|||
- *(ckt->CKTstate0 + inst->NUMOSdIsDVsb); |
|||
return (OK); |
|||
case NUMOS_G41: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NUMOSdIdDVdb) |
|||
- *(ckt->CKTstate0 + inst->NUMOSdIgDVdb) |
|||
- *(ckt->CKTstate0 + inst->NUMOSdIsDVdb); |
|||
return (OK); |
|||
case NUMOS_G42: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NUMOSdIdDVgb) |
|||
- *(ckt->CKTstate0 + inst->NUMOSdIgDVgb) |
|||
- *(ckt->CKTstate0 + inst->NUMOSdIsDVgb); |
|||
return (OK); |
|||
case NUMOS_G43: |
|||
value->rValue = -*(ckt->CKTstate0 + inst->NUMOSdIdDVsb) |
|||
- *(ckt->CKTstate0 + inst->NUMOSdIgDVsb) |
|||
- *(ckt->CKTstate0 + inst->NUMOSdIsDVsb); |
|||
return (OK); |
|||
case NUMOS_G44: |
|||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIdDVdb) |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIgDVdb) |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIsDVdb) |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIdDVgb) |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIgDVgb) |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIsDVgb) |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIdDVsb) |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIgDVsb) |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIsDVsb); |
|||
return (OK); |
|||
case NUMOS_C11: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMOSc11; |
|||
return (OK); |
|||
case NUMOS_C12: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMOSc12; |
|||
return (OK); |
|||
case NUMOS_C13: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMOSc13; |
|||
return (OK); |
|||
case NUMOS_C14: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NUMOSc11 - inst->NUMOSc12 - inst->NUMOSc13; |
|||
return (OK); |
|||
case NUMOS_C21: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMOSc21; |
|||
return (OK); |
|||
case NUMOS_C22: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMOSc22; |
|||
return (OK); |
|||
case NUMOS_C23: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMOSc23; |
|||
return (OK); |
|||
case NUMOS_C24: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NUMOSc21 - inst->NUMOSc22 - inst->NUMOSc23; |
|||
return (OK); |
|||
case NUMOS_C31: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMOSc31; |
|||
return (OK); |
|||
case NUMOS_C32: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMOSc32; |
|||
return (OK); |
|||
case NUMOS_C33: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMOSc33; |
|||
return (OK); |
|||
case NUMOS_C34: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NUMOSc31 - inst->NUMOSc32 - inst->NUMOSc33; |
|||
return (OK); |
|||
case NUMOS_C41: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NUMOSc11 - inst->NUMOSc21 - inst->NUMOSc31; |
|||
return (OK); |
|||
case NUMOS_C42: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NUMOSc12 - inst->NUMOSc22 - inst->NUMOSc32; |
|||
return (OK); |
|||
case NUMOS_C43: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = -inst->NUMOSc13 - inst->NUMOSc23 - inst->NUMOSc33; |
|||
return (OK); |
|||
case NUMOS_C44: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->rValue = inst->NUMOSc11 + inst->NUMOSc12 + inst->NUMOSc13 |
|||
+ inst->NUMOSc21 + inst->NUMOSc22 + inst->NUMOSc23 |
|||
+ inst->NUMOSc31 + inst->NUMOSc32 + inst->NUMOSc33; |
|||
return (OK); |
|||
case NUMOS_Y11: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMOSy11r; |
|||
value->cValue.imag = inst->NUMOSy11i; |
|||
return (OK); |
|||
case NUMOS_Y12: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMOSy12r; |
|||
value->cValue.imag = inst->NUMOSy12i; |
|||
return (OK); |
|||
case NUMOS_Y13: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMOSy13r; |
|||
value->cValue.imag = inst->NUMOSy13i; |
|||
return (OK); |
|||
case NUMOS_Y14: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NUMOSy11r - inst->NUMOSy11r - inst->NUMOSy11r; |
|||
value->cValue.imag = -inst->NUMOSy11i - inst->NUMOSy11i - inst->NUMOSy11i; |
|||
return (OK); |
|||
case NUMOS_Y21: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMOSy21r; |
|||
value->cValue.imag = inst->NUMOSy21i; |
|||
return (OK); |
|||
case NUMOS_Y22: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMOSy22r; |
|||
value->cValue.imag = inst->NUMOSy22i; |
|||
return (OK); |
|||
case NUMOS_Y23: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMOSy23r; |
|||
value->cValue.imag = inst->NUMOSy23i; |
|||
return (OK); |
|||
case NUMOS_Y24: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NUMOSy21r - inst->NUMOSy22r - inst->NUMOSy23r; |
|||
value->cValue.imag = -inst->NUMOSy21i - inst->NUMOSy22i - inst->NUMOSy23i; |
|||
return (OK); |
|||
case NUMOS_Y31: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMOSy31r; |
|||
value->cValue.imag = inst->NUMOSy31i; |
|||
return (OK); |
|||
case NUMOS_Y32: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMOSy32r; |
|||
value->cValue.imag = inst->NUMOSy32i; |
|||
return (OK); |
|||
case NUMOS_Y33: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMOSy33r; |
|||
value->cValue.imag = inst->NUMOSy33i; |
|||
return (OK); |
|||
case NUMOS_Y34: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NUMOSy31r - inst->NUMOSy32r - inst->NUMOSy33r; |
|||
value->cValue.imag = -inst->NUMOSy31i - inst->NUMOSy32i - inst->NUMOSy33i; |
|||
return (OK); |
|||
case NUMOS_Y41: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NUMOSy11r - inst->NUMOSy21r - inst->NUMOSy31r; |
|||
value->cValue.imag = -inst->NUMOSy11i - inst->NUMOSy21i - inst->NUMOSy31i; |
|||
return (OK); |
|||
case NUMOS_Y42: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NUMOSy12r - inst->NUMOSy22r - inst->NUMOSy32r; |
|||
value->cValue.imag = -inst->NUMOSy12i - inst->NUMOSy22i - inst->NUMOSy32i; |
|||
return (OK); |
|||
case NUMOS_Y43: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = -inst->NUMOSy13r - inst->NUMOSy23r - inst->NUMOSy33r; |
|||
value->cValue.imag = -inst->NUMOSy13i - inst->NUMOSy23i - inst->NUMOSy33i; |
|||
return (OK); |
|||
case NUMOS_Y44: |
|||
if (!inst->NUMOSsmSigAvail |
|||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) { |
|||
NUMOSinitSmSig(inst); |
|||
} |
|||
value->cValue.real = inst->NUMOSy11r + inst->NUMOSy21r + inst->NUMOSy31r |
|||
+ inst->NUMOSy12r + inst->NUMOSy22r + inst->NUMOSy32r |
|||
+ inst->NUMOSy13r + inst->NUMOSy23r + inst->NUMOSy33r; |
|||
value->cValue.imag = inst->NUMOSy11i + inst->NUMOSy21i + inst->NUMOSy31i |
|||
+ inst->NUMOSy12i + inst->NUMOSy22i + inst->NUMOSy32i |
|||
+ inst->NUMOSy13i + inst->NUMOSy23i + inst->NUMOSy33i; |
|||
return (OK); |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
/* NOTREACHED */ |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine deletes a NUMOS instance from the circuit and frees the |
|||
* storage it was using. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "numosdef.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NUMOSdelete(inModel, name, kill) |
|||
GENmodel *inModel; |
|||
IFuid name; |
|||
GENinstance **kill; |
|||
|
|||
{ |
|||
|
|||
NUMOSmodel *model = (NUMOSmodel *) inModel; |
|||
NUMOSinstance **fast = (NUMOSinstance **) kill; |
|||
NUMOSinstance **prev = NULL; |
|||
NUMOSinstance *inst; |
|||
|
|||
for (; model; model = model->NUMOSnextModel) { |
|||
prev = &(model->NUMOSinstances); |
|||
for (inst = *prev; inst; inst = *prev) { |
|||
if (inst->NUMOSname == name || (fast && inst == *fast)) { |
|||
*prev = inst->NUMOSnextInstance; |
|||
FREE(inst); |
|||
return (OK); |
|||
} |
|||
prev = &(inst->NUMOSnextInstance); |
|||
} |
|||
} |
|||
return (E_NODEV); |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine deletes all NUMOSs from the circuit and frees all storage |
|||
* they were using. The current implementation has memory leaks. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "numosdef.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "suffix.h" |
|||
|
|||
void |
|||
NUMOSdestroy(inModel) |
|||
GENmodel **inModel; |
|||
|
|||
{ |
|||
|
|||
NUMOSmodel **model = (NUMOSmodel **) inModel; |
|||
NUMOSmodel *mod, *nextMod; |
|||
NUMOSinstance *inst, *nextInst; |
|||
|
|||
for (mod = *model; mod;) { |
|||
for (inst = mod->NUMOSinstances; inst;) { |
|||
TWOdestroy(inst->NUMOSpDevice); |
|||
nextInst = inst->NUMOSnextInstance; |
|||
FREE(inst); |
|||
inst = nextInst; |
|||
} |
|||
nextMod = mod->NUMOSnextModel; |
|||
FREE(mod); |
|||
mod = nextMod; |
|||
} |
|||
*model = NULL; |
|||
} |
|||
@ -0,0 +1,179 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This is a simple routine to dump the internal device states. It produces |
|||
* states for .OP, .DC, & .TRAN simulations. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "numosdef.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
/* Forward Declarations */ |
|||
static void NUMOSputHeader(FILE *, CKTcircuit *, NUMOSinstance *); |
|||
|
|||
/* State Counter */ |
|||
static int state_numOP = 0; |
|||
static int state_numDC = 0; |
|||
static int state_numTR = 0; |
|||
|
|||
void |
|||
NUMOSdump(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
register NUMOSmodel *model = (NUMOSmodel *) inModel; |
|||
register NUMOSinstance *inst; |
|||
OUTPcard *output; |
|||
FILE *fpState; |
|||
char fileName[BSIZE_SP]; |
|||
char description[BSIZE_SP]; |
|||
char *prefix; |
|||
int *state_num; |
|||
int anyOutput = 0; |
|||
|
|||
if (ckt->CKTmode & MODEDCOP) { |
|||
prefix = "OP"; |
|||
state_num = &state_numOP; |
|||
sprintf(description, "..."); |
|||
} else if (ckt->CKTmode & MODEDCTRANCURVE) { |
|||
prefix = "DC"; |
|||
state_num = &state_numDC; |
|||
sprintf(description, "sweep = % e", ckt->CKTtime); |
|||
} else if (ckt->CKTmode & MODETRAN) { |
|||
prefix = "TR"; |
|||
state_num = &state_numTR; |
|||
sprintf(description, "time = % e", ckt->CKTtime); |
|||
} else { |
|||
/* Not a recognized CKT mode. */ |
|||
return; |
|||
} |
|||
|
|||
for (; model != NULL; model = model->NUMOSnextModel) { |
|||
output = model->NUMOSoutputs; |
|||
for (inst = model->NUMOSinstances; inst != NULL; |
|||
inst = inst->NUMOSnextInstance) { |
|||
if (inst->NUMOSowner != ARCHme) continue; |
|||
|
|||
if (inst->NUMOSprintGiven) { |
|||
if ((ckt->CKTmode & MODETRAN) && |
|||
((ckt->CKTstat->STATaccepted - 1) % inst->NUMOSprint != 0)) { |
|||
continue; |
|||
} |
|||
anyOutput = 1; |
|||
sprintf(fileName, "%s%s.%d.%s", output->OUTProotFile, prefix, |
|||
*state_num, inst->NUMOSname); |
|||
if (!(fpState = fopen(fileName, "w"))) { |
|||
perror(fileName); |
|||
} else { |
|||
NUMOSputHeader(fpState, ckt, inst); |
|||
TWOprnSolution(fpState, inst->NUMOSpDevice, |
|||
model->NUMOSoutputs); |
|||
fclose(fpState); |
|||
LOGmakeEntry(fileName, description); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if (anyOutput) { |
|||
(*state_num)++; |
|||
} |
|||
} |
|||
|
|||
#define NUMOSnumOutputs 10 |
|||
|
|||
static |
|||
void |
|||
NUMOSputHeader(file, ckt, inst) |
|||
FILE *file; |
|||
CKTcircuit *ckt; |
|||
NUMOSinstance *inst; |
|||
{ |
|||
char *reference; |
|||
double refVal = 0.0; |
|||
int numVars = NUMOSnumOutputs; |
|||
|
|||
if (ckt->CKTmode & MODEDCOP) { |
|||
reference = NULL; |
|||
} else if (ckt->CKTmode & MODEDCTRANCURVE) { |
|||
reference = "sweep"; |
|||
refVal = ckt->CKTtime; |
|||
numVars++; |
|||
} else if (ckt->CKTmode & MODETRAN) { |
|||
reference = "time"; |
|||
refVal = ckt->CKTtime; |
|||
numVars++; |
|||
} else { |
|||
reference = NULL; |
|||
} |
|||
fprintf(file, "Title: Device %s external state\n", inst->NUMOSname); |
|||
fprintf(file, "Plotname: Device Operating Point\n"); |
|||
fprintf(file, "Command: deftype v conductance S\n"); |
|||
fprintf(file, "Flags: real\n"); |
|||
fprintf(file, "No. Variables: %d\n", numVars); |
|||
fprintf(file, "No. Points: 1\n"); |
|||
numVars = 0; |
|||
fprintf(file, "Variables:\n"); |
|||
if (reference) { |
|||
fprintf(file, "\t%d %s unknown\n", numVars++, reference); |
|||
} |
|||
fprintf(file, "\t%d v14 voltage\n", numVars++); |
|||
fprintf(file, "\t%d v24 voltage\n", numVars++); |
|||
fprintf(file, "\t%d v34 voltage\n", numVars++); |
|||
fprintf(file, "\t%d i1 current\n", numVars++); |
|||
fprintf(file, "\t%d i2 current\n", numVars++); |
|||
fprintf(file, "\t%d i3 current\n", numVars++); |
|||
fprintf(file, "\t%d i4 current\n", numVars++); |
|||
fprintf(file, "\t%d g11 conductance\n", numVars++); |
|||
fprintf(file, "\t%d g12 conductance\n", numVars++); |
|||
fprintf(file, "\t%d g13 conductance\n", numVars++); |
|||
fprintf(file, "Values:\n0"); |
|||
if (reference) { |
|||
fprintf(file, "\t% e\n", refVal); |
|||
} |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSvdb)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSvgb)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSvsb)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSid)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSig)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSis)); |
|||
fprintf(file, "\t% e\n", -*(ckt->CKTstate0 + inst->NUMOSid) |
|||
- *(ckt->CKTstate0 + inst->NUMOSig) |
|||
- *(ckt->CKTstate0 + inst->NUMOSis)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSdIdDVdb)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSdIdDVgb)); |
|||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSdIdDVsb)); |
|||
} |
|||
|
|||
void |
|||
NUMOSacct(inModel, ckt, file) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
FILE *file; |
|||
{ |
|||
register NUMOSmodel *model = (NUMOSmodel *) inModel; |
|||
register NUMOSinstance *inst; |
|||
OUTPcard *output; |
|||
|
|||
for (; model != NULL; model = model->NUMOSnextModel) { |
|||
output = model->NUMOSoutputs; |
|||
for (inst = model->NUMOSinstances; inst != NULL; |
|||
inst = inst->NUMOSnextInstance) { |
|||
if (inst->NUMOSowner != ARCHme) continue; |
|||
|
|||
if (output->OUTPstats) { |
|||
TWOmemStats(file, inst->NUMOSpDevice); |
|||
TWOcpuStats(file, inst->NUMOSpDevice); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,639 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This is the function called each iteration to evaluate the 2d numerical |
|||
* MOSFETs in the circuit and load them into the matrix as appropriate |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "devdefs.h" |
|||
#include "cktdefs.h" |
|||
#include "numosdef.h" |
|||
#include "trandefs.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
|
|||
/* External Declarations */ |
|||
extern int TWOdcDebug; |
|||
extern int TWOtranDebug; |
|||
extern int TWOacDebug; |
|||
|
|||
/* Forward Declarations */ |
|||
|
|||
int NUMOSinitSmSig(NUMOSinstance *inst); |
|||
|
|||
int |
|||
NUMOSload(inModel, ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
register NUMOSmodel *model = (NUMOSmodel *) inModel; |
|||
register NUMOSinstance *inst; |
|||
register TWOdevice *pDevice; |
|||
double startTime, startTime2, totalTime, totalTime2; |
|||
double tol; |
|||
double xfact; |
|||
double id, is, ig; |
|||
double ideq, iseq, igeq; |
|||
double idhat = 0.0, ishat = 0.0, ighat = 0.0; |
|||
double delVdb, delVsb, delVgb; |
|||
double vdb, vsb, vgb; |
|||
struct mosConductances g; |
|||
int icheck; |
|||
int icheck1; |
|||
int i; |
|||
double deltaNorm[7]; |
|||
int devConverged = 0; |
|||
int numDevNonCon; |
|||
int deviceType; |
|||
int doInitSolve; |
|||
int doVoltPred; |
|||
char *initStateName; |
|||
|
|||
/* loop through all the models */ |
|||
for (; model != NULL; model = model->NUMOSnextModel) { |
|||
FieldDepMobility = model->NUMOSmodels->MODLfieldDepMobility; |
|||
TransDepMobility = model->NUMOSmodels->MODLtransDepMobility; |
|||
SurfaceMobility = model->NUMOSmodels->MODLsurfaceMobility; |
|||
Srh = model->NUMOSmodels->MODLsrh; |
|||
Auger = model->NUMOSmodels->MODLauger; |
|||
AvalancheGen = model->NUMOSmodels->MODLavalancheGen; |
|||
OneCarrier = model->NUMOSmethods->METHoneCarrier; |
|||
MobDeriv = model->NUMOSmethods->METHmobDeriv; |
|||
MaxIterations = model->NUMOSmethods->METHitLim; |
|||
TWOdcDebug = model->NUMOSoutputs->OUTPdcDebug; |
|||
TWOtranDebug = model->NUMOSoutputs->OUTPtranDebug; |
|||
TWOacDebug = model->NUMOSoutputs->OUTPacDebug; |
|||
deviceType = model->NUMOSoptions->OPTNdeviceType; |
|||
doVoltPred = model->NUMOSmethods->METHvoltPred; |
|||
|
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
/* compute normalized deltas and predictor coeff */ |
|||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) { |
|||
model->NUMOSpInfo->order = ckt->CKTorder; |
|||
model->NUMOSpInfo->method = ckt->CKTintegrateMethod; |
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NUMOSpInfo->intCoeff, deltaNorm); |
|||
computePredCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NUMOSpInfo->predCoeff, deltaNorm); |
|||
} |
|||
} else if (ckt->CKTmode & MODEINITTRAN) { |
|||
model->NUMOSpInfo->order = ckt->CKTorder; |
|||
model->NUMOSpInfo->method = ckt->CKTintegrateMethod; |
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, |
|||
model->NUMOSpInfo->intCoeff, deltaNorm); |
|||
} |
|||
/* loop through all the instances of the model */ |
|||
for (inst = model->NUMOSinstances; inst != NULL; |
|||
inst = inst->NUMOSnextInstance) { |
|||
if (inst->NUMOSowner != ARCHme) continue; |
|||
|
|||
pDevice = inst->NUMOSpDevice; |
|||
|
|||
totalTime = 0.0; |
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NUMOSglobals)); |
|||
|
|||
/* |
|||
* initialization |
|||
*/ |
|||
pDevice->devStates = ckt->CKTstates; |
|||
icheck = 1; |
|||
doInitSolve = FALSE; |
|||
initStateName = NULL; |
|||
if (ckt->CKTmode & MODEINITSMSIG) { |
|||
vdb = *(ckt->CKTstate0 + inst->NUMOSvdb); |
|||
vsb = *(ckt->CKTstate0 + inst->NUMOSvsb); |
|||
vgb = *(ckt->CKTstate0 + inst->NUMOSvgb); |
|||
delVdb = 0.0; |
|||
delVsb = 0.0; |
|||
delVgb = 0.0; |
|||
NUMOSsetBCs(pDevice, vdb, vsb, vgb); |
|||
} else if (ckt->CKTmode & MODEINITTRAN) { |
|||
*(ckt->CKTstate0 + inst->NUMOSvdb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSvdb); |
|||
*(ckt->CKTstate0 + inst->NUMOSvsb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSvsb); |
|||
*(ckt->CKTstate0 + inst->NUMOSvgb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSvgb); |
|||
vdb = *(ckt->CKTstate1 + inst->NUMOSvdb); |
|||
vsb = *(ckt->CKTstate1 + inst->NUMOSvsb); |
|||
vgb = *(ckt->CKTstate1 + inst->NUMOSvgb); |
|||
TWOsaveState(pDevice); |
|||
delVdb = 0.0; |
|||
delVsb = 0.0; |
|||
delVgb = 0.0; |
|||
} else if ((ckt->CKTmode & MODEINITJCT) && |
|||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) { |
|||
doInitSolve = TRUE; |
|||
initStateName = inst->NUMOSicFile; |
|||
vdb = 0.0; |
|||
vsb = 0.0; |
|||
vgb = 0.0; |
|||
delVdb = vdb; |
|||
delVsb = vsb; |
|||
delVgb = vgb; |
|||
} else if ((ckt->CKTmode & MODEINITJCT) && (inst->NUMOSoff == 0)) { |
|||
doInitSolve = TRUE; |
|||
initStateName = inst->NUMOSicFile; |
|||
if (deviceType == OPTN_BIPOLAR) { |
|||
/* d,g,s,b => c,b,e,s */ |
|||
vdb = 0.0; |
|||
vsb = -inst->NUMOStype * 1.0; |
|||
vgb = -inst->NUMOStype * (1.0 - 0.6); |
|||
} else if (deviceType == OPTN_JFET) { |
|||
vdb = inst->NUMOStype * 0.5; |
|||
vsb = 0.0; |
|||
vgb = 0.0; |
|||
} else { |
|||
vdb = inst->NUMOStype * 0.5; |
|||
vsb = 0.0; |
|||
vgb = inst->NUMOStype * 1.0; |
|||
} |
|||
delVdb = vdb; |
|||
delVsb = vsb; |
|||
delVgb = vgb; |
|||
} else if (ckt->CKTmode & MODEINITJCT) { |
|||
doInitSolve = TRUE; |
|||
vdb = 0.0; |
|||
vsb = 0.0; |
|||
vgb = 0.0; |
|||
delVdb = vdb; |
|||
delVsb = vsb; |
|||
delVgb = vgb; |
|||
} else if ((ckt->CKTmode & MODEINITFIX) && inst->NUMOSoff) { |
|||
vdb = 0.0; |
|||
vsb = 0.0; |
|||
vgb = 0.0; |
|||
delVdb = vdb; |
|||
delVsb = vsb; |
|||
delVgb = vgb; |
|||
} else { |
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
*(ckt->CKTstate0 + inst->NUMOSvdb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSvdb); |
|||
*(ckt->CKTstate0 + inst->NUMOSvsb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSvsb); |
|||
*(ckt->CKTstate0 + inst->NUMOSvgb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSvgb); |
|||
*(ckt->CKTstate0 + inst->NUMOSid) = |
|||
*(ckt->CKTstate1 + inst->NUMOSid); |
|||
*(ckt->CKTstate0 + inst->NUMOSis) = |
|||
*(ckt->CKTstate1 + inst->NUMOSis); |
|||
*(ckt->CKTstate0 + inst->NUMOSig) = |
|||
*(ckt->CKTstate1 + inst->NUMOSig); |
|||
*(ckt->CKTstate0 + inst->NUMOSdIdDVdb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSdIdDVdb); |
|||
*(ckt->CKTstate0 + inst->NUMOSdIdDVsb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSdIdDVsb); |
|||
*(ckt->CKTstate0 + inst->NUMOSdIdDVgb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSdIdDVgb); |
|||
*(ckt->CKTstate0 + inst->NUMOSdIsDVdb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSdIsDVdb); |
|||
*(ckt->CKTstate0 + inst->NUMOSdIsDVsb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSdIsDVsb); |
|||
*(ckt->CKTstate0 + inst->NUMOSdIsDVgb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSdIsDVgb); |
|||
*(ckt->CKTstate0 + inst->NUMOSdIgDVdb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSdIgDVdb); |
|||
*(ckt->CKTstate0 + inst->NUMOSdIgDVsb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSdIgDVsb); |
|||
*(ckt->CKTstate0 + inst->NUMOSdIgDVgb) = |
|||
*(ckt->CKTstate1 + inst->NUMOSdIgDVgb); |
|||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) { |
|||
/* no linear prediction on device voltages */ |
|||
vdb = *(ckt->CKTstate1 + inst->NUMOSvdb); |
|||
vsb = *(ckt->CKTstate1 + inst->NUMOSvsb); |
|||
vgb = *(ckt->CKTstate1 + inst->NUMOSvgb); |
|||
TWOpredict(pDevice, model->NUMOSpInfo); |
|||
} else { |
|||
if (doVoltPred) { |
|||
/* linear prediction */ |
|||
xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1]; |
|||
vdb = (1+xfact) * (*(ckt->CKTstate1 + inst->NUMOSvdb)) |
|||
- (xfact) * (*(ckt->CKTstate2 + inst->NUMOSvdb)); |
|||
vsb = (1+xfact) * (*(ckt->CKTstate1 + inst->NUMOSvsb)) |
|||
- (xfact) * (*(ckt->CKTstate2 + inst->NUMOSvsb)); |
|||
vgb = (1+xfact) * (*(ckt->CKTstate1 + inst->NUMOSvgb)) |
|||
- (xfact) * (*(ckt->CKTstate2 + inst->NUMOSvgb)); |
|||
} else { |
|||
vdb = *(ckt->CKTstate1 + inst->NUMOSvdb); |
|||
vsb = *(ckt->CKTstate1 + inst->NUMOSvsb); |
|||
vgb = *(ckt->CKTstate1 + inst->NUMOSvgb); |
|||
} |
|||
} |
|||
} else { |
|||
/* |
|||
* compute new nonlinear branch voltages |
|||
*/ |
|||
vdb = *(ckt->CKTrhsOld + inst->NUMOSdrainNode) |
|||
- *(ckt->CKTrhsOld + inst->NUMOSbulkNode); |
|||
vsb = *(ckt->CKTrhsOld + inst->NUMOSsourceNode) |
|||
- *(ckt->CKTrhsOld + inst->NUMOSbulkNode); |
|||
vgb = *(ckt->CKTrhsOld + inst->NUMOSgateNode) |
|||
- *(ckt->CKTrhsOld + inst->NUMOSbulkNode); |
|||
} |
|||
delVdb = vdb - *(ckt->CKTstate0 + inst->NUMOSvdb); |
|||
delVsb = vsb - *(ckt->CKTstate0 + inst->NUMOSvsb); |
|||
delVgb = vgb - *(ckt->CKTstate0 + inst->NUMOSvgb); |
|||
idhat = *(ckt->CKTstate0 + inst->NUMOSid) |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIdDVdb) * delVdb |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIdDVsb) * delVsb |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIdDVgb) * delVgb; |
|||
ishat = *(ckt->CKTstate0 + inst->NUMOSis) |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIsDVdb) * delVdb |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIsDVsb) * delVsb |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIsDVgb) * delVgb; |
|||
ighat = *(ckt->CKTstate0 + inst->NUMOSig) |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIgDVdb) * delVdb |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIgDVsb) * delVsb |
|||
+ *(ckt->CKTstate0 + inst->NUMOSdIgDVgb) * delVgb; |
|||
|
|||
|
|||
#ifndef NOBYPASS |
|||
/* |
|||
* bypass if solution has not changed |
|||
*/ |
|||
/* |
|||
* the following collections of if's would be just one if the average |
|||
* compiler could handle it, but many find the expression too |
|||
* complicated, thus the split. |
|||
*/ |
|||
if ((ckt->CKTbypass) && pDevice->converged && |
|||
(!(ckt->CKTmode & MODEINITPRED)) && |
|||
(fabs(delVdb) < (ckt->CKTreltol * MAX(fabs(vdb), |
|||
fabs(*(ckt->CKTstate0 + inst->NUMOSvdb))) + |
|||
ckt->CKTvoltTol))) |
|||
if ((fabs(delVsb) < ckt->CKTreltol * MAX(fabs(vsb), |
|||
fabs(*(ckt->CKTstate0 + inst->NUMOSvsb))) + |
|||
ckt->CKTvoltTol)) |
|||
if ((fabs(delVgb) < ckt->CKTreltol * MAX(fabs(vgb), |
|||
fabs(*(ckt->CKTstate0 + inst->NUMOSvgb))) + |
|||
ckt->CKTvoltTol)) |
|||
if ((fabs(idhat - *(ckt->CKTstate0 + inst->NUMOSid)) < |
|||
ckt->CKTreltol * MAX(fabs(idhat), |
|||
fabs(*(ckt->CKTstate0 + inst->NUMOSid))) + |
|||
ckt->CKTabstol)) |
|||
if ((fabs(ishat - *(ckt->CKTstate0 + inst->NUMOSis)) < |
|||
ckt->CKTreltol * MAX(fabs(ishat), |
|||
fabs(*(ckt->CKTstate0 + inst->NUMOSis))) + |
|||
ckt->CKTabstol)) |
|||
if ((fabs(ighat - *(ckt->CKTstate0 + inst->NUMOSig)) < |
|||
ckt->CKTreltol * MAX(fabs(ighat), |
|||
fabs(*(ckt->CKTstate0 + inst->NUMOSig))) + |
|||
ckt->CKTabstol)) { |
|||
/* |
|||
* bypassing.... |
|||
*/ |
|||
vdb = *(ckt->CKTstate0 + inst->NUMOSvdb); |
|||
vsb = *(ckt->CKTstate0 + inst->NUMOSvsb); |
|||
vgb = *(ckt->CKTstate0 + inst->NUMOSvgb); |
|||
id = *(ckt->CKTstate0 + inst->NUMOSid); |
|||
is = *(ckt->CKTstate0 + inst->NUMOSis); |
|||
ig = *(ckt->CKTstate0 + inst->NUMOSig); |
|||
g.dIdDVdb = *(ckt->CKTstate0 + inst->NUMOSdIdDVdb); |
|||
g.dIdDVsb = *(ckt->CKTstate0 + inst->NUMOSdIdDVsb); |
|||
g.dIdDVgb = *(ckt->CKTstate0 + inst->NUMOSdIdDVgb); |
|||
g.dIsDVdb = *(ckt->CKTstate0 + inst->NUMOSdIsDVdb); |
|||
g.dIsDVsb = *(ckt->CKTstate0 + inst->NUMOSdIsDVsb); |
|||
g.dIsDVgb = *(ckt->CKTstate0 + inst->NUMOSdIsDVgb); |
|||
g.dIgDVdb = *(ckt->CKTstate0 + inst->NUMOSdIgDVdb); |
|||
g.dIgDVsb = *(ckt->CKTstate0 + inst->NUMOSdIgDVsb); |
|||
g.dIgDVgb = *(ckt->CKTstate0 + inst->NUMOSdIgDVgb); |
|||
goto load; |
|||
} |
|||
#endif /* NOBYPASS */ |
|||
/* |
|||
* limit nonlinear branch voltages |
|||
*/ |
|||
icheck1 = 1; |
|||
if (deviceType == OPTN_BIPOLAR) { |
|||
double vbe, vbe0; |
|||
double vce, vce0; |
|||
|
|||
vdb = -inst->NUMOStype * limitJunctionVoltage(-inst->NUMOStype * vdb, |
|||
-inst->NUMOStype * *(ckt->CKTstate0 + inst->NUMOSvdb), &icheck); |
|||
vce = vdb - vsb; |
|||
vce0 = *(ckt->CKTstate0 + inst->NUMOSvdb) - |
|||
*(ckt->CKTstate0 + inst->NUMOSvsb); |
|||
vce = inst->NUMOStype * limitVce(inst->NUMOStype * vce, |
|||
inst->NUMOStype * vce0, &icheck1); |
|||
if (icheck1 == 1) |
|||
icheck = 1; |
|||
vsb = vdb - vce; |
|||
vbe = vgb - vsb; |
|||
vbe0 = *(ckt->CKTstate0 + inst->NUMOSvgb) - |
|||
*(ckt->CKTstate0 + inst->NUMOSvsb); |
|||
vbe = inst->NUMOStype * limitVbe(inst->NUMOStype * vbe, |
|||
inst->NUMOStype * vbe0, &icheck1); |
|||
if (icheck1 == 1) |
|||
icheck = 1; |
|||
vgb = vbe + vsb; |
|||
} else { |
|||
vdb = -inst->NUMOStype * limitJunctionVoltage(-inst->NUMOStype * vdb, |
|||
-inst->NUMOStype * *(ckt->CKTstate0 + inst->NUMOSvdb), &icheck); |
|||
vsb = -inst->NUMOStype * limitJunctionVoltage(-inst->NUMOStype * vsb, |
|||
-inst->NUMOStype * *(ckt->CKTstate0 + inst->NUMOSvsb), &icheck1); |
|||
if (icheck1 == 1) |
|||
icheck = 1; |
|||
vgb = inst->NUMOStype * limitVgb(inst->NUMOStype * vgb, |
|||
inst->NUMOStype * *(ckt->CKTstate0 + inst->NUMOSvgb), &icheck1); |
|||
if (icheck1 == 1) |
|||
icheck = 1; |
|||
} |
|||
delVdb = vdb - *(ckt->CKTstate0 + inst->NUMOSvdb); |
|||
delVsb = vsb - *(ckt->CKTstate0 + inst->NUMOSvsb); |
|||
delVgb = vgb - *(ckt->CKTstate0 + inst->NUMOSvgb); |
|||
NUMOSsetBCs(pDevice, vdb - delVdb, vsb - delVsb, vgb - delVgb); |
|||
} |
|||
|
|||
if (doInitSolve) { |
|||
if (TWOdcDebug) { |
|||
printVoltages(stdout, model->NUMOSmodName, inst->NUMOSname, |
|||
deviceType, 3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); |
|||
} |
|||
startTime2 = SPfrontEnd->IFseconds(); |
|||
TWOequilSolve(pDevice); |
|||
totalTime2 = SPfrontEnd->IFseconds() - startTime2; |
|||
pDevice->pStats->totalTime[STAT_SETUP] += totalTime2; |
|||
pDevice->pStats->totalTime[STAT_DC] -= totalTime2; |
|||
|
|||
TWObiasSolve(pDevice, MaxIterations, FALSE, NULL); |
|||
|
|||
*(ckt->CKTstate0 + inst->NUMOSvdb) = 0.0; |
|||
*(ckt->CKTstate0 + inst->NUMOSvsb) = 0.0; |
|||
*(ckt->CKTstate0 + inst->NUMOSvgb) = 0.0; |
|||
|
|||
if (initStateName != NULL) { |
|||
if (TWOreadState(pDevice, initStateName, 3, &vdb, &vgb, &vsb ) < 0) { |
|||
fprintf(stderr, |
|||
"NUMOSload: trouble reading state-file %s\n", initStateName); |
|||
} else { |
|||
NUMOSsetBCs(pDevice, vdb, vsb, vgb); |
|||
delVdb = delVsb = delVgb = 0.0; |
|||
} |
|||
} |
|||
} |
|||
/* |
|||
* determine dc current and derivatives using the numerical routines |
|||
*/ |
|||
if (ckt->CKTmode & (MODEDCOP | MODETRANOP | MODEDCTRANCURVE | MODEINITSMSIG)) { |
|||
numDevNonCon = 0; |
|||
inst->NUMOSc11 = inst->NUMOSy11r = inst->NUMOSy11i = 0.0; |
|||
inst->NUMOSc12 = inst->NUMOSy12r = inst->NUMOSy12i = 0.0; |
|||
inst->NUMOSc13 = inst->NUMOSy13r = inst->NUMOSy13i = 0.0; |
|||
inst->NUMOSc21 = inst->NUMOSy21r = inst->NUMOSy21i = 0.0; |
|||
inst->NUMOSc22 = inst->NUMOSy22r = inst->NUMOSy22i = 0.0; |
|||
inst->NUMOSc23 = inst->NUMOSy23r = inst->NUMOSy23i = 0.0; |
|||
inst->NUMOSc31 = inst->NUMOSy31r = inst->NUMOSy31i = 0.0; |
|||
inst->NUMOSc32 = inst->NUMOSy32r = inst->NUMOSy32i = 0.0; |
|||
inst->NUMOSc33 = inst->NUMOSy33r = inst->NUMOSy33i = 0.0; |
|||
inst->NUMOSsmSigAvail = FALSE; |
|||
devNonCon: |
|||
NUMOSproject(pDevice, delVdb, delVsb, delVgb); |
|||
if (TWOdcDebug) { |
|||
printVoltages(stdout, model->NUMOSmodName, inst->NUMOSname, |
|||
deviceType, 3, vdb, delVdb, vgb, delVgb, vsb, delVsb); |
|||
} |
|||
TWObiasSolve(pDevice, MaxIterations, FALSE, model->NUMOSpInfo); |
|||
|
|||
devConverged = pDevice->converged; |
|||
if (devConverged && finite(pDevice->rhsNorm)) { |
|||
/* compute the currents */ |
|||
NUMOScurrent(pDevice, FALSE, (double *) NULL, &id, &is, &ig); |
|||
NUMOSconductance(pDevice, FALSE, (double *) NULL, &g); |
|||
/* |
|||
* Add gmin to the gate conductance terms since they will be zero. |
|||
* XXX This messes up the gXY output values, but we choose not to |
|||
* correct this error, because it shouldn't cause practical problems. |
|||
*/ |
|||
g.dIgDVdb += ckt->CKTgmin; |
|||
g.dIgDVsb += ckt->CKTgmin; |
|||
g.dIgDVgb += ckt->CKTgmin; |
|||
|
|||
} else { |
|||
/* reduce the voltage step until converged */ |
|||
/* restore boundary nodes to previous potential */ |
|||
NUMOSsetBCs(pDevice, |
|||
vdb - delVdb, vsb - delVsb, vgb - delVgb); |
|||
TWOstoreInitialGuess(pDevice); |
|||
TWOresetJacobian(pDevice); |
|||
delVdb *= 0.5; |
|||
delVsb *= 0.5; |
|||
delVgb *= 0.5; |
|||
vdb = delVdb + *(ckt->CKTstate0 + inst->NUMOSvdb); |
|||
vsb = delVsb + *(ckt->CKTstate0 + inst->NUMOSvsb); |
|||
vgb = delVgb + *(ckt->CKTstate0 + inst->NUMOSvgb); |
|||
numDevNonCon++; |
|||
icheck = 1; |
|||
if (numDevNonCon > 10) { |
|||
printVoltages(stderr, model->NUMOSmodName, inst->NUMOSname, |
|||
deviceType, 3, vdb, delVdb, vgb, delVgb, vsb, delVsb); |
|||
fprintf(stderr, "*** Non-convergence during load ***\n"); |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
return (E_BADMATRIX); |
|||
} else { |
|||
goto devNonCon; |
|||
} |
|||
} |
|||
} |
|||
if ((ckt->CKTmode & (MODETRAN | MODEAC)) || |
|||
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) || |
|||
(ckt->CKTmode & MODEINITSMSIG)) { |
|||
/* |
|||
* store small-signal parameters |
|||
*/ |
|||
if ((!(ckt->CKTmode & MODETRANOP)) || |
|||
(!(ckt->CKTmode & MODEUIC))) { |
|||
if (ckt->CKTmode & MODEINITSMSIG) { |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
startTime2 = SPfrontEnd->IFseconds(); |
|||
NUMOSinitSmSig(inst); |
|||
pDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime2; |
|||
continue; |
|||
} else { |
|||
inst->NUMOSsmSigAvail = FALSE; |
|||
} |
|||
/* |
|||
* transient analysis |
|||
*/ |
|||
if (ckt->CKTmode & MODEINITPRED) { |
|||
NUMOSsetBCs(pDevice, vdb, vsb, vgb); |
|||
TWOstoreInitialGuess(pDevice); |
|||
} else { |
|||
NUMOSupdate(pDevice, delVdb, delVsb, delVgb, TRUE); |
|||
} |
|||
if (TWOtranDebug) { |
|||
printVoltages(stdout, model->NUMOSmodName, inst->NUMOSname, |
|||
deviceType, 3, vdb, delVdb, vgb, delVgb, vsb, delVsb); |
|||
} |
|||
TWObiasSolve(pDevice, 0, TRUE, model->NUMOSpInfo); |
|||
if (!finite(pDevice->rhsNorm)) { |
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
return (E_BADMATRIX); |
|||
} |
|||
devConverged = TWOdeviceConverged(pDevice); |
|||
pDevice->converged = devConverged; |
|||
|
|||
/* compute the currents and conductances */ |
|||
NUMOScurrent(pDevice, TRUE, model->NUMOSpInfo->intCoeff, |
|||
&id, &is, &ig); |
|||
NUMOSconductance(pDevice, TRUE, |
|||
model->NUMOSpInfo->intCoeff, &g); |
|||
} |
|||
} |
|||
/* |
|||
* check convergence |
|||
*/ |
|||
if ((!(ckt->CKTmode & MODEINITFIX)) || (!(inst->NUMOSoff))) { |
|||
if (icheck == 1 || !devConverged) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} else { |
|||
tol = ckt->CKTreltol * MAX(fabs(idhat), fabs(id)) + ckt->CKTabstol; |
|||
if (fabs(idhat - id) > tol) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} else { |
|||
tol = ckt->CKTreltol * MAX(fabs(ishat), fabs(is)) + |
|||
ckt->CKTabstol; |
|||
if (fabs(ishat - is) > tol) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} else { |
|||
tol = ckt->CKTreltol * MAX(fabs(ighat), fabs(ig)) + |
|||
ckt->CKTabstol; |
|||
if (fabs(ighat - ig) > tol) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) inst; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
*(ckt->CKTstate0 + inst->NUMOSvdb) = vdb; |
|||
*(ckt->CKTstate0 + inst->NUMOSvsb) = vsb; |
|||
*(ckt->CKTstate0 + inst->NUMOSvgb) = vgb; |
|||
*(ckt->CKTstate0 + inst->NUMOSid) = id; |
|||
*(ckt->CKTstate0 + inst->NUMOSis) = is; |
|||
*(ckt->CKTstate0 + inst->NUMOSig) = ig; |
|||
*(ckt->CKTstate0 + inst->NUMOSdIdDVdb) = g.dIdDVdb; |
|||
*(ckt->CKTstate0 + inst->NUMOSdIdDVsb) = g.dIdDVsb; |
|||
*(ckt->CKTstate0 + inst->NUMOSdIdDVgb) = g.dIdDVgb; |
|||
*(ckt->CKTstate0 + inst->NUMOSdIsDVdb) = g.dIsDVdb; |
|||
*(ckt->CKTstate0 + inst->NUMOSdIsDVsb) = g.dIsDVsb; |
|||
*(ckt->CKTstate0 + inst->NUMOSdIsDVgb) = g.dIsDVgb; |
|||
*(ckt->CKTstate0 + inst->NUMOSdIgDVdb) = g.dIgDVdb; |
|||
*(ckt->CKTstate0 + inst->NUMOSdIgDVsb) = g.dIgDVsb; |
|||
*(ckt->CKTstate0 + inst->NUMOSdIgDVgb) = g.dIgDVgb; |
|||
|
|||
load: |
|||
/* |
|||
* load current excitation vector |
|||
*/ |
|||
|
|||
ideq = id - g.dIdDVdb * vdb - g.dIdDVsb * vsb - g.dIdDVgb * vgb; |
|||
iseq = is - g.dIsDVdb * vdb - g.dIsDVsb * vsb - g.dIsDVgb * vgb; |
|||
igeq = ig - g.dIgDVdb * vdb - g.dIgDVsb * vsb - g.dIgDVgb * vgb; |
|||
*(ckt->CKTrhs + inst->NUMOSdrainNode) -= ideq; |
|||
*(ckt->CKTrhs + inst->NUMOSsourceNode) -= iseq; |
|||
*(ckt->CKTrhs + inst->NUMOSgateNode) -= igeq; |
|||
*(ckt->CKTrhs + inst->NUMOSbulkNode) += ideq + iseq + igeq; |
|||
/* |
|||
* load y matrix |
|||
*/ |
|||
|
|||
*(inst->NUMOSdrainDrainPtr) += g.dIdDVdb; |
|||
*(inst->NUMOSdrainSourcePtr) += g.dIdDVsb; |
|||
*(inst->NUMOSdrainGatePtr) += g.dIdDVgb; |
|||
*(inst->NUMOSdrainBulkPtr) -= g.dIdDVdb + g.dIdDVsb + g.dIdDVgb; |
|||
|
|||
*(inst->NUMOSsourceDrainPtr) += g.dIsDVdb; |
|||
*(inst->NUMOSsourceSourcePtr) += g.dIsDVsb; |
|||
*(inst->NUMOSsourceGatePtr) += g.dIsDVgb; |
|||
*(inst->NUMOSsourceBulkPtr) -= g.dIsDVdb + g.dIsDVsb + g.dIsDVgb; |
|||
|
|||
*(inst->NUMOSgateDrainPtr) += g.dIgDVdb; |
|||
*(inst->NUMOSgateSourcePtr) += g.dIgDVsb; |
|||
*(inst->NUMOSgateGatePtr) += g.dIgDVgb; |
|||
*(inst->NUMOSgateBulkPtr) -= g.dIgDVdb + g.dIgDVsb + g.dIgDVgb; |
|||
|
|||
*(inst->NUMOSbulkDrainPtr) -= g.dIdDVdb + g.dIsDVdb + g.dIgDVdb; |
|||
*(inst->NUMOSbulkSourcePtr) -= g.dIdDVsb + g.dIsDVsb + g.dIgDVsb; |
|||
*(inst->NUMOSbulkGatePtr) -= g.dIdDVgb + g.dIsDVgb + g.dIgDVgb; |
|||
*(inst->NUMOSbulkBulkPtr) += g.dIdDVdb + g.dIdDVsb + g.dIdDVgb |
|||
+ g.dIsDVdb + g.dIsDVsb + g.dIsDVgb |
|||
+ g.dIgDVdb + g.dIgDVsb + g.dIgDVgb; |
|||
|
|||
totalTime += SPfrontEnd->IFseconds() - startTime; |
|||
if (ckt->CKTmode & MODETRAN) { |
|||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime; |
|||
} else { |
|||
pDevice->pStats->totalTime[STAT_DC] += totalTime; |
|||
} |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
|
|||
int |
|||
NUMOSinitSmSig(inst) |
|||
NUMOSinstance *inst; |
|||
{ |
|||
struct mosAdmittances yAc; |
|||
double omega = inst->NUMOSmodPtr->NUMOSmethods->METHomega; |
|||
|
|||
AcAnalysisMethod = SOR_ONLY; |
|||
(void) NUMOSadmittance(inst->NUMOSpDevice, omega, &yAc); |
|||
inst->NUMOSc11 = yAc.yIdVdb.imag / omega; |
|||
inst->NUMOSc12 = yAc.yIdVgb.imag / omega; |
|||
inst->NUMOSc13 = yAc.yIdVsb.imag / omega; |
|||
inst->NUMOSc21 = yAc.yIgVdb.imag / omega; |
|||
inst->NUMOSc22 = yAc.yIgVgb.imag / omega; |
|||
inst->NUMOSc23 = yAc.yIgVsb.imag / omega; |
|||
inst->NUMOSc31 = yAc.yIsVdb.imag / omega; |
|||
inst->NUMOSc32 = yAc.yIsVgb.imag / omega; |
|||
inst->NUMOSc33 = yAc.yIsVsb.imag / omega; |
|||
inst->NUMOSy11r = yAc.yIdVdb.real; |
|||
inst->NUMOSy11i = yAc.yIdVdb.imag; |
|||
inst->NUMOSy12r = yAc.yIdVgb.real; |
|||
inst->NUMOSy12i = yAc.yIdVgb.imag; |
|||
inst->NUMOSy13r = yAc.yIdVsb.real; |
|||
inst->NUMOSy13i = yAc.yIdVsb.imag; |
|||
inst->NUMOSy21r = yAc.yIgVdb.real; |
|||
inst->NUMOSy21i = yAc.yIgVdb.imag; |
|||
inst->NUMOSy22r = yAc.yIgVgb.real; |
|||
inst->NUMOSy22i = yAc.yIgVgb.imag; |
|||
inst->NUMOSy23r = yAc.yIgVsb.real; |
|||
inst->NUMOSy23i = yAc.yIgVsb.imag; |
|||
inst->NUMOSy31r = yAc.yIsVdb.real; |
|||
inst->NUMOSy31i = yAc.yIsVdb.imag; |
|||
inst->NUMOSy32r = yAc.yIsVgb.real; |
|||
inst->NUMOSy32i = yAc.yIsVgb.imag; |
|||
inst->NUMOSy33r = yAc.yIsVsb.real; |
|||
inst->NUMOSy33i = yAc.yIsVsb.imag; |
|||
inst->NUMOSsmSigAvail = TRUE; |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine deletes a NUMOS model from the circuit and frees the storage |
|||
* it was using. returns an error if the model has instances |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "numosdef.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NUMOSmDelete(inModel, modname, kill) |
|||
GENmodel **inModel; |
|||
IFuid modname; |
|||
GENmodel *kill; |
|||
|
|||
{ |
|||
|
|||
NUMOSmodel **model = (NUMOSmodel **) inModel; |
|||
NUMOSmodel *modfast = (NUMOSmodel *) kill; |
|||
NUMOSmodel **oldmod; |
|||
oldmod = model; |
|||
for (; *model; model = &((*model)->NUMOSnextModel)) { |
|||
if ((*model)->NUMOSmodName == modname || |
|||
(modfast && *model == modfast)) |
|||
goto delgot; |
|||
oldmod = model; |
|||
} |
|||
return (E_NOMOD); |
|||
|
|||
delgot: |
|||
if ((*model)->NUMOSinstances) |
|||
return (E_NOTEMPTY); |
|||
*oldmod = (*model)->NUMOSnextModel; /* cut deleted device out of list */ |
|||
FREE(*model); |
|||
return (OK); |
|||
|
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine sets model parameters for NUMOSs in the circuit. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "numosdef.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NUMOSmParam(param, value, inModel) |
|||
int param; |
|||
IFvalue *value; |
|||
GENmodel *inModel; |
|||
{ |
|||
switch (param) { |
|||
case NUMOS_MOD_NUMOS: |
|||
/* no action - already know it is a 2d-numerical MOS, but this */ |
|||
/* makes life easier for spice-2 like parsers */ |
|||
break; |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine sets instance parameters for NUMOSs in the circuit. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "numosdef.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
NUMOSparam(param, value, inInst, select) |
|||
int param; |
|||
IFvalue *value; |
|||
GENinstance *inInst; |
|||
IFvalue *select; |
|||
{ |
|||
register NUMOSinstance *inst = (NUMOSinstance *) inInst; |
|||
switch (param) { |
|||
case NUMOS_AREA: |
|||
inst->NUMOSarea = value->rValue; |
|||
inst->NUMOSareaGiven = TRUE; |
|||
break; |
|||
case NUMOS_WIDTH: |
|||
inst->NUMOSwidth = value->rValue; |
|||
inst->NUMOSwidthGiven = TRUE; |
|||
break; |
|||
case NUMOS_LENGTH: |
|||
inst->NUMOSlength = value->rValue; |
|||
inst->NUMOSlengthGiven = TRUE; |
|||
break; |
|||
case NUMOS_OFF: |
|||
inst->NUMOSoff = TRUE; |
|||
break; |
|||
case NUMOS_IC_FILE: |
|||
inst->NUMOSicFile = value->sValue; |
|||
inst->NUMOSicFileGiven = TRUE; |
|||
break; |
|||
case NUMOS_PRINT: |
|||
inst->NUMOSprint = value->rValue; |
|||
inst->NUMOSprintGiven = TRUE; |
|||
break; |
|||
case NUMOS_TEMP: |
|||
inst->NUMOStemp = value->rValue + CONSTCtoK; |
|||
inst->NUMOStempGiven = TRUE; |
|||
break; |
|||
default: |
|||
return (E_BADPARM); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,113 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "complex.h" |
|||
#include "numosdef.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
/* External Declarations */ |
|||
extern int TWOacDebug; |
|||
|
|||
|
|||
int |
|||
NUMOSpzLoad(inModel, ckt, s) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
SPcomplex *s; |
|||
|
|||
{ |
|||
register NUMOSmodel *model = (NUMOSmodel *) inModel; |
|||
register NUMOSinstance *inst; |
|||
struct mosAdmittances yAc; |
|||
double startTime; |
|||
|
|||
for (; model != NULL; model = model->NUMOSnextModel) { |
|||
FieldDepMobility = model->NUMOSmodels->MODLfieldDepMobility; |
|||
TransDepMobility = model->NUMOSmodels->MODLtransDepMobility; |
|||
SurfaceMobility = model->NUMOSmodels->MODLsurfaceMobility; |
|||
Srh = model->NUMOSmodels->MODLsrh; |
|||
Auger = model->NUMOSmodels->MODLauger; |
|||
AvalancheGen = model->NUMOSmodels->MODLavalancheGen; |
|||
OneCarrier = model->NUMOSmethods->METHoneCarrier; |
|||
AcAnalysisMethod = model->NUMOSmethods->METHacAnalysisMethod; |
|||
MobDeriv = model->NUMOSmethods->METHmobDeriv; |
|||
TWOacDebug = model->NUMOSoutputs->OUTPacDebug; |
|||
|
|||
for (inst = model->NUMOSinstances; inst != NULL; |
|||
inst = inst->NUMOSnextInstance) { |
|||
if (inst->NUMOSowner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
/* Get Temp.-Dep. Global Parameters */ |
|||
GLOBgetGlobals(&(inst->NUMOSglobals)); |
|||
|
|||
NUMOSys(inst->NUMOSpDevice, s, &yAc); |
|||
|
|||
*(inst->NUMOSdrainDrainPtr) += yAc.yIdVdb.real; |
|||
*(inst->NUMOSdrainDrainPtr + 1) += yAc.yIdVdb.imag; |
|||
*(inst->NUMOSdrainSourcePtr) += yAc.yIdVsb.real; |
|||
*(inst->NUMOSdrainSourcePtr + 1) += yAc.yIdVsb.imag; |
|||
*(inst->NUMOSdrainGatePtr) += yAc.yIdVgb.real; |
|||
*(inst->NUMOSdrainGatePtr + 1) += yAc.yIdVgb.imag; |
|||
*(inst->NUMOSdrainBulkPtr) -= |
|||
yAc.yIdVdb.real + yAc.yIdVsb.real + yAc.yIdVgb.real; |
|||
*(inst->NUMOSdrainBulkPtr + 1) -= |
|||
yAc.yIdVdb.imag + yAc.yIdVsb.imag + yAc.yIdVgb.imag; |
|||
|
|||
*(inst->NUMOSsourceDrainPtr) += yAc.yIsVdb.real; |
|||
*(inst->NUMOSsourceDrainPtr + 1) += yAc.yIsVdb.imag; |
|||
*(inst->NUMOSsourceSourcePtr) += yAc.yIsVsb.real; |
|||
*(inst->NUMOSsourceSourcePtr + 1) += yAc.yIsVsb.imag; |
|||
*(inst->NUMOSsourceGatePtr) += yAc.yIsVgb.real; |
|||
*(inst->NUMOSsourceGatePtr + 1) += yAc.yIsVgb.imag; |
|||
*(inst->NUMOSsourceBulkPtr) -= |
|||
yAc.yIsVdb.real + yAc.yIsVsb.real + yAc.yIsVgb.real; |
|||
*(inst->NUMOSsourceBulkPtr + 1) -= |
|||
yAc.yIsVdb.imag + yAc.yIsVsb.imag + yAc.yIsVgb.imag; |
|||
|
|||
*(inst->NUMOSgateDrainPtr) += yAc.yIgVdb.real; |
|||
*(inst->NUMOSgateDrainPtr + 1) += yAc.yIgVdb.imag; |
|||
*(inst->NUMOSgateSourcePtr) += yAc.yIgVsb.real; |
|||
*(inst->NUMOSgateSourcePtr + 1) += yAc.yIgVsb.imag; |
|||
*(inst->NUMOSgateGatePtr) += yAc.yIgVgb.real; |
|||
*(inst->NUMOSgateGatePtr + 1) += yAc.yIgVgb.imag; |
|||
*(inst->NUMOSgateBulkPtr) -= |
|||
yAc.yIgVdb.real + yAc.yIgVsb.real + yAc.yIgVgb.real; |
|||
*(inst->NUMOSgateBulkPtr + 1) -= |
|||
yAc.yIgVdb.imag + yAc.yIgVsb.imag + yAc.yIgVgb.imag; |
|||
|
|||
*(inst->NUMOSbulkDrainPtr) -= |
|||
yAc.yIdVdb.real + yAc.yIsVdb.real + yAc.yIgVdb.real; |
|||
*(inst->NUMOSbulkDrainPtr + 1) -= |
|||
yAc.yIdVdb.imag + yAc.yIsVdb.imag + yAc.yIgVdb.imag; |
|||
*(inst->NUMOSbulkSourcePtr) -= |
|||
yAc.yIdVsb.real + yAc.yIsVsb.real + yAc.yIgVsb.real; |
|||
*(inst->NUMOSbulkSourcePtr + 1) -= |
|||
yAc.yIdVsb.imag + yAc.yIsVsb.imag + yAc.yIgVsb.imag; |
|||
*(inst->NUMOSbulkGatePtr) -= |
|||
yAc.yIdVgb.real + yAc.yIsVgb.real + yAc.yIgVgb.real; |
|||
*(inst->NUMOSbulkGatePtr + 1) -= |
|||
yAc.yIdVgb.imag + yAc.yIsVgb.imag + yAc.yIgVgb.imag; |
|||
*(inst->NUMOSbulkBulkPtr) += |
|||
yAc.yIdVdb.real + yAc.yIdVsb.real + yAc.yIdVgb.real + |
|||
yAc.yIsVdb.real + yAc.yIsVsb.real + yAc.yIsVgb.real + |
|||
yAc.yIgVdb.real + yAc.yIgVsb.real + yAc.yIgVgb.real; |
|||
*(inst->NUMOSbulkBulkPtr + 1) -= |
|||
yAc.yIdVdb.imag + yAc.yIdVsb.imag + yAc.yIdVgb.imag + |
|||
yAc.yIsVdb.imag + yAc.yIsVsb.imag + yAc.yIsVgb.imag + |
|||
yAc.yIgVdb.imag + yAc.yIgVsb.imag + yAc.yIgVgb.imag; |
|||
|
|||
inst->NUMOSpDevice->pStats->totalTime[STAT_AC] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,278 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "smpdefs.h" |
|||
#include "numosdef.h" |
|||
#include "numconst.h" |
|||
#include "numenum.h" |
|||
#include "meshext.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "ciderinp.h" |
|||
#include "suffix.h" |
|||
|
|||
#define NIL(type) ((type *)0) |
|||
#define TSCALLOC(var, size, type)\ |
|||
if (size && (!(var =(type *)calloc(1, (unsigned)(size)*sizeof(type))))) {\ |
|||
return(E_NOMEM);\ |
|||
} |
|||
|
|||
int |
|||
NUMOSsetup(matrix, inModel, ckt, states) |
|||
register SMPmatrix *matrix; |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
int *states; |
|||
/* |
|||
* load the structure with those pointers needed later for fast matrix |
|||
* loading |
|||
*/ |
|||
{ |
|||
register NUMOSmodel *model = (NUMOSmodel *) inModel; |
|||
register NUMOSinstance *inst; |
|||
METHcard *methods; |
|||
MODLcard *models; |
|||
OPTNcard *options; |
|||
OUTPcard *outputs; |
|||
char *icFileName = NULL; |
|||
int nameLen; |
|||
int error, xIndex, yIndex; |
|||
int xMeshSize, yMeshSize; |
|||
TWOdevice *pDevice; |
|||
TWOcoord *xCoordList = NIL(TWOcoord); |
|||
TWOcoord *yCoordList = NIL(TWOcoord); |
|||
TWOdomain *domainList = NIL(TWOdomain); |
|||
TWOelectrode *electrodeList = NIL(TWOelectrode); |
|||
TWOmaterial *pM, *pMaterial = NIL(TWOmaterial), *materialList = NIL(TWOmaterial); |
|||
DOPprofile *profileList = NIL(DOPprofile); |
|||
DOPtable *dopTableList = NIL(DOPtable); |
|||
double startTime; |
|||
|
|||
/* loop through all the models */ |
|||
for (; model != NULL; model = model->NUMOSnextModel) { |
|||
if (!model->NUMOSpInfo) { |
|||
TSCALLOC(model->NUMOSpInfo, 1, TWOtranInfo); |
|||
} |
|||
methods = model->NUMOSmethods; |
|||
if (!methods) { |
|||
TSCALLOC(methods, 1, METHcard); |
|||
model->NUMOSmethods = methods; |
|||
} |
|||
models = model->NUMOSmodels; |
|||
if (!models) { |
|||
TSCALLOC(models, 1, MODLcard); |
|||
model->NUMOSmodels = models; |
|||
} |
|||
options = model->NUMOSoptions; |
|||
if (!options) { |
|||
TSCALLOC(options, 1, OPTNcard); |
|||
model->NUMOSoptions = options; |
|||
} |
|||
outputs = model->NUMOSoutputs; |
|||
if (!outputs) { |
|||
TSCALLOC(outputs, 1, OUTPcard); |
|||
model->NUMOSoutputs = outputs; |
|||
} |
|||
if (!methods->METHvoltPredGiven) { |
|||
methods->METHvoltPred = FALSE; |
|||
} |
|||
if (!methods->METHmobDerivGiven) { |
|||
methods->METHmobDeriv = TRUE; |
|||
} |
|||
if (!methods->METHoneCarrierGiven) { |
|||
methods->METHoneCarrier = FALSE; |
|||
} |
|||
if (!methods->METHacAnalysisMethodGiven) { |
|||
methods->METHacAnalysisMethod = SOR; |
|||
} |
|||
if (!methods->METHdabstolGiven) { |
|||
methods->METHdabstol = DABSTOL2D; |
|||
} |
|||
if (!methods->METHdreltolGiven) { |
|||
methods->METHdreltol = ckt->CKTreltol; |
|||
} |
|||
if (!methods->METHitLimGiven) { |
|||
methods->METHitLim = 50; |
|||
} |
|||
if (!methods->METHomegaGiven || methods->METHomega <= 0.0) { |
|||
methods->METHomega = 2.0 * M_PI /* radians/sec */ ; |
|||
} |
|||
if (!options->OPTNdefaGiven || options->OPTNdefa <= 0.0) { |
|||
options->OPTNdefa = 1.0e4 /* cm^2 */ ; |
|||
} |
|||
if (!options->OPTNdeflGiven || options->OPTNdefl <= 0.0) { |
|||
options->OPTNdefl = 1.0e2 /* cm */ ; |
|||
} |
|||
if (!options->OPTNdefwGiven && options->OPTNdefaGiven) { |
|||
options->OPTNdefw = options->OPTNdefa / options->OPTNdefl; |
|||
} else if (!options->OPTNdefwGiven || options->OPTNdefw <= 0.0) { |
|||
options->OPTNdefw = 1.0e2 /* cm */ ; |
|||
} |
|||
if (!options->OPTNdeviceTypeGiven) { |
|||
options->OPTNdeviceType = OPTN_MOSFET; |
|||
} |
|||
if (!options->OPTNicFileGiven) { |
|||
options->OPTNicFile = NULL; |
|||
options->OPTNunique = FALSE; /* Can't form a unique name. */ |
|||
} |
|||
if (!options->OPTNuniqueGiven) { |
|||
options->OPTNunique = FALSE; |
|||
} |
|||
OneCarrier = methods->METHoneCarrier; |
|||
|
|||
/* Set up the rest of the card lists */ |
|||
if ((error = MODLsetup(model->NUMOSmodels))) |
|||
return (error); |
|||
BandGapNarrowing = models->MODLbandGapNarrowing; |
|||
ConcDepLifetime = models->MODLconcDepLifetime; |
|||
TempDepMobility = models->MODLtempDepMobility; |
|||
ConcDepMobility = models->MODLconcDepMobility; |
|||
SurfaceMobility = models->MODLsurfaceMobility; |
|||
|
|||
if ((error = OUTPsetup(model->NUMOSoutputs))) |
|||
return (error); |
|||
if ((error = MATLsetup(model->NUMOSmaterials, &materialList))) |
|||
return (error); |
|||
if ((error = MOBsetup(model->NUMOSmobility, materialList))) |
|||
return (error); |
|||
if ((error = MESHsetup('x', model->NUMOSxMeshes, &xCoordList, &xMeshSize))) |
|||
return (error); |
|||
if ((error = MESHsetup('y', model->NUMOSyMeshes, &yCoordList, &yMeshSize))) |
|||
return (error); |
|||
if ((error = DOMNsetup(model->NUMOSdomains, &domainList, |
|||
xCoordList, yCoordList, materialList))) |
|||
return (error); |
|||
if ((error = BDRYsetup(model->NUMOSboundaries, |
|||
xCoordList, yCoordList, domainList))) |
|||
return (error); |
|||
if ((error = ELCTsetup(model->NUMOSelectrodes, &electrodeList, |
|||
xCoordList, yCoordList))) |
|||
return (error); |
|||
/* Make sure electrodes are OK. */ |
|||
checkElectrodes(electrodeList, 4); /* NUMOS has 4 electrodes */ |
|||
|
|||
if ((error = CONTsetup(model->NUMOScontacts, electrodeList))) |
|||
return (error); |
|||
if ((error = DOPsetup(model->NUMOSdopings, &profileList, |
|||
&dopTableList, xCoordList, yCoordList))) |
|||
return (error); |
|||
model->NUMOSmatlInfo = materialList; |
|||
model->NUMOSprofiles = profileList; |
|||
model->NUMOSdopTables = dopTableList; |
|||
|
|||
/* loop through all the instances of the model */ |
|||
for (inst = model->NUMOSinstances; inst != NULL; |
|||
inst = inst->NUMOSnextInstance) { |
|||
if (inst->NUMOSowner != ARCHme) goto matrixpointers; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
if (!inst->NUMOSprintGiven) { |
|||
inst->NUMOSprint = 0; |
|||
} else if (inst->NUMOSprint <= 0) { |
|||
inst->NUMOSprint = 1; |
|||
} |
|||
if (!inst->NUMOSicFileGiven) { |
|||
if (options->OPTNunique) { |
|||
nameLen = strlen(options->OPTNicFile) + strlen(inst->NUMOSname) + 1; |
|||
TSCALLOC(icFileName, nameLen+1, char); |
|||
sprintf(icFileName, "%s.%s", options->OPTNicFile, inst->NUMOSname); |
|||
icFileName[nameLen] = '\0'; |
|||
inst->NUMOSicFile = icFileName; |
|||
} else if (options->OPTNicFile != NULL) { |
|||
nameLen = strlen(options->OPTNicFile); |
|||
TSCALLOC(icFileName, nameLen+1, char); |
|||
icFileName = strcpy(icFileName, options->OPTNicFile); |
|||
inst->NUMOSicFile = icFileName; |
|||
} else { |
|||
inst->NUMOSicFile = NULL; |
|||
} |
|||
} |
|||
inst->NUMOSstate = *states; |
|||
*states += NUMOSnumStates; |
|||
|
|||
if (!inst->NUMOSpDevice) { |
|||
/* Assign the mesh info to each instance. */ |
|||
TSCALLOC(pDevice, 1, TWOdevice); |
|||
TSCALLOC(pDevice->pStats, 1, TWOstats); |
|||
pDevice->name = inst->NUMOSname; |
|||
pDevice->solverType = SLV_NONE; |
|||
pDevice->numXNodes = xMeshSize; |
|||
pDevice->numYNodes = yMeshSize; |
|||
pDevice->xScale = MESHmkArray(xCoordList, xMeshSize); |
|||
pDevice->yScale = MESHmkArray(yCoordList, yMeshSize); |
|||
pDevice->abstol = methods->METHdabstol; |
|||
pDevice->reltol = methods->METHdreltol; |
|||
TSCALLOC(pDevice->elemArray, pDevice->numXNodes, TWOelem **); |
|||
for (xIndex = 1; xIndex < pDevice->numXNodes; xIndex++) { |
|||
TSCALLOC(pDevice->elemArray[xIndex], pDevice->numYNodes, TWOelem *); |
|||
} |
|||
|
|||
/* Create a copy of material data that can change with temperature. */ |
|||
pDevice->pMaterials = NIL(TWOmaterial); |
|||
for (pM = materialList; pM != NIL(TWOmaterial); pM = pM->next) { |
|||
if (pDevice->pMaterials == NIL(TWOmaterial)) { |
|||
TSCALLOC(pMaterial, 1, TWOmaterial); |
|||
pDevice->pMaterials = pMaterial; |
|||
} else { |
|||
TSCALLOC(pMaterial->next, 1, TWOmaterial); |
|||
pMaterial = pMaterial->next; |
|||
} |
|||
/* Copy everything, then fix the incorrect pointer. */ |
|||
bcopy((char *) pM, (char *) pMaterial, sizeof(TWOmaterial)); |
|||
pMaterial->next = NIL(TWOmaterial); |
|||
} |
|||
|
|||
/* Generate the mesh structure for the device. */ |
|||
TWObuildMesh(pDevice, domainList, electrodeList, pDevice->pMaterials); |
|||
|
|||
/* Store the device info in the instance. */ |
|||
inst->NUMOSpDevice = pDevice; |
|||
} |
|||
/* Now update the state pointers. */ |
|||
TWOgetStatePointers(inst->NUMOSpDevice, states); |
|||
|
|||
/* Wipe out statistics from previous runs (if any). */ |
|||
bzero((char *) inst->NUMOSpDevice->pStats, sizeof(TWOstats)); |
|||
|
|||
inst->NUMOSpDevice->pStats->totalTime[STAT_SETUP] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
|
|||
/* macro to make elements with built in test for out of memory */ |
|||
#define TSTALLOC(ptr,first,second) \ |
|||
if ((inst->ptr = SMPmakeElt(matrix,inst->first,inst->second))==(double *)NULL){\ |
|||
return(E_NOMEM);\ |
|||
} |
|||
|
|||
matrixpointers: |
|||
TSTALLOC(NUMOSdrainDrainPtr, NUMOSdrainNode, NUMOSdrainNode) |
|||
TSTALLOC(NUMOSdrainSourcePtr, NUMOSdrainNode, NUMOSsourceNode) |
|||
TSTALLOC(NUMOSdrainGatePtr, NUMOSdrainNode, NUMOSgateNode) |
|||
TSTALLOC(NUMOSdrainBulkPtr, NUMOSdrainNode, NUMOSbulkNode) |
|||
TSTALLOC(NUMOSsourceDrainPtr, NUMOSsourceNode, NUMOSdrainNode) |
|||
TSTALLOC(NUMOSsourceSourcePtr, NUMOSsourceNode, NUMOSsourceNode) |
|||
TSTALLOC(NUMOSsourceGatePtr, NUMOSsourceNode, NUMOSgateNode) |
|||
TSTALLOC(NUMOSsourceBulkPtr, NUMOSsourceNode, NUMOSbulkNode) |
|||
TSTALLOC(NUMOSgateDrainPtr, NUMOSgateNode, NUMOSdrainNode) |
|||
TSTALLOC(NUMOSgateSourcePtr, NUMOSgateNode, NUMOSsourceNode) |
|||
TSTALLOC(NUMOSgateGatePtr, NUMOSgateNode, NUMOSgateNode) |
|||
TSTALLOC(NUMOSgateBulkPtr, NUMOSgateNode, NUMOSbulkNode) |
|||
TSTALLOC(NUMOSbulkDrainPtr, NUMOSbulkNode, NUMOSdrainNode) |
|||
TSTALLOC(NUMOSbulkSourcePtr, NUMOSbulkNode, NUMOSsourceNode) |
|||
TSTALLOC(NUMOSbulkGatePtr, NUMOSbulkNode, NUMOSgateNode) |
|||
TSTALLOC(NUMOSbulkBulkPtr, NUMOSbulkNode, NUMOSbulkNode) |
|||
} |
|||
/* Clean up lists */ |
|||
killCoordInfo(xCoordList); |
|||
killCoordInfo(yCoordList); |
|||
killDomainInfo(domainList); |
|||
killElectrodeInfo(electrodeList); |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,128 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "numosdef.h" |
|||
#include "numenum.h" |
|||
#include "carddefs.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
#define NIL(type) ((type *)0) |
|||
|
|||
int |
|||
NUMOStemp(inModel, ckt) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
/* |
|||
* perform the temperature update |
|||
*/ |
|||
{ |
|||
register NUMOSmodel *model = (NUMOSmodel *) inModel; |
|||
register NUMOSinstance *inst; |
|||
METHcard *methods; |
|||
MODLcard *models; |
|||
OPTNcard *options; |
|||
OUTPcard *outputs; |
|||
TWOmaterial *pM, *pMaterial, *pNextMaterial; |
|||
double startTime; |
|||
|
|||
|
|||
/* loop through all the models */ |
|||
for (; model != NULL; model = model->NUMOSnextModel) { |
|||
methods = model->NUMOSmethods; |
|||
models = model->NUMOSmodels; |
|||
options = model->NUMOSoptions; |
|||
outputs = model->NUMOSoutputs; |
|||
|
|||
if (!options->OPTNtnomGiven) { |
|||
options->OPTNtnom = ckt->CKTnomTemp; |
|||
} |
|||
for (pM = model->NUMOSmatlInfo; pM != NIL(TWOmaterial); |
|||
pM = pM->next) { |
|||
pM->tnom = options->OPTNtnom; |
|||
} |
|||
BandGapNarrowing = models->MODLbandGapNarrowing; |
|||
ConcDepLifetime = models->MODLconcDepLifetime; |
|||
TempDepMobility = models->MODLtempDepMobility; |
|||
ConcDepMobility = models->MODLconcDepMobility; |
|||
SurfaceMobility = models->MODLsurfaceMobility; |
|||
MatchingMobility = models->MODLmatchingMobility; |
|||
OneCarrier = methods->METHoneCarrier; |
|||
|
|||
for (inst = model->NUMOSinstances; inst != NULL; |
|||
inst = inst->NUMOSnextInstance) { |
|||
if (inst->NUMOSowner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
|
|||
if (!inst->NUMOStempGiven) { |
|||
inst->NUMOStemp = ckt->CKTtemp; |
|||
} |
|||
if (!inst->NUMOSareaGiven || inst->NUMOSarea <= 0.0) { |
|||
inst->NUMOSarea = 1.0; |
|||
} |
|||
if (!inst->NUMOSwidthGiven || inst->NUMOSwidth <= 0.0) { |
|||
inst->NUMOSwidth = 1.0; |
|||
} |
|||
inst->NUMOSpDevice->width = |
|||
inst->NUMOSarea * inst->NUMOSwidth * options->OPTNdefw; |
|||
|
|||
/* Compute and save globals for this instance. */ |
|||
GLOBcomputeGlobals(&(inst->NUMOSglobals), inst->NUMOStemp); |
|||
|
|||
/* Calculate new sets of material parameters. */ |
|||
pM = model->NUMOSmatlInfo; |
|||
pMaterial = inst->NUMOSpDevice->pMaterials; |
|||
for (; pM != NULL; pM = pM->next, pMaterial = pMaterial->next) { |
|||
|
|||
/* Copy everything, then fix the incorrect pointer. */ |
|||
pNextMaterial = pMaterial->next; |
|||
bcopy((char *) pM, (char *) pMaterial, sizeof(TWOmaterial)); |
|||
pMaterial->next = pNextMaterial; |
|||
|
|||
/* Now do the temperature dependence. */ |
|||
MATLtempDep(pMaterial, pMaterial->tnom); |
|||
if (outputs->OUTPmaterial) { |
|||
printMaterialInfo(pMaterial); |
|||
} |
|||
} |
|||
|
|||
/* Assign doping to the mesh. */ |
|||
TWOsetDoping(inst->NUMOSpDevice, model->NUMOSprofiles, |
|||
model->NUMOSdopTables); |
|||
|
|||
/* Assign physical parameters to the mesh. */ |
|||
TWOsetup(inst->NUMOSpDevice); |
|||
|
|||
/* Assign boundary condition parameters. */ |
|||
TWOsetBCparams(inst->NUMOSpDevice, model->NUMOSboundaries); |
|||
|
|||
/* Normalize everything. */ |
|||
TWOnormalize(inst->NUMOSpDevice); |
|||
|
|||
/* Find the device's type. */ |
|||
if (inst->NUMOSpDevice->pFirstContact->pNodes[0]->netConc < 0.0) { |
|||
inst->NUMOStype = P_CH; |
|||
if (OneCarrier) { |
|||
methods->METHoneCarrier = P_TYPE; |
|||
} |
|||
} else { |
|||
inst->NUMOStype = N_CH; |
|||
if (OneCarrier) { |
|||
methods->METHoneCarrier = N_TYPE; |
|||
} |
|||
} |
|||
inst->NUMOSpDevice->pStats->totalTime[STAT_SETUP] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group |
|||
**********/ |
|||
|
|||
/* |
|||
* This routine performs truncation error calculations for NUMOSs in the |
|||
* circuit. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
#include "numosdef.h" |
|||
#include "sperror.h" |
|||
#include "../../../ciderlib/twod/twoddefs.h" |
|||
#include "../../../ciderlib/twod/twodext.h" |
|||
#include "cidersupt.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
int |
|||
NUMOStrunc(inModel, ckt, timeStep) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
double *timeStep; |
|||
{ |
|||
register NUMOSmodel *model = (NUMOSmodel *) inModel; |
|||
register NUMOSinstance *inst; |
|||
double deltaNew; |
|||
double deltaNorm[7]; |
|||
double startTime; |
|||
int i; |
|||
|
|||
for (i = 0; i <= ckt->CKTmaxOrder; i++) { |
|||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; |
|||
} |
|||
|
|||
for (; model != NULL; model = model->NUMOSnextModel) { |
|||
OneCarrier = model->NUMOSmethods->METHoneCarrier; |
|||
model->NUMOSpInfo->order = ckt->CKTorder; |
|||
model->NUMOSpInfo->delta = deltaNorm; |
|||
model->NUMOSpInfo->lteCoeff = computeLTECoeff(model->NUMOSpInfo); |
|||
for (inst = model->NUMOSinstances; inst != NULL; |
|||
inst = inst->NUMOSnextInstance) { |
|||
if (inst->NUMOSowner != ARCHme) continue; |
|||
|
|||
startTime = SPfrontEnd->IFseconds(); |
|||
deltaNew = TWOtrunc(inst->NUMOSpDevice, model->NUMOSpInfo, |
|||
ckt->CKTdelta); |
|||
*timeStep = MIN(*timeStep, deltaNew); |
|||
inst->NUMOSpDevice->pStats->totalTime[STAT_TRAN] += |
|||
SPfrontEnd->IFseconds() - startTime; |
|||
} |
|||
} |
|||
return (OK); |
|||
} |
|||
@ -0,0 +1,218 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
Authors: 1987 Karti Mayaram, 1991 David Gates |
|||
**********/ |
|||
|
|||
#ifndef NUMOS_H |
|||
#define NUMOS_H "NUMOSdefs.h $Revision$ on $Date$ " |
|||
|
|||
/* data structures used to describe 2D Numerical MOSFETs */ |
|||
|
|||
/* circuit level includes */ |
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "gendefs.h" |
|||
|
|||
/* device level includes */ |
|||
#include "twomesh.h" |
|||
#include "twodev.h" |
|||
#include "profile.h" |
|||
#include "numglobs.h" |
|||
#include "carddefs.h" |
|||
|
|||
/* information needed per instance */ |
|||
typedef struct sNUMOSinstance { |
|||
struct sNUMOSmodel *NUMOSmodPtr; /* back pointer to model */ |
|||
struct sNUMOSinstance *NUMOSnextInstance; /* pointer to next instance |
|||
* of current model */ |
|||
IFuid NUMOSname; /* pointer to character string naming this |
|||
* instance */ |
|||
int NUMOSowner; /* number of owner process */ |
|||
int NUMOSstate; /* pointer to start of state vector for |
|||
* mosfet */ |
|||
|
|||
/* entries in the state vector for mosfet: */ |
|||
#define NUMOSvdb NUMOSstate |
|||
#define NUMOSvsb NUMOSstate+1 |
|||
#define NUMOSvgb NUMOSstate+2 |
|||
#define NUMOSid NUMOSstate+3 |
|||
#define NUMOSis NUMOSstate+4 |
|||
#define NUMOSig NUMOSstate+5 |
|||
#define NUMOSdIdDVdb NUMOSstate+6 |
|||
#define NUMOSdIdDVsb NUMOSstate+7 |
|||
#define NUMOSdIdDVgb NUMOSstate+8 |
|||
#define NUMOSdIsDVdb NUMOSstate+9 |
|||
#define NUMOSdIsDVsb NUMOSstate+10 |
|||
#define NUMOSdIsDVgb NUMOSstate+11 |
|||
#define NUMOSdIgDVdb NUMOSstate+12 |
|||
#define NUMOSdIgDVsb NUMOSstate+13 |
|||
#define NUMOSdIgDVgb NUMOSstate+14 |
|||
#define NUMOSnumStates 15 |
|||
|
|||
int NUMOSdrainNode; /* number of drain node of MOSFET */ |
|||
int NUMOSgateNode; /* number of gate node of MOSFET */ |
|||
int NUMOSsourceNode; /* number of source node of MOSFET */ |
|||
int NUMOSbulkNode; /* number of bulk node of MOSFET */ |
|||
double NUMOSarea; /* area factor for the mosfet */ |
|||
double NUMOSwidth; /* width factor for the mosfet */ |
|||
double NUMOSlength; /* length factor for the mosfet */ |
|||
TWOdevice *NUMOSpDevice; |
|||
int NUMOStype; |
|||
double NUMOStemp; /* Instance Temperature */ |
|||
double NUMOSc11; /* small-signal capacitance */ |
|||
double NUMOSy11r; /* small-signal admittance, real part */ |
|||
double NUMOSy11i; /* small-signal admittance, imag part */ |
|||
double NUMOSc12; /* small-signal capacitance */ |
|||
double NUMOSy12r; /* small-signal admittance, real part */ |
|||
double NUMOSy12i; /* small-signal admittance, imag part */ |
|||
double NUMOSc13; /* small-signal capacitance */ |
|||
double NUMOSy13r; /* small-signal admittance, real part */ |
|||
double NUMOSy13i; /* small-signal admittance, imag part */ |
|||
double NUMOSc21; /* small-signal capacitance */ |
|||
double NUMOSy21r; /* small-signal admittance, real part */ |
|||
double NUMOSy21i; /* small-signal admittance, imag part */ |
|||
double NUMOSc22; /* small-signal capacitance */ |
|||
double NUMOSy22r; /* small-signal admittance, real part */ |
|||
double NUMOSy22i; /* small-signal admittance, imag part */ |
|||
double NUMOSc23; /* small-signal capacitance */ |
|||
double NUMOSy23r; /* small-signal admittance, real part */ |
|||
double NUMOSy23i; /* small-signal admittance, imag part */ |
|||
double NUMOSc31; /* small-signal capacitance */ |
|||
double NUMOSy31r; /* small-signal admittance, real part */ |
|||
double NUMOSy31i; /* small-signal admittance, imag part */ |
|||
double NUMOSc32; /* small-signal capacitance */ |
|||
double NUMOSy32r; /* small-signal admittance, real part */ |
|||
double NUMOSy32i; /* small-signal admittance, imag part */ |
|||
double NUMOSc33; /* small-signal capacitance */ |
|||
double NUMOSy33r; /* small-signal admittance, real part */ |
|||
double NUMOSy33i; /* small-signal admittance, imag part */ |
|||
GLOBvalues NUMOSglobals; /* Temp.-Dep. Global Parameters */ |
|||
int NUMOSprint; /* print timepoints */ |
|||
char *NUMOSicFile; /* Name of initial condition file */ |
|||
double *NUMOSdrainDrainPtr; /* pointer to sparse matrix at (drain,drain) */ |
|||
double *NUMOSdrainSourcePtr; /* pointer to sparse matrix at (drain,source) */ |
|||
double *NUMOSdrainGatePtr; /* pointer to sparse matrix at (drain,gate) */ |
|||
double *NUMOSdrainBulkPtr; /* pointer to sparse matrix at (drain,bulk) */ |
|||
double *NUMOSsourceDrainPtr; /* pointer to sparse matrix at (source,drain) */ |
|||
double *NUMOSsourceSourcePtr; /* pointer to sparse matrix at |
|||
* (source,source) */ |
|||
double *NUMOSsourceGatePtr; /* pointer to sparse matrix at (source,gate) */ |
|||
double *NUMOSsourceBulkPtr; /* pointer to sparse matrix at (source,bulk) */ |
|||
double *NUMOSgateDrainPtr; /* pointer to sparse matrix at (gate,drain) */ |
|||
double *NUMOSgateSourcePtr; /* pointer to sparse matrix at (gate,source) */ |
|||
double *NUMOSgateGatePtr; /* pointer to sparse matrix at (gate,gate) */ |
|||
double *NUMOSgateBulkPtr; /* pointer to sparse matrix at (gate,bulk) */ |
|||
double *NUMOSbulkDrainPtr; /* pointer to sparse matrix at (bulk,drain) */ |
|||
double *NUMOSbulkSourcePtr; /* pointer to sparse matrix at (bulk,source) */ |
|||
double *NUMOSbulkGatePtr; /* pointer to sparse matrix at (bulk,gate) */ |
|||
double *NUMOSbulkBulkPtr; /* pointer to sparse matrix at (bulk,bulk) */ |
|||
|
|||
int NUMOSoff; /* 'off' flag for mosfet */ |
|||
unsigned NUMOSsmSigAvail:1; /* flag to indicate small-signal done */ |
|||
unsigned NUMOSareaGiven:1; /* flag to indicate area was specified */ |
|||
unsigned NUMOSwidthGiven:1; /* flag to indicate width was specified */ |
|||
unsigned NUMOSlengthGiven:1; /* flag to indicate length was specified */ |
|||
unsigned NUMOSicFileGiven:1; /* flag to indicate init. cond. file given */ |
|||
unsigned NUMOSprintGiven:1; /* flag to indicate print was given */ |
|||
unsigned NUMOStempGiven:1; /* flag to indicate temp was given */ |
|||
} NUMOSinstance; |
|||
|
|||
/* per model data */ |
|||
typedef struct sNUMOSmodel { /* model structure for a numerical device */ |
|||
int NUMOSmodType; /* type index of this device type */ |
|||
struct sNUMOSmodel *NUMOSnextModel; /* pointer to next model in list */ |
|||
NUMOSinstance *NUMOSinstances;/* pointer to list of instances */ |
|||
IFuid NUMOSmodName; /* pointer to string naming this model */ |
|||
/* Everything below here is numerical-device-specific */ |
|||
MESHcard *NUMOSxMeshes; /* list of xmesh cards */ |
|||
MESHcard *NUMOSyMeshes; /* list of ymesh cards */ |
|||
DOMNcard *NUMOSdomains; /* list of domain cards */ |
|||
BDRYcard *NUMOSboundaries; /* list of boundary cards */ |
|||
DOPcard *NUMOSdopings; /* list of doping cards */ |
|||
ELCTcard *NUMOSelectrodes; /* list of electrode cards */ |
|||
CONTcard *NUMOScontacts; /* list of contact cards */ |
|||
MODLcard *NUMOSmodels; /* list of model cards */ |
|||
MATLcard *NUMOSmaterials; /* list of material cards */ |
|||
MOBcard *NUMOSmobility; /* list of mobility cards */ |
|||
METHcard *NUMOSmethods; /* list of method cards */ |
|||
OPTNcard *NUMOSoptions; /* list of option cards */ |
|||
OUTPcard *NUMOSoutputs; /* list of output cards */ |
|||
TWOtranInfo *NUMOSpInfo; /* transient analysis information */ |
|||
DOPprofile *NUMOSprofiles; /* expanded list of doping profiles */ |
|||
DOPtable *NUMOSdopTables; /* list of tables used by profiles */ |
|||
TWOmaterial *NUMOSmatlInfo; /* list of material info structures */ |
|||
} NUMOSmodel; |
|||
|
|||
/* type of 2D MOSFET */ |
|||
#define N_CH 1 |
|||
#define P_CH -1 |
|||
|
|||
/* device parameters */ |
|||
#define NUMOS_AREA 1 |
|||
#define NUMOS_WIDTH 2 |
|||
#define NUMOS_LENGTH 3 |
|||
#define NUMOS_OFF 4 |
|||
#define NUMOS_IC_FILE 5 |
|||
#define NUMOS_PRINT 9 |
|||
#define NUMOS_TEMP 10 |
|||
|
|||
#define NUMOS_G11 11 |
|||
#define NUMOS_C11 12 |
|||
#define NUMOS_Y11 13 |
|||
#define NUMOS_G12 14 |
|||
#define NUMOS_C12 15 |
|||
#define NUMOS_Y12 16 |
|||
#define NUMOS_G13 17 |
|||
#define NUMOS_C13 18 |
|||
#define NUMOS_Y13 19 |
|||
#define NUMOS_G14 20 |
|||
#define NUMOS_C14 21 |
|||
#define NUMOS_Y14 22 |
|||
#define NUMOS_G21 23 |
|||
#define NUMOS_C21 24 |
|||
#define NUMOS_Y21 25 |
|||
#define NUMOS_G22 26 |
|||
#define NUMOS_C22 27 |
|||
#define NUMOS_Y22 28 |
|||
#define NUMOS_G23 29 |
|||
#define NUMOS_C23 30 |
|||
#define NUMOS_Y23 31 |
|||
#define NUMOS_G24 32 |
|||
#define NUMOS_C24 33 |
|||
#define NUMOS_Y24 34 |
|||
#define NUMOS_G31 35 |
|||
#define NUMOS_C31 36 |
|||
#define NUMOS_Y31 37 |
|||
#define NUMOS_G32 38 |
|||
#define NUMOS_C32 39 |
|||
#define NUMOS_Y32 40 |
|||
#define NUMOS_G33 41 |
|||
#define NUMOS_C33 42 |
|||
#define NUMOS_Y33 43 |
|||
#define NUMOS_G34 44 |
|||
#define NUMOS_C34 45 |
|||
#define NUMOS_Y34 46 |
|||
#define NUMOS_G41 47 |
|||
#define NUMOS_C41 48 |
|||
#define NUMOS_Y41 49 |
|||
#define NUMOS_G42 50 |
|||
#define NUMOS_C42 51 |
|||
#define NUMOS_Y42 52 |
|||
#define NUMOS_G43 53 |
|||
#define NUMOS_C43 54 |
|||
#define NUMOS_Y43 55 |
|||
#define NUMOS_G44 56 |
|||
#define NUMOS_C44 57 |
|||
#define NUMOS_Y44 58 |
|||
|
|||
/* model parameters */ |
|||
/* NOTE: all true model parameters have been moved to IFcardInfo structures */ |
|||
#define NUMOS_MOD_NUMOS 1 |
|||
|
|||
/* device questions */ |
|||
|
|||
/* model questions */ |
|||
|
|||
#include "numosext.h" |
|||
|
|||
#endif /* NUMOS_H */ |
|||
@ -0,0 +1,27 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Karti Mayaram |
|||
**********/ |
|||
|
|||
#ifndef NUMOSEXT_H |
|||
#define NUMOSEXT_H |
|||
|
|||
|
|||
extern int NUMOSacLoad(GENmodel *, CKTcircuit *); |
|||
extern int NUMOSask(CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *); |
|||
extern int NUMOSdelete(GENmodel *, IFuid, GENinstance **); |
|||
extern void NUMOSdestroy(GENmodel **); |
|||
extern int NUMOSgetic(GENmodel *, CKTcircuit *); |
|||
extern int NUMOSload(GENmodel *, CKTcircuit *); |
|||
extern int NUMOSmDelete(GENmodel **, IFuid, GENmodel *); |
|||
extern int NUMOSmParam(int, IFvalue *, GENmodel *); |
|||
extern int NUMOSparam(int, IFvalue *, GENinstance *, IFvalue *); |
|||
extern int NUMOSpzLoad(GENmodel *, CKTcircuit *, SPcomplex *); |
|||
extern int NUMOSsetup(SMPmatrix *, GENmodel *, CKTcircuit *, int *); |
|||
extern int NUMOStemp(GENmodel *, CKTcircuit *); |
|||
extern int NUMOStrunc(GENmodel *, CKTcircuit *, double *); |
|||
|
|||
extern void NUMOSdump(GENmodel *, CKTcircuit *); |
|||
extern void NUMOSacct(GENmodel *, CKTcircuit *, FILE *); |
|||
|
|||
#endif /* NUMOSEXT_H */ |
|||
@ -0,0 +1,83 @@ |
|||
#include <config.h> |
|||
|
|||
#include <devdefs.h> |
|||
|
|||
#include "numositf.h" |
|||
#include "numosext.h" |
|||
#include "numosinit.h" |
|||
|
|||
|
|||
SPICEdev NUMOSinfo = { |
|||
{ |
|||
"NUMOS", |
|||
"2D Numerical MOS Field Effect Transistor model", |
|||
|
|||
&NUMOSnSize, |
|||
&NUMOSnSize, |
|||
NUMOSnames, |
|||
|
|||
&NUMOSpTSize, |
|||
NUMOSpTable, |
|||
|
|||
&NUMOSmPTSize, |
|||
NUMOSmPTable, |
|||
|
|||
#ifdef XSPICE |
|||
/*---- Fixed by SDB 5.2.2003 to enable XSPICE/tclspice integration -----*/ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
|
|||
0, /* This is a SPICE device, it has no MIF info data */ |
|||
NULL, /* This is a SPICE device, it has no MIF info data */ |
|||
/*--------------------------- End of SDB fix -------------------------*/ |
|||
#endif |
|||
|
|||
DEV_DEFAULT |
|||
}, |
|||
|
|||
DEVparam : NUMOSparam, |
|||
DEVmodParam : NUMOSmParam, |
|||
DEVload : NUMOSload, |
|||
DEVsetup : NUMOSsetup, |
|||
DEVunsetup : NULL, |
|||
DEVpzSetup : NUMOSsetup, |
|||
DEVtemperature: NUMOStemp, |
|||
DEVtrunc : NUMOStrunc, |
|||
DEVfindBranch : NULL, |
|||
DEVacLoad : NUMOSacLoad, |
|||
DEVaccept : NULL, |
|||
DEVdestroy : NUMOSdestroy, |
|||
DEVmodDelete : NUMOSmDelete, |
|||
DEVdelete : NUMOSdelete, |
|||
DEVsetic : NULL, |
|||
DEVask : NUMOSask, |
|||
DEVmodAsk : NULL, |
|||
DEVpzLoad : NUMOSpzLoad, |
|||
DEVconvTest : NULL, |
|||
DEVsenSetup : NULL, |
|||
DEVsenLoad : NULL, |
|||
DEVsenUpdate : NULL, |
|||
DEVsenAcLoad : NULL, |
|||
DEVsenPrint : NULL, |
|||
DEVsenTrunc : NULL, |
|||
DEVdisto : NULL, |
|||
DEVnoise : NULL, |
|||
DEVdump : NUMOSdump, |
|||
DEVacct : NUMOSacct, |
|||
|
|||
DEVinstSize : &NUMOSiSize, |
|||
DEVmodSize : &NUMOSmSize |
|||
|
|||
}; |
|||
|
|||
|
|||
SPICEdev * |
|||
get_numos_info(void) |
|||
{ |
|||
return &NUMOSinfo; |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
#ifndef _NUMOSINIT_H |
|||
#define _NUMOSINIT_H |
|||
|
|||
extern IFparm NUMOSpTable[ ]; |
|||
extern IFparm NUMOSmPTable[ ]; |
|||
extern char *NUMOSnames[ ]; |
|||
extern int NUMOSpTSize; |
|||
extern int NUMOSmPTSize; |
|||
extern int NUMOSnSize; |
|||
extern int NUMOSiSize; |
|||
extern int NUMOSmSize; |
|||
|
|||
#endif |
|||
@ -0,0 +1,10 @@ |
|||
/********** |
|||
Copyright 1991 Regents of the University of California. All rights reserved. |
|||
**********/ |
|||
|
|||
#ifndef DEV_NUMOS |
|||
#define DEV_NUMOS |
|||
|
|||
extern SPICEdev *get_numos_info(void); |
|||
|
|||
#endif |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue