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.
 
 
 
 
 
 

338 lines
12 KiB

/**********
Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
Modified: 2000 AlansFixes
**********/
/* load the VDMOS device structure with those pointers needed later
* for fast matrix loading
*/
#include "ngspice/ngspice.h"
#include "ngspice/smpdefs.h"
#include "ngspice/cktdefs.h"
#include "vdmosdefs.h"
#include "ngspice/sperror.h"
#include "ngspice/suffix.h"
int
VDMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
int *states)
{
VDMOSmodel *model = (VDMOSmodel *)inModel;
VDMOSinstance *here;
int error;
CKTnode *tmp;
/* loop through all the VDMOS device models */
for (; model != NULL; model = VDMOSnextModel(model)) {
if (!model->VDMOStypeGiven) {
model->VDMOStype = NMOS;
}
if (!model->VDIOjctSatCurGiven) {
model->VDIOjctSatCur = 1e-14;
}
if (!model->VDMOStransconductanceGiven) {
model->VDMOStransconductance = 1;
}
if (!model->VDMOSvt0Given) {
model->VDMOSvt0 = 0;
}
if (!model->VDIOjunctionPotGiven) {
model->VDIOjunctionPot = .8;
}
if (!model->VDIOgradCoeffGiven) {
model->VDIOgradCoeff = .5;
}
if (!model->VDIOdepletionCapCoeffGiven) {
model->VDIOdepletionCapCoeff = .5;
}
if (!model->VDMOSphiGiven) {
model->VDMOSphi = .6;
}
if (!model->VDMOSlambdaGiven) {
model->VDMOSlambda = 0;
}
if (!model->VDMOSfNcoefGiven) {
model->VDMOSfNcoef = 0;
}
if (!model->VDMOSfNexpGiven) {
model->VDMOSfNexp = 1;
}
if (!model->VDMOScgdminGiven) {
model->VDMOScgdmin = 0;
}
if (!model->VDMOScgdmaxGiven) {
model->VDMOScgdmax = 0;
}
if (!model->VDMOScgsGiven) {
model->VDMOScgs = 0;
}
if (!model->VDMOSaGiven) {
model->VDMOSa = 1.;
}
if (!model->VDMOSsubslGiven) {
model->VDMOSsubsl = 0;
}
if (!model->VDMOSsubshiftGiven) {
model->VDMOSsubshift = 0;
}
if (!model->VDMOSmtrGiven) {
model->VDMOSmtr = 1.;
}
if (!model->VDMOSDbvGiven) {
model->VDMOSDbv = 1.0e30;
}
if (!model->VDMOSDibvGiven) {
model->VDMOSDibv = 1.0e-10;
}
if (!model->VDIObrkdEmissionCoeffGiven) {
model->VDIObrkdEmissionCoeff = 1.;
}
if (!model->VDMOSrdsGiven) {
model->VDMOSrds = 1.0e30;
}
if (!model->VDMOSDnGiven) {
model->VDMOSDn = 1.;
}
if (!model->VDIOtransitTimeGiven) {
model->VDIOtransitTime = 0.;
}
if (!model->VDMOSDegGiven) {
model->VDMOSDeg = 1.11;
}
/* loop through all the instances of the model */
for (here = VDMOSinstances(model); here != NULL;
here = VDMOSnextInstance(here)) {
/* Check if source and bulk nodes are the same.
* The power MOS devices in fact are 3-terminal devices,
* but the actual device input still uses 4 terminals to be compatible.
*/
if (here->VDMOSbNode != here->VDMOSsNode) {
fprintf(stderr, "\nError: source and bulk nodes of device %s have to be the same!\n",
here->VDMOSname);
controlled_exit(1);
}
/* allocate a chunk of the state vector */
here->VDMOSstates = *states;
*states += VDMOSnumStates;
if (!here->VDMOSicVBSGiven) {
here->VDMOSicVBS = 0;
}
if (!here->VDMOSicVDSGiven) {
here->VDMOSicVDS = 0;
}
if (!here->VDMOSicVGSGiven) {
here->VDMOSicVGS = 0;
}
if (!here->VDMOSvdsatGiven) {
here->VDMOSvdsat = 0;
}
if (!here->VDMOSvonGiven) {
here->VDMOSvon = 0;
}
if (model->VDMOSdrainResistance != 0) {
if (here->VDMOSdNodePrime == 0) {
error = CKTmkVolt(ckt, &tmp, here->VDMOSname, "drain");
if (error) return(error);
here->VDMOSdNodePrime = tmp->number;
if (ckt->CKTcopyNodesets) {
CKTnode *tmpNode;
IFuid tmpName;
if (CKTinst2Node(ckt, here, 1, &tmpNode, &tmpName) == OK) {
if (tmpNode->nsGiven) {
tmp->nodeset = tmpNode->nodeset;
tmp->nsGiven = tmpNode->nsGiven;
}
}
}
}
}
else {
here->VDMOSdNodePrime = here->VDMOSdNode;
}
if (model->VDMOSsourceResistance != 0) {
if (here->VDMOSsNodePrime == 0) {
error = CKTmkVolt(ckt, &tmp, here->VDMOSname, "source");
if (error) return(error);
here->VDMOSsNodePrime = tmp->number;
if (ckt->CKTcopyNodesets) {
CKTnode *tmpNode;
IFuid tmpName;
if (CKTinst2Node(ckt, here, 3, &tmpNode, &tmpName) == OK) {
if (tmpNode->nsGiven) {
tmp->nodeset = tmpNode->nodeset;
tmp->nsGiven = tmpNode->nsGiven;
}
}
}
}
}
else {
here->VDMOSsNodePrime = here->VDMOSsNode;
}
if (model->VDMOSgateResistance != 0 ) {
if (here->VDMOSgNodePrime == 0) {
error = CKTmkVolt(ckt, &tmp, here->VDMOSname, "gate");
if (error) return(error);
here->VDMOSgNodePrime = tmp->number;
if (ckt->CKTcopyNodesets) {
CKTnode *tmpNode;
IFuid tmpName;
if (CKTinst2Node(ckt, here, 3, &tmpNode, &tmpName) == OK) {
if (tmpNode->nsGiven) {
tmp->nodeset = tmpNode->nodeset;
tmp->nsGiven = tmpNode->nsGiven;
}
}
}
}
}
else {
here->VDMOSgNodePrime = here->VDMOSgNode;
}
if (model->VDIOresistance != 0 ) {
if (here->VDIOposPrimeNode == 0) {
error = CKTmkVolt(ckt, &tmp, here->VDMOSname, "bulk diode");
if (error) return(error);
here->VDIOposPrimeNode = tmp->number;
if (ckt->CKTcopyNodesets) {
CKTnode *tmpNode;
IFuid tmpName;
if (CKTinst2Node(ckt, here, 3, &tmpNode, &tmpName) == OK) {
if (tmpNode->nsGiven) {
tmp->nodeset = tmpNode->nodeset;
tmp->nsGiven = tmpNode->nsGiven;
}
}
}
}
}
else {
here->VDIOposPrimeNode = here->VDMOSsNode;
}
/* 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(VDMOSDdPtr, VDMOSdNode, VDMOSdNode);
TSTALLOC(VDMOSGgPtr, VDMOSgNode, VDMOSgNode);
TSTALLOC(VDMOSSsPtr, VDMOSsNode, VDMOSsNode);
TSTALLOC(VDMOSBbPtr, VDMOSbNode, VDMOSbNode);
TSTALLOC(VDMOSDPdpPtr, VDMOSdNodePrime, VDMOSdNodePrime);
TSTALLOC(VDMOSSPspPtr, VDMOSsNodePrime, VDMOSsNodePrime);
TSTALLOC(VDMOSDdpPtr, VDMOSdNode, VDMOSdNodePrime);
TSTALLOC(VDMOSGbPtr, VDMOSgNode, VDMOSbNode);
TSTALLOC(VDMOSGdpPtr, VDMOSgNode, VDMOSdNodePrime);
TSTALLOC(VDMOSGspPtr, VDMOSgNode, VDMOSsNodePrime);
TSTALLOC(VDMOSSspPtr, VDMOSsNode, VDMOSsNodePrime);
TSTALLOC(VDMOSBdpPtr, VDMOSbNode, VDMOSdNodePrime);
TSTALLOC(VDMOSBspPtr, VDMOSbNode, VDMOSsNodePrime);
TSTALLOC(VDMOSDPspPtr, VDMOSdNodePrime, VDMOSsNodePrime);
TSTALLOC(VDMOSDPdPtr, VDMOSdNodePrime, VDMOSdNode);
TSTALLOC(VDMOSBgPtr, VDMOSbNode, VDMOSgNode);
TSTALLOC(VDMOSDPgPtr, VDMOSdNodePrime, VDMOSgNode);
TSTALLOC(VDMOSSPgPtr, VDMOSsNodePrime, VDMOSgNode);
TSTALLOC(VDMOSSPsPtr, VDMOSsNodePrime, VDMOSsNode);
TSTALLOC(VDMOSDPbPtr, VDMOSdNodePrime, VDMOSbNode);
TSTALLOC(VDMOSSPbPtr, VDMOSsNodePrime, VDMOSbNode);
TSTALLOC(VDMOSSPdpPtr, VDMOSsNodePrime, VDMOSdNodePrime);
*/
TSTALLOC(VDMOSDdPtr, VDMOSdNode, VDMOSdNode);
TSTALLOC(VDMOSGgPtr, VDMOSgNode, VDMOSgNode);
TSTALLOC(VDMOSSsPtr, VDMOSsNode, VDMOSsNode);
TSTALLOC(VDMOSBbPtr, VDMOSbNode, VDMOSbNode);
TSTALLOC(VDMOSDPdpPtr, VDMOSdNodePrime, VDMOSdNodePrime);
TSTALLOC(VDMOSSPspPtr, VDMOSsNodePrime, VDMOSsNodePrime);
TSTALLOC(VDMOSGPgpPtr, VDMOSgNodePrime, VDMOSgNodePrime);
TSTALLOC(VDMOSDdpPtr, VDMOSdNode, VDMOSdNodePrime);
TSTALLOC(VDMOSGPbPtr, VDMOSgNodePrime, VDMOSbNode);
TSTALLOC(VDMOSGPdpPtr, VDMOSgNodePrime, VDMOSdNodePrime);
TSTALLOC(VDMOSGPspPtr, VDMOSgNodePrime, VDMOSsNodePrime);
TSTALLOC(VDMOSSspPtr, VDMOSsNode, VDMOSsNodePrime);
TSTALLOC(VDMOSBdpPtr, VDMOSbNode, VDMOSdNodePrime);
TSTALLOC(VDMOSBspPtr, VDMOSbNode, VDMOSsNodePrime);
TSTALLOC(VDMOSDPspPtr, VDMOSdNodePrime, VDMOSsNodePrime);
TSTALLOC(VDMOSDPdPtr, VDMOSdNodePrime, VDMOSdNode);
TSTALLOC(VDMOSBgpPtr, VDMOSbNode, VDMOSgNodePrime);
TSTALLOC(VDMOSDPgpPtr, VDMOSdNodePrime, VDMOSgNodePrime);
TSTALLOC(VDMOSSPgpPtr, VDMOSsNodePrime, VDMOSgNodePrime);
TSTALLOC(VDMOSSPsPtr, VDMOSsNodePrime, VDMOSsNode);
TSTALLOC(VDMOSDPbPtr, VDMOSdNodePrime, VDMOSbNode);
TSTALLOC(VDMOSSPbPtr, VDMOSsNodePrime, VDMOSbNode);
TSTALLOC(VDMOSSPdpPtr, VDMOSsNodePrime, VDMOSdNodePrime);
TSTALLOC(VDMOSGgpPtr, VDMOSgNode, VDMOSgNodePrime);
TSTALLOC(VDMOSGPgPtr, VDMOSgNodePrime, VDMOSgNode);
TSTALLOC(VDMOSDsPtr, VDMOSdNode, VDMOSsNode);
TSTALLOC(VDMOSSdPtr, VDMOSsNode, VDMOSdNode);
TSTALLOC(VDIORPdPtr, VDIOposPrimeNode, VDMOSdNode);
TSTALLOC(VDIODrpPtr, VDMOSdNode, VDIOposPrimeNode);
TSTALLOC(VDIOSrpPtr, VDMOSsNode, VDIOposPrimeNode);
TSTALLOC(VDIORPsPtr, VDIOposPrimeNode, VDMOSsNode);
TSTALLOC(VDIORPrpPtr, VDIOposPrimeNode, VDIOposPrimeNode);
}
}
return(OK);
}
int
VDMOSunsetup(GENmodel *inModel, CKTcircuit *ckt)
{
VDMOSmodel *model;
VDMOSinstance *here;
for (model = (VDMOSmodel *)inModel; model != NULL;
model = VDMOSnextModel(model))
{
for (here = VDMOSinstances(model); here != NULL;
here = VDMOSnextInstance(here))
{
if (here->VDMOSsNodePrime > 0
&& here->VDMOSsNodePrime != here->VDMOSsNode)
CKTdltNNum(ckt, here->VDMOSsNodePrime);
here->VDMOSsNodePrime = 0;
if (here->VDMOSdNodePrime > 0
&& here->VDMOSdNodePrime != here->VDMOSdNode)
CKTdltNNum(ckt, here->VDMOSdNodePrime);
here->VDMOSdNodePrime = 0;
if (here->VDMOSgNodePrime > 0
&& here->VDMOSgNodePrime != here->VDMOSgNode)
CKTdltNNum(ckt, here->VDMOSgNodePrime);
here->VDMOSgNodePrime = 0;
if (here->VDIOposPrimeNode > 0
&& here->VDIOposPrimeNode != here->VDMOSsNode)
CKTdltNNum(ckt, here->VDIOposPrimeNode);
here->VDIOposPrimeNode = 0;
}
}
return OK;
}