Imported mo9 (mos3 modified by Alan Gillespie)
This commit is contained in:
parent
e515e01ede
commit
dba228e7dc
|
|
@ -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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||
}
|
||||
Loading…
Reference in New Issue