ngspice/src/spicelib/devices/mos2/mos2set.c

249 lines
7.8 KiB
C

/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
#include "ngspice.h"
#include <stdio.h>
#include "smpdefs.h"
#include "const.h"
#include "cktdefs.h"
#include "mos2defs.h"
#include "sperror.h"
#include "suffix.h"
int
MOS2setup(matrix,inModel,ckt,states)
register SMPmatrix *matrix;
GENmodel *inModel;
register CKTcircuit *ckt;
int *states;
/* load the MOS2 device structure with those pointers needed later
* for fast matrix loading
*/
{
register MOS2model *model = (MOS2model *)inModel;
register MOS2instance *here;
int error;
CKTnode *tmp;
/* loop through all the MOS2 device models */
for( ; model != NULL; model = model->MOS2nextModel ) {
if(!model->MOS2typeGiven) {
model->MOS2type = NMOS;
}
if(!model->MOS2latDiffGiven) {
model->MOS2latDiff = 0;
}
if(!model->MOS2jctSatCurDensityGiven) {
model->MOS2jctSatCurDensity = 0;
}
if(!model->MOS2jctSatCurGiven) {
model->MOS2jctSatCur = 1e-14;
}
if(!model->MOS2drainResistanceGiven) {
model->MOS2drainResistance = 0;
}
if(!model->MOS2sourceResistanceGiven) {
model->MOS2sourceResistance = 0;
}
if(!model->MOS2sheetResistanceGiven) {
model->MOS2sheetResistance = 0;
}
if(!model->MOS2gateSourceOverlapCapFactorGiven) {
model->MOS2gateSourceOverlapCapFactor = 0;
}
if(!model->MOS2gateDrainOverlapCapFactorGiven) {
model->MOS2gateDrainOverlapCapFactor = 0;
}
if(!model->MOS2gateBulkOverlapCapFactorGiven) {
model->MOS2gateBulkOverlapCapFactor = 0;
}
if(!model->MOS2vt0Given) {
model->MOS2vt0 = 0;
}
if(!model->MOS2bulkJctPotentialGiven) {
model->MOS2bulkJctPotential = .8;
}
if(!model->MOS2capBDGiven) {
model->MOS2capBD = 0;
}
if(!model->MOS2capBSGiven) {
model->MOS2capBS = 0;
}
if(!model->MOS2sideWallCapFactorGiven) {
model->MOS2sideWallCapFactor = 0;
}
if(!model->MOS2bulkJctBotGradingCoeffGiven) {
model->MOS2bulkJctBotGradingCoeff = .5;
}
if(!model->MOS2bulkJctSideGradingCoeffGiven) {
model->MOS2bulkJctSideGradingCoeff = .33;
}
if(!model->MOS2fwdCapDepCoeffGiven) {
model->MOS2fwdCapDepCoeff = .5;
}
if(!model->MOS2phiGiven) {
model->MOS2phi = .6;
}
if(!model->MOS2lambdaGiven) {
model->MOS2lambda = 0;
}
if(!model->MOS2gammaGiven) {
model->MOS2gamma = 0;
}
if(!model->MOS2narrowFactorGiven) {
model->MOS2narrowFactor = 0;
}
if(!model->MOS2critFieldExpGiven) {
model->MOS2critFieldExp = 0;
}
if(!model->MOS2critFieldGiven) {
model->MOS2critField = 1e4;
}
if(!model->MOS2maxDriftVelGiven) {
model->MOS2maxDriftVel = 0;
}
if(!model->MOS2junctionDepthGiven) {
model->MOS2junctionDepth = 0;
}
if(!model->MOS2channelChargeGiven) {
model->MOS2channelCharge = 1;
}
if(!model->MOS2fastSurfaceStateDensityGiven) {
model->MOS2fastSurfaceStateDensity = 0;
}
if(!model->MOS2fNcoefGiven) {
model->MOS2fNcoef = 0;
}
if(!model->MOS2fNexpGiven) {
model->MOS2fNexp = 1;
}
/* loop through all the instances of the model */
for (here = model->MOS2instances; here != NULL ;
here=here->MOS2nextInstance) {
if (here->MOS2owner == ARCHme) {
/* allocate a chunk of the state vector */
here->MOS2states = *states;
*states += MOS2numStates;
if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN) ){
*states += 10 * (ckt->CKTsenInfo->SENparms);
}
}
if(!here->MOS2drainPerimiterGiven) {
here->MOS2drainPerimiter = 0;
}
if(!here->MOS2icVBSGiven) {
here->MOS2icVBS = 0;
}
if(!here->MOS2icVDSGiven) {
here->MOS2icVDS = 0;
}
if(!here->MOS2icVGSGiven) {
here->MOS2icVGS = 0;
}
if(!here->MOS2sourcePerimiterGiven) {
here->MOS2sourcePerimiter = 0;
}
if(!here->MOS2vdsatGiven) {
here->MOS2vdsat = 0;
}
if (!here->MOS2drainSquaresGiven) {
here->MOS2drainSquares=1;
}
if (!here->MOS2sourceSquaresGiven) {
here->MOS2sourceSquares=1;
}
if ((model->MOS2drainResistance != 0
|| (here->MOS2drainSquares != 0
&& model->MOS2sheetResistance != 0))
&& here->MOS2dNodePrime==0) {
error = CKTmkVolt(ckt,&tmp,here->MOS2name,"internal#drain");
if(error) return(error);
here->MOS2dNodePrime = tmp->number;
} else {
here->MOS2dNodePrime = here->MOS2dNode;
}
if( ( (model->MOS2sourceResistance != 0) ||
((here->MOS2sourceSquares != 0) &&
(model->MOS2sheetResistance != 0)) ) &&
(here->MOS2sNodePrime==0) ) {
error = CKTmkVolt(ckt,&tmp,here->MOS2name,"internal#source");
if(error) return(error);
here->MOS2sNodePrime = tmp->number;
} else {
here->MOS2sNodePrime = here->MOS2sNode;
}
/* 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(MOS2DdPtr, MOS2dNode, MOS2dNode)
TSTALLOC(MOS2GgPtr, MOS2gNode, MOS2gNode)
TSTALLOC(MOS2SsPtr, MOS2sNode, MOS2sNode)
TSTALLOC(MOS2BbPtr, MOS2bNode, MOS2bNode)
TSTALLOC(MOS2DPdpPtr, MOS2dNodePrime, MOS2dNodePrime)
TSTALLOC(MOS2SPspPtr, MOS2sNodePrime, MOS2sNodePrime)
TSTALLOC(MOS2DdpPtr, MOS2dNode, MOS2dNodePrime)
TSTALLOC(MOS2GbPtr, MOS2gNode, MOS2bNode)
TSTALLOC(MOS2GdpPtr, MOS2gNode, MOS2dNodePrime)
TSTALLOC(MOS2GspPtr, MOS2gNode, MOS2sNodePrime)
TSTALLOC(MOS2SspPtr, MOS2sNode, MOS2sNodePrime)
TSTALLOC(MOS2BdpPtr, MOS2bNode, MOS2dNodePrime)
TSTALLOC(MOS2BspPtr, MOS2bNode, MOS2sNodePrime)
TSTALLOC(MOS2DPspPtr, MOS2dNodePrime, MOS2sNodePrime)
TSTALLOC(MOS2DPdPtr, MOS2dNodePrime, MOS2dNode)
TSTALLOC(MOS2BgPtr, MOS2bNode, MOS2gNode)
TSTALLOC(MOS2DPgPtr, MOS2dNodePrime, MOS2gNode)
TSTALLOC(MOS2SPgPtr, MOS2sNodePrime, MOS2gNode)
TSTALLOC(MOS2SPsPtr, MOS2sNodePrime, MOS2sNode)
TSTALLOC(MOS2DPbPtr, MOS2dNodePrime, MOS2bNode)
TSTALLOC(MOS2SPbPtr, MOS2sNodePrime, MOS2bNode)
TSTALLOC(MOS2SPdpPtr, MOS2sNodePrime, MOS2dNodePrime)
}
}
return(OK);
}
int
MOS2unsetup(inModel,ckt)
GENmodel *inModel;
CKTcircuit *ckt;
{
#ifndef HAS_BATCHSIM
MOS2model *model;
MOS2instance *here;
for (model = (MOS2model *)inModel; model != NULL;
model = model->MOS2nextModel)
{
for (here = model->MOS2instances; here != NULL;
here=here->MOS2nextInstance)
{
if (here->MOS2sNodePrime
&& here->MOS2sNodePrime != here->MOS2sNode)
{
CKTdltNNum(ckt, here->MOS2sNodePrime);
here->MOS2sNodePrime = 0;
}
if (here->MOS2dNodePrime
&& here->MOS2dNodePrime != here->MOS2dNode)
{
CKTdltNNum(ckt, here->MOS2dNodePrime);
here->MOS2dNodePrime = 0;
}
}
}
#endif
return OK;
}