📄 nummload.c
字号:
/**********Copyright 1991 Regents of the University of California. All rights reserved.Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group**********//* * This is the function called each iteration to evaluate the 2d numerical * MOSFETs in the circuit and load them into the matrix as appropriate */#include "spice.h"#include <stdio.h>#include <math.h>#include "util.h"#include "devdefs.h"#include "cktdefs.h"#include "numosdef.h"#include "trandefs.h"#include "sperror.h"#include "suffix.h"struct mosAdmittances { SPcomplex yIdVdb; SPcomplex yIdVsb; SPcomplex yIdVgb; SPcomplex yIsVdb; SPcomplex yIsVsb; SPcomplex yIsVgb; SPcomplex yIgVdb; SPcomplex yIgVsb; SPcomplex yIgVgb;};/* External Declarations */extern int TWOdcDebug;extern int TWOtranDebug;extern int TWOacDebug;double limitJunctionVoltage();double limitVbe();double limitVce();double limitVgb();void TWOstoreInitialGuess();void NUMOSconductance();void NUMOScurrent();void NUMOSproject();void NUMOSupdate();void NUMOSsetBCs();void TWOequilSolve();void TWObiasSolve();void computeIntegCoeff();void computePredCoeff();void TWOpredict();void TWOsaveState();void TWOresetJacobian();int TWOdeviceConverged(), TWOreadState();intNUMOSload(inModel, ckt) GENmodel *inModel; CKTcircuit *ckt;{ register NUMOSmodel *model = (NUMOSmodel *) inModel; register NUMOSinstance *inst; register TWOdevice *pDevice; double startTime, startTime2, totalTime, totalTime2; double tol; double xfact; double id, is, ig; double ideq, iseq, igeq; double idhat, ishat, ighat; double delVdb, delVsb, delVgb; double vdb, vsb, vgb; struct mosConductances g; int icheck; int icheck1; int i; double deltaNorm[7]; int devConverged; int numDevNonCon; int deviceType; int doInitSolve; int doVoltPred; char *initStateName; /* loop through all the models */ for (; model != NULL; model = model->NUMOSnextModel) { FieldDepMobility = model->NUMOSmodels->MODLfieldDepMobility; TransDepMobility = model->NUMOSmodels->MODLtransDepMobility; SurfaceMobility = model->NUMOSmodels->MODLsurfaceMobility; Srh = model->NUMOSmodels->MODLsrh; Auger = model->NUMOSmodels->MODLauger; AvalancheGen = model->NUMOSmodels->MODLavalancheGen; OneCarrier = model->NUMOSmethods->METHoneCarrier; MobDeriv = model->NUMOSmethods->METHmobDeriv; MaxIterations = model->NUMOSmethods->METHitLim; TWOdcDebug = model->NUMOSoutputs->OUTPdcDebug; TWOtranDebug = model->NUMOSoutputs->OUTPtranDebug; TWOacDebug = model->NUMOSoutputs->OUTPacDebug; deviceType = model->NUMOSoptions->OPTNdeviceType; doVoltPred = model->NUMOSmethods->METHvoltPred; if (ckt->CKTmode & MODEINITPRED) { /* compute normalized deltas and predictor coeff */ if (!(ckt->CKTmode & MODEDCTRANCURVE)) { model->NUMOSpInfo->order = ckt->CKTorder; model->NUMOSpInfo->method = ckt->CKTintegrateMethod; for (i = 0; i <= ckt->CKTmaxOrder; i++) { deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; } computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, model->NUMOSpInfo->intCoeff, deltaNorm); computePredCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, model->NUMOSpInfo->predCoeff, deltaNorm); } } else if (ckt->CKTmode & MODEINITTRAN) { model->NUMOSpInfo->order = ckt->CKTorder; model->NUMOSpInfo->method = ckt->CKTintegrateMethod; for (i = 0; i <= ckt->CKTmaxOrder; i++) { deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm; } computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder, model->NUMOSpInfo->intCoeff, deltaNorm); } /* loop through all the instances of the model */ for (inst = model->NUMOSinstances; inst != NULL; inst = inst->NUMOSnextInstance) { if (inst->NUMOSowner != ARCHme) continue; pDevice = inst->NUMOSpDevice; totalTime = 0.0; startTime = SPfrontEnd->IFseconds(); /* Get Temp.-Dep. Global Parameters */ GLOBgetGlobals(&(inst->NUMOSglobals)); /* * initialization */ pDevice->devStates = ckt->CKTstates; icheck = 1; doInitSolve = FALSE; initStateName = NULL; if (ckt->CKTmode & MODEINITSMSIG) { vdb = *(ckt->CKTstate0 + inst->NUMOSvdb); vsb = *(ckt->CKTstate0 + inst->NUMOSvsb); vgb = *(ckt->CKTstate0 + inst->NUMOSvgb); delVdb = 0.0; delVsb = 0.0; delVgb = 0.0; NUMOSsetBCs(pDevice, vdb, vsb, vgb); } else if (ckt->CKTmode & MODEINITTRAN) { *(ckt->CKTstate0 + inst->NUMOSvdb) = *(ckt->CKTstate1 + inst->NUMOSvdb); *(ckt->CKTstate0 + inst->NUMOSvsb) = *(ckt->CKTstate1 + inst->NUMOSvsb); *(ckt->CKTstate0 + inst->NUMOSvgb) = *(ckt->CKTstate1 + inst->NUMOSvgb); vdb = *(ckt->CKTstate1 + inst->NUMOSvdb); vsb = *(ckt->CKTstate1 + inst->NUMOSvsb); vgb = *(ckt->CKTstate1 + inst->NUMOSvgb); TWOsaveState(pDevice); delVdb = 0.0; delVsb = 0.0; delVgb = 0.0; } else if ((ckt->CKTmode & MODEINITJCT) && (ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) { doInitSolve = TRUE; initStateName = inst->NUMOSicFile; vdb = 0.0; vsb = 0.0; vgb = 0.0; delVdb = vdb; delVsb = vsb; delVgb = vgb; } else if ((ckt->CKTmode & MODEINITJCT) && (inst->NUMOSoff == 0)) { doInitSolve = TRUE; initStateName = inst->NUMOSicFile; if (deviceType == OPTN_BIPOLAR) { /* d,g,s,b => c,b,e,s */ vdb = 0.0; vsb = -inst->NUMOStype * 1.0; vgb = -inst->NUMOStype * (1.0 - 0.6); } else if (deviceType == OPTN_JFET) { vdb = inst->NUMOStype * 0.5; vsb = 0.0; vgb = 0.0; } else { vdb = inst->NUMOStype * 0.5; vsb = 0.0; vgb = inst->NUMOStype * 1.0; } delVdb = vdb; delVsb = vsb; delVgb = vgb; } else if (ckt->CKTmode & MODEINITJCT) { doInitSolve = TRUE; vdb = 0.0; vsb = 0.0; vgb = 0.0; delVdb = vdb; delVsb = vsb; delVgb = vgb; } else if ((ckt->CKTmode & MODEINITFIX) && inst->NUMOSoff) { vdb = 0.0; vsb = 0.0; vgb = 0.0; delVdb = vdb; delVsb = vsb; delVgb = vgb; } else { if (ckt->CKTmode & MODEINITPRED) { *(ckt->CKTstate0 + inst->NUMOSvdb) = *(ckt->CKTstate1 + inst->NUMOSvdb); *(ckt->CKTstate0 + inst->NUMOSvsb) = *(ckt->CKTstate1 + inst->NUMOSvsb); *(ckt->CKTstate0 + inst->NUMOSvgb) = *(ckt->CKTstate1 + inst->NUMOSvgb); *(ckt->CKTstate0 + inst->NUMOSid) = *(ckt->CKTstate1 + inst->NUMOSid); *(ckt->CKTstate0 + inst->NUMOSis) = *(ckt->CKTstate1 + inst->NUMOSis); *(ckt->CKTstate0 + inst->NUMOSig) = *(ckt->CKTstate1 + inst->NUMOSig); *(ckt->CKTstate0 + inst->NUMOSdIdDVdb) = *(ckt->CKTstate1 + inst->NUMOSdIdDVdb); *(ckt->CKTstate0 + inst->NUMOSdIdDVsb) = *(ckt->CKTstate1 + inst->NUMOSdIdDVsb); *(ckt->CKTstate0 + inst->NUMOSdIdDVgb) = *(ckt->CKTstate1 + inst->NUMOSdIdDVgb); *(ckt->CKTstate0 + inst->NUMOSdIsDVdb) = *(ckt->CKTstate1 + inst->NUMOSdIsDVdb); *(ckt->CKTstate0 + inst->NUMOSdIsDVsb) = *(ckt->CKTstate1 + inst->NUMOSdIsDVsb); *(ckt->CKTstate0 + inst->NUMOSdIsDVgb) = *(ckt->CKTstate1 + inst->NUMOSdIsDVgb); *(ckt->CKTstate0 + inst->NUMOSdIgDVdb) = *(ckt->CKTstate1 + inst->NUMOSdIgDVdb); *(ckt->CKTstate0 + inst->NUMOSdIgDVsb) = *(ckt->CKTstate1 + inst->NUMOSdIgDVsb); *(ckt->CKTstate0 + inst->NUMOSdIgDVgb) = *(ckt->CKTstate1 + inst->NUMOSdIgDVgb); if (!(ckt->CKTmode & MODEDCTRANCURVE)) { /* no linear prediction on device voltages */ vdb = *(ckt->CKTstate1 + inst->NUMOSvdb); vsb = *(ckt->CKTstate1 + inst->NUMOSvsb); vgb = *(ckt->CKTstate1 + inst->NUMOSvgb); TWOpredict(pDevice, model->NUMOSpInfo); } else { if (doVoltPred) { /* linear prediction */ xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1]; vdb = (1+xfact) * (*(ckt->CKTstate1 + inst->NUMOSvdb)) - (xfact) * (*(ckt->CKTstate2 + inst->NUMOSvdb)); vsb = (1+xfact) * (*(ckt->CKTstate1 + inst->NUMOSvsb)) - (xfact) * (*(ckt->CKTstate2 + inst->NUMOSvsb)); vgb = (1+xfact) * (*(ckt->CKTstate1 + inst->NUMOSvgb)) - (xfact) * (*(ckt->CKTstate2 + inst->NUMOSvgb)); } else { vdb = *(ckt->CKTstate1 + inst->NUMOSvdb); vsb = *(ckt->CKTstate1 + inst->NUMOSvsb); vgb = *(ckt->CKTstate1 + inst->NUMOSvgb); } } } else { /* * compute new nonlinear branch voltages */ vdb = *(ckt->CKTrhsOld + inst->NUMOSdrainNode) - *(ckt->CKTrhsOld + inst->NUMOSbulkNode); vsb = *(ckt->CKTrhsOld + inst->NUMOSsourceNode) - *(ckt->CKTrhsOld + inst->NUMOSbulkNode); vgb = *(ckt->CKTrhsOld + inst->NUMOSgateNode) - *(ckt->CKTrhsOld + inst->NUMOSbulkNode); } delVdb = vdb - *(ckt->CKTstate0 + inst->NUMOSvdb); delVsb = vsb - *(ckt->CKTstate0 + inst->NUMOSvsb); delVgb = vgb - *(ckt->CKTstate0 + inst->NUMOSvgb); idhat = *(ckt->CKTstate0 + inst->NUMOSid) + *(ckt->CKTstate0 + inst->NUMOSdIdDVdb) * delVdb + *(ckt->CKTstate0 + inst->NUMOSdIdDVsb) * delVsb + *(ckt->CKTstate0 + inst->NUMOSdIdDVgb) * delVgb; ishat = *(ckt->CKTstate0 + inst->NUMOSis) + *(ckt->CKTstate0 + inst->NUMOSdIsDVdb) * delVdb + *(ckt->CKTstate0 + inst->NUMOSdIsDVsb) * delVsb + *(ckt->CKTstate0 + inst->NUMOSdIsDVgb) * delVgb; ighat = *(ckt->CKTstate0 + inst->NUMOSig) + *(ckt->CKTstate0 + inst->NUMOSdIgDVdb) * delVdb + *(ckt->CKTstate0 + inst->NUMOSdIgDVsb) * delVsb + *(ckt->CKTstate0 + inst->NUMOSdIgDVgb) * delVgb;#ifndef NOBYPASS /* * bypass if solution has not changed */ /* * the following collections of if's would be just one if the average * compiler could handle it, but many find the expression too * complicated, thus the split. */ if ((ckt->CKTbypass) && pDevice->converged && (!(ckt->CKTmode & MODEINITPRED)) && (FABS(delVdb) < (ckt->CKTreltol * MAX(FABS(vdb), FABS(*(ckt->CKTstate0 + inst->NUMOSvdb))) + ckt->CKTvoltTol))) if ((FABS(delVsb) < ckt->CKTreltol * MAX(FABS(vsb), FABS(*(ckt->CKTstate0 + inst->NUMOSvsb))) + ckt->CKTvoltTol)) if ((FABS(delVgb) < ckt->CKTreltol * MAX(FABS(vgb), FABS(*(ckt->CKTstate0 + inst->NUMOSvgb))) + ckt->CKTvoltTol)) if ((FABS(idhat - *(ckt->CKTstate0 + inst->NUMOSid)) < ckt->CKTreltol * MAX(FABS(idhat), FABS(*(ckt->CKTstate0 + inst->NUMOSid))) + ckt->CKTabstol)) if ((FABS(ishat - *(ckt->CKTstate0 + inst->NUMOSis)) < ckt->CKTreltol * MAX(FABS(ishat), FABS(*(ckt->CKTstate0 + inst->NUMOSis))) + ckt->CKTabstol)) if ((FABS(ighat - *(ckt->CKTstate0 + inst->NUMOSig)) < ckt->CKTreltol * MAX(FABS(ighat), FABS(*(ckt->CKTstate0 + inst->NUMOSig))) + ckt->CKTabstol)) { /* * bypassing.... */ vdb = *(ckt->CKTstate0 + inst->NUMOSvdb); vsb = *(ckt->CKTstate0 + inst->NUMOSvsb); vgb = *(ckt->CKTstate0 + inst->NUMOSvgb); id = *(ckt->CKTstate0 + inst->NUMOSid); is = *(ckt->CKTstate0 + inst->NUMOSis);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -