📄 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 "ngspice.h"#include "devdefs.h"#include "cktdefs.h"#include "numosdef.h"#include "trandefs.h"#include "sperror.h"#include "../../../ciderlib/twod/twoddefs.h"#include "../../../ciderlib/twod/twodext.h"#include "cidersupt.h"#include "suffix.h"/* External Declarations */extern int TWOdcDebug;extern int TWOtranDebug;extern int TWOacDebug;/* Forward Declarations */int NUMOSinitSmSig(NUMOSinstance *inst);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 = 0.0, ishat = 0.0, ighat = 0.0; double delVdb, delVsb, delVgb; double vdb, vsb, vgb; struct mosConductances g; int icheck; int icheck1; int i; double deltaNorm[7]; int devConverged = 0; 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); ig = *(ckt->CKTstate0 + inst->NUMOSig); g.dIdDVdb = *(ckt->CKTstate0 + inst->NUMOSdIdDVdb); g.dIdDVsb = *(ckt->CKTstate0 + inst->NUMOSdIdDVsb); g.dIdDVgb = *(ckt->CKTstate0 + inst->NUMOSdIdDVgb); g.dIsDVdb = *(ckt->CKTstate0 + inst->NUMOSdIsDVdb); g.dIsDVsb = *(ckt->CKTstate0 + inst->NUMOSdIsDVsb); g.dIsDVgb = *(ckt->CKTstate0 + inst->NUMOSdIsDVgb); g.dIgDVdb = *(ckt->CKTstate0 + inst->NUMOSdIgDVdb); g.dIgDVsb = *(ckt->CKTstate0 + inst->NUMOSdIgDVsb); g.dIgDVgb = *(ckt->CKTstate0 + inst->NUMOSdIgDVgb); goto load; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -