You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

289 lines
9.4 KiB

/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarlesù
Modified: 2000 AlansFixes
**********/
#include "ngspice/ngspice.h"
#include "ngspice/smpdefs.h"
#include "ngspice/cktdefs.h"
#include "mos3defs.h"
#include "ngspice/const.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
/* assuming silicon - make definition for epsilon of silicon */
#define EPSSIL (11.7 * 8.854214871e-12)
int
MOS3setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
/* load the MOS3 device structure with those pointers needed later
* for fast matrix loading
*/
{
MOS3model *model = (MOS3model *)inModel;
MOS3instance *here;
int error;
CKTnode *tmp;
/* loop through all the MOS3 device models */
for( ; model != NULL; model = model->MOS3nextModel ) {
/* perform model defaulting */
if(!model->MOS3typeGiven) {
model->MOS3type = NMOS;
}
if(!model->MOS3latDiffGiven) {
model->MOS3latDiff = 0;
}
if(!model->MOS3lengthAdjustGiven) {
model->MOS3lengthAdjust = 0;
}
if(!model->MOS3widthNarrowGiven) {
model->MOS3widthNarrow = 0;
}
if(!model->MOS3widthAdjustGiven) {
model->MOS3widthAdjust = 0;
}
if(!model->MOS3delvt0Given) {
model->MOS3delvt0 = 0;
}
if(!model->MOS3jctSatCurDensityGiven) {
model->MOS3jctSatCurDensity = 0;
}
if(!model->MOS3jctSatCurGiven) {
model->MOS3jctSatCur = 1e-14;
}
if(!model->MOS3drainResistanceGiven) {
model->MOS3drainResistance = 0;
}
if(!model->MOS3sourceResistanceGiven) {
model->MOS3sourceResistance = 0;
}
if(!model->MOS3sheetResistanceGiven) {
model->MOS3sheetResistance = 0;
}
if(!model->MOS3transconductanceGiven) {
model->MOS3transconductance = 2e-5;
}
if(!model->MOS3gateSourceOverlapCapFactorGiven) {
model->MOS3gateSourceOverlapCapFactor = 0;
}
if(!model->MOS3gateDrainOverlapCapFactorGiven) {
model->MOS3gateDrainOverlapCapFactor = 0;
}
if(!model->MOS3gateBulkOverlapCapFactorGiven) {
model->MOS3gateBulkOverlapCapFactor = 0;
}
if(!model->MOS3vt0Given) {
model->MOS3vt0 = 0;
}
if(!model->MOS3capBDGiven) {
model->MOS3capBD = 0;
}
if(!model->MOS3capBSGiven) {
model->MOS3capBS = 0;
}
if(!model->MOS3bulkCapFactorGiven) {
model->MOS3bulkCapFactor = 0;
}
if(!model->MOS3sideWallCapFactorGiven) {
model->MOS3sideWallCapFactor = 0;
}
if(!model->MOS3bulkJctPotentialGiven) {
model->MOS3bulkJctPotential = .8;
}
if(!model->MOS3bulkJctBotGradingCoeffGiven) {
model->MOS3bulkJctBotGradingCoeff = .5;
}
if(!model->MOS3bulkJctSideGradingCoeffGiven) {
model->MOS3bulkJctSideGradingCoeff = .33;
}
if(!model->MOS3fwdCapDepCoeffGiven) {
model->MOS3fwdCapDepCoeff = .5;
}
if(!model->MOS3phiGiven) {
model->MOS3phi = .6;
}
if(!model->MOS3gammaGiven) {
model->MOS3gamma = 0;
}
if(!model->MOS3deltaGiven) {
model->MOS3delta = 0;
}
if(!model->MOS3maxDriftVelGiven) {
model->MOS3maxDriftVel = 0;
}
if(!model->MOS3junctionDepthGiven) {
model->MOS3junctionDepth = 0;
}
if(!model->MOS3fastSurfaceStateDensityGiven) {
model->MOS3fastSurfaceStateDensity = 0;
}
if(!model->MOS3etaGiven) {
model->MOS3eta = 0;
}
if(!model->MOS3thetaGiven) {
model->MOS3theta = 0;
}
if(!model->MOS3kappaGiven) {
model->MOS3kappa = .2;
}
if(!model->MOS3oxideThicknessGiven) {
model->MOS3oxideThickness = 1e-7;
}
if(!model->MOS3fNcoefGiven) {
model->MOS3fNcoef = 0;
}
if(!model->MOS3fNexpGiven) {
model->MOS3fNexp = 1;
}
/* loop through all the instances of the model */
for (here = model->MOS3instances; here != NULL ;
here=here->MOS3nextInstance) {
CKTnode *tmpNode;
IFuid tmpName;
/* allocate a chunk of the state vector */
here->MOS3states = *states;
*states += MOS3NUMSTATES;
if(!here->MOS3drainAreaGiven) {
here->MOS3drainArea = ckt->CKTdefaultMosAD;
}
if(!here->MOS3drainPerimiterGiven) {
here->MOS3drainPerimiter = 0;
}
if(!here->MOS3drainSquaresGiven) {
here->MOS3drainSquares = 1;
}
if(!here->MOS3icVBSGiven) {
here->MOS3icVBS = 0;
}
if(!here->MOS3icVDSGiven) {
here->MOS3icVDS = 0;
}
if(!here->MOS3icVGSGiven) {
here->MOS3icVGS = 0;
}
if(!here->MOS3sourcePerimiterGiven) {
here->MOS3sourcePerimiter = 0;
}
if(!here->MOS3sourceSquaresGiven) {
here->MOS3sourceSquares = 1;
}
if(!here->MOS3vdsatGiven) {
here->MOS3vdsat = 0;
}
if(!here->MOS3vonGiven) {
here->MOS3von = 0;
}
if(!here->MOS3modeGiven) {
here->MOS3mode = 1;
}
if((model->MOS3drainResistance != 0 ||
(model->MOS3sheetResistance != 0 &&
here->MOS3drainSquares != 0 ) )) {
if (here->MOS3dNodePrime == 0) {
error = CKTmkVolt(ckt,&tmp,here->MOS3name,"internal#drain");
if(error) return(error);
here->MOS3dNodePrime = 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->MOS3dNodePrime = here->MOS3dNode;
}
if((model->MOS3sourceResistance != 0 ||
(model->MOS3sheetResistance != 0 &&
here->MOS3sourceSquares != 0 ) )) {
if (here->MOS3sNodePrime == 0) {
error = CKTmkVolt(ckt,&tmp,here->MOS3name,"internal#source");
if(error) return(error);
here->MOS3sNodePrime = 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->MOS3sNodePrime = here->MOS3sNode;
}
/* macro to make elements with built in test for out of memory */
#define TSTALLOC(ptr,first,second) \
do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
return(E_NOMEM);\
} } while(0)
TSTALLOC(MOS3DdPtr, MOS3dNode, MOS3dNode);
TSTALLOC(MOS3GgPtr, MOS3gNode, MOS3gNode);
TSTALLOC(MOS3SsPtr, MOS3sNode, MOS3sNode);
TSTALLOC(MOS3BbPtr, MOS3bNode, MOS3bNode);
TSTALLOC(MOS3DPdpPtr, MOS3dNodePrime, MOS3dNodePrime);
TSTALLOC(MOS3SPspPtr, MOS3sNodePrime, MOS3sNodePrime);
TSTALLOC(MOS3DdpPtr, MOS3dNode, MOS3dNodePrime);
TSTALLOC(MOS3GbPtr, MOS3gNode, MOS3bNode);
TSTALLOC(MOS3GdpPtr, MOS3gNode, MOS3dNodePrime);
TSTALLOC(MOS3GspPtr, MOS3gNode, MOS3sNodePrime);
TSTALLOC(MOS3SspPtr, MOS3sNode, MOS3sNodePrime);
TSTALLOC(MOS3BdpPtr, MOS3bNode, MOS3dNodePrime);
TSTALLOC(MOS3BspPtr, MOS3bNode, MOS3sNodePrime);
TSTALLOC(MOS3DPspPtr, MOS3dNodePrime, MOS3sNodePrime);
TSTALLOC(MOS3DPdPtr, MOS3dNodePrime, MOS3dNode);
TSTALLOC(MOS3BgPtr, MOS3bNode, MOS3gNode);
TSTALLOC(MOS3DPgPtr, MOS3dNodePrime, MOS3gNode);
TSTALLOC(MOS3SPgPtr, MOS3sNodePrime, MOS3gNode);
TSTALLOC(MOS3SPsPtr, MOS3sNodePrime, MOS3sNode);
TSTALLOC(MOS3DPbPtr, MOS3dNodePrime, MOS3bNode);
TSTALLOC(MOS3SPbPtr, MOS3sNodePrime, MOS3bNode);
TSTALLOC(MOS3SPdpPtr, MOS3sNodePrime, MOS3dNodePrime);
}
}
return(OK);
}
int
MOS3unsetup(GENmodel *inModel, CKTcircuit *ckt)
{
MOS3model *model;
MOS3instance *here;
for (model = (MOS3model *)inModel; model != NULL;
model = model->MOS3nextModel)
{
for (here = model->MOS3instances; here != NULL;
here=here->MOS3nextInstance)
{
if (here->MOS3dNodePrime
&& here->MOS3dNodePrime != here->MOS3dNode)
{
CKTdltNNum(ckt, here->MOS3dNodePrime);
here->MOS3dNodePrime= 0;
}
if (here->MOS3sNodePrime
&& here->MOS3sNodePrime != here->MOS3sNode)
{
CKTdltNNum(ckt, here->MOS3sNodePrime);
here->MOS3sNodePrime= 0;
}
}
}
return OK;
}