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