30 changed files with 8677 additions and 0 deletions
-
27src/spicelib/devices/mos9/Makefile.am
-
174src/spicelib/devices/mos9/mos9.c
-
128src/spicelib/devices/mos9/mos9acld.c
-
444src/spicelib/devices/mos9/mos9ask.c
-
104src/spicelib/devices/mos9/mos9conv.c
-
560src/spicelib/devices/mos9/mos9defs.h
-
39src/spicelib/devices/mos9/mos9del.c
-
40src/spicelib/devices/mos9/mos9dest.c
-
1386src/spicelib/devices/mos9/mos9dist.c
-
979src/spicelib/devices/mos9/mos9dset.c
-
30src/spicelib/devices/mos9/mos9ext.h
-
49src/spicelib/devices/mos9/mos9ic.c
-
65src/spicelib/devices/mos9/mos9init.c
-
13src/spicelib/devices/mos9/mos9init.h
-
10src/spicelib/devices/mos9/mos9itf.h
-
1358src/spicelib/devices/mos9/mos9load.c
-
171src/spicelib/devices/mos9/mos9mask.c
-
45src/spicelib/devices/mos9/mos9mdel.c
-
202src/spicelib/devices/mos9/mos9mpar.c
-
220src/spicelib/devices/mos9/mos9noi.c
-
116src/spicelib/devices/mos9/mos9par.c
-
141src/spicelib/devices/mos9/mos9pzld.c
-
782src/spicelib/devices/mos9/mos9sacl.c
-
294src/spicelib/devices/mos9/mos9set.c
-
625src/spicelib/devices/mos9/mos9sld.c
-
65src/spicelib/devices/mos9/mos9sprt.c
-
54src/spicelib/devices/mos9/mos9sset.c
-
182src/spicelib/devices/mos9/mos9supd.c
-
343src/spicelib/devices/mos9/mos9temp.c
-
31src/spicelib/devices/mos9/mos9trun.c
@ -0,0 +1,27 @@ |
|||
## Process this file with automake to produce Makefile.in
|
|||
|
|||
pkglib_LTLIBRARIES = libmos9.la |
|||
|
|||
libmos9_la_SOURCES = \
|
|||
mos9.c \
|
|||
mos9ask.c \
|
|||
mos9conv.c \
|
|||
mos9defs.h \
|
|||
mos9dest.c \
|
|||
mos9ext.h \
|
|||
mos9ic.c \
|
|||
mos9init.c \
|
|||
mos9init.h \
|
|||
mos9itf.h \
|
|||
mos9load.c \
|
|||
mos9mask.c \
|
|||
mos9mpar.c \
|
|||
mos9par.c \
|
|||
mos9set.c \
|
|||
mos9temp.c \
|
|||
mos9trun.c |
|||
|
|||
|
|||
|
|||
INCLUDES = -I$(top_srcdir)/src/include |
|||
MAINTAINERCLEANFILES = Makefile.in |
|||
@ -0,0 +1,174 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "devdefs.h" |
|||
#include "ifsim.h" |
|||
#include "mos9defs.h" |
|||
#include "suffix.h" |
|||
|
|||
IFparm MOS9pTable[] = { /* parameters */ |
|||
|
|||
IOPU("m", MOS9_M, IF_REAL , "Multiplier"), |
|||
IOPU("l", MOS9_L, IF_REAL , "Length"), |
|||
IOPU("w", MOS9_W, IF_REAL , "Width"), |
|||
IOPU("ad", MOS9_AD, IF_REAL , "Drain area"), |
|||
IOPU("as", MOS9_AS, IF_REAL , "Source area"), |
|||
IOPU("pd", MOS9_PD, IF_REAL , "Drain perimeter"), |
|||
IOPU("ps", MOS9_PS, IF_REAL , "Source perimeter"), |
|||
OP("id", MOS9_CD, IF_REAL, "Drain current"), |
|||
OPR("cd", MOS9_CD, IF_REAL, "Drain current"), |
|||
OPU("ibd", MOS9_CBD, IF_REAL, "B-D junction current"), |
|||
OPU("ibs", MOS9_CBS, IF_REAL, "B-S junction current"), |
|||
OPU("is", MOS9_CS, IF_REAL, "Source current"), |
|||
OPU("ig", MOS9_CG, IF_REAL, "Gate current"), |
|||
OPU("ib", MOS9_CB, IF_REAL, "Bulk current"), |
|||
OP("vgs", MOS9_VGS, IF_REAL, "Gate-Source voltage"), |
|||
OP("vds", MOS9_VDS, IF_REAL, "Drain-Source voltage"), |
|||
OP("vbs", MOS9_VBS, IF_REAL, "Bulk-Source voltage"), |
|||
OPU("vbd", MOS9_VBD, IF_REAL, "Bulk-Drain voltage"), |
|||
IOPU("nrd", MOS9_NRD, IF_REAL , "Drain squares"), |
|||
IOPU("nrs", MOS9_NRS, IF_REAL , "Source squares"), |
|||
IP("off", MOS9_OFF, IF_FLAG , "Device initially off"), |
|||
IOPAU("icvds", MOS9_IC_VDS, IF_REAL , "Initial D-S voltage"), |
|||
IOPAU("icvgs", MOS9_IC_VGS, IF_REAL , "Initial G-S voltage"), |
|||
IOPAU("icvbs", MOS9_IC_VBS, IF_REAL , "Initial B-S voltage"), |
|||
IOPU("ic", MOS9_IC, IF_REALVEC, "Vector of D-S, G-S, B-S voltages"), |
|||
IOPU("temp", MOS9_TEMP, IF_REAL , "Instance operating temperature"), |
|||
IP("sens_l", MOS9_L_SENS, IF_FLAG, "flag to request sensitivity WRT length"), |
|||
IP("sens_w", MOS9_W_SENS, IF_FLAG, "flag to request sensitivity WRT width"), |
|||
OPU("dnode", MOS9_DNODE, IF_INTEGER, "Number of drain node"), |
|||
OPU("gnode", MOS9_GNODE, IF_INTEGER, "Number of gate node"), |
|||
OPU("snode", MOS9_SNODE, IF_INTEGER, "Number of source node"), |
|||
OPU("bnode", MOS9_BNODE, IF_INTEGER, "Number of bulk node"), |
|||
OPU("dnodeprime", MOS9_DNODEPRIME,IF_INTEGER,"Number of internal drain node"), |
|||
OPU("snodeprime", MOS9_SNODEPRIME,IF_INTEGER,"Number of internal source node"), |
|||
OP("von", MOS9_VON, IF_REAL, "Turn-on voltage"), |
|||
OP("vdsat", MOS9_VDSAT, IF_REAL, "Saturation drain voltage"), |
|||
OPU("sourcevcrit", MOS9_SOURCEVCRIT, IF_REAL, "Critical source voltage"), |
|||
OPU("drainvcrit", MOS9_DRAINVCRIT, IF_REAL, "Critical drain voltage"), |
|||
OP("rs", MOS9_SOURCERESIST, IF_REAL, "Source resistance"), |
|||
OPU("sourceconductance", MOS9_SOURCECONDUCT, IF_REAL, "Source conductance"), |
|||
OP("rd", MOS9_DRAINRESIST, IF_REAL, "Drain resistance"), |
|||
OPU("drainconductance", MOS9_DRAINCONDUCT, IF_REAL, "Drain conductance"), |
|||
OP("gm", MOS9_GM, IF_REAL, "Transconductance"), |
|||
OP("gds", MOS9_GDS, IF_REAL, "Drain-Source conductance"), |
|||
OP("gmb", MOS9_GMBS, IF_REAL, "Bulk-Source transconductance"), |
|||
OPR("gmbs", MOS9_GMBS, IF_REAL, "Bulk-Source transconductance"), |
|||
OPU("gbd", MOS9_GBD, IF_REAL, "Bulk-Drain conductance"), |
|||
OPU("gbs", MOS9_GBS, IF_REAL, "Bulk-Source conductance"), |
|||
|
|||
OP("cbd", MOS9_CAPBD, IF_REAL, "Bulk-Drain capacitance"), |
|||
OP("cbs", MOS9_CAPBS, IF_REAL, "Bulk-Source capacitance"), |
|||
OP("cgs", MOS9_CAPGS, IF_REAL, "Gate-Source capacitance"), |
|||
/* OPR("cgs", MOS9_CGS, IF_REAL , "Gate-Source capacitance"),*/ |
|||
OP("cgd", MOS9_CAPGD, IF_REAL, "Gate-Drain capacitance"), |
|||
/* OPR("cgd", MOS9_CGD, IF_REAL , "Gate-Drain capacitance"),*/ |
|||
OP("cgb", MOS9_CAPGB, IF_REAL, "Gate-Bulk capacitance"), |
|||
|
|||
OPU("cqgs",MOS9_CQGS,IF_REAL,"Capacitance due to gate-source charge storage"), |
|||
OPU("cqgd",MOS9_CQGD, IF_REAL,"Capacitance due to gate-drain charge storage"), |
|||
OPU("cqgb",MOS9_CQGB, IF_REAL,"Capacitance due to gate-bulk charge storage"), |
|||
OPU("cqbd",MOS9_CQBD,IF_REAL,"Capacitance due to bulk-drain charge storage"), |
|||
OPU("cqbs",MOS9_CQBS,IF_REAL,"Capacitance due to bulk-source charge storage"), |
|||
|
|||
OPU("cbd0",MOS9_CAPZEROBIASBD,IF_REAL,"Zero-Bias B-D junction capacitance"), |
|||
OPU("cbdsw0",MOS9_CAPZEROBIASBDSW,IF_REAL, |
|||
"Zero-Bias B-D sidewall capacitance"), |
|||
OPU("cbs0",MOS9_CAPZEROBIASBS,IF_REAL,"Zero-Bias B-S junction capacitance"), |
|||
OPU("cbssw0",MOS9_CAPZEROBIASBSSW,IF_REAL, |
|||
"Zero-Bias B-S sidewall capacitance"), |
|||
OPU("qbs", MOS9_QBS, IF_REAL, "Bulk-Source charge storage"), |
|||
OPU("qgs", MOS9_QGS, IF_REAL, "Gate-Source charge storage"), |
|||
OPU("qgd", MOS9_QGD, IF_REAL, "Gate-Drain charge storage"), |
|||
OPU("qgb", MOS9_QGB, IF_REAL, "Gate-Bulk charge storage"), |
|||
OPU("qbd", MOS9_QBD, IF_REAL, "Bulk-Drain charge storage"), |
|||
OPU("p", MOS9_POWER, IF_REAL, "Instantaneous power"), |
|||
OPU("sens_l_dc", MOS9_L_SENS_DC, IF_REAL, "dc sensitivity wrt length"), |
|||
OPU("sens_l_real",MOS9_L_SENS_REAL, IF_REAL, |
|||
"real part of ac sensitivity wrt length"), |
|||
OPU("sens_l_imag",MOS9_L_SENS_IMAG, IF_REAL, |
|||
"imag part of ac sensitivity wrt length"), |
|||
OPU("sens_l_cplx",MOS9_L_SENS_CPLX, IF_COMPLEX, "ac sensitivity wrt length"), |
|||
OPU("sens_l_mag", MOS9_L_SENS_MAG, IF_REAL, |
|||
"sensitivity wrt l of ac magnitude"), |
|||
OPU("sens_l_ph", MOS9_L_SENS_PH, IF_REAL, "sensitivity wrt l of ac phase"), |
|||
OPU("sens_w_dc", MOS9_W_SENS_DC, IF_REAL, "dc sensitivity wrt width"), |
|||
OPU("sens_w_real",MOS9_W_SENS_REAL, IF_REAL, |
|||
"real part of ac sensitivity wrt width"), |
|||
OPU("sens_w_imag",MOS9_W_SENS_IMAG, IF_REAL, |
|||
"imag part of ac sensitivity wrt width"), |
|||
OPU("sens_w_mag", MOS9_W_SENS_MAG, IF_REAL, |
|||
"sensitivity wrt w of ac magnitude"), |
|||
OPU("sens_w_ph", MOS9_W_SENS_PH, IF_REAL, "sensitivity wrt w of ac phase"), |
|||
OPU("sens_w_cplx",MOS9_W_SENS_CPLX, IF_COMPLEX, "ac sensitivity wrt width") |
|||
}; |
|||
|
|||
IFparm MOS9mPTable[] = { /* model parameters */ |
|||
OP("type", MOS9_MOD_TYPE, IF_STRING ,"N-channel or P-channel MOS"), |
|||
IP("nmos", MOS9_MOD_NMOS, IF_FLAG ,"N type MOSfet model"), |
|||
IP("pmos", MOS9_MOD_PMOS, IF_FLAG ,"P type MOSfet model"), |
|||
IOP("vto", MOS9_MOD_VTO, IF_REAL ,"Threshold voltage"), |
|||
IOPR("vt0", MOS9_MOD_VTO, IF_REAL ,"Threshold voltage"), |
|||
IOP("kp", MOS9_MOD_KP, IF_REAL ,"Transconductance parameter"), |
|||
IOP("gamma", MOS9_MOD_GAMMA, IF_REAL ,"Bulk threshold parameter"), |
|||
IOP("phi", MOS9_MOD_PHI, IF_REAL ,"Surface potential"), |
|||
IOP("rd", MOS9_MOD_RD, IF_REAL ,"Drain ohmic resistance"), |
|||
IOP("rs", MOS9_MOD_RS, IF_REAL ,"Source ohmic resistance"), |
|||
IOPA("cbd", MOS9_MOD_CBD, IF_REAL ,"B-D junction capacitance"), |
|||
IOPA("cbs", MOS9_MOD_CBS, IF_REAL ,"B-S junction capacitance"), |
|||
IOP("is", MOS9_MOD_IS, IF_REAL ,"Bulk junction sat. current"), |
|||
IOP("pb", MOS9_MOD_PB, IF_REAL ,"Bulk junction potential"), |
|||
IOPA("cgso", MOS9_MOD_CGSO, IF_REAL ,"Gate-source overlap cap."), |
|||
IOPA("cgdo", MOS9_MOD_CGDO, IF_REAL ,"Gate-drain overlap cap."), |
|||
IOPA("cgbo", MOS9_MOD_CGBO, IF_REAL ,"Gate-bulk overlap cap."), |
|||
IOP("rsh", MOS9_MOD_RSH, IF_REAL ,"Sheet resistance"), |
|||
IOPA("cj", MOS9_MOD_CJ, IF_REAL ,"Bottom junction cap per area"), |
|||
IOP("mj", MOS9_MOD_MJ, IF_REAL ,"Bottom grading coefficient"), |
|||
IOPA("cjsw", MOS9_MOD_CJSW, IF_REAL ,"Side junction cap per area"), |
|||
IOP("mjsw", MOS9_MOD_MJSW, IF_REAL ,"Side grading coefficient"), |
|||
IOPU("js", MOS9_MOD_JS, IF_REAL ,"Bulk jct. sat. current density"), |
|||
IOP("tox", MOS9_MOD_TOX, IF_REAL ,"Oxide thickness"), |
|||
IOP("ld", MOS9_MOD_LD, IF_REAL ,"Lateral diffusion"), |
|||
IOP("xl", MOS9_MOD_XL, IF_REAL ,"Length mask adjustment"), |
|||
IOP("wd", MOS9_MOD_WD, IF_REAL ,"Width Narrowing (Diffusion)"), |
|||
IOP("xw", MOS9_MOD_XW, IF_REAL ,"Width mask adjustment"), |
|||
IOPU("delvto", MOS9_MOD_DELVTO, IF_REAL ,"Threshold voltage Adjust"), |
|||
IOPR("delvt0", MOS9_MOD_DELVTO, IF_REAL ,"Threshold voltage Adjust"), |
|||
IOP("u0", MOS9_MOD_U0, IF_REAL ,"Surface mobility"), |
|||
IOPR("uo", MOS9_MOD_U0, IF_REAL ,"Surface mobility"), |
|||
IOP("fc", MOS9_MOD_FC, IF_REAL ,"Forward bias jct. fit parm."), |
|||
IOP("nsub", MOS9_MOD_NSUB, IF_REAL ,"Substrate doping"), |
|||
IOP("tpg", MOS9_MOD_TPG, IF_INTEGER,"Gate type"), |
|||
IOP("nss", MOS9_MOD_NSS, IF_REAL ,"Surface state density"), |
|||
IOP("vmax", MOS9_MOD_VMAX, IF_REAL ,"Maximum carrier drift velocity"), |
|||
IOP("xj", MOS9_MOD_XJ, IF_REAL ,"Junction depth"), |
|||
IOP("nfs", MOS9_MOD_NFS, IF_REAL ,"Fast surface state density"), |
|||
IOP("xd", MOS9_MOD_XD, IF_REAL ,"Depletion layer width"), |
|||
IOP("alpha", MOS9_MOD_ALPHA, IF_REAL ,"Alpha"), |
|||
IOP("eta", MOS9_MOD_ETA, IF_REAL ,"Vds dependence of threshold voltage"), |
|||
IOP("delta", MOS9_MOD_DELTA, IF_REAL ,"Width effect on threshold"), |
|||
IOPR("input_delta", MOS9_DELTA, IF_REAL ,""), |
|||
IOP("theta", MOS9_MOD_THETA, IF_REAL ,"Vgs dependence on mobility"), |
|||
IOP("kappa", MOS9_MOD_KAPPA, IF_REAL ,"Kappa"), |
|||
IOPU("tnom", MOS9_MOD_TNOM, IF_REAL ,"Parameter measurement temperature"), |
|||
IOP("kf", MOS9_MOD_KF, IF_REAL ,"Flicker noise coefficient"), |
|||
IOP("af", MOS9_MOD_AF, IF_REAL ,"Flicker noise exponent") |
|||
}; |
|||
|
|||
char *MOS9names[] = { |
|||
"Drain", |
|||
"Gate", |
|||
"Source", |
|||
"Bulk" |
|||
}; |
|||
|
|||
int MOS9nSize = NUMELEMS(MOS9names); |
|||
int MOS9pTSize = NUMELEMS(MOS9pTable); |
|||
int MOS9mPTSize = NUMELEMS(MOS9mPTable); |
|||
int MOS9iSize = sizeof(MOS9instance); |
|||
int MOS9mSize = sizeof(MOS9model); |
|||
@ -0,0 +1,128 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
/* |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "cktdefs.h" |
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
int |
|||
MOS9acLoad(inModel,ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
MOS9model *model = (MOS9model *)inModel; |
|||
MOS9instance *here; |
|||
int xnrm; |
|||
int xrev; |
|||
double EffectiveLength; |
|||
double EffectiveWidth; |
|||
double xgs; |
|||
double xgd; |
|||
double xgb; |
|||
double xbd; |
|||
double xbs; |
|||
double capgs; |
|||
double capgd; |
|||
double capgb; |
|||
double GateBulkOverlapCap; |
|||
double GateDrainOverlapCap; |
|||
double GateSourceOverlapCap; |
|||
|
|||
for( ; model != NULL; model = model->MOS9nextModel) { |
|||
for(here = model->MOS9instances; here!= NULL; |
|||
here = here->MOS9nextInstance) { |
|||
|
|||
if (here->MOS9mode < 0) { |
|||
xnrm=0; |
|||
xrev=1; |
|||
} else { |
|||
xnrm=1; |
|||
xrev=0; |
|||
} |
|||
/* |
|||
* charge oriented model parameters |
|||
*/ |
|||
EffectiveWidth=here->MOS9w-2*model->MOS9widthNarrow+ |
|||
model->MOS9widthAdjust; |
|||
EffectiveLength=here->MOS9l - 2*model->MOS9latDiff+ |
|||
model->MOS9lengthAdjust; |
|||
GateSourceOverlapCap = model->MOS9gateSourceOverlapCapFactor * |
|||
here->MOS9m * EffectiveWidth; |
|||
GateDrainOverlapCap = model->MOS9gateDrainOverlapCapFactor * |
|||
here->MOS9m * EffectiveWidth; |
|||
GateBulkOverlapCap = model->MOS9gateBulkOverlapCapFactor * |
|||
here->MOS9m * EffectiveLength; |
|||
|
|||
|
|||
/* |
|||
* meyer"s model parameters |
|||
*/ |
|||
capgs = ( *(ckt->CKTstate0+here->MOS9capgs)+ |
|||
*(ckt->CKTstate0+here->MOS9capgs) + |
|||
GateSourceOverlapCap ); |
|||
capgd = ( *(ckt->CKTstate0+here->MOS9capgd)+ |
|||
*(ckt->CKTstate0+here->MOS9capgd) + |
|||
GateDrainOverlapCap ); |
|||
capgb = ( *(ckt->CKTstate0+here->MOS9capgb)+ |
|||
*(ckt->CKTstate0+here->MOS9capgb) + |
|||
GateBulkOverlapCap ); |
|||
xgs = capgs * ckt->CKTomega; |
|||
xgd = capgd * ckt->CKTomega; |
|||
xgb = capgb * ckt->CKTomega; |
|||
xbd = here->MOS9capbd * ckt->CKTomega; |
|||
xbs = here->MOS9capbs * ckt->CKTomega; |
|||
|
|||
/* |
|||
* load matrix |
|||
*/ |
|||
|
|||
*(here->MOS9GgPtr +1) += xgd+xgs+xgb; |
|||
*(here->MOS9BbPtr +1) += xgb+xbd+xbs; |
|||
*(here->MOS9DPdpPtr +1) += xgd+xbd; |
|||
*(here->MOS9SPspPtr +1) += xgs+xbs; |
|||
*(here->MOS9GbPtr +1) -= xgb; |
|||
*(here->MOS9GdpPtr +1) -= xgd; |
|||
*(here->MOS9GspPtr +1) -= xgs; |
|||
*(here->MOS9BgPtr +1) -= xgb; |
|||
*(here->MOS9BdpPtr +1) -= xbd; |
|||
*(here->MOS9BspPtr +1) -= xbs; |
|||
*(here->MOS9DPgPtr +1) -= xgd; |
|||
*(here->MOS9DPbPtr +1) -= xbd; |
|||
*(here->MOS9SPgPtr +1) -= xgs; |
|||
*(here->MOS9SPbPtr +1) -= xbs; |
|||
*(here->MOS9DdPtr) += here->MOS9drainConductance; |
|||
*(here->MOS9SsPtr) += here->MOS9sourceConductance; |
|||
*(here->MOS9BbPtr) += here->MOS9gbd+here->MOS9gbs; |
|||
*(here->MOS9DPdpPtr) += here->MOS9drainConductance+ |
|||
here->MOS9gds+here->MOS9gbd+ |
|||
xrev*(here->MOS9gm+here->MOS9gmbs); |
|||
*(here->MOS9SPspPtr) += here->MOS9sourceConductance+ |
|||
here->MOS9gds+here->MOS9gbs+ |
|||
xnrm*(here->MOS9gm+here->MOS9gmbs); |
|||
*(here->MOS9DdpPtr) -= here->MOS9drainConductance; |
|||
*(here->MOS9SspPtr) -= here->MOS9sourceConductance; |
|||
*(here->MOS9BdpPtr) -= here->MOS9gbd; |
|||
*(here->MOS9BspPtr) -= here->MOS9gbs; |
|||
*(here->MOS9DPdPtr) -= here->MOS9drainConductance; |
|||
*(here->MOS9DPgPtr) += (xnrm-xrev)*here->MOS9gm; |
|||
*(here->MOS9DPbPtr) += -here->MOS9gbd+(xnrm-xrev)*here->MOS9gmbs; |
|||
*(here->MOS9DPspPtr) -= here->MOS9gds+ |
|||
xnrm*(here->MOS9gm+here->MOS9gmbs); |
|||
*(here->MOS9SPgPtr) -= (xnrm-xrev)*here->MOS9gm; |
|||
*(here->MOS9SPsPtr) -= here->MOS9sourceConductance; |
|||
*(here->MOS9SPbPtr) -= here->MOS9gbs+(xnrm-xrev)*here->MOS9gmbs; |
|||
*(here->MOS9SPdpPtr) -= here->MOS9gds+ |
|||
xrev*(here->MOS9gm+here->MOS9gmbs); |
|||
} |
|||
} |
|||
return(OK); |
|||
} |
|||
@ -0,0 +1,444 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Mathew Lew and Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "devdefs.h" |
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
/*ARGSUSED*/ |
|||
int |
|||
MOS9ask(ckt,inst,which,value,select) |
|||
CKTcircuit *ckt; |
|||
GENinstance *inst; |
|||
int which; |
|||
IFvalue *value; |
|||
IFvalue *select; |
|||
{ |
|||
MOS9instance *here = (MOS9instance *)inst; |
|||
double vr; |
|||
double vi; |
|||
double sr; |
|||
double si; |
|||
double vm; |
|||
static char *msg = "Current and power not available for ac analysis"; |
|||
switch(which) { |
|||
case MOS9_TEMP: |
|||
value->rValue = here->MOS9temp-CONSTCtoK; |
|||
return(OK); |
|||
case MOS9_CGS: |
|||
value->rValue = 2* *(ckt->CKTstate0 + here->MOS9capgs); |
|||
return(OK); |
|||
case MOS9_CGD: |
|||
value->rValue = 2* *(ckt->CKTstate0 + here->MOS9capgd); |
|||
return(OK); |
|||
case MOS9_M: |
|||
value->rValue = here->MOS9m; |
|||
return(OK); |
|||
case MOS9_L: |
|||
value->rValue = here->MOS9l; |
|||
return(OK); |
|||
case MOS9_W: |
|||
value->rValue = here->MOS9w; |
|||
return(OK); |
|||
case MOS9_AS: |
|||
value->rValue = here->MOS9sourceArea; |
|||
return(OK); |
|||
case MOS9_AD: |
|||
value->rValue = here->MOS9drainArea; |
|||
return(OK); |
|||
case MOS9_PS: |
|||
value->rValue = here->MOS9sourcePerimiter; |
|||
return(OK); |
|||
case MOS9_PD: |
|||
value->rValue = here->MOS9drainPerimiter; |
|||
return(OK); |
|||
case MOS9_NRS: |
|||
value->rValue = here->MOS9sourceSquares; |
|||
return(OK); |
|||
case MOS9_NRD: |
|||
value->rValue = here->MOS9drainSquares; |
|||
return(OK); |
|||
case MOS9_OFF: |
|||
value->rValue = here->MOS9off; |
|||
return(OK); |
|||
case MOS9_IC_VBS: |
|||
value->rValue = here->MOS9icVBS; |
|||
return(OK); |
|||
case MOS9_IC_VDS: |
|||
value->rValue = here->MOS9icVDS; |
|||
return(OK); |
|||
case MOS9_IC_VGS: |
|||
value->rValue = here->MOS9icVGS; |
|||
return(OK); |
|||
case MOS9_DNODE: |
|||
value->iValue = here->MOS9dNode; |
|||
return(OK); |
|||
case MOS9_GNODE: |
|||
value->iValue = here->MOS9gNode; |
|||
return(OK); |
|||
case MOS9_SNODE: |
|||
value->iValue = here->MOS9sNode; |
|||
return(OK); |
|||
case MOS9_BNODE: |
|||
value->iValue = here->MOS9bNode; |
|||
return(OK); |
|||
case MOS9_DNODEPRIME: |
|||
value->iValue = here->MOS9dNodePrime; |
|||
return(OK); |
|||
case MOS9_SNODEPRIME: |
|||
value->iValue = here->MOS9sNodePrime; |
|||
return(OK); |
|||
case MOS9_SOURCECONDUCT: |
|||
value->rValue = here->MOS9sourceConductance; |
|||
return(OK); |
|||
case MOS9_DRAINCONDUCT: |
|||
value->rValue = here->MOS9drainConductance; |
|||
return(OK); |
|||
case MOS9_SOURCERESIST: |
|||
if (here->MOS9sNodePrime != here->MOS9sNode) |
|||
value->rValue = 1.0 / here->MOS9sourceConductance; |
|||
else |
|||
value->rValue = 0.0; |
|||
return(OK); |
|||
case MOS9_DRAINRESIST: |
|||
if (here->MOS9dNodePrime != here->MOS9dNode) |
|||
value->rValue = 1.0 / here->MOS9drainConductance; |
|||
else |
|||
value->rValue = 0.0; |
|||
return(OK); |
|||
case MOS9_VON: |
|||
value->rValue = here->MOS9von; |
|||
return(OK); |
|||
case MOS9_VDSAT: |
|||
value->rValue = here->MOS9vdsat; |
|||
return(OK); |
|||
case MOS9_SOURCEVCRIT: |
|||
value->rValue = here->MOS9sourceVcrit; |
|||
return(OK); |
|||
case MOS9_DRAINVCRIT: |
|||
value->rValue = here->MOS9drainVcrit; |
|||
return(OK); |
|||
case MOS9_CD: |
|||
value->rValue = here->MOS9cd; |
|||
return(OK); |
|||
case MOS9_CBS: |
|||
value->rValue = here->MOS9cbs; |
|||
return(OK); |
|||
case MOS9_CBD: |
|||
value->rValue = here->MOS9cbd; |
|||
return(OK); |
|||
case MOS9_GMBS: |
|||
value->rValue = here->MOS9gmbs; |
|||
return(OK); |
|||
case MOS9_GM: |
|||
value->rValue = here->MOS9gm; |
|||
return(OK); |
|||
case MOS9_GDS: |
|||
value->rValue = here->MOS9gds; |
|||
return(OK); |
|||
case MOS9_GBD: |
|||
value->rValue = here->MOS9gbd; |
|||
return(OK); |
|||
case MOS9_GBS: |
|||
value->rValue = here->MOS9gbs; |
|||
return(OK); |
|||
case MOS9_CAPBD: |
|||
value->rValue = here->MOS9capbd; |
|||
return(OK); |
|||
case MOS9_CAPBS: |
|||
value->rValue = here->MOS9capbs; |
|||
return(OK); |
|||
case MOS9_CAPZEROBIASBD: |
|||
value->rValue = here->MOS9Cbd; |
|||
return(OK); |
|||
case MOS9_CAPZEROBIASBDSW: |
|||
value->rValue = here->MOS9Cbdsw; |
|||
return(OK); |
|||
case MOS9_CAPZEROBIASBS: |
|||
value->rValue = here->MOS9Cbs; |
|||
return(OK); |
|||
case MOS9_CAPZEROBIASBSSW: |
|||
value->rValue = here->MOS9Cbssw; |
|||
return(OK); |
|||
case MOS9_VBD: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9vbd); |
|||
return(OK); |
|||
case MOS9_VBS: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9vbs); |
|||
return(OK); |
|||
case MOS9_VGS: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9vgs); |
|||
return(OK); |
|||
case MOS9_VDS: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9vds); |
|||
return(OK); |
|||
case MOS9_CAPGS: |
|||
value->rValue = 2* *(ckt->CKTstate0 + here->MOS9capgs); |
|||
/* add overlap capacitance */ |
|||
value->rValue += (here->MOS9modPtr->MOS9gateSourceOverlapCapFactor) |
|||
* here->MOS9m |
|||
* (here->MOS9w |
|||
+here->MOS9modPtr->MOS9widthAdjust |
|||
-2*(here->MOS9modPtr->MOS9widthNarrow)); |
|||
return(OK); |
|||
case MOS9_QGS: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9qgs); |
|||
return(OK); |
|||
case MOS9_CQGS: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9cqgs); |
|||
return(OK); |
|||
case MOS9_CAPGD: |
|||
value->rValue = 2* *(ckt->CKTstate0 + here->MOS9capgd); |
|||
/* add overlap capacitance */ |
|||
value->rValue += (here->MOS9modPtr->MOS9gateDrainOverlapCapFactor) |
|||
* here->MOS9m |
|||
* (here->MOS9w |
|||
+here->MOS9modPtr->MOS9widthAdjust |
|||
-2*(here->MOS9modPtr->MOS9widthNarrow)); |
|||
return(OK); |
|||
case MOS9_QGD: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9qgd); |
|||
return(OK); |
|||
case MOS9_CQGD: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9cqgd); |
|||
return(OK); |
|||
case MOS9_CAPGB: |
|||
value->rValue = 2* *(ckt->CKTstate0 + here->MOS9capgb); |
|||
/* add overlap capacitance */ |
|||
value->rValue += (here->MOS9modPtr->MOS9gateBulkOverlapCapFactor) |
|||
* here->MOS9m |
|||
* (here->MOS9l |
|||
+here->MOS9modPtr->MOS9lengthAdjust |
|||
-2*(here->MOS9modPtr->MOS9latDiff)); |
|||
return(OK); |
|||
case MOS9_QGB: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9qgb); |
|||
return(OK); |
|||
case MOS9_CQGB: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9cqgb); |
|||
return(OK); |
|||
case MOS9_QBD: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9qbd); |
|||
return(OK); |
|||
case MOS9_CQBD: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9cqbd); |
|||
return(OK); |
|||
case MOS9_QBS: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9qbs); |
|||
return(OK); |
|||
case MOS9_CQBS: |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9cqbs); |
|||
return(OK); |
|||
case MOS9_L_SENS_DC: |
|||
if(ckt->CKTsenInfo){ |
|||
value->rValue = *(ckt->CKTsenInfo->SEN_Sap[select->iValue + 1]+ |
|||
here->MOS9senParmNo); |
|||
} |
|||
return(OK); |
|||
case MOS9_L_SENS_REAL: |
|||
if(ckt->CKTsenInfo){ |
|||
value->rValue = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo); |
|||
} |
|||
return(OK); |
|||
case MOS9_L_SENS_IMAG: |
|||
if(ckt->CKTsenInfo){ |
|||
value->rValue = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo); |
|||
} |
|||
return(OK); |
|||
case MOS9_L_SENS_MAG: |
|||
if(ckt->CKTsenInfo){ |
|||
vr = *(ckt->CKTrhsOld + select->iValue + 1); |
|||
vi = *(ckt->CKTirhsOld + select->iValue + 1); |
|||
vm = sqrt(vr*vr + vi*vi); |
|||
if(vm == 0){ |
|||
value->rValue = 0; |
|||
return(OK); |
|||
} |
|||
sr = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo); |
|||
si = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo); |
|||
value->rValue = (vr * sr + vi * si)/vm; |
|||
} |
|||
return(OK); |
|||
case MOS9_L_SENS_PH: |
|||
if(ckt->CKTsenInfo){ |
|||
vr = *(ckt->CKTrhsOld + select->iValue + 1); |
|||
vi = *(ckt->CKTirhsOld + select->iValue + 1); |
|||
vm = vr*vr + vi*vi; |
|||
if(vm == 0){ |
|||
value->rValue = 0; |
|||
return(OK); |
|||
} |
|||
sr = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo); |
|||
si = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo); |
|||
value->rValue = (vr * si - vi * sr)/vm; |
|||
} |
|||
return(OK); |
|||
case MOS9_L_SENS_CPLX: |
|||
if(ckt->CKTsenInfo){ |
|||
value->cValue.real= |
|||
*(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo); |
|||
value->cValue.imag= |
|||
*(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo); |
|||
} |
|||
return(OK); |
|||
case MOS9_W_SENS_DC: |
|||
if(ckt->CKTsenInfo){ |
|||
value->rValue = *(ckt->CKTsenInfo->SEN_Sap[select->iValue + 1]+ |
|||
here->MOS9senParmNo + here->MOS9sens_l); |
|||
} |
|||
return(OK); |
|||
case MOS9_W_SENS_REAL: |
|||
if(ckt->CKTsenInfo){ |
|||
value->rValue = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo + here->MOS9sens_l); |
|||
} |
|||
return(OK); |
|||
case MOS9_W_SENS_IMAG: |
|||
if(ckt->CKTsenInfo){ |
|||
value->rValue = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo + here->MOS9sens_l); |
|||
} |
|||
return(OK); |
|||
case MOS9_W_SENS_MAG: |
|||
if(ckt->CKTsenInfo){ |
|||
vr = *(ckt->CKTrhsOld + select->iValue + 1); |
|||
vi = *(ckt->CKTirhsOld + select->iValue + 1); |
|||
vm = sqrt(vr*vr + vi*vi); |
|||
if(vm == 0){ |
|||
value->rValue = 0; |
|||
return(OK); |
|||
} |
|||
sr = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo + here->MOS9sens_l); |
|||
si = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo + here->MOS9sens_l); |
|||
value->rValue = (vr * sr + vi * si)/vm; |
|||
} |
|||
return(OK); |
|||
case MOS9_W_SENS_PH: |
|||
if(ckt->CKTsenInfo){ |
|||
vr = *(ckt->CKTrhsOld + select->iValue + 1); |
|||
vi = *(ckt->CKTirhsOld + select->iValue + 1); |
|||
vm = vr*vr + vi*vi; |
|||
if(vm == 0){ |
|||
value->rValue = 0; |
|||
return(OK); |
|||
} |
|||
sr = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo + here->MOS9sens_l); |
|||
si = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo + here->MOS9sens_l); |
|||
value->rValue = (vr * si - vi * sr)/vm; |
|||
} |
|||
return(OK); |
|||
case MOS9_W_SENS_CPLX: |
|||
if(ckt->CKTsenInfo){ |
|||
value->cValue.real= |
|||
*(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo + here->MOS9sens_l); |
|||
value->cValue.imag= |
|||
*(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ |
|||
here->MOS9senParmNo + here->MOS9sens_l); |
|||
} |
|||
return(OK); |
|||
case MOS9_CB : |
|||
if (ckt->CKTcurrentAnalysis & DOING_AC) { |
|||
errMsg = MALLOC(strlen(msg)+1); |
|||
errRtn = "MOS9ask.c"; |
|||
strcpy(errMsg,msg); |
|||
return(E_ASKCURRENT); |
|||
} else { |
|||
value->rValue = here->MOS9cbd + here->MOS9cbs - *(ckt->CKTstate0 |
|||
+ here->MOS9cqgb); |
|||
} |
|||
return(OK); |
|||
case MOS9_CG : |
|||
if (ckt->CKTcurrentAnalysis & DOING_AC) { |
|||
errMsg = MALLOC(strlen(msg)+1); |
|||
errRtn = "MOS9ask.c"; |
|||
strcpy(errMsg,msg); |
|||
return(E_ASKCURRENT); |
|||
} else if (ckt->CKTcurrentAnalysis & (DOING_DCOP | DOING_TRCV)) { |
|||
value->rValue = 0; |
|||
} else if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && |
|||
(ckt->CKTmode & MODETRANOP)) { |
|||
value->rValue = 0; |
|||
} else { |
|||
value->rValue = *(ckt->CKTstate0 + here->MOS9cqgb) + |
|||
*(ckt->CKTstate0 + here->MOS9cqgd) + *(ckt->CKTstate0 + |
|||
here->MOS9cqgs); |
|||
} |
|||
return(OK); |
|||
case MOS9_CS : |
|||
if (ckt->CKTcurrentAnalysis & DOING_AC) { |
|||
errMsg = MALLOC(strlen(msg)+1); |
|||
errRtn = "MOS9ask.c"; |
|||
strcpy(errMsg,msg); |
|||
return(E_ASKCURRENT); |
|||
} else { |
|||
value->rValue = -here->MOS9cd; |
|||
value->rValue -= here->MOS9cbd + here->MOS9cbs - |
|||
*(ckt->CKTstate0 + here->MOS9cqgb); |
|||
if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && |
|||
!(ckt->CKTmode & MODETRANOP)) { |
|||
value->rValue -= *(ckt->CKTstate0 + here->MOS9cqgb) + |
|||
*(ckt->CKTstate0 + here->MOS9cqgd) + |
|||
*(ckt->CKTstate0 + here->MOS9cqgs); |
|||
} |
|||
} |
|||
return(OK); |
|||
case MOS9_POWER : |
|||
if (ckt->CKTcurrentAnalysis & DOING_AC) { |
|||
errMsg = MALLOC(strlen(msg)+1); |
|||
errRtn = "MOS9ask.c"; |
|||
strcpy(errMsg,msg); |
|||
return(E_ASKPOWER); |
|||
} else { |
|||
double temp; |
|||
|
|||
value->rValue = here->MOS9cd * |
|||
*(ckt->CKTrhsOld + here->MOS9dNode); |
|||
value->rValue += (here->MOS9cbd + here->MOS9cbs - |
|||
*(ckt->CKTstate0 + here->MOS9cqgb)) * |
|||
*(ckt->CKTrhsOld + here->MOS9bNode); |
|||
if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && |
|||
!(ckt->CKTmode & MODETRANOP)) { |
|||
value->rValue += (*(ckt->CKTstate0 + here->MOS9cqgb) + |
|||
*(ckt->CKTstate0 + here->MOS9cqgd) + |
|||
*(ckt->CKTstate0 + here->MOS9cqgs)) * |
|||
*(ckt->CKTrhsOld + here->MOS9gNode); |
|||
} |
|||
temp = -here->MOS9cd; |
|||
temp -= here->MOS9cbd + here->MOS9cbs ; |
|||
if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && |
|||
!(ckt->CKTmode & MODETRANOP)) { |
|||
temp -= *(ckt->CKTstate0 + here->MOS9cqgb) + |
|||
*(ckt->CKTstate0 + here->MOS9cqgd) + |
|||
*(ckt->CKTstate0 + here->MOS9cqgs); |
|||
} |
|||
value->rValue += temp * *(ckt->CKTrhsOld + here->MOS9sNode); |
|||
} |
|||
return(OK); |
|||
default: |
|||
return(E_BADPARM); |
|||
} |
|||
/* NOTREACHED */ |
|||
} |
|||
|
|||
@ -0,0 +1,104 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "cktdefs.h" |
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
|
|||
#include "suffix.h" |
|||
|
|||
int |
|||
MOS9convTest(inModel,ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
MOS9model *model = (MOS9model *)inModel; |
|||
MOS9instance *here; |
|||
double delvbs; |
|||
double delvbd; |
|||
double delvgs; |
|||
double delvds; |
|||
double delvgd; |
|||
double cbhat; |
|||
double cdhat; |
|||
double vbs; |
|||
double vbd; |
|||
double vgs; |
|||
double vds; |
|||
double vgd; |
|||
double vgdo; |
|||
double tol; |
|||
|
|||
for( ; model != NULL; model = model->MOS9nextModel) { |
|||
for(here = model->MOS9instances; here!= NULL; |
|||
here = here->MOS9nextInstance) { |
|||
|
|||
vbs = model->MOS9type * ( |
|||
*(ckt->CKTrhs+here->MOS9bNode) - |
|||
*(ckt->CKTrhs+here->MOS9sNodePrime)); |
|||
vgs = model->MOS9type * ( |
|||
*(ckt->CKTrhs+here->MOS9gNode) - |
|||
*(ckt->CKTrhs+here->MOS9sNodePrime)); |
|||
vds = model->MOS9type * ( |
|||
*(ckt->CKTrhs+here->MOS9dNodePrime) - |
|||
*(ckt->CKTrhs+here->MOS9sNodePrime)); |
|||
vbd=vbs-vds; |
|||
vgd=vgs-vds; |
|||
vgdo = *(ckt->CKTstate0 + here->MOS9vgs) - |
|||
*(ckt->CKTstate0 + here->MOS9vds); |
|||
delvbs = vbs - *(ckt->CKTstate0 + here->MOS9vbs); |
|||
delvbd = vbd - *(ckt->CKTstate0 + here->MOS9vbd); |
|||
delvgs = vgs - *(ckt->CKTstate0 + here->MOS9vgs); |
|||
delvds = vds - *(ckt->CKTstate0 + here->MOS9vds); |
|||
delvgd = vgd-vgdo; |
|||
|
|||
/* these are needed for convergence testing */ |
|||
|
|||
if (here->MOS9mode >= 0) { |
|||
cdhat= |
|||
here->MOS9cd- |
|||
here->MOS9gbd * delvbd + |
|||
here->MOS9gmbs * delvbs + |
|||
here->MOS9gm * delvgs + |
|||
here->MOS9gds * delvds ; |
|||
} else { |
|||
cdhat= |
|||
here->MOS9cd - |
|||
( here->MOS9gbd - |
|||
here->MOS9gmbs) * delvbd - |
|||
here->MOS9gm * delvgd + |
|||
here->MOS9gds * delvds ; |
|||
} |
|||
cbhat= |
|||
here->MOS9cbs + |
|||
here->MOS9cbd + |
|||
here->MOS9gbd * delvbd + |
|||
here->MOS9gbs * delvbs ; |
|||
/* |
|||
* check convergence |
|||
*/ |
|||
tol=ckt->CKTreltol*MAX(fabs(cdhat),fabs(here->MOS9cd))+ |
|||
ckt->CKTabstol; |
|||
if (fabs(cdhat-here->MOS9cd) >= tol) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) here; |
|||
return(OK); /* no reason to continue, we haven't converged */ |
|||
} else { |
|||
tol=ckt->CKTreltol* |
|||
MAX(fabs(cbhat),fabs(here->MOS9cbs+here->MOS9cbd)) |
|||
+ ckt->CKTabstol; |
|||
if (fabs(cbhat-(here->MOS9cbs+here->MOS9cbd)) > tol) { |
|||
ckt->CKTnoncon++; |
|||
ckt->CKTtroubleElt = (GENinstance *) here; |
|||
return(OK); /* no reason to continue, we haven't converged*/ |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return(OK); |
|||
} |
|||
@ -0,0 +1,560 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
#ifndef MOS9 |
|||
#define MOS9 |
|||
|
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "gendefs.h" |
|||
#include "complex.h" |
|||
#include "noisedef.h" |
|||
|
|||
/* declarations for level 9 MOSFETs */ |
|||
|
|||
/* information needed for each instance */ |
|||
|
|||
typedef struct sMOS9instance { |
|||
struct sMOS9model *MOS9modPtr; /* backpointer to model */ |
|||
struct sMOS9instance *MOS9nextInstance; /* pointer to next instance of |
|||
*current model*/ |
|||
IFuid MOS9name; /* pointer to character string naming this instance */ |
|||
int MOS9owner; /* number of owner process */ |
|||
int MOS9states; /* index into state table for this device */ |
|||
int MOS9dNode; /* number of the gate node of the mosfet */ |
|||
int MOS9gNode; /* number of the gate node of the mosfet */ |
|||
int MOS9sNode; /* number of the source node of the mosfet */ |
|||
int MOS9bNode; /* number of the bulk node of the mosfet */ |
|||
int MOS9dNodePrime; /* number of the internal drain node of the mosfet */ |
|||
int MOS9sNodePrime; /* number of the internal source node of the mosfet */ |
|||
|
|||
double MOS9m; /* parallel device multiplier */ |
|||
double MOS9l; /* the length of the channel region */ |
|||
double MOS9w; /* the width of the channel region */ |
|||
double MOS9drainArea; /* the area of the drain diffusion */ |
|||
double MOS9sourceArea; /* the area of the source diffusion */ |
|||
double MOS9drainSquares; /* the length of the drain in squares */ |
|||
double MOS9sourceSquares; /* the length of the source in squares */ |
|||
double MOS9drainPerimiter; |
|||
double MOS9sourcePerimiter; |
|||
double MOS9sourceConductance; /*conductance of source(or 0):set in setup*/ |
|||
double MOS9drainConductance; /*conductance of drain(or 0):set in setup*/ |
|||
double MOS9temp; /* operating temperature of this instance */ |
|||
|
|||
double MOS9tTransconductance; /* temperature corrected transconductance*/ |
|||
double MOS9tSurfMob; /* temperature corrected surface mobility */ |
|||
double MOS9tPhi; /* temperature corrected Phi */ |
|||
double MOS9tVto; /* temperature corrected Vto */ |
|||
double MOS9tSatCur; /* temperature corrected saturation Cur. */ |
|||
double MOS9tSatCurDens; /* temperature corrected saturation Cur. density*/ |
|||
double MOS9tCbd; /* temperature corrected B-D Capacitance */ |
|||
double MOS9tCbs; /* temperature corrected B-S Capacitance */ |
|||
double MOS9tCj; /* temperature corrected Bulk bottom Capacitance */ |
|||
double MOS9tCjsw; /* temperature corrected Bulk side Capacitance */ |
|||
double MOS9tBulkPot; /* temperature corrected Bulk potential */ |
|||
double MOS9tDepCap; /* temperature adjusted transition point in */ |
|||
/* the cureve matching Fc * Vj */ |
|||
double MOS9tVbi; /* temperature adjusted Vbi */ |
|||
|
|||
double MOS9icVBS; /* initial condition B-S voltage */ |
|||
double MOS9icVDS; /* initial condition D-S voltage */ |
|||
double MOS9icVGS; /* initial condition G-S voltage */ |
|||
double MOS9von; |
|||
double MOS9vdsat; |
|||
double MOS9sourceVcrit; /* vcrit for pos. vds */ |
|||
double MOS9drainVcrit; /* vcrit for neg. vds */ |
|||
double MOS9cd; |
|||
double MOS9cbs; |
|||
double MOS9cbd; |
|||
double MOS9gmbs; |
|||
double MOS9gm; |
|||
double MOS9gds; |
|||
double MOS9gbd; |
|||
double MOS9gbs; |
|||
double MOS9capbd; |
|||
double MOS9capbs; |
|||
double MOS9Cbd; |
|||
double MOS9Cbdsw; |
|||
double MOS9Cbs; |
|||
double MOS9Cbssw; |
|||
double MOS9f2d; |
|||
double MOS9f3d; |
|||
double MOS9f4d; |
|||
double MOS9f2s; |
|||
double MOS9f3s; |
|||
double MOS9f4s; |
|||
int MOS9mode; /* device mode : 1 = normal, -1 = inverse */ |
|||
|
|||
|
|||
unsigned MOS9off :1;/* non-zero to indicate device is off for dc analysis*/ |
|||
unsigned MOS9tempGiven :1; /* instance temperature specified */ |
|||
|
|||
unsigned MOS9mGiven :1; |
|||
|
|||
unsigned MOS9lGiven :1; |
|||
unsigned MOS9wGiven :1; |
|||
unsigned MOS9drainAreaGiven :1; |
|||
unsigned MOS9sourceAreaGiven :1; |
|||
unsigned MOS9drainSquaresGiven :1; |
|||
unsigned MOS9sourceSquaresGiven :1; |
|||
unsigned MOS9drainPerimiterGiven :1; |
|||
unsigned MOS9sourcePerimiterGiven :1; |
|||
unsigned MOS9dNodePrimeSet :1; |
|||
unsigned MOS9sNodePrimeSet :1; |
|||
unsigned MOS9icVBSGiven :1; |
|||
unsigned MOS9icVDSGiven :1; |
|||
unsigned MOS9icVGSGiven :1; |
|||
unsigned MOS9vonGiven :1; |
|||
unsigned MOS9vdsatGiven :1; |
|||
unsigned MOS9modeGiven :1; |
|||
|
|||
|
|||
double *MOS9DdPtr; /* pointer to sparse matrix element at |
|||
* (Drain node,drain node) */ |
|||
double *MOS9GgPtr; /* pointer to sparse matrix element at |
|||
* (gate node,gate node) */ |
|||
double *MOS9SsPtr; /* pointer to sparse matrix element at |
|||
* (source node,source node) */ |
|||
double *MOS9BbPtr; /* pointer to sparse matrix element at |
|||
* (bulk node,bulk node) */ |
|||
double *MOS9DPdpPtr; /* pointer to sparse matrix element at |
|||
* (drain prime node,drain prime node) */ |
|||
double *MOS9SPspPtr; /* pointer to sparse matrix element at |
|||
* (source prime node,source prime node) */ |
|||
double *MOS9DdpPtr; /* pointer to sparse matrix element at |
|||
* (drain node,drain prime node) */ |
|||
double *MOS9GbPtr; /* pointer to sparse matrix element at |
|||
* (gate node,bulk node) */ |
|||
double *MOS9GdpPtr; /* pointer to sparse matrix element at |
|||
* (gate node,drain prime node) */ |
|||
double *MOS9GspPtr; /* pointer to sparse matrix element at |
|||
* (gate node,source prime node) */ |
|||
double *MOS9SspPtr; /* pointer to sparse matrix element at |
|||
* (source node,source prime node) */ |
|||
double *MOS9BdpPtr; /* pointer to sparse matrix element at |
|||
* (bulk node,drain prime node) */ |
|||
double *MOS9BspPtr; /* pointer to sparse matrix element at |
|||
* (bulk node,source prime node) */ |
|||
double *MOS9DPspPtr; /* pointer to sparse matrix element at |
|||
* (drain prime node,source prime node) */ |
|||
double *MOS9DPdPtr; /* pointer to sparse matrix element at |
|||
* (drain prime node,drain node) */ |
|||
double *MOS9BgPtr; /* pointer to sparse matrix element at |
|||
* (bulk node,gate node) */ |
|||
double *MOS9DPgPtr; /* pointer to sparse matrix element at |
|||
* (drain prime node,gate node) */ |
|||
|
|||
double *MOS9SPgPtr; /* pointer to sparse matrix element at |
|||
* (source prime node,gate node) */ |
|||
double *MOS9SPsPtr; /* pointer to sparse matrix element at |
|||
* (source prime node,source node) */ |
|||
double *MOS9DPbPtr; /* pointer to sparse matrix element at |
|||
* (drain prime node,bulk node) */ |
|||
double *MOS9SPbPtr; /* pointer to sparse matrix element at |
|||
* (source prime node,bulk node) */ |
|||
double *MOS9SPdpPtr; /* pointer to sparse matrix element at |
|||
* (source prime node,drain prime node) */ |
|||
int MOS9senParmNo; /* parameter # for sensitivity use; |
|||
set equal to 0 if neither length |
|||
nor width of the mosfet is a design |
|||
parameter */ |
|||
unsigned MOS9sens_l :1; /* field which indicates whether |
|||
length of the mosfet is a design |
|||
parameter or not */ |
|||
unsigned MOS9sens_w :1; /* field which indicates whether |
|||
width of the mosfet is a design |
|||
parameter or not */ |
|||
unsigned MOS9senPertFlag :1; /* indictes whether the the parameter of |
|||
the particular instance is to be perturbed */ |
|||
double MOS9cgs; |
|||
double MOS9cgd; |
|||
double MOS9cgb; |
|||
double *MOS9sens; |
|||
|
|||
#define MOS9senGdpr MOS9sens |
|||
#define MOS9senGspr MOS9sens + 1 |
|||
#define MOS9senCgs MOS9sens + 2 /* contains pertured values of cgs */ |
|||
#define MOS9senCgd MOS9sens + 8 /* contains perturbed values of cgd*/ |
|||
#define MOS9senCgb MOS9sens + 14 /* contains perturbed values of cgb*/ |
|||
#define MOS9senCbd MOS9sens + 20 /* contains perturbed values of cbd*/ |
|||
#define MOS9senCbs MOS9sens + 26 /* contains perturbed values of cbs*/ |
|||
#define MOS9senGds MOS9sens + 32 /* contains perturbed values of gds*/ |
|||
#define MOS9senGbs MOS9sens + 38 /* contains perturbed values of gbs*/ |
|||
#define MOS9senGbd MOS9sens + 44 /* contains perturbed values of gbd*/ |
|||
#define MOS9senGm MOS9sens + 50 /* contains perturbed values of gm*/ |
|||
#define MOS9senGmbs MOS9sens + 56 /* contains perturbed values of gmbs*/ |
|||
#define MOS9dphigs_dl MOS9sens + 62 |
|||
#define MOS9dphigd_dl MOS9sens + 63 |
|||
#define MOS9dphigb_dl MOS9sens + 64 |
|||
#define MOS9dphibs_dl MOS9sens + 65 |
|||
#define MOS9dphibd_dl MOS9sens + 66 |
|||
#define MOS9dphigs_dw MOS9sens + 67 |
|||
#define MOS9dphigd_dw MOS9sens + 68 |
|||
#define MOS9dphigb_dw MOS9sens + 69 |
|||
#define MOS9dphibs_dw MOS9sens + 70 |
|||
#define MOS9dphibd_dw MOS9sens + 71 |
|||
|
|||
/* distortion stuff */ |
|||
/* |
|||
* naming convention: |
|||
* x = vgs |
|||
* y = vbs |
|||
* z = vds |
|||
* cdr = cdrain |
|||
*/ |
|||
|
|||
|
|||
#define MOS9NDCOEFFS 30 |
|||
|
|||
#ifndef NODISTO |
|||
double MOS9dCoeffs[MOS9NDCOEFFS]; |
|||
#else /* NODISTO */ |
|||
double *MOS9dCoeffs; |
|||
#endif /* NODISTO */ |
|||
|
|||
#ifndef CONFIG |
|||
|
|||
#define capbs2 MOS9dCoeffs[0] |
|||
#define capbs3 MOS9dCoeffs[1] |
|||
#define capbd2 MOS9dCoeffs[2] |
|||
#define capbd3 MOS9dCoeffs[3] |
|||
#define gbs2 MOS9dCoeffs[4] |
|||
#define gbs3 MOS9dCoeffs[5] |
|||
#define gbd2 MOS9dCoeffs[6] |
|||
#define gbd3 MOS9dCoeffs[7] |
|||
#define capgb2 MOS9dCoeffs[8] |
|||
#define capgb3 MOS9dCoeffs[9] |
|||
#define cdr_x2 MOS9dCoeffs[10] |
|||
#define cdr_y2 MOS9dCoeffs[11] |
|||
#define cdr_z2 MOS9dCoeffs[12] |
|||
#define cdr_xy MOS9dCoeffs[13] |
|||
#define cdr_yz MOS9dCoeffs[14] |
|||
#define cdr_xz MOS9dCoeffs[15] |
|||
#define cdr_x3 MOS9dCoeffs[16] |
|||
#define cdr_y3 MOS9dCoeffs[17] |
|||
#define cdr_z3 MOS9dCoeffs[18] |
|||
#define cdr_x2z MOS9dCoeffs[19] |
|||
#define cdr_x2y MOS9dCoeffs[20] |
|||
#define cdr_y2z MOS9dCoeffs[21] |
|||
#define cdr_xy2 MOS9dCoeffs[22] |
|||
#define cdr_xz2 MOS9dCoeffs[23] |
|||
#define cdr_yz2 MOS9dCoeffs[24] |
|||
#define cdr_xyz MOS9dCoeffs[25] |
|||
#define capgs2 MOS9dCoeffs[26] |
|||
#define capgs3 MOS9dCoeffs[27] |
|||
#define capgd2 MOS9dCoeffs[28] |
|||
#define capgd3 MOS9dCoeffs[29] |
|||
|
|||
#endif |
|||
|
|||
/* end distortion coeffs. */ |
|||
/* indices to the array of MOSFET(3) noise sources */ |
|||
|
|||
#define MOS9RDNOIZ 0 |
|||
#define MOS9RSNOIZ 1 |
|||
#define MOS9IDNOIZ 2 |
|||
#define MOS9FLNOIZ 3 |
|||
#define MOS9TOTNOIZ 4 |
|||
|
|||
#define MOS9NSRCS 5 /* the number of MOSFET(9) noise sources */ |
|||
|
|||
#ifndef NONOISE |
|||
double MOS9nVar[NSTATVARS][MOS9NSRCS]; |
|||
#else /* NONOISE */ |
|||
double **MOS9nVar; |
|||
#endif /* NONOISE */ |
|||
|
|||
} MOS9instance ; |
|||
|
|||
#define MOS9vbd MOS9states+ 0 |
|||
#define MOS9vbs MOS9states+ 1 |
|||
#define MOS9vgs MOS9states+ 2 |
|||
#define MOS9vds MOS9states+ 3 |
|||
|
|||
/* meyer capacitances */ |
|||
#define MOS9capgs MOS9states+ 4 /* gate-source capacitor value */ |
|||
#define MOS9qgs MOS9states+ 5 /* gate-source capacitor charge */ |
|||
#define MOS9cqgs MOS9states+ 6 /* gate-source capacitor current */ |
|||
|
|||
#define MOS9capgd MOS9states+ 7 /* gate-drain capacitor value */ |
|||
#define MOS9qgd MOS9states+ 8 /* gate-drain capacitor charge */ |
|||
#define MOS9cqgd MOS9states+ 9 /* gate-drain capacitor current */ |
|||
|
|||
#define MOS9capgb MOS9states+ 10/* gate-bulk capacitor value */ |
|||
#define MOS9qgb MOS9states+ 11 /* gate-bulk capacitor charge */ |
|||
#define MOS9cqgb MOS9states+ 12 /* gate-bulk capacitor current */ |
|||
|
|||
/* diode capacitances */ |
|||
#define MOS9qbd MOS9states+ 13 /* bulk-drain capacitor charge */ |
|||
#define MOS9cqbd MOS9states+ 14 /* bulk-drain capacitor current */ |
|||
|
|||
#define MOS9qbs MOS9states+ 15 /* bulk-source capacitor charge */ |
|||
#define MOS9cqbs MOS9states+ 16 /* bulk-source capacitor current */ |
|||
|
|||
#define MOS9NUMSTATES 17 |
|||
|
|||
|
|||
#define MOS9sensxpgs MOS9states+17 /* charge sensitivities and their derivatives |
|||
+18 for the derivatives - pointer to the |
|||
beginning of the array */ |
|||
#define MOS9sensxpgd MOS9states+19 |
|||
#define MOS9sensxpgb MOS9states+21 |
|||
#define MOS9sensxpbs MOS9states+23 |
|||
#define MOS9sensxpbd MOS9states+25 |
|||
|
|||
#define MOS9numSenStates 10 |
|||
|
|||
|
|||
/* per model data */ |
|||
|
|||
/* NOTE: parameters marked 'input - use xxxx' are paramters for |
|||
* which a temperature correction is applied in MOS9temp, thus |
|||
* the MOS9xxxx value in the per-instance structure should be used |
|||
* instead in all calculations |
|||
*/ |
|||
|
|||
typedef struct sMOS9model { /* model structure for a resistor */ |
|||
int MOS9modType; /* type index of this device type */ |
|||
struct sMOS9model *MOS9nextModel; /* pointer to next possible model |
|||
*in linked list */ |
|||
MOS9instance * MOS9instances; /* pointer to list of instances |
|||
* that have this model */ |
|||
IFuid MOS9modName; /* pointer to character string naming this model */ |
|||
int MOS9type; /* device type : 1 = nmos, -1 = pmos */ |
|||
double MOS9tnom; /* temperature at which parameters measured */ |
|||
double MOS9latDiff; |
|||
double MOS9lengthAdjust; /* New parm: mask adjustment to length */ |
|||
double MOS9widthNarrow; /* New parm to reduce effective width */ |
|||
double MOS9widthAdjust; /* New parm: mask adjustment to width */ |
|||
double MOS9delvt0; /* New parm: adjustment to calculated vtO */ |
|||
double MOS9jctSatCurDensity; /* input - use tSatCurDens*/ |
|||
double MOS9jctSatCur; /* input - use tSatCur instead */ |
|||
double MOS9drainResistance; |
|||
double MOS9sourceResistance; |
|||
double MOS9sheetResistance; |
|||
double MOS9transconductance; /* input - use tTransconductance */ |
|||
double MOS9gateSourceOverlapCapFactor; |
|||
double MOS9gateDrainOverlapCapFactor; |
|||
double MOS9gateBulkOverlapCapFactor; |
|||
double MOS9oxideCapFactor; |
|||
double MOS9vt0; /* input - use tVto */ |
|||
double MOS9capBD; /* input - use tCbs */ |
|||
double MOS9capBS; /* input - use tCbd */ |
|||
double MOS9bulkCapFactor; /* input - use tCj */ |
|||
double MOS9sideWallCapFactor; /* input - use tCjsw */ |
|||
double MOS9bulkJctPotential; /* input - use tBulkPot */ |
|||
double MOS9bulkJctBotGradingCoeff; |
|||
double MOS9bulkJctSideGradingCoeff; |
|||
double MOS9fwdCapDepCoeff; |
|||
double MOS9phi; /* input - use tPhi */ |
|||
double MOS9gamma; |
|||
double MOS9substrateDoping; |
|||
int MOS9gateType; |
|||
double MOS9surfaceStateDensity; |
|||
double MOS9oxideThickness; |
|||
double MOS9surfaceMobility; /* input - use tSurfMob */ |
|||
double MOS9eta; |
|||
double MOS9junctionDepth; |
|||
double MOS9coeffDepLayWidth; /* xd */ |
|||
double MOS9narrowFactor; /* delta */ |
|||
double MOS9delta; /* input delta */ |
|||
double MOS9fastSurfaceStateDensity; /* nfs */ |
|||
double MOS9theta; /* theta */ |
|||
double MOS9maxDriftVel; /* vmax */ |
|||
double MOS9alpha; /* alpha */ |
|||
double MOS9kappa; /* kappa */ |
|||
double MOS9fNcoef; |
|||
double MOS9fNexp; |
|||
|
|||
unsigned MOS9typeGiven :1; |
|||
unsigned MOS9latDiffGiven :1; |
|||
unsigned MOS9lengthAdjustGiven :1; |
|||
unsigned MOS9widthNarrowGiven :1; |
|||
unsigned MOS9widthAdjustGiven :1; |
|||
unsigned MOS9delvt0Given :1; |
|||
unsigned MOS9jctSatCurDensityGiven :1; |
|||
unsigned MOS9jctSatCurGiven :1; |
|||
unsigned MOS9drainResistanceGiven :1; |
|||
unsigned MOS9sourceResistanceGiven :1; |
|||
unsigned MOS9sheetResistanceGiven :1; |
|||
unsigned MOS9transconductanceGiven :1; |
|||
unsigned MOS9gateSourceOverlapCapFactorGiven :1; |
|||
unsigned MOS9gateDrainOverlapCapFactorGiven :1; |
|||
unsigned MOS9gateBulkOverlapCapFactorGiven :1; |
|||
unsigned MOS9vt0Given :1; |
|||
unsigned MOS9capBDGiven :1; |
|||
unsigned MOS9capBSGiven :1; |
|||
unsigned MOS9bulkCapFactorGiven :1; |
|||
unsigned MOS9sideWallCapFactorGiven :1; |
|||
unsigned MOS9bulkJctPotentialGiven :1; |
|||
unsigned MOS9bulkJctBotGradingCoeffGiven :1; |
|||
unsigned MOS9bulkJctSideGradingCoeffGiven :1; |
|||
unsigned MOS9fwdCapDepCoeffGiven :1; |
|||
unsigned MOS9phiGiven :1; |
|||
unsigned MOS9gammaGiven :1; |
|||
unsigned MOS9substrateDopingGiven :1; |
|||
unsigned MOS9gateTypeGiven :1; |
|||
unsigned MOS9surfaceStateDensityGiven :1; |
|||
unsigned MOS9oxideThicknessGiven :1; |
|||
unsigned MOS9surfaceMobilityGiven :1; |
|||
unsigned MOS9etaGiven :1; |
|||
unsigned MOS9junctionDepthGiven :1; |
|||
unsigned MOS9deltaGiven :1; /* delta */ |
|||
unsigned MOS9fastSurfaceStateDensityGiven :1; /* nfs */ |
|||
unsigned MOS9thetaGiven :1; /* theta */ |
|||
unsigned MOS9maxDriftVelGiven :1; /* vmax */ |
|||
unsigned MOS9kappaGiven :1; /* kappa */ |
|||
unsigned MOS9tnomGiven :1; /* Tnom was given? */ |
|||
unsigned MOS9fNcoefGiven :1; |
|||
unsigned MOS9fNexpGiven :1; |
|||
|
|||
} MOS9model; |
|||
|
|||
#ifndef NMOS |
|||
#define NMOS 1 |
|||
#define PMOS -1 |
|||
#endif /*NMOS*/ |
|||
|
|||
/* device parameters */ |
|||
#define MOS9_W 1 |
|||
#define MOS9_L 2 |
|||
#define MOS9_AS 3 |
|||
#define MOS9_AD 4 |
|||
#define MOS9_PS 5 |
|||
#define MOS9_PD 6 |
|||
#define MOS9_NRS 7 |
|||
#define MOS9_NRD 8 |
|||
#define MOS9_OFF 9 |
|||
#define MOS9_IC 10 |
|||
#define MOS9_IC_VBS 11 |
|||
#define MOS9_IC_VDS 12 |
|||
#define MOS9_IC_VGS 13 |
|||
#define MOS9_W_SENS 14 |
|||
#define MOS9_L_SENS 15 |
|||
#define MOS9_CB 16 |
|||
#define MOS9_CG 17 |
|||
#define MOS9_CS 18 |
|||
#define MOS9_POWER 19 |
|||
#define MOS9_CGS 20 |
|||
#define MOS9_CGD 21 |
|||
#define MOS9_DNODE 22 |
|||
#define MOS9_GNODE 23 |
|||
#define MOS9_SNODE 24 |
|||
#define MOS9_BNODE 25 |
|||
#define MOS9_DNODEPRIME 26 |
|||
#define MOS9_SNODEPRIME 27 |
|||
#define MOS9_SOURCECONDUCT 28 |
|||
#define MOS9_DRAINCONDUCT 29 |
|||
#define MOS9_VON 30 |
|||
#define MOS9_VDSAT 31 |
|||
#define MOS9_SOURCEVCRIT 32 |
|||
#define MOS9_DRAINVCRIT 33 |
|||
#define MOS9_CD 34 |
|||
#define MOS9_CBS 35 |
|||
#define MOS9_CBD 36 |
|||
#define MOS9_GMBS 37 |
|||
#define MOS9_GM 38 |
|||
#define MOS9_GDS 39 |
|||
#define MOS9_GBD 40 |
|||
#define MOS9_GBS 41 |
|||
#define MOS9_CAPBD 42 |
|||
#define MOS9_CAPBS 43 |
|||
#define MOS9_CAPZEROBIASBD 44 |
|||
#define MOS9_CAPZEROBIASBDSW 45 |
|||
#define MOS9_CAPZEROBIASBS 46 |
|||
#define MOS9_CAPZEROBIASBSSW 47 |
|||
#define MOS9_VBD 48 |
|||
#define MOS9_VBS 49 |
|||
#define MOS9_VGS 50 |
|||
#define MOS9_VDS 51 |
|||
#define MOS9_CAPGS 52 |
|||
#define MOS9_QGS 53 |
|||
#define MOS9_CQGS 54 |
|||
#define MOS9_CAPGD 55 |
|||
#define MOS9_QGD 56 |
|||
#define MOS9_CQGD 57 |
|||
#define MOS9_CAPGB 58 |
|||
#define MOS9_QGB 59 |
|||
#define MOS9_CQGB 60 |
|||
#define MOS9_QBD 61 |
|||
#define MOS9_CQBD 62 |
|||
#define MOS9_QBS 63 |
|||
#define MOS9_CQBS 64 |
|||
#define MOS9_W_SENS_REAL 65 |
|||
#define MOS9_W_SENS_IMAG 66 |
|||
#define MOS9_W_SENS_MAG 67 |
|||
#define MOS9_W_SENS_PH 68 |
|||
#define MOS9_W_SENS_CPLX 69 |
|||
#define MOS9_L_SENS_REAL 70 |
|||
#define MOS9_L_SENS_IMAG 71 |
|||
#define MOS9_L_SENS_MAG 72 |
|||
#define MOS9_L_SENS_PH 73 |
|||
#define MOS9_L_SENS_CPLX 74 |
|||
#define MOS9_W_SENS_DC 75 |
|||
#define MOS9_L_SENS_DC 76 |
|||
#define MOS9_TEMP 77 |
|||
#define MOS9_SOURCERESIST 78 |
|||
#define MOS9_DRAINRESIST 79 |
|||
#define MOS9_M 80
|
|||
|
|||
/* model parameters */ |
|||
#define MOS9_MOD_VTO 101 |
|||
#define MOS9_MOD_KP 102 |
|||
#define MOS9_MOD_GAMMA 103 |
|||
#define MOS9_MOD_PHI 104 |
|||
#define MOS9_MOD_RD 105 |
|||
#define MOS9_MOD_RS 106 |
|||
#define MOS9_MOD_CBD 107 |
|||
#define MOS9_MOD_CBS 108 |
|||
#define MOS9_MOD_IS 109 |
|||
#define MOS9_MOD_PB 110 |
|||
#define MOS9_MOD_CGSO 111 |
|||
#define MOS9_MOD_CGDO 112 |
|||
#define MOS9_MOD_CGBO 113 |
|||
#define MOS9_MOD_RSH 114 |
|||
#define MOS9_MOD_CJ 115 |
|||
#define MOS9_MOD_MJ 116 |
|||
#define MOS9_MOD_CJSW 117 |
|||
#define MOS9_MOD_MJSW 118 |
|||
#define MOS9_MOD_JS 119 |
|||
#define MOS9_MOD_TOX 120 |
|||
#define MOS9_MOD_LD 121 |
|||
#define MOS9_MOD_U0 122 |
|||
#define MOS9_MOD_FC 123 |
|||
#define MOS9_MOD_NSUB 124 |
|||
#define MOS9_MOD_TPG 125 |
|||
#define MOS9_MOD_NSS 126 |
|||
#define MOS9_MOD_ETA 127 |
|||
#define MOS9_MOD_DELTA 128 |
|||
#define MOS9_MOD_NFS 129 |
|||
#define MOS9_MOD_THETA 130 |
|||
#define MOS9_MOD_VMAX 131 |
|||
#define MOS9_MOD_KAPPA 132 |
|||
#define MOS9_MOD_NMOS 133 |
|||
#define MOS9_MOD_PMOS 134 |
|||
#define MOS9_MOD_XJ 135 |
|||
#define MOS9_MOD_UEXP 136 |
|||
#define MOS9_MOD_NEFF 137 |
|||
#define MOS9_MOD_XD 138 |
|||
#define MOS9_MOD_ALPHA 139 |
|||
#define MOS9_DELTA 140 |
|||
#define MOS9_MOD_TNOM 141 |
|||
#define MOS9_MOD_KF 142 |
|||
#define MOS9_MOD_AF 143 |
|||
#define MOS9_MOD_TYPE 144
|
|||
#define MOS9_MOD_XL 145 |
|||
#define MOS9_MOD_WD 146 |
|||
#define MOS9_MOD_XW 147 |
|||
#define MOS9_MOD_DELVTO 148
|
|||
|
|||
/* device questions */ |
|||
|
|||
|
|||
/* model questions */ |
|||
|
|||
#include "mos9ext.h" |
|||
|
|||
#endif /*MOS9*/ |
|||
@ -0,0 +1,39 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
/* |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h>
|
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
int |
|||
MOS9delete(inModel,name,inst) |
|||
GENmodel *inModel; |
|||
IFuid name; |
|||
GENinstance **inst; |
|||
{ |
|||
MOS9model *model = (MOS9model *)inModel; |
|||
MOS9instance **fast = (MOS9instance **)inst; |
|||
MOS9instance **prev = NULL; |
|||
MOS9instance *here; |
|||
|
|||
for( ; model ; model = model->MOS9nextModel) { |
|||
prev = &(model->MOS9instances); |
|||
for(here = *prev; here ; here = *prev) { |
|||
if(here->MOS9name == name || (fast && here==*fast) ) { |
|||
*prev= here->MOS9nextInstance; |
|||
FREE(here); |
|||
return(OK); |
|||
} |
|||
prev = &(here->MOS9nextInstance); |
|||
} |
|||
} |
|||
return(E_NODEV); |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
/* |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h>
|
|||
#include "mos9defs.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
void |
|||
MOS9destroy(inModel) |
|||
GENmodel **inModel; |
|||
{ |
|||
MOS9model **model = (MOS9model **)inModel; |
|||
MOS9instance *here; |
|||
MOS9instance *prev = NULL; |
|||
MOS9model *mod = *model; |
|||
MOS9model *oldmod = NULL; |
|||
|
|||
for( ; mod ; mod = mod->MOS9nextModel) { |
|||
if(oldmod) FREE(oldmod); |
|||
oldmod = mod; |
|||
prev = (MOS9instance *)NULL; |
|||
for(here = mod->MOS9instances ; here ; here = here->MOS9nextInstance) { |
|||
if(prev){ |
|||
if(prev->MOS9sens) FREE(prev->MOS9sens); |
|||
FREE(prev); |
|||
} |
|||
prev = here; |
|||
} |
|||
if(prev) FREE(prev); |
|||
} |
|||
if(oldmod) FREE(oldmod); |
|||
*model = NULL; |
|||
} |
|||
1386
src/spicelib/devices/mos9/mos9dist.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,979 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1988 Jaijeet S Roychowdhury |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "cktdefs.h" |
|||
#include "devdefs.h" |
|||
#include "mos9defs.h"
|
|||
#include "trandefs.h" |
|||
#include "distodef.h" |
|||
#include "const.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
MOS9dSetup(inModel,ckt) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
/* actually load the current value into the |
|||
* sparse matrix previously provided |
|||
*/ |
|||
{ |
|||
register MOS9model *model = (MOS9model *)inModel; |
|||
register MOS9instance *here; |
|||
double Beta; |
|||
double DrainSatCur; |
|||
double EffectiveLength; |
|||
double EffectiveWidth; |
|||
double GateBulkOverlapCap; |
|||
double GateDrainOverlapCap; |
|||
double GateSourceOverlapCap; |
|||
double OxideCap; |
|||
double SourceSatCur; |
|||
double arg; |
|||
double cdrain; |
|||
double evbs; |
|||
double sarg; |
|||
double sargsw; |
|||
double lvgs; |
|||
double vbd; |
|||
double vbs; |
|||
double vds; |
|||
double vdsat; |
|||
double vgb; |
|||
double vgd; |
|||
double vgs; |
|||
double von; |
|||
double lcapgs2,lcapgs3; /* total gate-source capacitance */ |
|||
double lcapgd2,lcapgd3; /* total gate-drain capacitance */ |
|||
double lcapgb2,lcapgb3; /* total gate-bulk capacitance */ |
|||
double lgbs, lgbs2, lgbs3; |
|||
double lgbd, lgbd2, lgbd3; |
|||
double gm2, gb2, gds2, gmb, gmds, gbds; |
|||
double gm3, gb3, gds3, gm2ds, gm2b, gb2ds, gbds2, gmb2, gmds2, gmbds; |
|||
double lcapbd, lcapbd2, lcapbd3; |
|||
double lcapbs, lcapbs2, lcapbs3; |
|||
double ebd; |
|||
double vt; /* vt at instance temperature */ |
|||
Dderivs d_cdrain; |
|||
|
|||
|
|||
|
|||
/* loop through all the MOS9 device models */ |
|||
next: for( ; model != NULL; model = model->MOS9nextModel ) { |
|||
|
|||
/* loop through all the instances of the model */ |
|||
for (here = model->MOS9instances; here != NULL ; |
|||
here=here->MOS9nextInstance) { |
|||
|
|||
vt = CONSTKoverQ * here->MOS9temp; |
|||
|
|||
|
|||
/* first, we compute a few useful values - these could be |
|||
* pre-computed, but for historical reasons are still done |
|||
* here. They may be moved at the expense of instance size |
|||
*/ |
|||
|
|||
EffectiveWidth=here->MOS9w-2*model->MOS9widthNarrow+ |
|||
model->MOS9widthAdjust; |
|||
EffectiveLength=here->MOS9l - 2*model->MOS9latDiff+ |
|||
model->MOS9lengthAdjust; |
|||
|
|||
if( (here->MOS9tSatCurDens == 0) || |
|||
(here->MOS9drainArea == 0) || |
|||
(here->MOS9sourceArea == 0)) { |
|||
DrainSatCur = here->MOS9m * here->MOS9tSatCur; |
|||
SourceSatCur = here->MOS9m * here->MOS9tSatCur; |
|||
} else { |
|||
DrainSatCur = here->MOS9tSatCurDens * |
|||
here->MOS9m * here->MOS9drainArea; |
|||
SourceSatCur = here->MOS9tSatCurDens * |
|||
here->MOS9m * here->MOS9sourceArea; |
|||
} |
|||
GateSourceOverlapCap = model->MOS9gateSourceOverlapCapFactor * |
|||
here->MOS9m * EffectiveWidth; |
|||
GateDrainOverlapCap = model->MOS9gateDrainOverlapCapFactor * |
|||
here->MOS9m * EffectiveWidth; |
|||
GateBulkOverlapCap = model->MOS9gateBulkOverlapCapFactor * |
|||
here->MOS9m * EffectiveLength; |
|||
Beta = here->MOS9tTransconductance * here->MOS9m * |
|||
EffectiveWidth/EffectiveLength; |
|||
OxideCap = model->MOS9oxideCapFactor * EffectiveLength * |
|||
here->MOS9m * EffectiveWidth; |
|||
|
|||
|
|||
/* |
|||
* ok - now to do the start-up operations |
|||
* |
|||
* we must get values for vbs, vds, and vgs from somewhere |
|||
* so we either predict them or recover them from last iteration |
|||
* These are the two most common cases - either a prediction |
|||
* step or the general iteration step and they |
|||
* share some code, so we put them first - others later on |
|||
*/ |
|||
|
|||
|
|||
/* general iteration */ |
|||
|
|||
vbs = model->MOS9type * ( |
|||
*(ckt->CKTrhsOld+here->MOS9bNode) - |
|||
*(ckt->CKTrhsOld+here->MOS9sNodePrime)); |
|||
vgs = model->MOS9type * ( |
|||
*(ckt->CKTrhsOld+here->MOS9gNode) - |
|||
*(ckt->CKTrhsOld+here->MOS9sNodePrime)); |
|||
vds = model->MOS9type * ( |
|||
*(ckt->CKTrhsOld+here->MOS9dNodePrime) - |
|||
*(ckt->CKTrhsOld+here->MOS9sNodePrime)); |
|||
|
|||
/* now some common crunching for some more useful quantities */ |
|||
|
|||
|
|||
|
|||
/* |
|||
* now all the preliminaries are over - we can start doing the |
|||
* real work |
|||
*/ |
|||
vbd = vbs - vds; |
|||
vgd = vgs - vds; |
|||
vgb = vgs - vbs; |
|||
|
|||
/* bulk-source and bulk-drain doides |
|||
* here we just evaluate the ideal diode current and the |
|||
* correspoinding derivative (conductance). |
|||
*/ |
|||
next1: if(vbs <= 0) { |
|||
lgbs = SourceSatCur/vt; |
|||
lgbs += ckt->CKTgmin; |
|||
lgbs2 = lgbs3 = 0; |
|||
} else { |
|||
evbs = exp(MIN(MAX_EXP_ARG,vbs/vt)); |
|||
lgbs = SourceSatCur*evbs/vt + ckt->CKTgmin; |
|||
lgbs2 = model->MOS9type *0.5 * (lgbs - ckt->CKTgmin)/vt; |
|||
lgbs3 = model->MOS9type *lgbs2/(vt*3); |
|||
|
|||
} |
|||
if(vbd <= 0) { |
|||
lgbd = DrainSatCur/vt; |
|||
lgbd += ckt->CKTgmin; |
|||
lgbd2 = lgbd3 = 0; |
|||
} else { |
|||
ebd = exp(MIN(MAX_EXP_ARG,vbd/vt)); |
|||
lgbd = DrainSatCur*ebd/vt +ckt->CKTgmin; |
|||
lgbd2 = model->MOS9type *0.5 * (lgbd - ckt->CKTgmin)/vt; |
|||
lgbd3 = model->MOS9type *lgbd2/(vt*3); |
|||
} |
|||
|
|||
|
|||
/* now to determine whether the user was able to correctly |
|||
* identify the source and drain of his device |
|||
*/ |
|||
if(vds >= 0) { |
|||
/* normal mode */ |
|||
here->MOS9mode = 1; |
|||
} else { |
|||
/* inverse mode */ |
|||
here->MOS9mode = -1; |
|||
} |
|||
|
|||
{ |
|||
/* |
|||
* subroutine moseq3(vds,vbs,vgs,gm,gds,gmbs, |
|||
* qg,qc,qb,cggb,cgdb,cgsb,cbgb,cbdb,cbsb) |
|||
*/ |
|||
|
|||
/* |
|||
* this routine evaluates the drain current, its derivatives and |
|||
* the charges associated with the gate, channel and bulk |
|||
* for mosfets based on semi-empirical equations |
|||
*/ |
|||
|
|||
/* |
|||
common /mosarg/ vto,beta,gamma,phi,phib,cox,xnsub,xnfs,xd,xj,xld, |
|||
1 xlamda,uo,uexp,vbp,utra,vmax,xneff,xl,xw,vbi,von,vdsat,qspof, |
|||
2 beta0,beta1,cdrain,xqco,xqc,fnarrw,fshort,lev |
|||
common /status/ omega,time,delta,delold(7),ag(7),vt,xni,egfet, |
|||
1 xmu,sfactr,mode,modedc,icalc,initf,method,iord,maxord,noncon, |
|||
2 iterno,itemno,nosolv,modac,ipiv,ivmflg,ipostp,iscrch,iofile |
|||
common /knstnt/ twopi,xlog2,xlog10,root2,rad,boltz,charge,ctok, |
|||
1 gmin,reltol,abstol,vntol,trtol,chgtol,eps0,epssil,epsox, |
|||
2 pivtol,pivrel |
|||
*/ |
|||
|
|||
/* equivalence (xlamda,alpha),(vbp,theta),(uexp,eta),(utra,xkappa)*/ |
|||
|
|||
double coeff0 = 0.0631353e0; |
|||
double coeff1 = 0.8013292e0; |
|||
double coeff2 = -0.01110777e0; |
|||
double oneoverxl; /* 1/effective length */ |
|||
double eta; /* eta from model after length factor */ |
|||
double phibs; /* phi - vbs */ |
|||
double sqphbs; /* square root of phibs */ |
|||
double sqphis; /* square root of phi */ |
|||
double wps; |
|||
double oneoverxj; /* 1/junction depth */ |
|||
double xjonxl; /* junction depth/effective length */ |
|||
double djonxj; |
|||
double wponxj; |
|||
double arga; |
|||
double argb; |
|||
double argc; |
|||
double gammas; |
|||
double fbodys; |
|||
double fbody; |
|||
double onfbdy; |
|||
double qbonco; |
|||
double vbix; |
|||
double wconxj; |
|||
double vth; |
|||
double csonco; |
|||
double cdonco; |
|||
double vgsx; |
|||
double onfg; |
|||
double fgate; |
|||
double us; |
|||
double xn; |
|||
double vdsc; |
|||
double onvdsc; |
|||
double vdsx; |
|||
double cdnorm; |
|||
double cdo; |
|||
double fdrain; |
|||
double gdsat; |
|||
double cdsat; |
|||
double emax; |
|||
double delxl; |
|||
double dlonxl; |
|||
double xlfact; |
|||
double ondvt; |
|||
double onxn; |
|||
double wfact; |
|||
double fshort; |
|||
double lvds, lvbs, lvbd; |
|||
Dderivs d_onxn, d_ondvt, d_wfact, d_MOS9gds; |
|||
Dderivs d_emax, d_delxl, d_dlonxl, d_xlfact; |
|||
Dderivs d_cdonco, d_fdrain, d_cdsat, d_gdsat; |
|||
Dderivs d_vdsx, d_cdo, d_cdnorm, d_Beta, d_dummy; |
|||
Dderivs d_vdsc, d_onvdsc, d_arga, d_argb; |
|||
Dderivs d_onfg, d_fgate, d_us, d_vgsx; |
|||
Dderivs d_von, d_xn, d_vth, d_onfbdy, d_qbonco, d_vbix; |
|||
Dderivs d_argc, d_fshort, d_gammas, d_fbodys, d_fbody; |
|||
Dderivs d_wps, d_wconxj, d_wponxj; |
|||
Dderivs d_phibs, d_sqphbs; |
|||
Dderivs d_p, d_q, d_r, d_zero, d_vdsat; |
|||
|
|||
/* |
|||
* bypasses the computation of charges |
|||
*/ |
|||
if (here->MOS9mode == 1) { |
|||
lvgs = vgs; |
|||
lvds = vds; |
|||
lvbs = vbs; |
|||
lvbd = vbd; |
|||
} else { |
|||
lvgs = vgd; |
|||
lvds = -vds; |
|||
lvbs = vbd; |
|||
lvbd = vbs; |
|||
} |
|||
|
|||
/* |
|||
* reference cdrain equations to source and |
|||
* charge equations to bulk |
|||
*/ |
|||
d_p.value = 0.0; |
|||
d_p.d1_p = 1.0; |
|||
d_p.d1_q = 0.0; |
|||
d_p.d1_r = 0.0; |
|||
d_p.d2_p2 = 0.0; |
|||
d_p.d2_q2 = 0.0; |
|||
d_p.d2_r2 = 0.0; |
|||
d_p.d2_pq = 0.0; |
|||
d_p.d2_qr = 0.0; |
|||
d_p.d2_pr = 0.0; |
|||
d_p.d3_p3 = 0.0; |
|||
d_p.d3_q3 = 0.0; |
|||
d_p.d3_r3 = 0.0; |
|||
d_p.d3_p2r = 0.0; |
|||
d_p.d3_p2q = 0.0; |
|||
d_p.d3_q2r = 0.0; |
|||
d_p.d3_pq2 = 0.0; |
|||
d_p.d3_pr2 = 0.0; |
|||
d_p.d3_qr2 = 0.0; |
|||
d_p.d3_pqr = 0.0; |
|||
EqualDeriv(&d_q,&d_p); |
|||
EqualDeriv(&d_r,&d_p); |
|||
EqualDeriv(&d_zero,&d_p); |
|||
d_q.d1_p = d_r.d1_p = d_zero.d1_p = 0.0; |
|||
d_q.d1_q = d_r.d1_r = 1.0; |
|||
vdsat = 0.0; |
|||
EqualDeriv(&d_vdsat,&d_zero); |
|||
oneoverxl = 1.0/EffectiveLength;/*const*/ |
|||
eta = model->MOS9eta * 8.15e-22/(model->MOS9oxideCapFactor* |
|||
EffectiveLength*EffectiveLength*EffectiveLength);/*const*/ |
|||
/* |
|||
*.....square root term |
|||
*/ |
|||
if ( lvbs <= 0.0 ) { |
|||
phibs = here->MOS9tPhi-lvbs; |
|||
EqualDeriv(&d_phibs,&d_q); |
|||
d_phibs.value = lvbs; |
|||
TimesDeriv(&d_phibs,&d_phibs,-1.0); |
|||
d_phibs.value += here->MOS9tPhi; |
|||
sqphbs = sqrt(phibs); |
|||
SqrtDeriv(&d_sqphbs,&d_phibs); |
|||
} else { |
|||
sqphis = sqrt(here->MOS9tPhi);/*const*/ |
|||
/*sqphs3 = here->MOS9tPhi*sqphis;const*/ |
|||
sqphbs = sqphis/(1.0+lvbs/ |
|||
(here->MOS9tPhi+here->MOS9tPhi)); |
|||
EqualDeriv(&d_sqphbs,&d_q); d_sqphbs.value = lvbs; |
|||
TimesDeriv(&d_sqphbs,&d_sqphbs,1/(here->MOS9tPhi+here->MOS9tPhi)); |
|||
d_sqphbs.value += 1.0; |
|||
InvDeriv(&d_sqphbs,&d_sqphbs); |
|||
TimesDeriv(&d_sqphbs,&d_sqphbs,sqphis); |
|||
phibs = sqphbs*sqphbs; |
|||
MultDeriv(&d_phibs,&d_sqphbs,&d_sqphbs); |
|||
} |
|||
/* |
|||
*.....short channel effect factor |
|||
*/ |
|||
if ( (model->MOS9junctionDepth != 0.0) && |
|||
(model->MOS9coeffDepLayWidth != 0.0) ) { |
|||
wps = model->MOS9coeffDepLayWidth*sqphbs; |
|||
TimesDeriv(&d_wps,&d_sqphbs,model->MOS9coeffDepLayWidth); |
|||
oneoverxj = 1.0/model->MOS9junctionDepth;/*const*/ |
|||
xjonxl = model->MOS9junctionDepth*oneoverxl;/*const*/ |
|||
djonxj = model->MOS9latDiff*oneoverxj;/*const*/ |
|||
wponxj = wps*oneoverxj; |
|||
TimesDeriv(&d_wponxj,&d_wps,oneoverxj); |
|||
wconxj = coeff0+coeff1*wponxj+coeff2*wponxj*wponxj; |
|||
TimesDeriv(&d_wconxj,&d_wponxj,coeff2); |
|||
d_wconxj.value += coeff1; |
|||
MultDeriv(&d_wconxj,&d_wconxj,&d_wponxj); |
|||
d_wconxj.value += coeff0; |
|||
arga = wconxj + djonxj; |
|||
EqualDeriv(&d_arga,&d_wconxj); d_arga.value += djonxj; |
|||
argc = wponxj/(1.0+wponxj); |
|||
EqualDeriv(&d_argc,&d_wponxj); |
|||
d_argc.value += 1.0; |
|||
InvDeriv(&d_argc,&d_argc); |
|||
MultDeriv(&d_argc,&d_argc,&d_wponxj); |
|||
argb = sqrt(1.0-argc*argc); |
|||
MultDeriv(&d_argb,&d_argc,&d_argc); |
|||
TimesDeriv(&d_argb,&d_argb,-1.0); |
|||
d_argb.value += 1.0; |
|||
SqrtDeriv(&d_argb,&d_argb); |
|||
|
|||
fshort = 1.0-xjonxl*(arga*argb-djonxj); |
|||
MultDeriv(&d_fshort,&d_arga,&d_argb); |
|||
d_fshort.value -= djonxj; |
|||
TimesDeriv(&d_fshort,&d_fshort,-xjonxl); |
|||
d_fshort.value += 1.0; |
|||
} else { |
|||
fshort = 1.0; |
|||
EqualDeriv(&d_fshort,&d_zero); |
|||
d_fshort.value = 1.0; |
|||
|
|||
} |
|||
/* |
|||
*.....body effect |
|||
*/ |
|||
gammas = model->MOS9gamma*fshort; |
|||
TimesDeriv(&d_gammas,&d_fshort,model->MOS9gamma); |
|||
fbodys = 0.5*gammas/(sqphbs+sqphbs); |
|||
DivDeriv(&d_fbodys,&d_gammas,&d_sqphbs); |
|||
TimesDeriv(&d_fbodys,&d_fbodys,0.25); |
|||
fbody = fbodys+model->MOS9narrowFactor/EffectiveWidth; |
|||
EqualDeriv(&d_fbody,&d_fbodys); |
|||
d_fbody.value += fbody - fbodys; |
|||
|
|||
onfbdy = 1.0/(1.0+fbody); |
|||
EqualDeriv(&d_onfbdy,&d_fbody); |
|||
d_onfbdy.value += 1.0; |
|||
InvDeriv(&d_onfbdy,&d_onfbdy); |
|||
qbonco =gammas*sqphbs+model->MOS9narrowFactor*phibs/EffectiveWidth; |
|||
EqualDeriv(&d_dummy,&d_phibs); |
|||
TimesDeriv(&d_dummy,&d_dummy,model-> |
|||
MultDeriv(&d_qbonco,&d_gammas,&d_sqphbs); |
|||
PlusDeriv(&d_qbonco,&d_qbonco,&d_dummy); |
|||
/* |
|||
*.....static feedback effect |
|||
*/ |
|||
vbix = here->MOS9tVbi*model->MOS9type-eta*(lvds); |
|||
EqualDeriv(&d_vbix,&d_r); d_vbix.value = vbix; |
|||
d_vbix.d1_r = -eta; |
|||
/* |
|||
*.....threshold voltage |
|||
*/ |
|||
vth = vbix+qbonco; |
|||
PlusDeriv(&d_vth,&d_vbix,&d_qbonco); |
|||
/* |
|||
*.....joint weak inversion and strong inversion |
|||
*/ |
|||
von = vth; |
|||
EqualDeriv(&d_von,&d_vth); |
|||
if ( model->MOS9fastSurfaceStateDensity != 0.0 ) { |
|||
csonco = CHARGE*model->MOS9fastSurfaceStateDensity * |
|||
1e4 /*(cm**2/m**2)*/ *EffectiveLength*EffectiveWidth * |
|||
here->MOS9m/OxideCap; /*const*/ |
|||
cdonco = 0.5*qbonco/phibs; |
|||
DivDeriv(&d_cdonco,&d_qbonco,&d_phibs); |
|||
TimesDeriv(&d_cdonco,&d_cdonco,0.5); |
|||
xn = 1.0+csonco+cdonco; |
|||
EqualDeriv(&d_xn,&d_cdonco); |
|||
d_xn.value += 1.0 + csonco; |
|||
von = vth+vt*xn; |
|||
TimesDeriv(&d_von,&d_xn,vt); |
|||
PlusDeriv(&d_von,&d_von,&d_vth); |
|||
|
|||
|
|||
} else { |
|||
/* |
|||
*.....cutoff region |
|||
*/ |
|||
if ( lvgs <= von ) { |
|||
cdrain = 0.0; |
|||
EqualDeriv(&d_cdrain,&d_zero); |
|||
goto innerline1000; |
|||
} |
|||
} |
|||
/* |
|||
*.....device is on |
|||
*/ |
|||
vgsx = MAX(lvgs,von); |
|||
if (lvgs >= von) { |
|||
EqualDeriv(&d_vgsx,&d_p); |
|||
d_vgsx.value = lvgs; |
|||
} else { |
|||
EqualDeriv(&d_vgsx,&d_von); |
|||
} |
|||
/* |
|||
*.....mobility modulation by gate voltage |
|||
*/ |
|||
onfg = 1.0+model->MOS9theta*(vgsx-vth); |
|||
TimesDeriv(&d_onfg,&d_vth,-1.0); |
|||
PlusDeriv(&d_onfg,&d_onfg,&d_vgsx); |
|||
TimesDeriv(&d_onfg,&d_onfg,model->MOS9theta); |
|||
d_onfg.value += 1.0; |
|||
fgate = 1.0/onfg; |
|||
InvDeriv(&d_fgate,&d_onfg); |
|||
us = here->MOS9tSurfMob * 1e-4 /*(m**2/cm**2)*/ *fgate; |
|||
TimesDeriv(&d_us,&d_fgate,here->MOS9tSurfMob * 1e-4); |
|||
/* |
|||
*.....saturation voltage |
|||
*/ |
|||
vdsat = (vgsx-vth)*onfbdy; |
|||
TimesDeriv(&d_vdsat,&d_vth, -1.0); |
|||
PlusDeriv(&d_vdsat,&d_vdsat,&d_vgsx); |
|||
MultDeriv(&d_vdsat,&d_vdsat,&d_onfbdy); |
|||
if ( model->MOS9maxDriftVel <= 0.0 ) { |
|||
} else { |
|||
vdsc = EffectiveLength*model->MOS9maxDriftVel/us; |
|||
InvDeriv(&d_vdsc,&d_us); |
|||
TimesDeriv(&d_vdsc,&d_vdsc,EffectiveLength*model->MOS9maxDriftVel); |
|||
onvdsc = 1.0/vdsc; |
|||
InvDeriv(&d_onvdsc,&d_vdsc); |
|||
arga = (vgsx-vth)*onfbdy; |
|||
/* note arga = vdsat at this point */ |
|||
EqualDeriv(&d_arga,&d_vdsat); |
|||
argb = sqrt(arga*arga+vdsc*vdsc); |
|||
MultDeriv(&d_dummy,&d_arga,&d_arga); |
|||
MultDeriv(&d_argb,&d_vdsc,&d_vdsc); |
|||
PlusDeriv(&d_argb,&d_argb,&d_dummy); |
|||
SqrtDeriv(&d_argb,&d_argb); |
|||
vdsat = arga+vdsc-argb; |
|||
TimesDeriv(&d_vdsat,&d_argb,-1.0); |
|||
PlusDeriv(&d_vdsat,&d_vdsat,&d_vdsc); |
|||
PlusDeriv(&d_vdsat,&d_vdsat,&d_arga); |
|||
} |
|||
/* |
|||
*.....current factors in linear region |
|||
*/ |
|||
vdsx = MIN((lvds),vdsat); |
|||
if (lvds < vdsat) { |
|||
EqualDeriv(&d_vdsx,&d_r); |
|||
d_vdsx.value = lvds; |
|||
} else { |
|||
EqualDeriv(&d_vdsx,&d_vdsat); |
|||
} |
|||
|
|||
if ( vdsx == 0.0 ) goto line900; |
|||
cdo = vgsx-vth-0.5*(1.0+fbody)*vdsx; |
|||
EqualDeriv(&d_cdo,&d_fbody); |
|||
d_cdo.value += 1.0; |
|||
MultDeriv(&d_cdo,&d_cdo,&d_vdsx); |
|||
TimesDeriv(&d_cdo,&d_cdo,0.5); |
|||
PlusDeriv(&d_cdo,&d_cdo,&d_vth); |
|||
TimesDeriv(&d_cdo,&d_cdo,-1.0); |
|||
PlusDeriv(&d_cdo,&d_cdo,&d_vgsx); |
|||
|
|||
|
|||
/* |
|||
*.....normalized drain current |
|||
*/ |
|||
cdnorm = cdo*vdsx; |
|||
MultDeriv(&d_cdnorm,&d_cdo,&d_vdsx); |
|||
/* |
|||
*.....drain current without velocity saturation effect |
|||
*/ |
|||
/* Beta is a constant till now */ |
|||
Beta = Beta*fgate; |
|||
TimesDeriv(&d_Beta,&d_fgate,Beta); |
|||
cdrain = Beta*cdnorm; |
|||
MultDeriv(&d_cdrain,&d_Beta,&d_cdnorm); |
|||
/* |
|||
*.....velocity saturation factor |
|||
*/ |
|||
if ( model->MOS9maxDriftVel != 0.0 ) { |
|||
fdrain = 1.0/(1.0+vdsx*onvdsc); |
|||
MultDeriv(&d_fdrain,&d_vdsx,&d_onvdsc); |
|||
d_fdrain.value += 1.0; |
|||
InvDeriv(&d_fdrain,&d_fdrain); |
|||
/* |
|||
*.....drain current |
|||
*/ |
|||
cdrain = fdrain*cdrain; |
|||
MultDeriv(&d_cdrain,&d_cdrain,&d_fdrain); |
|||
Beta = Beta*fdrain; |
|||
MultDeriv(&d_Beta,&d_Beta,&d_fdrain); |
|||
|
|||
} |
|||
/* |
|||
*.....channel length modulation |
|||
*/ |
|||
if ( (lvds) <= vdsat ) goto line700; |
|||
if ( model->MOS9maxDriftVel == 0.0 ) goto line510; |
|||
if (model->MOS9alpha == 0.0) goto line700; |
|||
cdsat = cdrain; |
|||
EqualDeriv(&d_cdsat,&d_cdrain); |
|||
gdsat = cdsat*(1.0-fdrain)*onvdsc; |
|||
TimesDeriv(&d_dummy,&d_fdrain,-1.0); |
|||
d_dummy.value += 1.0; |
|||
MultDeriv(&d_gdsat,&d_cdsat,&d_dummy); |
|||
MultDeriv(&d_gdsat,&d_gdsat,&d_onvdsc); |
|||
gdsat = MAX(1.0e-12,gdsat); |
|||
if (gdsat == 1.0e-12) { |
|||
EqualDeriv(&d_gdsat,&d_zero); |
|||
d_gdsat.value = gdsat; |
|||
} |
|||
|
|||
emax = cdsat*oneoverxl/gdsat; |
|||
DivDeriv(&d_emax,&d_cdsat,&d_gdsat); |
|||
TimesDeriv(&d_emax,&d_emax,oneoverxl); |
|||
|
|||
|
|||
arga = 0.5*emax*model->MOS9alpha; |
|||
TimesDeriv(&d_arga,&d_emax,0.5*model->MOS9alpha); |
|||
argc = model->MOS9kappa*model->MOS9alpha;/*const*/ |
|||
argb = sqrt(arga*arga+argc*((lvds)-vdsat)); |
|||
TimesDeriv(&d_dummy,&d_vdsat,-1.0); |
|||
d_dummy.value += lvds; |
|||
d_dummy.d1_r += 1.0; |
|||
TimesDeriv(&d_argb,&d_dummy,argc); |
|||
MultDeriv(&d_dummy,&d_arga,&d_arga); |
|||
PlusDeriv(&d_argb,&d_argb,&d_dummy); |
|||
SqrtDeriv(&d_argb,&d_argb); |
|||
delxl = argb-arga; |
|||
TimesDeriv(&d_delxl,&d_arga,-1.0); |
|||
PlusDeriv(&d_delxl,&d_argb,&d_delxl); |
|||
goto line520; |
|||
line510: |
|||
delxl = sqrt(model->MOS9kappa*((lvds)-vdsat)*model->MOS9alpha); |
|||
TimesDeriv(&d_delxl,&d_vdsat,-1.0); |
|||
d_delxl.value += lvds; |
|||
d_delxl.d1_r += 1.0; |
|||
TimesDeriv(&d_delxl,&d_delxl,model->MOS9kappa*model->MOS9alpha); |
|||
SqrtDeriv(&d_delxl,&d_delxl); |
|||
|
|||
/* |
|||
*.....punch through approximation |
|||
*/ |
|||
line520: |
|||
if ( delxl > (0.5*EffectiveLength) ) { |
|||
delxl = EffectiveLength - (EffectiveLength*EffectiveLength/ |
|||
delxl*0.25); |
|||
InvDeriv(&d_delxl,&d_delxl); |
|||
TimesDeriv(&d_delxl,&d_delxl,-EffectiveLength*EffectiveLength*0.25); |
|||
d_delxl.value += EffectiveLength; |
|||
} |
|||
/* |
|||
*.....saturation region |
|||
*/ |
|||
dlonxl = delxl*oneoverxl; |
|||
TimesDeriv(&d_dlonxl,&d_delxl,oneoverxl); |
|||
xlfact = 1.0/(1.0-dlonxl); |
|||
TimesDeriv(&d_xlfact,&d_dlonxl,-1.0); |
|||
d_xlfact.value += 1.0; |
|||
InvDeriv(&d_xlfact,&d_xlfact); |
|||
|
|||
cdrain = cdrain*xlfact; |
|||
MultDeriv(&d_cdrain,&d_cdrain,&d_xlfact); |
|||
/* |
|||
*.....finish strong inversion case |
|||
*/ |
|||
line700: |
|||
if ( lvgs < von ) { |
|||
/* |
|||
*.....weak inversion |
|||
*/ |
|||
onxn = 1.0/xn; |
|||
InvDeriv(&d_onxn,&d_xn); |
|||
ondvt = onxn/vt; |
|||
TimesDeriv(&d_ondvt,&d_onxn,1/vt); |
|||
wfact = exp( (lvgs-von)*ondvt ); |
|||
TimesDeriv(&d_wfact,&d_von,-1.0); |
|||
d_wfact.value += lvgs; |
|||
d_wfact.d1_p += 1.0; |
|||
MultDeriv(&d_wfact,&d_wfact,&d_ondvt); |
|||
ExpDeriv(&d_wfact,&d_wfact); |
|||
cdrain = cdrain*wfact; |
|||
MultDeriv(&d_cdrain,&d_cdrain,&d_wfact); |
|||
} |
|||
/* |
|||
*.....charge computation |
|||
*/ |
|||
goto innerline1000; |
|||
/* |
|||
*.....special case of vds = 0.0d0 |
|||
*/ |
|||
|
|||
line900: |
|||
Beta = Beta*fgate; |
|||
/* Beta is still a constant */ |
|||
TimesDeriv(&d_Beta,&d_fgate,Beta); |
|||
cdrain = 0.0; |
|||
EqualDeriv(&d_cdrain,&d_zero); |
|||
here->MOS9gds = Beta*(vgsx-vth); |
|||
TimesDeriv(&d_MOS9gds,&d_vth,-1.0); |
|||
PlusDeriv(&d_MOS9gds,&d_MOS9gds,&d_vgsx); |
|||
MultDeriv(&d_MOS9gds,&d_MOS9gds,&d_Beta); |
|||
if ( (model->MOS9fastSurfaceStateDensity != 0.0) && |
|||
(lvgs < von) ) { |
|||
here->MOS9gds *=exp((lvgs-von)/(vt*xn)); |
|||
TimesDeriv(&d_dummy,&d_von,-1.0); |
|||
d_dummy.value += lvgs; |
|||
d_dummy.d1_p += 1.0; |
|||
DivDeriv(&d_dummy,&d_dummy,&d_xn); |
|||
TimesDeriv(&d_dummy,&d_dummy,1/vt); |
|||
ExpDeriv(&d_dummy,&d_dummy); |
|||
MultDeriv(&d_MOS9gds,&d_MOS9gds,&d_dummy); |
|||
} |
|||
d_cdrain.d1_r = d_MOS9gds.value; |
|||
d_cdrain.d2_r2 = d_MOS9gds.d1_r; |
|||
d_cdrain.d3_r3 = d_MOS9gds.d2_r2; |
|||
|
|||
|
|||
|
|||
innerline1000:; |
|||
/* |
|||
*.....done |
|||
*/ |
|||
} |
|||
|
|||
|
|||
/* |
|||
* COMPUTE EQUIVALENT DRAIN CURRENT SOURCE |
|||
*/ |
|||
/* |
|||
* now we do the hard part of the bulk-drain and bulk-source |
|||
* diode - we evaluate the non-linear capacitance and |
|||
* charge |
|||
* |
|||
* the basic equations are not hard, but the implementation |
|||
* is somewhat long in an attempt to avoid log/exponential |
|||
* evaluations |
|||
*/ |
|||
/* |
|||
* charge storage elements |
|||
* |
|||
*.. bulk-drain and bulk-source depletion capacitances |
|||
*/ |
|||
if (vbs < here->MOS9tDepCap){ |
|||
arg=1-vbs/here->MOS9tBulkPot; |
|||
/* |
|||
* the following block looks somewhat long and messy, |
|||
* but since most users use the default grading |
|||
* coefficients of .5, and sqrt is MUCH faster than an |
|||
* exp(log()) we use this special case code to buy time. |
|||
* (as much as 10% of total job time!) |
|||
*/ |
|||
#ifndef NOSQRT |
|||
if(model->MOS9bulkJctBotGradingCoeff == |
|||
model->MOS9bulkJctSideGradingCoeff) { |
|||
if(model->MOS9bulkJctBotGradingCoeff == .5) { |
|||
sarg = sargsw = 1/sqrt(arg); |
|||
} else { |
|||
sarg = sargsw = |
|||
exp(-model->MOS9bulkJctBotGradingCoeff* |
|||
log(arg)); |
|||
} |
|||
} else { |
|||
if(model->MOS9bulkJctBotGradingCoeff == .5) { |
|||
sarg = 1/sqrt(arg); |
|||
} else { |
|||
#endif /*NOSQRT*/ |
|||
sarg = exp(-model->MOS9bulkJctBotGradingCoeff* |
|||
log(arg)); |
|||
#ifndef NOSQRT |
|||
} |
|||
if(model->MOS9bulkJctSideGradingCoeff == .5) { |
|||
sargsw = 1/sqrt(arg); |
|||
} else { |
|||
#endif /*NOSQRT*/ |
|||
sargsw =exp(-model->MOS9bulkJctSideGradingCoeff* |
|||
log(arg)); |
|||
#ifndef NOSQRT |
|||
} |
|||
} |
|||
#endif /*NOSQRT*/ |
|||
lcapbs=here->MOS9Cbs*sarg+ |
|||
here->MOS9Cbssw*sargsw; |
|||
lcapbs2 = model->MOS9type*0.5/here->MOS9tBulkPot*( |
|||
here->MOS9Cbs*model->MOS9bulkJctBotGradingCoeff* |
|||
sarg/arg + here->MOS9Cbssw* |
|||
model->MOS9bulkJctSideGradingCoeff*sargsw/arg); |
|||
lcapbs3 = here->MOS9Cbs*sarg* |
|||
model->MOS9bulkJctBotGradingCoeff* |
|||
(model->MOS9bulkJctBotGradingCoeff+1); |
|||
lcapbs3 += here->MOS9Cbssw*sargsw* |
|||
model->MOS9bulkJctSideGradingCoeff* |
|||
(model->MOS9bulkJctSideGradingCoeff+1); |
|||
lcapbs3 = lcapbs3/(6*here->MOS9tBulkPot* |
|||
here->MOS9tBulkPot*arg*arg); |
|||
} else { |
|||
/* *(ckt->CKTstate0 + here->MOS9qbs)= here->MOS9f4s + |
|||
vbs*(here->MOS9f2s+vbs*(here->MOS9f3s/2));*/ |
|||
lcapbs=here->MOS9f2s+here->MOS9f3s*vbs; |
|||
lcapbs2 = 0.5*here->MOS9f3s; |
|||
lcapbs3 = 0; |
|||
} |
|||
if (vbd < here->MOS9tDepCap) { |
|||
arg=1-vbd/here->MOS9tBulkPot; |
|||
/* |
|||
* the following block looks somewhat long and messy, |
|||
* but since most users use the default grading |
|||
* coefficients of .5, and sqrt is MUCH faster than an |
|||
* exp(log()) we use this special case code to buy time. |
|||
* (as much as 10% of total job time!) |
|||
*/ |
|||
#ifndef NOSQRT |
|||
if(model->MOS9bulkJctBotGradingCoeff == .5 && |
|||
model->MOS9bulkJctSideGradingCoeff == .5) { |
|||
sarg = sargsw = 1/sqrt(arg); |
|||
} else { |
|||
if(model->MOS9bulkJctBotGradingCoeff == .5) { |
|||
sarg = 1/sqrt(arg); |
|||
} else { |
|||
#endif /*NOSQRT*/ |
|||
sarg = exp(-model->MOS9bulkJctBotGradingCoeff* |
|||
log(arg)); |
|||
#ifndef NOSQRT |
|||
} |
|||
if(model->MOS9bulkJctSideGradingCoeff == .5) { |
|||
sargsw = 1/sqrt(arg); |
|||
} else { |
|||
#endif /*NOSQRT*/ |
|||
sargsw =exp(-model->MOS9bulkJctSideGradingCoeff* |
|||
log(arg)); |
|||
#ifndef NOSQRT |
|||
} |
|||
} |
|||
#endif /*NOSQRT*/ |
|||
lcapbd=here->MOS9Cbd*sarg+ |
|||
here->MOS9Cbdsw*sargsw; |
|||
lcapbd2 = model->MOS9type*0.5/here->MOS9tBulkPot*( |
|||
here->MOS9Cbd*model->MOS9bulkJctBotGradingCoeff* |
|||
sarg/arg + here->MOS9Cbdsw* |
|||
model->MOS9bulkJctSideGradingCoeff*sargsw/arg); |
|||
lcapbd3 = here->MOS9Cbd*sarg* |
|||
model->MOS9bulkJctBotGradingCoeff* |
|||
(model->MOS9bulkJctBotGradingCoeff+1); |
|||
lcapbd3 += here->MOS9Cbdsw*sargsw* |
|||
model->MOS9bulkJctSideGradingCoeff* |
|||
(model->MOS9bulkJctSideGradingCoeff+1); |
|||
lcapbd3 = lcapbd3/(6*here->MOS9tBulkPot* |
|||
here->MOS9tBulkPot*arg*arg); |
|||
} else { |
|||
lcapbd=here->MOS9f2d + vbd * here->MOS9f3d; |
|||
lcapbd2=0.5*here->MOS9f3d; |
|||
lcapbd3=0; |
|||
} |
|||
/* |
|||
* meyer's capacitor model |
|||
*/ |
|||
/* |
|||
* the meyer capacitance equations are in DEVqmeyer |
|||
* these expressions are derived from those equations. |
|||
* these expressions are incorrect; they assume just one |
|||
* controlling variable for each charge storage element |
|||
* while actually there are several; the MOS9 small |
|||
* signal ac linear model is also wrong because it |
|||
* ignores controlled capacitive elements. these can be |
|||
* corrected (as can the linear ss ac model) if the |
|||
* expressions for the charge are available |
|||
*/ |
|||
|
|||
|
|||
{ |
|||
|
|||
|
|||
double phi; |
|||
double cox; |
|||
double vddif; |
|||
double vddif1; |
|||
double vddif2; |
|||
double vgst; |
|||
/* von, lvgs and vdsat have already been adjusted for |
|||
possible source-drain interchange */ |
|||
|
|||
|
|||
|
|||
vgst = lvgs -von; |
|||
phi = here->MOS9tPhi; |
|||
cox = OxideCap; |
|||
if (vgst <= -phi) { |
|||
lcapgb2=lcapgb3=lcapgs2=lcapgs3=lcapgd2=lcapgd3=0; |
|||
} else if (vgst <= -phi/2) { |
|||
lcapgb2= -cox/(4*phi); |
|||
lcapgb3=lcapgs2=lcapgs3=lcapgd2=lcapgd3=0; |
|||
} else if (vgst <= 0) { |
|||
lcapgb2= -cox/(4*phi); |
|||
lcapgb3=lcapgs3=lcapgd2=lcapgd3=0; |
|||
lcapgs2 = cox/(3*phi); |
|||
} else { /* the MOS9modes are around because |
|||
vds has not been adjusted */ |
|||
if (vdsat <= here->MOS9mode*vds) { |
|||
lcapgb2=lcapgb3=lcapgs2=lcapgs3=lcapgd2=lcapgd3=0; |
|||
} else { |
|||
vddif = 2.0*vdsat-here->MOS9mode*vds; |
|||
vddif1 = vdsat-here->MOS9mode*vds/*-1.0e-12*/; |
|||
vddif2 = vddif*vddif; |
|||
lcapgd2 = -vdsat*here->MOS9mode*vds*cox/(3*vddif*vddif2); |
|||
lcapgd3 = - here->MOS9mode*vds*cox*(vddif - 6*vdsat)/(9*vddif2*vddif2); |
|||
lcapgs2 = -vddif1*here->MOS9mode*vds*cox/(3*vddif*vddif2); |
|||
lcapgs3 = - here->MOS9mode*vds*cox*(vddif - 6*vddif1)/(9*vddif2*vddif2); |
|||
lcapgb2=lcapgb3=0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* the b-s and b-d diodes need no processing ... */ |
|||
here->capbs2 = lcapbs2; |
|||
here->capbs3 = lcapbs3; |
|||
here->capbd2 = lcapbd2; |
|||
here->capbd3 = lcapbd3; |
|||
here->gbs2 = lgbs2; |
|||
here->gbs3 = lgbs3; |
|||
here->gbd2 = lgbd2; |
|||
here->gbd3 = lgbd3; |
|||
here->capgb2 = model->MOS9type*lcapgb2; |
|||
here->capgb3 = lcapgb3; |
|||
/* |
|||
* process to get Taylor coefficients, taking into |
|||
* account type and mode. |
|||
*/ |
|||
gm2 = d_cdrain.d2_p2; |
|||
gb2 = d_cdrain.d2_q2; |
|||
gds2 = d_cdrain.d2_r2; |
|||
gmb = d_cdrain.d2_pq; |
|||
gbds = d_cdrain.d2_qr; |
|||
gmds = d_cdrain.d2_pr; |
|||
gm3 = d_cdrain.d3_p3; |
|||
gb3 = d_cdrain.d3_q3; |
|||
gds3 = d_cdrain.d3_r3; |
|||
gm2ds = d_cdrain.d3_p2r; |
|||
gm2b = d_cdrain.d3_p2q; |
|||
gb2ds = d_cdrain.d3_q2r; |
|||
gmb2 = d_cdrain.d3_pq2; |
|||
gmds2 = d_cdrain.d3_pr2; |
|||
gbds2 = d_cdrain.d3_qr2; |
|||
gmbds = d_cdrain.d3_pqr; |
|||
|
|||
if (here->MOS9mode == 1) |
|||
{ |
|||
/* normal mode - no source-drain interchange */ |
|||
|
|||
here->cdr_x2 = gm2; |
|||
here->cdr_y2 = gb2;; |
|||
here->cdr_z2 = gds2;; |
|||
here->cdr_xy = gmb; |
|||
here->cdr_yz = gbds; |
|||
here->cdr_xz = gmds; |
|||
here->cdr_x3 = gm3; |
|||
here->cdr_y3 = gb3; |
|||
here->cdr_z3 = gds3; |
|||
here->cdr_x2z = gm2ds; |
|||
here->cdr_x2y = gm2b; |
|||
here->cdr_y2z = gb2ds; |
|||
here->cdr_xy2 = gmb2; |
|||
here->cdr_xz2 = gmds2; |
|||
here->cdr_yz2 = gbds2; |
|||
here->cdr_xyz = gmbds; |
|||
|
|||
/* the gate caps have been divided and made into |
|||
Taylor coeffs., but not adjusted for type */ |
|||
|
|||
here->capgs2 = model->MOS9type*lcapgs2; |
|||
here->capgs3 = lcapgs3; |
|||
here->capgd2 = model->MOS9type*lcapgd2; |
|||
here->capgd3 = lcapgd3; |
|||
} else { |
|||
/* |
|||
* inverse mode - source and drain interchanged |
|||
*/ |
|||
|
|||
here->cdr_x2 = -gm2; |
|||
here->cdr_y2 = -gb2; |
|||
here->cdr_z2 = -(gm2 + gb2 + gds2 + 2*(gmb + gmds + gbds)); |
|||
here->cdr_xy = -gmb; |
|||
here->cdr_yz = gmb + gb2 + gbds; |
|||
here->cdr_xz = gm2 + gmb + gmds; |
|||
here->cdr_x3 = -gm3; |
|||
here->cdr_y3 = -gb3; |
|||
here->cdr_z3 = gm3 + gb3 + gds3 + |
|||
3*(gm2b + gm2ds + gmb2 + gb2ds + gmds2 + gbds2) + 6*gmbds ; |
|||
here->cdr_x2z = gm3 + gm2b + gm2ds; |
|||
here->cdr_x2y = -gm2b; |
|||
here->cdr_y2z = gmb2 + gb3 + gb2ds; |
|||
here->cdr_xy2 = -gmb2; |
|||
here->cdr_xz2 = -(gm3 + 2*(gm2b + gm2ds + gmbds) + |
|||
gmb2 + gmds2); |
|||
here->cdr_yz2 = -(gb3 + 2*(gmb2 + gb2ds + gmbds) + |
|||
gm2b + gbds2); |
|||
here->cdr_xyz = gm2b + gmb2 + gmbds; |
|||
|
|||
here->capgs2 = model->MOS9type*lcapgd2; |
|||
here->capgs3 = lcapgd3; |
|||
|
|||
here->capgd2 = model->MOS9type*lcapgs2; |
|||
here->capgd3 = lcapgs3; |
|||
|
|||
} |
|||
|
|||
/* now to adjust for type and multiply by factors to convert to Taylor coeffs. */ |
|||
|
|||
here->cdr_x2 = 0.5*model->MOS9type*here->cdr_x2; |
|||
here->cdr_y2 = 0.5*model->MOS9type*here->cdr_y2; |
|||
here->cdr_z2 = 0.5*model->MOS9type*here->cdr_z2; |
|||
here->cdr_xy = model->MOS9type*here->cdr_xy; |
|||
here->cdr_yz = model->MOS9type*here->cdr_yz; |
|||
here->cdr_xz = model->MOS9type*here->cdr_xz; |
|||
here->cdr_x3 = here->cdr_x3/6.; |
|||
here->cdr_y3 = here->cdr_y3/6.; |
|||
here->cdr_z3 = here->cdr_z3/6.; |
|||
here->cdr_x2z = 0.5*here->cdr_x2z; |
|||
here->cdr_x2y = 0.5*here->cdr_x2y; |
|||
here->cdr_y2z = 0.5*here->cdr_y2z; |
|||
here->cdr_xy2 = 0.5*here->cdr_xy2; |
|||
here->cdr_xz2 = 0.5*here->cdr_xz2; |
|||
here->cdr_yz2 = 0.5*here->cdr_yz2; |
|||
|
|||
|
|||
} |
|||
} |
|||
return(OK); |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
extern int MOS9acLoad(GENmodel*,CKTcircuit*); |
|||
extern int MOS9ask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*); |
|||
extern int MOS9convTest(GENmodel *,CKTcircuit *); |
|||
extern int MOS9delete(GENmodel*,IFuid,GENinstance**); |
|||
extern void MOS9destroy(GENmodel**); |
|||
extern int MOS9getic(GENmodel*,CKTcircuit*); |
|||
extern int MOS9load(GENmodel*,CKTcircuit*); |
|||
extern int MOS9mAsk(CKTcircuit*,GENmodel*,int,IFvalue*); |
|||
extern int MOS9mDelete(GENmodel**,IFuid,GENmodel*); |
|||
extern int MOS9mParam(int,IFvalue*,GENmodel*); |
|||
extern int MOS9param(int,IFvalue*,GENinstance*,IFvalue*); |
|||
extern int MOS9pzLoad(GENmodel*,CKTcircuit*,SPcomplex*); |
|||
extern int MOS9sAcLoad(GENmodel*,CKTcircuit*); |
|||
extern int MOS9sLoad(GENmodel*,CKTcircuit*); |
|||
extern void MOS9sPrint(GENmodel*,CKTcircuit*); |
|||
extern int MOS9sSetup(SENstruct*,GENmodel*); |
|||
extern int MOS9sUpdate(GENmodel*,CKTcircuit*); |
|||
extern int MOS9setup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); |
|||
extern int MOS9unsetup(GENmodel*,CKTcircuit*); |
|||
extern int MOS9temp(GENmodel*,CKTcircuit*); |
|||
extern int MOS9trunc(GENmodel*,CKTcircuit*,double*); |
|||
extern int MOS9disto(int,GENmodel*,CKTcircuit*); |
|||
extern int MOS9noise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); |
|||
extern int MOS9dSetup(GENmodel*,CKTcircuit*); |
|||
@ -0,0 +1,49 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
/* |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "cktdefs.h" |
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
int |
|||
MOS9getic(inModel,ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
MOS9model *model = (MOS9model *)inModel; |
|||
MOS9instance *here; |
|||
/* |
|||
* grab initial conditions out of rhs array. User specified, so use |
|||
* external nodes to get values |
|||
*/ |
|||
|
|||
for( ; model ; model = model->MOS9nextModel) { |
|||
for(here = model->MOS9instances; here ; here = here->MOS9nextInstance) { |
|||
if(!here->MOS9icVBSGiven) { |
|||
here->MOS9icVBS = |
|||
*(ckt->CKTrhs + here->MOS9bNode) - |
|||
*(ckt->CKTrhs + here->MOS9sNode); |
|||
} |
|||
if(!here->MOS9icVDSGiven) { |
|||
here->MOS9icVDS = |
|||
*(ckt->CKTrhs + here->MOS9dNode) - |
|||
*(ckt->CKTrhs + here->MOS9sNode); |
|||
} |
|||
if(!here->MOS9icVGSGiven) { |
|||
here->MOS9icVGS = |
|||
*(ckt->CKTrhs + here->MOS9gNode) - |
|||
*(ckt->CKTrhs + here->MOS9sNode); |
|||
} |
|||
} |
|||
} |
|||
return(OK); |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
#include <config.h> |
|||
|
|||
#include <devdefs.h> |
|||
|
|||
#include "mos9itf.h" |
|||
#include "mos9ext.h" |
|||
#include "mos9init.h" |
|||
|
|||
|
|||
SPICEdev MOS9info = { |
|||
{ |
|||
"Mos9", |
|||
"Modified Level 3 MOSfet model", |
|||
|
|||
&MOS9nSize, |
|||
&MOS9nSize, |
|||
MOS9names, |
|||
|
|||
&MOS9pTSize, |
|||
MOS9pTable, |
|||
|
|||
&MOS9mPTSize, |
|||
MOS9mPTable, |
|||
DEV_DEFAULT |
|||
}, |
|||
|
|||
DEVparam : MOS9param, |
|||
DEVmodParam : MOS9mParam, |
|||
DEVload : MOS9load, |
|||
DEVsetup : MOS9setup, |
|||
DEVunsetup : MOS9unsetup, |
|||
DEVpzSetup : MOS9setup, |
|||
DEVtemperature: MOS9temp, |
|||
DEVtrunc : MOS9trunc, |
|||
DEVfindBranch : NULL, |
|||
DEVacLoad : MOS9acLoad, |
|||
DEVaccept : NULL, |
|||
DEVdestroy : MOS9destroy, |
|||
DEVmodDelete : MOS9mDelete, |
|||
DEVdelete : MOS9delete, |
|||
DEVsetic : MOS9getic, |
|||
DEVask : MOS9ask, |
|||
DEVmodAsk : MOS9mAsk, |
|||
DEVpzLoad : MOS9pzLoad, |
|||
DEVconvTest : MOS9convTest, |
|||
DEVsenSetup : MOS9sSetup, |
|||
DEVsenLoad : MOS9sLoad, |
|||
DEVsenUpdate : MOS9sUpdate, |
|||
DEVsenAcLoad : MOS9sAcLoad, |
|||
DEVsenPrint : MOS9sPrint, |
|||
DEVsenTrunc : NULL, |
|||
DEVdisto : MOS9disto, |
|||
DEVnoise : MOS9noise, |
|||
|
|||
DEVinstSize : &MOS9iSize, |
|||
DEVmodSize : &MOS9mSize |
|||
|
|||
}; |
|||
|
|||
|
|||
SPICEdev * |
|||
get_mos9_info(void) |
|||
{ |
|||
return &MOS9info; |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
#ifndef _MOS9INIT_H |
|||
#define _MOS9INIT_H |
|||
|
|||
extern IFparm MOS9pTable[ ]; |
|||
extern IFparm MOS9mPTable[ ]; |
|||
extern char *MOS9names[ ]; |
|||
extern int MOS9pTSize; |
|||
extern int MOS9mPTSize; |
|||
extern int MOS9nSize; |
|||
extern int MOS9iSize; |
|||
extern int MOS9mSize; |
|||
|
|||
#endif |
|||
@ -0,0 +1,10 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
**********/ |
|||
|
|||
#ifndef DEV_MOS9 |
|||
#define DEV_MOS9 |
|||
|
|||
SPICEdev *get_mos9_info(void); |
|||
|
|||
#endif |
|||
1358
src/spicelib/devices/mos9/mos9load.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,171 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
/* |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "cktdefs.h" |
|||
#include "devdefs.h" |
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
/*ARGSUSED*/ |
|||
int |
|||
MOS9mAsk(ckt,inst,which,value) |
|||
CKTcircuit *ckt; |
|||
GENmodel *inst; |
|||
int which; |
|||
IFvalue *value; |
|||
{ |
|||
MOS9model *here = (MOS9model *)inst; |
|||
switch(which) { |
|||
case MOS9_MOD_TNOM: |
|||
value->rValue = here->MOS9tnom-CONSTCtoK; |
|||
return(OK); |
|||
case MOS9_MOD_VTO: |
|||
value->rValue = here->MOS9vt0; |
|||
return(OK); |
|||
case MOS9_MOD_KP: |
|||
value->rValue = here->MOS9transconductance; |
|||
return(OK); |
|||
case MOS9_MOD_GAMMA: |
|||
value->rValue = here->MOS9gamma; |
|||
return(OK); |
|||
case MOS9_MOD_PHI: |
|||
value->rValue = here->MOS9phi; |
|||
return(OK); |
|||
case MOS9_MOD_RD: |
|||
value->rValue = here->MOS9drainResistance; |
|||
return(OK); |
|||
case MOS9_MOD_RS: |
|||
value->rValue = here->MOS9sourceResistance; |
|||
return(OK); |
|||
case MOS9_MOD_CBD: |
|||
value->rValue = here->MOS9capBD; |
|||
return(OK); |
|||
case MOS9_MOD_CBS: |
|||
value->rValue = here->MOS9capBS; |
|||
return(OK); |
|||
case MOS9_MOD_IS: |
|||
value->rValue = here->MOS9jctSatCur; |
|||
return(OK); |
|||
case MOS9_MOD_PB: |
|||
value->rValue = here->MOS9bulkJctPotential; |
|||
return(OK); |
|||
case MOS9_MOD_CGSO: |
|||
value->rValue = here->MOS9gateSourceOverlapCapFactor; |
|||
return(OK); |
|||
case MOS9_MOD_CGDO: |
|||
value->rValue = here->MOS9gateDrainOverlapCapFactor; |
|||
return(OK); |
|||
case MOS9_MOD_CGBO: |
|||
value->rValue = here->MOS9gateBulkOverlapCapFactor; |
|||
return(OK); |
|||
case MOS9_MOD_CJ: |
|||
value->rValue = here->MOS9bulkCapFactor; |
|||
return(OK); |
|||
case MOS9_MOD_MJ: |
|||
value->rValue = here->MOS9bulkJctBotGradingCoeff; |
|||
return(OK); |
|||
case MOS9_MOD_CJSW: |
|||
value->rValue = here->MOS9sideWallCapFactor; |
|||
return(OK); |
|||
case MOS9_MOD_MJSW: |
|||
value->rValue = here->MOS9bulkJctSideGradingCoeff; |
|||
return(OK); |
|||
case MOS9_MOD_JS: |
|||
value->rValue = here->MOS9jctSatCurDensity; |
|||
return(OK); |
|||
case MOS9_MOD_TOX: |
|||
value->rValue = here->MOS9oxideThickness; |
|||
return(OK); |
|||
case MOS9_MOD_LD: |
|||
value->rValue = here->MOS9latDiff; |
|||
return(OK); |
|||
case MOS9_MOD_XL: |
|||
value->rValue = here->MOS9lengthAdjust; |
|||
return(OK); |
|||
case MOS9_MOD_WD: |
|||
value->rValue = here->MOS9widthNarrow; |
|||
return(OK); |
|||
case MOS9_MOD_XW: |
|||
value->rValue = here->MOS9widthAdjust; |
|||
return(OK); |
|||
case MOS9_MOD_DELVTO: |
|||
value->rValue = here->MOS9delvt0; |
|||
return(OK); |
|||
case MOS9_MOD_RSH: |
|||
value->rValue = here->MOS9sheetResistance; |
|||
return(OK); |
|||
case MOS9_MOD_U0: |
|||
value->rValue = here->MOS9surfaceMobility; |
|||
return(OK); |
|||
case MOS9_MOD_FC: |
|||
value->rValue = here->MOS9fwdCapDepCoeff; |
|||
return(OK); |
|||
case MOS9_MOD_NSUB: |
|||
value->rValue = here->MOS9substrateDoping; |
|||
return(OK); |
|||
case MOS9_MOD_TPG: |
|||
value->iValue = here->MOS9gateType; |
|||
return(OK); |
|||
case MOS9_MOD_NSS: |
|||
value->rValue = here->MOS9surfaceStateDensity; |
|||
return(OK); |
|||
case MOS9_MOD_NFS: |
|||
value->rValue = here->MOS9fastSurfaceStateDensity; |
|||
return(OK); |
|||
case MOS9_MOD_DELTA: |
|||
value->rValue = here->MOS9narrowFactor; |
|||
return(OK); |
|||
case MOS9_MOD_VMAX: |
|||
value->rValue = here->MOS9maxDriftVel; |
|||
return(OK); |
|||
case MOS9_MOD_XJ: |
|||
value->rValue = here->MOS9junctionDepth; |
|||
return(OK); |
|||
case MOS9_MOD_ETA: |
|||
value->rValue = here->MOS9eta; |
|||
return(OK); |
|||
case MOS9_MOD_XD: |
|||
value->rValue = here->MOS9coeffDepLayWidth; |
|||
return(OK); |
|||
case MOS9_DELTA: |
|||
value->rValue = here->MOS9delta; |
|||
return(OK); |
|||
case MOS9_MOD_THETA: |
|||
value->rValue = here->MOS9theta; |
|||
return(OK); |
|||
case MOS9_MOD_ALPHA: |
|||
value->rValue = here->MOS9alpha; |
|||
return(OK); |
|||
case MOS9_MOD_KAPPA: |
|||
value->rValue = here->MOS9kappa; |
|||
return(OK); |
|||
case MOS9_MOD_KF: |
|||
value->rValue = here->MOS9fNcoef; |
|||
return(OK); |
|||
case MOS9_MOD_AF: |
|||
value->rValue = here->MOS9fNexp; |
|||
return(OK); |
|||
|
|||
case MOS9_MOD_TYPE: |
|||
if (here->MOS9type > 0) |
|||
value->sValue = "nmos"; |
|||
else |
|||
value->sValue = "pmos"; |
|||
return(OK); |
|||
default: |
|||
return(E_BADPARM); |
|||
} |
|||
/* NOTREACHED */ |
|||
} |
|||
|
|||
@ -0,0 +1,45 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
/* |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h>
|
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
int |
|||
MOS9mDelete(inModel,modname,kill) |
|||
GENmodel **inModel; |
|||
IFuid modname; |
|||
GENmodel *kill; |
|||
{ |
|||
MOS9model **model = (MOS9model **)inModel; |
|||
MOS9model *modfast = (MOS9model *)kill; |
|||
MOS9instance *here; |
|||
MOS9instance *prev = NULL; |
|||
MOS9model **oldmod; |
|||
oldmod = model; |
|||
for( ; *model ; model = &((*model)->MOS9nextModel)) { |
|||
if( (*model)->MOS9modName == modname || |
|||
(modfast && *model == modfast) ) goto delgot; |
|||
oldmod = model; |
|||
} |
|||
return(E_NOMOD); |
|||
|
|||
delgot: |
|||
*oldmod = (*model)->MOS9nextModel; /* cut deleted device out of list */ |
|||
for(here = (*model)->MOS9instances ; here ; here = here->MOS9nextInstance) { |
|||
if(prev) FREE(prev); |
|||
prev = here; |
|||
} |
|||
if(prev) FREE(prev); |
|||
FREE(*model); |
|||
return(OK); |
|||
|
|||
} |
|||
@ -0,0 +1,202 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
/* |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "const.h" |
|||
#include "ifsim.h" |
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
int |
|||
MOS9mParam(param,value,inModel) |
|||
int param; |
|||
IFvalue *value; |
|||
GENmodel *inModel; |
|||
{ |
|||
register MOS9model *model = (MOS9model *)inModel; |
|||
switch(param) { |
|||
case MOS9_MOD_VTO: |
|||
model->MOS9vt0 = value->rValue; |
|||
model->MOS9vt0Given = TRUE; |
|||
break; |
|||
case MOS9_MOD_KP: |
|||
model->MOS9transconductance = value->rValue; |
|||
model->MOS9transconductanceGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_GAMMA: |
|||
model->MOS9gamma = value->rValue; |
|||
model->MOS9gammaGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_PHI: |
|||
model->MOS9phi = value->rValue; |
|||
model->MOS9phiGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_RD: |
|||
model->MOS9drainResistance = value->rValue; |
|||
model->MOS9drainResistanceGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_RS: |
|||
model->MOS9sourceResistance = value->rValue; |
|||
model->MOS9sourceResistanceGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_CBD: |
|||
model->MOS9capBD = value->rValue; |
|||
model->MOS9capBDGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_CBS: |
|||
model->MOS9capBS = value->rValue; |
|||
model->MOS9capBSGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_IS: |
|||
model->MOS9jctSatCur = value->rValue; |
|||
model->MOS9jctSatCurGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_PB: |
|||
model->MOS9bulkJctPotential = value->rValue; |
|||
model->MOS9bulkJctPotentialGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_CGSO: |
|||
model->MOS9gateSourceOverlapCapFactor = value->rValue; |
|||
model->MOS9gateSourceOverlapCapFactorGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_CGDO: |
|||
model->MOS9gateDrainOverlapCapFactor = value->rValue; |
|||
model->MOS9gateDrainOverlapCapFactorGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_CGBO: |
|||
model->MOS9gateBulkOverlapCapFactor = value->rValue; |
|||
model->MOS9gateBulkOverlapCapFactorGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_RSH: |
|||
model->MOS9sheetResistance = value->rValue; |
|||
model->MOS9sheetResistanceGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_CJ: |
|||
model->MOS9bulkCapFactor = value->rValue; |
|||
model->MOS9bulkCapFactorGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_MJ: |
|||
model->MOS9bulkJctBotGradingCoeff = value->rValue; |
|||
model->MOS9bulkJctBotGradingCoeffGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_CJSW: |
|||
model->MOS9sideWallCapFactor = value->rValue; |
|||
model->MOS9sideWallCapFactorGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_MJSW: |
|||
model->MOS9bulkJctSideGradingCoeff = value->rValue; |
|||
model->MOS9bulkJctSideGradingCoeffGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_JS: |
|||
model->MOS9jctSatCurDensity = value->rValue; |
|||
model->MOS9jctSatCurDensityGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_TOX: |
|||
model->MOS9oxideThickness = value->rValue; |
|||
model->MOS9oxideThicknessGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_LD: |
|||
model->MOS9latDiff = value->rValue; |
|||
model->MOS9latDiffGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_XL: |
|||
model->MOS9lengthAdjust = value->rValue; |
|||
model->MOS9lengthAdjustGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_WD: |
|||
model->MOS9widthNarrow = value->rValue; |
|||
model->MOS9widthNarrowGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_XW: |
|||
model->MOS9widthAdjust = value->rValue; |
|||
model->MOS9widthAdjustGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_DELVTO: |
|||
model->MOS9delvt0 = value->rValue; |
|||
model->MOS9delvt0Given = TRUE; |
|||
break; |
|||
case MOS9_MOD_U0: |
|||
model->MOS9surfaceMobility = value->rValue; |
|||
model->MOS9surfaceMobilityGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_FC: |
|||
model->MOS9fwdCapDepCoeff = value->rValue; |
|||
model->MOS9fwdCapDepCoeffGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_NSUB: |
|||
model->MOS9substrateDoping = value->rValue; |
|||
model->MOS9substrateDopingGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_TPG: |
|||
model->MOS9gateType = value->iValue; |
|||
model->MOS9gateTypeGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_NSS: |
|||
model->MOS9surfaceStateDensity = value->rValue; |
|||
model->MOS9surfaceStateDensityGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_ETA: |
|||
model->MOS9eta = value->rValue; |
|||
model->MOS9etaGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_DELTA: |
|||
model->MOS9delta = value->rValue; |
|||
model->MOS9deltaGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_NFS: |
|||
model->MOS9fastSurfaceStateDensity = value->rValue; |
|||
model->MOS9fastSurfaceStateDensityGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_THETA: |
|||
model->MOS9theta = value->rValue; |
|||
model->MOS9thetaGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_VMAX: |
|||
model->MOS9maxDriftVel = value->rValue; |
|||
model->MOS9maxDriftVelGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_KAPPA: |
|||
model->MOS9kappa = value->rValue; |
|||
model->MOS9kappaGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_NMOS: |
|||
if(value->iValue) { |
|||
model->MOS9type = 1; |
|||
model->MOS9typeGiven = TRUE; |
|||
} |
|||
break; |
|||
case MOS9_MOD_PMOS: |
|||
if(value->iValue) { |
|||
model->MOS9type = -1; |
|||
model->MOS9typeGiven = TRUE; |
|||
} |
|||
break; |
|||
case MOS9_MOD_XJ: |
|||
model->MOS9junctionDepth = value->rValue; |
|||
model->MOS9junctionDepthGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_TNOM: |
|||
model->MOS9tnom = value->rValue+CONSTCtoK; |
|||
model->MOS9tnomGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_KF: |
|||
model->MOS9fNcoef = value->rValue; |
|||
model->MOS9fNcoefGiven = TRUE; |
|||
break; |
|||
case MOS9_MOD_AF: |
|||
model->MOS9fNexp = value->rValue; |
|||
model->MOS9fNexpGiven = TRUE; |
|||
break; |
|||
default: |
|||
return(E_BADPARM); |
|||
} |
|||
return(OK); |
|||
} |
|||
@ -0,0 +1,220 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1987 Gary W. Ng |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "mos9defs.h" |
|||
#include "cktdefs.h" |
|||
#include "fteconst.h" |
|||
#include "iferrmsg.h" |
|||
#include "noisedef.h"
|
|||
#include "suffix.h" |
|||
|
|||
/* |
|||
* MOS9noise (mode, operation, firstModel, ckt, data, OnDens) |
|||
* This routine names and evaluates all of the noise sources |
|||
* associated with MOSFET's. It starts with the model *firstModel and |
|||
* traverses all of its insts. It then proceeds to any other models |
|||
* on the linked list. The total output noise density generated by |
|||
* all of the MOSFET's is summed with the variable "OnDens". |
|||
*/ |
|||
|
|||
extern void NevalSrc(); |
|||
extern double Nintegrate(); |
|||
|
|||
int |
|||
MOS9noise (mode, operation, genmodel, ckt, data, OnDens) |
|||
int mode; |
|||
int operation; |
|||
GENmodel *genmodel; |
|||
CKTcircuit *ckt; |
|||
Ndata *data; |
|||
double *OnDens; |
|||
{ |
|||
MOS9model *firstModel = (MOS9model *) genmodel; |
|||
MOS9model *model; |
|||
MOS9instance *inst; |
|||
char name[N_MXVLNTH]; |
|||
double tempOnoise; |
|||
double tempInoise; |
|||
double noizDens[MOS9NSRCS]; |
|||
double lnNdens[MOS9NSRCS]; |
|||
int error; |
|||
int i; |
|||
|
|||
/* define the names of the noise sources */ |
|||
|
|||
static char *MOS9nNames[MOS9NSRCS] = { /* Note that we have to keep the order */ |
|||
"_rd", /* noise due to rd */ /* consistent with the index definitions */ |
|||
"_rs", /* noise due to rs */ /* in MOS9defs.h */ |
|||
"_id", /* noise due to id */ |
|||
"_1overf", /* flicker (1/f) noise */ |
|||
"" /* total transistor noise */ |
|||
}; |
|||
|
|||
for (model=firstModel; model != NULL; model=model->MOS9nextModel) { |
|||
for (inst=model->MOS9instances; inst != NULL; inst=inst->MOS9nextInstance) { |
|||
switch (operation) { |
|||
|
|||
case N_OPEN: |
|||
|
|||
/* see if we have to to produce a summary report */ |
|||
/* if so, name all the noise generators */ |
|||
|
|||
if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) { |
|||
switch (mode) { |
|||
|
|||
case N_DENS: |
|||
for (i=0; i < MOS9NSRCS; i++) { |
|||
(void)sprintf(name,"onoise_%s%s",inst->MOS9name,MOS9nNames[i]); |
|||
|
|||
|
|||
data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); |
|||
if (!data->namelist) return(E_NOMEM); |
|||
(*(SPfrontEnd->IFnewUid))(ckt, |
|||
&(data->namelist[data->numPlots++]), |
|||
(IFuid)NULL,name,UID_OTHER,(GENERIC **)NULL); |
|||
/* we've added one more plot */ |
|||
|
|||
|
|||
} |
|||
break; |
|||
|
|||
case INT_NOIZ: |
|||
for (i=0; i < MOS9NSRCS; i++) { |
|||
(void)sprintf(name,"onoise_total_%s%s",inst->MOS9name,MOS9nNames[i]); |
|||
|
|||
|
|||
data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); |
|||
if (!data->namelist) return(E_NOMEM); |
|||
(*(SPfrontEnd->IFnewUid))(ckt, |
|||
&(data->namelist[data->numPlots++]), |
|||
(IFuid)NULL,name,UID_OTHER,(GENERIC **)NULL); |
|||
/* we've added one more plot */ |
|||
|
|||
|
|||
(void)sprintf(name,"inoise_total_%s%s",inst->MOS9name,MOS9nNames[i]); |
|||
|
|||
|
|||
data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); |
|||
if (!data->namelist) return(E_NOMEM); |
|||
(*(SPfrontEnd->IFnewUid))(ckt, |
|||
&(data->namelist[data->numPlots++]), |
|||
(IFuid)NULL,name,UID_OTHER,(GENERIC **)NULL); |
|||
/* we've added one more plot */ |
|||
|
|||
|
|||
|
|||
} |
|||
break; |
|||
} |
|||
} |
|||
break; |
|||
|
|||
case N_CALC: |
|||
switch (mode) { |
|||
|
|||
case N_DENS: |
|||
NevalSrc(&noizDens[MOS9RDNOIZ],&lnNdens[MOS9RDNOIZ], |
|||
ckt,THERMNOISE,inst->MOS9dNodePrime,inst->MOS9dNode, |
|||
inst->MOS9drainConductance); |
|||
|
|||
NevalSrc(&noizDens[MOS9RSNOIZ],&lnNdens[MOS9RSNOIZ], |
|||
ckt,THERMNOISE,inst->MOS9sNodePrime,inst->MOS9sNode, |
|||
inst->MOS9sourceConductance); |
|||
|
|||
NevalSrc(&noizDens[MOS9IDNOIZ],&lnNdens[MOS9IDNOIZ], |
|||
ckt,THERMNOISE,inst->MOS9dNodePrime,inst->MOS9sNodePrime, |
|||
(2.0/3.0 * fabs(inst->MOS9gm))); |
|||
|
|||
NevalSrc(&noizDens[MOS9FLNOIZ],(double*)NULL,ckt, |
|||
N_GAIN,inst->MOS9dNodePrime, inst->MOS9sNodePrime, |
|||
(double)0.0); |
|||
noizDens[MOS9FLNOIZ] *= model->MOS9fNcoef * |
|||
exp(model->MOS9fNexp * |
|||
log(MAX(fabs(inst->MOS9cd),N_MINLOG))) / |
|||
(data->freq * |
|||
(inst->MOS9w - 2*model->MOS9widthNarrow) * |
|||
inst->MOS9m * |
|||
(inst->MOS9l - 2*model->MOS9latDiff) * |
|||
model->MOS9oxideCapFactor * model->MOS9oxideCapFactor); |
|||
lnNdens[MOS9FLNOIZ] = |
|||
log(MAX(noizDens[MOS9FLNOIZ],N_MINLOG)); |
|||
|
|||
noizDens[MOS9TOTNOIZ] = noizDens[MOS9RDNOIZ] + |
|||
noizDens[MOS9RSNOIZ] + |
|||
noizDens[MOS9IDNOIZ] + |
|||
noizDens[MOS9FLNOIZ]; |
|||
lnNdens[MOS9TOTNOIZ] = |
|||
log(MAX(noizDens[MOS9TOTNOIZ], N_MINLOG)); |
|||
|
|||
*OnDens += noizDens[MOS9TOTNOIZ]; |
|||
|
|||
if (data->delFreq == 0.0) { |
|||
|
|||
/* if we haven't done any previous integration, we need to */ |
|||
/* initialize our "history" variables */ |
|||
|
|||
for (i=0; i < MOS9NSRCS; i++) { |
|||
inst->MOS9nVar[LNLSTDENS][i] = lnNdens[i]; |
|||
} |
|||
|
|||
/* clear out our integration variables if it's the first pass */ |
|||
|
|||
if (data->freq == ((NOISEAN*)ckt->CKTcurJob)->NstartFreq) { |
|||
for (i=0; i < MOS9NSRCS; i++) { |
|||
inst->MOS9nVar[OUTNOIZ][i] = 0.0; |
|||
inst->MOS9nVar[INNOIZ][i] = 0.0; |
|||
} |
|||
} |
|||
} else { /* data->delFreq != 0.0 (we have to integrate) */ |
|||
for (i=0; i < MOS9NSRCS; i++) { |
|||
if (i != MOS9TOTNOIZ) { |
|||
tempOnoise = Nintegrate(noizDens[i], lnNdens[i], |
|||
inst->MOS9nVar[LNLSTDENS][i], data); |
|||
tempInoise = Nintegrate(noizDens[i] * data->GainSqInv , |
|||
lnNdens[i] + data->lnGainInv, |
|||
inst->MOS9nVar[LNLSTDENS][i] + data->lnGainInv, |
|||
data); |
|||
inst->MOS9nVar[LNLSTDENS][i] = lnNdens[i]; |
|||
data->outNoiz += tempOnoise; |
|||
data->inNoise += tempInoise; |
|||
if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) { |
|||
inst->MOS9nVar[OUTNOIZ][i] += tempOnoise; |
|||
inst->MOS9nVar[OUTNOIZ][MOS9TOTNOIZ] += tempOnoise; |
|||
inst->MOS9nVar[INNOIZ][i] += tempInoise; |
|||
inst->MOS9nVar[INNOIZ][MOS9TOTNOIZ] += tempInoise; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
if (data->prtSummary) { |
|||
for (i=0; i < MOS9NSRCS; i++) { /* print a summary report */ |
|||
data->outpVector[data->outNumber++] = noizDens[i]; |
|||
} |
|||
} |
|||
break; |
|||
|
|||
case INT_NOIZ: /* already calculated, just output */ |
|||
if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) { |
|||
for (i=0; i < MOS9NSRCS; i++) { |
|||
data->outpVector[data->outNumber++] = inst->MOS9nVar[OUTNOIZ][i]; |
|||
data->outpVector[data->outNumber++] = inst->MOS9nVar[INNOIZ][i]; |
|||
} |
|||
} /* if */ |
|||
break; |
|||
} /* switch (mode) */ |
|||
break; |
|||
|
|||
case N_CLOSE: |
|||
return (OK); /* do nothing, the main calling routine will close */ |
|||
break; /* the plots */ |
|||
} /* switch (operation) */ |
|||
} /* for inst */ |
|||
} /* for model */ |
|||
|
|||
return(OK); |
|||
} |
|||
@ -0,0 +1,116 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
/* |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "const.h" |
|||
#include "ifsim.h"
|
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
/* ARGSUSED */ |
|||
int |
|||
MOS9param(param,value,inst,select) |
|||
int param; |
|||
IFvalue *value; |
|||
GENinstance *inst; |
|||
IFvalue *select; |
|||
{ |
|||
MOS9instance *here = (MOS9instance *)inst; |
|||
switch(param) { |
|||
|
|||
case MOS9_M: |
|||
here->MOS9m = value->rValue; |
|||
here->MOS9mGiven = TRUE; |
|||
break; |
|||
case MOS9_W: |
|||
here->MOS9w = value->rValue; |
|||
here->MOS9wGiven = TRUE; |
|||
break; |
|||
case MOS9_L: |
|||
here->MOS9l = value->rValue; |
|||
here->MOS9lGiven = TRUE; |
|||
break; |
|||
case MOS9_AS: |
|||
here->MOS9sourceArea = value->rValue; |
|||
here->MOS9sourceAreaGiven = TRUE; |
|||
break; |
|||
case MOS9_AD: |
|||
here->MOS9drainArea = value->rValue; |
|||
here->MOS9drainAreaGiven = TRUE; |
|||
break; |
|||
case MOS9_PS: |
|||
here->MOS9sourcePerimiter = value->rValue; |
|||
here->MOS9sourcePerimiterGiven = TRUE; |
|||
break; |
|||
case MOS9_PD: |
|||
here->MOS9drainPerimiter = value->rValue; |
|||
here->MOS9drainPerimiterGiven = TRUE; |
|||
break; |
|||
case MOS9_NRS: |
|||
here->MOS9sourceSquares = value->rValue; |
|||
here->MOS9sourceSquaresGiven = TRUE; |
|||
break; |
|||
case MOS9_NRD: |
|||
here->MOS9drainSquares = value->rValue; |
|||
here->MOS9drainSquaresGiven = TRUE; |
|||
break; |
|||
case MOS9_OFF: |
|||
here->MOS9off = value->iValue; |
|||
break; |
|||
case MOS9_IC_VBS: |
|||
here->MOS9icVBS = value->rValue; |
|||
here->MOS9icVBSGiven = TRUE; |
|||
break; |
|||
case MOS9_IC_VDS: |
|||
here->MOS9icVDS = value->rValue; |
|||
here->MOS9icVDSGiven = TRUE; |
|||
break; |
|||
case MOS9_IC_VGS: |
|||
here->MOS9icVGS = value->rValue; |
|||
here->MOS9icVGSGiven = TRUE; |
|||
break; |
|||
case MOS9_TEMP: |
|||
here->MOS9temp = value->rValue+CONSTCtoK; |
|||
here->MOS9tempGiven = TRUE; |
|||
break; |
|||
case MOS9_IC: |
|||
switch(value->v.numValue){ |
|||
case 3: |
|||
here->MOS9icVBS = *(value->v.vec.rVec+2); |
|||
here->MOS9icVBSGiven = TRUE; |
|||
case 2: |
|||
here->MOS9icVGS = *(value->v.vec.rVec+1); |
|||
here->MOS9icVGSGiven = TRUE; |
|||
case 1: |
|||
here->MOS9icVDS = *(value->v.vec.rVec); |
|||
here->MOS9icVDSGiven = TRUE; |
|||
break; |
|||
default: |
|||
return(E_BADPARM); |
|||
} |
|||
break; |
|||
case MOS9_L_SENS: |
|||
if(value->iValue) { |
|||
here->MOS9senParmNo = 1; |
|||
here->MOS9sens_l = 1; |
|||
} |
|||
break; |
|||
case MOS9_W_SENS: |
|||
if(value->iValue) { |
|||
here->MOS9senParmNo = 1; |
|||
here->MOS9sens_w = 1; |
|||
} |
|||
break; |
|||
default: |
|||
return(E_BADPARM); |
|||
} |
|||
return(OK); |
|||
} |
|||
@ -0,0 +1,141 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
/* |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "cktdefs.h" |
|||
#include "complex.h" |
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
|
|||
int |
|||
MOS9pzLoad(inModel,ckt,s) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
SPcomplex *s; |
|||
{ |
|||
MOS9model *model = (MOS9model *)inModel; |
|||
MOS9instance *here; |
|||
int xnrm; |
|||
int xrev; |
|||
double xgs; |
|||
double xgd; |
|||
double xgb; |
|||
double xbd; |
|||
double xbs; |
|||
double capgs; |
|||
double capgd; |
|||
double capgb; |
|||
double GateBulkOverlapCap; |
|||
double GateDrainOverlapCap; |
|||
double GateSourceOverlapCap; |
|||
double EffectiveLength; |
|||
double EffectiveWidth; |
|||
|
|||
for( ; model != NULL; model = model->MOS9nextModel) { |
|||
for(here = model->MOS9instances; here!= NULL; |
|||
here = here->MOS9nextInstance) { |
|||
|
|||
if (here->MOS9mode < 0) { |
|||
xnrm=0; |
|||
xrev=1; |
|||
} else { |
|||
xnrm=1; |
|||
xrev=0; |
|||
} |
|||
/* |
|||
* meyer's model parameters |
|||
*/ |
|||
|
|||
EffectiveWidth=here->MOS9w-2*model->MOS9widthNarrow+ |
|||
model->MOS9widthAdjust; |
|||
EffectiveLength=here->MOS9l - 2*model->MOS9latDiff+ |
|||
model->MOS9lengthAdjust; |
|||
|
|||
GateSourceOverlapCap = model->MOS9gateSourceOverlapCapFactor * |
|||
here->MOS9m * EffectiveWidth; |
|||
GateDrainOverlapCap = model->MOS9gateDrainOverlapCapFactor * |
|||
here->MOS9m * EffectiveWidth; |
|||
GateBulkOverlapCap = model->MOS9gateBulkOverlapCapFactor * |
|||
here->MOS9m * EffectiveLength; |
|||
|
|||
capgs = ( 2* *(ckt->CKTstate0+here->MOS9capgs)+ |
|||
GateSourceOverlapCap ); |
|||
capgd = ( 2* *(ckt->CKTstate0+here->MOS9capgd)+ |
|||
GateDrainOverlapCap ); |
|||
capgb = ( 2* *(ckt->CKTstate0+here->MOS9capgb)+ |
|||
GateBulkOverlapCap ); |
|||
xgs = capgs; |
|||
xgd = capgd; |
|||
xgb = capgb; |
|||
xbd = here->MOS9capbd; |
|||
xbs = here->MOS9capbs; |
|||
/*printf("mos2: xgs=%g, xgd=%g, xgb=%g, xbd=%g, xbs=%g\n", |
|||
xgs,xgd,xgb,xbd,xbs);*/ |
|||
/* |
|||
* load matrix |
|||
*/ |
|||
|
|||
*(here->MOS9GgPtr ) += (xgd+xgs+xgb)*s->real; |
|||
*(here->MOS9GgPtr +1) += (xgd+xgs+xgb)*s->imag; |
|||
*(here->MOS9BbPtr ) += (xgb+xbd+xbs)*s->real; |
|||
*(here->MOS9BbPtr +1) += (xgb+xbd+xbs)*s->imag; |
|||
*(here->MOS9DPdpPtr ) += (xgd+xbd)*s->real; |
|||
*(here->MOS9DPdpPtr +1) += (xgd+xbd)*s->imag; |
|||
*(here->MOS9SPspPtr ) += (xgs+xbs)*s->real; |
|||
*(here->MOS9SPspPtr +1) += (xgs+xbs)*s->imag; |
|||
*(here->MOS9GbPtr ) -= xgb*s->real; |
|||
*(here->MOS9GbPtr +1) -= xgb*s->imag; |
|||
*(here->MOS9GdpPtr ) -= xgd*s->real; |
|||
*(here->MOS9GdpPtr +1) -= xgd*s->imag; |
|||
*(here->MOS9GspPtr ) -= xgs*s->real; |
|||
*(here->MOS9GspPtr +1) -= xgs*s->imag; |
|||
*(here->MOS9BgPtr ) -= xgb*s->real; |
|||
*(here->MOS9BgPtr +1) -= xgb*s->imag; |
|||
*(here->MOS9BdpPtr ) -= xbd*s->real; |
|||
*(here->MOS9BdpPtr +1) -= xbd*s->imag; |
|||
*(here->MOS9BspPtr ) -= xbs*s->real; |
|||
*(here->MOS9BspPtr +1) -= xbs*s->imag; |
|||
*(here->MOS9DPgPtr ) -= xgd*s->real; |
|||
*(here->MOS9DPgPtr +1) -= xgd*s->imag; |
|||
*(here->MOS9DPbPtr ) -= xbd*s->real; |
|||
*(here->MOS9DPbPtr +1) -= xbd*s->imag; |
|||
*(here->MOS9SPgPtr ) -= xgs*s->real; |
|||
*(here->MOS9SPgPtr +1) -= xgs*s->imag; |
|||
*(here->MOS9SPbPtr ) -= xbs*s->real; |
|||
*(here->MOS9SPbPtr +1) -= xbs*s->imag; |
|||
*(here->MOS9DdPtr) += here->MOS9drainConductance; |
|||
*(here->MOS9SsPtr) += here->MOS9sourceConductance; |
|||
*(here->MOS9BbPtr) += here->MOS9gbd+here->MOS9gbs; |
|||
*(here->MOS9DPdpPtr) += here->MOS9drainConductance+ |
|||
here->MOS9gds+here->MOS9gbd+ |
|||
xrev*(here->MOS9gm+here->MOS9gmbs); |
|||
*(here->MOS9SPspPtr) += here->MOS9sourceConductance+ |
|||
here->MOS9gds+here->MOS9gbs+ |
|||
xnrm*(here->MOS9gm+here->MOS9gmbs); |
|||
*(here->MOS9DdpPtr) -= here->MOS9drainConductance; |
|||
*(here->MOS9SspPtr) -= here->MOS9sourceConductance; |
|||
*(here->MOS9BdpPtr) -= here->MOS9gbd; |
|||
*(here->MOS9BspPtr) -= here->MOS9gbs; |
|||
*(here->MOS9DPdPtr) -= here->MOS9drainConductance; |
|||
*(here->MOS9DPgPtr) += (xnrm-xrev)*here->MOS9gm; |
|||
*(here->MOS9DPbPtr) += -here->MOS9gbd+(xnrm-xrev)*here->MOS9gmbs; |
|||
*(here->MOS9DPspPtr) -= here->MOS9gds+ |
|||
xnrm*(here->MOS9gm+here->MOS9gmbs); |
|||
*(here->MOS9SPgPtr) -= (xnrm-xrev)*here->MOS9gm; |
|||
*(here->MOS9SPsPtr) -= here->MOS9sourceConductance; |
|||
*(here->MOS9SPbPtr) -= here->MOS9gbs+(xnrm-xrev)*here->MOS9gmbs; |
|||
*(here->MOS9SPdpPtr) -= here->MOS9gds+ |
|||
xrev*(here->MOS9gm+here->MOS9gmbs); |
|||
|
|||
} |
|||
} |
|||
return(OK); |
|||
} |
|||
@ -0,0 +1,782 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
/* actually load the current ac sensitivity |
|||
* information into the array previously provided |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "smpdefs.h" |
|||
#include "cktdefs.h" |
|||
#include "const.h" |
|||
#include "mos9defs.h"
|
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
MOS9sAcLoad(inModel,ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
MOS9model *model = (MOS9model *)inModel; |
|||
MOS9instance *here; |
|||
int xnrm; |
|||
int xrev; |
|||
double A0; |
|||
double Apert; |
|||
double DELA; |
|||
double DELAinv; |
|||
double gdpr0; |
|||
double gspr0; |
|||
double gds0; |
|||
double gbs0; |
|||
double gbd0; |
|||
double gm0; |
|||
double gmbs0; |
|||
double gdpr; |
|||
double gspr; |
|||
double gds; |
|||
double gbs; |
|||
double gbd; |
|||
double gm; |
|||
double gmbs; |
|||
double xcgs0; |
|||
double xcgd0; |
|||
double xcgb0; |
|||
double xbd0; |
|||
double xbs0; |
|||
double xcgs; |
|||
double xcgd; |
|||
double xcgb; |
|||
double xbd; |
|||
double xbs; |
|||
double vbsOp; |
|||
double vbdOp; |
|||
double vspr; |
|||
double vdpr; |
|||
double vgs; |
|||
double vgd; |
|||
double vgb; |
|||
double vbs; |
|||
double vbd; |
|||
double vds; |
|||
double ivspr; |
|||
double ivdpr; |
|||
double ivgs; |
|||
double ivgd; |
|||
double ivgb; |
|||
double ivbs; |
|||
double ivbd; |
|||
double ivds; |
|||
double cspr; |
|||
double cdpr; |
|||
double cgs; |
|||
double cgd; |
|||
double cgb; |
|||
double cbs; |
|||
double cbd; |
|||
double cds; |
|||
double cs0; |
|||
double csprm0; |
|||
double cd0; |
|||
double cdprm0; |
|||
double cg0; |
|||
double cb0; |
|||
double cs; |
|||
double csprm; |
|||
double cd; |
|||
double cdprm; |
|||
double cg; |
|||
double cb; |
|||
double icspr; |
|||
double icdpr; |
|||
double icgs; |
|||
double icgd; |
|||
double icgb; |
|||
double icbs; |
|||
double icbd; |
|||
double icds; |
|||
double ics0; |
|||
double icsprm0; |
|||
double icd0; |
|||
double icdprm0; |
|||
double icg0; |
|||
double icb0; |
|||
double ics; |
|||
double icsprm; |
|||
double icd; |
|||
double icdprm; |
|||
double icg; |
|||
double icb; |
|||
double DvDp; |
|||
int i; |
|||
int flag; |
|||
int error; |
|||
int iparmno; |
|||
double arg; |
|||
double sarg; |
|||
double sargsw; |
|||
double SaveState[44]; |
|||
int save_mode; |
|||
SENstruct *info; |
|||
|
|||
#ifdef SENSDEBUG |
|||
printf("MOS9senacload\n"); |
|||
printf("CKTomega = %.5e\n",ckt->CKTomega); |
|||
#endif /* SENSDEBUG */ |
|||
info = ckt->CKTsenInfo; |
|||
info->SENstatus = PERTURBATION; |
|||
for( ; model != NULL; model = model->MOS9nextModel) { |
|||
for(here = model->MOS9instances; here!= NULL; |
|||
here = here->MOS9nextInstance) { |
|||
|
|||
/* save the unperturbed values in the state vector */ |
|||
for(i=0; i <= 16; i++) |
|||
*(SaveState + i) = *(ckt->CKTstate0 + here->MOS9states + i); |
|||
|
|||
*(SaveState + 17) = here->MOS9sourceConductance; |
|||
*(SaveState + 18) = here->MOS9drainConductance; |
|||
*(SaveState + 19) = here->MOS9cd; |
|||
*(SaveState + 20) = here->MOS9cbs; |
|||
*(SaveState + 21) = here->MOS9cbd; |
|||
*(SaveState + 22) = here->MOS9gmbs; |
|||
*(SaveState + 23) = here->MOS9gm; |
|||
*(SaveState + 24) = here->MOS9gds; |
|||
*(SaveState + 25) = here->MOS9gbd; |
|||
*(SaveState + 26) = here->MOS9gbs; |
|||
*(SaveState + 27) = here->MOS9capbd; |
|||
*(SaveState + 28) = here->MOS9capbs; |
|||
*(SaveState + 29) = here->MOS9Cbd; |
|||
*(SaveState + 30) = here->MOS9Cbdsw; |
|||
*(SaveState + 31) = here->MOS9Cbs; |
|||
*(SaveState + 32) = here->MOS9Cbssw; |
|||
*(SaveState + 33) = here->MOS9f2d; |
|||
*(SaveState + 34) = here->MOS9f3d; |
|||
*(SaveState + 35) = here->MOS9f4d; |
|||
*(SaveState + 36) = here->MOS9f2s; |
|||
*(SaveState + 37) = here->MOS9f3s; |
|||
*(SaveState + 38) = here->MOS9f4s; |
|||
*(SaveState + 39) = here->MOS9cgs; |
|||
*(SaveState + 40) = here->MOS9cgd; |
|||
*(SaveState + 41) = here->MOS9cgb; |
|||
*(SaveState + 42) = here->MOS9vdsat; |
|||
*(SaveState + 43) = here->MOS9von; |
|||
save_mode = here->MOS9mode; |
|||
|
|||
xnrm=1; |
|||
xrev=0; |
|||
if (here->MOS9mode < 0) { |
|||
xnrm=0; |
|||
xrev=1; |
|||
} |
|||
|
|||
vbsOp = model->MOS9type * ( |
|||
*(ckt->CKTrhsOp+here->MOS9bNode) - |
|||
*(ckt->CKTrhsOp+here->MOS9sNodePrime)); |
|||
vbdOp = model->MOS9type * ( |
|||
*(ckt->CKTrhsOp+here->MOS9bNode) - |
|||
*(ckt->CKTrhsOp+here->MOS9dNodePrime)); |
|||
vspr = *(ckt->CKTrhsOld + here->MOS9sNode) |
|||
- *(ckt->CKTrhsOld + |
|||
here->MOS9sNodePrime) ; |
|||
ivspr = *(ckt->CKTirhsOld + here->MOS9sNode) |
|||
- *(ckt->CKTirhsOld + |
|||
here->MOS9sNodePrime) ; |
|||
vdpr = *(ckt->CKTrhsOld + here->MOS9dNode) |
|||
- *(ckt->CKTrhsOld + |
|||
here->MOS9dNodePrime) ; |
|||
ivdpr = *(ckt->CKTirhsOld + here->MOS9dNode) |
|||
- *(ckt->CKTirhsOld + |
|||
here->MOS9dNodePrime) ; |
|||
vgb = *(ckt->CKTrhsOld + here->MOS9gNode) |
|||
- *(ckt->CKTrhsOld + |
|||
here->MOS9bNode) ; |
|||
ivgb = *(ckt->CKTirhsOld + here->MOS9gNode) |
|||
- *(ckt->CKTirhsOld + |
|||
here->MOS9bNode) ; |
|||
vbs = *(ckt->CKTrhsOld + here->MOS9bNode) |
|||
- *(ckt->CKTrhsOld + |
|||
here->MOS9sNodePrime) ; |
|||
ivbs = *(ckt->CKTirhsOld + here->MOS9bNode) |
|||
- *(ckt->CKTirhsOld + |
|||
here->MOS9sNodePrime) ; |
|||
vbd = *(ckt->CKTrhsOld + here->MOS9bNode) |
|||
- *(ckt->CKTrhsOld + |
|||
here->MOS9dNodePrime) ; |
|||
ivbd = *(ckt->CKTirhsOld + here->MOS9bNode) |
|||
- *(ckt->CKTirhsOld + |
|||
here->MOS9dNodePrime) ; |
|||
vds = vbs - vbd ; |
|||
ivds = ivbs - ivbd ; |
|||
vgs = vgb + vbs ; |
|||
ivgs = ivgb + ivbs ; |
|||
vgd = vgb + vbd ; |
|||
ivgd = ivgb + ivbd ; |
|||
|
|||
#ifdef SENSDEBUG |
|||
printf("senacload instance name %s\n",here->MOS9name); |
|||
printf("gate = %d ,drain = %d, drainprm = %d\n", |
|||
here->MOS9gNode,here->MOS9dNode,here->MOS9dNodePrime); |
|||
printf("source = %d , sourceprm = %d ,body = %d, senparmno = %d\n", |
|||
here->MOS9sNode ,here->MOS9sNodePrime, |
|||
here->MOS9bNode,here->MOS9senParmNo); |
|||
printf("\n without perturbation \n"); |
|||
#endif /* SENSDEBUG */ |
|||
/* without perturbation */ |
|||
*(ckt->CKTstate0 + here->MOS9vbs) = vbsOp; |
|||
*(ckt->CKTstate0 + here->MOS9vbd) = vbdOp; |
|||
|
|||
here->MOS9senPertFlag = ON ; |
|||
if(info->SENacpertflag == 1){ |
|||
/* store the unperturbed values of small signal parameters */ |
|||
if(error = MOS9load((GENmodel*)model,ckt)) return(error); |
|||
*(here->MOS9senCgs) = here->MOS9cgs; |
|||
*(here->MOS9senCgd) = here->MOS9cgd; |
|||
*(here->MOS9senCgb) = here->MOS9cgb; |
|||
*(here->MOS9senCbd) = here->MOS9capbd; |
|||
*(here->MOS9senCbs) = here->MOS9capbs; |
|||
*(here->MOS9senGds) = here->MOS9gds; |
|||
*(here->MOS9senGbs) = here->MOS9gbs; |
|||
*(here->MOS9senGbd) = here->MOS9gbd; |
|||
*(here->MOS9senGm) = here->MOS9gm; |
|||
*(here->MOS9senGmbs) = here->MOS9gmbs; |
|||
|
|||
} |
|||
xcgs0= *(here->MOS9senCgs) * ckt->CKTomega; |
|||
xcgd0= *(here->MOS9senCgd) * ckt->CKTomega; |
|||
xcgb0= *(here->MOS9senCgb) * ckt->CKTomega; |
|||
xbd0= *(here->MOS9senCbd) * ckt->CKTomega; |
|||
xbs0= *(here->MOS9senCbs) * ckt->CKTomega; |
|||
gds0= *(here->MOS9senGds); |
|||
gbs0= *(here->MOS9senGbs); |
|||
gbd0= *(here->MOS9senGbd); |
|||
gm0= *(here->MOS9senGm); |
|||
gmbs0= *(here->MOS9senGmbs); |
|||
gdpr0 = here->MOS9drainConductance; |
|||
gspr0 = here->MOS9sourceConductance; |
|||
|
|||
|
|||
cspr = gspr0 * vspr ; |
|||
icspr = gspr0 * ivspr ; |
|||
cdpr = gdpr0 * vdpr ; |
|||
icdpr = gdpr0 * ivdpr ; |
|||
cgs = ( - xcgs0 * ivgs ); |
|||
icgs = xcgs0 * vgs ; |
|||
cgd = ( - xcgd0 * ivgd ); |
|||
icgd = xcgd0 * vgd ; |
|||
cgb = ( - xcgb0 * ivgb ); |
|||
icgb = xcgb0 * vgb ; |
|||
cbs = ( gbs0 * vbs - xbs0 * ivbs ); |
|||
icbs = ( xbs0 * vbs + gbs0 * ivbs ); |
|||
cbd = ( gbd0 * vbd - xbd0 * ivbd ); |
|||
icbd = ( xbd0 * vbd + gbd0 * ivbd ); |
|||
cds = ( gds0 * vds + xnrm * (gm0 * vgs + gmbs0 * vbs) |
|||
- xrev * (gm0 * vgd + gmbs0 * vbd) ); |
|||
icds = ( gds0 * ivds + xnrm * (gm0 * ivgs + gmbs0 * ivbs) |
|||
- xrev * (gm0 * ivgd + gmbs0 * ivbd) ); |
|||
|
|||
cs0 = cspr; |
|||
ics0 = icspr; |
|||
csprm0 = ( -cspr - cgs - cbs - cds ) ; |
|||
icsprm0 = ( -icspr - icgs - icbs - icds ) ; |
|||
cd0 = cdpr; |
|||
icd0 = icdpr; |
|||
cdprm0 = ( -cdpr - cgd - cbd + cds ) ; |
|||
icdprm0 = ( -icdpr - icgd - icbd + icds ) ; |
|||
cg0 = cgs + cgd + cgb ; |
|||
icg0 = icgs + icgd + icgb ; |
|||
cb0 = cbs + cbd - cgb ; |
|||
icb0 = icbs + icbd - icgb ; |
|||
#ifdef SENSDEBUG |
|||
printf("gspr0 = %.7e , gdpr0 = %.7e , gds0 = %.7e, gbs0 = %.7e\n", |
|||
gspr0,gdpr0,gds0,gbs0); |
|||
printf("gbd0 = %.7e , gm0 = %.7e , gmbs0 = %.7e\n",gbd0,gm0,gmbs0); |
|||
printf("xcgs0 = %.7e , xcgd0 = %.7e ,", xcgs0,xcgd0); |
|||
printf("xcgb0 = %.7e, xbd0 = %.7e,xbs0 = %.7e\n" ,xcgb0,xbd0,xbs0); |
|||
printf("vbs = %.7e , vbd = %.7e , vgb = %.7e\n",vbs,vbd,vgb); |
|||
printf("ivbs = %.7e , ivbd = %.7e , ivgb = %.7e\n",ivbs,ivbd,ivgb); |
|||
printf("cbs0 = %.7e , cbd0 = %.7e , cgb0 = %.7e\n",cbs,cbd,cgb); |
|||
printf("cb0 = %.7e , cg0 = %.7e , cs0 = %.7e\n",cb0,cg0,cs0); |
|||
printf("csprm0 = %.7e, cd0 = %.7e, cdprm0 = %.7e\n", |
|||
csprm0,cd0,cdprm0); |
|||
printf("icb0 = %.7e , icg0 = %.7e , ics0 = %.7e\n",icb0,icg0,ics0); |
|||
printf("icsprm0 = %.7e, icd0 = %.7e, icdprm0 = %.7e\n", |
|||
icsprm0,icd0,icdprm0); |
|||
printf("\nPerturbation of vbs\n"); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
/* Perturbation of vbs */ |
|||
flag = 1; |
|||
A0 = vbsOp; |
|||
DELA = info->SENpertfac * CONSTvt0 ; |
|||
DELAinv = 1.0/DELA; |
|||
|
|||
if(info->SENacpertflag == 1){ |
|||
/* store the values of small signal parameters |
|||
* corresponding to perturbed vbs */ |
|||
Apert = A0 + DELA; |
|||
*(ckt->CKTstate0 + here->MOS9vbs) = Apert; |
|||
*(ckt->CKTstate0 + here->MOS9vbd) = vbdOp; |
|||
|
|||
if(error = MOS9load((GENmodel*)model,ckt)) return(error); |
|||
|
|||
*(here->MOS9senCgs + 1) = here->MOS9cgs; |
|||
*(here->MOS9senCgd + 1) = here->MOS9cgd; |
|||
*(here->MOS9senCgb + 1) = here->MOS9cgb; |
|||
*(here->MOS9senCbd + 1) = here->MOS9capbd; |
|||
*(here->MOS9senCbs + 1) = here->MOS9capbs; |
|||
*(here->MOS9senGds + 1) = here->MOS9gds; |
|||
*(here->MOS9senGbs + 1) = here->MOS9gbs; |
|||
*(here->MOS9senGbd + 1) = here->MOS9gbd; |
|||
*(here->MOS9senGm + 1) = here->MOS9gm; |
|||
*(here->MOS9senGmbs + 1) = here->MOS9gmbs; |
|||
|
|||
*(ckt->CKTstate0 + here->MOS9vbs) = A0; |
|||
|
|||
|
|||
} |
|||
|
|||
goto load; |
|||
|
|||
|
|||
pertvbd: /* Perturbation of vbd */ |
|||
#ifdef SENSDEBUG |
|||
printf("\nPerturbation of vbd\n"); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
flag = 2; |
|||
A0 = vbdOp; |
|||
DELA = info->SENpertfac * CONSTvt0 + 1e-8; |
|||
DELAinv = 1.0/DELA; |
|||
|
|||
if(info->SENacpertflag == 1){ |
|||
/* store the values of small signal parameters |
|||
* corresponding to perturbed vbd */ |
|||
Apert = A0 + DELA; |
|||
*(ckt->CKTstate0 + here->MOS9vbs) = vbsOp; |
|||
*(ckt->CKTstate0 + here->MOS9vbd) = Apert; |
|||
|
|||
if(error = MOS9load((GENmodel*)model,ckt)) return(error); |
|||
|
|||
*(here->MOS9senCgs + 2) = here->MOS9cgs; |
|||
*(here->MOS9senCgd + 2) = here->MOS9cgd; |
|||
*(here->MOS9senCgb + 2) = here->MOS9cgb; |
|||
*(here->MOS9senCbd + 2) = here->MOS9capbd; |
|||
*(here->MOS9senCbs + 2) = here->MOS9capbs; |
|||
*(here->MOS9senGds + 2) = here->MOS9gds; |
|||
*(here->MOS9senGbs + 2) = here->MOS9gbs; |
|||
*(here->MOS9senGbd + 2) = here->MOS9gbd; |
|||
*(here->MOS9senGm + 2) = here->MOS9gm; |
|||
*(here->MOS9senGmbs + 2) = here->MOS9gmbs; |
|||
|
|||
*(ckt->CKTstate0 + here->MOS9vbd) = A0; |
|||
|
|||
} |
|||
|
|||
goto load; |
|||
|
|||
|
|||
pertvgb: /* Perturbation of vgb */ |
|||
#ifdef SENSDEBUG |
|||
printf("\nPerturbation of vgb\n"); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
flag = 3; |
|||
A0 = model->MOS9type * (*(ckt->CKTrhsOp + here->MOS9gNode) |
|||
- *(ckt->CKTrhsOp + here->MOS9bNode)); |
|||
DELA = info->SENpertfac * A0 + 1e-8; |
|||
DELAinv = model->MOS9type * 1.0/DELA; |
|||
|
|||
|
|||
if(info->SENacpertflag == 1){ |
|||
/* store the values of small signal parameters |
|||
* corresponding to perturbed vgb */ |
|||
*(ckt->CKTstate0 + here->MOS9vbs) = vbsOp; |
|||
*(ckt->CKTstate0 + here->MOS9vbd) = vbdOp; |
|||
*(ckt->CKTrhsOp + here->MOS9bNode) -= DELA; |
|||
|
|||
if(error = MOS9load((GENmodel*)model,ckt)) return(error); |
|||
|
|||
*(here->MOS9senCgs + 3) = here->MOS9cgs; |
|||
*(here->MOS9senCgd + 3) = here->MOS9cgd; |
|||
*(here->MOS9senCgb + 3) = here->MOS9cgb; |
|||
*(here->MOS9senCbd + 3) = here->MOS9capbd; |
|||
*(here->MOS9senCbs + 3) = here->MOS9capbs; |
|||
*(here->MOS9senGds + 3) = here->MOS9gds; |
|||
*(here->MOS9senGbs + 3) = here->MOS9gbs; |
|||
*(here->MOS9senGbd + 3) = here->MOS9gbd; |
|||
*(here->MOS9senGm + 3) = here->MOS9gm; |
|||
*(here->MOS9senGmbs + 3) = here->MOS9gmbs; |
|||
|
|||
|
|||
*(ckt->CKTrhsOp + here->MOS9bNode) += DELA; |
|||
} |
|||
goto load; |
|||
|
|||
pertl: /* Perturbation of length */ |
|||
|
|||
if(here->MOS9sens_l == 0){ |
|||
goto pertw; |
|||
} |
|||
#ifdef SENSDEBUG |
|||
printf("\nPerturbation of length\n"); |
|||
#endif /* SENSDEBUG */ |
|||
flag = 4; |
|||
A0 = here->MOS9l; |
|||
DELA = info->SENpertfac * A0; |
|||
DELAinv = 1.0/DELA; |
|||
|
|||
if(info->SENacpertflag == 1){ |
|||
/* store the values of small signal parameters |
|||
* corresponding to perturbed length */ |
|||
Apert = A0 + DELA; |
|||
here->MOS9l = Apert; |
|||
|
|||
*(ckt->CKTstate0 + here->MOS9vbs) = vbsOp; |
|||
*(ckt->CKTstate0 + here->MOS9vbd) = vbdOp; |
|||
|
|||
if(error = MOS9load((GENmodel*)model,ckt)) return(error); |
|||
|
|||
*(here->MOS9senCgs + 4) = here->MOS9cgs; |
|||
*(here->MOS9senCgd + 4) = here->MOS9cgd; |
|||
*(here->MOS9senCgb + 4) = here->MOS9cgb; |
|||
*(here->MOS9senCbd + 4) = here->MOS9capbd; |
|||
*(here->MOS9senCbs + 4) = here->MOS9capbs; |
|||
*(here->MOS9senGds + 4) = here->MOS9gds; |
|||
*(here->MOS9senGbs + 4) = here->MOS9gbs; |
|||
*(here->MOS9senGbd + 4) = here->MOS9gbd; |
|||
*(here->MOS9senGm + 4) = here->MOS9gm; |
|||
*(here->MOS9senGmbs + 4) = here->MOS9gmbs; |
|||
|
|||
here->MOS9l = A0; |
|||
|
|||
} |
|||
|
|||
goto load; |
|||
|
|||
pertw: /* Perturbation of width */ |
|||
if(here->MOS9sens_w == 0) |
|||
goto next; |
|||
#ifdef SENSDEBUG |
|||
printf("\nPerturbation of width\n"); |
|||
#endif /* SENSDEBUG */ |
|||
flag = 5; |
|||
A0 = here->MOS9w; |
|||
DELA = info->SENpertfac * A0; |
|||
DELAinv = 1.0/DELA; |
|||
Apert = A0 + DELA; |
|||
|
|||
if(info->SENacpertflag == 1){ |
|||
/* store the values of small signal parameters |
|||
* corresponding to perturbed width */ |
|||
here->MOS9w = Apert; |
|||
here->MOS9drainArea *= (1 + info->SENpertfac); |
|||
here->MOS9sourceArea *= (1 + info->SENpertfac); |
|||
here->MOS9Cbd *= (1 + info->SENpertfac); |
|||
here->MOS9Cbs *= (1 + info->SENpertfac); |
|||
if(here->MOS9drainPerimiter){ |
|||
here->MOS9Cbdsw += here->MOS9Cbdsw * |
|||
DELA/here->MOS9drainPerimiter; |
|||
} |
|||
if(here->MOS9sourcePerimiter){ |
|||
here->MOS9Cbssw += here->MOS9Cbssw * |
|||
DELA/here->MOS9sourcePerimiter; |
|||
} |
|||
if(vbdOp >= here->MOS9tDepCap){ |
|||
arg = 1-model->MOS9fwdCapDepCoeff; |
|||
sarg = exp( (-model->MOS9bulkJctBotGradingCoeff) * |
|||
log(arg) ); |
|||
sargsw = exp( (-model->MOS9bulkJctSideGradingCoeff) * |
|||
log(arg) ); |
|||
here->MOS9f2d = here->MOS9Cbd*(1-model->MOS9fwdCapDepCoeff* |
|||
(1+model->MOS9bulkJctBotGradingCoeff))* sarg/arg |
|||
+ here->MOS9Cbdsw*(1-model->MOS9fwdCapDepCoeff* |
|||
(1+model->MOS9bulkJctSideGradingCoeff))* |
|||
sargsw/arg; |
|||
here->MOS9f3d = here->MOS9Cbd * |
|||
model->MOS9bulkJctBotGradingCoeff * sarg/arg/ |
|||
model->MOS9bulkJctPotential |
|||
+ here->MOS9Cbdsw * |
|||
model->MOS9bulkJctSideGradingCoeff * sargsw/arg / |
|||
model->MOS9bulkJctPotential; |
|||
here->MOS9f4d = here->MOS9Cbd*model->MOS9bulkJctPotential* |
|||
(1-arg*sarg)/ (1-model->MOS9bulkJctBotGradingCoeff) |
|||
+ here->MOS9Cbdsw*model->MOS9bulkJctPotential* |
|||
(1-arg*sargsw)/ |
|||
(1-model->MOS9bulkJctSideGradingCoeff) |
|||
-here->MOS9f3d/2* |
|||
(here->MOS9tDepCap*here->MOS9tDepCap) |
|||
-here->MOS9tDepCap * here->MOS9f2d; |
|||
} |
|||
if(vbsOp >= here->MOS9tDepCap){ |
|||
arg = 1-model->MOS9fwdCapDepCoeff; |
|||
sarg = exp( (-model->MOS9bulkJctBotGradingCoeff) * |
|||
log(arg) ); |
|||
sargsw = exp( (-model->MOS9bulkJctSideGradingCoeff) * |
|||
log(arg) ); |
|||
here->MOS9f2s = here->MOS9Cbs*(1-model->MOS9fwdCapDepCoeff* |
|||
(1+model->MOS9bulkJctBotGradingCoeff))* sarg/arg |
|||
+ here->MOS9Cbssw*(1-model->MOS9fwdCapDepCoeff* |
|||
(1+model->MOS9bulkJctSideGradingCoeff))* |
|||
sargsw/arg; |
|||
here->MOS9f3s = here->MOS9Cbs * |
|||
model->MOS9bulkJctBotGradingCoeff * sarg/arg/ |
|||
model->MOS9bulkJctPotential + here->MOS9Cbssw * |
|||
model->MOS9bulkJctSideGradingCoeff * sargsw/arg / |
|||
model->MOS9bulkJctPotential; |
|||
here->MOS9f4s = here->MOS9Cbs*model->MOS9bulkJctPotential* |
|||
(1-arg*sarg)/ (1-model->MOS9bulkJctBotGradingCoeff) |
|||
+ here->MOS9Cbssw*model->MOS9bulkJctPotential* |
|||
(1-arg*sargsw)/ |
|||
(1-model->MOS9bulkJctSideGradingCoeff) |
|||
-here->MOS9f3s/2* |
|||
(here->MOS9tBulkPot*here->MOS9tBulkPot) |
|||
-here->MOS9tBulkPot * here->MOS9f2s; |
|||
} |
|||
|
|||
*(ckt->CKTstate0 + here->MOS9vbs) = vbsOp; |
|||
*(ckt->CKTstate0 + here->MOS9vbd) = vbdOp; |
|||
|
|||
if(error = MOS9load((GENmodel*)model,ckt)) return(error); |
|||
|
|||
*(here->MOS9senCgs + 5) = here->MOS9cgs; |
|||
*(here->MOS9senCgd + 5) = here->MOS9cgd; |
|||
*(here->MOS9senCgb + 5) = here->MOS9cgb; |
|||
*(here->MOS9senCbd + 5) = here->MOS9capbd; |
|||
*(here->MOS9senCbs + 5) = here->MOS9capbs; |
|||
*(here->MOS9senGds + 5) = here->MOS9gds; |
|||
*(here->MOS9senGbs + 5) = here->MOS9gbs; |
|||
*(here->MOS9senGbd + 5) = here->MOS9gbd; |
|||
*(here->MOS9senGm + 5) = here->MOS9gm; |
|||
*(here->MOS9senGmbs + 5) = here->MOS9gmbs; |
|||
|
|||
here->MOS9w = A0; |
|||
here->MOS9drainArea /= (1 + info->SENpertfac); |
|||
here->MOS9sourceArea /= (1 + info->SENpertfac); |
|||
} |
|||
|
|||
load: |
|||
|
|||
gds= *(here->MOS9senGds + flag); |
|||
gbs= *(here->MOS9senGbs + flag); |
|||
gbd= *(here->MOS9senGbd + flag); |
|||
gm= *(here->MOS9senGm + flag); |
|||
gmbs= *(here->MOS9senGmbs + flag); |
|||
if(flag == 5){ |
|||
gdpr = here->MOS9drainConductance * Apert/A0; |
|||
gspr = here->MOS9sourceConductance * Apert/A0; |
|||
} |
|||
else{ |
|||
gdpr = here->MOS9drainConductance; |
|||
gspr = here->MOS9sourceConductance; |
|||
} |
|||
|
|||
xcgs= *(here->MOS9senCgs + flag) * ckt->CKTomega; |
|||
xcgd= *(here->MOS9senCgd + flag) * ckt->CKTomega; |
|||
xcgb= *(here->MOS9senCgb + flag) * ckt->CKTomega; |
|||
xbd= *(here->MOS9senCbd + flag) * ckt->CKTomega; |
|||
xbs= *(here->MOS9senCbs + flag) * ckt->CKTomega; |
|||
|
|||
#ifdef SENSDEBUG |
|||
printf("flag = %d \n",flag); |
|||
printf("gspr = %.7e , gdpr = %.7e , gds = %.7e, gbs = %.7e\n", |
|||
gspr,gdpr,gds,gbs); |
|||
printf("gbd = %.7e , gm = %.7e , gmbs = %.7e\n",gbd,gm,gmbs); |
|||
printf("xcgs = %.7e , xcgd = %.7e , xcgb = %.7e,", xcgs,xcgd,xcgb); |
|||
printf("xbd = %.7e,xbs = %.7e\n" ,xbd,xbs); |
|||
#endif /* SENSDEBUG */ |
|||
cspr = gspr * vspr ; |
|||
icspr = gspr * ivspr ; |
|||
cdpr = gdpr * vdpr ; |
|||
icdpr = gdpr * ivdpr ; |
|||
cgs = ( - xcgs * ivgs ); |
|||
icgs = xcgs * vgs ; |
|||
cgd = ( - xcgd * ivgd ); |
|||
icgd = xcgd * vgd ; |
|||
cgb = ( - xcgb * ivgb ); |
|||
icgb = xcgb * vgb ; |
|||
cbs = ( gbs * vbs - xbs * ivbs ); |
|||
icbs = ( xbs * vbs + gbs * ivbs ); |
|||
cbd = ( gbd * vbd - xbd * ivbd ); |
|||
icbd = ( xbd * vbd + gbd * ivbd ); |
|||
cds = ( gds * vds + xnrm * (gm * vgs + gmbs * vbs) |
|||
- xrev * (gm * vgd + gmbs * vbd) ); |
|||
icds = ( gds * ivds + xnrm * (gm * ivgs + gmbs * ivbs) |
|||
- xrev * (gm * ivgd + gmbs * ivbd) ); |
|||
|
|||
cs = cspr; |
|||
ics = icspr; |
|||
csprm = ( -cspr - cgs - cbs - cds ) ; |
|||
icsprm = ( -icspr - icgs - icbs - icds ) ; |
|||
cd = cdpr; |
|||
icd = icdpr; |
|||
cdprm = ( -cdpr - cgd - cbd + cds ) ; |
|||
icdprm = ( -icdpr - icgd - icbd + icds ) ; |
|||
cg = cgs + cgd + cgb ; |
|||
icg = icgs + icgd + icgb ; |
|||
cb = cbs + cbd - cgb ; |
|||
icb = icbs + icbd - icgb ; |
|||
|
|||
#ifdef SENSDEBUG |
|||
printf("vbs = %.7e , vbd = %.7e , vgb = %.7e\n",vbs,vbd,vgb); |
|||
printf("ivbs = %.7e , ivbd = %.7e , ivgb = %.7e\n",ivbs,ivbd,ivgb); |
|||
printf("cbs = %.7e , cbd = %.7e , cgb = %.7e\n",cbs,cbd,cgb); |
|||
printf("cb = %.7e , cg = %.7e , cs = %.7e\n",cb,cg,cs); |
|||
printf("csprm = %.7e, cd = %.7e, cdprm = %.7e\n",csprm,cd,cdprm); |
|||
printf("icb = %.7e , icg = %.7e , ics = %.7e\n",icb,icg,ics); |
|||
printf("icsprm = %.7e, icd = %.7e, icdprm = %.7e\n", |
|||
icsprm,icd,icdprm); |
|||
#endif /* SENSDEBUG */ |
|||
for(iparmno = 1;iparmno<=info->SENparms;iparmno++){ |
|||
if( (flag == 4) && (iparmno != here->MOS9senParmNo) ) continue; |
|||
if( (flag == 5) && (iparmno != (here->MOS9senParmNo + |
|||
here->MOS9sens_l)) ) continue; |
|||
|
|||
switch(flag){ |
|||
case 1: |
|||
DvDp = model->MOS9type * |
|||
(info->SEN_Sap[here->MOS9bNode][iparmno] |
|||
- info->SEN_Sap[here->MOS9sNodePrime][iparmno]); |
|||
break; |
|||
case 2: |
|||
DvDp = model->MOS9type * |
|||
( info->SEN_Sap[here->MOS9bNode][iparmno] |
|||
- info->SEN_Sap[here->MOS9dNodePrime][iparmno]); |
|||
break; |
|||
case 3: |
|||
DvDp = model->MOS9type * |
|||
( info->SEN_Sap[here->MOS9gNode][iparmno] |
|||
- info->SEN_Sap[here->MOS9bNode][iparmno]); |
|||
break; |
|||
case 4: |
|||
DvDp = 1; |
|||
break; |
|||
case 5: |
|||
DvDp = 1; |
|||
break; |
|||
} |
|||
*(info->SEN_RHS[here->MOS9bNode] + iparmno) -= |
|||
( cb - cb0) * DELAinv * DvDp; |
|||
*(info->SEN_iRHS[here->MOS9bNode] + iparmno) -= |
|||
( icb - icb0) * DELAinv * DvDp; |
|||
|
|||
*(info->SEN_RHS[here->MOS9gNode] + iparmno) -= |
|||
( cg - cg0) * DELAinv * DvDp; |
|||
*(info->SEN_iRHS[here->MOS9gNode] + iparmno) -= |
|||
( icg - icg0) * DELAinv * DvDp; |
|||
|
|||
if(here->MOS9sNode != here->MOS9sNodePrime){ |
|||
*(info->SEN_RHS[here->MOS9sNode] + iparmno) -= |
|||
( cs - cs0) * DELAinv * DvDp; |
|||
*(info->SEN_iRHS[here->MOS9sNode] + iparmno) -= |
|||
( ics - ics0) * DELAinv * DvDp; |
|||
} |
|||
|
|||
*(info->SEN_RHS[here->MOS9sNodePrime] + iparmno) -= |
|||
( csprm - csprm0) * DELAinv * DvDp; |
|||
*(info->SEN_iRHS[here->MOS9sNodePrime] + iparmno) -= |
|||
( icsprm - icsprm0) * DELAinv * DvDp; |
|||
|
|||
if(here->MOS9dNode != here->MOS9dNodePrime){ |
|||
*(info->SEN_RHS[here->MOS9dNode] + iparmno) -= |
|||
( cd - cd0) * DELAinv * DvDp; |
|||
*(info->SEN_iRHS[here->MOS9dNode] + iparmno) -= |
|||
( icd - icd0) * DELAinv * DvDp; |
|||
} |
|||
|
|||
*(info->SEN_RHS[here->MOS9dNodePrime] + iparmno) -= |
|||
( cdprm - cdprm0) * DELAinv * DvDp; |
|||
*(info->SEN_iRHS[here->MOS9dNodePrime] + iparmno) -= |
|||
( icdprm - icdprm0) * DELAinv * DvDp; |
|||
#ifdef SENSDEBUG |
|||
printf("after loading\n"); |
|||
printf("DvDp = %.5e , DELAinv = %.5e ,flag = %d ,", |
|||
DvDp,DELAinv,flag); |
|||
printf("iparmno = %d,senparmno = %d\n", |
|||
iparmno,here->MOS9senParmNo); |
|||
printf("A0 = %.5e , Apert = %.5e ,CONSTvt0 = %.5e \n", |
|||
A0,Apert,CONSTvt0); |
|||
printf("senb = %.7e + j%.7e ", |
|||
*(info->SEN_RHS[here->MOS9bNode] + iparmno), |
|||
*(info->SEN_iRHS[here->MOS9bNode] + iparmno)); |
|||
printf("seng = %.7e + j%.7e ", |
|||
*(info->SEN_RHS[here->MOS9gNode] + iparmno), |
|||
*(info->SEN_iRHS[here->MOS9gNode] + iparmno)); |
|||
printf("sens = %.7e + j%.7e ", |
|||
*(info->SEN_RHS[here->MOS9sNode] + iparmno), |
|||
*(info->SEN_iRHS[here->MOS9sNode] + iparmno)); |
|||
printf("sensprm = %.7e + j%.7e ", |
|||
*(info->SEN_RHS[here->MOS9sNodePrime] + iparmno), |
|||
*(info->SEN_iRHS[here->MOS9sNodePrime] + iparmno)); |
|||
printf("send = %.7e + j%.7e ", |
|||
*(info->SEN_RHS[here->MOS9dNode] + iparmno), |
|||
*(info->SEN_iRHS[here->MOS9dNode] + iparmno)); |
|||
printf("sendprm = %.7e + j%.7e ", |
|||
*(info->SEN_RHS[here->MOS9dNodePrime] + iparmno), |
|||
*(info->SEN_iRHS[here->MOS9dNodePrime] + iparmno)); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
} |
|||
switch(flag){ |
|||
case 1: |
|||
goto pertvbd ; |
|||
case 2: |
|||
goto pertvgb ; |
|||
case 3: |
|||
goto pertl ; |
|||
case 4: |
|||
goto pertw ; |
|||
case 5: |
|||
break; |
|||
} |
|||
next: |
|||
; |
|||
|
|||
/* put the unperturbed values back into the state vector */ |
|||
for(i=0; i <= 16; i++) |
|||
*(ckt->CKTstate0 + here->MOS9states + i) = *(SaveState + i); |
|||
|
|||
here->MOS9sourceConductance = *(SaveState + 17) ; |
|||
here->MOS9drainConductance = *(SaveState + 18) ; |
|||
here->MOS9cd = *(SaveState + 19) ; |
|||
here->MOS9cbs = *(SaveState + 20) ; |
|||
here->MOS9cbd = *(SaveState + 21) ; |
|||
here->MOS9gmbs = *(SaveState + 22) ; |
|||
here->MOS9gm = *(SaveState + 23) ; |
|||
here->MOS9gds = *(SaveState + 24) ; |
|||
here->MOS9gbd = *(SaveState + 25) ; |
|||
here->MOS9gbs = *(SaveState + 26) ; |
|||
here->MOS9capbd = *(SaveState + 27) ; |
|||
here->MOS9capbs = *(SaveState + 28) ; |
|||
here->MOS9Cbd = *(SaveState + 29) ; |
|||
here->MOS9Cbdsw = *(SaveState + 30) ; |
|||
here->MOS9Cbs = *(SaveState + 31) ; |
|||
here->MOS9Cbssw = *(SaveState + 32) ; |
|||
here->MOS9f2d = *(SaveState + 33) ; |
|||
here->MOS9f3d = *(SaveState + 34) ; |
|||
here->MOS9f4d = *(SaveState + 35) ; |
|||
here->MOS9f2s = *(SaveState + 36) ; |
|||
here->MOS9f3s = *(SaveState + 37) ; |
|||
here->MOS9f4s = *(SaveState + 38) ; |
|||
here->MOS9cgs = *(SaveState + 39) ; |
|||
here->MOS9cgd = *(SaveState + 40) ; |
|||
here->MOS9cgb = *(SaveState + 41) ; |
|||
here->MOS9vdsat = *(SaveState + 42) ; |
|||
here->MOS9von = *(SaveState + 43) ; |
|||
here->MOS9mode = save_mode ; |
|||
|
|||
here->MOS9senPertFlag = OFF; |
|||
} |
|||
} |
|||
info->SENstatus = NORMAL; |
|||
#ifdef SENSDEBUG |
|||
printf("MOS9senacload end\n"); |
|||
#endif /* SENSDEBUG */ |
|||
return(OK); |
|||
} |
|||
|
|||
|
|||
@ -0,0 +1,294 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "smpdefs.h" |
|||
#include "cktdefs.h" |
|||
#include "mos9defs.h"
|
|||
#include "const.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
/* assuming silicon - make definition for epsilon of silicon */ |
|||
#define EPSSIL (11.7 * 8.854214871e-12) |
|||
|
|||
int |
|||
MOS9setup(matrix,inModel,ckt,states) |
|||
SMPmatrix *matrix; |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
int *states; |
|||
/* load the MOS9 device structure with those pointers needed later |
|||
* for fast matrix loading |
|||
*/ |
|||
|
|||
{ |
|||
register MOS9model *model = (MOS9model *)inModel; |
|||
register MOS9instance *here; |
|||
int error; |
|||
CKTnode *tmp; |
|||
|
|||
/* loop through all the MOS9 device models */ |
|||
for( ; model != NULL; model = model->MOS9nextModel ) { |
|||
|
|||
/* perform model defaulting */ |
|||
if(!model->MOS9typeGiven) { |
|||
model->MOS9type = NMOS; |
|||
} |
|||
if(!model->MOS9latDiffGiven) { |
|||
model->MOS9latDiff = 0; |
|||
} |
|||
if(!model->MOS9lengthAdjustGiven) { |
|||
model->MOS9lengthAdjust = 0; |
|||
} |
|||
if(!model->MOS9widthNarrowGiven) { |
|||
model->MOS9widthNarrow = 0; |
|||
} |
|||
if(!model->MOS9widthAdjustGiven) { |
|||
model->MOS9widthAdjust = 0; |
|||
} |
|||
if(!model->MOS9delvt0Given) { |
|||
model->MOS9delvt0 = 0; |
|||
} |
|||
if(!model->MOS9jctSatCurDensityGiven) { |
|||
model->MOS9jctSatCurDensity = 0; |
|||
} |
|||
if(!model->MOS9jctSatCurGiven) { |
|||
model->MOS9jctSatCur = 1e-14; |
|||
} |
|||
if(!model->MOS9drainResistanceGiven) { |
|||
model->MOS9drainResistance = 0; |
|||
} |
|||
if(!model->MOS9sourceResistanceGiven) { |
|||
model->MOS9sourceResistance = 0; |
|||
} |
|||
if(!model->MOS9sheetResistanceGiven) { |
|||
model->MOS9sheetResistance = 0; |
|||
} |
|||
if(!model->MOS9transconductanceGiven) { |
|||
model->MOS9transconductance = 2e-5; |
|||
} |
|||
if(!model->MOS9gateSourceOverlapCapFactorGiven) { |
|||
model->MOS9gateSourceOverlapCapFactor = 0; |
|||
} |
|||
if(!model->MOS9gateDrainOverlapCapFactorGiven) { |
|||
model->MOS9gateDrainOverlapCapFactor = 0; |
|||
} |
|||
if(!model->MOS9gateBulkOverlapCapFactorGiven) { |
|||
model->MOS9gateBulkOverlapCapFactor = 0; |
|||
} |
|||
if(!model->MOS9vt0Given) { |
|||
model->MOS9vt0 = 0; |
|||
} |
|||
if(!model->MOS9capBDGiven) { |
|||
model->MOS9capBD = 0; |
|||
} |
|||
if(!model->MOS9capBSGiven) { |
|||
model->MOS9capBS = 0; |
|||
} |
|||
if(!model->MOS9bulkCapFactorGiven) { |
|||
model->MOS9bulkCapFactor = 0; |
|||
} |
|||
if(!model->MOS9sideWallCapFactorGiven) { |
|||
model->MOS9sideWallCapFactor = 0; |
|||
} |
|||
if(!model->MOS9bulkJctPotentialGiven) { |
|||
model->MOS9bulkJctPotential = .8; |
|||
} |
|||
if(!model->MOS9bulkJctBotGradingCoeffGiven) { |
|||
model->MOS9bulkJctBotGradingCoeff = .5; |
|||
} |
|||
if(!model->MOS9bulkJctSideGradingCoeffGiven) { |
|||
model->MOS9bulkJctSideGradingCoeff = .33; |
|||
} |
|||
if(!model->MOS9fwdCapDepCoeffGiven) { |
|||
model->MOS9fwdCapDepCoeff = .5; |
|||
} |
|||
if(!model->MOS9phiGiven) { |
|||
model->MOS9phi = .6; |
|||
} |
|||
if(!model->MOS9gammaGiven) { |
|||
model->MOS9gamma = 0; |
|||
} |
|||
if(!model->MOS9deltaGiven) { |
|||
model->MOS9delta = 0; |
|||
} |
|||
if(!model->MOS9maxDriftVelGiven) { |
|||
model->MOS9maxDriftVel = 0; |
|||
} |
|||
if(!model->MOS9junctionDepthGiven) { |
|||
model->MOS9junctionDepth = 0; |
|||
} |
|||
if(!model->MOS9fastSurfaceStateDensityGiven) { |
|||
model->MOS9fastSurfaceStateDensity = 0; |
|||
} |
|||
if(!model->MOS9etaGiven) { |
|||
model->MOS9eta = 0; |
|||
} |
|||
if(!model->MOS9thetaGiven) { |
|||
model->MOS9theta = 0; |
|||
} |
|||
if(!model->MOS9kappaGiven) { |
|||
model->MOS9kappa = .2; |
|||
} |
|||
if(!model->MOS9oxideThicknessGiven) { |
|||
model->MOS9oxideThickness = 1e-7; |
|||
} |
|||
if(!model->MOS9fNcoefGiven) { |
|||
model->MOS9fNcoef = 0; |
|||
} |
|||
if(!model->MOS9fNexpGiven) { |
|||
model->MOS9fNexp = 1; |
|||
} |
|||
|
|||
/* loop through all the instances of the model */ |
|||
for (here = model->MOS9instances; here != NULL ; |
|||
here=here->MOS9nextInstance) { |
|||
|
|||
CKTnode *tmpNode; |
|||
IFuid tmpName; |
|||
|
|||
/* allocate a chunk of the state vector */ |
|||
here->MOS9states = *states; |
|||
*states += MOS9NUMSTATES; |
|||
|
|||
if(!here->MOS9drainAreaGiven) { |
|||
here->MOS9drainArea = ckt->CKTdefaultMosAD; |
|||
} |
|||
if(!here->MOS9drainPerimiterGiven) { |
|||
here->MOS9drainPerimiter = 0; |
|||
} |
|||
if(!here->MOS9drainSquaresGiven) { |
|||
here->MOS9drainSquares = 1; |
|||
} |
|||
if(!here->MOS9icVBSGiven) { |
|||
here->MOS9icVBS = 0; |
|||
} |
|||
if(!here->MOS9icVDSGiven) { |
|||
here->MOS9icVDS = 0; |
|||
} |
|||
if(!here->MOS9icVGSGiven) { |
|||
here->MOS9icVGS = 0; |
|||
} |
|||
if(!here->MOS9sourcePerimiterGiven) { |
|||
here->MOS9sourcePerimiter = 0; |
|||
} |
|||
if(!here->MOS9sourceSquaresGiven) { |
|||
here->MOS9sourceSquares = 1; |
|||
} |
|||
if(!here->MOS9vdsatGiven) { |
|||
here->MOS9vdsat = 0; |
|||
} |
|||
if(!here->MOS9vonGiven) { |
|||
here->MOS9von = 0; |
|||
} |
|||
if(!here->MOS9modeGiven) { |
|||
here->MOS9mode = 1; |
|||
} |
|||
|
|||
if((model->MOS9drainResistance != 0 || |
|||
(model->MOS9sheetResistance != 0 && |
|||
here->MOS9drainSquares != 0 ) ) && |
|||
here->MOS9dNodePrime==0) { |
|||
error = CKTmkVolt(ckt,&tmp,here->MOS9name,"internal#drain"); |
|||
if(error) return(error); |
|||
here->MOS9dNodePrime = tmp->number; |
|||
if (ckt->CKTcopyNodesets) { |
|||
if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { |
|||
if (tmpNode->nsGiven) { |
|||
tmp->nodeset=tmpNode->nodeset; |
|||
tmp->nsGiven=tmpNode->nsGiven; |
|||
} |
|||
} |
|||
} |
|||
} else { |
|||
here->MOS9dNodePrime = here->MOS9dNode; |
|||
} |
|||
|
|||
if((model->MOS9sourceResistance != 0 || |
|||
(model->MOS9sheetResistance != 0 && |
|||
here->MOS9sourceSquares != 0 ) ) && |
|||
here->MOS9sNodePrime==0) { |
|||
error = CKTmkVolt(ckt,&tmp,here->MOS9name,"internal#source"); |
|||
if(error) return(error); |
|||
here->MOS9sNodePrime = tmp->number; |
|||
if (ckt->CKTcopyNodesets) { |
|||
if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { |
|||
if (tmpNode->nsGiven) { |
|||
tmp->nodeset=tmpNode->nodeset; |
|||
tmp->nsGiven=tmpNode->nsGiven; |
|||
} |
|||
} |
|||
} |
|||
} else { |
|||
here->MOS9sNodePrime = here->MOS9sNode; |
|||
} |
|||
|
|||
/* macro to make elements with built in test for out of memory */ |
|||
#define TSTALLOC(ptr,first,second) \ |
|||
if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ |
|||
return(E_NOMEM);\ |
|||
} |
|||
|
|||
TSTALLOC(MOS9DdPtr, MOS9dNode, MOS9dNode) |
|||
TSTALLOC(MOS9GgPtr, MOS9gNode, MOS9gNode) |
|||
TSTALLOC(MOS9SsPtr, MOS9sNode, MOS9sNode) |
|||
TSTALLOC(MOS9BbPtr, MOS9bNode, MOS9bNode) |
|||
TSTALLOC(MOS9DPdpPtr, MOS9dNodePrime, MOS9dNodePrime) |
|||
TSTALLOC(MOS9SPspPtr, MOS9sNodePrime, MOS9sNodePrime) |
|||
TSTALLOC(MOS9DdpPtr, MOS9dNode, MOS9dNodePrime) |
|||
TSTALLOC(MOS9GbPtr, MOS9gNode, MOS9bNode) |
|||
TSTALLOC(MOS9GdpPtr, MOS9gNode, MOS9dNodePrime) |
|||
TSTALLOC(MOS9GspPtr, MOS9gNode, MOS9sNodePrime) |
|||
TSTALLOC(MOS9SspPtr, MOS9sNode, MOS9sNodePrime) |
|||
TSTALLOC(MOS9BdpPtr, MOS9bNode, MOS9dNodePrime) |
|||
TSTALLOC(MOS9BspPtr, MOS9bNode, MOS9sNodePrime) |
|||
TSTALLOC(MOS9DPspPtr, MOS9dNodePrime, MOS9sNodePrime) |
|||
TSTALLOC(MOS9DPdPtr, MOS9dNodePrime, MOS9dNode) |
|||
TSTALLOC(MOS9BgPtr, MOS9bNode, MOS9gNode) |
|||
TSTALLOC(MOS9DPgPtr, MOS9dNodePrime, MOS9gNode) |
|||
TSTALLOC(MOS9SPgPtr, MOS9sNodePrime, MOS9gNode) |
|||
TSTALLOC(MOS9SPsPtr, MOS9sNodePrime, MOS9sNode) |
|||
TSTALLOC(MOS9DPbPtr, MOS9dNodePrime, MOS9bNode) |
|||
TSTALLOC(MOS9SPbPtr, MOS9sNodePrime, MOS9bNode) |
|||
TSTALLOC(MOS9SPdpPtr, MOS9sNodePrime, MOS9dNodePrime) |
|||
|
|||
} |
|||
} |
|||
return(OK); |
|||
} |
|||
|
|||
int |
|||
MOS9unsetup(inModel,ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
MOS9model *model; |
|||
MOS9instance *here; |
|||
|
|||
for (model = (MOS9model *)inModel; model != NULL; |
|||
model = model->MOS9nextModel) |
|||
{ |
|||
for (here = model->MOS9instances; here != NULL; |
|||
here=here->MOS9nextInstance) |
|||
{ |
|||
if (here->MOS9dNodePrime |
|||
&& here->MOS9dNodePrime != here->MOS9dNode) |
|||
{ |
|||
CKTdltNNum(ckt, here->MOS9dNodePrime); |
|||
here->MOS9dNodePrime= 0; |
|||
} |
|||
if (here->MOS9sNodePrime |
|||
&& here->MOS9sNodePrime != here->MOS9sNode) |
|||
{ |
|||
CKTdltNNum(ckt, here->MOS9sNodePrime); |
|||
here->MOS9sNodePrime= 0; |
|||
} |
|||
} |
|||
} |
|||
return OK; |
|||
} |
|||
@ -0,0 +1,625 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
/* actually load the current sensitivity |
|||
* information into the array previously provided |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "smpdefs.h" |
|||
#include "cktdefs.h" |
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
MOS9sLoad(inModel,ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
MOS9model *model = (MOS9model *)inModel; |
|||
MOS9instance *here; |
|||
double SaveState[44]; |
|||
int save_mode; |
|||
int i; |
|||
int iparmno; |
|||
int error; |
|||
int flag; |
|||
double A0; |
|||
double DELA; |
|||
double Apert; |
|||
double DELAinv; |
|||
double gspr0; |
|||
double gspr; |
|||
double gdpr0; |
|||
double gdpr; |
|||
double cdpr0; |
|||
double cspr0; |
|||
double cd0; |
|||
double cbd0; |
|||
double cbs0; |
|||
double cd; |
|||
double cbd; |
|||
double cbs; |
|||
double DcdprDp; |
|||
double DcsprDp; |
|||
double DcbDp; |
|||
double DcdDp; |
|||
double DcbsDp; |
|||
double DcbdDp; |
|||
double DcdprmDp; |
|||
double DcsprmDp; |
|||
double qgs0; |
|||
double qgd0; |
|||
double qgb0; |
|||
double qbd0; |
|||
double qbd; |
|||
double qbs0; |
|||
double qbs; |
|||
double DqgsDp; |
|||
double DqgdDp; |
|||
double DqgbDp; |
|||
double DqbdDp; |
|||
double DqbsDp; |
|||
double Osxpgs; |
|||
double Osxpgd; |
|||
double Osxpgb; |
|||
double Osxpbd; |
|||
double Osxpbs; |
|||
double tag0; |
|||
double tag1; |
|||
double arg; |
|||
double sarg; |
|||
double sargsw; |
|||
int offset; |
|||
double EffectiveLength; |
|||
double EffectiveWidth; |
|||
SENstruct *info; |
|||
|
|||
#ifdef SENSDEBUG |
|||
printf("MOS9senload \n"); |
|||
printf("CKTtime = %.5e\n",ckt->CKTtime); |
|||
printf("CKTorder = %d\n",ckt->CKTorder); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
info = ckt->CKTsenInfo; |
|||
info->SENstatus = PERTURBATION; |
|||
|
|||
tag0 = ckt->CKTag[0]; |
|||
tag1 = ckt->CKTag[1]; |
|||
if(ckt->CKTorder == 1){ |
|||
tag1 = 0; |
|||
} |
|||
|
|||
/* loop through all the models */ |
|||
for( ; model != NULL; model = model->MOS9nextModel ) { |
|||
|
|||
/* loop through all the instances of the model */ |
|||
for (here = model->MOS9instances; here != NULL ; |
|||
here=here->MOS9nextInstance) { |
|||
|
|||
|
|||
#ifdef SENSDEBUG |
|||
printf("senload instance name %s\n",here->MOS9name); |
|||
printf("gate = %d ,drain = %d, drainprm = %d\n", |
|||
here->MOS9gNode,here->MOS9dNode,here->MOS9dNodePrime); |
|||
printf("source = %d , sourceprm = %d ,body = %d, senparmno = %d\n", |
|||
here->MOS9sNode ,here->MOS9sNodePrime, |
|||
here->MOS9bNode,here->MOS9senParmNo); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
|
|||
/* save the unperturbed values in the state vector */ |
|||
for(i=0; i <= 16; i++){ |
|||
*(SaveState + i) = *(ckt->CKTstate0 + here->MOS9states + i); |
|||
} |
|||
|
|||
*(SaveState + 17) = here->MOS9sourceConductance; |
|||
*(SaveState + 18) = here->MOS9drainConductance; |
|||
*(SaveState + 19) = here->MOS9cd; |
|||
*(SaveState + 20) = here->MOS9cbs; |
|||
*(SaveState + 21) = here->MOS9cbd; |
|||
*(SaveState + 22) = here->MOS9gmbs; |
|||
*(SaveState + 23) = here->MOS9gm; |
|||
*(SaveState + 24) = here->MOS9gds; |
|||
*(SaveState + 25) = here->MOS9gbd; |
|||
*(SaveState + 26) = here->MOS9gbs; |
|||
*(SaveState + 27) = here->MOS9capbd; |
|||
*(SaveState + 28) = here->MOS9capbs; |
|||
*(SaveState + 29) = here->MOS9Cbd; |
|||
*(SaveState + 30) = here->MOS9Cbdsw; |
|||
*(SaveState + 31) = here->MOS9Cbs; |
|||
*(SaveState + 32) = here->MOS9Cbssw; |
|||
*(SaveState + 33) = here->MOS9f2d; |
|||
*(SaveState + 34) = here->MOS9f3d; |
|||
*(SaveState + 35) = here->MOS9f4d; |
|||
*(SaveState + 36) = here->MOS9f2s; |
|||
*(SaveState + 37) = here->MOS9f3s; |
|||
*(SaveState + 38) = here->MOS9f4s; |
|||
*(SaveState + 39) = here->MOS9cgs; |
|||
*(SaveState + 40) = here->MOS9cgd; |
|||
*(SaveState + 41) = here->MOS9cgb; |
|||
*(SaveState + 42) = here->MOS9vdsat; |
|||
*(SaveState + 43) = here->MOS9von; |
|||
save_mode = here->MOS9mode; |
|||
|
|||
|
|||
if(here->MOS9senParmNo == 0) goto next1; |
|||
|
|||
#ifdef SENSDEBUG |
|||
printf("without perturbation \n"); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
cdpr0= here->MOS9cd; |
|||
cspr0= -(here->MOS9cd + here->MOS9cbd + here->MOS9cbs); |
|||
if((info->SENmode == TRANSEN) && |
|||
(ckt->CKTmode & MODEINITTRAN)){ |
|||
qgs0 = *(ckt->CKTstate1 + here->MOS9qgs); |
|||
qgd0 = *(ckt->CKTstate1 + here->MOS9qgd); |
|||
qgb0 = *(ckt->CKTstate1 + here->MOS9qgb); |
|||
} |
|||
else{ |
|||
qgs0 = *(ckt->CKTstate0 + here->MOS9qgs); |
|||
qgd0 = *(ckt->CKTstate0 + here->MOS9qgd); |
|||
qgb0 = *(ckt->CKTstate0 + here->MOS9qgb); |
|||
} |
|||
|
|||
here->MOS9senPertFlag = ON; |
|||
error = MOS9load((GENmodel*)model,ckt); |
|||
if(error) return(error); |
|||
|
|||
cd0 = here->MOS9cd ; |
|||
cbd0 = here->MOS9cbd ; |
|||
cbs0 = here->MOS9cbs ; |
|||
gspr0= here->MOS9sourceConductance ; |
|||
gdpr0= here->MOS9drainConductance ; |
|||
|
|||
qbs0 = *(ckt->CKTstate0 + here->MOS9qbs); |
|||
qbd0 = *(ckt->CKTstate0 + here->MOS9qbd); |
|||
|
|||
for( flag = 0 ; flag <= 1 ; flag++){ |
|||
if(here->MOS9sens_l == 0) |
|||
if(flag == 0) goto next2; |
|||
if(here->MOS9sens_w == 0) |
|||
if(flag == 1) goto next2; |
|||
if(flag == 0){ |
|||
A0 = here->MOS9l; |
|||
DELA = info->SENpertfac * A0; |
|||
DELAinv = 1.0/DELA; |
|||
Apert = A0 + DELA; |
|||
here->MOS9l = Apert; |
|||
} |
|||
else{ |
|||
A0 = here->MOS9w; |
|||
DELA = info->SENpertfac * A0; |
|||
DELAinv = 1.0/DELA; |
|||
Apert = A0 + DELA; |
|||
here->MOS9w = Apert; |
|||
here->MOS9drainArea *= (1 + info->SENpertfac); |
|||
here->MOS9sourceArea *= (1 + info->SENpertfac); |
|||
here->MOS9Cbd *= (1 + info->SENpertfac); |
|||
here->MOS9Cbs *= (1 + info->SENpertfac); |
|||
if(here->MOS9drainPerimiter){ |
|||
here->MOS9Cbdsw += here->MOS9Cbdsw * |
|||
DELA/here->MOS9drainPerimiter; |
|||
} |
|||
if(here->MOS9sourcePerimiter){ |
|||
here->MOS9Cbssw += here->MOS9Cbssw * |
|||
DELA/here->MOS9sourcePerimiter; |
|||
} |
|||
if(*(ckt->CKTstate0 + here->MOS9vbd) >= |
|||
here->MOS9tDepCap){ |
|||
arg = 1-model->MOS9fwdCapDepCoeff; |
|||
sarg = exp( (-model->MOS9bulkJctBotGradingCoeff) * |
|||
log(arg) ); |
|||
sargsw = exp( (-model->MOS9bulkJctSideGradingCoeff) * |
|||
log(arg) ); |
|||
here->MOS9f2d = here->MOS9Cbd* |
|||
(1-model->MOS9fwdCapDepCoeff* |
|||
(1+model->MOS9bulkJctBotGradingCoeff))* sarg/arg |
|||
+ here->MOS9Cbdsw*(1-model->MOS9fwdCapDepCoeff* |
|||
(1+model->MOS9bulkJctSideGradingCoeff))* |
|||
sargsw/arg; |
|||
here->MOS9f3d = here->MOS9Cbd * |
|||
model->MOS9bulkJctBotGradingCoeff * sarg/arg/ |
|||
model->MOS9bulkJctPotential |
|||
+ here->MOS9Cbdsw * |
|||
model->MOS9bulkJctSideGradingCoeff *sargsw/arg / |
|||
model->MOS9bulkJctPotential; |
|||
here->MOS9f4d = here->MOS9Cbd* |
|||
model->MOS9bulkJctPotential*(1-arg*sarg)/ |
|||
(1-model->MOS9bulkJctBotGradingCoeff) |
|||
+ here->MOS9Cbdsw*model->MOS9bulkJctPotential* |
|||
(1-arg*sargsw)/ |
|||
(1-model->MOS9bulkJctSideGradingCoeff) |
|||
-here->MOS9f3d/2* |
|||
(here->MOS9tDepCap*here->MOS9tDepCap) |
|||
-here->MOS9tDepCap * here->MOS9f2d; |
|||
} |
|||
if(*(ckt->CKTstate0 + here->MOS9vbs) >= |
|||
here->MOS9tDepCap){ |
|||
arg = 1-model->MOS9fwdCapDepCoeff; |
|||
sarg = exp( (-model->MOS9bulkJctBotGradingCoeff) * |
|||
log(arg) ); |
|||
sargsw = exp( (-model->MOS9bulkJctSideGradingCoeff) * |
|||
log(arg) ); |
|||
here->MOS9f2s = here->MOS9Cbs* |
|||
(1-model->MOS9fwdCapDepCoeff* |
|||
(1+model->MOS9bulkJctBotGradingCoeff))* sarg/arg |
|||
+ here->MOS9Cbssw*(1-model->MOS9fwdCapDepCoeff* |
|||
(1+model->MOS9bulkJctSideGradingCoeff))* |
|||
sargsw/arg; |
|||
here->MOS9f3s = here->MOS9Cbs * |
|||
model->MOS9bulkJctBotGradingCoeff * sarg/arg/ |
|||
model->MOS9bulkJctPotential |
|||
+ here->MOS9Cbssw * |
|||
model->MOS9bulkJctSideGradingCoeff * sargsw/arg/ |
|||
model->MOS9bulkJctPotential; |
|||
here->MOS9f4s = here->MOS9Cbs* |
|||
model->MOS9bulkJctPotential*(1-arg*sarg)/ |
|||
(1-model->MOS9bulkJctBotGradingCoeff) |
|||
+ here->MOS9Cbssw*model->MOS9bulkJctPotential* |
|||
(1-arg*sargsw)/ |
|||
(1-model->MOS9bulkJctSideGradingCoeff) |
|||
-here->MOS9f3s/2* |
|||
(here->MOS9tBulkPot*here->MOS9tBulkPot) |
|||
-here->MOS9tBulkPot * here->MOS9f2s; |
|||
} |
|||
here->MOS9drainConductance *= Apert/A0; |
|||
here->MOS9sourceConductance *= Apert/A0; |
|||
} |
|||
|
|||
|
|||
#ifdef SENSDEBUG |
|||
if(flag == 0) |
|||
printf("perturbation of l\n"); |
|||
if(flag == 1) |
|||
printf("perturbation of w\n"); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
error = MOS9load((GENmodel*)model,ckt); |
|||
if(error) return(error); |
|||
|
|||
if(flag == 0){ |
|||
here->MOS9l = A0; |
|||
} |
|||
else{ |
|||
here->MOS9w = A0; |
|||
here->MOS9drainArea /= (1 + info->SENpertfac); |
|||
here->MOS9sourceArea /= (1 + info->SENpertfac); |
|||
here->MOS9drainConductance *= A0/Apert; |
|||
here->MOS9sourceConductance *= A0/Apert; |
|||
} |
|||
cd = here->MOS9cd ; |
|||
cbd = here->MOS9cbd ; |
|||
cbs = here->MOS9cbs ; |
|||
|
|||
gspr= here->MOS9sourceConductance ; |
|||
gdpr= here->MOS9drainConductance ; |
|||
|
|||
DcdDp = (cd - cd0) * DELAinv; |
|||
DcbsDp = (cbs - cbs0) * DELAinv; |
|||
DcbdDp = (cbd - cbd0) * DELAinv; |
|||
DcbDp = ( DcbsDp + DcbdDp ); |
|||
|
|||
DcdprDp = 0; |
|||
DcsprDp = 0; |
|||
if(here->MOS9dNode != here->MOS9dNodePrime) |
|||
if(gdpr0) DcdprDp = cdpr0 * (gdpr - gdpr0)/gdpr0 * DELAinv; |
|||
if(here->MOS9sNode != here->MOS9sNodePrime) |
|||
if(gspr0) DcsprDp = cspr0 * (gspr - gspr0)/gspr0 * DELAinv; |
|||
|
|||
DcdprmDp = ( - DcdprDp + DcdDp); |
|||
DcsprmDp = ( - DcbsDp - DcdDp - DcbdDp - DcsprDp); |
|||
|
|||
if(flag == 0){ |
|||
EffectiveLength = here->MOS9l |
|||
- 2*model->MOS9latDiff + model->MOS9lengthAdjust; |
|||
if(EffectiveLength == 0){ |
|||
DqgsDp = 0; |
|||
DqgdDp = 0; |
|||
DqgbDp = 0; |
|||
} |
|||
else{ |
|||
DqgsDp = model->MOS9type * qgs0 / EffectiveLength; |
|||
DqgdDp = model->MOS9type * qgd0 / EffectiveLength; |
|||
DqgbDp = model->MOS9type * qgb0 / EffectiveLength; |
|||
} |
|||
} |
|||
else{ |
|||
EffectiveWidth = here->MOS9w |
|||
- 2*model->MOS9widthNarrow + model->MOS9widthAdjust; |
|||
DqgsDp = model->MOS9type * qgs0 / EffectiveWidth; |
|||
DqgdDp = model->MOS9type * qgd0 / EffectiveWidth; |
|||
DqgbDp = model->MOS9type * qgb0 / EffectiveWidth; |
|||
} |
|||
|
|||
|
|||
qbd = *(ckt->CKTstate0 + here->MOS9qbd); |
|||
qbs = *(ckt->CKTstate0 + here->MOS9qbs); |
|||
|
|||
DqbsDp = model->MOS9type * (qbs - qbs0)*DELAinv; |
|||
DqbdDp = model->MOS9type * (qbd - qbd0)*DELAinv; |
|||
|
|||
if(flag == 0){ |
|||
*(here->MOS9dphigs_dl) = DqgsDp; |
|||
*(here->MOS9dphigd_dl) = DqgdDp; |
|||
*(here->MOS9dphibs_dl) = DqbsDp; |
|||
*(here->MOS9dphibd_dl) = DqbdDp; |
|||
*(here->MOS9dphigb_dl) = DqgbDp; |
|||
} |
|||
else{ |
|||
*(here->MOS9dphigs_dw) = DqgsDp; |
|||
*(here->MOS9dphigd_dw) = DqgdDp; |
|||
*(here->MOS9dphibs_dw) = DqbsDp; |
|||
*(here->MOS9dphibd_dw) = DqbdDp; |
|||
*(here->MOS9dphigb_dw) = DqgbDp; |
|||
} |
|||
|
|||
|
|||
#ifdef SENSDEBUG |
|||
printf("CKTag[0]=%.7e,CKTag[1]=%.7e,flag= %d\n", |
|||
ckt->CKTag[0],ckt->CKTag[1],flag); |
|||
printf("cd0 = %.7e ,cd = %.7e,\n",cd0,cd); |
|||
printf("cbs0 = %.7e ,cbs = %.7e,\n",cbs0,cbs); |
|||
printf("cbd0 = %.7e ,cbd = %.7e,\n",cbd0,cbd); |
|||
printf("DcdprmDp = %.7e,\n",DcdprmDp); |
|||
printf("DcsprmDp = %.7e,\n",DcsprmDp); |
|||
printf("DcdprDp = %.7e,\n",DcdprDp); |
|||
printf("DcsprDp = %.7e,\n",DcsprDp); |
|||
printf("qgs0 = %.7e \n",qgs0); |
|||
printf("qgd0 = %.7e \n",qgd0); |
|||
printf("qgb0 = %.7e \n",qgb0); |
|||
printf("qbs0 = %.7e ,qbs = %.7e,\n",qbs0,qbs); |
|||
printf("qbd0 = %.7e ,qbd = %.7e,\n",qbd0,qbd); |
|||
printf("DqgsDp = %.7e \n",DqgsDp); |
|||
printf("DqgdDp = %.7e \n",DqgdDp); |
|||
printf("DqgbDp = %.7e \n",DqgbDp); |
|||
printf("DqbsDp = %.7e \n",DqbsDp); |
|||
printf("DqbdDp = %.7e \n",DqbdDp); |
|||
printf("EffectiveLength = %.7e \n",EffectiveLength); |
|||
printf("tdepCap = %.7e \n",here->MOS9tDepCap); |
|||
printf("\n"); |
|||
#endif /* SENSDEBUG*/ |
|||
if((info->SENmode == TRANSEN) && |
|||
(ckt->CKTmode & MODEINITTRAN)) |
|||
goto next2; |
|||
|
|||
/* |
|||
* load RHS matrix |
|||
*/ |
|||
|
|||
if(flag == 0){ |
|||
*(info->SEN_RHS[here->MOS9bNode] + here->MOS9senParmNo) |
|||
-= model->MOS9type * DcbDp; |
|||
*(info->SEN_RHS[here->MOS9dNode] + here->MOS9senParmNo) |
|||
-= model->MOS9type * DcdprDp; |
|||
*(info->SEN_RHS[here->MOS9dNodePrime] + here->MOS9senParmNo) |
|||
-= model->MOS9type * DcdprmDp; |
|||
*(info->SEN_RHS[here->MOS9sNode] + here->MOS9senParmNo) |
|||
-= model->MOS9type * DcsprDp; |
|||
*(info->SEN_RHS[here->MOS9sNodePrime] + here->MOS9senParmNo) |
|||
-= model->MOS9type * DcsprmDp; |
|||
} |
|||
else{ |
|||
offset = here->MOS9sens_l; |
|||
|
|||
*(info->SEN_RHS[here->MOS9bNode] + here->MOS9senParmNo + |
|||
offset) -= model->MOS9type * DcbDp; |
|||
*(info->SEN_RHS[here->MOS9dNode] + here->MOS9senParmNo + |
|||
offset) -= model->MOS9type * DcdprDp; |
|||
*(info->SEN_RHS[here->MOS9dNodePrime] + here->MOS9senParmNo |
|||
+ offset) -= model->MOS9type * DcdprmDp; |
|||
*(info->SEN_RHS[here->MOS9sNode] + here->MOS9senParmNo + |
|||
offset) -= model->MOS9type * DcsprDp; |
|||
*(info->SEN_RHS[here->MOS9sNodePrime] + here->MOS9senParmNo |
|||
+ offset) -= model->MOS9type * DcsprmDp; |
|||
} |
|||
#ifdef SENSDEBUG |
|||
printf("after loading\n"); |
|||
if(flag == 0){ |
|||
printf("DcbDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9bNode] + |
|||
here->MOS9senParmNo)); |
|||
printf("DcdprDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9dNode] + |
|||
here->MOS9senParmNo)); |
|||
printf("DcsprDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9sNode] + |
|||
here->MOS9senParmNo)); |
|||
printf("DcdprmDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9dNodePrime] + |
|||
here->MOS9senParmNo)); |
|||
printf("DcsprmDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9sNodePrime] + |
|||
here->MOS9senParmNo)); |
|||
printf("\n"); |
|||
} |
|||
else{ |
|||
printf("DcbDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9bNode] + |
|||
here->MOS9senParmNo + here->MOS9sens_l)); |
|||
printf("DcdprDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9dNode] + |
|||
here->MOS9senParmNo + here->MOS9sens_l)); |
|||
printf("DcsprDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9sNode] + |
|||
here->MOS9senParmNo + here->MOS9sens_l)); |
|||
printf("DcdprmDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9dNodePrime] + |
|||
here->MOS9senParmNo + here->MOS9sens_l)); |
|||
printf("DcsprmDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9sNodePrime] + |
|||
here->MOS9senParmNo + here->MOS9sens_l)); |
|||
} |
|||
#endif /* SENSDEBUG*/ |
|||
next2: |
|||
; |
|||
} |
|||
next1: |
|||
if((info->SENmode == DCSEN) || |
|||
(ckt->CKTmode&MODETRANOP) ) goto restore; |
|||
if((info->SENmode == TRANSEN) && |
|||
(ckt->CKTmode & MODEINITTRAN)) goto restore; |
|||
for(iparmno = 1;iparmno<=info->SENparms;iparmno++){ |
|||
#ifdef SENSDEBUG |
|||
printf("after conductive currents\n"); |
|||
printf("iparmno = %d\n",iparmno); |
|||
printf("DcbDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9bNode] + iparmno)); |
|||
printf("DcdprDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9dNode] + iparmno)); |
|||
printf("DcdprmDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9dNodePrime] + iparmno)); |
|||
printf("DcsprDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9sNode] + iparmno)); |
|||
printf("DcsprmDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9sNodePrime] + iparmno)); |
|||
printf("\n"); |
|||
#endif /* SENSDEBUG */ |
|||
Osxpgs = tag0 * *(ckt->CKTstate1 + here->MOS9sensxpgs + |
|||
10*(iparmno - 1)) |
|||
+ tag1 * *(ckt->CKTstate1 + here->MOS9sensxpgs + |
|||
10*(iparmno - 1) + 1); |
|||
|
|||
Osxpgd = tag0 * *(ckt->CKTstate1 + here->MOS9sensxpgd + |
|||
10*(iparmno - 1)) |
|||
+ tag1 * *(ckt->CKTstate1 + here->MOS9sensxpgd + |
|||
10*(iparmno - 1) + 1); |
|||
|
|||
Osxpbs = tag0 * *(ckt->CKTstate1 + here->MOS9sensxpbs + |
|||
10*(iparmno - 1)) |
|||
+ tag1 * *(ckt->CKTstate1 + here->MOS9sensxpbs + |
|||
10*(iparmno - 1) + 1); |
|||
|
|||
Osxpbd =tag0 * *(ckt->CKTstate1 + here->MOS9sensxpbd + |
|||
10*(iparmno - 1)) |
|||
+ tag1 * *(ckt->CKTstate1 + here->MOS9sensxpbd + |
|||
10*(iparmno - 1) + 1); |
|||
Osxpgb = tag0 * *(ckt->CKTstate1 + here->MOS9sensxpgb + |
|||
10*(iparmno - 1)) |
|||
+ tag1 * *(ckt->CKTstate1 + here->MOS9sensxpgb + |
|||
10*(iparmno - 1) + 1); |
|||
|
|||
#ifdef SENSDEBUG |
|||
printf("iparmno=%d\n",iparmno); |
|||
printf("sxpgs=%.7e,sdgs=%.7e\n", |
|||
*(ckt->CKTstate1 + here->MOS9sensxpgs + |
|||
10*(iparmno - 1)), *(ckt->CKTstate1 + |
|||
here->MOS9sensxpgs + 10*(iparmno - 1) + 1)); |
|||
printf("sxpgd=%.7e,sdgd=%.7e\n", |
|||
*(ckt->CKTstate1 + here->MOS9sensxpgd + |
|||
10*(iparmno - 1)), *(ckt->CKTstate1 + |
|||
here->MOS9sensxpgd + 10*(iparmno - 1) + 1)); |
|||
printf("sxpbs=%.7e,sdbs=%.7e\n", |
|||
*(ckt->CKTstate1 + here->MOS9sensxpbs + |
|||
10*(iparmno - 1)), *(ckt->CKTstate1 + |
|||
here->MOS9sensxpbs + 10*(iparmno - 1) + 1)); |
|||
printf("sxpbd=%.7e,sdbd=%.7e\n", |
|||
*(ckt->CKTstate1 + here->MOS9sensxpbd + |
|||
10*(iparmno - 1)), *(ckt->CKTstate1 + |
|||
here->MOS9sensxpbd + 10*(iparmno - 1) + 1)); |
|||
printf("sxpgb=%.7e,sdgb=%.7e\n", |
|||
*(ckt->CKTstate1 + here->MOS9sensxpgb + |
|||
10*(iparmno - 1)), *(ckt->CKTstate1 + |
|||
here->MOS9sensxpgb + 10*(iparmno - 1) + 1)); |
|||
printf("before loading DqDp\n"); |
|||
printf("Osxpgs=%.7e,Osxpgd=%.7e\n",Osxpgs,Osxpgd); |
|||
printf("Osxpbs=%.7e,Osxpbd=%.7e,Osxpgb=%.7e\n", |
|||
Osxpbs,Osxpbd,Osxpgb); |
|||
printf("\n"); |
|||
#endif /* SENSDEBUG */ |
|||
if(here->MOS9sens_l && (iparmno == here->MOS9senParmNo)){ |
|||
Osxpgs -= tag0 * *(here->MOS9dphigs_dl); |
|||
Osxpgd -= tag0 * *(here->MOS9dphigd_dl); |
|||
Osxpbs -= tag0 * *(here->MOS9dphibs_dl); |
|||
Osxpbd -= tag0 * *(here->MOS9dphibd_dl); |
|||
Osxpgb -= tag0 * *(here->MOS9dphigb_dl); |
|||
} |
|||
if(here->MOS9sens_w && |
|||
(iparmno == (here->MOS9senParmNo + here->MOS9sens_l))){ |
|||
Osxpgs -= tag0 * *(here->MOS9dphigs_dw); |
|||
Osxpgd -= tag0 * *(here->MOS9dphigd_dw); |
|||
Osxpbs -= tag0 * *(here->MOS9dphibs_dw); |
|||
Osxpbd -= tag0 * *(here->MOS9dphibd_dw); |
|||
Osxpgb -= tag0 * *(here->MOS9dphigb_dw); |
|||
} |
|||
#ifdef SENSDEBUG |
|||
printf("after loading DqDp\n"); |
|||
printf("DqgsDp=%.7e",DqgsDp); |
|||
printf("Osxpgs=%.7e,Osxpgd=%.7e\n",Osxpgs,Osxpgd); |
|||
printf("Osxpbs=%.7e,Osxpbd=%.7e,Osxpgb=%.7e\n", |
|||
Osxpbs,Osxpbd,Osxpgb); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
*(info->SEN_RHS[here->MOS9bNode] + iparmno) += |
|||
Osxpbs + Osxpbd -Osxpgb; |
|||
*(info->SEN_RHS[here->MOS9gNode] + iparmno) += |
|||
Osxpgs + Osxpgd + Osxpgb; |
|||
|
|||
*(info->SEN_RHS[here->MOS9dNodePrime] + iparmno) -= |
|||
Osxpgd + Osxpbd ; |
|||
*(info->SEN_RHS[here->MOS9sNodePrime] + iparmno) -= |
|||
Osxpgs + Osxpbs; |
|||
#ifdef SENSDEBUG |
|||
printf("after capacitive currents\n"); |
|||
printf("DcbDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9bNode] + iparmno)); |
|||
printf("DcdprDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9dNode] + iparmno)); |
|||
printf("DcdprmDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9dNodePrime] + iparmno)); |
|||
printf("DcsprDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9sNode] + iparmno)); |
|||
printf("DcsprmDp=%.7e\n", |
|||
*(info->SEN_RHS[here->MOS9sNodePrime] + iparmno)); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
} |
|||
restore: /* put the unperturbed values back into the state vector */ |
|||
for(i=0; i <= 16; i++) |
|||
*(ckt->CKTstate0 + here->MOS9states + i) = *(SaveState + i); |
|||
here->MOS9sourceConductance = *(SaveState + 17) ; |
|||
here->MOS9drainConductance = *(SaveState + 18) ; |
|||
here->MOS9cd = *(SaveState + 19) ; |
|||
here->MOS9cbs = *(SaveState + 20) ; |
|||
here->MOS9cbd = *(SaveState + 21) ; |
|||
here->MOS9gmbs = *(SaveState + 22) ; |
|||
here->MOS9gm = *(SaveState + 23) ; |
|||
here->MOS9gds = *(SaveState + 24) ; |
|||
here->MOS9gbd = *(SaveState + 25) ; |
|||
here->MOS9gbs = *(SaveState + 26) ; |
|||
here->MOS9capbd = *(SaveState + 27) ; |
|||
here->MOS9capbs = *(SaveState + 28) ; |
|||
here->MOS9Cbd = *(SaveState + 29) ; |
|||
here->MOS9Cbdsw = *(SaveState + 30) ; |
|||
here->MOS9Cbs = *(SaveState + 31) ; |
|||
here->MOS9Cbssw = *(SaveState + 32) ; |
|||
here->MOS9f2d = *(SaveState + 33) ; |
|||
here->MOS9f3d = *(SaveState + 34) ; |
|||
here->MOS9f4d = *(SaveState + 35) ; |
|||
here->MOS9f2s = *(SaveState + 36) ; |
|||
here->MOS9f3s = *(SaveState + 37) ; |
|||
here->MOS9f4s = *(SaveState + 38) ; |
|||
here->MOS9cgs = *(SaveState + 39) ; |
|||
here->MOS9cgd = *(SaveState + 40) ; |
|||
here->MOS9cgb = *(SaveState + 41) ; |
|||
here->MOS9vdsat = *(SaveState + 42) ; |
|||
here->MOS9von = *(SaveState + 43) ; |
|||
here->MOS9mode = save_mode ; |
|||
|
|||
here->MOS9senPertFlag = OFF; |
|||
|
|||
} |
|||
} |
|||
info->SENstatus = NORMAL; |
|||
#ifdef SENSDEBUG |
|||
printf("MOS9senload end\n"); |
|||
#endif /* SENSDEBUG */ |
|||
return(OK); |
|||
} |
|||
|
|||
@ -0,0 +1,65 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
/* Pretty print the sensitivity info for all the MOS9 |
|||
* devices in the circuit. |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "smpdefs.h" |
|||
#include "cktdefs.h" |
|||
#include "mos9defs.h"
|
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
void |
|||
MOS9sPrint(inModel,ckt) |
|||
GENmodel *inModel; |
|||
register CKTcircuit *ckt; |
|||
{ |
|||
register MOS9model *model = (MOS9model *)inModel; |
|||
register MOS9instance *here; |
|||
|
|||
printf("LEVEL 3 MOSFETS (AG) -----------------\n"); |
|||
/* loop through all the MOS9 models */ |
|||
for( ; model != NULL; model = model->MOS9nextModel ) { |
|||
|
|||
printf("Model name:%s\n",model->MOS9modName); |
|||
|
|||
/* loop through all the instances of the model */ |
|||
for (here = model->MOS9instances; here != NULL ; |
|||
here=here->MOS9nextInstance) { |
|||
|
|||
printf(" Instance name:%s\n",here->MOS9name); |
|||
printf(" Drain, Gate , Source nodes: %s, %s ,%s\n", |
|||
CKTnodName(ckt,here->MOS9dNode),CKTnodName(ckt,here->MOS9gNode), |
|||
CKTnodName(ckt,here->MOS9sNode)); |
|||
|
|||
printf(" Multiplier: %g ",here->MOS9m); |
|||
printf(here->MOS9mGiven ? "(specified)\n" : "(default)\n"); |
|||
printf(" Length: %g ",here->MOS9l); |
|||
printf(here->MOS9lGiven ? "(specified)\n" : "(default)\n"); |
|||
printf(" Width: %g ",here->MOS9w); |
|||
printf(here->MOS9wGiven ? "(specified)\n" : "(default)\n"); |
|||
if(here->MOS9sens_l == 1){ |
|||
printf(" MOS9senParmNo:l = %d ",here->MOS9senParmNo); |
|||
} |
|||
else{ |
|||
printf(" MOS9senParmNo:l = 0 "); |
|||
} |
|||
if(here->MOS9sens_w == 1){ |
|||
printf(" w = %d \n",here->MOS9senParmNo + here->MOS9sens_l); |
|||
} |
|||
else{ |
|||
printf(" w = 0 \n"); |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,54 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
/* loop through all the devices and |
|||
* allocate parameter #s to design parameters |
|||
*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "smpdefs.h" |
|||
#include "cktdefs.h" |
|||
#include "mos9defs.h"
|
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
MOS9sSetup(info,inModel) |
|||
SENstruct *info; |
|||
GENmodel *inModel; |
|||
{ |
|||
MOS9model *model = (MOS9model *)inModel; |
|||
MOS9instance *here; |
|||
|
|||
/* loop through all the models */ |
|||
for( ; model != NULL; model = model->MOS9nextModel ) { |
|||
|
|||
/* loop through all the instances of the model */ |
|||
for (here = model->MOS9instances; here != NULL ; |
|||
here=here->MOS9nextInstance) { |
|||
|
|||
|
|||
if(here->MOS9senParmNo){ |
|||
if((here->MOS9sens_l)&&(here->MOS9sens_w)){ |
|||
here->MOS9senParmNo = ++(info->SENparms); |
|||
++(info->SENparms);/* MOS has two design parameters */ |
|||
} |
|||
else{ |
|||
here->MOS9senParmNo = ++(info->SENparms); |
|||
} |
|||
} |
|||
here->MOS9senPertFlag = OFF; |
|||
if((here->MOS9sens = (double *)MALLOC(72*sizeof(double))) == NULL) { |
|||
return(E_NOMEM); |
|||
} |
|||
|
|||
} |
|||
} |
|||
return(OK); |
|||
} |
|||
|
|||
|
|||
@ -0,0 +1,182 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
#include <stdio.h> |
|||
#include "ngspice.h" |
|||
#include "smpdefs.h" |
|||
#include "cktdefs.h" |
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
MOS9sUpdate(inModel,ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
MOS9model *model = (MOS9model *)inModel; |
|||
MOS9instance *here; |
|||
int iparmno; |
|||
double sb; |
|||
double sg; |
|||
double sdprm; |
|||
double ssprm; |
|||
double sxpgs; |
|||
double sxpgd; |
|||
double sxpbs; |
|||
double sxpbd; |
|||
double sxpgb; |
|||
double dummy1; |
|||
double dummy2; |
|||
SENstruct *info; |
|||
|
|||
|
|||
if(ckt->CKTtime == 0) return(OK); |
|||
info = ckt->CKTsenInfo; |
|||
|
|||
#ifdef SENSDEBUG |
|||
printf("MOS9senupdate\n"); |
|||
printf("CKTtime = %.5e\n",ckt->CKTtime); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
sxpgs = 0; |
|||
sxpgd = 0; |
|||
sxpbs = 0; |
|||
sxpbd = 0; |
|||
sxpgb = 0; |
|||
dummy1 = 0; |
|||
dummy2 = 0; |
|||
|
|||
/* loop through all the MOS9 models */ |
|||
for( ; model != NULL; model = model->MOS9nextModel ) { |
|||
|
|||
/* loop through all the instances of the model */ |
|||
for (here = model->MOS9instances; here != NULL ; |
|||
here=here->MOS9nextInstance) { |
|||
|
|||
|
|||
#ifdef SENSDEBUG |
|||
printf("senupdate instance name %s\n",here->MOS9name); |
|||
printf("before loading\n"); |
|||
printf("CKTag[0] = %.2e,CKTag[1] = %.2e\n", |
|||
ckt->CKTag[0],ckt->CKTag[1]); |
|||
printf("capgs = %.7e\n",here->MOS9cgs); |
|||
printf("capgd = %.7e\n",here->MOS9cgd); |
|||
printf("capgb = %.7e\n",here->MOS9cgb); |
|||
printf("capbs = %.7e\n",here->MOS9capbs); |
|||
printf("capbd = %.7e\n",here->MOS9capbd); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
for(iparmno = 1;iparmno<=info->SENparms;iparmno++){ |
|||
|
|||
sb = *(info->SEN_Sap[here->MOS9bNode] + iparmno); |
|||
sg = *(info->SEN_Sap[here->MOS9gNode] + iparmno); |
|||
ssprm = *(info->SEN_Sap[here->MOS9sNodePrime] + iparmno); |
|||
sdprm = *(info->SEN_Sap[here->MOS9dNodePrime] + iparmno); |
|||
#ifdef SENSDEBUG |
|||
printf("iparmno = %d\n",iparmno); |
|||
printf("sb = %.7e,sg = %.7e\n",sb,sg); |
|||
printf("ssprm = %.7e,sdprm = %.7e\n",ssprm,sdprm); |
|||
#endif /* SENSDEBUG */ |
|||
|
|||
sxpgs = (sg - ssprm) * here->MOS9cgs ; |
|||
sxpgd = (sg - sdprm) * here->MOS9cgd ; |
|||
sxpgb = (sg - sb) * here->MOS9cgb ; |
|||
sxpbs = (sb - ssprm) * here->MOS9capbs ; |
|||
sxpbd = (sb - sdprm) * here->MOS9capbd ; |
|||
|
|||
if(here->MOS9sens_l && (iparmno == here->MOS9senParmNo)){ |
|||
sxpgs += *(here->MOS9dphigs_dl); |
|||
sxpgd += *(here->MOS9dphigd_dl); |
|||
sxpbs += *(here->MOS9dphibs_dl); |
|||
sxpbd += *(here->MOS9dphibd_dl); |
|||
sxpgb += *(here->MOS9dphigb_dl); |
|||
} |
|||
if(here->MOS9sens_w && |
|||
(iparmno == (here->MOS9senParmNo+here->MOS9sens_l))){ |
|||
sxpgs += *(here->MOS9dphigs_dw); |
|||
sxpgd += *(here->MOS9dphigd_dw); |
|||
sxpbs += *(here->MOS9dphibs_dw); |
|||
sxpbd += *(here->MOS9dphibd_dw); |
|||
sxpgb += *(here->MOS9dphigb_dw); |
|||
} |
|||
if(ckt->CKTmode & MODEINITTRAN) { |
|||
*(ckt->CKTstate1 + here->MOS9sensxpgs + |
|||
10 * (iparmno - 1)) = sxpgs; |
|||
*(ckt->CKTstate1 + here->MOS9sensxpgd + |
|||
10 * (iparmno - 1)) = sxpgd; |
|||
*(ckt->CKTstate1 + here->MOS9sensxpbs + |
|||
10 * (iparmno - 1)) = sxpbs; |
|||
*(ckt->CKTstate1 + here->MOS9sensxpbd + |
|||
10 * (iparmno - 1)) = sxpbd; |
|||
*(ckt->CKTstate1 + here->MOS9sensxpgb + |
|||
10 * (iparmno - 1)) = sxpgb; |
|||
*(ckt->CKTstate1 + here->MOS9sensxpgs + |
|||
10 * (iparmno - 1) + 1) = 0; |
|||
*(ckt->CKTstate1 + here->MOS9sensxpgd + |
|||
10 * (iparmno - 1) + 1) = 0; |
|||
*(ckt->CKTstate1 + here->MOS9sensxpbs + |
|||
10 * (iparmno - 1) + 1) = 0; |
|||
*(ckt->CKTstate1 + here->MOS9sensxpbd + |
|||
10 * (iparmno - 1) + 1) = 0; |
|||
*(ckt->CKTstate1 + here->MOS9sensxpgb + |
|||
10 * (iparmno - 1) + 1) = 0; |
|||
goto next; |
|||
} |
|||
|
|||
*(ckt->CKTstate0 + here->MOS9sensxpgs + |
|||
10 * (iparmno - 1)) = sxpgs; |
|||
*(ckt->CKTstate0 + here->MOS9sensxpgd + |
|||
10 * (iparmno - 1)) = sxpgd; |
|||
*(ckt->CKTstate0 + here->MOS9sensxpbs + |
|||
10 * (iparmno - 1)) = sxpbs; |
|||
*(ckt->CKTstate0 + here->MOS9sensxpbd + |
|||
10 * (iparmno - 1)) = sxpbd; |
|||
*(ckt->CKTstate0 + here->MOS9sensxpgb + |
|||
10 * (iparmno - 1)) = sxpgb; |
|||
|
|||
NIintegrate(ckt,&dummy1,&dummy2,here->MOS9cgs, |
|||
here->MOS9sensxpgs + 10*(iparmno -1)); |
|||
NIintegrate(ckt,&dummy1,&dummy2,here->MOS9cgd, |
|||
here->MOS9sensxpgd + 10*(iparmno -1)); |
|||
NIintegrate(ckt,&dummy1,&dummy2,here->MOS9cgb, |
|||
here->MOS9sensxpgb + 10*(iparmno -1)); |
|||
NIintegrate(ckt,&dummy1,&dummy2,here->MOS9capbs, |
|||
here->MOS9sensxpbs + 10*(iparmno -1)); |
|||
NIintegrate(ckt,&dummy1,&dummy2,here->MOS9capbd, |
|||
here->MOS9sensxpbd + 10*(iparmno -1)); |
|||
|
|||
|
|||
next: |
|||
; |
|||
#ifdef SENSDEBUG |
|||
printf("after loading\n"); |
|||
printf("sxpgs = %.7e,sdotxpgs = %.7e\n", |
|||
sxpgs,*(ckt->CKTstate0 + here->MOS9sensxpgs + |
|||
10 * (iparmno - 1) + 1)); |
|||
printf("sxpgd = %.7e,sdotxpgd = %.7e\n", |
|||
sxpgd,*(ckt->CKTstate0 + here->MOS9sensxpgd + |
|||
10 * (iparmno - 1) + 1)); |
|||
printf("sxpgb = %.7e,sdotxpgb = %.7e\n", |
|||
sxpgb,*(ckt->CKTstate0 + here->MOS9sensxpgb + |
|||
10 * (iparmno - 1) + 1)); |
|||
printf("sxpbs = %.7e,sdotxpbs = %.7e\n", |
|||
sxpbs,*(ckt->CKTstate0 + here->MOS9sensxpbs + |
|||
10 * (iparmno - 1) + 1)); |
|||
printf("sxpbd = %.7e,sdotxpbd = %.7e\n", |
|||
sxpbd,*(ckt->CKTstate0 + here->MOS9sensxpbd + |
|||
10 * (iparmno - 1) + 1)); |
|||
#endif /* SENSDEBUG */ |
|||
} |
|||
} |
|||
} |
|||
#ifdef SENSDEBUG |
|||
printf("MOS9senupdate end\n"); |
|||
#endif /* SENSDEBUG */ |
|||
return(OK); |
|||
|
|||
} |
|||
|
|||
@ -0,0 +1,343 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "cktdefs.h" |
|||
#include "mos9defs.h"
|
|||
#include "const.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
/* assuming silicon - make definition for epsilon of silicon */ |
|||
#define EPSSIL (11.7 * 8.854214871e-12) |
|||
|
|||
int |
|||
MOS9temp(inModel,ckt) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
{ |
|||
MOS9model *model = (MOS9model *)inModel; |
|||
MOS9instance *here; |
|||
double wkfngs; |
|||
double wkfng; |
|||
double fermig; |
|||
double fermis; |
|||
double vfb; |
|||
double fact1,fact2; |
|||
double vt,vtnom; |
|||
double kt,kt1; |
|||
double ratio,ratio4; |
|||
double egfet,egfet1; |
|||
double pbfact,pbfact1,pbo; |
|||
double phio; |
|||
double arg1; |
|||
double capfact; |
|||
double gmanew,gmaold; |
|||
double ni_temp, nifact; |
|||
/* loop through all the mosfet models */ |
|||
for( ; model != NULL; model = model->MOS9nextModel) { |
|||
|
|||
if(!model->MOS9tnomGiven) { |
|||
model->MOS9tnom = ckt->CKTnomTemp; |
|||
} |
|||
fact1 = model->MOS9tnom/REFTEMP; |
|||
vtnom = model->MOS9tnom*CONSTKoverQ; |
|||
kt1 = CONSTboltz * model->MOS9tnom; |
|||
egfet1 = 1.16-(7.02e-4*model->MOS9tnom*model->MOS9tnom)/ |
|||
(model->MOS9tnom+1108); |
|||
arg1 = -egfet1/(kt1+kt1)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP)); |
|||
pbfact1 = -2*vtnom *(1.5*log(fact1)+CHARGE*arg1); |
|||
|
|||
nifact=(model->MOS9tnom/300)*sqrt(model->MOS9tnom/300); |
|||
nifact*=exp(0.5*egfet1*((1/(double)300)-(1/model->MOS9tnom))/ |
|||
CONSTKoverQ); |
|||
ni_temp=1.45e16*nifact;
|
|||
|
|||
|
|||
model->MOS9oxideCapFactor = 3.9 * 8.854214871e-12/ |
|||
model->MOS9oxideThickness; |
|||
if(!model->MOS9surfaceMobilityGiven) model->MOS9surfaceMobility=600; |
|||
if(!model->MOS9transconductanceGiven) { |
|||
model->MOS9transconductance = model->MOS9surfaceMobility * |
|||
model->MOS9oxideCapFactor * 1e-4; |
|||
} |
|||
if(model->MOS9substrateDopingGiven) { |
|||
if(model->MOS9substrateDoping*1e6 /*(cm**3/m**3)*/ >ni_temp) { |
|||
|
|||
if(!model->MOS9phiGiven) { |
|||
model->MOS9phi = 2*vtnom* |
|||
log(model->MOS9substrateDoping* |
|||
|
|||
1e6/*(cm**3/m**3)*//ni_temp); |
|||
|
|||
model->MOS9phi = MAX(.1,model->MOS9phi); |
|||
} |
|||
fermis = model->MOS9type * .5 * model->MOS9phi; |
|||
wkfng = 3.2; |
|||
if(!model->MOS9gateTypeGiven) model->MOS9gateType=1; |
|||
if(model->MOS9gateType != 0) { |
|||
fermig = model->MOS9type * model->MOS9gateType*.5*egfet1; |
|||
wkfng = 3.25 + .5 * egfet1 - fermig; |
|||
} |
|||
wkfngs = wkfng - (3.25 + .5 * egfet1 +fermis); |
|||
if(!model->MOS9gammaGiven) { |
|||
model->MOS9gamma = sqrt(2 * EPSSIL * |
|||
CHARGE * model->MOS9substrateDoping* |
|||
1e6 /*(cm**3/m**3)*/ )/ model->MOS9oxideCapFactor; |
|||
} |
|||
if(!model->MOS9vt0Given) { |
|||
if(!model->MOS9surfaceStateDensityGiven) |
|||
model->MOS9surfaceStateDensity=0; |
|||
vfb = wkfngs - model->MOS9surfaceStateDensity * 1e4 |
|||
* CHARGE/model->MOS9oxideCapFactor; |
|||
model->MOS9vt0 = vfb + model->MOS9type * |
|||
(model->MOS9gamma * sqrt(model->MOS9phi)+ |
|||
model->MOS9phi); |
|||
} else { |
|||
vfb = model->MOS9vt0 - model->MOS9type * (model->MOS9gamma* |
|||
sqrt(model->MOS9phi)+model->MOS9phi); |
|||
} |
|||
model->MOS9alpha = (EPSSIL+EPSSIL)/ |
|||
(CHARGE*model->MOS9substrateDoping*1e6 /*(cm**3/m**3)*/ ); |
|||
model->MOS9coeffDepLayWidth = sqrt(model->MOS9alpha); |
|||
} else { |
|||
model->MOS9substrateDoping = 0; |
|||
(*(SPfrontEnd->IFerror))(ERR_FATAL, |
|||
"%s: Nsub < Ni ",&(model->MOS9modName)); |
|||
return(E_BADPARM); |
|||
} |
|||
} |
|||
/* now model parameter preprocessing */ |
|||
model->MOS9narrowFactor = model->MOS9delta * 0.5 * M_PI * EPSSIL / |
|||
model->MOS9oxideCapFactor ; |
|||
|
|||
|
|||
/* loop through all instances of the model */ |
|||
for(here = model->MOS9instances; here!= NULL; |
|||
here = here->MOS9nextInstance) { |
|||
|
|||
double czbd; /* zero voltage bulk-drain capacitance */ |
|||
double czbdsw; /* zero voltage bulk-drain sidewall capacitance */ |
|||
double czbs; /* zero voltage bulk-source capacitance */ |
|||
double czbssw; /* zero voltage bulk-source sidewall capacitance */ |
|||
double arg; /* 1 - fc */ |
|||
double sarg; /* (1-fc) ^^ (-mj) */ |
|||
double sargsw; /* (1-fc) ^^ (-mjsw) */ |
|||
|
|||
/* perform the parameter defaulting */ |
|||
|
|||
if(!here->MOS9tempGiven) { |
|||
here->MOS9temp = ckt->CKTtemp; |
|||
} |
|||
vt = here->MOS9temp * CONSTKoverQ; |
|||
ratio = here->MOS9temp/model->MOS9tnom; |
|||
fact2 = here->MOS9temp/REFTEMP; |
|||
kt = here->MOS9temp * CONSTboltz; |
|||
egfet = 1.16-(7.02e-4*here->MOS9temp*here->MOS9temp)/ |
|||
(here->MOS9temp+1108); |
|||
arg = -egfet/(kt+kt)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP)); |
|||
pbfact = -2*vt *(1.5*log(fact2)+CHARGE*arg); |
|||
|
|||
if(!here->MOS9mGiven) { |
|||
here->MOS9m = ckt->CKTdefaultMosM; |
|||
} |
|||
|
|||
if(!here->MOS9lGiven) { |
|||
here->MOS9l = ckt->CKTdefaultMosL; |
|||
} |
|||
if(!here->MOS9sourceAreaGiven) { |
|||
here->MOS9sourceArea = ckt->CKTdefaultMosAS; |
|||
} |
|||
if(!here->MOS9wGiven) { |
|||
here->MOS9w = ckt->CKTdefaultMosW; |
|||
} |
|||
if(model->MOS9drainResistanceGiven) { |
|||
if(model->MOS9drainResistance != 0) { |
|||
here->MOS9drainConductance = here->MOS9m / |
|||
model->MOS9drainResistance; |
|||
} else { |
|||
here->MOS9drainConductance = 0; |
|||
} |
|||
} else if (model->MOS9sheetResistanceGiven) { |
|||
if ((model->MOS9sheetResistance != 0) && |
|||
(here->MOS9drainSquares != 0)) { |
|||
here->MOS9drainConductance = |
|||
here->MOS9m / |
|||
(model->MOS9sheetResistance*here->MOS9drainSquares); |
|||
} else { |
|||
here->MOS9drainConductance = 0; |
|||
} |
|||
} else { |
|||
here->MOS9drainConductance = 0; |
|||
} |
|||
if(model->MOS9sourceResistanceGiven) { |
|||
if(model->MOS9sourceResistance != 0) { |
|||
here->MOS9sourceConductance = here->MOS9m / |
|||
model->MOS9sourceResistance; |
|||
} else { |
|||
here->MOS9sourceConductance = 0; |
|||
} |
|||
} else if (model->MOS9sheetResistanceGiven) { |
|||
if ((model->MOS9sheetResistance != 0) && |
|||
(here->MOS9sourceSquares != 0)) { |
|||
here->MOS9sourceConductance = |
|||
here->MOS9m / |
|||
(model->MOS9sheetResistance*here->MOS9sourceSquares); |
|||
} else { |
|||
here->MOS9sourceConductance = 0; |
|||
} |
|||
} else { |
|||
here->MOS9sourceConductance = 0; |
|||
} |
|||
|
|||
if(here->MOS9l - 2 * model->MOS9latDiff + |
|||
model->MOS9lengthAdjust <1e-6) { |
|||
(*(SPfrontEnd->IFerror))(ERR_FATAL, |
|||
"%s: effective channel length less than zero", |
|||
&(here->MOS9name)); |
|||
return(E_PARMVAL); |
|||
} |
|||
|
|||
if(here->MOS9w - 2 * model->MOS9widthNarrow + |
|||
model->MOS9widthAdjust <1e-6) { |
|||
(*(SPfrontEnd->IFerror))(ERR_FATAL, |
|||
"%s: effective channel width less than zero", |
|||
&(here->MOS9name)); |
|||
return(E_PARMVAL); |
|||
} |
|||
|
|||
|
|||
ratio4 = ratio * sqrt(ratio); |
|||
here->MOS9tTransconductance = model->MOS9transconductance / ratio4; |
|||
here->MOS9tSurfMob = model->MOS9surfaceMobility/ratio4; |
|||
phio= (model->MOS9phi-pbfact1)/fact1; |
|||
here->MOS9tPhi = fact2 * phio + pbfact; |
|||
here->MOS9tVbi = |
|||
model->MOS9delvt0 + |
|||
model->MOS9vt0 - model->MOS9type * |
|||
(model->MOS9gamma* sqrt(model->MOS9phi)) |
|||
+.5*(egfet1-egfet) |
|||
+ model->MOS9type*.5* (here->MOS9tPhi-model->MOS9phi); |
|||
here->MOS9tVto = here->MOS9tVbi + model->MOS9type * |
|||
model->MOS9gamma * sqrt(here->MOS9tPhi); |
|||
here->MOS9tSatCur = model->MOS9jctSatCur* |
|||
exp(-egfet/vt+egfet1/vtnom); |
|||
here->MOS9tSatCurDens = model->MOS9jctSatCurDensity * |
|||
exp(-egfet/vt+egfet1/vtnom); |
|||
pbo = (model->MOS9bulkJctPotential - pbfact1)/fact1; |
|||
gmaold = (model->MOS9bulkJctPotential-pbo)/pbo; |
|||
capfact = 1/(1+model->MOS9bulkJctBotGradingCoeff* |
|||
(4e-4*(model->MOS9tnom-REFTEMP)-gmaold)); |
|||
here->MOS9tCbd = model->MOS9capBD * capfact; |
|||
here->MOS9tCbs = model->MOS9capBS * capfact; |
|||
here->MOS9tCj = model->MOS9bulkCapFactor * capfact; |
|||
capfact = 1/(1+model->MOS9bulkJctSideGradingCoeff* |
|||
(4e-4*(model->MOS9tnom-REFTEMP)-gmaold)); |
|||
here->MOS9tCjsw = model->MOS9sideWallCapFactor * capfact; |
|||
here->MOS9tBulkPot = fact2 * pbo+pbfact; |
|||
gmanew = (here->MOS9tBulkPot-pbo)/pbo; |
|||
capfact = (1+model->MOS9bulkJctBotGradingCoeff* |
|||
(4e-4*(here->MOS9temp-REFTEMP)-gmanew)); |
|||
here->MOS9tCbd *= capfact; |
|||
here->MOS9tCbs *= capfact; |
|||
here->MOS9tCj *= capfact; |
|||
capfact = (1+model->MOS9bulkJctSideGradingCoeff* |
|||
(4e-4*(here->MOS9temp-REFTEMP)-gmanew)); |
|||
here->MOS9tCjsw *= capfact; |
|||
here->MOS9tDepCap = model->MOS9fwdCapDepCoeff * here->MOS9tBulkPot; |
|||
|
|||
if( (model->MOS9jctSatCurDensity == 0) || |
|||
(here->MOS9drainArea == 0) || |
|||
(here->MOS9sourceArea == 0) ) { |
|||
here->MOS9sourceVcrit = here->MOS9drainVcrit = |
|||
vt*log(vt/(CONSTroot2*here->MOS9m*here->MOS9tSatCur)); |
|||
} else { |
|||
here->MOS9drainVcrit = |
|||
vt * log( vt / (CONSTroot2 * |
|||
here->MOS9m * |
|||
here->MOS9tSatCurDens * here->MOS9drainArea)); |
|||
here->MOS9sourceVcrit = |
|||
vt * log( vt / (CONSTroot2 * |
|||
here->MOS9m * |
|||
here->MOS9tSatCurDens * here->MOS9sourceArea)); |
|||
} |
|||
if(model->MOS9capBDGiven) { |
|||
czbd = here->MOS9tCbd * here->MOS9m; |
|||
} else { |
|||
if(model->MOS9bulkCapFactorGiven) { |
|||
czbd=here->MOS9tCj*here->MOS9drainArea * here->MOS9m; |
|||
} else { |
|||
czbd=0; |
|||
} |
|||
} |
|||
if(model->MOS9sideWallCapFactorGiven) { |
|||
czbdsw= here->MOS9tCjsw * here->MOS9drainPerimiter * |
|||
here->MOS9m; |
|||
} else { |
|||
czbdsw=0; |
|||
} |
|||
arg = 1-model->MOS9fwdCapDepCoeff; |
|||
sarg = exp( (-model->MOS9bulkJctBotGradingCoeff) * log(arg) ); |
|||
sargsw = exp( (-model->MOS9bulkJctSideGradingCoeff) * log(arg) ); |
|||
here->MOS9Cbd = czbd; |
|||
here->MOS9Cbdsw = czbdsw; |
|||
here->MOS9f2d = czbd*(1-model->MOS9fwdCapDepCoeff* |
|||
(1+model->MOS9bulkJctBotGradingCoeff))* sarg/arg |
|||
+ czbdsw*(1-model->MOS9fwdCapDepCoeff* |
|||
(1+model->MOS9bulkJctSideGradingCoeff))* |
|||
sargsw/arg; |
|||
here->MOS9f3d = czbd * model->MOS9bulkJctBotGradingCoeff * sarg/arg/ |
|||
here->MOS9tBulkPot |
|||
+ czbdsw * model->MOS9bulkJctSideGradingCoeff * sargsw/arg / |
|||
here->MOS9tBulkPot;
|
|||
here->MOS9f4d = czbd*here->MOS9tBulkPot*(1-arg*sarg)/ |
|||
(1-model->MOS9bulkJctBotGradingCoeff) |
|||
+ czbdsw*here->MOS9tBulkPot*(1-arg*sargsw)/ |
|||
(1-model->MOS9bulkJctSideGradingCoeff) |
|||
-here->MOS9f3d/2* |
|||
(here->MOS9tDepCap*here->MOS9tDepCap) |
|||
-here->MOS9tDepCap * here->MOS9f2d; |
|||
if(model->MOS9capBSGiven) { |
|||
czbs = here->MOS9tCbs * here->MOS9m; |
|||
} else { |
|||
if(model->MOS9bulkCapFactorGiven) { |
|||
czbs=here->MOS9tCj*here->MOS9sourceArea * here->MOS9m; |
|||
} else { |
|||
czbs=0; |
|||
} |
|||
} |
|||
if(model->MOS9sideWallCapFactorGiven) { |
|||
czbssw = here->MOS9tCjsw * here->MOS9sourcePerimiter * |
|||
here->MOS9m; |
|||
} else { |
|||
czbssw=0; |
|||
} |
|||
arg = 1-model->MOS9fwdCapDepCoeff; |
|||
sarg = exp( (-model->MOS9bulkJctBotGradingCoeff) * log(arg) ); |
|||
sargsw = exp( (-model->MOS9bulkJctSideGradingCoeff) * log(arg) ); |
|||
here->MOS9Cbs = czbs; |
|||
here->MOS9Cbssw = czbssw; |
|||
here->MOS9f2s = czbs*(1-model->MOS9fwdCapDepCoeff* |
|||
(1+model->MOS9bulkJctBotGradingCoeff))* sarg/arg |
|||
+ czbssw*(1-model->MOS9fwdCapDepCoeff* |
|||
(1+model->MOS9bulkJctSideGradingCoeff))* |
|||
sargsw/arg; |
|||
here->MOS9f3s = czbs * model->MOS9bulkJctBotGradingCoeff * sarg/arg/ |
|||
here->MOS9tBulkPot |
|||
+ czbssw * model->MOS9bulkJctSideGradingCoeff * sargsw/arg / |
|||
here->MOS9tBulkPot; |
|||
here->MOS9f4s = czbs*here->MOS9tBulkPot*(1-arg*sarg)/ |
|||
(1-model->MOS9bulkJctBotGradingCoeff) |
|||
+ czbssw*here->MOS9tBulkPot*(1-arg*sargsw)/ |
|||
(1-model->MOS9bulkJctSideGradingCoeff) |
|||
-here->MOS9f3s/2* |
|||
(here->MOS9tDepCap*here->MOS9tDepCap) |
|||
-here->MOS9tDepCap * here->MOS9f2s; |
|||
} |
|||
} |
|||
return(OK); |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
/********** |
|||
Copyright 1990 Regents of the University of California. All rights reserved. |
|||
Author: 1985 Thomas L. Quarles |
|||
Modified: Alan Gillespie |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "cktdefs.h" |
|||
#include "mos9defs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
int |
|||
MOS9trunc(inModel,ckt,timeStep) |
|||
GENmodel *inModel; |
|||
CKTcircuit *ckt; |
|||
double *timeStep; |
|||
{ |
|||
MOS9model *model = (MOS9model *)inModel; |
|||
MOS9instance *here; |
|||
|
|||
for( ; model != NULL; model = model->MOS9nextModel) { |
|||
for(here=model->MOS9instances;here!=NULL;here = here->MOS9nextInstance){ |
|||
CKTterr(here->MOS9qgs,ckt,timeStep); |
|||
CKTterr(here->MOS9qgd,ckt,timeStep); |
|||
CKTterr(here->MOS9qgb,ckt,timeStep); |
|||
} |
|||
} |
|||
return(OK); |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue