Cider simulator (numerical devices) Import.
This commit is contained in:
parent
f5f8602d3a
commit
89317d34e8
|
|
@ -0,0 +1,30 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
noinst_LIBRARIES = libnbjt.a
|
||||
|
||||
libnbjt_a_SOURCES = \
|
||||
nbjt.c \
|
||||
nbjtacld.c \
|
||||
nbjtask.c \
|
||||
nbjtdefs.h \
|
||||
nbjtdel.c \
|
||||
nbjtdest.c \
|
||||
nbjtdump.c \
|
||||
nbjtext.h \
|
||||
nbjtinit.c \
|
||||
nbjtinit.h \
|
||||
nbjtitf.h \
|
||||
nbjtload.c \
|
||||
nbjtmdel.c \
|
||||
nbjtmpar.c \
|
||||
nbjtparm.c \
|
||||
nbjtpzld.c \
|
||||
nbjtset.c \
|
||||
nbjttemp.c \
|
||||
nbjttrun.c
|
||||
|
||||
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/src/include
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "devdefs.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/*
|
||||
* This file defines the Numerical BJT data structures that are available to
|
||||
* the next level(s) up the calling hierarchy
|
||||
*/
|
||||
|
||||
IFparm NBJTpTable[] = { /* parameters */
|
||||
IP("off", NBJT_OFF, IF_FLAG, "Device initially off"),
|
||||
IP("ic.file", NBJT_IC_FILE, IF_STRING, "Initial condition file"),
|
||||
IOP("area", NBJT_AREA, IF_REAL, "Area factor"),
|
||||
IP("save", NBJT_PRINT, IF_REAL, "Save Solutions"),
|
||||
IP("print", NBJT_PRINT, IF_REAL, "Print Solutions"),
|
||||
OP("g11", NBJT_G11, IF_REAL, "Conductance"),
|
||||
OP("c11", NBJT_C11, IF_REAL, "Capacitance"),
|
||||
OP("y11", NBJT_Y11, IF_COMPLEX, "Admittance"),
|
||||
OP("g12", NBJT_G12, IF_REAL, "Conductance"),
|
||||
OP("c12", NBJT_C12, IF_REAL, "Capacitance"),
|
||||
OP("y12", NBJT_Y12, IF_COMPLEX, "Admittance"),
|
||||
OPU("g13", NBJT_G13, IF_REAL, "Conductance"),
|
||||
OPU("c13", NBJT_C13, IF_REAL, "Capacitance"),
|
||||
OPU("y13", NBJT_Y13, IF_COMPLEX, "Admittance"),
|
||||
OP("g21", NBJT_G21, IF_REAL, "Conductance"),
|
||||
OP("c21", NBJT_C21, IF_REAL, "Capacitance"),
|
||||
OP("y21", NBJT_Y21, IF_COMPLEX, "Admittance"),
|
||||
OP("g22", NBJT_G22, IF_REAL, "Conductance"),
|
||||
OP("c22", NBJT_C22, IF_REAL, "Capacitance"),
|
||||
OP("y22", NBJT_Y22, IF_COMPLEX, "Admittance"),
|
||||
OPU("g23", NBJT_G23, IF_REAL, "Conductance"),
|
||||
OPU("c23", NBJT_C23, IF_REAL, "Capacitance"),
|
||||
OPU("y23", NBJT_Y23, IF_COMPLEX, "Admittance"),
|
||||
OPU("g31", NBJT_G31, IF_REAL, "Conductance"),
|
||||
OPU("c31", NBJT_C31, IF_REAL, "Capacitance"),
|
||||
OPU("y31", NBJT_Y31, IF_COMPLEX, "Admittance"),
|
||||
OPU("g32", NBJT_G32, IF_REAL, "Conductance"),
|
||||
OPU("c32", NBJT_C32, IF_REAL, "Capacitance"),
|
||||
OPU("y32", NBJT_Y32, IF_COMPLEX, "Admittance"),
|
||||
OPU("g33", NBJT_G33, IF_REAL, "Conductance"),
|
||||
OPU("c33", NBJT_C33, IF_REAL, "Capacitance"),
|
||||
OPU("y33", NBJT_Y33, IF_COMPLEX, "Admittance"),
|
||||
IOP("temp", NBJT_TEMP, IF_REAL, "Instance Temperature")
|
||||
};
|
||||
|
||||
IFparm NBJTmPTable[] = { /* model parameters */
|
||||
/* numerical-device models no longer have parameters */
|
||||
/* one is left behind to keep the table from being empty */
|
||||
IP("nbjt", NBJT_MOD_NBJT, IF_FLAG, "Numerical BJT Model")
|
||||
};
|
||||
|
||||
char *NBJTnames[] = {
|
||||
"Collector",
|
||||
"Base",
|
||||
"Emitter",
|
||||
"Substrate"
|
||||
};
|
||||
|
||||
int NBJTnSize = NUMELEMS(NBJTnames);
|
||||
int NBJTpTSize = NUMELEMS(NBJTpTable);
|
||||
int NBJTmPTSize = NUMELEMS(NBJTmPTable);
|
||||
int NBJTiSize = sizeof(NBJTinstance);
|
||||
int NBJTmSize = sizeof(NBJTmodel);
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* Function to load the COMPLEX circuit matrix using the small signal
|
||||
* parameters saved during a previous DC operating point analysis.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "sperror.h"
|
||||
#include "complex.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "numglobs.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* External Declarations */
|
||||
extern int ONEacDebug;
|
||||
|
||||
int
|
||||
NBJTacLoad(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
|
||||
{
|
||||
register NBJTmodel *model = (NBJTmodel *) inModel;
|
||||
register NBJTinstance *inst;
|
||||
SPcomplex yIeVce, yIeVbe;
|
||||
SPcomplex yIcVce, yIcVbe;
|
||||
double startTime;
|
||||
|
||||
for (; model != NULL; model = model->NBJTnextModel) {
|
||||
FieldDepMobility = model->NBJTmodels->MODLfieldDepMobility;
|
||||
Srh = model->NBJTmodels->MODLsrh;
|
||||
Auger = model->NBJTmodels->MODLauger;
|
||||
AvalancheGen = model->NBJTmodels->MODLavalancheGen;
|
||||
AcAnalysisMethod = model->NBJTmethods->METHacAnalysisMethod;
|
||||
MobDeriv = model->NBJTmethods->METHmobDeriv;
|
||||
ONEacDebug = model->NBJToutputs->OUTPacDebug;
|
||||
|
||||
for (inst = model->NBJTinstances; inst != NULL;
|
||||
inst = inst->NBJTnextInstance) {
|
||||
if (inst->NBJTowner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NBJTglobals));
|
||||
|
||||
model->NBJTmethods->METHacAnalysisMethod =
|
||||
NBJTadmittance(inst->NBJTpDevice, ckt->CKTomega,
|
||||
&yIeVce, &yIcVce, &yIeVbe, &yIcVbe);
|
||||
|
||||
*(inst->NBJTcolColPtr) += yIcVce.real;
|
||||
*(inst->NBJTcolColPtr + 1) += yIcVce.imag;
|
||||
*(inst->NBJTcolBasePtr) += yIcVbe.real;
|
||||
*(inst->NBJTcolBasePtr + 1) += yIcVbe.imag;
|
||||
*(inst->NBJTcolEmitPtr) -= yIcVbe.real + yIcVce.real;
|
||||
*(inst->NBJTcolEmitPtr + 1) -= yIcVbe.imag + yIcVce.imag;
|
||||
*(inst->NBJTbaseColPtr) -= yIcVce.real - yIeVce.real;
|
||||
*(inst->NBJTbaseColPtr + 1) -= yIcVce.imag - yIeVce.imag;
|
||||
*(inst->NBJTbaseBasePtr) -= yIcVbe.real - yIeVbe.real;
|
||||
*(inst->NBJTbaseBasePtr + 1) -= yIcVbe.imag - yIeVbe.imag;
|
||||
*(inst->NBJTbaseEmitPtr) += yIcVbe.real + yIcVce.real - yIeVbe.real - yIeVce.real;
|
||||
*(inst->NBJTbaseEmitPtr + 1) += yIcVbe.imag + yIcVce.imag - yIeVbe.imag - yIeVce.imag;
|
||||
*(inst->NBJTemitColPtr) -= yIeVce.real;
|
||||
*(inst->NBJTemitColPtr + 1) -= yIeVce.imag;
|
||||
*(inst->NBJTemitBasePtr) -= yIeVbe.real;
|
||||
*(inst->NBJTemitBasePtr + 1) -= yIeVbe.imag;
|
||||
*(inst->NBJTemitEmitPtr) += yIeVbe.real + yIeVce.real;
|
||||
*(inst->NBJTemitEmitPtr + 1) += yIeVbe.imag + yIeVce.imag;
|
||||
if (ckt->CKTomega != 0.0) {
|
||||
inst->NBJTc11 = yIcVce.imag / ckt->CKTomega;
|
||||
inst->NBJTc12 = yIcVbe.imag / ckt->CKTomega;
|
||||
inst->NBJTc21 = (yIeVce.imag - yIcVce.imag) / ckt->CKTomega;
|
||||
inst->NBJTc22 = (yIeVbe.imag - yIcVbe.imag) / ckt->CKTomega;
|
||||
} else {
|
||||
inst->NBJTc11 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NBJTc12 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NBJTc21 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NBJTc22 = 0.0; /* XXX What else can be done?! */
|
||||
}
|
||||
inst->NBJTy11r = yIcVce.real;
|
||||
inst->NBJTy11i = yIcVce.imag;
|
||||
inst->NBJTy12r = yIcVbe.real;
|
||||
inst->NBJTy12i = yIcVbe.imag;
|
||||
inst->NBJTy21r = yIeVce.real - yIcVce.real;
|
||||
inst->NBJTy21i = yIeVce.imag - yIcVce.imag;
|
||||
inst->NBJTy22r = yIeVbe.real - yIcVbe.real;
|
||||
inst->NBJTy22i = yIeVbe.imag - yIcVbe.imag;
|
||||
inst->NBJTsmSigAvail = TRUE;
|
||||
inst->NBJTpDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Thomas L. Quarles
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "cktdefs.h"
|
||||
#include "devdefs.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* Check out this one */
|
||||
extern int NBJTinitSmSig(NBJTinstance *);
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
NBJTask(ckt, inInst, which, value, select)
|
||||
CKTcircuit *ckt;
|
||||
GENinstance *inInst;
|
||||
int which;
|
||||
IFvalue *value;
|
||||
IFvalue *select;
|
||||
{
|
||||
NBJTinstance *inst = (NBJTinstance *) inInst;
|
||||
switch (which) {
|
||||
case NBJT_AREA:
|
||||
value->rValue = inst->NBJTarea;
|
||||
return (OK);
|
||||
case NBJT_TEMP:
|
||||
value->rValue = inst->NBJTtemp - CONSTCtoK;
|
||||
return (OK);
|
||||
case NBJT_G11:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NBJTdIcDVce);
|
||||
return (OK);
|
||||
case NBJT_G12:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NBJTdIcDVbe);
|
||||
return (OK);
|
||||
case NBJT_G13:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NBJTdIcDVce)
|
||||
- *(ckt->CKTstate0 + inst->NBJTdIcDVbe);
|
||||
return (OK);
|
||||
case NBJT_G21:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NBJTdIeDVce)
|
||||
- *(ckt->CKTstate0 + inst->NBJTdIcDVce);
|
||||
return (OK);
|
||||
case NBJT_G22:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NBJTdIeDVbe)
|
||||
- *(ckt->CKTstate0 + inst->NBJTdIcDVbe);
|
||||
return (OK);
|
||||
case NBJT_G23:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NBJTdIeDVce)
|
||||
+ *(ckt->CKTstate0 + inst->NBJTdIcDVce) /* XXX there was a ;*/
|
||||
-*(ckt->CKTstate0 + inst->NBJTdIeDVbe)
|
||||
+ *(ckt->CKTstate0 + inst->NBJTdIcDVbe);
|
||||
return (OK);
|
||||
case NBJT_G31:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NBJTdIeDVce);
|
||||
return (OK);
|
||||
case NBJT_G32:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NBJTdIeDVbe);
|
||||
return (OK);
|
||||
case NBJT_G33:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NBJTdIeDVce)
|
||||
+ *(ckt->CKTstate0 + inst->NBJTdIeDVbe);
|
||||
return (OK);
|
||||
case NBJT_C11:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NBJTc11;
|
||||
return (OK);
|
||||
case NBJT_C12:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NBJTc12;
|
||||
return (OK);
|
||||
case NBJT_C13:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NBJTc11 - inst->NBJTc12;
|
||||
return (OK);
|
||||
case NBJT_C21:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NBJTc21;
|
||||
return (OK);
|
||||
case NBJT_C22:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NBJTc22;
|
||||
return (OK);
|
||||
case NBJT_C23:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NBJTc21 - inst->NBJTc22;
|
||||
return (OK);
|
||||
case NBJT_C31:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NBJTc11 - inst->NBJTc21;
|
||||
return (OK);
|
||||
case NBJT_C32:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NBJTc12 - inst->NBJTc22;
|
||||
return (OK);
|
||||
case NBJT_C33:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NBJTc11 + inst->NBJTc21
|
||||
+ inst->NBJTc12 + inst->NBJTc22;
|
||||
return (OK);
|
||||
case NBJT_Y11:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NBJTy11r;
|
||||
value->cValue.imag = inst->NBJTy11i;
|
||||
return (OK);
|
||||
case NBJT_Y12:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NBJTy12r;
|
||||
value->cValue.imag = inst->NBJTy12i;
|
||||
return (OK);
|
||||
case NBJT_Y13:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NBJTy11r - inst->NBJTy12r;
|
||||
value->cValue.imag = -inst->NBJTy11i - inst->NBJTy12i;
|
||||
return (OK);
|
||||
case NBJT_Y21:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NBJTy21r;
|
||||
value->cValue.imag = inst->NBJTy21i;
|
||||
return (OK);
|
||||
case NBJT_Y22:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NBJTy22r;
|
||||
value->cValue.imag = inst->NBJTy22i;
|
||||
return (OK);
|
||||
case NBJT_Y23:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NBJTy21r - inst->NBJTy22r;
|
||||
value->cValue.imag = -inst->NBJTy21i - inst->NBJTy22i;
|
||||
return (OK);
|
||||
case NBJT_Y31:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NBJTy11r - inst->NBJTy21r;
|
||||
value->cValue.imag = -inst->NBJTy11i - inst->NBJTy21i;
|
||||
return (OK);
|
||||
case NBJT_Y32:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NBJTy12r - inst->NBJTy22r;
|
||||
value->cValue.imag = -inst->NBJTy12i - inst->NBJTy22i;
|
||||
return (OK);
|
||||
case NBJT_Y33:
|
||||
if (!inst->NBJTsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJTinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NBJTy11r + inst->NBJTy21r
|
||||
+ inst->NBJTy12r + inst->NBJTy22r;
|
||||
value->cValue.imag = inst->NBJTy11i + inst->NBJTy21i
|
||||
+ inst->NBJTy12i + inst->NBJTy22i;
|
||||
return (OK);
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Authors: 1987 Karti Mayaram, 1991 David Gates
|
||||
**********/
|
||||
|
||||
#ifndef NBJT_H
|
||||
#define NBJT_H
|
||||
|
||||
/* data structures used to describe 1D Numerical BJTs */
|
||||
|
||||
/* circuit level includes */
|
||||
#include "ifsim.h"
|
||||
#include "cktdefs.h"
|
||||
#include "gendefs.h"
|
||||
|
||||
/* device level includes */
|
||||
#include "onemesh.h"
|
||||
#include "onedev.h"
|
||||
#include "profile.h"
|
||||
#include "numglobs.h"
|
||||
#include "carddefs.h"
|
||||
|
||||
/* information needed per instance */
|
||||
typedef struct sNBJTinstance {
|
||||
struct sNBJTmodel *NBJTmodPtr;/* back pointer to model */
|
||||
struct sNBJTinstance *NBJTnextInstance; /* pointer to next instance
|
||||
* of current model */
|
||||
IFuid NBJTname; /* pointer to character string naming this
|
||||
* instance */
|
||||
int NBJTowner; /* number of owner process */
|
||||
int NBJTstate; /* pointer to start of state vector for bjt */
|
||||
|
||||
/* entries in the state vector for bjt: */
|
||||
#define NBJTvbe NBJTstate
|
||||
#define NBJTvce NBJTstate+1
|
||||
#define NBJTic NBJTstate+2
|
||||
#define NBJTie NBJTstate+3
|
||||
#define NBJTdIeDVce NBJTstate+4
|
||||
#define NBJTdIeDVbe NBJTstate+5
|
||||
#define NBJTdIcDVce NBJTstate+6
|
||||
#define NBJTdIcDVbe NBJTstate+7
|
||||
#define NBJTnumStates 8
|
||||
|
||||
int NBJTcolNode; /* number of collector node of bjt */
|
||||
int NBJTbaseNode; /* number of base node of bjt */
|
||||
int NBJTemitNode; /* number of emitter node of bjt */
|
||||
ONEdevice *NBJTpDevice;
|
||||
GLOBvalues NBJTglobals; /* Temp.-Dep. Global Parameters */
|
||||
int NBJTtype;
|
||||
double NBJTarea; /* area factor of the BJT */
|
||||
double NBJTtemp; /* Instance Temperature */
|
||||
double NBJTc11; /* small-signal capacitance */
|
||||
double NBJTy11r; /* small-signal admittance, real part */
|
||||
double NBJTy11i; /* small-signal admittance, imag part */
|
||||
double NBJTc12; /* small-signal capacitance */
|
||||
double NBJTy12r; /* small-signal admittance, real part */
|
||||
double NBJTy12i; /* small-signal admittance, imag part */
|
||||
double NBJTc21; /* small-signal capacitance */
|
||||
double NBJTy21r; /* small-signal admittance, real part */
|
||||
double NBJTy21i; /* small-signal admittance, imag part */
|
||||
double NBJTc22; /* small-signal capacitance */
|
||||
double NBJTy22r; /* small-signal admittance, real part */
|
||||
double NBJTy22i; /* small-signal admittance, imag part */
|
||||
int NBJTprint;
|
||||
char *NBJTicFile; /* Name of initial condition file */
|
||||
double *NBJTcolColPtr; /* pointer to sparse matrix at
|
||||
* (collector,collector) */
|
||||
double *NBJTbaseBasePtr; /* pointer to sparse matrix at (base,base) */
|
||||
double *NBJTemitEmitPtr; /* pointer to sparse matrix at
|
||||
* (emitter,emitter) */
|
||||
double *NBJTcolBasePtr; /* pointer to sparse matrix at
|
||||
* (collector,base) */
|
||||
double *NBJTcolEmitPtr; /* pointer to sparse matrix at
|
||||
* (collector,emitter) */
|
||||
double *NBJTbaseColPtr; /* pointer to sparse matrix at
|
||||
* (base,collector) */
|
||||
double *NBJTbaseEmitPtr; /* pointer to sparse matrix at (base,emitter) */
|
||||
double *NBJTemitColPtr; /* pointer to sparse matrix at
|
||||
* (emitter,collector) */
|
||||
double *NBJTemitBasePtr; /* pointer to sparse matrix at (emitter,base) */
|
||||
int NBJToff; /* 'off' flag for bjt */
|
||||
unsigned NBJTsmSigAvail:1; /* flag to indicate small-signal done */
|
||||
unsigned NBJTareaGiven:1; /* flag to indicate area was specified */
|
||||
unsigned NBJTicFileGiven:1; /* flag to indicate init. cond. file given */
|
||||
unsigned NBJTprintGiven:1; /* flag to indicate if print was given */
|
||||
unsigned NBJTtempGiven:1; /* flag to indicate if temp was given */
|
||||
} NBJTinstance;
|
||||
|
||||
/* per model data */
|
||||
typedef struct sNBJTmodel { /* model structure for a bjt */
|
||||
int NBJTmodType; /* type index of this device type */
|
||||
struct sNBJTmodel *NBJTnextModel; /* pointer to next possible model in
|
||||
* linked list */
|
||||
NBJTinstance *NBJTinstances; /* pointer to list of instances that have
|
||||
* this model */
|
||||
IFuid NBJTmodName; /* pointer to character string naming this
|
||||
* model */
|
||||
/* Everything below here is numerical-device-specific */
|
||||
MESHcard *NBJTxMeshes; /* list of xmesh cards */
|
||||
MESHcard *NBJTyMeshes; /* list of ymesh cards */
|
||||
DOMNcard *NBJTdomains; /* list of domain cards */
|
||||
BDRYcard *NBJTboundaries; /* list of boundary cards */
|
||||
DOPcard *NBJTdopings; /* list of doping cards */
|
||||
ELCTcard *NBJTelectrodes; /* list of electrode cards */
|
||||
CONTcard *NBJTcontacts; /* list of contact cards */
|
||||
MODLcard *NBJTmodels; /* list of model cards */
|
||||
MATLcard *NBJTmaterials; /* list of material cards */
|
||||
MOBcard *NBJTmobility; /* list of mobility cards */
|
||||
METHcard *NBJTmethods; /* list of method cards */
|
||||
OPTNcard *NBJToptions; /* list of option cards */
|
||||
OUTPcard *NBJToutputs; /* list of output cards */
|
||||
ONEtranInfo *NBJTpInfo; /* transient analysis information */
|
||||
DOPprofile *NBJTprofiles; /* expanded list of doping profiles */
|
||||
DOPtable *NBJTdopTables; /* list of tables used by profiles */
|
||||
ONEmaterial *NBJTmatlInfo; /* list of material info structures */
|
||||
} NBJTmodel;
|
||||
|
||||
/* type of BJT */
|
||||
#define NPN 1
|
||||
#define PNP -1
|
||||
|
||||
/* device parameters */
|
||||
#define NBJT_AREA 1
|
||||
#define NBJT_OFF 2
|
||||
#define NBJT_IC_FILE 3
|
||||
#define NBJT_PRINT 4
|
||||
#define NBJT_TEMP 5
|
||||
|
||||
#define NBJT_G11 8
|
||||
#define NBJT_C11 9
|
||||
#define NBJT_Y11 10
|
||||
#define NBJT_G12 11
|
||||
#define NBJT_C12 12
|
||||
#define NBJT_Y12 13
|
||||
#define NBJT_G13 14
|
||||
#define NBJT_C13 15
|
||||
#define NBJT_Y13 16
|
||||
#define NBJT_G21 17
|
||||
#define NBJT_C21 18
|
||||
#define NBJT_Y21 19
|
||||
#define NBJT_G22 20
|
||||
#define NBJT_C22 21
|
||||
#define NBJT_Y22 22
|
||||
#define NBJT_G23 23
|
||||
#define NBJT_C23 24
|
||||
#define NBJT_Y23 25
|
||||
#define NBJT_G31 26
|
||||
#define NBJT_C31 27
|
||||
#define NBJT_Y31 28
|
||||
#define NBJT_G32 29
|
||||
#define NBJT_C32 30
|
||||
#define NBJT_Y32 31
|
||||
#define NBJT_G33 32
|
||||
#define NBJT_C33 33
|
||||
#define NBJT_Y33 34
|
||||
|
||||
/* model parameters */
|
||||
/* NOTE: all true model parameters have been moved to IFcardInfo structures */
|
||||
#define NBJT_MOD_NBJT 101
|
||||
|
||||
/* device questions */
|
||||
|
||||
/* model questions */
|
||||
|
||||
#include "nbjtext.h"
|
||||
|
||||
#endif /* NBJT_H */
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine deletes a NBJT instance from the circuit and frees the
|
||||
* storage it was using.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NBJTdelete(inModel, name, kill)
|
||||
GENmodel *inModel;
|
||||
IFuid name;
|
||||
GENinstance **kill;
|
||||
|
||||
{
|
||||
NBJTmodel *model = (NBJTmodel *) inModel;
|
||||
NBJTinstance **fast = (NBJTinstance **) kill;
|
||||
NBJTinstance **prev = NULL;
|
||||
NBJTinstance *inst;
|
||||
|
||||
for (; model; model = model->NBJTnextModel) {
|
||||
prev = &(model->NBJTinstances);
|
||||
for (inst = *prev; inst; inst = *prev) {
|
||||
if (inst->NBJTname == name || (fast && inst == *fast)) {
|
||||
*prev = inst->NBJTnextInstance;
|
||||
FREE(inst);
|
||||
return (OK);
|
||||
}
|
||||
prev = &(inst->NBJTnextInstance);
|
||||
}
|
||||
}
|
||||
return (E_NODEV);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine deletes all NBJTs from the circuit and frees all storage they
|
||||
* were using. The current implementation has memory leaks.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
void
|
||||
NBJTdestroy(inModel)
|
||||
GENmodel **inModel;
|
||||
|
||||
{
|
||||
|
||||
NBJTmodel **model = (NBJTmodel **) inModel;
|
||||
NBJTmodel *mod, *nextMod;
|
||||
NBJTinstance *inst, *nextInst;
|
||||
|
||||
|
||||
for (mod = *model; mod;) {
|
||||
for (inst = mod->NBJTinstances; inst;) {
|
||||
ONEdestroy(inst->NBJTpDevice);
|
||||
nextInst = inst->NBJTnextInstance;
|
||||
FREE(inst);
|
||||
inst = nextInst;
|
||||
}
|
||||
nextMod = mod->NBJTnextModel;
|
||||
FREE(mod);
|
||||
mod = nextMod;
|
||||
}
|
||||
*model = NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This is a simple routine to dump the internal device states. It produces
|
||||
* states for .OP, .DC, & .TRAN simulations.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
|
||||
/* Forward Declarations */
|
||||
static void NBJTputHeader(FILE *, CKTcircuit *, NBJTinstance *);
|
||||
|
||||
/* State Counter */
|
||||
static int state_numOP = 0;
|
||||
static int state_numDC = 0;
|
||||
static int state_numTR = 0;
|
||||
|
||||
void
|
||||
NBJTdump(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
{
|
||||
register NBJTmodel *model = (NBJTmodel *) inModel;
|
||||
register NBJTinstance *inst;
|
||||
OUTPcard *output;
|
||||
FILE *fpState;
|
||||
char fileName[BSIZE_SP];
|
||||
char description[BSIZE_SP];
|
||||
char *prefix;
|
||||
int *state_num;
|
||||
int anyOutput = 0;
|
||||
|
||||
if (ckt->CKTmode & MODEDCOP) {
|
||||
prefix = "OP";
|
||||
state_num = &state_numOP;
|
||||
sprintf(description, "...");
|
||||
} else if (ckt->CKTmode & MODEDCTRANCURVE) {
|
||||
prefix = "DC";
|
||||
state_num = &state_numDC;
|
||||
sprintf(description, "sweep = % e", ckt->CKTtime);
|
||||
} else if (ckt->CKTmode & MODETRAN) {
|
||||
prefix = "TR";
|
||||
state_num = &state_numTR;
|
||||
sprintf(description, "time = % e", ckt->CKTtime);
|
||||
} else {
|
||||
/* Not a recognized CKT mode. */
|
||||
return;
|
||||
}
|
||||
|
||||
for (; model != NULL; model = model->NBJTnextModel) {
|
||||
output = model->NBJToutputs;
|
||||
for (inst = model->NBJTinstances; inst != NULL;
|
||||
inst = inst->NBJTnextInstance) {
|
||||
if (inst->NBJTowner != ARCHme) continue;
|
||||
|
||||
if (inst->NBJTprintGiven) {
|
||||
if ((ckt->CKTmode & MODETRAN) &&
|
||||
((ckt->CKTstat->STATaccepted - 1) % inst->NBJTprint != 0)) {
|
||||
continue;
|
||||
}
|
||||
anyOutput = 1;
|
||||
sprintf(fileName, "%s%s.%d.%s", output->OUTProotFile, prefix,
|
||||
*state_num, inst->NBJTname);
|
||||
if (!(fpState = fopen(fileName, "w"))) {
|
||||
perror(fileName);
|
||||
} else {
|
||||
NBJTputHeader(fpState, ckt, inst);
|
||||
ONEprnSolution(fpState, inst->NBJTpDevice,
|
||||
model->NBJToutputs);
|
||||
fclose(fpState);
|
||||
LOGmakeEntry(fileName, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (anyOutput) {
|
||||
(*state_num)++;
|
||||
}
|
||||
}
|
||||
|
||||
#define NBJTnumOutputs 9
|
||||
|
||||
static
|
||||
void
|
||||
NBJTputHeader(file, ckt, inst)
|
||||
FILE *file;
|
||||
CKTcircuit *ckt;
|
||||
NBJTinstance *inst;
|
||||
{
|
||||
char *reference;
|
||||
double refVal = 0.0;
|
||||
int numVars = NBJTnumOutputs;
|
||||
|
||||
if (ckt->CKTmode & MODEDCOP) {
|
||||
reference = NULL;
|
||||
} else if (ckt->CKTmode & MODEDCTRANCURVE) {
|
||||
reference = "sweep";
|
||||
refVal = ckt->CKTtime;
|
||||
numVars++;
|
||||
} else if (ckt->CKTmode & MODETRAN) {
|
||||
reference = "time";
|
||||
refVal = ckt->CKTtime;
|
||||
numVars++;
|
||||
} else {
|
||||
reference = NULL;
|
||||
}
|
||||
fprintf(file, "Title: Device %s external state\n", inst->NBJTname);
|
||||
fprintf(file, "Plotname: Device Operating Point\n");
|
||||
fprintf(file, "Command: deftype v conductance S\n");
|
||||
fprintf(file, "Flags: real\n");
|
||||
fprintf(file, "No. Variables: %d\n", numVars);
|
||||
fprintf(file, "No. Points: 1\n");
|
||||
numVars = 0;
|
||||
fprintf(file, "Variables:\n");
|
||||
if (reference) {
|
||||
fprintf(file, "\t%d %s unknown\n", numVars++, reference);
|
||||
}
|
||||
fprintf(file, "\t%d v13 voltage\n", numVars++);
|
||||
fprintf(file, "\t%d v23 voltage\n", numVars++);
|
||||
fprintf(file, "\t%d i1 current\n", numVars++);
|
||||
fprintf(file, "\t%d i2 current\n", numVars++);
|
||||
fprintf(file, "\t%d i3 current\n", numVars++);
|
||||
fprintf(file, "\t%d g22 conductance\n", numVars++);
|
||||
fprintf(file, "\t%d g21 conductance\n", numVars++);
|
||||
fprintf(file, "\t%d g12 conductance\n", numVars++);
|
||||
fprintf(file, "\t%d g11 conductance\n", numVars++);
|
||||
fprintf(file, "Values:\n0");
|
||||
if (reference) {
|
||||
fprintf(file, "\t% e\n", refVal);
|
||||
}
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTvce));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTvbe));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTic));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTie)
|
||||
- *(ckt->CKTstate0 + inst->NBJTic));
|
||||
fprintf(file, "\t% e\n", -*(ckt->CKTstate0 + inst->NBJTie));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTdIeDVbe)
|
||||
- *(ckt->CKTstate0 + inst->NBJTdIcDVbe));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTdIeDVce)
|
||||
- *(ckt->CKTstate0 + inst->NBJTdIcDVce));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTdIcDVbe));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJTdIcDVce));
|
||||
}
|
||||
|
||||
void
|
||||
NBJTacct(inModel, ckt, file)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
FILE *file;
|
||||
{
|
||||
register NBJTmodel *model = (NBJTmodel *) inModel;
|
||||
register NBJTinstance *inst;
|
||||
OUTPcard *output;
|
||||
|
||||
for (; model != NULL; model = model->NBJTnextModel) {
|
||||
output = model->NBJToutputs;
|
||||
for (inst = model->NBJTinstances; inst != NULL;
|
||||
inst = inst->NBJTnextInstance) {
|
||||
if (inst->NBJTowner != ARCHme) continue;
|
||||
|
||||
if (output->OUTPstats) {
|
||||
ONEmemStats(file, inst->NBJTpDevice);
|
||||
ONEcpuStats(file, inst->NBJTpDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Karti Mayaram
|
||||
**********/
|
||||
|
||||
#ifndef __NBJT_H
|
||||
#define __NBJT_H
|
||||
|
||||
extern int NBJTacLoad(GENmodel *, CKTcircuit *);
|
||||
extern int NBJTask(CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *);
|
||||
extern int NBJTdelete(GENmodel *, IFuid, GENinstance **);
|
||||
extern void NBJTdestroy(GENmodel **);
|
||||
extern int NBJTgetic(GENmodel *, CKTcircuit *);
|
||||
extern int NBJTload(GENmodel *, CKTcircuit *);
|
||||
extern int NBJTmDelete(GENmodel **, IFuid, GENmodel *);
|
||||
extern int NBJTmParam(int, IFvalue *, GENmodel *);
|
||||
extern int NBJTparam(int, IFvalue *, GENinstance *, IFvalue *);
|
||||
extern int NBJTpzLoad(GENmodel *, CKTcircuit *, SPcomplex *);
|
||||
extern int NBJTsetup(SMPmatrix *, GENmodel *, CKTcircuit *, int *);
|
||||
extern int NBJTtemp(GENmodel *, CKTcircuit *);
|
||||
extern int NBJTtrunc(GENmodel *, CKTcircuit *, double *);
|
||||
|
||||
extern void NBJTdump(GENmodel *, CKTcircuit *);
|
||||
extern void NBJTacct(GENmodel *, CKTcircuit *, FILE *);
|
||||
|
||||
|
||||
#endif /* NBJT_H */
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <devdefs.h>
|
||||
|
||||
#include "nbjtitf.h"
|
||||
#include "nbjtext.h"
|
||||
#include "nbjtinit.h"
|
||||
|
||||
|
||||
SPICEdev NBJTinfo = {
|
||||
{
|
||||
"NBJT",
|
||||
"1D Numerical Bipolar Junction Transistor model",
|
||||
|
||||
&NBJTnSize,
|
||||
&NBJTnSize,
|
||||
NBJTnames,
|
||||
|
||||
&NBJTpTSize,
|
||||
NBJTpTable,
|
||||
|
||||
&NBJTmPTSize,
|
||||
NBJTmPTable,
|
||||
|
||||
#ifdef XSPICE
|
||||
/*---- Fixed by SDB 5.2.2003 to enable XSPICE/tclspice integration -----*/
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
/*--------------------------- End of SDB fix -------------------------*/
|
||||
#endif
|
||||
|
||||
DEV_DEFAULT
|
||||
},
|
||||
|
||||
DEVparam : NBJTparam,
|
||||
DEVmodParam : NBJTmParam,
|
||||
DEVload : NBJTload,
|
||||
DEVsetup : NBJTsetup,
|
||||
DEVunsetup : NULL,
|
||||
DEVpzSetup : NBJTsetup,
|
||||
DEVtemperature: NBJTtemp,
|
||||
DEVtrunc : NBJTtrunc,
|
||||
DEVfindBranch : NULL,
|
||||
DEVacLoad : NBJTacLoad,
|
||||
DEVaccept : NULL,
|
||||
DEVdestroy : NBJTdestroy,
|
||||
DEVmodDelete : NBJTmDelete,
|
||||
DEVdelete : NBJTdelete,
|
||||
DEVsetic : NULL,
|
||||
DEVask : NBJTask,
|
||||
DEVmodAsk : NULL,
|
||||
DEVpzLoad : NBJTpzLoad,
|
||||
DEVconvTest : NULL,
|
||||
DEVsenSetup : NULL,
|
||||
DEVsenLoad : NULL,
|
||||
DEVsenUpdate : NULL,
|
||||
DEVsenAcLoad : NULL,
|
||||
DEVsenPrint : NULL,
|
||||
DEVsenTrunc : NULL,
|
||||
DEVdisto : NULL,
|
||||
DEVnoise : NULL,
|
||||
DEVdump : NBJTdump,
|
||||
DEVacct : NBJTacct,
|
||||
|
||||
DEVinstSize : &NBJTiSize,
|
||||
DEVmodSize : &NBJTmSize
|
||||
|
||||
};
|
||||
|
||||
|
||||
SPICEdev *
|
||||
get_nbjt_info(void)
|
||||
{
|
||||
return &NBJTinfo;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef _NBJTINIT_H
|
||||
#define _NBJTINIT_H
|
||||
|
||||
extern IFparm NBJTpTable[ ];
|
||||
extern IFparm NBJTmPTable[ ];
|
||||
extern char *NBJTnames[ ];
|
||||
extern int NBJTpTSize;
|
||||
extern int NBJTmPTSize;
|
||||
extern int NBJTnSize;
|
||||
extern int NBJTiSize;
|
||||
extern int NBJTmSize;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
**********/
|
||||
|
||||
#ifndef DEV_NBJT
|
||||
#define DEV_NBJT
|
||||
|
||||
extern SPICEdev *get_nbjt_info(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,517 @@
|
|||
/**********
|
||||
Copyright 1992 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 numerical BJTs
|
||||
* in the circuit and load them into the matrix as appropriate
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "devdefs.h"
|
||||
#include "cktdefs.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "trandefs.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* Forward declarations */
|
||||
int NBJTinitSmSig(NBJTinstance *);
|
||||
|
||||
/* External Declarations */
|
||||
extern int ONEdcDebug;
|
||||
extern int ONEtranDebug;
|
||||
extern int ONEacDebug;
|
||||
|
||||
|
||||
int
|
||||
NBJTload(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
{
|
||||
register NBJTmodel *model = (NBJTmodel *) inModel;
|
||||
register NBJTinstance *inst;
|
||||
register ONEdevice *pDevice;
|
||||
double startTime, startTime2, totalTime, totalTime2;
|
||||
double tol;
|
||||
double ic, ie;
|
||||
double iceq, ieeq;
|
||||
double ichat = 0.0, iehat = 0.0;
|
||||
double delVce, delVbe;
|
||||
double vce, vbe, vbc;
|
||||
double dIeDVce, dIeDVbe;
|
||||
double dIcDVce, dIcDVbe;
|
||||
double xfact;
|
||||
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->NBJTnextModel) {
|
||||
FieldDepMobility = model->NBJTmodels->MODLfieldDepMobility;
|
||||
Srh = model->NBJTmodels->MODLsrh;
|
||||
Auger = model->NBJTmodels->MODLauger;
|
||||
AvalancheGen = model->NBJTmodels->MODLavalancheGen;
|
||||
MobDeriv = model->NBJTmethods->METHmobDeriv;
|
||||
MaxIterations = model->NBJTmethods->METHitLim;
|
||||
ONEdcDebug = model->NBJToutputs->OUTPdcDebug;
|
||||
ONEtranDebug = model->NBJToutputs->OUTPtranDebug;
|
||||
ONEacDebug = model->NBJToutputs->OUTPacDebug;
|
||||
deviceType = model->NBJToptions->OPTNdeviceType;
|
||||
doVoltPred = model->NBJTmethods->METHvoltPred;
|
||||
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
/* compute normalized deltas and predictor coeff */
|
||||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) {
|
||||
model->NBJTpInfo->order = ckt->CKTorder;
|
||||
model->NBJTpInfo->method = ckt->CKTintegrateMethod;
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder,
|
||||
model->NBJTpInfo->intCoeff, deltaNorm);
|
||||
computePredCoeff(ckt->CKTintegrateMethod, ckt->CKTorder,
|
||||
model->NBJTpInfo->predCoeff, deltaNorm);
|
||||
}
|
||||
} else if (ckt->CKTmode & MODEINITTRAN) {
|
||||
model->NBJTpInfo->order = ckt->CKTorder;
|
||||
model->NBJTpInfo->method = ckt->CKTintegrateMethod;
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder,
|
||||
model->NBJTpInfo->intCoeff, deltaNorm);
|
||||
}
|
||||
/* loop through all the instances of the model */
|
||||
for (inst = model->NBJTinstances; inst != NULL;
|
||||
inst = inst->NBJTnextInstance) {
|
||||
if (inst->NBJTowner != ARCHme) continue;
|
||||
|
||||
pDevice = inst->NBJTpDevice;
|
||||
|
||||
totalTime = 0.0;
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NBJTglobals));
|
||||
|
||||
/*
|
||||
* initialization
|
||||
*/
|
||||
|
||||
pDevice->devStates = ckt->CKTstates;
|
||||
icheck = 1;
|
||||
doInitSolve = FALSE;
|
||||
initStateName = NULL;
|
||||
if (ckt->CKTmode & MODEINITSMSIG) {
|
||||
vbe = *(ckt->CKTstate0 + inst->NBJTvbe);
|
||||
vce = *(ckt->CKTstate0 + inst->NBJTvce);
|
||||
delVbe = 0.0;
|
||||
delVce = 0.0;
|
||||
NBJTsetBCs(pDevice, vce, vbe);
|
||||
} else if (ckt->CKTmode & MODEINITTRAN) {
|
||||
*(ckt->CKTstate0 + inst->NBJTvbe) =
|
||||
*(ckt->CKTstate1 + inst->NBJTvbe);
|
||||
*(ckt->CKTstate0 + inst->NBJTvce) =
|
||||
*(ckt->CKTstate1 + inst->NBJTvce);
|
||||
vbe = *(ckt->CKTstate1 + inst->NBJTvbe);
|
||||
vce = *(ckt->CKTstate1 + inst->NBJTvce);
|
||||
ONEsaveState(pDevice);
|
||||
delVbe = 0.0;
|
||||
delVce = 0.0;
|
||||
} else if ((ckt->CKTmode & MODEINITJCT) &&
|
||||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) {
|
||||
doInitSolve = TRUE;
|
||||
initStateName = inst->NBJTicFile;
|
||||
vbe = 0.0;
|
||||
vce = 0.0;
|
||||
delVbe = vbe;
|
||||
delVce = vce;
|
||||
} else if ((ckt->CKTmode & MODEINITJCT) && (inst->NBJToff == 0)) {
|
||||
doInitSolve = TRUE;
|
||||
initStateName = inst->NBJTicFile;
|
||||
vbe = inst->NBJTtype * 0.6;
|
||||
vce = inst->NBJTtype * 1.0;
|
||||
delVbe = vbe;
|
||||
delVce = vce;
|
||||
} else if (ckt->CKTmode & MODEINITJCT) {
|
||||
doInitSolve = TRUE;
|
||||
vbe = 0.0;
|
||||
vce = 0.0;
|
||||
delVbe = vbe;
|
||||
delVce = vce;
|
||||
} else if ((ckt->CKTmode & MODEINITFIX) && inst->NBJToff) {
|
||||
vbe = 0.0;
|
||||
vce = 0.0;
|
||||
delVbe = vbe;
|
||||
delVce = vce;
|
||||
} else {
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
*(ckt->CKTstate0 + inst->NBJTvbe) =
|
||||
*(ckt->CKTstate1 + inst->NBJTvbe);
|
||||
*(ckt->CKTstate0 + inst->NBJTvce) =
|
||||
*(ckt->CKTstate1 + inst->NBJTvce);
|
||||
*(ckt->CKTstate0 + inst->NBJTic) =
|
||||
*(ckt->CKTstate1 + inst->NBJTic);
|
||||
*(ckt->CKTstate0 + inst->NBJTie) =
|
||||
*(ckt->CKTstate1 + inst->NBJTie);
|
||||
*(ckt->CKTstate0 + inst->NBJTdIeDVce) =
|
||||
*(ckt->CKTstate1 + inst->NBJTdIeDVce);
|
||||
*(ckt->CKTstate0 + inst->NBJTdIeDVbe) =
|
||||
*(ckt->CKTstate1 + inst->NBJTdIeDVbe);
|
||||
*(ckt->CKTstate0 + inst->NBJTdIcDVce) =
|
||||
*(ckt->CKTstate1 + inst->NBJTdIcDVce);
|
||||
*(ckt->CKTstate0 + inst->NBJTdIcDVbe) =
|
||||
*(ckt->CKTstate1 + inst->NBJTdIcDVbe);
|
||||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) {
|
||||
/* no linear prediction on device voltages */
|
||||
vbe = *(ckt->CKTstate1 + inst->NBJTvbe);
|
||||
vce = *(ckt->CKTstate1 + inst->NBJTvce);
|
||||
ONEpredict(pDevice, model->NBJTpInfo);
|
||||
} else {
|
||||
if (doVoltPred) {
|
||||
/* linear prediction */
|
||||
xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1];
|
||||
vbe = (1+xfact) * (*(ckt->CKTstate1 + inst->NBJTvbe))
|
||||
- (xfact) * (*(ckt->CKTstate2 + inst->NBJTvbe));
|
||||
vce = (1+xfact) * (*(ckt->CKTstate1 + inst->NBJTvce))
|
||||
- (xfact) * (*(ckt->CKTstate2 + inst->NBJTvce));
|
||||
} else {
|
||||
vbe = *(ckt->CKTstate1 + inst->NBJTvbe);
|
||||
vce = *(ckt->CKTstate1 + inst->NBJTvce);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* compute new nonlinear branch voltages
|
||||
*/
|
||||
vbe = *(ckt->CKTrhsOld + inst->NBJTbaseNode) -
|
||||
*(ckt->CKTrhsOld + inst->NBJTemitNode);
|
||||
vce = *(ckt->CKTrhsOld + inst->NBJTcolNode) -
|
||||
*(ckt->CKTrhsOld + inst->NBJTemitNode);
|
||||
}
|
||||
delVbe = vbe - *(ckt->CKTstate0 + inst->NBJTvbe);
|
||||
delVce = vce - *(ckt->CKTstate0 + inst->NBJTvce);
|
||||
ichat = *(ckt->CKTstate0 + inst->NBJTic) -
|
||||
*(ckt->CKTstate0 + inst->NBJTdIcDVbe) * delVbe -
|
||||
*(ckt->CKTstate0 + inst->NBJTdIcDVce) * delVce;
|
||||
iehat = *(ckt->CKTstate0 + inst->NBJTie) -
|
||||
*(ckt->CKTstate0 + inst->NBJTdIeDVbe) * delVbe -
|
||||
*(ckt->CKTstate0 + inst->NBJTdIeDVce) * delVce;
|
||||
|
||||
#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(delVbe) < (ckt->CKTreltol * MAX(fabs(vbe),
|
||||
fabs(*(ckt->CKTstate0 + inst->NBJTvbe))) +
|
||||
ckt->CKTvoltTol)))
|
||||
if ((fabs(delVce) < ckt->CKTreltol * MAX(fabs(vce),
|
||||
fabs(*(ckt->CKTstate0 + inst->NBJTvce))) +
|
||||
ckt->CKTvoltTol))
|
||||
if ((fabs(ichat - *(ckt->CKTstate0 + inst->NBJTic)) <
|
||||
ckt->CKTreltol * MAX(fabs(ichat),
|
||||
fabs(*(ckt->CKTstate0 + inst->NBJTic))) +
|
||||
ckt->CKTabstol))
|
||||
if ((fabs(iehat - *(ckt->CKTstate0 + inst->NBJTie)) <
|
||||
ckt->CKTreltol * MAX(fabs(iehat),
|
||||
fabs(*(ckt->CKTstate0 + inst->NBJTie))) +
|
||||
ckt->CKTabstol)) {
|
||||
/*
|
||||
* bypassing....
|
||||
*/
|
||||
vbe = *(ckt->CKTstate0 + inst->NBJTvbe);
|
||||
vce = *(ckt->CKTstate0 + inst->NBJTvce);
|
||||
ic = *(ckt->CKTstate0 + inst->NBJTic);
|
||||
ie = *(ckt->CKTstate0 + inst->NBJTie);
|
||||
dIeDVce = *(ckt->CKTstate0 + inst->NBJTdIeDVce);
|
||||
dIeDVbe = *(ckt->CKTstate0 + inst->NBJTdIeDVbe);
|
||||
dIcDVce = *(ckt->CKTstate0 + inst->NBJTdIcDVce);
|
||||
dIcDVbe = *(ckt->CKTstate0 + inst->NBJTdIcDVbe);
|
||||
goto load;
|
||||
}
|
||||
#endif /* NOBYPASS */
|
||||
/*
|
||||
* limit nonlinear branch voltages
|
||||
*/
|
||||
icheck1 = 1;
|
||||
vbe = inst->NBJTtype * limitVbe(inst->NBJTtype * vbe,
|
||||
inst->NBJTtype * *(ckt->CKTstate0 + inst->NBJTvbe), &icheck);
|
||||
/*
|
||||
vbc = vbe - vce;
|
||||
vbc = inst->NBJTtype * limitVbe(inst->NBJTtype * vbc,
|
||||
inst->NBJTtype * (*(ckt->CKTstate0 + inst->NBJTvbe)
|
||||
- *(ckt->CKTstate0 + inst->NBJTvce)), &icheck1);
|
||||
vce = vbe - vbc;
|
||||
*/
|
||||
vce = inst->NBJTtype * limitVce(inst->NBJTtype * vce,
|
||||
inst->NBJTtype * *(ckt->CKTstate0 + inst->NBJTvce), &icheck1);
|
||||
if (icheck1 == 1)
|
||||
icheck = 1;
|
||||
delVbe = vbe - *(ckt->CKTstate0 + inst->NBJTvbe);
|
||||
delVce = vce - *(ckt->CKTstate0 + inst->NBJTvce);
|
||||
}
|
||||
if (doInitSolve) {
|
||||
if (ONEdcDebug) {
|
||||
printVoltages(stdout,
|
||||
model->NBJTmodName, inst->NBJTname,
|
||||
deviceType, 2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
startTime2 = SPfrontEnd->IFseconds();
|
||||
ONEequilSolve(pDevice);
|
||||
totalTime2 = SPfrontEnd->IFseconds() - startTime2;
|
||||
pDevice->pStats->totalTime[STAT_SETUP] += totalTime2;
|
||||
pDevice->pStats->totalTime[STAT_DC] -= totalTime2;
|
||||
|
||||
ONEbiasSolve(pDevice, MaxIterations, FALSE, NULL);
|
||||
|
||||
*(ckt->CKTstate0 + inst->NBJTvbe) = 0.0;
|
||||
*(ckt->CKTstate0 + inst->NBJTvce) = 0.0;
|
||||
|
||||
if (initStateName != NULL) {
|
||||
if (ONEreadState(pDevice, initStateName, 2, &vce, &vbe ) < 0) {
|
||||
fprintf(stderr,
|
||||
"NBJTload: trouble reading state-file %s\n", initStateName);
|
||||
} else {
|
||||
NBJTsetBCs(pDevice, vce, vbe);
|
||||
delVce = delVbe = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* determine dc current and derivatives using the numerical routines
|
||||
*/
|
||||
if (ckt->CKTmode & (MODEDCOP | MODETRANOP | MODEDCTRANCURVE | MODEINITSMSIG)) {
|
||||
|
||||
numDevNonCon = 0;
|
||||
inst->NBJTc11 = inst->NBJTy11r = inst->NBJTy11i = 0.0;
|
||||
inst->NBJTc12 = inst->NBJTy12r = inst->NBJTy12i = 0.0;
|
||||
inst->NBJTc21 = inst->NBJTy21r = inst->NBJTy21i = 0.0;
|
||||
inst->NBJTc22 = inst->NBJTy22r = inst->NBJTy22i = 0.0;
|
||||
inst->NBJTsmSigAvail = FALSE;
|
||||
devNonCon:
|
||||
NBJTproject(pDevice, delVce, delVbe, vbe);
|
||||
if (ONEdcDebug) {
|
||||
printVoltages(stdout,
|
||||
model->NBJTmodName, inst->NBJTname,
|
||||
deviceType, 2, vce, delVce, vbe, delVbe, 0.0, 0.0);
|
||||
}
|
||||
ONEbiasSolve(pDevice, MaxIterations, FALSE, model->NBJTpInfo);
|
||||
|
||||
devConverged = pDevice->converged;
|
||||
if (devConverged && finite(pDevice->rhsNorm)) {
|
||||
/* compute the currents */
|
||||
NBJTcurrent(pDevice, FALSE, (double *) NULL,
|
||||
&ie, &ic);
|
||||
NBJTconductance(pDevice, FALSE, (double *) NULL,
|
||||
&dIeDVce, &dIcDVce, &dIeDVbe, &dIcDVbe);
|
||||
/*
|
||||
* Add Gmin terms to everything in case we are operating at
|
||||
* abnormally low current levels
|
||||
*/
|
||||
ie += ckt->CKTgmin * (vce + vbe);
|
||||
dIeDVce += ckt->CKTgmin;
|
||||
dIeDVbe += ckt->CKTgmin;
|
||||
ic += ckt->CKTgmin * (2.0 * vce - vbe);
|
||||
dIcDVce += 2.0 * ckt->CKTgmin;
|
||||
dIcDVbe -= ckt->CKTgmin;
|
||||
|
||||
} else {
|
||||
/* reduce the voltage step until converged */
|
||||
/* restore the boundary potential to previous value */
|
||||
NBJTsetBCs(pDevice, vce - delVce, vbe - delVbe);
|
||||
ONEstoreInitialGuess(pDevice);
|
||||
ONEresetJacobian(pDevice);
|
||||
delVbe *= 0.5;
|
||||
delVce *= 0.5;
|
||||
vbe = delVbe + *(ckt->CKTstate0 + inst->NBJTvbe);
|
||||
vce = delVce + *(ckt->CKTstate0 + inst->NBJTvce);
|
||||
numDevNonCon++;
|
||||
icheck = 1;
|
||||
if (numDevNonCon > 10) {
|
||||
printVoltages(stderr,
|
||||
model->NBJTmodName, inst->NBJTname,
|
||||
deviceType, 2, vce, delVce, vbe, delVbe, 0.0, 0.0);
|
||||
fprintf(stderr,
|
||||
"*** Non-convergence during load ***\n");
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
return (E_BADMATRIX);
|
||||
} else {
|
||||
goto devNonCon;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if ((ckt->CKTmode & (MODETRAN | MODEAC)) ||
|
||||
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) ||
|
||||
(ckt->CKTmode & MODEINITSMSIG)) {
|
||||
/*
|
||||
* store small-signal parameters
|
||||
*/
|
||||
if ((!(ckt->CKTmode & MODETRANOP)) ||
|
||||
(!(ckt->CKTmode & MODEUIC))) {
|
||||
if (ckt->CKTmode & MODEINITSMSIG) {
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
startTime2 = SPfrontEnd->IFseconds();
|
||||
NBJTinitSmSig(inst);
|
||||
pDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime2;
|
||||
continue;
|
||||
} else {
|
||||
inst->NBJTsmSigAvail = FALSE;
|
||||
}
|
||||
/*
|
||||
* transient analysis
|
||||
*/
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
NBJTsetBCs(pDevice, vce, vbe);
|
||||
ONEstoreInitialGuess(pDevice);
|
||||
} else {
|
||||
NBJTupdate(pDevice, delVce, delVbe, vbe, TRUE);
|
||||
}
|
||||
if (ONEtranDebug) {
|
||||
printVoltages(stdout,
|
||||
model->NBJTmodName, inst->NBJTname,
|
||||
deviceType, 2, vce, delVce, vbe, delVbe, 0.0, 0.0);
|
||||
}
|
||||
ONEbiasSolve(pDevice, 0, TRUE, model->NBJTpInfo);
|
||||
if (!finite(pDevice->rhsNorm)) {
|
||||
/* Timestep took us to never-never land. */
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
return (E_BADMATRIX);
|
||||
}
|
||||
devConverged = ONEdeviceConverged(pDevice);
|
||||
pDevice->converged = devConverged;
|
||||
|
||||
/* compute the currents */
|
||||
NBJTcurrent(pDevice, TRUE,
|
||||
model->NBJTpInfo->intCoeff, &ie, &ic);
|
||||
NBJTconductance(pDevice, TRUE,
|
||||
model->NBJTpInfo->intCoeff,
|
||||
&dIeDVce, &dIcDVce, &dIeDVbe, &dIcDVbe);
|
||||
|
||||
/*
|
||||
* Add Gmin terms to everything in case we are operating at
|
||||
* abnormally low current levels
|
||||
*/
|
||||
ie += ckt->CKTgmin * (vce + vbe);
|
||||
dIeDVce += ckt->CKTgmin;
|
||||
dIeDVbe += ckt->CKTgmin;
|
||||
ic += ckt->CKTgmin * (2.0 * vce - vbe);
|
||||
dIcDVce += 2.0 * ckt->CKTgmin;
|
||||
dIcDVbe -= ckt->CKTgmin;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check convergence
|
||||
*/
|
||||
if ((!(ckt->CKTmode & MODEINITFIX)) || (!(inst->NBJToff))) {
|
||||
if (icheck == 1 || !devConverged) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
} else {
|
||||
tol = ckt->CKTreltol * MAX(fabs(ichat), fabs(ic)) + ckt->CKTabstol;
|
||||
if (fabs(ichat - ic) > tol) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
} else {
|
||||
tol = ckt->CKTreltol * MAX(fabs(iehat), fabs(ie)) +
|
||||
ckt->CKTabstol;
|
||||
if (fabs(iehat - ie) > tol) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*(ckt->CKTstate0 + inst->NBJTvbe) = vbe;
|
||||
*(ckt->CKTstate0 + inst->NBJTvce) = vce;
|
||||
*(ckt->CKTstate0 + inst->NBJTic) = ic;
|
||||
*(ckt->CKTstate0 + inst->NBJTie) = ie;
|
||||
*(ckt->CKTstate0 + inst->NBJTdIeDVce) = dIeDVce;
|
||||
*(ckt->CKTstate0 + inst->NBJTdIeDVbe) = dIeDVbe;
|
||||
*(ckt->CKTstate0 + inst->NBJTdIcDVce) = dIcDVce;
|
||||
*(ckt->CKTstate0 + inst->NBJTdIcDVbe) = dIcDVbe;
|
||||
|
||||
load:
|
||||
/*
|
||||
* load current excitation vector
|
||||
*/
|
||||
iceq = ic - dIcDVce * vce - dIcDVbe * vbe;
|
||||
ieeq = ie - dIeDVce * vce - dIeDVbe * vbe;
|
||||
*(ckt->CKTrhs + inst->NBJTcolNode) -= iceq;
|
||||
*(ckt->CKTrhs + inst->NBJTbaseNode) -= ieeq - iceq;
|
||||
*(ckt->CKTrhs + inst->NBJTemitNode) += ieeq;
|
||||
|
||||
/*
|
||||
* load y matrix
|
||||
*/
|
||||
*(inst->NBJTcolColPtr) += dIcDVce;
|
||||
*(inst->NBJTcolBasePtr) += dIcDVbe;
|
||||
*(inst->NBJTcolEmitPtr) -= dIcDVbe + dIcDVce;
|
||||
*(inst->NBJTbaseColPtr) -= dIcDVce - dIeDVce;
|
||||
*(inst->NBJTbaseBasePtr) -= dIcDVbe - dIeDVbe;
|
||||
*(inst->NBJTbaseEmitPtr) += dIcDVbe + dIcDVce - dIeDVbe - dIeDVce;
|
||||
*(inst->NBJTemitColPtr) -= dIeDVce;
|
||||
*(inst->NBJTemitBasePtr) -= dIeDVbe;
|
||||
*(inst->NBJTemitEmitPtr) += dIeDVbe + dIeDVce;
|
||||
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
if (ckt->CKTmode & MODETRAN) {
|
||||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime;
|
||||
} else {
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
||||
int
|
||||
NBJTinitSmSig(inst)
|
||||
NBJTinstance *inst;
|
||||
{
|
||||
SPcomplex yIeVce, yIeVbe;
|
||||
SPcomplex yIcVce, yIcVbe;
|
||||
double omega = inst->NBJTmodPtr->NBJTmethods->METHomega;
|
||||
|
||||
AcAnalysisMethod = SOR_ONLY;
|
||||
(void) NBJTadmittance(inst->NBJTpDevice, omega,
|
||||
&yIeVce, &yIcVce, &yIeVbe, &yIcVbe);
|
||||
inst->NBJTc11 = yIcVce.imag / omega;
|
||||
inst->NBJTc12 = yIcVbe.imag / omega;
|
||||
inst->NBJTc21 = (yIeVce.imag - yIcVce.imag) / omega;
|
||||
inst->NBJTc22 = (yIeVbe.imag - yIcVbe.imag) / omega;
|
||||
inst->NBJTy11r = yIcVce.real;
|
||||
inst->NBJTy11i = yIcVce.imag;
|
||||
inst->NBJTy12r = yIcVbe.real;
|
||||
inst->NBJTy12i = yIcVbe.imag;
|
||||
inst->NBJTy21r = yIeVce.real - yIcVce.real;
|
||||
inst->NBJTy21i = yIeVce.imag - yIcVce.imag;
|
||||
inst->NBJTy22r = yIeVbe.real - yIcVbe.real;
|
||||
inst->NBJTy22i = yIeVbe.imag - yIcVbe.imag;
|
||||
inst->NBJTsmSigAvail = TRUE;
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine deletes a NBJT model from the circuit and frees the storage
|
||||
* it was using. returns an error if the model has instances
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NBJTmDelete(inModel, modname, kill)
|
||||
GENmodel **inModel;
|
||||
IFuid modname;
|
||||
GENmodel *kill;
|
||||
|
||||
{
|
||||
|
||||
NBJTmodel **model = (NBJTmodel **) inModel;
|
||||
NBJTmodel *modfast = (NBJTmodel *) kill;
|
||||
NBJTmodel **oldmod;
|
||||
oldmod = model;
|
||||
for (; *model; model = &((*model)->NBJTnextModel)) {
|
||||
if ((*model)->NBJTmodName == modname ||
|
||||
(modfast && *model == modfast))
|
||||
goto delgot;
|
||||
oldmod = model;
|
||||
}
|
||||
return (E_NOMOD);
|
||||
|
||||
delgot:
|
||||
if ((*model)->NBJTinstances)
|
||||
return (E_NOTEMPTY);
|
||||
*oldmod = (*model)->NBJTnextModel; /* cut deleted device out of list */
|
||||
FREE(*model);
|
||||
return (OK);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine sets model parameters for NBJTs in the circuit.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NBJTmParam(param, value, inModel)
|
||||
int param;
|
||||
IFvalue *value;
|
||||
GENmodel *inModel;
|
||||
{
|
||||
switch (param) {
|
||||
case NBJT_MOD_NBJT:
|
||||
/* no action - already know it is a numerical bjt, but this */
|
||||
/* makes life easier for spice-2 like parsers */
|
||||
break;
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine sets instance parameters for NBJTs in the circuit.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NBJTparam(param, value, inInst, select)
|
||||
int param;
|
||||
IFvalue *value;
|
||||
GENinstance *inInst;
|
||||
IFvalue *select;
|
||||
{
|
||||
register NBJTinstance *inst = (NBJTinstance *) inInst;
|
||||
switch (param) {
|
||||
case NBJT_AREA:
|
||||
inst->NBJTarea = value->rValue;
|
||||
inst->NBJTareaGiven = TRUE;
|
||||
break;
|
||||
case NBJT_OFF:
|
||||
inst->NBJToff = TRUE;
|
||||
break;
|
||||
case NBJT_IC_FILE:
|
||||
inst->NBJTicFile = value->sValue;
|
||||
inst->NBJTicFileGiven = TRUE;
|
||||
break;
|
||||
case NBJT_PRINT:
|
||||
inst->NBJTprint = value->rValue;
|
||||
inst->NBJTprintGiven = TRUE;
|
||||
break;
|
||||
case NBJT_TEMP:
|
||||
inst->NBJTtemp = value->rValue + CONSTCtoK;
|
||||
inst->NBJTtempGiven = TRUE;
|
||||
break;
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* Function to load the COMPLEX circuit matrix using the small signal
|
||||
* parameters saved during a previous DC operating point analysis.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "sperror.h"
|
||||
#include "complex.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* External Declarations */
|
||||
extern int ONEacDebug;
|
||||
|
||||
int
|
||||
NBJTpzLoad(inModel, ckt, s)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
SPcomplex *s;
|
||||
|
||||
{
|
||||
register NBJTmodel *model = (NBJTmodel *) inModel;
|
||||
register NBJTinstance *inst;
|
||||
SPcomplex yIeVce, yIeVbe;
|
||||
SPcomplex yIcVce, yIcVbe;
|
||||
double startTime;
|
||||
|
||||
for (; model != NULL; model = model->NBJTnextModel) {
|
||||
FieldDepMobility = model->NBJTmodels->MODLfieldDepMobility;
|
||||
Srh = model->NBJTmodels->MODLsrh;
|
||||
Auger = model->NBJTmodels->MODLauger;
|
||||
AvalancheGen = model->NBJTmodels->MODLavalancheGen;
|
||||
AcAnalysisMethod = model->NBJTmethods->METHacAnalysisMethod;
|
||||
MobDeriv = model->NBJTmethods->METHmobDeriv;
|
||||
ONEacDebug = model->NBJToutputs->OUTPacDebug;
|
||||
|
||||
for (inst = model->NBJTinstances; inst != NULL;
|
||||
inst = inst->NBJTnextInstance) {
|
||||
if (inst->NBJTowner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NBJTglobals));
|
||||
|
||||
NBJTys(inst->NBJTpDevice, s,
|
||||
&yIeVce, &yIcVce, &yIeVbe, &yIcVbe);
|
||||
|
||||
if (ONEacDebug) {
|
||||
fprintf(stdout, "BJT admittances: %s:%s at s = % .5g, % .5g\n",
|
||||
model->NBJTmodName, inst->NBJTname, s->real, s->imag);
|
||||
fprintf(stdout, "Ycc: % .5g,% .5g\n",
|
||||
yIcVce.real, yIcVce.imag);
|
||||
fprintf(stdout, "Ycb: % .5g,% .5g\n",
|
||||
yIcVbe.real, yIcVbe.imag);
|
||||
fprintf(stdout, "Ybc: % .5g,% .5g\n",
|
||||
yIeVce.real - yIcVce.real, yIeVce.imag - yIcVce.imag);
|
||||
fprintf(stdout, "Ybb: % .5g,% .5g\n",
|
||||
yIeVbe.real - yIcVbe.real, yIeVbe.imag - yIcVbe.imag);
|
||||
}
|
||||
*(inst->NBJTcolColPtr) += yIcVce.real;
|
||||
*(inst->NBJTcolColPtr + 1) += yIcVce.imag;
|
||||
*(inst->NBJTcolBasePtr) += yIcVbe.real;
|
||||
*(inst->NBJTcolBasePtr + 1) += yIcVbe.imag;
|
||||
*(inst->NBJTcolEmitPtr) -= yIcVbe.real + yIcVce.real;
|
||||
*(inst->NBJTcolEmitPtr + 1) -= yIcVbe.imag + yIcVce.imag;
|
||||
*(inst->NBJTbaseColPtr) -= yIcVce.real - yIeVce.real;
|
||||
*(inst->NBJTbaseColPtr + 1) -= yIcVce.imag - yIeVce.imag;
|
||||
*(inst->NBJTbaseBasePtr) -= yIcVbe.real - yIeVbe.real;
|
||||
*(inst->NBJTbaseBasePtr + 1) -= yIcVbe.imag - yIeVbe.imag;
|
||||
*(inst->NBJTbaseEmitPtr) += yIcVbe.real + yIcVce.real - yIeVbe.real - yIeVce.real;
|
||||
*(inst->NBJTbaseEmitPtr + 1) += yIcVbe.imag + yIcVce.imag - yIeVbe.imag - yIeVce.imag;
|
||||
*(inst->NBJTemitColPtr) -= yIeVce.real;
|
||||
*(inst->NBJTemitColPtr + 1) -= yIeVce.imag;
|
||||
*(inst->NBJTemitBasePtr) -= yIeVbe.real;
|
||||
*(inst->NBJTemitBasePtr + 1) -= yIeVbe.imag;
|
||||
*(inst->NBJTemitEmitPtr) += yIeVbe.real + yIeVce.real;
|
||||
*(inst->NBJTemitEmitPtr + 1) += yIeVbe.imag + yIeVce.imag;
|
||||
|
||||
inst->NBJTpDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,255 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "smpdefs.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "numconst.h"
|
||||
#include "numenum.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "ciderinp.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#define NIL(type) ((type *)0)
|
||||
#define TSCALLOC(var, size, type)\
|
||||
if (size && (!(var =(type *)calloc(1, (unsigned)(size)*sizeof(type))))) {\
|
||||
return(E_NOMEM);\
|
||||
}
|
||||
|
||||
int
|
||||
NBJTsetup(matrix, inModel, ckt, states)
|
||||
register SMPmatrix *matrix;
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
int *states;
|
||||
/*
|
||||
* load the diode structure with those pointers needed later for fast matrix
|
||||
* loading
|
||||
*/
|
||||
{
|
||||
register NBJTmodel *model = (NBJTmodel *) inModel;
|
||||
register NBJTinstance *inst;
|
||||
METHcard *methods;
|
||||
MODLcard *models;
|
||||
OPTNcard *options;
|
||||
OUTPcard *outputs;
|
||||
char *icFileName = NULL;
|
||||
int nameLen;
|
||||
int error;
|
||||
int xMeshSize;
|
||||
ONEdevice *pDevice;
|
||||
ONEcoord *xCoordList = NIL(ONEcoord);
|
||||
ONEdomain *domainList = NIL(ONEdomain);
|
||||
DOPprofile *profileList = NIL(DOPprofile);
|
||||
DOPtable *dopTableList = NIL(DOPtable);
|
||||
ONEmaterial *pM, *pMaterial = NULL, *materialList = NIL(ONEmaterial);
|
||||
double startTime;
|
||||
|
||||
|
||||
/* loop through all the diode models */
|
||||
for (; model != NULL; model = model->NBJTnextModel) {
|
||||
if (!model->NBJTpInfo) {
|
||||
TSCALLOC(model->NBJTpInfo, 1, ONEtranInfo);
|
||||
}
|
||||
methods = model->NBJTmethods;
|
||||
if (!methods) {
|
||||
TSCALLOC(methods, 1, METHcard);
|
||||
model->NBJTmethods = methods;
|
||||
}
|
||||
models = model->NBJTmodels;
|
||||
if (!models) {
|
||||
TSCALLOC(models, 1, MODLcard);
|
||||
model->NBJTmodels = models;
|
||||
}
|
||||
options = model->NBJToptions;
|
||||
if (!options) {
|
||||
TSCALLOC(options, 1, OPTNcard);
|
||||
model->NBJToptions = options;
|
||||
}
|
||||
outputs = model->NBJToutputs;
|
||||
if (!outputs) {
|
||||
TSCALLOC(outputs, 1, OUTPcard);
|
||||
model->NBJToutputs = outputs;
|
||||
}
|
||||
if (!methods->METHvoltPredGiven) {
|
||||
methods->METHvoltPred = FALSE;
|
||||
}
|
||||
if (!methods->METHmobDerivGiven) {
|
||||
methods->METHmobDeriv = TRUE;
|
||||
}
|
||||
if (!methods->METHoneCarrierGiven) {
|
||||
methods->METHoneCarrier = FALSE;
|
||||
}
|
||||
if (!methods->METHacAnalysisMethodGiven) {
|
||||
methods->METHacAnalysisMethod = SOR;
|
||||
}
|
||||
if (!methods->METHdabstolGiven) {
|
||||
methods->METHdabstol = DABSTOL1D;
|
||||
}
|
||||
if (!methods->METHdreltolGiven) {
|
||||
methods->METHdreltol = ckt->CKTreltol;
|
||||
}
|
||||
if (!methods->METHitLimGiven) {
|
||||
methods->METHitLim = 20;
|
||||
}
|
||||
if (!methods->METHomegaGiven || methods->METHomega <= 0.0) {
|
||||
methods->METHomega = 2.0 * M_PI /* radians/sec */ ;
|
||||
}
|
||||
if (!options->OPTNdefaGiven || options->OPTNdefa <= 0.0) {
|
||||
options->OPTNdefa = 1.0e4 /* cm^2 */ ;
|
||||
}
|
||||
if (!options->OPTNbaseLengthGiven) {
|
||||
options->OPTNbaseLength = 0.0;
|
||||
}
|
||||
if (!options->OPTNbaseAreaGiven) {
|
||||
options->OPTNbaseArea = 1.0;
|
||||
}
|
||||
if (!options->OPTNdeviceTypeGiven) {
|
||||
options->OPTNdeviceType = OPTN_BIPOLAR;
|
||||
}
|
||||
if (!options->OPTNicFileGiven) {
|
||||
options->OPTNicFile = NULL;
|
||||
options->OPTNunique = FALSE; /* Can't form a unique name. */
|
||||
}
|
||||
if (!options->OPTNuniqueGiven) {
|
||||
options->OPTNunique = FALSE;
|
||||
}
|
||||
|
||||
/* Set up the rest of the card lists */
|
||||
if ((error = MODLsetup(model->NBJTmodels)))
|
||||
return (error);
|
||||
BandGapNarrowing = models->MODLbandGapNarrowing;
|
||||
ConcDepLifetime = models->MODLconcDepLifetime;
|
||||
TempDepMobility = models->MODLtempDepMobility;
|
||||
ConcDepMobility = models->MODLconcDepMobility;
|
||||
|
||||
if ((error = OUTPsetup(model->NBJToutputs)))
|
||||
return (error);
|
||||
if ((error = MATLsetup(model->NBJTmaterials, &materialList)))
|
||||
return (error);
|
||||
if ((error = MOBsetup(model->NBJTmobility, materialList)))
|
||||
return (error);
|
||||
if ((error = MESHsetup('x', model->NBJTxMeshes, &xCoordList, &xMeshSize)))
|
||||
return (error);
|
||||
if ((error = DOMNsetup(model->NBJTdomains, &domainList,
|
||||
xCoordList, NIL(ONEcoord), materialList)))
|
||||
return (error);
|
||||
if ((error = BDRYsetup(model->NBJTboundaries,
|
||||
xCoordList, NIL(ONEcoord), domainList)))
|
||||
return (error);
|
||||
if ((error = CONTsetup(model->NBJTcontacts, NULL)))
|
||||
return (error);
|
||||
if ((error = DOPsetup(model->NBJTdopings, &profileList,
|
||||
&dopTableList, xCoordList, NIL(ONEcoord))))
|
||||
return (error);
|
||||
model->NBJTmatlInfo = materialList;
|
||||
model->NBJTprofiles = profileList;
|
||||
model->NBJTdopTables = dopTableList;
|
||||
|
||||
/* loop through all the instances of the model */
|
||||
for (inst = model->NBJTinstances; inst != NULL;
|
||||
inst = inst->NBJTnextInstance) {
|
||||
if (inst->NBJTowner != ARCHme) goto matrixpointers;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
if (!inst->NBJTprintGiven) {
|
||||
inst->NBJTprint = 0;
|
||||
} else if (inst->NBJTprint <= 0) {
|
||||
inst->NBJTprint = 1;
|
||||
}
|
||||
if (!inst->NBJTicFileGiven) {
|
||||
if (options->OPTNunique) {
|
||||
nameLen = strlen(options->OPTNicFile) + strlen(inst->NBJTname) + 1;
|
||||
TSCALLOC(icFileName, nameLen+1, char);
|
||||
sprintf(icFileName, "%s.%s", options->OPTNicFile, inst->NBJTname);
|
||||
icFileName[nameLen] = '\0';
|
||||
inst->NBJTicFile = icFileName;
|
||||
} else if (options->OPTNicFile != NULL) {
|
||||
nameLen = strlen(options->OPTNicFile);
|
||||
TSCALLOC(icFileName, nameLen+1, char);
|
||||
icFileName = strcpy(icFileName, options->OPTNicFile);
|
||||
inst->NBJTicFile = icFileName;
|
||||
} else {
|
||||
inst->NBJTicFile = NULL;
|
||||
}
|
||||
}
|
||||
inst->NBJTstate = *states;
|
||||
*states += NBJTnumStates;
|
||||
|
||||
if (!inst->NBJTpDevice) {
|
||||
/* Assign the mesh info to each instance. */
|
||||
TSCALLOC(pDevice, 1, ONEdevice);
|
||||
TSCALLOC(pDevice->pStats, 1, ONEstats);
|
||||
pDevice->name = inst->NBJTname;
|
||||
pDevice->solverType = SLV_NONE;
|
||||
pDevice->numNodes = xMeshSize;
|
||||
pDevice->abstol = methods->METHdabstol;
|
||||
pDevice->reltol = methods->METHdreltol;
|
||||
pDevice->rhsImag = NIL(double);
|
||||
TSCALLOC(pDevice->elemArray, pDevice->numNodes, ONEelem *);
|
||||
|
||||
/* Create a copy of material data that can change with temperature. */
|
||||
pDevice->pMaterials = NIL(ONEmaterial);
|
||||
for (pM = materialList; pM != NIL(ONEmaterial); pM = pM->next) {
|
||||
if (pDevice->pMaterials == NIL(ONEmaterial)) {
|
||||
TSCALLOC(pMaterial, 1, ONEmaterial);
|
||||
pDevice->pMaterials = pMaterial;
|
||||
} else {
|
||||
TSCALLOC(pMaterial->next, 1, ONEmaterial);
|
||||
pMaterial = pMaterial->next;
|
||||
}
|
||||
/* Copy everything, then fix the incorrect pointer. */
|
||||
bcopy((char *) pM, (char *) pMaterial, sizeof(ONEmaterial));
|
||||
pMaterial->next = NIL(ONEmaterial);
|
||||
}
|
||||
|
||||
/* generate the mesh structure for the device */
|
||||
ONEbuildMesh(pDevice, xCoordList, domainList, pDevice->pMaterials);
|
||||
|
||||
if (options->OPTNbaseDepthGiven) {
|
||||
/* The base contact depth has been specified in the input. */
|
||||
pDevice->baseIndex = MESHlocate(xCoordList, options->OPTNbaseDepth);
|
||||
} else {
|
||||
pDevice->baseIndex = -1; /* Invalid index acts as a flag */
|
||||
}
|
||||
/* store the device info in the instance */
|
||||
inst->NBJTpDevice = pDevice;
|
||||
}
|
||||
/* Now update the state pointers. */
|
||||
ONEgetStatePointers(inst->NBJTpDevice, states);
|
||||
|
||||
/* Wipe out statistics from previous runs (if any). */
|
||||
bzero((char *) inst->NBJTpDevice->pStats, sizeof(ONEstats));
|
||||
|
||||
inst->NBJTpDevice->pStats->totalTime[STAT_SETUP] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
|
||||
/* macro to make elements with built in test for out of memory */
|
||||
#define TSTALLOC(ptr,first,second) \
|
||||
if ((inst->ptr = SMPmakeElt(matrix,inst->first,inst->second))==(double *)NULL){\
|
||||
return(E_NOMEM);\
|
||||
}
|
||||
|
||||
matrixpointers:
|
||||
TSTALLOC(NBJTcolColPtr, NBJTcolNode, NBJTcolNode)
|
||||
TSTALLOC(NBJTbaseBasePtr, NBJTbaseNode, NBJTbaseNode)
|
||||
TSTALLOC(NBJTemitEmitPtr, NBJTemitNode, NBJTemitNode)
|
||||
TSTALLOC(NBJTcolBasePtr, NBJTcolNode, NBJTbaseNode)
|
||||
TSTALLOC(NBJTcolEmitPtr, NBJTcolNode, NBJTemitNode)
|
||||
TSTALLOC(NBJTbaseColPtr, NBJTbaseNode, NBJTcolNode)
|
||||
TSTALLOC(NBJTbaseEmitPtr, NBJTbaseNode, NBJTemitNode)
|
||||
TSTALLOC(NBJTemitColPtr, NBJTemitNode, NBJTcolNode)
|
||||
TSTALLOC(NBJTemitBasePtr, NBJTemitNode, NBJTbaseNode)
|
||||
}
|
||||
/* Clean up lists */
|
||||
killCoordInfo(xCoordList);
|
||||
killDomainInfo(domainList);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
Author: 1992 David A. Gates, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "numenum.h"
|
||||
#include "carddefs.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#define NIL(type) ((type *)0)
|
||||
extern int ONEdcDebug;
|
||||
extern double LNorm;
|
||||
|
||||
int
|
||||
NBJTtemp(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
register CKTcircuit *ckt;
|
||||
/*
|
||||
* perform the temperature update to the bjt
|
||||
*/
|
||||
{
|
||||
register NBJTmodel *model = (NBJTmodel *) inModel;
|
||||
register NBJTinstance *inst;
|
||||
METHcard *methods;
|
||||
MODLcard *models;
|
||||
OPTNcard *options;
|
||||
OUTPcard *outputs;
|
||||
ONEmaterial *pM, *pMaterial, *pNextMaterial;
|
||||
ONEdevice *pDevice;
|
||||
double startTime;
|
||||
int baseIndex, indexBE, indexBC;
|
||||
|
||||
|
||||
/* loop through all the bjt models */
|
||||
for (; model != NULL; model = model->NBJTnextModel) {
|
||||
methods = model->NBJTmethods;
|
||||
models = model->NBJTmodels;
|
||||
options = model->NBJToptions;
|
||||
outputs = model->NBJToutputs;
|
||||
|
||||
if (!options->OPTNtnomGiven) {
|
||||
options->OPTNtnom = ckt->CKTnomTemp;
|
||||
}
|
||||
for (pM = model->NBJTmatlInfo; pM != NIL(ONEmaterial); pM = pM->next) {
|
||||
pM->tnom = options->OPTNtnom;
|
||||
}
|
||||
|
||||
BandGapNarrowing = models->MODLbandGapNarrowing;
|
||||
ConcDepLifetime = models->MODLconcDepLifetime;
|
||||
TempDepMobility = models->MODLtempDepMobility;
|
||||
ConcDepMobility = models->MODLconcDepMobility;
|
||||
|
||||
for (inst = model->NBJTinstances; inst != NULL;
|
||||
inst = inst->NBJTnextInstance) {
|
||||
if (inst->NBJTowner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
if (!inst->NBJTtempGiven) {
|
||||
inst->NBJTtemp = ckt->CKTtemp;
|
||||
}
|
||||
if (!inst->NBJTareaGiven || inst->NBJTarea <= 0.0) {
|
||||
inst->NBJTarea = 1.0;
|
||||
}
|
||||
inst->NBJTpDevice->area = inst->NBJTarea * options->OPTNdefa;
|
||||
|
||||
/* Compute and save globals for this instance. */
|
||||
GLOBcomputeGlobals(&(inst->NBJTglobals), inst->NBJTtemp);
|
||||
|
||||
/* Calculate new sets of material parameters. */
|
||||
pM = model->NBJTmatlInfo;
|
||||
pMaterial = inst->NBJTpDevice->pMaterials;
|
||||
for (; pM != NULL; pM = pM->next, pMaterial = pMaterial->next) {
|
||||
|
||||
/* Copy the original values, then fix the incorrect pointer. */
|
||||
pNextMaterial = pMaterial->next;
|
||||
bcopy((char *) pM, (char *) pMaterial, sizeof(ONEmaterial));
|
||||
pMaterial->next = pNextMaterial;
|
||||
|
||||
/* Now do the temperature dependence. */
|
||||
MATLtempDep(pMaterial, pMaterial->tnom);
|
||||
if (outputs->OUTPmaterial) {
|
||||
printMaterialInfo(pMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign doping to the mesh. */
|
||||
ONEsetDoping(inst->NBJTpDevice, model->NBJTprofiles,
|
||||
model->NBJTdopTables);
|
||||
|
||||
/* Assign other physical parameters to the mesh. */
|
||||
ONEsetup(inst->NBJTpDevice);
|
||||
|
||||
/* Assign boundary condition parameters. */
|
||||
ONEsetBCparams(inst->NBJTpDevice, model->NBJTboundaries,
|
||||
model->NBJTcontacts);
|
||||
|
||||
/* Normalize everything. */
|
||||
ONEnormalize(inst->NBJTpDevice);
|
||||
|
||||
/* Find the device's type. */
|
||||
if (inst->NBJTpDevice->elemArray[1]->pNodes[0]->netConc < 0.0) {
|
||||
inst->NBJTtype = PNP;
|
||||
} else {
|
||||
inst->NBJTtype = NPN;
|
||||
}
|
||||
|
||||
/* Find the location of the base index. */
|
||||
pDevice = inst->NBJTpDevice;
|
||||
baseIndex = pDevice->baseIndex;
|
||||
if (baseIndex <= 0) {
|
||||
if (options->OPTNbaseDepthGiven) {
|
||||
printf("Warning: base contact not on node -- adjusting contact\n");
|
||||
}
|
||||
NBJTjunctions(pDevice, &indexBE, &indexBC);
|
||||
pDevice->baseIndex = 0.5 * (indexBE + indexBC);
|
||||
}
|
||||
if (inst->NBJTtype == PNP) {
|
||||
pDevice->elemArray[pDevice->baseIndex]->pNodes[0]->baseType = N_TYPE;
|
||||
} else if (inst->NBJTtype == NPN) {
|
||||
pDevice->elemArray[pDevice->baseIndex]->pNodes[0]->baseType = P_TYPE;
|
||||
} else {
|
||||
printf("NBJTtemp: unknown BJT type \n");
|
||||
}
|
||||
if (baseIndex <= 0 && !options->OPTNbaseDepthGiven) {
|
||||
ONEdcDebug = FALSE;
|
||||
ONEequilSolve(pDevice);
|
||||
adjustBaseContact(pDevice, indexBE, indexBC);
|
||||
}
|
||||
printf("BJT: base contact depth is %g um at node %d\n",
|
||||
pDevice->elemArray[pDevice->baseIndex]->pNodes[0]->x * 1e4,
|
||||
pDevice->baseIndex);
|
||||
|
||||
/* Find, normalize and convert to reciprocal-form the base length. */
|
||||
pDevice->baseLength = options->OPTNbaseLength;
|
||||
if (pDevice->baseLength > 0.0) {
|
||||
pDevice->baseLength /= LNorm;
|
||||
pDevice->baseLength = 1.0 / pDevice->baseLength;
|
||||
} else if (pDevice->elemArray[pDevice->baseIndex]->evalNodes[0]) {
|
||||
pDevice->baseLength = pDevice->elemArray[pDevice->baseIndex]->rDx;
|
||||
} else {
|
||||
pDevice->baseLength = pDevice->elemArray[pDevice->baseIndex - 1]->rDx;
|
||||
}
|
||||
/* Adjust reciprocal base length to account for base area factor */
|
||||
pDevice->baseLength *= options->OPTNbaseArea;
|
||||
|
||||
inst->NBJTpDevice->pStats->totalTime[STAT_SETUP] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine performs truncation error calculations for NBJTs in the
|
||||
* circuit.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "nbjtdefs.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
|
||||
int
|
||||
NBJTtrunc(inModel, ckt, timeStep)
|
||||
GENmodel *inModel;
|
||||
register CKTcircuit *ckt;
|
||||
double *timeStep;
|
||||
|
||||
{
|
||||
register NBJTmodel *model = (NBJTmodel *) inModel;
|
||||
register NBJTinstance *inst;
|
||||
double deltaNew;
|
||||
double deltaNorm[7];
|
||||
double startTime;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
for (; model != NULL; model = model->NBJTnextModel) {
|
||||
model->NBJTpInfo->order = ckt->CKTorder;
|
||||
model->NBJTpInfo->delta = deltaNorm;
|
||||
model->NBJTpInfo->lteCoeff = computeLTECoeff(model->NBJTpInfo);
|
||||
for (inst = model->NBJTinstances; inst != NULL;
|
||||
inst = inst->NBJTnextInstance) {
|
||||
if (inst->NBJTowner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
deltaNew = ONEtrunc(inst->NBJTpDevice, model->NBJTpInfo,
|
||||
ckt->CKTdelta);
|
||||
*timeStep = MIN(*timeStep, deltaNew);
|
||||
inst->NBJTpDevice->pStats->totalTime[STAT_TRAN] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
noinst_LIBRARIES = libnbjt2.a
|
||||
|
||||
libnbjt2_a_SOURCES = \
|
||||
nbt2.c \
|
||||
nbt2acld.c \
|
||||
nbt2ask.c \
|
||||
nbjt2defs.h \
|
||||
nbt2del.c \
|
||||
nbt2dest.c \
|
||||
nbt2dump.c \
|
||||
nbjt2ext.h \
|
||||
nbt2init.c \
|
||||
nbt2init.h \
|
||||
nbjt2itf.h \
|
||||
nbt2load.c \
|
||||
nbt2mdel.c \
|
||||
nbt2mpar.c \
|
||||
nbt2parm.c \
|
||||
nbt2pzld.c \
|
||||
nbt2set.c \
|
||||
nbt2temp.c \
|
||||
nbt2trun.c
|
||||
|
||||
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/src/include
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Authors: 1987 Karti Mayaram, 1991 David Gates
|
||||
**********/
|
||||
|
||||
#ifndef NBJT2_H
|
||||
#define NBJT2_H "NBJT2defs.h $Revision$ on $Date$ "
|
||||
|
||||
/* structures to describe 2d Numerical Bipolar Junction Transistors */
|
||||
|
||||
/* circuit level includes */
|
||||
#include "ifsim.h"
|
||||
#include "cktdefs.h"
|
||||
#include "gendefs.h"
|
||||
|
||||
/* device level includes */
|
||||
#include "twomesh.h"
|
||||
#include "twodev.h"
|
||||
#include "profile.h"
|
||||
#include "numglobs.h"
|
||||
#include "carddefs.h"
|
||||
|
||||
/* information needed per instance */
|
||||
typedef struct sNBJT2instance {
|
||||
struct sNBJT2model *NBJT2modPtr; /* back pointer to model */
|
||||
struct sNBJT2instance *NBJT2nextInstance; /* pointer to next instance
|
||||
* of current model */
|
||||
IFuid NBJT2name; /* pointer to character string naming this
|
||||
* instance */
|
||||
int NBJT2owner; /* number of owner process */
|
||||
int NBJT2state; /* pointer to start of state vector for bjt */
|
||||
|
||||
/* entries in the state vector for bjt: */
|
||||
#define NBJT2vbe NBJT2state
|
||||
#define NBJT2vce NBJT2state+1
|
||||
#define NBJT2ic NBJT2state+2
|
||||
#define NBJT2ie NBJT2state+3
|
||||
#define NBJT2dIeDVce NBJT2state+4
|
||||
#define NBJT2dIeDVbe NBJT2state+5
|
||||
#define NBJT2dIcDVce NBJT2state+6
|
||||
#define NBJT2dIcDVbe NBJT2state+7
|
||||
#define NBJT2numStates 8
|
||||
|
||||
int NBJT2colNode; /* number of collector node of bjt */
|
||||
int NBJT2baseNode; /* number of base node of bjt */
|
||||
int NBJT2emitNode; /* number of emitter node of bjt */
|
||||
double NBJT2width; /* width factor for the bjt */
|
||||
double NBJT2area; /* area factor for the bjt */
|
||||
TWOdevice *NBJT2pDevice;
|
||||
GLOBvalues NBJT2globals; /* Temp.-Dep. Global Parameters */
|
||||
int NBJT2type;
|
||||
double NBJT2temp; /* Instance Temperature */
|
||||
double NBJT2c11; /* small-signal capacitance */
|
||||
double NBJT2y11r; /* small-signal admittance, real part */
|
||||
double NBJT2y11i; /* small-signal admittance, imag part */
|
||||
double NBJT2c12; /* small-signal capacitance */
|
||||
double NBJT2y12r; /* small-signal admittance, real part */
|
||||
double NBJT2y12i; /* small-signal admittance, imag part */
|
||||
double NBJT2c21; /* small-signal capacitance */
|
||||
double NBJT2y21r; /* small-signal admittance, real part */
|
||||
double NBJT2y21i; /* small-signal admittance, imag part */
|
||||
double NBJT2c22; /* small-signal capacitance */
|
||||
double NBJT2y22r; /* small-signal admittance, real part */
|
||||
double NBJT2y22i; /* small-signal admittance, imag part */
|
||||
int NBJT2print;
|
||||
char *NBJT2icFile; /* Name of initial condition file */
|
||||
double *NBJT2colColPtr; /* pointer to sparse matrix at
|
||||
* (collector,collector) */
|
||||
double *NBJT2baseBasePtr; /* pointer to sparse matrix at (base,base) */
|
||||
double *NBJT2emitEmitPtr; /* pointer to sparse matrix at
|
||||
* (emitter,emitter) */
|
||||
double *NBJT2colBasePtr; /* pointer to sparse matrix at
|
||||
* (collector,base) */
|
||||
double *NBJT2colEmitPtr; /* pointer to sparse matrix at
|
||||
* (collector,emitter) */
|
||||
double *NBJT2baseColPtr; /* pointer to sparse matrix at
|
||||
* (base,collector) */
|
||||
double *NBJT2baseEmitPtr; /* pointer to sparse matrix at (base,emitter) */
|
||||
double *NBJT2emitColPtr; /* pointer to sparse matrix at
|
||||
* (emitter,collector) */
|
||||
double *NBJT2emitBasePtr; /* pointer to sparse matrix at (emitter,base) */
|
||||
int NBJT2off; /* 'off' flag for bjt */
|
||||
unsigned NBJT2smSigAvail:1; /* flag to indicate small-signal done */
|
||||
unsigned NBJT2widthGiven:1; /* flag to indicate width was specified */
|
||||
unsigned NBJT2areaGiven:1; /* flag to indicate area was specified */
|
||||
unsigned NBJT2icFileGiven:1; /* flag to indicate init. cond. file given */
|
||||
unsigned NBJT2printGiven:1; /* flag to indicate print given */
|
||||
unsigned NBJT2tempGiven:1; /* flag to indicate temp given */
|
||||
} NBJT2instance;
|
||||
|
||||
/* per model data */
|
||||
typedef struct sNBJT2model { /* model structure for a bjt */
|
||||
int NBJT2modType; /* type index of this device type */
|
||||
struct sNBJT2model *NBJT2nextModel; /* pointer to next possible model in
|
||||
* linked list */
|
||||
NBJT2instance *NBJT2instances;/* pointer to list of instances that have
|
||||
* this model */
|
||||
IFuid NBJT2modName; /* pointer to character string naming this
|
||||
* model */
|
||||
/* Everything below here is numerical-device-specific */
|
||||
MESHcard *NBJT2xMeshes; /* list of xmesh cards */
|
||||
MESHcard *NBJT2yMeshes; /* list of ymesh cards */
|
||||
DOMNcard *NBJT2domains; /* list of domain cards */
|
||||
BDRYcard *NBJT2boundaries; /* list of boundary cards */
|
||||
DOPcard *NBJT2dopings; /* list of doping cards */
|
||||
ELCTcard *NBJT2electrodes; /* list of electrode cards */
|
||||
CONTcard *NBJT2contacts; /* list of contact cards */
|
||||
MODLcard *NBJT2models; /* list of model cards */
|
||||
MATLcard *NBJT2materials; /* list of material cards */
|
||||
MOBcard *NBJT2mobility; /* list of mobility cards */
|
||||
METHcard *NBJT2methods; /* list of method cards */
|
||||
OPTNcard *NBJT2options; /* list of option cards */
|
||||
OUTPcard *NBJT2outputs; /* list of output cards */
|
||||
TWOtranInfo *NBJT2pInfo; /* transient analysis information */
|
||||
DOPprofile *NBJT2profiles; /* expanded list of doping profiles */
|
||||
DOPtable *NBJT2dopTables; /* list of tables used by profiles */
|
||||
TWOmaterial *NBJT2matlInfo; /* list of material info structures */
|
||||
} NBJT2model;
|
||||
|
||||
/* type of 2D BJT */
|
||||
#define NPN 1
|
||||
#define PNP -1
|
||||
|
||||
/* device parameters */
|
||||
#define NBJT2_WIDTH 1
|
||||
#define NBJT2_AREA 2
|
||||
#define NBJT2_OFF 3
|
||||
#define NBJT2_IC_FILE 4
|
||||
#define NBJT2_PRINT 7
|
||||
#define NBJT2_TEMP 8
|
||||
|
||||
#define NBJT2_G11 9
|
||||
#define NBJT2_C11 10
|
||||
#define NBJT2_Y11 11
|
||||
#define NBJT2_G12 12
|
||||
#define NBJT2_C12 13
|
||||
#define NBJT2_Y12 14
|
||||
#define NBJT2_G13 15
|
||||
#define NBJT2_C13 16
|
||||
#define NBJT2_Y13 17
|
||||
#define NBJT2_G21 18
|
||||
#define NBJT2_C21 19
|
||||
#define NBJT2_Y21 20
|
||||
#define NBJT2_G22 21
|
||||
#define NBJT2_C22 22
|
||||
#define NBJT2_Y22 23
|
||||
#define NBJT2_G23 24
|
||||
#define NBJT2_C23 25
|
||||
#define NBJT2_Y23 26
|
||||
#define NBJT2_G31 27
|
||||
#define NBJT2_C31 28
|
||||
#define NBJT2_Y31 29
|
||||
#define NBJT2_G32 30
|
||||
#define NBJT2_C32 31
|
||||
#define NBJT2_Y32 32
|
||||
#define NBJT2_G33 33
|
||||
#define NBJT2_C33 34
|
||||
#define NBJT2_Y33 35
|
||||
|
||||
/* model parameters */
|
||||
/* NOTE: all true model parameters have been moved to IFcardInfo structures */
|
||||
#define NBJT2_MOD_NBJT 1
|
||||
|
||||
/* device questions */
|
||||
|
||||
/* model questions */
|
||||
|
||||
#include "nbjt2ext.h"
|
||||
|
||||
#endif /* NBJT2_H */
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Karti Mayaram
|
||||
**********/
|
||||
|
||||
#ifndef NBJT2EXT_H
|
||||
#define NBJT2EXT_H
|
||||
|
||||
|
||||
extern int NBJT2acLoad(GENmodel *, CKTcircuit *);
|
||||
extern int NBJT2ask(CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *);
|
||||
extern int NBJT2delete(GENmodel *, IFuid, GENinstance **);
|
||||
extern void NBJT2destroy(GENmodel **);
|
||||
extern int NBJT2getic(GENmodel *, CKTcircuit *);
|
||||
extern int NBJT2load(GENmodel *, CKTcircuit *);
|
||||
extern int NBJT2mDelete(GENmodel **, IFuid, GENmodel *);
|
||||
extern int NBJT2mParam(int, IFvalue *, GENmodel *);
|
||||
extern int NBJT2param(int, IFvalue *, GENinstance *, IFvalue *);
|
||||
extern int NBJT2pzLoad(GENmodel *, CKTcircuit *, SPcomplex *);
|
||||
extern int NBJT2setup(SMPmatrix *, GENmodel *, CKTcircuit *, int *);
|
||||
extern int NBJT2temp(GENmodel *, CKTcircuit *);
|
||||
extern int NBJT2trunc(GENmodel *, CKTcircuit *, double *);
|
||||
|
||||
extern void NBJT2dump(GENmodel *, CKTcircuit *);
|
||||
extern void NBJT2acct(GENmodel *, CKTcircuit *, FILE *);
|
||||
|
||||
#endif /* NBJT2EXT_H */
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
**********/
|
||||
|
||||
#ifndef DEV_NBJT2
|
||||
#define DEV_NBJT2
|
||||
|
||||
extern SPICEdev *get_nbjt2_info(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "devdefs.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/*
|
||||
* This file defines the 2d Numerical BJT data structures that are available
|
||||
* to the next level(s) up the calling hierarchy
|
||||
*/
|
||||
|
||||
IFparm NBJT2pTable[] = { /* parameters */
|
||||
IP("off", NBJT2_OFF, IF_FLAG, "Device initially off"),
|
||||
IP("ic.file", NBJT2_IC_FILE, IF_STRING, "Initial condition file"),
|
||||
IOP("w", NBJT2_WIDTH, IF_REAL, "Width factor"),
|
||||
IOP("area", NBJT2_AREA, IF_REAL, "Area factor"),
|
||||
IP("save", NBJT2_PRINT, IF_REAL, "Save solutions"),
|
||||
IP("print", NBJT2_PRINT, IF_REAL, "Print solutions"),
|
||||
OP("g11", NBJT2_G11, IF_REAL, "Conductance"),
|
||||
OP("c11", NBJT2_C11, IF_REAL, "Capacitance"),
|
||||
OP("y11", NBJT2_Y11, IF_COMPLEX, "Admittance"),
|
||||
OP("g12", NBJT2_G12, IF_REAL, "Conductance"),
|
||||
OP("c12", NBJT2_C12, IF_REAL, "Capacitance"),
|
||||
OP("y12", NBJT2_Y12, IF_COMPLEX, "Admittance"),
|
||||
OPU("g13", NBJT2_G13, IF_REAL, "Conductance"),
|
||||
OPU("c13", NBJT2_C13, IF_REAL, "Capacitance"),
|
||||
OPU("y13", NBJT2_Y13, IF_COMPLEX, "Admittance"),
|
||||
OP("g21", NBJT2_G21, IF_REAL, "Conductance"),
|
||||
OP("c21", NBJT2_C21, IF_REAL, "Capacitance"),
|
||||
OP("y21", NBJT2_Y21, IF_COMPLEX, "Admittance"),
|
||||
OP("g22", NBJT2_G22, IF_REAL, "Conductance"),
|
||||
OP("c22", NBJT2_C22, IF_REAL, "Capacitance"),
|
||||
OP("y22", NBJT2_Y22, IF_COMPLEX, "Admittance"),
|
||||
OPU("g23", NBJT2_G23, IF_REAL, "Conductance"),
|
||||
OPU("c23", NBJT2_C23, IF_REAL, "Capacitance"),
|
||||
OPU("y23", NBJT2_Y23, IF_COMPLEX, "Admittance"),
|
||||
OPU("g31", NBJT2_G31, IF_REAL, "Conductance"),
|
||||
OPU("c31", NBJT2_C31, IF_REAL, "Capacitance"),
|
||||
OPU("y31", NBJT2_Y31, IF_COMPLEX, "Admittance"),
|
||||
OPU("g32", NBJT2_G32, IF_REAL, "Conductance"),
|
||||
OPU("c32", NBJT2_C32, IF_REAL, "Capacitance"),
|
||||
OPU("y32", NBJT2_Y32, IF_COMPLEX, "Admittance"),
|
||||
OPU("g33", NBJT2_G33, IF_REAL, "Conductance"),
|
||||
OPU("c33", NBJT2_C33, IF_REAL, "Capacitance"),
|
||||
OPU("y33", NBJT2_Y33, IF_COMPLEX, "Admittance"),
|
||||
IOP("temp", NBJT2_TEMP, IF_REAL, "Instance Temperature")
|
||||
};
|
||||
|
||||
IFparm NBJT2mPTable[] = { /* model parameters */
|
||||
/* numerical-device models no longer have parameters */
|
||||
/* one is left behind to keep the table from being empty */
|
||||
IP("nbjt", NBJT2_MOD_NBJT, IF_FLAG, "Numerical BJT Model")
|
||||
};
|
||||
|
||||
|
||||
char *NBJT2names[] = {
|
||||
"Collector",
|
||||
"Base",
|
||||
"Emitter",
|
||||
"Substrate"
|
||||
};
|
||||
|
||||
int NBJT2nSize = NUMELEMS(NBJT2names);
|
||||
int NBJT2pTSize = NUMELEMS(NBJT2pTable);
|
||||
int NBJT2mPTSize = NUMELEMS(NBJT2mPTable);
|
||||
int NBJT2iSize = sizeof(NBJT2instance);
|
||||
int NBJT2mSize = sizeof(NBJT2model);
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* Function to load the COMPLEX circuit matrix using the small signal
|
||||
* parameters saved during a previous DC operating point analysis.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "sperror.h"
|
||||
#include "complex.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* External Declarations */
|
||||
extern int TWOacDebug;
|
||||
|
||||
int
|
||||
NBJT2acLoad(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
|
||||
{
|
||||
register NBJT2model *model = (NBJT2model *) inModel;
|
||||
register NBJT2instance *inst;
|
||||
SPcomplex yIeVce, yIeVbe;
|
||||
SPcomplex yIcVce, yIcVbe;
|
||||
double startTime;
|
||||
|
||||
for (; model != NULL; model = model->NBJT2nextModel) {
|
||||
FieldDepMobility = model->NBJT2models->MODLfieldDepMobility;
|
||||
TransDepMobility = model->NBJT2models->MODLtransDepMobility;
|
||||
SurfaceMobility = model->NBJT2models->MODLsurfaceMobility;
|
||||
Srh = model->NBJT2models->MODLsrh;
|
||||
Auger = model->NBJT2models->MODLauger;
|
||||
AvalancheGen = model->NBJT2models->MODLavalancheGen;
|
||||
OneCarrier = model->NBJT2methods->METHoneCarrier;
|
||||
AcAnalysisMethod = model->NBJT2methods->METHacAnalysisMethod;
|
||||
MobDeriv = model->NBJT2methods->METHmobDeriv;
|
||||
TWOacDebug = model->NBJT2outputs->OUTPacDebug;
|
||||
|
||||
for (inst = model->NBJT2instances; inst != NULL;
|
||||
inst = inst->NBJT2nextInstance) {
|
||||
if (inst->NBJT2owner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NBJT2globals));
|
||||
|
||||
model->NBJT2methods->METHacAnalysisMethod =
|
||||
NBJT2admittance(inst->NBJT2pDevice, ckt->CKTomega,
|
||||
&yIeVce, &yIcVce, &yIeVbe, &yIcVbe);
|
||||
|
||||
*(inst->NBJT2colColPtr) += yIcVce.real;
|
||||
*(inst->NBJT2colColPtr + 1) += yIcVce.imag;
|
||||
*(inst->NBJT2colBasePtr) += yIcVbe.real;
|
||||
*(inst->NBJT2colBasePtr + 1) += yIcVbe.imag;
|
||||
*(inst->NBJT2colEmitPtr) -= yIcVbe.real + yIcVce.real;
|
||||
*(inst->NBJT2colEmitPtr + 1) -= yIcVbe.imag + yIcVce.imag;
|
||||
*(inst->NBJT2baseColPtr) -= yIcVce.real + yIeVce.real;
|
||||
*(inst->NBJT2baseColPtr + 1) -= yIcVce.imag + yIeVce.imag;
|
||||
*(inst->NBJT2baseBasePtr) -= yIcVbe.real + yIeVbe.real;
|
||||
*(inst->NBJT2baseBasePtr + 1) -= yIcVbe.imag + yIeVbe.imag;
|
||||
*(inst->NBJT2baseEmitPtr) += yIcVbe.real + yIcVce.real + yIeVbe.real + yIeVce.real;
|
||||
*(inst->NBJT2baseEmitPtr + 1) += yIcVbe.imag + yIcVce.imag + yIeVbe.imag + yIeVce.imag;
|
||||
*(inst->NBJT2emitColPtr) += yIeVce.real;
|
||||
*(inst->NBJT2emitColPtr + 1) += yIeVce.imag;
|
||||
*(inst->NBJT2emitBasePtr) += yIeVbe.real;
|
||||
*(inst->NBJT2emitBasePtr + 1) += yIeVbe.imag;
|
||||
*(inst->NBJT2emitEmitPtr) -= yIeVbe.real + yIeVce.real;
|
||||
*(inst->NBJT2emitEmitPtr + 1) -= yIeVbe.imag + yIeVce.imag;
|
||||
if (ckt->CKTomega != 0.0) {
|
||||
inst->NBJT2c11 = yIcVce.imag / ckt->CKTomega;
|
||||
inst->NBJT2c12 = yIcVbe.imag / ckt->CKTomega;
|
||||
inst->NBJT2c21 = (yIeVce.imag - yIcVce.imag) / ckt->CKTomega;
|
||||
inst->NBJT2c22 = (yIeVbe.imag - yIcVbe.imag) / ckt->CKTomega;
|
||||
} else {
|
||||
inst->NBJT2c11 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NBJT2c12 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NBJT2c21 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NBJT2c22 = 0.0; /* XXX What else can be done?! */
|
||||
}
|
||||
inst->NBJT2y11r = yIcVce.real;
|
||||
inst->NBJT2y11i = yIcVce.imag;
|
||||
inst->NBJT2y12r = yIcVbe.real;
|
||||
inst->NBJT2y12i = yIcVbe.imag;
|
||||
inst->NBJT2y21r = yIeVce.real - yIcVce.real;
|
||||
inst->NBJT2y21i = yIeVce.imag - yIcVce.imag;
|
||||
inst->NBJT2y22r = yIeVbe.real - yIcVbe.real;
|
||||
inst->NBJT2y22i = yIeVbe.imag - yIcVbe.imag;
|
||||
inst->NBJT2smSigAvail = TRUE;
|
||||
inst->NBJT2pDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,216 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Thomas L. Quarles
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "cktdefs.h"
|
||||
#include "devdefs.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
|
||||
/* Check out this one */
|
||||
extern int NBJT2initSmSig(NBJT2instance *);
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
NBJT2ask(ckt, inInst, which, value, select)
|
||||
CKTcircuit *ckt;
|
||||
GENinstance *inInst;
|
||||
int which;
|
||||
IFvalue *value;
|
||||
IFvalue *select;
|
||||
{
|
||||
NBJT2instance *inst = (NBJT2instance *) inInst;
|
||||
switch (which) {
|
||||
case NBJT2_WIDTH:
|
||||
value->rValue = inst->NBJT2width;
|
||||
return (OK);
|
||||
case NBJT2_AREA:
|
||||
value->rValue = inst->NBJT2area;
|
||||
return (OK);
|
||||
case NBJT2_TEMP:
|
||||
value->rValue = inst->NBJT2temp - CONSTCtoK;
|
||||
return (OK);
|
||||
case NBJT2_G11:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NBJT2dIcDVce);
|
||||
return (OK);
|
||||
case NBJT2_G12:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NBJT2dIcDVbe);
|
||||
return (OK);
|
||||
case NBJT2_G13:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NBJT2dIcDVce)
|
||||
- *(ckt->CKTstate0 + inst->NBJT2dIcDVbe);
|
||||
return (OK);
|
||||
case NBJT2_G21:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NBJT2dIeDVce)
|
||||
- *(ckt->CKTstate0 + inst->NBJT2dIcDVce);
|
||||
return (OK);
|
||||
case NBJT2_G22:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NBJT2dIeDVbe)
|
||||
- *(ckt->CKTstate0 + inst->NBJT2dIcDVbe);
|
||||
return (OK);
|
||||
case NBJT2_G23:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NBJT2dIeDVce)
|
||||
+ *(ckt->CKTstate0 + inst->NBJT2dIcDVce)
|
||||
-*(ckt->CKTstate0 + inst->NBJT2dIeDVbe)
|
||||
+ *(ckt->CKTstate0 + inst->NBJT2dIcDVbe);
|
||||
return (OK);
|
||||
case NBJT2_G31:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NBJT2dIeDVce);
|
||||
return (OK);
|
||||
case NBJT2_G32:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NBJT2dIeDVbe);
|
||||
return (OK);
|
||||
case NBJT2_G33:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NBJT2dIeDVce)
|
||||
+ *(ckt->CKTstate0 + inst->NBJT2dIeDVbe);
|
||||
return (OK);
|
||||
case NBJT2_C11:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NBJT2c11;
|
||||
return (OK);
|
||||
case NBJT2_C12:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NBJT2c12;
|
||||
return (OK);
|
||||
case NBJT2_C13:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NBJT2c11 - inst->NBJT2c12;
|
||||
return (OK);
|
||||
case NBJT2_C21:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NBJT2c21;
|
||||
return (OK);
|
||||
case NBJT2_C22:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NBJT2c22;
|
||||
return (OK);
|
||||
case NBJT2_C23:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NBJT2c21 - inst->NBJT2c22;
|
||||
return (OK);
|
||||
case NBJT2_C31:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NBJT2c11 - inst->NBJT2c21;
|
||||
return (OK);
|
||||
case NBJT2_C32:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NBJT2c12 - inst->NBJT2c22;
|
||||
return (OK);
|
||||
case NBJT2_C33:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NBJT2c11 + inst->NBJT2c21
|
||||
+ inst->NBJT2c12 + inst->NBJT2c22;
|
||||
return (OK);
|
||||
case NBJT2_Y11:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NBJT2y11r;
|
||||
value->cValue.imag = inst->NBJT2y11i;
|
||||
return (OK);
|
||||
case NBJT2_Y12:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NBJT2y12r;
|
||||
value->cValue.imag = inst->NBJT2y12i;
|
||||
return (OK);
|
||||
case NBJT2_Y13:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NBJT2y11r - inst->NBJT2y12r;
|
||||
value->cValue.imag = -inst->NBJT2y11i - inst->NBJT2y12i;
|
||||
return (OK);
|
||||
case NBJT2_Y21:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NBJT2y21r;
|
||||
value->cValue.imag = inst->NBJT2y21i;
|
||||
return (OK);
|
||||
case NBJT2_Y22:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NBJT2y22r;
|
||||
value->cValue.imag = inst->NBJT2y22i;
|
||||
return (OK);
|
||||
case NBJT2_Y23:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NBJT2y21r - inst->NBJT2y22r;
|
||||
value->cValue.imag = -inst->NBJT2y21i - inst->NBJT2y22i;
|
||||
return (OK);
|
||||
case NBJT2_Y31:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NBJT2y11r - inst->NBJT2y21r;
|
||||
value->cValue.imag = -inst->NBJT2y11i - inst->NBJT2y21i;
|
||||
return (OK);
|
||||
case NBJT2_Y32:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NBJT2y12r - inst->NBJT2y22r;
|
||||
value->cValue.imag = -inst->NBJT2y12i - inst->NBJT2y22i;
|
||||
return (OK);
|
||||
case NBJT2_Y33:
|
||||
if (!inst->NBJT2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NBJT2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NBJT2y11r + inst->NBJT2y21r
|
||||
+ inst->NBJT2y12r + inst->NBJT2y22r;
|
||||
value->cValue.imag = inst->NBJT2y11i + inst->NBJT2y21i
|
||||
+ inst->NBJT2y12i + inst->NBJT2y22i;
|
||||
return (OK);
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine deletes a NBJT2 instance from the circuit and frees the
|
||||
* storage it was using.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NBJT2delete(inModel, name, kill)
|
||||
GENmodel *inModel;
|
||||
IFuid name;
|
||||
GENinstance **kill;
|
||||
|
||||
{
|
||||
|
||||
NBJT2model *model = (NBJT2model *) inModel;
|
||||
NBJT2instance **fast = (NBJT2instance **) kill;
|
||||
NBJT2instance **prev = NULL;
|
||||
NBJT2instance *inst;
|
||||
|
||||
for (; model; model = model->NBJT2nextModel) {
|
||||
prev = &(model->NBJT2instances);
|
||||
for (inst = *prev; inst; inst = *prev) {
|
||||
if (inst->NBJT2name == name || (fast && inst == *fast)) {
|
||||
*prev = inst->NBJT2nextInstance;
|
||||
FREE(inst);
|
||||
return (OK);
|
||||
}
|
||||
prev = &(inst->NBJT2nextInstance);
|
||||
}
|
||||
}
|
||||
return (E_NODEV);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine deletes all NBJT2s from the circuit and frees all storage
|
||||
* they were using. The current implementation has memory leaks.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "suffix.h"
|
||||
|
||||
void
|
||||
NBJT2destroy(inModel)
|
||||
GENmodel **inModel;
|
||||
|
||||
{
|
||||
|
||||
NBJT2model **model = (NBJT2model **) inModel;
|
||||
NBJT2model *mod, *nextMod;
|
||||
NBJT2instance *inst, *nextInst;
|
||||
|
||||
|
||||
for (mod = *model; mod;) {
|
||||
for (inst = mod->NBJT2instances; inst;) {
|
||||
TWOdestroy(inst->NBJT2pDevice);
|
||||
nextInst = inst->NBJT2nextInstance;
|
||||
FREE(inst);
|
||||
inst = nextInst;
|
||||
}
|
||||
nextMod = mod->NBJT2nextModel;
|
||||
FREE(mod);
|
||||
mod = nextMod;
|
||||
}
|
||||
*model = NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This is a simple routine to dump the internal device states. It produces
|
||||
* states for .OP, .DC, & .TRAN simulations.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
|
||||
/* Forward Declarations */
|
||||
static void NBJT2putHeader(FILE *, CKTcircuit *, NBJT2instance *);
|
||||
|
||||
/* State Counter */
|
||||
static int state_numOP = 0;
|
||||
static int state_numDC = 0;
|
||||
static int state_numTR = 0;
|
||||
|
||||
void
|
||||
NBJT2dump(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
{
|
||||
register NBJT2model *model = (NBJT2model *) inModel;
|
||||
register NBJT2instance *inst;
|
||||
OUTPcard *output;
|
||||
FILE *fpState;
|
||||
char fileName[BSIZE_SP];
|
||||
char description[BSIZE_SP];
|
||||
char *prefix;
|
||||
int *state_num;
|
||||
int anyOutput = 0;
|
||||
|
||||
if (ckt->CKTmode & MODEDCOP) {
|
||||
prefix = "OP";
|
||||
state_num = &state_numOP;
|
||||
sprintf(description, "...");
|
||||
} else if (ckt->CKTmode & MODEDCTRANCURVE) {
|
||||
prefix = "DC";
|
||||
state_num = &state_numDC;
|
||||
sprintf(description, "sweep = % e", ckt->CKTtime);
|
||||
} else if (ckt->CKTmode & MODETRAN) {
|
||||
prefix = "TR";
|
||||
state_num = &state_numTR;
|
||||
sprintf(description, "time = % e", ckt->CKTtime);
|
||||
} else {
|
||||
/* Not a recognized CKT mode. */
|
||||
return;
|
||||
}
|
||||
|
||||
for (; model != NULL; model = model->NBJT2nextModel) {
|
||||
output = model->NBJT2outputs;
|
||||
for (inst = model->NBJT2instances; inst != NULL;
|
||||
inst = inst->NBJT2nextInstance) {
|
||||
if (inst->NBJT2owner != ARCHme) continue;
|
||||
|
||||
if (inst->NBJT2printGiven) {
|
||||
if ((ckt->CKTmode & MODETRAN) &&
|
||||
((ckt->CKTstat->STATaccepted - 1) % inst->NBJT2print != 0)) {
|
||||
continue;
|
||||
}
|
||||
anyOutput = 1;
|
||||
sprintf(fileName, "%s%s.%d.%s", output->OUTProotFile, prefix,
|
||||
*state_num, inst->NBJT2name);
|
||||
if (!(fpState = fopen(fileName, "w"))) {
|
||||
perror(fileName);
|
||||
} else {
|
||||
NBJT2putHeader(fpState, ckt, inst);
|
||||
TWOprnSolution(fpState, inst->NBJT2pDevice,
|
||||
model->NBJT2outputs);
|
||||
fclose(fpState);
|
||||
LOGmakeEntry(fileName, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (anyOutput) {
|
||||
(*state_num)++;
|
||||
}
|
||||
}
|
||||
|
||||
#define NBJT2numOutputs 9
|
||||
|
||||
static
|
||||
void
|
||||
NBJT2putHeader(file, ckt, inst)
|
||||
FILE *file;
|
||||
CKTcircuit *ckt;
|
||||
NBJT2instance *inst;
|
||||
{
|
||||
char *reference;
|
||||
double refVal = 0.0;
|
||||
int numVars = NBJT2numOutputs;
|
||||
|
||||
if (ckt->CKTmode & MODEDCOP) {
|
||||
reference = NULL;
|
||||
} else if (ckt->CKTmode & MODEDCTRANCURVE) {
|
||||
reference = "sweep";
|
||||
refVal = ckt->CKTtime;
|
||||
numVars++;
|
||||
} else if (ckt->CKTmode & MODETRAN) {
|
||||
reference = "time";
|
||||
refVal = ckt->CKTtime;
|
||||
numVars++;
|
||||
} else {
|
||||
reference = NULL;
|
||||
}
|
||||
fprintf(file, "Title: Device %s external state\n", inst->NBJT2name);
|
||||
fprintf(file, "Plotname: Device Operating Point\n");
|
||||
fprintf(file, "Command: deftype v conductance S\n");
|
||||
fprintf(file, "Flags: real\n");
|
||||
fprintf(file, "No. Variables: %d\n", numVars);
|
||||
fprintf(file, "No. Points: 1\n");
|
||||
numVars = 0;
|
||||
fprintf(file, "Variables:\n");
|
||||
if (reference) {
|
||||
fprintf(file, "\t%d %s unknown\n", numVars++, reference);
|
||||
}
|
||||
fprintf(file, "\t%d v13 voltage\n", numVars++);
|
||||
fprintf(file, "\t%d v23 voltage\n", numVars++);
|
||||
fprintf(file, "\t%d i1 current\n", numVars++);
|
||||
fprintf(file, "\t%d i2 current\n", numVars++);
|
||||
fprintf(file, "\t%d i3 current\n", numVars++);
|
||||
fprintf(file, "\t%d g22 conductance\n", numVars++);
|
||||
fprintf(file, "\t%d g21 conductance\n", numVars++);
|
||||
fprintf(file, "\t%d g12 conductance\n", numVars++);
|
||||
fprintf(file, "\t%d g11 conductance\n", numVars++);
|
||||
fprintf(file, "Values:\n0");
|
||||
if (reference) {
|
||||
fprintf(file, "\t% e\n", refVal);
|
||||
}
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2vce));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2vbe));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2ic));
|
||||
fprintf(file, "\t% e\n", - *(ckt->CKTstate0 + inst->NBJT2ie)
|
||||
- *(ckt->CKTstate0 + inst->NBJT2ic));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2ie));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2dIeDVbe)
|
||||
- *(ckt->CKTstate0 + inst->NBJT2dIcDVbe));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2dIeDVce)
|
||||
- *(ckt->CKTstate0 + inst->NBJT2dIcDVce));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2dIcDVbe));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NBJT2dIcDVce));
|
||||
}
|
||||
|
||||
void
|
||||
NBJT2acct(inModel, ckt, file)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
FILE *file;
|
||||
{
|
||||
register NBJT2model *model = (NBJT2model *) inModel;
|
||||
register NBJT2instance *inst;
|
||||
OUTPcard *output;
|
||||
|
||||
for (; model != NULL; model = model->NBJT2nextModel) {
|
||||
output = model->NBJT2outputs;
|
||||
for (inst = model->NBJT2instances; inst != NULL;
|
||||
inst = inst->NBJT2nextInstance) {
|
||||
if (inst->NBJT2owner != ARCHme) continue;
|
||||
|
||||
if (output->OUTPstats) {
|
||||
TWOmemStats(file, inst->NBJT2pDevice);
|
||||
TWOcpuStats(file, inst->NBJT2pDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <devdefs.h>
|
||||
|
||||
#include "nbjt2itf.h"
|
||||
#include "nbjt2ext.h"
|
||||
#include "nbt2init.h"
|
||||
|
||||
|
||||
SPICEdev NBJT2info = {
|
||||
{
|
||||
"NBJT2",
|
||||
"2D Numerical Bipolar Junction Transistor model",
|
||||
|
||||
&NBJT2nSize,
|
||||
&NBJT2nSize,
|
||||
NBJT2names,
|
||||
|
||||
&NBJT2pTSize,
|
||||
NBJT2pTable,
|
||||
|
||||
&NBJT2mPTSize,
|
||||
NBJT2mPTable,
|
||||
|
||||
#ifdef XSPICE
|
||||
/*---- Fixed by SDB 5.2.2003 to enable XSPICE/tclspice integration -----*/
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
/*--------------------------- End of SDB fix -------------------------*/
|
||||
#endif
|
||||
|
||||
DEV_DEFAULT
|
||||
},
|
||||
|
||||
DEVparam : NBJT2param,
|
||||
DEVmodParam : NBJT2mParam,
|
||||
DEVload : NBJT2load,
|
||||
DEVsetup : NBJT2setup,
|
||||
DEVunsetup : NULL,
|
||||
DEVpzSetup : NBJT2setup,
|
||||
DEVtemperature: NBJT2temp,
|
||||
DEVtrunc : NBJT2trunc,
|
||||
DEVfindBranch : NULL,
|
||||
DEVacLoad : NBJT2acLoad,
|
||||
DEVaccept : NULL,
|
||||
DEVdestroy : NBJT2destroy,
|
||||
DEVmodDelete : NBJT2mDelete,
|
||||
DEVdelete : NBJT2delete,
|
||||
DEVsetic : NULL,
|
||||
DEVask : NBJT2ask,
|
||||
DEVmodAsk : NULL,
|
||||
DEVpzLoad : NBJT2pzLoad,
|
||||
DEVconvTest : NULL,
|
||||
DEVsenSetup : NULL,
|
||||
DEVsenLoad : NULL,
|
||||
DEVsenUpdate : NULL,
|
||||
DEVsenAcLoad : NULL,
|
||||
DEVsenPrint : NULL,
|
||||
DEVsenTrunc : NULL,
|
||||
DEVdisto : NULL,
|
||||
DEVnoise : NULL,
|
||||
DEVdump : NBJT2dump,
|
||||
DEVacct : NBJT2acct,
|
||||
|
||||
DEVinstSize : &NBJT2iSize,
|
||||
DEVmodSize : &NBJT2mSize
|
||||
|
||||
};
|
||||
|
||||
|
||||
SPICEdev *
|
||||
get_nbjt2_info(void)
|
||||
{
|
||||
return &NBJT2info;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef _NBJT2INIT_H
|
||||
#define _NBJT2INIT_H
|
||||
|
||||
extern IFparm NBJT2pTable[ ];
|
||||
extern IFparm NBJT2mPTable[ ];
|
||||
extern char *NBJT2names[ ];
|
||||
extern int NBJT2pTSize;
|
||||
extern int NBJT2mPTSize;
|
||||
extern int NBJT2nSize;
|
||||
extern int NBJT2iSize;
|
||||
extern int NBJT2mSize;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,509 @@
|
|||
/**********
|
||||
Copyright 1992 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
|
||||
* BJTs in the circuit and load them into the matrix as appropriate
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "devdefs.h"
|
||||
#include "cktdefs.h"
|
||||
#include "nbjt2def.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 */
|
||||
|
||||
/* Check out this one */
|
||||
extern int NBJT2initSmSig(NBJT2instance *);
|
||||
|
||||
extern int TWOdcDebug;
|
||||
extern int TWOtranDebug;
|
||||
extern int TWOacDebug;
|
||||
|
||||
|
||||
|
||||
int
|
||||
NBJT2load(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
{
|
||||
register NBJT2model *model = (NBJT2model *) inModel;
|
||||
register NBJT2instance *inst;
|
||||
register TWOdevice *pDevice;
|
||||
double startTime, startTime2, totalTime, totalTime2;
|
||||
double tol;
|
||||
double ic, ie;
|
||||
double iceq, ieeq;
|
||||
double ichat = 0.0, iehat = 0.0;
|
||||
double delVce, delVbe;
|
||||
double vce, vbe;
|
||||
double dIeDVce, dIeDVbe;
|
||||
double dIcDVce, dIcDVbe;
|
||||
double xfact;
|
||||
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->NBJT2nextModel) {
|
||||
FieldDepMobility = model->NBJT2models->MODLfieldDepMobility;
|
||||
TransDepMobility = model->NBJT2models->MODLtransDepMobility;
|
||||
SurfaceMobility = model->NBJT2models->MODLsurfaceMobility;
|
||||
Srh = model->NBJT2models->MODLsrh;
|
||||
Auger = model->NBJT2models->MODLauger;
|
||||
AvalancheGen = model->NBJT2models->MODLavalancheGen;
|
||||
OneCarrier = model->NBJT2methods->METHoneCarrier;
|
||||
MobDeriv = model->NBJT2methods->METHmobDeriv;
|
||||
MaxIterations = model->NBJT2methods->METHitLim;
|
||||
TWOdcDebug = model->NBJT2outputs->OUTPdcDebug;
|
||||
TWOtranDebug = model->NBJT2outputs->OUTPtranDebug;
|
||||
TWOacDebug = model->NBJT2outputs->OUTPacDebug;
|
||||
deviceType = model->NBJT2options->OPTNdeviceType;
|
||||
doVoltPred = model->NBJT2methods->METHvoltPred;
|
||||
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
/* compute normalized deltas and predictor coeff */
|
||||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) {
|
||||
model->NBJT2pInfo->order = ckt->CKTorder;
|
||||
model->NBJT2pInfo->method = ckt->CKTintegrateMethod;
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder,
|
||||
model->NBJT2pInfo->intCoeff, deltaNorm);
|
||||
computePredCoeff(ckt->CKTintegrateMethod, ckt->CKTorder,
|
||||
model->NBJT2pInfo->predCoeff, deltaNorm);
|
||||
}
|
||||
} else if (ckt->CKTmode & MODEINITTRAN) {
|
||||
model->NBJT2pInfo->order = ckt->CKTorder;
|
||||
model->NBJT2pInfo->method = ckt->CKTintegrateMethod;
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder,
|
||||
model->NBJT2pInfo->intCoeff, deltaNorm);
|
||||
}
|
||||
/* loop through all the instances of the model */
|
||||
for (inst = model->NBJT2instances; inst != NULL;
|
||||
inst = inst->NBJT2nextInstance) {
|
||||
if (inst->NBJT2owner != ARCHme) continue;
|
||||
|
||||
pDevice = inst->NBJT2pDevice;
|
||||
|
||||
totalTime = 0.0;
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NBJT2globals));
|
||||
|
||||
/*
|
||||
* initialization
|
||||
*/
|
||||
pDevice->devStates = ckt->CKTstates;
|
||||
icheck = 1;
|
||||
doInitSolve = FALSE;
|
||||
initStateName = NULL;
|
||||
if (ckt->CKTmode & MODEINITSMSIG) {
|
||||
vbe = *(ckt->CKTstate0 + inst->NBJT2vbe);
|
||||
vce = *(ckt->CKTstate0 + inst->NBJT2vce);
|
||||
delVbe = 0.0;
|
||||
delVce = 0.0;
|
||||
NBJT2setBCs(pDevice, vce, vbe);
|
||||
} else if (ckt->CKTmode & MODEINITTRAN) {
|
||||
*(ckt->CKTstate0 + inst->NBJT2vbe) =
|
||||
*(ckt->CKTstate1 + inst->NBJT2vbe);
|
||||
*(ckt->CKTstate0 + inst->NBJT2vce) =
|
||||
*(ckt->CKTstate1 + inst->NBJT2vce);
|
||||
vbe = *(ckt->CKTstate1 + inst->NBJT2vbe);
|
||||
vce = *(ckt->CKTstate1 + inst->NBJT2vce);
|
||||
TWOsaveState(pDevice);
|
||||
delVbe = 0.0;
|
||||
delVce = 0.0;
|
||||
} else if ((ckt->CKTmode & MODEINITJCT) &&
|
||||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) {
|
||||
doInitSolve = TRUE;
|
||||
initStateName = inst->NBJT2icFile;
|
||||
vbe = 0.0;
|
||||
vce = 0.0;
|
||||
delVbe = vbe;
|
||||
delVce = vce;
|
||||
} else if ((ckt->CKTmode & MODEINITJCT) && (inst->NBJT2off == 0)) {
|
||||
doInitSolve = TRUE;
|
||||
initStateName = inst->NBJT2icFile;
|
||||
if (deviceType == OPTN_JFET) {
|
||||
vbe = 0.0;
|
||||
vce = inst->NBJT2type * 0.5;
|
||||
} else {
|
||||
vbe = inst->NBJT2type * 0.6;
|
||||
vce = inst->NBJT2type * 1.0;
|
||||
}
|
||||
delVbe = vbe;
|
||||
delVce = vce;
|
||||
} else if (ckt->CKTmode & MODEINITJCT) {
|
||||
doInitSolve = TRUE;
|
||||
vbe = 0.0;
|
||||
vce = 0.0;
|
||||
delVbe = vbe;
|
||||
delVce = vce;
|
||||
} else if ((ckt->CKTmode & MODEINITFIX) && inst->NBJT2off) {
|
||||
vbe = 0.0;
|
||||
vce = 0.0;
|
||||
delVbe = vbe;
|
||||
delVce = vce;
|
||||
} else {
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
*(ckt->CKTstate0 + inst->NBJT2vbe) =
|
||||
*(ckt->CKTstate1 + inst->NBJT2vbe);
|
||||
*(ckt->CKTstate0 + inst->NBJT2vce) =
|
||||
*(ckt->CKTstate1 + inst->NBJT2vce);
|
||||
*(ckt->CKTstate0 + inst->NBJT2ic) =
|
||||
*(ckt->CKTstate1 + inst->NBJT2ic);
|
||||
*(ckt->CKTstate0 + inst->NBJT2ie) =
|
||||
*(ckt->CKTstate1 + inst->NBJT2ie);
|
||||
*(ckt->CKTstate0 + inst->NBJT2dIeDVce) =
|
||||
*(ckt->CKTstate1 + inst->NBJT2dIeDVce);
|
||||
*(ckt->CKTstate0 + inst->NBJT2dIeDVbe) =
|
||||
*(ckt->CKTstate1 + inst->NBJT2dIeDVbe);
|
||||
*(ckt->CKTstate0 + inst->NBJT2dIcDVce) =
|
||||
*(ckt->CKTstate1 + inst->NBJT2dIcDVce);
|
||||
*(ckt->CKTstate0 + inst->NBJT2dIcDVbe) =
|
||||
*(ckt->CKTstate1 + inst->NBJT2dIcDVbe);
|
||||
/* compute normalized deltas and predictor coeff */
|
||||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) {
|
||||
/* no linear prediction on device voltages */
|
||||
vbe = *(ckt->CKTstate1 + inst->NBJT2vbe);
|
||||
vce = *(ckt->CKTstate1 + inst->NBJT2vce);
|
||||
TWOpredict(pDevice, model->NBJT2pInfo);
|
||||
} else {
|
||||
if (doVoltPred) {
|
||||
/* linear prediction */
|
||||
xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1];
|
||||
vbe = (1+xfact) * (*(ckt->CKTstate1 + inst->NBJT2vbe))
|
||||
- (xfact) * (*(ckt->CKTstate2 + inst->NBJT2vbe));
|
||||
vce = (1+xfact) * (*(ckt->CKTstate1 + inst->NBJT2vce))
|
||||
- (xfact) * (*(ckt->CKTstate2 + inst->NBJT2vce));
|
||||
} else {
|
||||
vbe = *(ckt->CKTstate1 + inst->NBJT2vbe);
|
||||
vce = *(ckt->CKTstate1 + inst->NBJT2vce);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* compute new nonlinear branch voltages
|
||||
*/
|
||||
vbe = *(ckt->CKTrhsOld + inst->NBJT2baseNode) -
|
||||
*(ckt->CKTrhsOld + inst->NBJT2emitNode);
|
||||
vce = *(ckt->CKTrhsOld + inst->NBJT2colNode) -
|
||||
*(ckt->CKTrhsOld + inst->NBJT2emitNode);
|
||||
}
|
||||
delVbe = vbe - *(ckt->CKTstate0 + inst->NBJT2vbe);
|
||||
delVce = vce - *(ckt->CKTstate0 + inst->NBJT2vce);
|
||||
ichat = *(ckt->CKTstate0 + inst->NBJT2ic) +
|
||||
*(ckt->CKTstate0 + inst->NBJT2dIcDVbe) * delVbe +
|
||||
*(ckt->CKTstate0 + inst->NBJT2dIcDVce) * delVce;
|
||||
iehat = *(ckt->CKTstate0 + inst->NBJT2ie) +
|
||||
*(ckt->CKTstate0 + inst->NBJT2dIeDVbe) * delVbe +
|
||||
*(ckt->CKTstate0 + inst->NBJT2dIeDVce) * delVce;
|
||||
|
||||
|
||||
#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(delVbe) < (ckt->CKTreltol * MAX(fabs(vbe),
|
||||
fabs(*(ckt->CKTstate0 + inst->NBJT2vbe))) +
|
||||
ckt->CKTvoltTol)))
|
||||
if ((fabs(delVce) < ckt->CKTreltol * MAX(fabs(vce),
|
||||
fabs(*(ckt->CKTstate0 + inst->NBJT2vce))) +
|
||||
ckt->CKTvoltTol))
|
||||
if ((fabs(ichat - *(ckt->CKTstate0 + inst->NBJT2ic)) <
|
||||
ckt->CKTreltol * MAX(fabs(ichat),
|
||||
fabs(*(ckt->CKTstate0 + inst->NBJT2ic))) +
|
||||
ckt->CKTabstol))
|
||||
if ((fabs(iehat - *(ckt->CKTstate0 + inst->NBJT2ie)) <
|
||||
ckt->CKTreltol * MAX(fabs(iehat),
|
||||
fabs(*(ckt->CKTstate0 + inst->NBJT2ie))) +
|
||||
ckt->CKTabstol)) {
|
||||
/*
|
||||
* bypassing....
|
||||
*/
|
||||
vbe = *(ckt->CKTstate0 + inst->NBJT2vbe);
|
||||
vce = *(ckt->CKTstate0 + inst->NBJT2vce);
|
||||
ic = *(ckt->CKTstate0 + inst->NBJT2ic);
|
||||
ie = *(ckt->CKTstate0 + inst->NBJT2ie);
|
||||
dIeDVce = *(ckt->CKTstate0 + inst->NBJT2dIeDVce);
|
||||
dIeDVbe = *(ckt->CKTstate0 + inst->NBJT2dIeDVbe);
|
||||
dIcDVce = *(ckt->CKTstate0 + inst->NBJT2dIcDVce);
|
||||
dIcDVbe = *(ckt->CKTstate0 + inst->NBJT2dIcDVbe);
|
||||
goto load;
|
||||
}
|
||||
#endif /* NOBYPASS */
|
||||
/*
|
||||
* limit nonlinear branch voltages
|
||||
*/
|
||||
icheck1 = 1;
|
||||
if (deviceType == OPTN_JFET) {
|
||||
double vbc, vbc0;
|
||||
vbe = inst->NBJT2type * limitJunctionVoltage(inst->NBJT2type * vbe,
|
||||
inst->NBJT2type * *(ckt->CKTstate0 + inst->NBJT2vbe), &icheck);
|
||||
vbc = vbe - vce;
|
||||
vbc0 = *(ckt->CKTstate0 + inst->NBJT2vbe) -
|
||||
*(ckt->CKTstate0 + inst->NBJT2vce);
|
||||
vbc = inst->NBJT2type * limitJunctionVoltage(inst->NBJT2type * vbc,
|
||||
inst->NBJT2type * vbc0, &icheck);
|
||||
if (icheck1 == 1)
|
||||
icheck = 1;
|
||||
vce = vbe - vbc;
|
||||
} else {
|
||||
vbe = inst->NBJT2type * limitJunctionVoltage(inst->NBJT2type * vbe,
|
||||
inst->NBJT2type * *(ckt->CKTstate0 + inst->NBJT2vbe), &icheck);
|
||||
vce = inst->NBJT2type * limitVce(inst->NBJT2type * vce,
|
||||
inst->NBJT2type * *(ckt->CKTstate0 + inst->NBJT2vce), &icheck1);
|
||||
if (icheck1 == 1)
|
||||
icheck = 1;
|
||||
}
|
||||
delVbe = vbe - *(ckt->CKTstate0 + inst->NBJT2vbe);
|
||||
delVce = vce - *(ckt->CKTstate0 + inst->NBJT2vce);
|
||||
NBJT2setBCs(pDevice, vce - delVce, vbe - delVbe);
|
||||
}
|
||||
|
||||
if (doInitSolve) {
|
||||
if (TWOdcDebug) {
|
||||
printVoltages(stdout, model->NBJT2modName, inst->NBJT2name,
|
||||
deviceType, 2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
startTime2 = SPfrontEnd->IFseconds();
|
||||
TWOequilSolve(pDevice);
|
||||
totalTime2 = SPfrontEnd->IFseconds() - startTime2;
|
||||
pDevice->pStats->totalTime[STAT_SETUP] += totalTime2;
|
||||
pDevice->pStats->totalTime[STAT_DC] -= totalTime2;
|
||||
|
||||
TWObiasSolve(pDevice, MaxIterations, FALSE, NULL);
|
||||
|
||||
*(ckt->CKTstate0 + inst->NBJT2vbe) = 0.0;
|
||||
*(ckt->CKTstate0 + inst->NBJT2vce) = 0.0;
|
||||
|
||||
if (initStateName != NULL) {
|
||||
if (TWOreadState(pDevice, initStateName, 2, &vce, &vbe, NULL ) < 0) {
|
||||
fprintf(stderr,
|
||||
"NBJT2load: trouble reading state-file %s\n", initStateName);
|
||||
} else {
|
||||
NBJT2setBCs(pDevice, vce, vbe);
|
||||
delVce = delVbe = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* determine dc current and derivatives using the numerical routines
|
||||
*/
|
||||
if (ckt->CKTmode & (MODEDCOP | MODETRANOP | MODEDCTRANCURVE | MODEINITSMSIG)) {
|
||||
|
||||
numDevNonCon = 0;
|
||||
inst->NBJT2c11 = inst->NBJT2y11r = inst->NBJT2y11i = 0.0;
|
||||
inst->NBJT2c12 = inst->NBJT2y12r = inst->NBJT2y12i = 0.0;
|
||||
inst->NBJT2c21 = inst->NBJT2y21r = inst->NBJT2y21i = 0.0;
|
||||
inst->NBJT2c22 = inst->NBJT2y22r = inst->NBJT2y22i = 0.0;
|
||||
inst->NBJT2smSigAvail = FALSE;
|
||||
devNonCon:
|
||||
NBJT2project(pDevice, delVce, delVbe);
|
||||
if (TWOdcDebug) {
|
||||
printVoltages(stdout, model->NBJT2modName, inst->NBJT2name,
|
||||
deviceType, 2, vce, delVce, vbe, delVbe, 0.0, 0.0);
|
||||
}
|
||||
TWObiasSolve(pDevice, MaxIterations, FALSE, model->NBJT2pInfo);
|
||||
|
||||
devConverged = pDevice->converged;
|
||||
if (devConverged && finite(pDevice->rhsNorm)) {
|
||||
/* compute the currents */
|
||||
NBJT2current(pDevice, FALSE, (double *) NULL, &ie, &ic);
|
||||
NBJT2conductance(pDevice, FALSE, (double *) NULL,
|
||||
&dIeDVce, &dIcDVce, &dIeDVbe, &dIcDVbe);
|
||||
|
||||
} else {
|
||||
/* reduce the voltage step until converged */
|
||||
/* restore boundary nodes to previous potential */
|
||||
NBJT2setBCs(pDevice, vce - delVce, vbe - delVbe);
|
||||
TWOstoreInitialGuess(pDevice);
|
||||
TWOresetJacobian(pDevice);
|
||||
delVbe *= 0.5;
|
||||
delVce *= 0.5;
|
||||
vbe = delVbe + *(ckt->CKTstate0 + inst->NBJT2vbe);
|
||||
vce = delVce + *(ckt->CKTstate0 + inst->NBJT2vce);
|
||||
numDevNonCon++;
|
||||
icheck = 1;
|
||||
if (numDevNonCon > 10) {
|
||||
printVoltages(stderr, model->NBJT2modName, inst->NBJT2name,
|
||||
deviceType, 2, vce, delVce, vbe, delVbe, 0.0, 0.0);
|
||||
fprintf(stderr, "*** Non-convergence during load ***\n");
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
return (E_BADMATRIX);
|
||||
} else {
|
||||
goto devNonCon;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((ckt->CKTmode & (MODETRAN | MODEAC)) ||
|
||||
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) ||
|
||||
(ckt->CKTmode & MODEINITSMSIG)) {
|
||||
/*
|
||||
* store small-signal parameters
|
||||
*/
|
||||
if ((!(ckt->CKTmode & MODETRANOP)) ||
|
||||
(!(ckt->CKTmode & MODEUIC))) {
|
||||
if (ckt->CKTmode & MODEINITSMSIG) {
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
startTime2 = SPfrontEnd->IFseconds();
|
||||
NBJT2initSmSig(inst);
|
||||
pDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime2;
|
||||
continue;
|
||||
} else {
|
||||
inst->NBJT2smSigAvail = FALSE;
|
||||
}
|
||||
/*
|
||||
* transient analysis
|
||||
*/
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
NBJT2setBCs(pDevice, vce, vbe);
|
||||
TWOstoreInitialGuess(pDevice);
|
||||
} else {
|
||||
NBJT2update(pDevice, delVce, delVbe, TRUE);
|
||||
}
|
||||
if (TWOtranDebug) {
|
||||
printVoltages(stdout, model->NBJT2modName, inst->NBJT2name,
|
||||
deviceType, 2, vce, delVce, vbe, delVbe, 0.0, 0.0);
|
||||
}
|
||||
TWObiasSolve(pDevice, 0, TRUE, model->NBJT2pInfo);
|
||||
if (!finite(pDevice->rhsNorm)) {
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
return (E_BADMATRIX);
|
||||
}
|
||||
devConverged = TWOdeviceConverged(pDevice);
|
||||
pDevice->converged = devConverged;
|
||||
|
||||
/* compute the currents */
|
||||
NBJT2current(pDevice, TRUE,
|
||||
model->NBJT2pInfo->intCoeff, &ie, &ic);
|
||||
NBJT2conductance(pDevice, TRUE,
|
||||
model->NBJT2pInfo->intCoeff,
|
||||
&dIeDVce, &dIcDVce, &dIeDVbe, &dIcDVbe);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check convergence
|
||||
*/
|
||||
if ((!(ckt->CKTmode & MODEINITFIX)) || (!(inst->NBJT2off))) {
|
||||
if (icheck == 1 || !devConverged) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
} else {
|
||||
tol = ckt->CKTreltol * MAX(fabs(ichat), fabs(ic)) + ckt->CKTabstol;
|
||||
if (fabs(ichat - ic) > tol) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
} else {
|
||||
tol = ckt->CKTreltol * MAX(fabs(iehat), fabs(ie)) +
|
||||
ckt->CKTabstol;
|
||||
if (fabs(iehat - ie) > tol) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*(ckt->CKTstate0 + inst->NBJT2vbe) = vbe;
|
||||
*(ckt->CKTstate0 + inst->NBJT2vce) = vce;
|
||||
*(ckt->CKTstate0 + inst->NBJT2ic) = ic;
|
||||
*(ckt->CKTstate0 + inst->NBJT2ie) = ie;
|
||||
*(ckt->CKTstate0 + inst->NBJT2dIeDVce) = dIeDVce;
|
||||
*(ckt->CKTstate0 + inst->NBJT2dIeDVbe) = dIeDVbe;
|
||||
*(ckt->CKTstate0 + inst->NBJT2dIcDVce) = dIcDVce;
|
||||
*(ckt->CKTstate0 + inst->NBJT2dIcDVbe) = dIcDVbe;
|
||||
|
||||
load:
|
||||
/*
|
||||
* load current excitation vector
|
||||
*/
|
||||
|
||||
iceq = ic - dIcDVce * vce - dIcDVbe * vbe;
|
||||
ieeq = ie - dIeDVce * vce - dIeDVbe * vbe;
|
||||
*(ckt->CKTrhs + inst->NBJT2colNode) -= iceq;
|
||||
*(ckt->CKTrhs + inst->NBJT2baseNode) += ieeq + iceq;
|
||||
*(ckt->CKTrhs + inst->NBJT2emitNode) -= ieeq;
|
||||
/*
|
||||
* load y matrix
|
||||
*/
|
||||
*(inst->NBJT2colColPtr) += dIcDVce;
|
||||
*(inst->NBJT2colBasePtr) += dIcDVbe;
|
||||
*(inst->NBJT2colEmitPtr) -= dIcDVbe + dIcDVce;
|
||||
*(inst->NBJT2baseColPtr) -= dIcDVce + dIeDVce;
|
||||
*(inst->NBJT2baseBasePtr) -= dIcDVbe + dIeDVbe;
|
||||
*(inst->NBJT2baseEmitPtr) += dIcDVbe + dIcDVce + dIeDVbe + dIeDVce;
|
||||
*(inst->NBJT2emitColPtr) += dIeDVce;
|
||||
*(inst->NBJT2emitBasePtr) += dIeDVbe;
|
||||
*(inst->NBJT2emitEmitPtr) -= dIeDVbe + dIeDVce;
|
||||
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
if (ckt->CKTmode & MODETRAN) {
|
||||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime;
|
||||
} else {
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
||||
int
|
||||
NBJT2initSmSig(inst)
|
||||
NBJT2instance *inst;
|
||||
{
|
||||
SPcomplex yIeVce, yIeVbe;
|
||||
SPcomplex yIcVce, yIcVbe;
|
||||
double omega = inst->NBJT2modPtr->NBJT2methods->METHomega;
|
||||
|
||||
AcAnalysisMethod = SOR_ONLY;
|
||||
(void) NBJT2admittance(inst->NBJT2pDevice, omega,
|
||||
&yIeVce, &yIcVce, &yIeVbe, &yIcVbe);
|
||||
inst->NBJT2c11 = yIcVce.imag / omega;
|
||||
inst->NBJT2c12 = yIcVbe.imag / omega;
|
||||
inst->NBJT2c21 = (yIeVce.imag - yIcVce.imag) / omega;
|
||||
inst->NBJT2c22 = (yIeVbe.imag - yIcVbe.imag) / omega;
|
||||
inst->NBJT2y11r = yIcVce.real;
|
||||
inst->NBJT2y11i = yIcVce.imag;
|
||||
inst->NBJT2y12r = yIcVbe.real;
|
||||
inst->NBJT2y12i = yIcVbe.imag;
|
||||
inst->NBJT2y21r = yIeVce.real - yIcVce.real;
|
||||
inst->NBJT2y21i = yIeVce.imag - yIcVce.imag;
|
||||
inst->NBJT2y22r = yIeVbe.real - yIcVbe.real;
|
||||
inst->NBJT2y22i = yIeVbe.imag - yIcVbe.imag;
|
||||
inst->NBJT2smSigAvail = TRUE;
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine deletes a NBJT2 model from the circuit and frees the storage
|
||||
* it was using. returns an error if the model has instances
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NBJT2mDelete(inModel, modname, kill)
|
||||
GENmodel **inModel;
|
||||
IFuid modname;
|
||||
GENmodel *kill;
|
||||
|
||||
{
|
||||
|
||||
NBJT2model **model = (NBJT2model **) inModel;
|
||||
NBJT2model *modfast = (NBJT2model *) kill;
|
||||
NBJT2model **oldmod;
|
||||
oldmod = model;
|
||||
for (; *model; model = &((*model)->NBJT2nextModel)) {
|
||||
if ((*model)->NBJT2modName == modname ||
|
||||
(modfast && *model == modfast))
|
||||
goto delgot;
|
||||
oldmod = model;
|
||||
}
|
||||
return (E_NOMOD);
|
||||
|
||||
delgot:
|
||||
if ((*model)->NBJT2instances)
|
||||
return (E_NOTEMPTY);
|
||||
*oldmod = (*model)->NBJT2nextModel; /* cut deleted device out of list */
|
||||
FREE(*model);
|
||||
return (OK);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine sets model parameters for NBJT2s in the circuit.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NBJT2mParam(param, value, inModel)
|
||||
int param;
|
||||
IFvalue *value;
|
||||
GENmodel *inModel;
|
||||
{
|
||||
switch (param) {
|
||||
case NBJT2_MOD_NBJT:
|
||||
/* no action - already know it is a 2d-numerical bjt, but this */
|
||||
/* makes life easier for spice-2 like parsers */
|
||||
break;
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine sets instance parameters for NBJT2s in the circuit.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NBJT2param(param, value, inInst, select)
|
||||
int param;
|
||||
IFvalue *value;
|
||||
GENinstance *inInst;
|
||||
IFvalue *select;
|
||||
{
|
||||
register NBJT2instance *inst = (NBJT2instance *) inInst;
|
||||
switch (param) {
|
||||
case NBJT2_WIDTH:
|
||||
inst->NBJT2width = value->rValue;
|
||||
inst->NBJT2widthGiven = TRUE;
|
||||
break;
|
||||
case NBJT2_AREA:
|
||||
inst->NBJT2area = value->rValue;
|
||||
inst->NBJT2areaGiven = TRUE;
|
||||
break;
|
||||
case NBJT2_OFF:
|
||||
inst->NBJT2off = TRUE;
|
||||
break;
|
||||
case NBJT2_IC_FILE:
|
||||
inst->NBJT2icFile = value->sValue;
|
||||
inst->NBJT2icFileGiven = TRUE;
|
||||
break;
|
||||
case NBJT2_PRINT:
|
||||
inst->NBJT2print = value->rValue;
|
||||
inst->NBJT2printGiven = TRUE;
|
||||
break;
|
||||
case NBJT2_TEMP:
|
||||
inst->NBJT2temp = value->rValue + CONSTCtoK;
|
||||
inst->NBJT2tempGiven = TRUE;
|
||||
break;
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "complex.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* External Declarations */
|
||||
extern int TWOacDebug;
|
||||
|
||||
int
|
||||
NBJT2pzLoad(inModel, ckt, s)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
SPcomplex *s;
|
||||
{
|
||||
register NBJT2model *model = (NBJT2model *) inModel;
|
||||
register NBJT2instance *inst;
|
||||
SPcomplex yIeVce, yIeVbe;
|
||||
SPcomplex yIcVce, yIcVbe;
|
||||
double startTime;
|
||||
|
||||
for (; model != NULL; model = model->NBJT2nextModel) {
|
||||
FieldDepMobility = model->NBJT2models->MODLfieldDepMobility;
|
||||
TransDepMobility = model->NBJT2models->MODLtransDepMobility;
|
||||
SurfaceMobility = model->NBJT2models->MODLsurfaceMobility;
|
||||
Srh = model->NBJT2models->MODLsrh;
|
||||
Auger = model->NBJT2models->MODLauger;
|
||||
AvalancheGen = model->NBJT2models->MODLavalancheGen;
|
||||
OneCarrier = model->NBJT2methods->METHoneCarrier;
|
||||
AcAnalysisMethod = model->NBJT2methods->METHacAnalysisMethod;
|
||||
MobDeriv = model->NBJT2methods->METHmobDeriv;
|
||||
TWOacDebug = model->NBJT2outputs->OUTPacDebug;
|
||||
|
||||
for (inst = model->NBJT2instances; inst != NULL;
|
||||
inst = inst->NBJT2nextInstance) {
|
||||
if (inst->NBJT2owner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NBJT2globals));
|
||||
|
||||
NBJT2ys(inst->NBJT2pDevice, s,
|
||||
&yIeVce, &yIcVce, &yIeVbe, &yIcVbe);
|
||||
|
||||
*(inst->NBJT2colColPtr) += yIcVce.real;
|
||||
*(inst->NBJT2colColPtr + 1) += yIcVce.imag;
|
||||
*(inst->NBJT2colBasePtr) += yIcVbe.real;
|
||||
*(inst->NBJT2colBasePtr + 1) += yIcVbe.imag;
|
||||
*(inst->NBJT2colEmitPtr) -= yIcVbe.real + yIcVce.real;
|
||||
*(inst->NBJT2colEmitPtr + 1) -= yIcVbe.imag + yIcVce.imag;
|
||||
*(inst->NBJT2baseColPtr) -= yIcVce.real + yIeVce.real;
|
||||
*(inst->NBJT2baseColPtr + 1) -= yIcVce.imag + yIeVce.imag;
|
||||
*(inst->NBJT2baseBasePtr) -= yIcVbe.real + yIeVbe.real;
|
||||
*(inst->NBJT2baseBasePtr + 1) -= yIcVbe.imag + yIeVbe.imag;
|
||||
*(inst->NBJT2baseEmitPtr) += yIcVbe.real + yIcVce.real + yIeVbe.real + yIeVce.real;
|
||||
*(inst->NBJT2baseEmitPtr + 1) += yIcVbe.imag + yIcVce.imag + yIeVbe.imag + yIeVce.imag;
|
||||
*(inst->NBJT2emitColPtr) += yIeVce.real;
|
||||
*(inst->NBJT2emitColPtr + 1) += yIeVce.imag;
|
||||
*(inst->NBJT2emitBasePtr) += yIeVbe.real;
|
||||
*(inst->NBJT2emitBasePtr + 1) += yIeVbe.imag;
|
||||
*(inst->NBJT2emitEmitPtr) -= yIeVbe.real + yIeVce.real;
|
||||
*(inst->NBJT2emitEmitPtr + 1) -= yIeVbe.imag + yIeVce.imag;
|
||||
|
||||
inst->NBJT2pDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,274 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "smpdefs.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "numconst.h"
|
||||
#include "numenum.h"
|
||||
#include "meshext.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "ciderinp.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#define NIL(type) ((type *)0)
|
||||
#define TSCALLOC(var, size, type)\
|
||||
if (size && (!(var =(type *)calloc(1, (unsigned)(size)*sizeof(type))))) {\
|
||||
return(E_NOMEM);\
|
||||
}
|
||||
|
||||
int
|
||||
NBJT2setup(matrix, inModel, ckt, states)
|
||||
register SMPmatrix *matrix;
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
int *states;
|
||||
/*
|
||||
* load the structure with those pointers needed later for fast matrix
|
||||
* loading
|
||||
*/
|
||||
{
|
||||
register NBJT2model *model = (NBJT2model *) inModel;
|
||||
register NBJT2instance *inst;
|
||||
METHcard *methods;
|
||||
MODLcard *models;
|
||||
OPTNcard *options;
|
||||
OUTPcard *outputs;
|
||||
char *icFileName = NULL;
|
||||
int nameLen;
|
||||
int error, xIndex, yIndex;
|
||||
int xMeshSize, yMeshSize;
|
||||
TWOdevice *pDevice;
|
||||
TWOcoord *xCoordList = NIL(TWOcoord);
|
||||
TWOcoord *yCoordList = NIL(TWOcoord);
|
||||
TWOdomain *domainList = NIL(TWOdomain);
|
||||
TWOelectrode *electrodeList = NIL(TWOelectrode);
|
||||
TWOmaterial *pM, *pMaterial = NIL(TWOmaterial), *materialList = NIL(TWOmaterial);
|
||||
DOPprofile *profileList = NIL(DOPprofile);
|
||||
DOPtable *dopTableList = NIL(DOPtable);
|
||||
double startTime;
|
||||
|
||||
|
||||
|
||||
/* loop through all the models */
|
||||
for (; model != NULL; model = model->NBJT2nextModel) {
|
||||
if (!model->NBJT2pInfo) {
|
||||
TSCALLOC(model->NBJT2pInfo, 1, TWOtranInfo);
|
||||
}
|
||||
methods = model->NBJT2methods;
|
||||
if (!methods) {
|
||||
TSCALLOC(methods, 1, METHcard);
|
||||
model->NBJT2methods = methods;
|
||||
}
|
||||
models = model->NBJT2models;
|
||||
if (!models) {
|
||||
TSCALLOC(models, 1, MODLcard);
|
||||
model->NBJT2models = models;
|
||||
}
|
||||
options = model->NBJT2options;
|
||||
if (!options) {
|
||||
TSCALLOC(options, 1, OPTNcard);
|
||||
model->NBJT2options = options;
|
||||
}
|
||||
outputs = model->NBJT2outputs;
|
||||
if (!outputs) {
|
||||
TSCALLOC(outputs, 1, OUTPcard);
|
||||
model->NBJT2outputs = outputs;
|
||||
}
|
||||
if (!methods->METHvoltPredGiven) {
|
||||
methods->METHvoltPred = FALSE;
|
||||
}
|
||||
if (!methods->METHmobDerivGiven) {
|
||||
methods->METHmobDeriv = TRUE;
|
||||
}
|
||||
if (!methods->METHoneCarrierGiven) {
|
||||
methods->METHoneCarrier = FALSE;
|
||||
}
|
||||
if (!methods->METHacAnalysisMethodGiven) {
|
||||
methods->METHacAnalysisMethod = SOR;
|
||||
}
|
||||
if (!methods->METHdabstolGiven) {
|
||||
methods->METHdabstol = DABSTOL2D;
|
||||
}
|
||||
if (!methods->METHdreltolGiven) {
|
||||
methods->METHdreltol = ckt->CKTreltol;
|
||||
}
|
||||
if (!methods->METHitLimGiven) {
|
||||
methods->METHitLim = 50;
|
||||
}
|
||||
if (!methods->METHomegaGiven || methods->METHomega <= 0.0) {
|
||||
methods->METHomega = 2.0 * M_PI /* radians/sec */ ;
|
||||
}
|
||||
if (!options->OPTNdefaGiven || options->OPTNdefa <= 0.0) {
|
||||
options->OPTNdefa = 1.0e4 /* cm^2 */ ;
|
||||
}
|
||||
if (!options->OPTNdeflGiven || options->OPTNdefl <= 0.0) {
|
||||
options->OPTNdefl = 1.0e2 /* cm */ ;
|
||||
}
|
||||
if (!options->OPTNdefwGiven && options->OPTNdefaGiven) {
|
||||
options->OPTNdefw = options->OPTNdefa / options->OPTNdefl;
|
||||
} else if (!options->OPTNdefwGiven || options->OPTNdefw <= 0.0) {
|
||||
options->OPTNdefw = 1.0e2 /* cm */ ;
|
||||
}
|
||||
if (!options->OPTNdeviceTypeGiven) {
|
||||
options->OPTNdeviceType = OPTN_BIPOLAR;
|
||||
}
|
||||
if (!options->OPTNicFileGiven) {
|
||||
options->OPTNicFile = NULL;
|
||||
options->OPTNunique = FALSE; /* Can't form a unique name. */
|
||||
}
|
||||
if (!options->OPTNuniqueGiven) {
|
||||
options->OPTNunique = FALSE;
|
||||
}
|
||||
OneCarrier = methods->METHoneCarrier;
|
||||
|
||||
/* Set up the rest of the card lists */
|
||||
if ((error = MODLsetup(model->NBJT2models)))
|
||||
return (error);
|
||||
BandGapNarrowing = models->MODLbandGapNarrowing;
|
||||
ConcDepLifetime = models->MODLconcDepLifetime;
|
||||
TempDepMobility = models->MODLtempDepMobility;
|
||||
ConcDepMobility = models->MODLconcDepMobility;
|
||||
SurfaceMobility = models->MODLsurfaceMobility;
|
||||
|
||||
if ((error = OUTPsetup(model->NBJT2outputs)))
|
||||
return (error);
|
||||
if ((error = MATLsetup(model->NBJT2materials, &materialList)))
|
||||
return (error);
|
||||
if ((error = MOBsetup(model->NBJT2mobility, materialList)))
|
||||
return (error);
|
||||
if ((error = MESHsetup('x', model->NBJT2xMeshes, &xCoordList, &xMeshSize)))
|
||||
return (error);
|
||||
if ((error = MESHsetup('y', model->NBJT2yMeshes, &yCoordList, &yMeshSize)))
|
||||
return (error);
|
||||
if ((error = DOMNsetup(model->NBJT2domains, &domainList,
|
||||
xCoordList, yCoordList, materialList)))
|
||||
return (error);
|
||||
if ((error = BDRYsetup(model->NBJT2boundaries,
|
||||
xCoordList, yCoordList, domainList)))
|
||||
return (error);
|
||||
if ((error = ELCTsetup(model->NBJT2electrodes, &electrodeList,
|
||||
xCoordList, yCoordList)))
|
||||
return (error);
|
||||
/* Make sure electrodes are OK. */
|
||||
checkElectrodes(electrodeList, 3); /* NBJT2 has 3 electrodes */
|
||||
|
||||
if ((error = CONTsetup(model->NBJT2contacts, electrodeList)))
|
||||
return (error);
|
||||
if ((error = DOPsetup(model->NBJT2dopings, &profileList,
|
||||
&dopTableList, xCoordList, yCoordList)))
|
||||
return (error);
|
||||
model->NBJT2matlInfo = materialList;
|
||||
model->NBJT2profiles = profileList;
|
||||
model->NBJT2dopTables = dopTableList;
|
||||
|
||||
/* loop through all the instances of the model */
|
||||
for (inst = model->NBJT2instances; inst != NULL;
|
||||
inst = inst->NBJT2nextInstance) {
|
||||
if (inst->NBJT2owner != ARCHme) goto matrixpointers;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
if (!inst->NBJT2printGiven) {
|
||||
inst->NBJT2print = 0;
|
||||
} else if (inst->NBJT2print <= 0) {
|
||||
inst->NBJT2print = 1;
|
||||
}
|
||||
if (!inst->NBJT2icFileGiven) {
|
||||
if (options->OPTNunique) {
|
||||
nameLen = strlen(options->OPTNicFile) + strlen(inst->NBJT2name) + 1;
|
||||
TSCALLOC(icFileName, nameLen+1, char);
|
||||
sprintf(icFileName, "%s.%s", options->OPTNicFile, inst->NBJT2name);
|
||||
icFileName[nameLen] = '\0';
|
||||
inst->NBJT2icFile = icFileName;
|
||||
} else if (options->OPTNicFile != NULL) {
|
||||
nameLen = strlen(options->OPTNicFile);
|
||||
TSCALLOC(icFileName, nameLen+1, char);
|
||||
icFileName = strcpy(icFileName, options->OPTNicFile);
|
||||
inst->NBJT2icFile = icFileName;
|
||||
} else {
|
||||
inst->NBJT2icFile = NULL;
|
||||
}
|
||||
}
|
||||
inst->NBJT2state = *states;
|
||||
*states += NBJT2numStates;
|
||||
|
||||
if (!inst->NBJT2pDevice) {
|
||||
/* Assign the mesh and profile info to each instance. */
|
||||
TSCALLOC(pDevice, 1, TWOdevice);
|
||||
TSCALLOC(pDevice->pStats, 1, TWOstats);
|
||||
pDevice->name = inst->NBJT2name;
|
||||
pDevice->solverType = SLV_NONE;
|
||||
pDevice->numXNodes = xMeshSize;
|
||||
pDevice->numYNodes = yMeshSize;
|
||||
pDevice->xScale = MESHmkArray(xCoordList, xMeshSize);
|
||||
pDevice->yScale = MESHmkArray(yCoordList, yMeshSize);
|
||||
pDevice->abstol = methods->METHdabstol;
|
||||
pDevice->reltol = methods->METHdreltol;
|
||||
pDevice->rhsImag = NIL(double);
|
||||
TSCALLOC(pDevice->elemArray, pDevice->numXNodes, TWOelem **);
|
||||
for (xIndex = 1; xIndex < pDevice->numXNodes; xIndex++) {
|
||||
TSCALLOC(pDevice->elemArray[xIndex], pDevice->numYNodes, TWOelem *);
|
||||
}
|
||||
|
||||
/* Create a copy of material data that can change with temperature. */
|
||||
pDevice->pMaterials = NIL(TWOmaterial);
|
||||
for (pM = materialList; pM != NIL(TWOmaterial); pM = pM->next) {
|
||||
if (pDevice->pMaterials == NIL(TWOmaterial)) {
|
||||
TSCALLOC(pMaterial, 1, TWOmaterial);
|
||||
pDevice->pMaterials = pMaterial;
|
||||
} else {
|
||||
TSCALLOC(pMaterial->next, 1, TWOmaterial);
|
||||
pMaterial = pMaterial->next;
|
||||
}
|
||||
/* Copy everything, then fix the incorrect pointer. */
|
||||
bcopy((char *) pM, (char *) pMaterial, sizeof(TWOmaterial));
|
||||
pMaterial->next = NIL(TWOmaterial);
|
||||
}
|
||||
|
||||
/* Generate the mesh structure for the device. */
|
||||
TWObuildMesh(pDevice, domainList, electrodeList, pDevice->pMaterials);
|
||||
|
||||
/* Store the device info in the instance. */
|
||||
inst->NBJT2pDevice = pDevice;
|
||||
}
|
||||
/* Now update the state pointers. */
|
||||
TWOgetStatePointers(inst->NBJT2pDevice, states);
|
||||
|
||||
/* Wipe out statistics from previous runs (if any). */
|
||||
bzero((char *) inst->NBJT2pDevice->pStats, sizeof(TWOstats));
|
||||
|
||||
inst->NBJT2pDevice->pStats->totalTime[STAT_SETUP] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
|
||||
/* macro to make elements with built in test for out of memory */
|
||||
#define TSTALLOC(ptr,first,second) \
|
||||
if ((inst->ptr = SMPmakeElt(matrix,inst->first,inst->second))==(double *)NULL){\
|
||||
return(E_NOMEM);\
|
||||
}
|
||||
|
||||
matrixpointers:
|
||||
TSTALLOC(NBJT2colColPtr, NBJT2colNode, NBJT2colNode)
|
||||
TSTALLOC(NBJT2colBasePtr, NBJT2colNode, NBJT2baseNode)
|
||||
TSTALLOC(NBJT2colEmitPtr, NBJT2colNode, NBJT2emitNode)
|
||||
TSTALLOC(NBJT2baseColPtr, NBJT2baseNode, NBJT2colNode)
|
||||
TSTALLOC(NBJT2baseBasePtr, NBJT2baseNode, NBJT2baseNode)
|
||||
TSTALLOC(NBJT2baseEmitPtr, NBJT2baseNode, NBJT2emitNode)
|
||||
TSTALLOC(NBJT2emitColPtr, NBJT2emitNode, NBJT2colNode)
|
||||
TSTALLOC(NBJT2emitBasePtr, NBJT2emitNode, NBJT2baseNode)
|
||||
TSTALLOC(NBJT2emitEmitPtr, NBJT2emitNode, NBJT2emitNode)
|
||||
}
|
||||
/* Clean up lists */
|
||||
killCoordInfo(xCoordList);
|
||||
killCoordInfo(yCoordList);
|
||||
killDomainInfo(domainList);
|
||||
killElectrodeInfo(electrodeList);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
Author: 1992 David A. Gates, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "numenum.h"
|
||||
#include "carddefs.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#define NIL(type) ((type *)0)
|
||||
|
||||
int
|
||||
NBJT2temp(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
register CKTcircuit *ckt;
|
||||
/*
|
||||
* perform the temperature update
|
||||
*/
|
||||
{
|
||||
register NBJT2model *model = (NBJT2model *) inModel;
|
||||
register NBJT2instance *inst;
|
||||
METHcard *methods;
|
||||
MODLcard *models;
|
||||
OPTNcard *options;
|
||||
OUTPcard *outputs;
|
||||
TWOmaterial *pM, *pMaterial, *pNextMaterial;
|
||||
double startTime;
|
||||
|
||||
|
||||
/* loop through all the models */
|
||||
for (; model != NULL; model = model->NBJT2nextModel) {
|
||||
methods = model->NBJT2methods;
|
||||
models = model->NBJT2models;
|
||||
options = model->NBJT2options;
|
||||
outputs = model->NBJT2outputs;
|
||||
|
||||
if (!options->OPTNtnomGiven) {
|
||||
options->OPTNtnom = ckt->CKTnomTemp;
|
||||
}
|
||||
for (pM = model->NBJT2matlInfo; pM != NIL(TWOmaterial);
|
||||
pM = pM->next) {
|
||||
pM->tnom = options->OPTNtnom;
|
||||
}
|
||||
|
||||
BandGapNarrowing = models->MODLbandGapNarrowing;
|
||||
ConcDepLifetime = models->MODLconcDepLifetime;
|
||||
TempDepMobility = models->MODLtempDepMobility;
|
||||
ConcDepMobility = models->MODLconcDepMobility;
|
||||
SurfaceMobility = models->MODLsurfaceMobility;
|
||||
MatchingMobility = models->MODLmatchingMobility;
|
||||
OneCarrier = methods->METHoneCarrier;
|
||||
|
||||
for (inst = model->NBJT2instances; inst != NULL;
|
||||
inst = inst->NBJT2nextInstance) {
|
||||
if (inst->NBJT2owner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
if (!inst->NBJT2tempGiven) {
|
||||
inst->NBJT2temp = ckt->CKTtemp;
|
||||
}
|
||||
if (!inst->NBJT2areaGiven || inst->NBJT2area <= 0.0) {
|
||||
inst->NBJT2area = 1.0;
|
||||
}
|
||||
if (!inst->NBJT2widthGiven || inst->NBJT2width <= 0.0) {
|
||||
inst->NBJT2width = 1.0;
|
||||
}
|
||||
inst->NBJT2pDevice->width =
|
||||
inst->NBJT2area * inst->NBJT2width * options->OPTNdefw;
|
||||
|
||||
/* Compute and save globals for this instance. */
|
||||
GLOBcomputeGlobals(&(inst->NBJT2globals), inst->NBJT2temp);
|
||||
|
||||
/* Calculate new sets of material parameters. */
|
||||
pM = model->NBJT2matlInfo;
|
||||
pMaterial = inst->NBJT2pDevice->pMaterials;
|
||||
for (; pM != NULL; pM = pM->next, pMaterial = pMaterial->next) {
|
||||
|
||||
/* Copy everything, then fix the incorrect pointer. */
|
||||
pNextMaterial = pMaterial->next;
|
||||
bcopy((char *) pM, (char *) pMaterial, sizeof(TWOmaterial));
|
||||
pMaterial->next = pNextMaterial;
|
||||
|
||||
/* Now do the temperature dependence. */
|
||||
MATLtempDep(pMaterial, pMaterial->tnom);
|
||||
if (outputs->OUTPmaterial) {
|
||||
printMaterialInfo(pMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign doping to the mesh. */
|
||||
TWOsetDoping(inst->NBJT2pDevice, model->NBJT2profiles,
|
||||
model->NBJT2dopTables);
|
||||
|
||||
/* Assign physical parameters to the mesh. */
|
||||
TWOsetup(inst->NBJT2pDevice);
|
||||
|
||||
/* Assign boundary condition parameters. */
|
||||
TWOsetBCparams(inst->NBJT2pDevice, model->NBJT2boundaries);
|
||||
|
||||
/* Normalize everything. */
|
||||
TWOnormalize(inst->NBJT2pDevice);
|
||||
|
||||
/* Find the device's type. */
|
||||
if (inst->NBJT2pDevice->pFirstContact->pNodes[0]->netConc < 0.0) {
|
||||
inst->NBJT2type = PNP;
|
||||
if (OneCarrier) {
|
||||
methods->METHoneCarrier = P_TYPE;
|
||||
}
|
||||
} else {
|
||||
inst->NBJT2type = NPN;
|
||||
if (OneCarrier) {
|
||||
methods->METHoneCarrier = N_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
inst->NBJT2pDevice->pStats->totalTime[STAT_SETUP] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine performs truncation error calculations for NBJT2s in the
|
||||
* circuit.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "nbjt2def.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
|
||||
int
|
||||
NBJT2trunc(inModel, ckt, timeStep)
|
||||
GENmodel *inModel;
|
||||
register CKTcircuit *ckt;
|
||||
double *timeStep;
|
||||
|
||||
{
|
||||
register NBJT2model *model = (NBJT2model *) inModel;
|
||||
register NBJT2instance *inst;
|
||||
double deltaNew;
|
||||
double deltaNorm[7];
|
||||
double startTime;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
|
||||
for (; model != NULL; model = model->NBJT2nextModel) {
|
||||
OneCarrier = model->NBJT2methods->METHoneCarrier;
|
||||
model->NBJT2pInfo->order = ckt->CKTorder;
|
||||
model->NBJT2pInfo->delta = deltaNorm;
|
||||
model->NBJT2pInfo->lteCoeff = computeLTECoeff(model->NBJT2pInfo);
|
||||
for (inst = model->NBJT2instances; inst != NULL;
|
||||
inst = inst->NBJT2nextInstance) {
|
||||
if (inst->NBJT2owner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
deltaNew = TWOtrunc(inst->NBJT2pDevice, model->NBJT2pInfo,
|
||||
ckt->CKTdelta);
|
||||
*timeStep = MIN(*timeStep, deltaNew);
|
||||
inst->NBJT2pDevice->pStats->totalTime[STAT_TRAN] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
noinst_LIBRARIES = libnumd.a
|
||||
|
||||
libnumd_a_SOURCES = \
|
||||
numd.c \
|
||||
numdacld.c \
|
||||
numdask.c \
|
||||
numddefs.h \
|
||||
numddel.c \
|
||||
numddest.c \
|
||||
numddump.c \
|
||||
numdext.h \
|
||||
numdinit.c \
|
||||
numdinit.h \
|
||||
numditf.h \
|
||||
numdload.c \
|
||||
numdmdel.c \
|
||||
numdmpar.c \
|
||||
numdparm.c \
|
||||
numdpzld.c \
|
||||
numdset.c \
|
||||
numdtemp.c \
|
||||
numdtrun.c
|
||||
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/src/include
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "devdefs.h"
|
||||
#include "numddefs.h"
|
||||
#include "suffix.h"
|
||||
|
||||
IFparm NUMDpTable[] = { /* parameters */
|
||||
IP("off", NUMD_OFF, IF_FLAG, "Initially off"),
|
||||
IP("ic.file", NUMD_IC_FILE, IF_REAL, "Initial conditions file"),
|
||||
IOP("area", NUMD_AREA, IF_REAL, "Area factor"),
|
||||
IP("save", NUMD_PRINT, IF_REAL, "Save Solutions"),
|
||||
IP("print", NUMD_PRINT, IF_REAL, "Print Solutions"),
|
||||
OP("vd", NUMD_VD, IF_REAL, "Voltage"),
|
||||
OP("id", NUMD_ID, IF_REAL, "Current"),
|
||||
OP("g11", NUMD_G11, IF_REAL, "Conductance"),
|
||||
OP("c11", NUMD_C11, IF_REAL, "Capacitance"),
|
||||
OP("y11", NUMD_Y11, IF_COMPLEX, "Admittance"),
|
||||
OPU("g12", NUMD_G12, IF_REAL, "Conductance"),
|
||||
OPU("c12", NUMD_C12, IF_REAL, "Capacitance"),
|
||||
OPU("y12", NUMD_Y12, IF_COMPLEX, "Admittance"),
|
||||
OPU("g21", NUMD_G21, IF_REAL, "Conductance"),
|
||||
OPU("c21", NUMD_C21, IF_REAL, "Capacitance"),
|
||||
OPU("y21", NUMD_Y21, IF_COMPLEX, "Admittance"),
|
||||
OPU("g22", NUMD_G22, IF_REAL, "Conductance"),
|
||||
OPU("c22", NUMD_C22, IF_REAL, "Capacitance"),
|
||||
OPU("y22", NUMD_Y22, IF_COMPLEX, "Admittance"),
|
||||
OPR("voltage", NUMD_VD, IF_REAL, "Voltage"),
|
||||
OPR("current", NUMD_ID, IF_REAL, "Current"),
|
||||
OPR("conductance", NUMD_G11, IF_REAL, "Conductance"),
|
||||
OPR("capacitance", NUMD_C11, IF_REAL, "Capacitance"),
|
||||
IOP("temp", NUMD_TEMP, IF_REAL, "Instance Temperature")
|
||||
};
|
||||
|
||||
IFparm NUMDmPTable[] = { /* model parameters */
|
||||
/* numerical-device models no longer have parameters */
|
||||
/* one is left behind to keep the table from being empty */
|
||||
IP("numd", NUMD_MOD_NUMD, IF_REAL, "Numerical Diode")
|
||||
};
|
||||
|
||||
char *NUMDnames[] = {
|
||||
"D+",
|
||||
"D-"
|
||||
};
|
||||
|
||||
int NUMDnSize = NUMELEMS(NUMDnames);
|
||||
int NUMDpTSize = NUMELEMS(NUMDpTable);
|
||||
int NUMDmPTSize = NUMELEMS(NUMDmPTable);
|
||||
int NUMDiSize = sizeof(NUMDinstance);
|
||||
int NUMDmSize = sizeof(NUMDmodel);
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* Function to load the COMPLEX circuit matrix using the small signal
|
||||
* parameters saved during a previous DC operating point analysis.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numddefs.h"
|
||||
#include "sperror.h"
|
||||
#include "complex.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "numglobs.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* External Declarations */
|
||||
extern int ONEacDebug;
|
||||
|
||||
int
|
||||
NUMDacLoad(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
{
|
||||
register NUMDmodel *model = (NUMDmodel *) inModel;
|
||||
register NUMDinstance *inst;
|
||||
SPcomplex y;
|
||||
double startTime;
|
||||
|
||||
/* loop through all the diode models */
|
||||
for (; model != NULL; model = model->NUMDnextModel) {
|
||||
FieldDepMobility = model->NUMDmodels->MODLfieldDepMobility;
|
||||
Srh = model->NUMDmodels->MODLsrh;
|
||||
Auger = model->NUMDmodels->MODLauger;
|
||||
AvalancheGen = model->NUMDmodels->MODLavalancheGen;
|
||||
AcAnalysisMethod = model->NUMDmethods->METHacAnalysisMethod;
|
||||
MobDeriv = model->NUMDmethods->METHmobDeriv;
|
||||
ONEacDebug = model->NUMDoutputs->OUTPacDebug;
|
||||
|
||||
for (inst = model->NUMDinstances; inst != NULL;
|
||||
inst = inst->NUMDnextInstance) {
|
||||
if (inst->NUMDowner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NUMDglobals));
|
||||
|
||||
model->NUMDmethods->METHacAnalysisMethod =
|
||||
NUMDadmittance(inst->NUMDpDevice,
|
||||
ckt->CKTomega, &y);
|
||||
|
||||
*(inst->NUMDposPosPtr) += y.real;
|
||||
*(inst->NUMDposPosPtr + 1) += y.imag;
|
||||
*(inst->NUMDnegNegPtr) += y.real;
|
||||
*(inst->NUMDnegNegPtr + 1) += y.imag;
|
||||
*(inst->NUMDnegPosPtr) -= y.real;
|
||||
*(inst->NUMDnegPosPtr + 1) -= y.imag;
|
||||
*(inst->NUMDposNegPtr) -= y.real;
|
||||
*(inst->NUMDposNegPtr + 1) -= y.imag;
|
||||
if (ckt->CKTomega != 0.0) {
|
||||
inst->NUMDc11 = y.imag / ckt->CKTomega;
|
||||
} else {
|
||||
inst->NUMDc11 = 0.0; /* XXX What else can be done?! */
|
||||
}
|
||||
inst->NUMDy11r = y.real;
|
||||
inst->NUMDy11i = y.imag;
|
||||
inst->NUMDsmSigAvail = TRUE;
|
||||
inst->NUMDpDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Thomas L. Quarles
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "cktdefs.h"
|
||||
#include "devdefs.h"
|
||||
#include "numddefs.h"
|
||||
#include "complex.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* Check out this one */
|
||||
extern int NUMDinitSmSig(NUMDinstance *);
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
NUMDask(ckt, inInst, which, value, select)
|
||||
CKTcircuit *ckt;
|
||||
GENinstance *inInst;
|
||||
int which;
|
||||
IFvalue *value;
|
||||
IFvalue *select;
|
||||
{
|
||||
NUMDinstance *inst = (NUMDinstance *) inInst;
|
||||
SPcomplex yd;
|
||||
|
||||
switch (which) {
|
||||
case NUMD_AREA:
|
||||
value->rValue = inst->NUMDarea;
|
||||
return (OK);
|
||||
case NUMD_TEMP:
|
||||
value->rValue = inst->NUMDtemp - CONSTCtoK;
|
||||
return (OK);
|
||||
case NUMD_VD:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMDvoltage);
|
||||
return (OK);
|
||||
case NUMD_ID:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMDid);
|
||||
return (OK);
|
||||
case NUMD_G11:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMDconduct);
|
||||
return (OK);
|
||||
case NUMD_G12:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NUMDconduct);
|
||||
return (OK);
|
||||
case NUMD_G21:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NUMDconduct);
|
||||
return (OK);
|
||||
case NUMD_G22:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMDconduct);
|
||||
return (OK);
|
||||
case NUMD_C11:
|
||||
if (!inst->NUMDsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMDinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMDc11;
|
||||
return (OK);
|
||||
case NUMD_C12:
|
||||
if (!inst->NUMDsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMDinitSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NUMDc11;
|
||||
return (OK);
|
||||
case NUMD_C21:
|
||||
if (!inst->NUMDsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMDinitSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NUMDc11;
|
||||
return (OK);
|
||||
case NUMD_C22:
|
||||
if (!inst->NUMDsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMDinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMDc11;
|
||||
return (OK);
|
||||
case NUMD_Y11:
|
||||
if (!inst->NUMDsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMDinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMDy11r;
|
||||
value->cValue.imag = inst->NUMDy11i;
|
||||
return (OK);
|
||||
case NUMD_Y12:
|
||||
if (!inst->NUMDsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMDinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NUMDy11r;
|
||||
value->cValue.imag = -inst->NUMDy11i;
|
||||
return (OK);
|
||||
case NUMD_Y21:
|
||||
if (!inst->NUMDsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMDinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NUMDy11r;
|
||||
value->cValue.imag = -inst->NUMDy11i;
|
||||
return (OK);
|
||||
case NUMD_Y22:
|
||||
if (!inst->NUMDsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMDinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMDy11r;
|
||||
value->cValue.imag = inst->NUMDy11i;
|
||||
return (OK);
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Authors: 1987 Karti Mayaram, 1991 David Gates
|
||||
**********/
|
||||
|
||||
#ifndef NUMD_H
|
||||
#define NUMD_H
|
||||
|
||||
/* data structures used to describe 1D numerical diodes */
|
||||
|
||||
/* circuit level includes */
|
||||
#include "ifsim.h"
|
||||
#include "cktdefs.h"
|
||||
#include "gendefs.h"
|
||||
|
||||
/* device level includes */
|
||||
#include "onemesh.h"
|
||||
#include "onedev.h"
|
||||
#include "profile.h"
|
||||
#include "numglobs.h"
|
||||
#include "carddefs.h"
|
||||
|
||||
/* information needed per instance */
|
||||
typedef struct sNUMDinstance {
|
||||
struct sNUMDmodel *NUMDmodPtr;/* back pointer to model */
|
||||
struct sNUMDinstance *NUMDnextInstance; /* pointer to next instance
|
||||
* of current model */
|
||||
IFuid NUMDname; /* pointer to character string naming this
|
||||
* instance */
|
||||
int NUMDowner; /* number of owner process */
|
||||
int NUMDstate; /* pointer to start of state vector for diode */
|
||||
|
||||
#define NUMDvoltage NUMDstate
|
||||
#define NUMDid NUMDstate+1
|
||||
#define NUMDconduct NUMDstate+2
|
||||
#define NUMDnumStates 3
|
||||
|
||||
int NUMDposNode; /* number of positive node of diode */
|
||||
int NUMDnegNode; /* number of negative node of diode */
|
||||
ONEdevice *NUMDpDevice;
|
||||
GLOBvalues NUMDglobals; /* Temp.-Dep. Global Parameters */
|
||||
int NUMDtype; /* device type pn or np */
|
||||
double NUMDarea; /* area factor for the diode */
|
||||
double NUMDtemp; /* instance temperature */
|
||||
double NUMDc11; /* small-signal capacitance */
|
||||
double NUMDy11r; /* small-signal admittance, real part */
|
||||
double NUMDy11i; /* small-signal admittance, imag part */
|
||||
int NUMDprint; /* number of timesteps after which print
|
||||
* internal */
|
||||
char *NUMDicFile; /* Name of initial condition file */
|
||||
double *NUMDnegPosPtr; /* pointer to sparse matrix at
|
||||
* (negative,positive) */
|
||||
double *NUMDposNegPtr; /* pointer to sparse matrix at
|
||||
* (positive,negative) */
|
||||
double *NUMDposPosPtr; /* pointer to sparse matrix at
|
||||
* (positive,positive) */
|
||||
double *NUMDnegNegPtr; /* pointer to sparse matrix at
|
||||
* (negative,negative) */
|
||||
|
||||
int NUMDoff; /* 'off' flag for diode */
|
||||
unsigned NUMDsmSigAvail:1; /* flag to indicate small-signal done */
|
||||
unsigned NUMDareaGiven:1; /* flag to indicate area was specified */
|
||||
unsigned NUMDicFileGiven:1; /* flag to indicate init. cond. file given */
|
||||
unsigned NUMDtempGiven:1; /* flag to indicate temp was specified */
|
||||
unsigned NUMDprintGiven:1; /* flag to indicate if print was specified */
|
||||
} NUMDinstance;
|
||||
|
||||
|
||||
/* per model data */
|
||||
|
||||
typedef struct sNUMDmodel { /* model structure for a diode */
|
||||
int NUMDmodType; /* type index of this device type */
|
||||
struct sNUMDmodel *NUMDnextModel; /* pointer to next possible model in
|
||||
* linked list */
|
||||
NUMDinstance *NUMDinstances; /* pointer to list of instances that have
|
||||
* this model */
|
||||
IFuid NUMDmodName; /* pointer to character string naming this
|
||||
* model */
|
||||
/* Everything below here is numerical-device-specific */
|
||||
MESHcard *NUMDxMeshes; /* list of xmesh cards */
|
||||
MESHcard *NUMDyMeshes; /* list of ymesh cards */
|
||||
DOMNcard *NUMDdomains; /* list of domain cards */
|
||||
BDRYcard *NUMDboundaries; /* list of boundary cards */
|
||||
DOPcard *NUMDdopings; /* list of doping cards */
|
||||
ELCTcard *NUMDelectrodes; /* list of electrode cards */
|
||||
CONTcard *NUMDcontacts; /* list of contact cards */
|
||||
MODLcard *NUMDmodels; /* list of model cards */
|
||||
MATLcard *NUMDmaterials; /* list of material cards */
|
||||
MOBcard *NUMDmobility; /* list of mobility cards */
|
||||
METHcard *NUMDmethods; /* list of method cards */
|
||||
OPTNcard *NUMDoptions; /* list of option cards */
|
||||
OUTPcard *NUMDoutputs; /* list of output cards */
|
||||
ONEtranInfo *NUMDpInfo; /* transient analysis information */
|
||||
DOPprofile *NUMDprofiles; /* expanded list of doping profiles */
|
||||
DOPtable *NUMDdopTables; /* list of tables used by profiles */
|
||||
ONEmaterial *NUMDmatlInfo; /* list of material info structures */
|
||||
} NUMDmodel;
|
||||
|
||||
/* type of 1D diode */
|
||||
#define PN 1
|
||||
#define NP -1
|
||||
|
||||
/* device parameters */
|
||||
#define NUMD_AREA 1
|
||||
#define NUMD_IC_FILE 2
|
||||
#define NUMD_OFF 3
|
||||
#define NUMD_PRINT 4
|
||||
#define NUMD_TEMP 5
|
||||
#define NUMD_VD 6
|
||||
#define NUMD_ID 7
|
||||
|
||||
#define NUMD_G11 8
|
||||
#define NUMD_C11 9
|
||||
#define NUMD_Y11 10
|
||||
#define NUMD_G12 11
|
||||
#define NUMD_C12 12
|
||||
#define NUMD_Y12 13
|
||||
#define NUMD_G21 14
|
||||
#define NUMD_C21 15
|
||||
#define NUMD_Y21 16
|
||||
#define NUMD_G22 17
|
||||
#define NUMD_C22 18
|
||||
#define NUMD_Y22 19
|
||||
|
||||
/* model parameters */
|
||||
/* NOTE: all true model parameters have been moved to IFcardInfo structures */
|
||||
#define NUMD_MOD_NUMD 101
|
||||
|
||||
/* device questions */
|
||||
|
||||
/* model questions */
|
||||
|
||||
#include "numdext.h"
|
||||
|
||||
#endif /* NUMD_H */
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "numddefs.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NUMDdelete(inModel, name, kill)
|
||||
GENmodel *inModel;
|
||||
IFuid name;
|
||||
GENinstance **kill;
|
||||
|
||||
{
|
||||
|
||||
NUMDmodel *model = (NUMDmodel *) inModel;
|
||||
NUMDinstance **fast = (NUMDinstance **) kill;
|
||||
NUMDinstance **prev = NULL;
|
||||
NUMDinstance *inst;
|
||||
|
||||
for (; model; model = model->NUMDnextModel) {
|
||||
prev = &(model->NUMDinstances);
|
||||
for (inst = *prev; inst; inst = *prev) {
|
||||
if (inst->NUMDname == name || (fast && inst == *fast)) {
|
||||
*prev = inst->NUMDnextInstance;
|
||||
FREE(inst);
|
||||
return (OK);
|
||||
}
|
||||
prev = &(inst->NUMDnextInstance);
|
||||
}
|
||||
}
|
||||
return (E_NODEV);
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine deletes all NUMDs from the circuit and frees all storage they
|
||||
* were using. The current implementation has memory leaks.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "numddefs.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
void
|
||||
NUMDdestroy(inModel)
|
||||
GENmodel **inModel;
|
||||
{
|
||||
|
||||
NUMDmodel **model = (NUMDmodel **) inModel;
|
||||
NUMDmodel *mod, *nextMod;
|
||||
NUMDinstance *inst, *nextInst;
|
||||
|
||||
|
||||
for (mod = *model; mod;) {
|
||||
for (inst = mod->NUMDinstances; inst;) {
|
||||
ONEdestroy(inst->NUMDpDevice);
|
||||
nextInst = inst->NUMDnextInstance;
|
||||
FREE(inst);
|
||||
inst = nextInst;
|
||||
}
|
||||
nextMod = mod->NUMDnextModel;
|
||||
FREE(mod);
|
||||
mod = nextMod;
|
||||
}
|
||||
*model = NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This is a simple routine to dump the internal device states. It produces
|
||||
* states for .OP, .DC, & .TRAN simulations.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numddefs.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
|
||||
/* Forward Declarations */
|
||||
static void NUMDputHeader(FILE *, CKTcircuit *, NUMDinstance *);
|
||||
|
||||
/* State Counter */
|
||||
static int state_numOP = 0;
|
||||
static int state_numDC = 0;
|
||||
static int state_numTR = 0;
|
||||
|
||||
void
|
||||
NUMDdump(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
{
|
||||
register NUMDmodel *model = (NUMDmodel *) inModel;
|
||||
register NUMDinstance *inst;
|
||||
OUTPcard *output;
|
||||
FILE *fpState;
|
||||
char fileName[BSIZE_SP];
|
||||
char description[BSIZE_SP];
|
||||
char *prefix;
|
||||
int *state_num;
|
||||
int anyOutput = 0;
|
||||
|
||||
if (ckt->CKTmode & MODEDCOP) {
|
||||
prefix = "OP";
|
||||
state_num = &state_numOP;
|
||||
sprintf(description, "...");
|
||||
} else if (ckt->CKTmode & MODEDCTRANCURVE) {
|
||||
prefix = "DC";
|
||||
state_num = &state_numDC;
|
||||
sprintf(description, "sweep = % e", ckt->CKTtime);
|
||||
} else if (ckt->CKTmode & MODETRAN) {
|
||||
prefix = "TR";
|
||||
state_num = &state_numTR;
|
||||
sprintf(description, "time = % e", ckt->CKTtime);
|
||||
} else {
|
||||
/* Not a recognized CKT mode. */
|
||||
return;
|
||||
}
|
||||
|
||||
for (; model != NULL; model = model->NUMDnextModel) {
|
||||
output = model->NUMDoutputs;
|
||||
for (inst = model->NUMDinstances; inst != NULL;
|
||||
inst = inst->NUMDnextInstance) {
|
||||
if (inst->NUMDowner != ARCHme) continue;
|
||||
|
||||
if (inst->NUMDprintGiven) {
|
||||
if ((ckt->CKTmode & MODETRAN) &&
|
||||
((ckt->CKTstat->STATaccepted - 1) % inst->NUMDprint != 0)) {
|
||||
continue;
|
||||
}
|
||||
anyOutput = 1;
|
||||
sprintf(fileName, "%s%s.%d.%s", output->OUTProotFile, prefix,
|
||||
*state_num, inst->NUMDname);
|
||||
if (!(fpState = fopen(fileName, "w"))) {
|
||||
perror(fileName);
|
||||
} else {
|
||||
NUMDputHeader(fpState, ckt, inst);
|
||||
ONEprnSolution(fpState, inst->NUMDpDevice,
|
||||
model->NUMDoutputs);
|
||||
fclose(fpState);
|
||||
LOGmakeEntry(fileName, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (anyOutput) {
|
||||
(*state_num)++;
|
||||
}
|
||||
}
|
||||
|
||||
#define NUMDnumOutputs 4
|
||||
|
||||
static
|
||||
void
|
||||
NUMDputHeader(file, ckt, inst)
|
||||
FILE *file;
|
||||
CKTcircuit *ckt;
|
||||
NUMDinstance *inst;
|
||||
{
|
||||
char *reference;
|
||||
double refVal = 0.0;
|
||||
int numVars = NUMDnumOutputs;
|
||||
|
||||
if (ckt->CKTmode & MODEDCOP) {
|
||||
reference = NULL;
|
||||
} else if (ckt->CKTmode & MODEDCTRANCURVE) {
|
||||
reference = "sweep";
|
||||
refVal = ckt->CKTtime;
|
||||
numVars++;
|
||||
} else if (ckt->CKTmode & MODETRAN) {
|
||||
reference = "time";
|
||||
refVal = ckt->CKTtime;
|
||||
numVars++;
|
||||
} else {
|
||||
reference = NULL;
|
||||
}
|
||||
fprintf(file, "Title: Device %s external state\n", inst->NUMDname);
|
||||
fprintf(file, "Plotname: Device Operating Point\n");
|
||||
fprintf(file, "Command: deftype v conductance S\n");
|
||||
fprintf(file, "Flags: real\n");
|
||||
fprintf(file, "No. Variables: %d\n", numVars);
|
||||
fprintf(file, "No. Points: 1\n");
|
||||
numVars = 0;
|
||||
fprintf(file, "Variables:\n");
|
||||
if (reference) {
|
||||
fprintf(file, "\t%d %s unknown\n", numVars++, reference);
|
||||
}
|
||||
fprintf(file, "\t%d v12 voltage\n", numVars++);
|
||||
fprintf(file, "\t%d i1 current\n", numVars++);
|
||||
fprintf(file, "\t%d i2 current\n", numVars++);
|
||||
fprintf(file, "\t%d g11 conductance\n", numVars++);
|
||||
fprintf(file, "Values:\n0");
|
||||
if (reference) {
|
||||
fprintf(file, "\t% e\n", refVal);
|
||||
}
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMDvoltage));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMDid));
|
||||
fprintf(file, "\t% e\n", - *(ckt->CKTstate0 + inst->NUMDid));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMDconduct));
|
||||
}
|
||||
|
||||
void
|
||||
NUMDacct(inModel, ckt, file)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
FILE *file;
|
||||
{
|
||||
register NUMDmodel *model = (NUMDmodel *) inModel;
|
||||
register NUMDinstance *inst;
|
||||
OUTPcard *output;
|
||||
|
||||
for (; model != NULL; model = model->NUMDnextModel) {
|
||||
output = model->NUMDoutputs;
|
||||
for (inst = model->NUMDinstances; inst != NULL;
|
||||
inst = inst->NUMDnextInstance) {
|
||||
if (inst->NUMDowner != ARCHme) continue;
|
||||
|
||||
if (output->OUTPstats) {
|
||||
ONEmemStats(file, inst->NUMDpDevice);
|
||||
ONEcpuStats(file, inst->NUMDpDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Karti Mayaram
|
||||
**********/
|
||||
|
||||
#ifndef NUMDEXT_H
|
||||
#define NUMDEXT_H
|
||||
|
||||
|
||||
extern int NUMDacLoad(GENmodel *, CKTcircuit *);
|
||||
extern int NUMDask(CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *);
|
||||
extern int NUMDdelete(GENmodel *, IFuid, GENinstance **);
|
||||
extern void NUMDdestroy(GENmodel **);
|
||||
extern int NUMDgetic(GENmodel *, CKTcircuit *);
|
||||
extern int NUMDload(GENmodel *, CKTcircuit *);
|
||||
extern int NUMDmDelete(GENmodel **, IFuid, GENmodel *);
|
||||
extern int NUMDmParam(int, IFvalue *, GENmodel *);
|
||||
extern int NUMDparam(int, IFvalue *, GENinstance *, IFvalue *);
|
||||
extern int NUMDpzLoad(GENmodel *, CKTcircuit *, SPcomplex *);
|
||||
extern int NUMDsetup(SMPmatrix *, GENmodel *, CKTcircuit *, int *);
|
||||
extern int NUMDtemp(GENmodel *, CKTcircuit *);
|
||||
extern int NUMDtrunc(GENmodel *, CKTcircuit *, double *);
|
||||
|
||||
extern void NUMDdump(GENmodel *, CKTcircuit *);
|
||||
extern void NUMDacct(GENmodel *, CKTcircuit *, FILE *);
|
||||
|
||||
#endif /* NUMDEXT_H */
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <devdefs.h>
|
||||
|
||||
#include "numditf.h"
|
||||
#include "numdext.h"
|
||||
#include "numdinit.h"
|
||||
|
||||
|
||||
SPICEdev NUMDinfo = {
|
||||
{
|
||||
"NUMD",
|
||||
"1D Numerical Junction Diode model",
|
||||
|
||||
&NUMDnSize,
|
||||
&NUMDnSize,
|
||||
NUMDnames,
|
||||
|
||||
&NUMDpTSize,
|
||||
NUMDpTable,
|
||||
|
||||
&NUMDmPTSize,
|
||||
NUMDmPTable,
|
||||
|
||||
#ifdef XSPICE
|
||||
/*---- Fixed by SDB 5.2.2003 to enable XSPICE/tclspice integration -----*/
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
/*--------------------------- End of SDB fix -------------------------*/
|
||||
#endif
|
||||
|
||||
DEV_DEFAULT
|
||||
},
|
||||
|
||||
DEVparam : NUMDparam,
|
||||
DEVmodParam : NUMDmParam,
|
||||
DEVload : NUMDload,
|
||||
DEVsetup : NUMDsetup,
|
||||
DEVunsetup : NULL,
|
||||
DEVpzSetup : NUMDsetup,
|
||||
DEVtemperature: NUMDtemp,
|
||||
DEVtrunc : NUMDtrunc,
|
||||
DEVfindBranch : NULL,
|
||||
DEVacLoad : NUMDacLoad,
|
||||
DEVaccept : NULL,
|
||||
DEVdestroy : NUMDdestroy,
|
||||
DEVmodDelete : NUMDmDelete,
|
||||
DEVdelete : NUMDdelete,
|
||||
DEVsetic : NULL,
|
||||
DEVask : NUMDask,
|
||||
DEVmodAsk : NULL,
|
||||
DEVpzLoad : NUMDpzLoad,
|
||||
DEVconvTest : NULL,
|
||||
DEVsenSetup : NULL,
|
||||
DEVsenLoad : NULL,
|
||||
DEVsenUpdate : NULL,
|
||||
DEVsenAcLoad : NULL,
|
||||
DEVsenPrint : NULL,
|
||||
DEVsenTrunc : NULL,
|
||||
DEVdisto : NULL,
|
||||
DEVnoise : NULL,
|
||||
DEVdump : NUMDdump,
|
||||
DEVacct : NUMDacct,
|
||||
|
||||
DEVinstSize : &NUMDiSize,
|
||||
DEVmodSize : &NUMDmSize
|
||||
|
||||
};
|
||||
|
||||
|
||||
SPICEdev *
|
||||
get_numd_info(void)
|
||||
{
|
||||
return &NUMDinfo;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef _NUMDINIT_H
|
||||
#define _NUMDINIT_H
|
||||
|
||||
extern IFparm NUMDpTable[ ];
|
||||
extern IFparm NUMDmPTable[ ];
|
||||
extern char *NUMDnames[ ];
|
||||
extern int NUMDpTSize;
|
||||
extern int NUMDmPTSize;
|
||||
extern int NUMDnSize;
|
||||
extern int NUMDiSize;
|
||||
extern int NUMDmSize;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
**********/
|
||||
|
||||
#ifndef DEV_NUMD
|
||||
#define DEV_NUMD
|
||||
|
||||
extern SPICEdev *get_numd_info(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,393 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "devdefs.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numddefs.h"
|
||||
#include "numenum.h"
|
||||
#include "trandefs.h"
|
||||
#include "complex.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
int NUMDinitSmSig(NUMDinstance *);
|
||||
|
||||
/* External Declarations */
|
||||
extern int ONEdcDebug;
|
||||
extern int ONEtranDebug;
|
||||
extern int ONEacDebug;
|
||||
|
||||
|
||||
int
|
||||
NUMDload(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
{
|
||||
register NUMDmodel *model = (NUMDmodel *) inModel;
|
||||
register NUMDinstance *inst;
|
||||
register ONEdevice *pDevice;
|
||||
double startTime, startTime2, totalTime, totalTime2;
|
||||
double tol; /* temporary for tolerance calculations */
|
||||
double id;
|
||||
double ideq;
|
||||
double idhat = 0.0;
|
||||
double delVd;
|
||||
double vd; /* current diode voltage */
|
||||
double gd;
|
||||
double xfact;
|
||||
int check;
|
||||
int i;
|
||||
double deltaNorm[7];
|
||||
int devConverged = FALSE;
|
||||
int numDevNonCon;
|
||||
int deviceType;
|
||||
int doInitSolve;
|
||||
int doVoltPred;
|
||||
char *initStateName;
|
||||
|
||||
/* loop through all the diode models */
|
||||
for (; model != NULL; model = model->NUMDnextModel) {
|
||||
/* Do model things */
|
||||
FieldDepMobility = model->NUMDmodels->MODLfieldDepMobility;
|
||||
Srh = model->NUMDmodels->MODLsrh;
|
||||
Auger = model->NUMDmodels->MODLauger;
|
||||
AvalancheGen = model->NUMDmodels->MODLavalancheGen;
|
||||
MobDeriv = model->NUMDmethods->METHmobDeriv;
|
||||
MaxIterations = model->NUMDmethods->METHitLim;
|
||||
ONEdcDebug = model->NUMDoutputs->OUTPdcDebug;
|
||||
ONEtranDebug = model->NUMDoutputs->OUTPtranDebug;
|
||||
ONEacDebug = model->NUMDoutputs->OUTPacDebug;
|
||||
deviceType = model->NUMDoptions->OPTNdeviceType;
|
||||
doVoltPred = model->NUMDmethods->METHvoltPred;
|
||||
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
/* compute normalized deltas and predictor coeff */
|
||||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) {
|
||||
model->NUMDpInfo->order = ckt->CKTorder;
|
||||
model->NUMDpInfo->method = ckt->CKTintegrateMethod;
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder,
|
||||
model->NUMDpInfo->intCoeff, deltaNorm);
|
||||
computePredCoeff(ckt->CKTintegrateMethod, ckt->CKTorder,
|
||||
model->NUMDpInfo->predCoeff, deltaNorm);
|
||||
}
|
||||
} else if (ckt->CKTmode & MODEINITTRAN) {
|
||||
model->NUMDpInfo->order = ckt->CKTorder;
|
||||
model->NUMDpInfo->method = ckt->CKTintegrateMethod;
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder,
|
||||
model->NUMDpInfo->intCoeff, deltaNorm);
|
||||
}
|
||||
/* Now do instance things */
|
||||
for (inst = model->NUMDinstances; inst != NULL;
|
||||
inst = inst->NUMDnextInstance) {
|
||||
if (inst->NUMDowner != ARCHme) continue;
|
||||
|
||||
pDevice = inst->NUMDpDevice;
|
||||
|
||||
totalTime = 0.0;
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NUMDglobals));
|
||||
|
||||
/*
|
||||
* this routine loads diodes for dc and transient analyses.
|
||||
*/
|
||||
pDevice->devStates = ckt->CKTstates;
|
||||
/*
|
||||
* initialization
|
||||
*/
|
||||
check = 1;
|
||||
doInitSolve = FALSE;
|
||||
initStateName = NULL;
|
||||
if (ckt->CKTmode & MODEINITSMSIG) {
|
||||
vd = *(ckt->CKTstate0 + inst->NUMDvoltage);
|
||||
delVd = 0.0;
|
||||
NUMDsetBCs(pDevice, vd);
|
||||
} else if (ckt->CKTmode & MODEINITTRAN) {
|
||||
*(ckt->CKTstate0 + inst->NUMDvoltage) =
|
||||
*(ckt->CKTstate1 + inst->NUMDvoltage);
|
||||
vd = *(ckt->CKTstate1 + inst->NUMDvoltage);
|
||||
ONEsaveState(pDevice);
|
||||
delVd = 0.0;
|
||||
} else if ((ckt->CKTmode & MODEINITJCT) &&
|
||||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) {
|
||||
doInitSolve = TRUE;
|
||||
initStateName = inst->NUMDicFile;
|
||||
vd = 0.0;
|
||||
delVd = vd;
|
||||
} else if ((ckt->CKTmode & MODEINITJCT) && inst->NUMDoff) {
|
||||
doInitSolve = TRUE;
|
||||
vd = 0.0;
|
||||
delVd = vd;
|
||||
} else if (ckt->CKTmode & MODEINITJCT) {
|
||||
doInitSolve = TRUE;
|
||||
initStateName = inst->NUMDicFile;
|
||||
if (deviceType == OPTN_DIODE) {
|
||||
vd = inst->NUMDtype * 0.5;
|
||||
} else if (deviceType == OPTN_MOSCAP) {
|
||||
vd = inst->NUMDtype * 0.8;
|
||||
} else {
|
||||
vd = 0.0;
|
||||
}
|
||||
delVd = vd;
|
||||
} else if (ckt->CKTmode & MODEINITFIX && inst->NUMDoff) {
|
||||
vd = 0.0;
|
||||
delVd = vd;
|
||||
} else {
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
*(ckt->CKTstate0 + inst->NUMDvoltage) =
|
||||
*(ckt->CKTstate1 + inst->NUMDvoltage);
|
||||
*(ckt->CKTstate0 + inst->NUMDid) =
|
||||
*(ckt->CKTstate1 + inst->NUMDid);
|
||||
*(ckt->CKTstate0 + inst->NUMDconduct) =
|
||||
*(ckt->CKTstate1 + inst->NUMDconduct);
|
||||
/* compute the normalized deltas */
|
||||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) {
|
||||
/* no linear prediction on device voltages */
|
||||
vd = *(ckt->CKTstate1 + inst->NUMDvoltage);
|
||||
ONEpredict(pDevice, model->NUMDpInfo);
|
||||
} else {
|
||||
if (doVoltPred) {
|
||||
/* linear prediction */
|
||||
xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1];
|
||||
vd = (1+xfact) * (*(ckt->CKTstate1 + inst->NUMDvoltage))
|
||||
- (xfact) * (*(ckt->CKTstate2 + inst->NUMDvoltage));
|
||||
} else {
|
||||
vd = *(ckt->CKTstate1 + inst->NUMDvoltage);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vd = *(ckt->CKTrhsOld + inst->NUMDposNode) -
|
||||
*(ckt->CKTrhsOld + inst->NUMDnegNode);
|
||||
}
|
||||
delVd = vd - *(ckt->CKTstate0 + inst->NUMDvoltage);
|
||||
idhat = *(ckt->CKTstate0 + inst->NUMDid) +
|
||||
*(ckt->CKTstate0 + inst->NUMDconduct) * delVd;
|
||||
/*
|
||||
* bypass if solution has not changed
|
||||
*/
|
||||
if ((ckt->CKTbypass) && pDevice->converged &&
|
||||
!(ckt->CKTmode & MODEINITPRED)) {
|
||||
tol = ckt->CKTvoltTol + ckt->CKTreltol *
|
||||
MAX(fabs(vd), fabs(*(ckt->CKTstate0 + inst->NUMDvoltage)));
|
||||
if (fabs(delVd) < tol) {
|
||||
tol = ckt->CKTreltol *
|
||||
MAX(fabs(idhat), fabs(*(ckt->CKTstate0 + inst->NUMDid))) +
|
||||
ckt->CKTabstol;
|
||||
if (fabs(idhat - *(ckt->CKTstate0 + inst->NUMDid))
|
||||
< tol) {
|
||||
vd = *(ckt->CKTstate0 + inst->NUMDvoltage);
|
||||
id = *(ckt->CKTstate0 + inst->NUMDid);
|
||||
gd = *(ckt->CKTstate0 + inst->NUMDconduct);
|
||||
goto load;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* limit new junction voltage
|
||||
*/
|
||||
if (deviceType == OPTN_DIODE) {
|
||||
vd = inst->NUMDtype * limitJunctionVoltage(inst->NUMDtype * vd,
|
||||
inst->NUMDtype * *(ckt->CKTstate0 + inst->NUMDvoltage), &check);
|
||||
} else if (deviceType == OPTN_MOSCAP) {
|
||||
vd = inst->NUMDtype * limitVgb(inst->NUMDtype * vd,
|
||||
inst->NUMDtype * *(ckt->CKTstate0 + inst->NUMDvoltage), &check);
|
||||
} else {
|
||||
vd = inst->NUMDtype * limitResistorVoltage(inst->NUMDtype * vd,
|
||||
inst->NUMDtype * *(ckt->CKTstate0 + inst->NUMDvoltage), &check);
|
||||
}
|
||||
delVd = vd - *(ckt->CKTstate0 + inst->NUMDvoltage);
|
||||
}
|
||||
if (doInitSolve) {
|
||||
if (ONEdcDebug) {
|
||||
printVoltages(stdout, model->NUMDmodName, inst->NUMDname,
|
||||
deviceType, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
startTime2 = SPfrontEnd->IFseconds();
|
||||
ONEequilSolve(pDevice);
|
||||
totalTime2 = SPfrontEnd->IFseconds() - startTime2;
|
||||
pDevice->pStats->totalTime[STAT_SETUP] += totalTime2;
|
||||
pDevice->pStats->totalTime[STAT_DC] -= totalTime2;
|
||||
|
||||
ONEbiasSolve(pDevice, MaxIterations, FALSE, NULL);
|
||||
|
||||
*(ckt->CKTstate0 + inst->NUMDvoltage) = 0.0;
|
||||
|
||||
if (initStateName != NULL) {
|
||||
if (ONEreadState(pDevice, initStateName, 1, &vd, NULL ) < 0) {
|
||||
fprintf(stderr,
|
||||
"NUMDload: trouble reading state-file %s\n", initStateName);
|
||||
} else {
|
||||
NUMDsetBCs(pDevice, vd);
|
||||
delVd = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* compute dc current and derivatives
|
||||
*/
|
||||
/* use the routines for numerical simulation */
|
||||
|
||||
if (ckt->CKTmode & (MODEDCOP | MODETRANOP | MODEDCTRANCURVE | MODEINITSMSIG)) {
|
||||
numDevNonCon = 0;
|
||||
inst->NUMDc11 = inst->NUMDy11r = inst->NUMDy11i = 0.0;
|
||||
inst->NUMDsmSigAvail = FALSE;
|
||||
devNonCon:
|
||||
NUMDproject(pDevice, delVd);
|
||||
if (ONEdcDebug) {
|
||||
printVoltages(stdout, model->NUMDmodName, inst->NUMDname,
|
||||
deviceType, 1, vd, delVd, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
ONEbiasSolve(pDevice, MaxIterations, FALSE, NULL);
|
||||
devConverged = pDevice->converged;
|
||||
if (devConverged && finite(pDevice->rhsNorm)) {
|
||||
/* Get the current and conductance information. */
|
||||
NUMDcurrent(pDevice, FALSE, (double *) NULL, &id);
|
||||
NUMDconductance(pDevice, FALSE, (double *) NULL, &gd);
|
||||
} else {
|
||||
/* reduce the voltage step until converged */
|
||||
/* restore the boundary potential to previous value */
|
||||
NUMDsetBCs(pDevice, vd - delVd);
|
||||
ONEstoreInitialGuess(pDevice);
|
||||
ONEresetJacobian(pDevice);
|
||||
delVd *= 0.5;
|
||||
vd = delVd + *(ckt->CKTstate0 + inst->NUMDvoltage);
|
||||
numDevNonCon++;
|
||||
check = 1;
|
||||
if (numDevNonCon > 10) {
|
||||
printVoltages(stderr, model->NUMDmodName, inst->NUMDname,
|
||||
deviceType, 1, vd, delVd, 0.0, 0.0, 0.0, 0.0);
|
||||
fprintf(stderr, "*** Non-convergence during load ***\n");
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
return (E_BADMATRIX);
|
||||
} else {
|
||||
goto devNonCon;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((ckt->CKTmode & (MODETRAN | MODEAC | MODEINITSMSIG)) ||
|
||||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) {
|
||||
/*
|
||||
* store small-signal parameters
|
||||
*/
|
||||
if ((!(ckt->CKTmode & MODETRANOP)) || (!(ckt->CKTmode & MODEUIC))) {
|
||||
if (ckt->CKTmode & MODEINITSMSIG) {
|
||||
totalTime = SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
startTime2 = SPfrontEnd->IFseconds();
|
||||
NUMDinitSmSig(inst);
|
||||
pDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime2;
|
||||
continue;
|
||||
} else {
|
||||
inst->NUMDsmSigAvail = FALSE;
|
||||
}
|
||||
/*
|
||||
* transient analysis
|
||||
*/
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
NUMDsetBCs(pDevice, vd);
|
||||
ONEstoreInitialGuess(pDevice);
|
||||
} else {
|
||||
NUMDupdate(pDevice, delVd, TRUE);
|
||||
}
|
||||
if (ONEtranDebug) {
|
||||
printVoltages(stdout, model->NUMDmodName, inst->NUMDname,
|
||||
deviceType, 1, vd, delVd, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
ONEbiasSolve(pDevice, 0, TRUE, model->NUMDpInfo);
|
||||
|
||||
if (!finite(pDevice->rhsNorm)) {
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
return (E_BADMATRIX);
|
||||
}
|
||||
|
||||
pDevice->converged = devConverged = ONEdeviceConverged(pDevice);
|
||||
|
||||
/* extract the current and conductance information */
|
||||
NUMDcurrent(pDevice, TRUE, model->NUMDpInfo->intCoeff, &id);
|
||||
NUMDconductance(pDevice, TRUE, model->NUMDpInfo->intCoeff, &gd);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check convergence
|
||||
*/
|
||||
if ((!(ckt->CKTmode & MODEINITFIX)) || (!(inst->NUMDoff))) {
|
||||
if (check == 1 || !devConverged) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
} else {
|
||||
tol = ckt->CKTreltol * MAX(fabs(idhat), fabs(id)) + ckt->CKTabstol;
|
||||
if (fabs(idhat - id) > tol) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
}
|
||||
}
|
||||
}
|
||||
*(ckt->CKTstate0 + inst->NUMDvoltage) = vd;
|
||||
*(ckt->CKTstate0 + inst->NUMDid) = id;
|
||||
*(ckt->CKTstate0 + inst->NUMDconduct) = gd;
|
||||
|
||||
load:
|
||||
|
||||
/*
|
||||
* load current vector
|
||||
*/
|
||||
|
||||
ideq = id - gd * vd;
|
||||
*(ckt->CKTrhs + inst->NUMDnegNode) += ideq;
|
||||
*(ckt->CKTrhs + inst->NUMDposNode) -= ideq;
|
||||
|
||||
/*
|
||||
* load matrix
|
||||
*/
|
||||
*(inst->NUMDposPosPtr) += gd;
|
||||
*(inst->NUMDnegNegPtr) += gd;
|
||||
*(inst->NUMDnegPosPtr) -= gd;
|
||||
*(inst->NUMDposNegPtr) -= gd;
|
||||
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
if (ckt->CKTmode & MODETRAN) {
|
||||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime;
|
||||
} else {
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
||||
int
|
||||
NUMDinitSmSig(inst)
|
||||
NUMDinstance *inst;
|
||||
{
|
||||
SPcomplex yd;
|
||||
double omega = inst->NUMDmodPtr->NUMDmethods->METHomega;
|
||||
|
||||
AcAnalysisMethod = SOR_ONLY;
|
||||
(void) NUMDadmittance(inst->NUMDpDevice, omega, &yd);
|
||||
inst->NUMDc11 = yd.imag / omega;
|
||||
inst->NUMDy11r = yd.real;
|
||||
inst->NUMDy11i = yd.imag;
|
||||
inst->NUMDsmSigAvail = TRUE;
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "numddefs.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NUMDmDelete(inModel, modname, kill)
|
||||
GENmodel **inModel;
|
||||
IFuid modname;
|
||||
GENmodel *kill;
|
||||
{
|
||||
|
||||
NUMDmodel **model = (NUMDmodel **) inModel;
|
||||
NUMDmodel *modfast = (NUMDmodel *) kill;
|
||||
NUMDinstance *inst;
|
||||
NUMDinstance *prev = NULL;
|
||||
NUMDmodel **oldmod;
|
||||
oldmod = model;
|
||||
for (; *model; model = &((*model)->NUMDnextModel)) {
|
||||
if ((*model)->NUMDmodName == modname ||
|
||||
(modfast && *model == modfast))
|
||||
goto delgot;
|
||||
oldmod = model;
|
||||
}
|
||||
return (E_NOMOD);
|
||||
|
||||
delgot:
|
||||
*oldmod = (*model)->NUMDnextModel; /* cut deleted device out of list */
|
||||
for (inst = (*model)->NUMDinstances; inst; inst = inst->NUMDnextInstance) {
|
||||
if (prev)
|
||||
FREE(prev);
|
||||
prev = inst;
|
||||
}
|
||||
if (prev)
|
||||
FREE(prev);
|
||||
FREE(*model);
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine sets model parameters for NUMDs in the circuit.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "numddefs.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NUMDmParam(param, value, inModel)
|
||||
int param;
|
||||
IFvalue *value;
|
||||
GENmodel *inModel;
|
||||
{
|
||||
switch (param) {
|
||||
case NUMD_MOD_NUMD:
|
||||
/* no action - already know it is a 1d-numerical diode, but this */
|
||||
/* makes life easier for spice-2 like parsers */
|
||||
break;
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "ifsim.h"
|
||||
#include "const.h"
|
||||
#include "numddefs.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NUMDparam(param, value, inInst, select)
|
||||
int param;
|
||||
IFvalue *value;
|
||||
GENinstance *inInst;
|
||||
IFvalue *select;
|
||||
{
|
||||
NUMDinstance *inst = (NUMDinstance *) inInst;
|
||||
switch (param) {
|
||||
case NUMD_AREA:
|
||||
inst->NUMDarea = value->rValue;
|
||||
inst->NUMDareaGiven = TRUE;
|
||||
break;
|
||||
case NUMD_OFF:
|
||||
inst->NUMDoff = TRUE;
|
||||
break;
|
||||
case NUMD_IC_FILE:
|
||||
inst->NUMDicFile = value->sValue;
|
||||
inst->NUMDicFileGiven = TRUE;
|
||||
break;
|
||||
case NUMD_PRINT:
|
||||
inst->NUMDprint = value->rValue;
|
||||
inst->NUMDprintGiven = TRUE;
|
||||
break;
|
||||
case NUMD_TEMP:
|
||||
inst->NUMDtemp = value->rValue + CONSTCtoK;
|
||||
inst->NUMDtempGiven = TRUE;
|
||||
break;
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "complex.h"
|
||||
#include "sperror.h"
|
||||
#include "numddefs.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* External Declarations */
|
||||
extern int ONEacDebug;
|
||||
|
||||
int
|
||||
NUMDpzLoad(inModel, ckt, s)
|
||||
GENmodel *inModel;
|
||||
register CKTcircuit *ckt;
|
||||
SPcomplex *s;
|
||||
{
|
||||
register NUMDmodel *model = (NUMDmodel *) inModel;
|
||||
register NUMDinstance *inst;
|
||||
SPcomplex y;
|
||||
double startTime;
|
||||
|
||||
/* loop through all the diode models */
|
||||
for (; model != NULL; model = model->NUMDnextModel) {
|
||||
FieldDepMobility = model->NUMDmodels->MODLfieldDepMobility;
|
||||
Srh = model->NUMDmodels->MODLsrh;
|
||||
Auger = model->NUMDmodels->MODLauger;
|
||||
AvalancheGen = model->NUMDmodels->MODLavalancheGen;
|
||||
AcAnalysisMethod = model->NUMDmethods->METHacAnalysisMethod;
|
||||
MobDeriv = model->NUMDmethods->METHmobDeriv;
|
||||
ONEacDebug = model->NUMDoutputs->OUTPacDebug;
|
||||
|
||||
for (inst = model->NUMDinstances; inst != NULL;
|
||||
inst = inst->NUMDnextInstance) {
|
||||
if (inst->NUMDowner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NUMDglobals));
|
||||
|
||||
NUMDys(inst->NUMDpDevice, s, &y);
|
||||
|
||||
*(inst->NUMDposPosPtr) += y.real;
|
||||
*(inst->NUMDposPosPtr + 1) += y.imag;
|
||||
*(inst->NUMDnegNegPtr) += y.real;
|
||||
*(inst->NUMDnegNegPtr + 1) += y.imag;
|
||||
*(inst->NUMDnegPosPtr) -= y.real;
|
||||
*(inst->NUMDnegPosPtr + 1) -= y.imag;
|
||||
*(inst->NUMDposNegPtr) -= y.real;
|
||||
*(inst->NUMDposNegPtr + 1) -= y.imag;
|
||||
|
||||
inst->NUMDpDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "smpdefs.h"
|
||||
#include "numddefs.h"
|
||||
#include "numconst.h"
|
||||
#include "numenum.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "ciderinp.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#define NIL(type) ((type *)0)
|
||||
#define TSCALLOC(var, size, type)\
|
||||
if (size && (!(var =(type *)calloc(1, (unsigned)(size)*sizeof(type))))) {\
|
||||
return(E_NOMEM);\
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NUMDsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
||||
/*
|
||||
* load the structure with those pointers needed later for fast matrix
|
||||
* loading
|
||||
*/
|
||||
{
|
||||
register NUMDmodel *model = (NUMDmodel *) inModel;
|
||||
register NUMDinstance *inst;
|
||||
METHcard *methods;
|
||||
MODLcard *models;
|
||||
OPTNcard *options;
|
||||
OUTPcard *outputs;
|
||||
char *icFileName = NULL;
|
||||
int nameLen;
|
||||
int error;
|
||||
int xMeshSize;
|
||||
ONEdevice *pDevice;
|
||||
ONEcoord *xCoordList = NIL(ONEcoord);
|
||||
ONEdomain *domainList = NIL(ONEdomain);
|
||||
ONEmaterial *pM, *pMaterial = NIL(ONEmaterial), *materialList = NIL(ONEmaterial);
|
||||
DOPprofile *profileList = NIL(DOPprofile);
|
||||
DOPtable *dopTableList = NIL(DOPtable);
|
||||
double startTime;
|
||||
|
||||
|
||||
/* loop through all the models */
|
||||
for (; model != NULL; model = model->NUMDnextModel) {
|
||||
if (!model->NUMDpInfo) {
|
||||
TSCALLOC(model->NUMDpInfo, 1, ONEtranInfo);
|
||||
}
|
||||
methods = model->NUMDmethods;
|
||||
if (!methods) {
|
||||
TSCALLOC(methods, 1, METHcard);
|
||||
model->NUMDmethods = methods;
|
||||
}
|
||||
models = model->NUMDmodels;
|
||||
if (!models) {
|
||||
TSCALLOC(models, 1, MODLcard);
|
||||
model->NUMDmodels = models;
|
||||
}
|
||||
options = model->NUMDoptions;
|
||||
if (!options) {
|
||||
TSCALLOC(options, 1, OPTNcard);
|
||||
model->NUMDoptions = options;
|
||||
}
|
||||
outputs = model->NUMDoutputs;
|
||||
if (!outputs) {
|
||||
TSCALLOC(outputs, 1, OUTPcard);
|
||||
model->NUMDoutputs = outputs;
|
||||
}
|
||||
if (!methods->METHvoltPredGiven) {
|
||||
methods->METHvoltPred = FALSE;
|
||||
}
|
||||
if (!methods->METHmobDerivGiven) {
|
||||
methods->METHmobDeriv = TRUE;
|
||||
}
|
||||
if (!methods->METHoneCarrierGiven) {
|
||||
methods->METHoneCarrier = FALSE;
|
||||
}
|
||||
if (!methods->METHacAnalysisMethodGiven) {
|
||||
methods->METHacAnalysisMethod = SOR;
|
||||
}
|
||||
if (!methods->METHdabstolGiven) {
|
||||
methods->METHdabstol = DABSTOL1D;
|
||||
}
|
||||
if (!methods->METHdreltolGiven) {
|
||||
methods->METHdreltol = ckt->CKTreltol;
|
||||
}
|
||||
if (!methods->METHitLimGiven) {
|
||||
methods->METHitLim = 20;
|
||||
}
|
||||
if (!methods->METHomegaGiven || methods->METHomega <= 0.0) {
|
||||
methods->METHomega = 2.0 * M_PI /* radians/sec */ ;
|
||||
}
|
||||
if (!options->OPTNdefaGiven || options->OPTNdefa <= 0.0) {
|
||||
options->OPTNdefa = 1.0e4 /* cm^2 */ ;
|
||||
}
|
||||
if (!options->OPTNdeviceTypeGiven) {
|
||||
options->OPTNdeviceType = OPTN_DIODE;
|
||||
}
|
||||
if (!options->OPTNicFileGiven) {
|
||||
options->OPTNicFile = NULL;
|
||||
options->OPTNunique = FALSE; /* Can't form a unique name. */
|
||||
}
|
||||
if (!options->OPTNuniqueGiven) {
|
||||
options->OPTNunique = FALSE;
|
||||
}
|
||||
|
||||
/* Set up the rest of the card lists */
|
||||
if ((error = MODLsetup(model->NUMDmodels)))
|
||||
return (error);
|
||||
BandGapNarrowing = models->MODLbandGapNarrowing;
|
||||
ConcDepLifetime = models->MODLconcDepLifetime;
|
||||
TempDepMobility = models->MODLtempDepMobility;
|
||||
ConcDepMobility = models->MODLconcDepMobility;
|
||||
|
||||
if ((error = OUTPsetup(model->NUMDoutputs)))
|
||||
return (error);
|
||||
if ((error = MATLsetup(model->NUMDmaterials, &materialList)))
|
||||
return (error);
|
||||
if ((error = MOBsetup(model->NUMDmobility, materialList)))
|
||||
return (error);
|
||||
if ((error = MESHsetup('x', model->NUMDxMeshes, &xCoordList, &xMeshSize)))
|
||||
return (error);
|
||||
if ((error = DOMNsetup(model->NUMDdomains, &domainList,
|
||||
xCoordList, NIL(ONEcoord), materialList)))
|
||||
return (error);
|
||||
if ((error = BDRYsetup(model->NUMDboundaries,
|
||||
xCoordList, NIL(ONEcoord), domainList)))
|
||||
return (error);
|
||||
if ((error = CONTsetup(model->NUMDcontacts, NULL)))
|
||||
return (error);
|
||||
if ((error = DOPsetup(model->NUMDdopings, &profileList,
|
||||
&dopTableList, xCoordList, NIL(ONEcoord))))
|
||||
return (error);
|
||||
model->NUMDmatlInfo = materialList;
|
||||
model->NUMDprofiles = profileList;
|
||||
model->NUMDdopTables = dopTableList;
|
||||
|
||||
/* loop through all the instances of the model */
|
||||
for (inst = model->NUMDinstances; inst != NULL;
|
||||
inst = inst->NUMDnextInstance) {
|
||||
if ((inst->NUMDowner != ARCHme)) goto matrixpointers;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
if ((!inst->NUMDprintGiven)) {
|
||||
inst->NUMDprint = 0;
|
||||
} else if (inst->NUMDprint <= 0) {
|
||||
inst->NUMDprint = 1;
|
||||
}
|
||||
if ((!inst->NUMDicFileGiven)) {
|
||||
if (options->OPTNunique) {
|
||||
nameLen = strlen(options->OPTNicFile) + strlen(inst->NUMDname) + 1;
|
||||
TSCALLOC(icFileName, nameLen+1, char);
|
||||
sprintf(icFileName, "%s.%s", options->OPTNicFile, inst->NUMDname);
|
||||
icFileName[nameLen] = '\0';
|
||||
inst->NUMDicFile = icFileName;
|
||||
} else if (options->OPTNicFile != NULL) {
|
||||
nameLen = strlen(options->OPTNicFile);
|
||||
TSCALLOC(icFileName, nameLen+1, char);
|
||||
icFileName = strcpy(icFileName, options->OPTNicFile);
|
||||
inst->NUMDicFile = icFileName;
|
||||
} else {
|
||||
inst->NUMDicFile = NULL;
|
||||
}
|
||||
}
|
||||
inst->NUMDstate = *states;
|
||||
*states += NUMDnumStates;
|
||||
|
||||
if (!inst->NUMDpDevice) {
|
||||
/* Assign the mesh info to each instance. */
|
||||
TSCALLOC(pDevice, 1, ONEdevice);
|
||||
TSCALLOC(pDevice->pStats, 1, ONEstats);
|
||||
pDevice->name = inst->NUMDname;
|
||||
pDevice->solverType = SLV_NONE;
|
||||
pDevice->numNodes = xMeshSize;
|
||||
pDevice->abstol = methods->METHdabstol;
|
||||
pDevice->reltol = methods->METHdreltol;
|
||||
pDevice->rhsImag = NIL(double);
|
||||
TSCALLOC(pDevice->elemArray, pDevice->numNodes, ONEelem *);
|
||||
|
||||
/* Create a copy of material data that can change with temperature. */
|
||||
pDevice->pMaterials = NIL(ONEmaterial);
|
||||
for (pM = materialList; pM != NIL(ONEmaterial); pM = pM->next) {
|
||||
if (pDevice->pMaterials == NIL(ONEmaterial)) {
|
||||
TSCALLOC(pMaterial, 1, ONEmaterial);
|
||||
pDevice->pMaterials = pMaterial;
|
||||
} else {
|
||||
TSCALLOC(pMaterial->next, 1, ONEmaterial);
|
||||
pMaterial = pMaterial->next;
|
||||
}
|
||||
/* Copy everything, then fix the incorrect pointer. */
|
||||
bcopy((void *) pM, (void *) pMaterial, sizeof(ONEmaterial));
|
||||
pMaterial->next = NIL(ONEmaterial);
|
||||
}
|
||||
|
||||
/* generate the mesh structure for the device */
|
||||
ONEbuildMesh(pDevice, xCoordList, domainList, pDevice->pMaterials);
|
||||
|
||||
/* store the device info in the instance */
|
||||
inst->NUMDpDevice = pDevice;
|
||||
}
|
||||
/* Now update the state pointers. */
|
||||
ONEgetStatePointers(inst->NUMDpDevice, states);
|
||||
|
||||
/* Wipe out statistics from previous runs (if any). */
|
||||
bzero((void *) inst->NUMDpDevice->pStats, sizeof(ONEstats));
|
||||
|
||||
inst->NUMDpDevice->pStats->totalTime[STAT_SETUP] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
|
||||
/* macro to make elements with built in test for out of memory */
|
||||
#define TSTALLOC(ptr,first,second) \
|
||||
if ((inst->ptr = SMPmakeElt(matrix,inst->first,inst->second))==(double *)NULL){\
|
||||
return(E_NOMEM);\
|
||||
}
|
||||
|
||||
matrixpointers:
|
||||
TSTALLOC(NUMDposPosPtr, NUMDposNode, NUMDposNode)
|
||||
TSTALLOC(NUMDnegNegPtr, NUMDnegNode, NUMDnegNode)
|
||||
TSTALLOC(NUMDnegPosPtr, NUMDnegNode, NUMDposNode)
|
||||
TSTALLOC(NUMDposNegPtr, NUMDposNode, NUMDnegNode)
|
||||
}
|
||||
/* Clean up lists */
|
||||
killCoordInfo(xCoordList);
|
||||
killDomainInfo(domainList);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
Author: 1992 David A. Gates, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numddefs.h"
|
||||
#include "numenum.h"
|
||||
#include "carddefs.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#define NIL(type) ((type *)0)
|
||||
|
||||
int
|
||||
NUMDtemp(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
register CKTcircuit *ckt;
|
||||
/*
|
||||
* perform the temperature update to the diode
|
||||
*/
|
||||
{
|
||||
register NUMDmodel *model = (NUMDmodel *) inModel;
|
||||
register NUMDinstance *inst;
|
||||
METHcard *methods;
|
||||
MODLcard *models;
|
||||
OPTNcard *options;
|
||||
OUTPcard *outputs;
|
||||
ONEmaterial *pM, *pMaterial, *pNextMaterial;
|
||||
double startTime;
|
||||
|
||||
|
||||
/* loop through all the diode models */
|
||||
for (; model != NULL; model = model->NUMDnextModel) {
|
||||
methods = model->NUMDmethods;
|
||||
models = model->NUMDmodels;
|
||||
options = model->NUMDoptions;
|
||||
outputs = model->NUMDoutputs;
|
||||
|
||||
if (!options->OPTNtnomGiven) {
|
||||
options->OPTNtnom = ckt->CKTnomTemp;
|
||||
}
|
||||
for (pM = model->NUMDmatlInfo; pM != NIL(ONEmaterial); pM = pM->next) {
|
||||
pM->tnom = options->OPTNtnom;
|
||||
}
|
||||
|
||||
BandGapNarrowing = models->MODLbandGapNarrowing;
|
||||
ConcDepLifetime = models->MODLconcDepLifetime;
|
||||
TempDepMobility = models->MODLtempDepMobility;
|
||||
ConcDepMobility = models->MODLconcDepMobility;
|
||||
|
||||
for (inst = model->NUMDinstances; inst != NULL;
|
||||
inst = inst->NUMDnextInstance) {
|
||||
if (inst->NUMDowner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
if (!inst->NUMDtempGiven) {
|
||||
inst->NUMDtemp = ckt->CKTtemp;
|
||||
}
|
||||
if (!inst->NUMDareaGiven || inst->NUMDarea <= 0.0) {
|
||||
inst->NUMDarea = 1.0;
|
||||
}
|
||||
inst->NUMDpDevice->area = inst->NUMDarea * options->OPTNdefa;
|
||||
|
||||
/* Compute and save globals for this instance. */
|
||||
GLOBcomputeGlobals(&(inst->NUMDglobals), inst->NUMDtemp);
|
||||
if (outputs->OUTPglobals) {
|
||||
GLOBprnGlobals(stdout, &(inst->NUMDglobals));
|
||||
}
|
||||
/* Calculate new sets of material parameters. */
|
||||
pM = model->NUMDmatlInfo;
|
||||
pMaterial = inst->NUMDpDevice->pMaterials;
|
||||
for (; pM != NULL; pM = pM->next, pMaterial = pMaterial->next) {
|
||||
|
||||
/* Copy the original values, then fix the incorrect pointer. */
|
||||
pNextMaterial = pMaterial->next;
|
||||
bcopy((char *) pM, (char *) pMaterial, sizeof(ONEmaterial));
|
||||
pMaterial->next = pNextMaterial;
|
||||
|
||||
/* Now do the temperature dependence. */
|
||||
MATLtempDep(pMaterial, pMaterial->tnom);
|
||||
if (outputs->OUTPmaterial) {
|
||||
printMaterialInfo(pMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign doping to the mesh. */
|
||||
ONEsetDoping(inst->NUMDpDevice, model->NUMDprofiles,
|
||||
model->NUMDdopTables);
|
||||
|
||||
/* Assign other physical parameters to the mesh. */
|
||||
ONEsetup(inst->NUMDpDevice);
|
||||
|
||||
/* Assign boundary condition parameters. */
|
||||
ONEsetBCparams(inst->NUMDpDevice, model->NUMDboundaries,
|
||||
model->NUMDcontacts);
|
||||
|
||||
/* Normalize everything. */
|
||||
ONEnormalize(inst->NUMDpDevice);
|
||||
|
||||
/* Find the device's polarity type. */
|
||||
switch (options->OPTNdeviceType) {
|
||||
case OPTN_DIODE:
|
||||
if (inst->NUMDpDevice->elemArray[1]
|
||||
->pNodes[0]->netConc < 0.0) {
|
||||
inst->NUMDtype = PN;
|
||||
} else {
|
||||
inst->NUMDtype = NP;
|
||||
}
|
||||
break;
|
||||
case OPTN_MOSCAP:
|
||||
if (inst->NUMDpDevice->elemArray[inst->NUMDpDevice->numNodes - 1]
|
||||
->pNodes[1]->netConc < 0.0) {
|
||||
inst->NUMDtype = PN;
|
||||
} else {
|
||||
inst->NUMDtype = NP;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
inst->NUMDtype = PN;
|
||||
break;
|
||||
}
|
||||
inst->NUMDpDevice->pStats->totalTime[STAT_SETUP] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numddefs.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/oned/onedext.h"
|
||||
#include "suffix.h"
|
||||
#include "cidersupt.h"
|
||||
|
||||
|
||||
|
||||
int
|
||||
NUMDtrunc(inModel, ckt, timeStep)
|
||||
GENmodel *inModel;
|
||||
register CKTcircuit *ckt;
|
||||
double *timeStep;
|
||||
|
||||
{
|
||||
register NUMDmodel *model = (NUMDmodel *) inModel;
|
||||
register NUMDinstance *inst;
|
||||
double deltaNew;
|
||||
double deltaNorm[7];
|
||||
double startTime;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
for (; model != NULL; model = model->NUMDnextModel) {
|
||||
model->NUMDpInfo->order = ckt->CKTorder;
|
||||
model->NUMDpInfo->delta = deltaNorm;
|
||||
model->NUMDpInfo->lteCoeff = computeLTECoeff(model->NUMDpInfo);
|
||||
for (inst = model->NUMDinstances; inst != NULL;
|
||||
inst = inst->NUMDnextInstance) {
|
||||
if (inst->NUMDowner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
deltaNew = ONEtrunc(inst->NUMDpDevice, model->NUMDpInfo, ckt->CKTdelta);
|
||||
*timeStep = MIN(*timeStep, deltaNew);
|
||||
inst->NUMDpDevice->pStats->totalTime[STAT_TRAN] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
noinst_LIBRARIES = libnumd2.a
|
||||
|
||||
libnumd2_a_SOURCES = \
|
||||
nud2.c \
|
||||
nud2acld.c \
|
||||
nud2ask.c \
|
||||
numd2defs.h \
|
||||
nud2del.c \
|
||||
nud2dest.c \
|
||||
nud2dump.c \
|
||||
numd2ext.h \
|
||||
numd2init.c \
|
||||
numd2init.h \
|
||||
numd2itf.h \
|
||||
nud2load.c \
|
||||
nud2mdel.c \
|
||||
nud2mpar.c \
|
||||
nud2parm.c \
|
||||
nud2pzld.c \
|
||||
nud2set.c \
|
||||
nud2temp.c \
|
||||
nud2trun.c
|
||||
|
||||
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/src/include
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "devdefs.h"
|
||||
#include "numd2def.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/*
|
||||
* This file defines the 2d Numerical Diode data structures that are
|
||||
* available to the next level(s) up the calling hierarchy
|
||||
*/
|
||||
|
||||
IFparm NUMD2pTable[] = { /* parameters */
|
||||
IP("off", NUMD2_OFF, IF_FLAG, "Initially off"),
|
||||
IP("ic.file", NUMD2_IC_FILE, IF_STRING, "Initial condition file"),
|
||||
IOP("w", NUMD2_WIDTH, IF_REAL, "Width factor"),
|
||||
IOP("area", NUMD2_AREA, IF_REAL, "Area factor"),
|
||||
IP("save", NUMD2_PRINT, IF_REAL, "Save solutions"),
|
||||
IP("print", NUMD2_PRINT, IF_REAL, "Print solutions"),
|
||||
OP("vd", NUMD2_VD, IF_REAL, "Voltage"),
|
||||
OP("id", NUMD2_ID, IF_REAL, "Current"),
|
||||
OP("g11", NUMD2_G11, IF_REAL, "Conductance"),
|
||||
OP("c11", NUMD2_C11, IF_REAL, "Capacitance"),
|
||||
OP("y11", NUMD2_Y11, IF_COMPLEX, "Admittance"),
|
||||
OPU("g12", NUMD2_G12, IF_REAL, "Conductance"),
|
||||
OPU("c12", NUMD2_C12, IF_REAL, "Capacitance"),
|
||||
OPU("y12", NUMD2_Y12, IF_COMPLEX, "Admittance"),
|
||||
OPU("g21", NUMD2_G21, IF_REAL, "Conductance"),
|
||||
OPU("c21", NUMD2_C21, IF_REAL, "Capacitance"),
|
||||
OPU("y21", NUMD2_Y21, IF_COMPLEX, "Admittance"),
|
||||
OPU("g22", NUMD2_G22, IF_REAL, "Conductance"),
|
||||
OPU("c22", NUMD2_C22, IF_REAL, "Capacitance"),
|
||||
OPU("y22", NUMD2_Y22, IF_COMPLEX, "Admittance"),
|
||||
OPR("voltage", NUMD2_VD, IF_REAL, "Voltage"),
|
||||
OPR("current", NUMD2_ID, IF_REAL, "Current"),
|
||||
OPR("conductance", NUMD2_G11, IF_REAL, "Conductance"),
|
||||
OPR("capacitance", NUMD2_C11, IF_REAL, "Capacitance"),
|
||||
IOP("temp", NUMD2_TEMP, IF_REAL, "Instance Temperature")
|
||||
};
|
||||
|
||||
IFparm NUMD2mPTable[] = { /* model parameters */
|
||||
/* numerical-device models no longer have parameters */
|
||||
/* one is left behind to keep the table from being empty */
|
||||
IP("numd", NUMD2_MOD_NUMD, IF_FLAG, "Numerical 2d-Diode Model")
|
||||
};
|
||||
|
||||
char *NUMD2names[] = {
|
||||
"Anode",
|
||||
"Cathode"
|
||||
};
|
||||
|
||||
int NUMD2nSize = NUMELEMS(NUMD2names);
|
||||
int NUMD2pTSize = NUMELEMS(NUMD2pTable);
|
||||
int NUMD2mPTSize = NUMELEMS(NUMD2mPTable);
|
||||
int NUMD2iSize = sizeof(NUMD2instance);
|
||||
int NUMD2mSize = sizeof(NUMD2model);
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* Function to load the COMPLEX circuit matrix using the small signal
|
||||
* parameters saved during a previous DC operating point analysis.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numd2def.h"
|
||||
#include "sperror.h"
|
||||
#include "complex.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "numglobs.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* External Declarations */
|
||||
extern int TWOacDebug;
|
||||
|
||||
int
|
||||
NUMD2acLoad(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
{
|
||||
register NUMD2model *model = (NUMD2model *) inModel;
|
||||
register NUMD2instance *inst;
|
||||
SPcomplex y;
|
||||
double startTime;
|
||||
|
||||
/* loop through all the diode models */
|
||||
for (; model != NULL; model = model->NUMD2nextModel) {
|
||||
FieldDepMobility = model->NUMD2models->MODLfieldDepMobility;
|
||||
TransDepMobility = model->NUMD2models->MODLtransDepMobility;
|
||||
SurfaceMobility = model->NUMD2models->MODLsurfaceMobility;
|
||||
Srh = model->NUMD2models->MODLsrh;
|
||||
Auger = model->NUMD2models->MODLauger;
|
||||
AvalancheGen = model->NUMD2models->MODLavalancheGen;
|
||||
OneCarrier = model->NUMD2methods->METHoneCarrier;
|
||||
AcAnalysisMethod = model->NUMD2methods->METHacAnalysisMethod;
|
||||
MobDeriv = model->NUMD2methods->METHmobDeriv;
|
||||
TWOacDebug = model->NUMD2outputs->OUTPacDebug;
|
||||
|
||||
for (inst = model->NUMD2instances; inst != NULL;
|
||||
inst = inst->NUMD2nextInstance) {
|
||||
if (inst->NUMD2owner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NUMD2globals));
|
||||
|
||||
model->NUMD2methods->METHacAnalysisMethod =
|
||||
NUMD2admittance(inst->NUMD2pDevice, ckt->CKTomega, &y);
|
||||
|
||||
*(inst->NUMD2posPosPtr) += y.real;
|
||||
*(inst->NUMD2posPosPtr + 1) += y.imag;
|
||||
*(inst->NUMD2negNegPtr) += y.real;
|
||||
*(inst->NUMD2negNegPtr + 1) += y.imag;
|
||||
*(inst->NUMD2negPosPtr) -= y.real;
|
||||
*(inst->NUMD2negPosPtr + 1) -= y.imag;
|
||||
*(inst->NUMD2posNegPtr) -= y.real;
|
||||
*(inst->NUMD2posNegPtr + 1) -= y.imag;
|
||||
if (ckt->CKTomega != 0.0) {
|
||||
inst->NUMD2c11 = y.imag / ckt->CKTomega;
|
||||
} else {
|
||||
inst->NUMD2c11 = 0.0; /* XXX What else can be done?! */
|
||||
}
|
||||
inst->NUMD2y11r = y.real;
|
||||
inst->NUMD2y11i = y.imag;
|
||||
inst->NUMD2smSigAvail = TRUE;
|
||||
inst->NUMD2pDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Thomas L. Quarles
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "cktdefs.h"
|
||||
#include "devdefs.h"
|
||||
#include "numd2def.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
|
||||
/* Check out this one */
|
||||
extern int NUMD2initSmSig(NUMD2instance *);
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
NUMD2ask(ckt, inInst, which, value, select)
|
||||
CKTcircuit *ckt;
|
||||
GENinstance *inInst;
|
||||
int which;
|
||||
IFvalue *value;
|
||||
IFvalue *select;
|
||||
{
|
||||
NUMD2instance *inst = (NUMD2instance *) inInst;
|
||||
switch (which) {
|
||||
case NUMD2_WIDTH:
|
||||
value->rValue = inst->NUMD2width;
|
||||
return (OK);
|
||||
case NUMD2_AREA:
|
||||
value->rValue = inst->NUMD2area;
|
||||
break;
|
||||
case NUMD2_TEMP:
|
||||
value->rValue = inst->NUMD2temp - CONSTCtoK;
|
||||
return (OK);
|
||||
case NUMD2_VD:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMD2voltage);
|
||||
return (OK);
|
||||
case NUMD2_ID:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMD2id);
|
||||
return (OK);
|
||||
case NUMD2_G11:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMD2conduct);
|
||||
return (OK);
|
||||
case NUMD2_G12:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NUMD2conduct);
|
||||
return (OK);
|
||||
case NUMD2_G21:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NUMD2conduct);
|
||||
return (OK);
|
||||
case NUMD2_G22:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMD2conduct);
|
||||
return (OK);
|
||||
case NUMD2_C11:
|
||||
if (!inst->NUMD2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMD2initSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMD2c11;
|
||||
return (OK);
|
||||
case NUMD2_C12:
|
||||
if (!inst->NUMD2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMD2initSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NUMD2c11;
|
||||
return (OK);
|
||||
case NUMD2_C21:
|
||||
if (!inst->NUMD2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMD2initSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NUMD2c11;
|
||||
return (OK);
|
||||
case NUMD2_C22:
|
||||
if (!inst->NUMD2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMD2initSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMD2c11;
|
||||
return (OK);
|
||||
case NUMD2_Y11:
|
||||
if (!inst->NUMD2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMD2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMD2y11r;
|
||||
value->cValue.imag = inst->NUMD2y11i;
|
||||
return (OK);
|
||||
case NUMD2_Y12:
|
||||
if (!inst->NUMD2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMD2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NUMD2y11r;
|
||||
value->cValue.imag = -inst->NUMD2y11i;
|
||||
return (OK);
|
||||
case NUMD2_Y21:
|
||||
if (!inst->NUMD2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMD2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NUMD2y11r;
|
||||
value->cValue.imag = -inst->NUMD2y11i;
|
||||
return (OK);
|
||||
case NUMD2_Y22:
|
||||
if (!inst->NUMD2smSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMD2initSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMD2y11r;
|
||||
value->cValue.imag = inst->NUMD2y11i;
|
||||
return (OK);
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "numd2def.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NUMD2delete(inModel, name, kill)
|
||||
GENmodel *inModel;
|
||||
IFuid name;
|
||||
GENinstance **kill;
|
||||
{
|
||||
NUMD2model *model = (NUMD2model *) inModel;
|
||||
NUMD2instance **fast = (NUMD2instance **) kill;
|
||||
NUMD2instance **prev = NULL;
|
||||
NUMD2instance *inst;
|
||||
|
||||
for (; model; model = model->NUMD2nextModel) {
|
||||
prev = &(model->NUMD2instances);
|
||||
for (inst = *prev; inst; inst = *prev) {
|
||||
if (inst->NUMD2name == name || (fast && inst == *fast)) {
|
||||
*prev = inst->NUMD2nextInstance;
|
||||
FREE(inst);
|
||||
return (OK);
|
||||
}
|
||||
prev = &(inst->NUMD2nextInstance);
|
||||
}
|
||||
}
|
||||
return (E_NODEV);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine deletes all NUMD2s from the circuit and frees all storage
|
||||
* they were using. The current implementation has memory leaks.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "numd2def.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
void
|
||||
NUMD2destroy(inModel)
|
||||
GENmodel **inModel;
|
||||
{
|
||||
|
||||
NUMD2model **model = (NUMD2model **) inModel;
|
||||
NUMD2model *mod, *nextMod;
|
||||
NUMD2instance *inst, *nextInst;
|
||||
|
||||
|
||||
for (mod = *model; mod;) {
|
||||
for (inst = mod->NUMD2instances; inst;) {
|
||||
TWOdestroy(inst->NUMD2pDevice);
|
||||
nextInst = inst->NUMD2nextInstance;
|
||||
FREE(inst);
|
||||
inst = nextInst;
|
||||
}
|
||||
nextMod = mod->NUMD2nextModel;
|
||||
FREE(mod);
|
||||
mod = nextMod;
|
||||
}
|
||||
*model = NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This is a simple routine to dump the internal device states. It produces
|
||||
* states for .OP, .DC, & .TRAN simulations.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numd2def.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
|
||||
/* Forward Declarations */
|
||||
static void NUMD2putHeader(FILE *, CKTcircuit *, NUMD2instance *);
|
||||
|
||||
/* State Counter */
|
||||
static int state_numOP = 0;
|
||||
static int state_numDC = 0;
|
||||
static int state_numTR = 0;
|
||||
|
||||
void
|
||||
NUMD2dump(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
{
|
||||
register NUMD2model *model = (NUMD2model *) inModel;
|
||||
register NUMD2instance *inst;
|
||||
OUTPcard *output;
|
||||
FILE *fpState;
|
||||
char fileName[BSIZE_SP];
|
||||
char description[BSIZE_SP];
|
||||
char *prefix;
|
||||
int *state_num;
|
||||
int anyOutput = 0;
|
||||
|
||||
if (ckt->CKTmode & MODEDCOP) {
|
||||
prefix = "OP";
|
||||
state_num = &state_numOP;
|
||||
sprintf(description, "...");
|
||||
} else if (ckt->CKTmode & MODEDCTRANCURVE) {
|
||||
prefix = "DC";
|
||||
state_num = &state_numDC;
|
||||
sprintf(description, "sweep = % e", ckt->CKTtime);
|
||||
} else if (ckt->CKTmode & MODETRAN) {
|
||||
prefix = "TR";
|
||||
state_num = &state_numTR;
|
||||
sprintf(description, "time = % e", ckt->CKTtime);
|
||||
} else {
|
||||
/* Not a recognized CKT mode. */
|
||||
return;
|
||||
}
|
||||
|
||||
for (; model != NULL; model = model->NUMD2nextModel) {
|
||||
output = model->NUMD2outputs;
|
||||
for (inst = model->NUMD2instances; inst != NULL;
|
||||
inst = inst->NUMD2nextInstance) {
|
||||
if (inst->NUMD2owner != ARCHme) continue;
|
||||
|
||||
if (inst->NUMD2printGiven) {
|
||||
if ((ckt->CKTmode & MODETRAN) &&
|
||||
((ckt->CKTstat->STATaccepted - 1) % inst->NUMD2print != 0)) {
|
||||
continue;
|
||||
}
|
||||
anyOutput = 1;
|
||||
sprintf(fileName, "%s%s.%d.%s", output->OUTProotFile, prefix,
|
||||
*state_num, inst->NUMD2name);
|
||||
if (!(fpState = fopen(fileName, "w"))) {
|
||||
perror(fileName);
|
||||
} else {
|
||||
NUMD2putHeader(fpState, ckt, inst);
|
||||
TWOprnSolution(fpState, inst->NUMD2pDevice,
|
||||
model->NUMD2outputs);
|
||||
fclose(fpState);
|
||||
LOGmakeEntry(fileName, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (anyOutput) {
|
||||
(*state_num)++;
|
||||
}
|
||||
}
|
||||
|
||||
#define NUMD2numOutputs 4
|
||||
|
||||
static
|
||||
void
|
||||
NUMD2putHeader(file, ckt, inst)
|
||||
FILE *file;
|
||||
CKTcircuit *ckt;
|
||||
NUMD2instance *inst;
|
||||
{
|
||||
char *reference;
|
||||
double refVal = 0.0;
|
||||
int numVars = NUMD2numOutputs;
|
||||
|
||||
if (ckt->CKTmode & MODEDCOP) {
|
||||
reference = NULL;
|
||||
} else if (ckt->CKTmode & MODEDCTRANCURVE) {
|
||||
reference = "sweep";
|
||||
refVal = ckt->CKTtime;
|
||||
numVars++;
|
||||
} else if (ckt->CKTmode & MODETRAN) {
|
||||
reference = "time";
|
||||
refVal = ckt->CKTtime;
|
||||
numVars++;
|
||||
} else {
|
||||
reference = NULL;
|
||||
}
|
||||
fprintf(file, "Title: Device %s external state\n", inst->NUMD2name);
|
||||
fprintf(file, "Plotname: Device Operating Point\n");
|
||||
fprintf(file, "Command: deftype v conductance S\n");
|
||||
fprintf(file, "Flags: real\n");
|
||||
fprintf(file, "No. Variables: %d\n", numVars);
|
||||
fprintf(file, "No. Points: 1\n");
|
||||
numVars = 0;
|
||||
fprintf(file, "Variables:\n");
|
||||
if (reference) {
|
||||
fprintf(file, "\t%d %s unknown\n", numVars++, reference);
|
||||
}
|
||||
fprintf(file, "\t%d v12 voltage\n", numVars++);
|
||||
fprintf(file, "\t%d i1 current\n", numVars++);
|
||||
fprintf(file, "\t%d i2 current\n", numVars++);
|
||||
fprintf(file, "\t%d g11 conductance\n", numVars++);
|
||||
fprintf(file, "Values:\n0");
|
||||
if (reference) {
|
||||
fprintf(file, "\t% e\n", refVal);
|
||||
}
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMD2voltage));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMD2id));
|
||||
fprintf(file, "\t% e\n", - *(ckt->CKTstate0 + inst->NUMD2id));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMD2conduct));
|
||||
}
|
||||
|
||||
void
|
||||
NUMD2acct(inModel, ckt, file)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
FILE *file;
|
||||
{
|
||||
register NUMD2model *model = (NUMD2model *) inModel;
|
||||
register NUMD2instance *inst;
|
||||
OUTPcard *output;
|
||||
|
||||
for (; model != NULL; model = model->NUMD2nextModel) {
|
||||
output = model->NUMD2outputs;
|
||||
for (inst = model->NUMD2instances; inst != NULL;
|
||||
inst = inst->NUMD2nextInstance) {
|
||||
if (inst->NUMD2owner != ARCHme) continue;
|
||||
|
||||
if (output->OUTPstats) {
|
||||
TWOmemStats(file, inst->NUMD2pDevice);
|
||||
TWOcpuStats(file, inst->NUMD2pDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,408 @@
|
|||
/**********
|
||||
Copyright 1992 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
|
||||
* Diodes in the circuit and load them into the matrix as appropriate
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "devdefs.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numd2def.h"
|
||||
#include "trandefs.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
|
||||
/* Forward declarations */
|
||||
int NUMD2initSmSig(NUMD2instance *);
|
||||
|
||||
/* External Declarations */
|
||||
extern int TWOdcDebug;
|
||||
extern int TWOtranDebug;
|
||||
extern int TWOacDebug;
|
||||
|
||||
int
|
||||
NUMD2load(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
|
||||
{
|
||||
register NUMD2model *model = (NUMD2model *) inModel;
|
||||
register NUMD2instance *inst;
|
||||
register TWOdevice *pDevice;
|
||||
double startTime, startTime2, totalTime, totalTime2;
|
||||
double id;
|
||||
double idhat = 0.0;
|
||||
double ideq;
|
||||
double gd;
|
||||
double xfact;
|
||||
double tol; /* temporary for tolerance calculations */
|
||||
double vd; /* current diode voltage */
|
||||
double delVd;
|
||||
int Check;
|
||||
int error;
|
||||
double deltaNorm[7];
|
||||
int devConverged = FALSE;
|
||||
int i;
|
||||
int numDevNonCon;
|
||||
int deviceType;
|
||||
int doInitSolve;
|
||||
int doVoltPred;
|
||||
char *initStateName;
|
||||
|
||||
/* loop through all the diode models */
|
||||
for (; model != NULL; model = model->NUMD2nextModel) {
|
||||
FieldDepMobility = model->NUMD2models->MODLfieldDepMobility;
|
||||
TransDepMobility = model->NUMD2models->MODLtransDepMobility;
|
||||
SurfaceMobility = model->NUMD2models->MODLsurfaceMobility;
|
||||
Srh = model->NUMD2models->MODLsrh;
|
||||
Auger = model->NUMD2models->MODLauger;
|
||||
AvalancheGen = model->NUMD2models->MODLavalancheGen;
|
||||
OneCarrier = model->NUMD2methods->METHoneCarrier;
|
||||
MobDeriv = model->NUMD2methods->METHmobDeriv;
|
||||
MaxIterations = model->NUMD2methods->METHitLim;
|
||||
TWOdcDebug = model->NUMD2outputs->OUTPdcDebug;
|
||||
TWOtranDebug = model->NUMD2outputs->OUTPtranDebug;
|
||||
TWOacDebug = model->NUMD2outputs->OUTPacDebug;
|
||||
deviceType = model->NUMD2options->OPTNdeviceType;
|
||||
doVoltPred = model->NUMD2methods->METHvoltPred;
|
||||
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
/* compute normalized deltas and predictor coeff */
|
||||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) {
|
||||
model->NUMD2pInfo->order = ckt->CKTorder;
|
||||
model->NUMD2pInfo->method = ckt->CKTintegrateMethod;
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder,
|
||||
model->NUMD2pInfo->intCoeff, deltaNorm);
|
||||
computePredCoeff(ckt->CKTintegrateMethod, ckt->CKTorder,
|
||||
model->NUMD2pInfo->predCoeff, deltaNorm);
|
||||
}
|
||||
} else if (ckt->CKTmode & MODEINITTRAN) {
|
||||
model->NUMD2pInfo->order = ckt->CKTorder;
|
||||
model->NUMD2pInfo->method = GEAR;
|
||||
model->NUMD2pInfo->method = ckt->CKTintegrateMethod;
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
computeIntegCoeff(ckt->CKTintegrateMethod, ckt->CKTorder,
|
||||
model->NUMD2pInfo->intCoeff, deltaNorm);
|
||||
}
|
||||
/* loop through all the instances of the model */
|
||||
for (inst = model->NUMD2instances; inst != NULL;
|
||||
inst = inst->NUMD2nextInstance) {
|
||||
if (inst->NUMD2owner != ARCHme) continue;
|
||||
|
||||
pDevice = inst->NUMD2pDevice;
|
||||
|
||||
totalTime = 0.0;
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NUMD2globals));
|
||||
|
||||
pDevice->devStates = ckt->CKTstates;
|
||||
/*
|
||||
* initialization
|
||||
*/
|
||||
Check = 1;
|
||||
doInitSolve = FALSE;
|
||||
initStateName = NULL;
|
||||
if (ckt->CKTmode & MODEINITSMSIG) {
|
||||
vd = *(ckt->CKTstate0 + inst->NUMD2voltage);
|
||||
delVd = 0.0;
|
||||
NUMD2setBCs(pDevice, vd);
|
||||
} else if (ckt->CKTmode & MODEINITTRAN) {
|
||||
*(ckt->CKTstate0 + inst->NUMD2voltage) =
|
||||
*(ckt->CKTstate1 + inst->NUMD2voltage);
|
||||
vd = *(ckt->CKTstate1 + inst->NUMD2voltage);
|
||||
TWOsaveState(pDevice);
|
||||
delVd = 0.0;
|
||||
} else if ((ckt->CKTmode & MODEINITJCT) &&
|
||||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) {
|
||||
doInitSolve = TRUE;
|
||||
initStateName = inst->NUMD2icFile;
|
||||
vd = 0.0;
|
||||
delVd = vd;
|
||||
} else if ((ckt->CKTmode & MODEINITJCT) && inst->NUMD2off) {
|
||||
doInitSolve = TRUE;
|
||||
vd = 0.0;
|
||||
delVd = vd;
|
||||
} else if (ckt->CKTmode & MODEINITJCT) {
|
||||
doInitSolve = TRUE;
|
||||
initStateName = inst->NUMD2icFile;
|
||||
if (deviceType == OPTN_DIODE) {
|
||||
vd = inst->NUMD2type * 0.6;
|
||||
} else if (deviceType == OPTN_MOSCAP) {
|
||||
vd = inst->NUMD2type * 0.8;
|
||||
} else {
|
||||
vd = 0.0;
|
||||
}
|
||||
delVd = vd;
|
||||
} else if (ckt->CKTmode & MODEINITFIX && inst->NUMD2off) {
|
||||
vd = 0.0;
|
||||
delVd = vd;
|
||||
} else {
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
*(ckt->CKTstate0 + inst->NUMD2voltage) =
|
||||
*(ckt->CKTstate1 + inst->NUMD2voltage);
|
||||
*(ckt->CKTstate0 + inst->NUMD2id) =
|
||||
*(ckt->CKTstate1 + inst->NUMD2id);
|
||||
*(ckt->CKTstate0 + inst->NUMD2conduct) =
|
||||
*(ckt->CKTstate1 + inst->NUMD2conduct);
|
||||
if (!(ckt->CKTmode & MODEDCTRANCURVE)) {
|
||||
/* no linear prediction on device voltages */
|
||||
vd = *(ckt->CKTstate1 + inst->NUMD2voltage);
|
||||
TWOpredict(pDevice, model->NUMD2pInfo);
|
||||
} else {
|
||||
if (doVoltPred) {
|
||||
/* linear prediction */
|
||||
xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1];
|
||||
vd = (1+xfact) * (*(ckt->CKTstate1 + inst->NUMD2voltage))
|
||||
- (xfact) * (*(ckt->CKTstate2 + inst->NUMD2voltage));
|
||||
} else {
|
||||
vd = *(ckt->CKTstate1 + inst->NUMD2voltage);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vd = *(ckt->CKTrhsOld + inst->NUMD2posNode) -
|
||||
*(ckt->CKTrhsOld + inst->NUMD2negNode);
|
||||
}
|
||||
delVd = vd - *(ckt->CKTstate0 + inst->NUMD2voltage);
|
||||
idhat = *(ckt->CKTstate0 + inst->NUMD2id) +
|
||||
*(ckt->CKTstate0 + inst->NUMD2conduct) * delVd;
|
||||
/*
|
||||
* bypass if solution has not changed
|
||||
*/
|
||||
if ((ckt->CKTbypass) && pDevice->converged &&
|
||||
!(ckt->CKTmode & MODEINITPRED)) {
|
||||
tol = ckt->CKTvoltTol + ckt->CKTreltol *
|
||||
MAX(fabs(vd), fabs(*(ckt->CKTstate0 + inst->NUMD2voltage)));
|
||||
if (fabs(delVd) < tol) {
|
||||
tol = ckt->CKTreltol *
|
||||
MAX(fabs(idhat), fabs(*(ckt->CKTstate0 + inst->NUMD2id))) +
|
||||
ckt->CKTabstol;
|
||||
if (fabs(idhat - *(ckt->CKTstate0 + inst->NUMD2id))
|
||||
< tol) {
|
||||
vd = *(ckt->CKTstate0 + inst->NUMD2voltage);
|
||||
id = *(ckt->CKTstate0 + inst->NUMD2id);
|
||||
gd = *(ckt->CKTstate0 + inst->NUMD2conduct);
|
||||
goto load;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* limit new junction voltage
|
||||
*/
|
||||
if (deviceType == OPTN_DIODE) {
|
||||
vd = inst->NUMD2type * limitJunctionVoltage(
|
||||
inst->NUMD2type * vd,
|
||||
inst->NUMD2type * *(ckt->CKTstate0 + inst->NUMD2voltage),
|
||||
&Check);
|
||||
} else if (deviceType == OPTN_MOSCAP) {
|
||||
vd = inst->NUMD2type * limitVgb(
|
||||
inst->NUMD2type * vd,
|
||||
inst->NUMD2type * *(ckt->CKTstate0 + inst->NUMD2voltage),
|
||||
&Check);
|
||||
} else {
|
||||
vd = inst->NUMD2type * limitResistorVoltage(
|
||||
inst->NUMD2type * vd,
|
||||
inst->NUMD2type * *(ckt->CKTstate0 + inst->NUMD2voltage),
|
||||
&Check);
|
||||
}
|
||||
delVd = vd - *(ckt->CKTstate0 + inst->NUMD2voltage);
|
||||
NUMD2setBCs(pDevice, vd - delVd);
|
||||
}
|
||||
if (doInitSolve) {
|
||||
if (TWOdcDebug) {
|
||||
printVoltages(stdout,
|
||||
model->NUMD2modName, inst->NUMD2name,
|
||||
deviceType, 1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
startTime2 = SPfrontEnd->IFseconds();
|
||||
TWOequilSolve(pDevice);
|
||||
totalTime2 = SPfrontEnd->IFseconds() - startTime2;
|
||||
pDevice->pStats->totalTime[STAT_SETUP] += totalTime2;
|
||||
pDevice->pStats->totalTime[STAT_DC] -= totalTime2;
|
||||
|
||||
TWObiasSolve(pDevice, MaxIterations, FALSE, NULL);
|
||||
|
||||
*(ckt->CKTstate0 + inst->NUMD2voltage) = 0.0;
|
||||
|
||||
if (initStateName != NULL) {
|
||||
if (TWOreadState(pDevice, initStateName, 1, &vd, NULL, NULL ) < 0) {
|
||||
fprintf(stderr,
|
||||
"NUMD2load: trouble reading state-file %s\n", initStateName);
|
||||
} else {
|
||||
*(ckt->CKTstate0 + inst->NUMD2voltage) = vd;
|
||||
NUMD2setBCs(pDevice, vd);
|
||||
delVd = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* compute dc current and derivitives
|
||||
*/
|
||||
/* use the routines for numerical simulation */
|
||||
|
||||
if (ckt->CKTmode & (MODEDCOP | MODETRANOP | MODEDCTRANCURVE | MODEINITSMSIG)) {
|
||||
numDevNonCon = 0;
|
||||
inst->NUMD2c11 = inst->NUMD2y11r = inst->NUMD2y11i = 0.0;
|
||||
inst->NUMD2smSigAvail = FALSE;
|
||||
devNonCon:
|
||||
NUMD2project(pDevice, delVd);
|
||||
if (TWOdcDebug) {
|
||||
printVoltages(stdout,
|
||||
model->NUMD2modName, inst->NUMD2name,
|
||||
deviceType, 1, vd, delVd, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
TWObiasSolve(pDevice, MaxIterations, FALSE, model->NUMD2pInfo);
|
||||
devConverged = pDevice->converged;
|
||||
|
||||
if (devConverged && finite(pDevice->rhsNorm)) {
|
||||
/* extract the current and conductance information */
|
||||
NUMD2current(pDevice, FALSE, (double *) NULL, &id);
|
||||
NUMD2conductance(pDevice, FALSE, (double *) NULL, &gd);
|
||||
} else {
|
||||
/* do voltage step backtracking */
|
||||
/* restore the boundary nodes to the previous value */
|
||||
NUMD2setBCs(pDevice, vd - delVd);
|
||||
TWOstoreInitialGuess(pDevice);
|
||||
TWOresetJacobian(pDevice);
|
||||
delVd *= 0.5;
|
||||
vd = delVd + *(ckt->CKTstate0 + inst->NUMD2voltage);
|
||||
numDevNonCon++;
|
||||
Check = 1;
|
||||
if (numDevNonCon > 10) {
|
||||
printVoltages(stderr,
|
||||
model->NUMD2modName, inst->NUMD2name,
|
||||
deviceType, 1, vd, delVd, 0.0, 0.0, 0.0, 0.0);
|
||||
fprintf(stderr,
|
||||
"*** Non-convergence during load ***\n");
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
return (E_BADMATRIX);
|
||||
} else {
|
||||
goto devNonCon;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((ckt->CKTmode & (MODETRAN | MODEAC | MODEINITSMSIG)) ||
|
||||
(ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) {
|
||||
/*
|
||||
* store small-signal parameters
|
||||
*/
|
||||
if ((!(ckt->CKTmode & MODETRANOP)) ||
|
||||
(!(ckt->CKTmode & MODEUIC))) {
|
||||
if (ckt->CKTmode & MODEINITSMSIG) {
|
||||
totalTime = SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
startTime2 = SPfrontEnd->IFseconds();
|
||||
NUMD2initSmSig(inst);
|
||||
pDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime2;
|
||||
continue;
|
||||
} else {
|
||||
inst->NUMD2smSigAvail = FALSE;
|
||||
}
|
||||
/*
|
||||
* transient analysis
|
||||
*/
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
NUMD2setBCs(pDevice, vd);
|
||||
TWOstoreInitialGuess(pDevice);
|
||||
} else {
|
||||
NUMD2update(pDevice, delVd, TRUE);
|
||||
}
|
||||
if (TWOtranDebug) {
|
||||
printVoltages(stdout,
|
||||
model->NUMD2modName, inst->NUMD2name,
|
||||
deviceType, 1, vd, delVd, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
TWObiasSolve(pDevice, 0, TRUE, model->NUMD2pInfo);
|
||||
|
||||
if (!finite(pDevice->rhsNorm)) {
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
return (E_BADMATRIX);
|
||||
}
|
||||
devConverged = TWOdeviceConverged(pDevice);
|
||||
pDevice->converged = devConverged;
|
||||
|
||||
/* extract the current and conductance information */
|
||||
NUMD2current(pDevice, TRUE, model->NUMD2pInfo->intCoeff, &id);
|
||||
NUMD2conductance(pDevice, TRUE, model->NUMD2pInfo->intCoeff, &gd);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check convergence
|
||||
*/
|
||||
if ((!(ckt->CKTmode & MODEINITFIX)) || (!(inst->NUMD2off))) {
|
||||
if (Check == 1 || !devConverged) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
} else {
|
||||
tol = ckt->CKTreltol * MAX(fabs(idhat), fabs(id)) + ckt->CKTabstol;
|
||||
if (fabs(idhat - id) > tol) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
}
|
||||
}
|
||||
}
|
||||
*(ckt->CKTstate0 + inst->NUMD2voltage) = vd;
|
||||
*(ckt->CKTstate0 + inst->NUMD2id) = id;
|
||||
*(ckt->CKTstate0 + inst->NUMD2conduct) = gd;
|
||||
|
||||
load:
|
||||
|
||||
/*
|
||||
* load current vector
|
||||
*/
|
||||
ideq = id - gd * vd;
|
||||
*(ckt->CKTrhs + inst->NUMD2negNode) += ideq;
|
||||
*(ckt->CKTrhs + inst->NUMD2posNode) -= ideq;
|
||||
/*
|
||||
* load matrix
|
||||
*/
|
||||
*(inst->NUMD2posPosPtr) += gd;
|
||||
*(inst->NUMD2negNegPtr) += gd;
|
||||
*(inst->NUMD2negPosPtr) -= gd;
|
||||
*(inst->NUMD2posNegPtr) -= gd;
|
||||
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
if (ckt->CKTmode & MODETRAN) {
|
||||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime;
|
||||
} else {
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
||||
int
|
||||
NUMD2initSmSig(inst)
|
||||
NUMD2instance *inst;
|
||||
{
|
||||
SPcomplex yd;
|
||||
double omega = inst->NUMD2modPtr->NUMD2methods->METHomega;
|
||||
|
||||
AcAnalysisMethod = SOR_ONLY;
|
||||
(void) NUMD2admittance(inst->NUMD2pDevice, omega, &yd);
|
||||
inst->NUMD2c11 = yd.imag / omega;
|
||||
inst->NUMD2y11r = yd.real;
|
||||
inst->NUMD2y11i = yd.imag;
|
||||
inst->NUMD2smSigAvail = TRUE;
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "numd2def.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NUMD2mDelete(inModel, modname, kill)
|
||||
GENmodel **inModel;
|
||||
IFuid modname;
|
||||
GENmodel *kill;
|
||||
|
||||
{
|
||||
NUMD2model **model = (NUMD2model **) inModel;
|
||||
NUMD2model *modfast = (NUMD2model *) kill;
|
||||
NUMD2instance *inst;
|
||||
NUMD2instance *prev = NULL;
|
||||
NUMD2model **oldmod;
|
||||
oldmod = model;
|
||||
for (; *model; model = &((*model)->NUMD2nextModel)) {
|
||||
if ((*model)->NUMD2modName == modname ||
|
||||
(modfast && *model == modfast))
|
||||
goto delgot;
|
||||
oldmod = model;
|
||||
}
|
||||
return (E_NOMOD);
|
||||
|
||||
delgot:
|
||||
*oldmod = (*model)->NUMD2nextModel; /* cut deleted device out of list */
|
||||
for (inst = (*model)->NUMD2instances; inst; inst = inst->NUMD2nextInstance) {
|
||||
if (prev)
|
||||
FREE(prev);
|
||||
prev = inst;
|
||||
}
|
||||
if (prev)
|
||||
FREE(prev);
|
||||
FREE(*model);
|
||||
return (OK);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine sets model parameters for NUMD2s in the circuit.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "numd2def.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NUMD2mParam(param, value, inModel)
|
||||
int param;
|
||||
IFvalue *value;
|
||||
GENmodel *inModel;
|
||||
{
|
||||
switch (param) {
|
||||
case NUMD2_MOD_NUMD:
|
||||
/* no action - already know it is a 2d-numerical diode, but this */
|
||||
/* makes life easier for spice-2 like parsers */
|
||||
break;
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "numd2def.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NUMD2param(param, value, inInst, select)
|
||||
int param;
|
||||
IFvalue *value;
|
||||
GENinstance *inInst;
|
||||
IFvalue *select;
|
||||
{
|
||||
NUMD2instance *inst = (NUMD2instance *) inInst;
|
||||
switch (param) {
|
||||
case NUMD2_WIDTH:
|
||||
inst->NUMD2width = value->rValue;
|
||||
inst->NUMD2widthGiven = TRUE;
|
||||
break;
|
||||
case NUMD2_AREA:
|
||||
inst->NUMD2area = value->rValue;
|
||||
inst->NUMD2areaGiven = TRUE;
|
||||
break;
|
||||
case NUMD2_OFF:
|
||||
inst->NUMD2off = TRUE;
|
||||
break;
|
||||
case NUMD2_IC_FILE:
|
||||
inst->NUMD2icFile = value->sValue;
|
||||
inst->NUMD2icFileGiven = TRUE;
|
||||
break;
|
||||
case NUMD2_PRINT:
|
||||
inst->NUMD2print = value->rValue;
|
||||
inst->NUMD2printGiven = TRUE;
|
||||
break;
|
||||
case NUMD2_TEMP:
|
||||
inst->NUMD2temp = value->rValue + CONSTCtoK;
|
||||
inst->NUMD2tempGiven = TRUE;
|
||||
break;
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "complex.h"
|
||||
#include "sperror.h"
|
||||
#include "numd2def.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* External Declarations */
|
||||
extern int TWOacDebug;
|
||||
|
||||
int
|
||||
NUMD2pzLoad(inModel, ckt, s)
|
||||
GENmodel *inModel;
|
||||
register CKTcircuit *ckt;
|
||||
SPcomplex *s;
|
||||
{
|
||||
register NUMD2model *model = (NUMD2model *) inModel;
|
||||
register NUMD2instance *inst;
|
||||
SPcomplex y;
|
||||
double startTime;
|
||||
|
||||
/* loop through all the diode models */
|
||||
for (; model != NULL; model = model->NUMD2nextModel) {
|
||||
FieldDepMobility = model->NUMD2models->MODLfieldDepMobility;
|
||||
TransDepMobility = model->NUMD2models->MODLtransDepMobility;
|
||||
SurfaceMobility = model->NUMD2models->MODLsurfaceMobility;
|
||||
Srh = model->NUMD2models->MODLsrh;
|
||||
Auger = model->NUMD2models->MODLauger;
|
||||
AvalancheGen = model->NUMD2models->MODLavalancheGen;
|
||||
OneCarrier = model->NUMD2methods->METHoneCarrier;
|
||||
AcAnalysisMethod = model->NUMD2methods->METHacAnalysisMethod;
|
||||
MobDeriv = model->NUMD2methods->METHmobDeriv;
|
||||
TWOacDebug = model->NUMD2outputs->OUTPacDebug;
|
||||
|
||||
for (inst = model->NUMD2instances; inst != NULL;
|
||||
inst = inst->NUMD2nextInstance) {
|
||||
if (inst->NUMD2owner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NUMD2globals));
|
||||
|
||||
NUMD2ys(inst->NUMD2pDevice, s, &y);
|
||||
|
||||
*(inst->NUMD2posPosPtr) += y.real;
|
||||
*(inst->NUMD2posPosPtr + 1) += y.imag;
|
||||
*(inst->NUMD2negNegPtr) += y.real;
|
||||
*(inst->NUMD2negNegPtr + 1) += y.imag;
|
||||
*(inst->NUMD2negPosPtr) -= y.real;
|
||||
*(inst->NUMD2negPosPtr + 1) -= y.imag;
|
||||
*(inst->NUMD2posNegPtr) -= y.real;
|
||||
*(inst->NUMD2posNegPtr + 1) -= y.imag;
|
||||
|
||||
inst->NUMD2pDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,266 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "smpdefs.h"
|
||||
#include "numd2def.h"
|
||||
#include "numconst.h"
|
||||
#include "numenum.h"
|
||||
#include "meshext.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "ciderinp.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#define NIL(type) ((type *)0)
|
||||
#define TSCALLOC(var, size, type)\
|
||||
if (size && (!(var =(type *)calloc(1, (unsigned)(size)*sizeof(type))))) {\
|
||||
return(E_NOMEM);\
|
||||
}
|
||||
|
||||
int
|
||||
NUMD2setup(matrix, inModel, ckt, states)
|
||||
register SMPmatrix *matrix;
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
int *states;
|
||||
/*
|
||||
* load the structure with those pointers needed later for fast matrix
|
||||
* loading
|
||||
*/
|
||||
{
|
||||
register NUMD2model *model = (NUMD2model *) inModel;
|
||||
register NUMD2instance *inst;
|
||||
METHcard *methods;
|
||||
MODLcard *models;
|
||||
OPTNcard *options;
|
||||
OUTPcard *outputs;
|
||||
char *icFileName = NULL;
|
||||
int nameLen;
|
||||
int error, xIndex, yIndex;
|
||||
int xMeshSize, yMeshSize;
|
||||
TWOdevice *pDevice;
|
||||
TWOcoord *xCoordList = NIL(TWOcoord);
|
||||
TWOcoord *yCoordList = NIL(TWOcoord);
|
||||
TWOdomain *domainList = NIL(TWOdomain);
|
||||
TWOelectrode *electrodeList = NIL(TWOelectrode);
|
||||
TWOmaterial *pM, *pMaterial = NIL(TWOmaterial), *materialList = NIL(TWOmaterial);
|
||||
DOPprofile *profileList = NIL(DOPprofile);
|
||||
DOPtable *dopTableList = NIL(DOPtable);
|
||||
double startTime;
|
||||
|
||||
|
||||
/* loop through all the models */
|
||||
for (; model != NULL; model = model->NUMD2nextModel) {
|
||||
if (!model->NUMD2pInfo) {
|
||||
TSCALLOC(model->NUMD2pInfo, 1, TWOtranInfo);
|
||||
}
|
||||
methods = model->NUMD2methods;
|
||||
if (!methods) {
|
||||
TSCALLOC(methods, 1, METHcard);
|
||||
model->NUMD2methods = methods;
|
||||
}
|
||||
models = model->NUMD2models;
|
||||
if (!models) {
|
||||
TSCALLOC(models, 1, MODLcard);
|
||||
model->NUMD2models = models;
|
||||
}
|
||||
options = model->NUMD2options;
|
||||
if (!options) {
|
||||
TSCALLOC(options, 1, OPTNcard);
|
||||
model->NUMD2options = options;
|
||||
}
|
||||
outputs = model->NUMD2outputs;
|
||||
if (!outputs) {
|
||||
TSCALLOC(outputs, 1, OUTPcard);
|
||||
model->NUMD2outputs = outputs;
|
||||
}
|
||||
if (!methods->METHvoltPredGiven) {
|
||||
methods->METHvoltPred = FALSE;
|
||||
}
|
||||
if (!methods->METHmobDerivGiven) {
|
||||
methods->METHmobDeriv = TRUE;
|
||||
}
|
||||
if (!methods->METHoneCarrierGiven) {
|
||||
methods->METHoneCarrier = FALSE;
|
||||
}
|
||||
if (!methods->METHacAnalysisMethodGiven) {
|
||||
methods->METHacAnalysisMethod = SOR;
|
||||
}
|
||||
if (!methods->METHdabstolGiven) {
|
||||
methods->METHdabstol = DABSTOL2D;
|
||||
}
|
||||
if (!methods->METHdreltolGiven) {
|
||||
methods->METHdreltol = ckt->CKTreltol;
|
||||
}
|
||||
if (!methods->METHitLimGiven) {
|
||||
methods->METHitLim = 50;
|
||||
}
|
||||
if (!methods->METHomegaGiven || methods->METHomega <= 0.0) {
|
||||
methods->METHomega = 2.0 * M_PI /* radians/sec */ ;
|
||||
}
|
||||
if (!options->OPTNdefaGiven || options->OPTNdefa <= 0.0) {
|
||||
options->OPTNdefa = 1.0e4 /* cm^2 */ ;
|
||||
}
|
||||
if (!options->OPTNdeflGiven || options->OPTNdefl <= 0.0) {
|
||||
options->OPTNdefl = 1.0e2 /* cm */ ;
|
||||
}
|
||||
if (!options->OPTNdefwGiven && options->OPTNdefaGiven) {
|
||||
options->OPTNdefw = options->OPTNdefa / options->OPTNdefl;
|
||||
} else if (!options->OPTNdefwGiven || options->OPTNdefw <= 0.0) {
|
||||
options->OPTNdefw = 1.0e2 /* cm */ ;
|
||||
}
|
||||
if (!options->OPTNdeviceTypeGiven) {
|
||||
options->OPTNdeviceType = OPTN_DIODE;
|
||||
}
|
||||
if (!options->OPTNicFileGiven) {
|
||||
options->OPTNicFile = NULL;
|
||||
options->OPTNunique = FALSE; /* Can't form a unique name. */
|
||||
}
|
||||
if (!options->OPTNuniqueGiven) {
|
||||
options->OPTNunique = FALSE;
|
||||
}
|
||||
OneCarrier = methods->METHoneCarrier;
|
||||
|
||||
/* Set up the rest of the card lists */
|
||||
if ((error = MODLsetup(model->NUMD2models)))
|
||||
return (error);
|
||||
BandGapNarrowing = models->MODLbandGapNarrowing;
|
||||
ConcDepLifetime = models->MODLconcDepLifetime;
|
||||
TempDepMobility = models->MODLtempDepMobility;
|
||||
ConcDepMobility = models->MODLconcDepMobility;
|
||||
SurfaceMobility = models->MODLsurfaceMobility;
|
||||
|
||||
if ((error = OUTPsetup(model->NUMD2outputs)))
|
||||
return (error);
|
||||
if ((error = MATLsetup(model->NUMD2materials, &materialList)))
|
||||
return (error);
|
||||
if ((error = MOBsetup(model->NUMD2mobility, materialList)))
|
||||
return (error);
|
||||
if ((error = MESHsetup('x', model->NUMD2xMeshes, &xCoordList, &xMeshSize)))
|
||||
return (error);
|
||||
if ((error = MESHsetup('y', model->NUMD2yMeshes, &yCoordList, &yMeshSize)))
|
||||
return (error);
|
||||
if ((error = DOMNsetup(model->NUMD2domains, &domainList,
|
||||
xCoordList, yCoordList, materialList)))
|
||||
return (error);
|
||||
if ((error = BDRYsetup(model->NUMD2boundaries,
|
||||
xCoordList, yCoordList, domainList)))
|
||||
return (error);
|
||||
if ((error = ELCTsetup(model->NUMD2electrodes, &electrodeList,
|
||||
xCoordList, yCoordList)))
|
||||
return (error);
|
||||
/* Make sure electrodes are OK. */
|
||||
checkElectrodes(electrodeList, 2); /* NUMD2 has 4 electrodes */
|
||||
|
||||
if ((error = CONTsetup(model->NUMD2contacts, electrodeList)))
|
||||
return (error);
|
||||
if ((error = DOPsetup(model->NUMD2dopings, &profileList,
|
||||
&dopTableList, xCoordList, yCoordList)))
|
||||
return (error);
|
||||
model->NUMD2matlInfo = materialList;
|
||||
model->NUMD2profiles = profileList;
|
||||
model->NUMD2dopTables = dopTableList;
|
||||
|
||||
/* loop through all the instances of the model */
|
||||
for (inst = model->NUMD2instances; inst != NULL;
|
||||
inst = inst->NUMD2nextInstance) {
|
||||
if (inst->NUMD2owner != ARCHme) goto matrixpointers;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
if (!inst->NUMD2printGiven) {
|
||||
inst->NUMD2print = 0;
|
||||
} else if (inst->NUMD2print <= 0) {
|
||||
inst->NUMD2print = 1;
|
||||
}
|
||||
if (!inst->NUMD2icFileGiven) {
|
||||
if (options->OPTNunique) {
|
||||
nameLen = strlen(options->OPTNicFile) + strlen(inst->NUMD2name) + 1;
|
||||
TSCALLOC(icFileName, nameLen+1, char);
|
||||
sprintf(icFileName, "%s.%s", options->OPTNicFile, inst->NUMD2name);
|
||||
icFileName[nameLen] = '\0';
|
||||
inst->NUMD2icFile = icFileName;
|
||||
} else if (options->OPTNicFile != NULL) {
|
||||
nameLen = strlen(options->OPTNicFile);
|
||||
TSCALLOC(icFileName, nameLen+1, char);
|
||||
icFileName = strcpy(icFileName, options->OPTNicFile);
|
||||
inst->NUMD2icFile = icFileName;
|
||||
} else {
|
||||
inst->NUMD2icFile = NULL;
|
||||
}
|
||||
}
|
||||
inst->NUMD2state = *states;
|
||||
*states += NUMD2numStates;
|
||||
|
||||
if (!inst->NUMD2pDevice) {
|
||||
/* Assign the mesh and profile info to each instance. */
|
||||
TSCALLOC(pDevice, 1, TWOdevice);
|
||||
TSCALLOC(pDevice->pStats, 1, TWOstats);
|
||||
pDevice->name = inst->NUMD2name;
|
||||
pDevice->solverType = SLV_NONE;
|
||||
pDevice->numXNodes = xMeshSize;
|
||||
pDevice->numYNodes = yMeshSize;
|
||||
pDevice->xScale = MESHmkArray(xCoordList, xMeshSize);
|
||||
pDevice->yScale = MESHmkArray(yCoordList, yMeshSize);
|
||||
pDevice->abstol = methods->METHdabstol;
|
||||
pDevice->reltol = methods->METHdreltol;
|
||||
TSCALLOC(pDevice->elemArray, pDevice->numXNodes, TWOelem **);
|
||||
for (xIndex = 1; xIndex < pDevice->numXNodes; xIndex++) {
|
||||
TSCALLOC(pDevice->elemArray[xIndex], pDevice->numYNodes, TWOelem *);
|
||||
}
|
||||
|
||||
/* Create a copy of material data that can change with temperature. */
|
||||
pDevice->pMaterials = NIL(TWOmaterial);
|
||||
for (pM = materialList; pM != NIL(TWOmaterial); pM = pM->next) {
|
||||
if (pDevice->pMaterials == NIL(TWOmaterial)) {
|
||||
TSCALLOC(pMaterial, 1, TWOmaterial);
|
||||
pDevice->pMaterials = pMaterial;
|
||||
} else {
|
||||
TSCALLOC(pMaterial->next, 1, TWOmaterial);
|
||||
pMaterial = pMaterial->next;
|
||||
}
|
||||
/* Copy everything, then fix the incorrect pointer. */
|
||||
bcopy((char *) pM, (char *) pMaterial, sizeof(TWOmaterial));
|
||||
pMaterial->next = NIL(TWOmaterial);
|
||||
}
|
||||
|
||||
/* Generate the mesh structure for the device. */
|
||||
TWObuildMesh(pDevice, domainList, electrodeList, pDevice->pMaterials);
|
||||
|
||||
/* Store the device info in the instance. */
|
||||
inst->NUMD2pDevice = pDevice;
|
||||
}
|
||||
/* Now update the state pointers. */
|
||||
TWOgetStatePointers(inst->NUMD2pDevice, states);
|
||||
|
||||
/* Wipe out statistics from previous runs (if any). */
|
||||
bzero((char *) inst->NUMD2pDevice->pStats, sizeof(TWOstats));
|
||||
|
||||
inst->NUMD2pDevice->pStats->totalTime[STAT_SETUP] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
|
||||
/* macro to make elements with built in test for out of memory */
|
||||
#define TSTALLOC(ptr,first,second) \
|
||||
if ((inst->ptr = SMPmakeElt(matrix,inst->first,inst->second))==(double *)NULL){\
|
||||
return(E_NOMEM);\
|
||||
}
|
||||
matrixpointers:
|
||||
TSTALLOC(NUMD2posPosPtr, NUMD2posNode, NUMD2posNode)
|
||||
TSTALLOC(NUMD2negNegPtr, NUMD2negNode, NUMD2negNode)
|
||||
TSTALLOC(NUMD2negPosPtr, NUMD2negNode, NUMD2posNode)
|
||||
TSTALLOC(NUMD2posNegPtr, NUMD2posNode, NUMD2negNode)
|
||||
}
|
||||
/* Clean up lists */
|
||||
killCoordInfo(xCoordList);
|
||||
killCoordInfo(yCoordList);
|
||||
killDomainInfo(domainList);
|
||||
killElectrodeInfo(electrodeList);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
Author: 1992 David A. Gates, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numd2def.h"
|
||||
#include "numenum.h"
|
||||
#include "carddefs.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#define NIL(type) ((type *)0)
|
||||
|
||||
int
|
||||
NUMD2temp(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
register CKTcircuit *ckt;
|
||||
/*
|
||||
* perform the temperature update
|
||||
*/
|
||||
{
|
||||
register NUMD2model *model = (NUMD2model *) inModel;
|
||||
register NUMD2instance *inst;
|
||||
METHcard *methods;
|
||||
MODLcard *models;
|
||||
OPTNcard *options;
|
||||
OUTPcard *outputs;
|
||||
TWOmaterial *pM, *pMaterial, *pNextMaterial;
|
||||
double startTime;
|
||||
|
||||
/* loop through all the models */
|
||||
for (; model != NULL; model = model->NUMD2nextModel) {
|
||||
methods = model->NUMD2methods;
|
||||
models = model->NUMD2models;
|
||||
options = model->NUMD2options;
|
||||
outputs = model->NUMD2outputs;
|
||||
|
||||
if (!options->OPTNtnomGiven) {
|
||||
options->OPTNtnom = ckt->CKTnomTemp;
|
||||
}
|
||||
for (pM = model->NUMD2matlInfo; pM != NIL(TWOmaterial);
|
||||
pM = pM->next) {
|
||||
pM->tnom = options->OPTNtnom;
|
||||
}
|
||||
BandGapNarrowing = models->MODLbandGapNarrowing;
|
||||
ConcDepLifetime = models->MODLconcDepLifetime;
|
||||
TempDepMobility = models->MODLtempDepMobility;
|
||||
ConcDepMobility = models->MODLconcDepMobility;
|
||||
SurfaceMobility = models->MODLsurfaceMobility;
|
||||
MatchingMobility = models->MODLmatchingMobility;
|
||||
OneCarrier = methods->METHoneCarrier;
|
||||
|
||||
for (inst = model->NUMD2instances; inst != NULL;
|
||||
inst = inst->NUMD2nextInstance) {
|
||||
if (inst->NUMD2owner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
if (!inst->NUMD2tempGiven) {
|
||||
inst->NUMD2temp = ckt->CKTtemp;
|
||||
}
|
||||
if (!inst->NUMD2areaGiven || inst->NUMD2area <= 0.0) {
|
||||
inst->NUMD2area = 1.0;
|
||||
}
|
||||
if (!inst->NUMD2widthGiven || inst->NUMD2width <= 0.0) {
|
||||
inst->NUMD2width = 1.0;
|
||||
}
|
||||
inst->NUMD2pDevice->width =
|
||||
inst->NUMD2area * inst->NUMD2width * options->OPTNdefw;
|
||||
|
||||
/* Compute and save globals for this instance. */
|
||||
GLOBcomputeGlobals(&(inst->NUMD2globals), inst->NUMD2temp);
|
||||
|
||||
/* Calculate new sets of material parameters. */
|
||||
pM = model->NUMD2matlInfo;
|
||||
pMaterial = inst->NUMD2pDevice->pMaterials;
|
||||
for (; pM != NULL; pM = pM->next, pMaterial = pMaterial->next) {
|
||||
|
||||
/* Copy everything, then fix the incorrect pointer. */
|
||||
pNextMaterial = pMaterial->next;
|
||||
bcopy((char *) pM, (char *) pMaterial, sizeof(TWOmaterial));
|
||||
pMaterial->next = pNextMaterial;
|
||||
|
||||
/* Now do the temperature dependence. */
|
||||
MATLtempDep(pMaterial, pMaterial->tnom);
|
||||
if (outputs->OUTPmaterial) {
|
||||
printMaterialInfo(pMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign doping to the mesh. */
|
||||
TWOsetDoping(inst->NUMD2pDevice, model->NUMD2profiles,
|
||||
model->NUMD2dopTables);
|
||||
|
||||
/* Assign physical parameters to the mesh. */
|
||||
TWOsetup(inst->NUMD2pDevice);
|
||||
|
||||
/* Assign boundary condition parameters. */
|
||||
TWOsetBCparams(inst->NUMD2pDevice, model->NUMD2boundaries);
|
||||
|
||||
/* Normalize everything. */
|
||||
TWOnormalize(inst->NUMD2pDevice);
|
||||
|
||||
/* Find the device's type. */
|
||||
if (inst->NUMD2pDevice->pFirstContact->pNodes[0]->netConc < 0.0) {
|
||||
inst->NUMD2type = PN;
|
||||
if (OneCarrier) {
|
||||
methods->METHoneCarrier = P_TYPE;
|
||||
}
|
||||
} else {
|
||||
inst->NUMD2type = NP;
|
||||
if (OneCarrier) {
|
||||
methods->METHoneCarrier = N_TYPE;
|
||||
}
|
||||
}
|
||||
inst->NUMD2pDevice->pStats->totalTime[STAT_SETUP] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numd2def.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "suffix.h"
|
||||
#include "cidersupt.h"
|
||||
|
||||
int
|
||||
NUMD2trunc(inModel, ckt, timeStep)
|
||||
GENmodel *inModel;
|
||||
register CKTcircuit *ckt;
|
||||
double *timeStep;
|
||||
{
|
||||
register NUMD2model *model = (NUMD2model *) inModel;
|
||||
register NUMD2instance *inst;
|
||||
double deltaNew;
|
||||
double deltaNorm[7];
|
||||
double startTime;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
|
||||
for (; model != NULL; model = model->NUMD2nextModel) {
|
||||
OneCarrier = model->NUMD2methods->METHoneCarrier;
|
||||
model->NUMD2pInfo->order = ckt->CKTorder;
|
||||
model->NUMD2pInfo->delta = deltaNorm;
|
||||
model->NUMD2pInfo->lteCoeff = computeLTECoeff(model->NUMD2pInfo);
|
||||
for (inst = model->NUMD2instances; inst != NULL;
|
||||
inst = inst->NUMD2nextInstance) {
|
||||
if (inst->NUMD2owner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
deltaNew = TWOtrunc(inst->NUMD2pDevice, model->NUMD2pInfo,
|
||||
ckt->CKTdelta);
|
||||
*timeStep = MIN(*timeStep, deltaNew);
|
||||
inst->NUMD2pDevice->pStats->totalTime[STAT_TRAN] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Authors: 1987 Karti Mayaram, 1991 David Gates
|
||||
**********/
|
||||
|
||||
#ifndef NUMD2_H
|
||||
#define NUMD2_H "NUMD2defs.h $Revision$ on $Date$ "
|
||||
|
||||
/* data structures used to describe 2D numerical diodes */
|
||||
|
||||
/* circuit level includes */
|
||||
#include "ifsim.h"
|
||||
#include "cktdefs.h"
|
||||
#include "gendefs.h"
|
||||
|
||||
/* device level includes */
|
||||
#include "twomesh.h"
|
||||
#include "twodev.h"
|
||||
#include "profile.h"
|
||||
#include "numglobs.h"
|
||||
#include "carddefs.h"
|
||||
|
||||
/* information needed per instance */
|
||||
typedef struct sNUMD2instance {
|
||||
struct sNUMD2model *NUMD2modPtr; /* back pointer to model */
|
||||
struct sNUMD2instance *NUMD2nextInstance; /* pointer to next instance
|
||||
* of current model */
|
||||
IFuid NUMD2name; /* pointer to character string naming this
|
||||
* instance */
|
||||
int NUMD2owner; /* number of owner process */
|
||||
int NUMD2state; /* pointer to start of state vector for diode */
|
||||
|
||||
#define NUMD2voltage NUMD2state
|
||||
#define NUMD2id NUMD2state+1
|
||||
#define NUMD2conduct NUMD2state+2
|
||||
#define NUMD2numStates 3
|
||||
|
||||
int NUMD2posNode; /* number of positive node of diode */
|
||||
int NUMD2negNode; /* number of negative node of diode */
|
||||
TWOdevice *NUMD2pDevice;
|
||||
GLOBvalues NUMD2globals; /* Temp.-Dep. Global Parameters */
|
||||
int NUMD2type; /* device type pn or np */
|
||||
double NUMD2width; /* width factor for the diode */
|
||||
double NUMD2area; /* area factor for the diode */
|
||||
double NUMD2temp; /* instance temperature */
|
||||
double NUMD2c11; /* small-signal capacitance */
|
||||
double NUMD2y11r; /* small-signal admittance, real part */
|
||||
double NUMD2y11i; /* small-signal admittance, imag part */
|
||||
int NUMD2print; /* number of timesteps after which print
|
||||
* internal */
|
||||
char *NUMD2icFile; /* Name of initial condition file */
|
||||
double *NUMD2negPosPtr; /* pointer to sparse matrix at
|
||||
* (negative,positive) */
|
||||
double *NUMD2posNegPtr; /* pointer to sparse matrix at
|
||||
* (positive,negative) */
|
||||
double *NUMD2posPosPtr; /* pointer to sparse matrix at
|
||||
* (positive,positive) */
|
||||
double *NUMD2negNegPtr; /* pointer to sparse matrix at
|
||||
* (negative,negative) */
|
||||
|
||||
int NUMD2off; /* 'off' flag for diode */
|
||||
unsigned NUMD2smSigAvail:1; /* flag to indicate small-signal done */
|
||||
unsigned NUMD2widthGiven:1; /* flag to indicate width was specified */
|
||||
unsigned NUMD2areaGiven:1; /* flag to indicate area was specified */
|
||||
unsigned NUMD2icFileGiven:1; /* flag to indicate init. cond. file given */
|
||||
unsigned NUMD2tempGiven:1; /* flag to indicate temp was specified */
|
||||
unsigned NUMD2printGiven:1; /* flag to indicate if print was specified */
|
||||
} NUMD2instance;
|
||||
|
||||
|
||||
/* per model data */
|
||||
|
||||
typedef struct sNUMD2model { /* model structure for a diode */
|
||||
int NUMD2modType; /* type index of this device type */
|
||||
struct sNUMD2model *NUMD2nextModel; /* pointer to next possible model in
|
||||
* linked list */
|
||||
NUMD2instance *NUMD2instances;/* pointer to list of instances that have
|
||||
* this model */
|
||||
IFuid NUMD2modName; /* pointer to character string naming this
|
||||
* model */
|
||||
/* Everything below here is numerical-device-specific */
|
||||
MESHcard *NUMD2xMeshes; /* list of xmesh cards */
|
||||
MESHcard *NUMD2yMeshes; /* list of ymesh cards */
|
||||
DOMNcard *NUMD2domains; /* list of domain cards */
|
||||
BDRYcard *NUMD2boundaries; /* list of boundary cards */
|
||||
DOPcard *NUMD2dopings; /* list of doping cards */
|
||||
ELCTcard *NUMD2electrodes; /* list of electrode cards */
|
||||
CONTcard *NUMD2contacts; /* list of contact cards */
|
||||
MODLcard *NUMD2models; /* list of model cards */
|
||||
MATLcard *NUMD2materials; /* list of material cards */
|
||||
MOBcard *NUMD2mobility; /* list of mobility cards */
|
||||
METHcard *NUMD2methods; /* list of method cards */
|
||||
OPTNcard *NUMD2options; /* list of option cards */
|
||||
OUTPcard *NUMD2outputs; /* list of output cards */
|
||||
TWOtranInfo *NUMD2pInfo; /* transient analysis information */
|
||||
DOPprofile *NUMD2profiles; /* expanded list of doping profiles */
|
||||
DOPtable *NUMD2dopTables; /* list of tables used by profiles */
|
||||
TWOmaterial *NUMD2matlInfo; /* list of material info structures */
|
||||
} NUMD2model;
|
||||
|
||||
/* type of 2D diode */
|
||||
#define PN 1
|
||||
#define NP -1
|
||||
|
||||
/* device parameters */
|
||||
#define NUMD2_WIDTH 1
|
||||
#define NUMD2_AREA 2
|
||||
#define NUMD2_IC_FILE 3
|
||||
#define NUMD2_OFF 4
|
||||
#define NUMD2_PRINT 5
|
||||
#define NUMD2_TEMP 6
|
||||
#define NUMD2_VD 7
|
||||
#define NUMD2_ID 8
|
||||
|
||||
#define NUMD2_G11 9
|
||||
#define NUMD2_C11 10
|
||||
#define NUMD2_Y11 11
|
||||
#define NUMD2_G12 12
|
||||
#define NUMD2_C12 13
|
||||
#define NUMD2_Y12 14
|
||||
#define NUMD2_G21 15
|
||||
#define NUMD2_C21 16
|
||||
#define NUMD2_Y21 17
|
||||
#define NUMD2_G22 18
|
||||
#define NUMD2_C22 19
|
||||
#define NUMD2_Y22 20
|
||||
|
||||
/* model parameters */
|
||||
/* NOTE: all true model parameters have been moved to IFcardInfo structures */
|
||||
#define NUMD2_MOD_NUMD 101
|
||||
|
||||
/* device questions */
|
||||
|
||||
/* model questions */
|
||||
|
||||
#include "numd2ext.h"
|
||||
|
||||
#endif /* NUMD2_H */
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Karti Mayaram
|
||||
**********/
|
||||
|
||||
#ifndef NUMD2EXT_H
|
||||
#define NUMD2EXT_H
|
||||
|
||||
|
||||
extern int NUMD2acLoad(GENmodel *, CKTcircuit *);
|
||||
extern int NUMD2ask(CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *);
|
||||
extern int NUMD2delete(GENmodel *, IFuid, GENinstance **);
|
||||
extern void NUMD2destroy(GENmodel **);
|
||||
extern int NUMD2getic(GENmodel *, CKTcircuit *);
|
||||
extern int NUMD2load(GENmodel *, CKTcircuit *);
|
||||
extern int NUMD2mDelete(GENmodel **, IFuid, GENmodel *);
|
||||
extern int NUMD2mParam(int, IFvalue *, GENmodel *);
|
||||
extern int NUMD2param(int, IFvalue *, GENinstance *, IFvalue *);
|
||||
extern int NUMD2pzLoad(GENmodel *, CKTcircuit *, SPcomplex *);
|
||||
extern int NUMD2setup(SMPmatrix *, GENmodel *, CKTcircuit *, int *);
|
||||
extern int NUMD2temp(GENmodel *, CKTcircuit *);
|
||||
extern int NUMD2trunc(GENmodel *, CKTcircuit *, double *);
|
||||
|
||||
extern void NUMD2dump(GENmodel *, CKTcircuit *);
|
||||
extern void NUMD2acct(GENmodel *, CKTcircuit *, FILE *);
|
||||
|
||||
|
||||
#endif /* NUMD2EXT_H */
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <devdefs.h>
|
||||
|
||||
#include "numd2itf.h"
|
||||
#include "numd2ext.h"
|
||||
#include "numd2init.h"
|
||||
|
||||
|
||||
SPICEdev NUMD2info = {
|
||||
{
|
||||
"NUMD2",
|
||||
"2D Numerical Junction Diode model",
|
||||
|
||||
&NUMD2nSize,
|
||||
&NUMD2nSize,
|
||||
NUMD2names,
|
||||
|
||||
&NUMD2pTSize,
|
||||
NUMD2pTable,
|
||||
|
||||
&NUMD2mPTSize,
|
||||
NUMD2mPTable,
|
||||
|
||||
#ifdef XSPICE
|
||||
/*---- Fixed by SDB 5.2.2003 to enable XSPICE/tclspice integration -----*/
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
/*--------------------------- End of SDB fix -------------------------*/
|
||||
#endif
|
||||
|
||||
DEV_DEFAULT
|
||||
},
|
||||
|
||||
DEVparam : NUMD2param,
|
||||
DEVmodParam : NUMD2mParam,
|
||||
DEVload : NUMD2load,
|
||||
DEVsetup : NUMD2setup,
|
||||
DEVunsetup : NULL,
|
||||
DEVpzSetup : NUMD2setup,
|
||||
DEVtemperature: NUMD2temp,
|
||||
DEVtrunc : NUMD2trunc,
|
||||
DEVfindBranch : NULL,
|
||||
DEVacLoad : NUMD2acLoad,
|
||||
DEVaccept : NULL,
|
||||
DEVdestroy : NUMD2destroy,
|
||||
DEVmodDelete : NUMD2mDelete,
|
||||
DEVdelete : NUMD2delete,
|
||||
DEVsetic : NULL,
|
||||
DEVask : NUMD2ask,
|
||||
DEVmodAsk : NULL,
|
||||
DEVpzLoad : NUMD2pzLoad,
|
||||
DEVconvTest : NULL,
|
||||
DEVsenSetup : NULL,
|
||||
DEVsenLoad : NULL,
|
||||
DEVsenUpdate : NULL,
|
||||
DEVsenAcLoad : NULL,
|
||||
DEVsenPrint : NULL,
|
||||
DEVsenTrunc : NULL,
|
||||
DEVdisto : NULL,
|
||||
DEVnoise : NULL,
|
||||
DEVdump : NUMD2dump,
|
||||
DEVacct : NUMD2acct,
|
||||
|
||||
DEVinstSize : &NUMD2iSize,
|
||||
DEVmodSize : &NUMD2mSize
|
||||
|
||||
};
|
||||
|
||||
|
||||
SPICEdev *
|
||||
get_numd2_info(void)
|
||||
{
|
||||
return &NUMD2info;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef _NUMD2INIT_H
|
||||
#define _NUMD2INIT_H
|
||||
|
||||
extern IFparm NUMD2pTable[ ];
|
||||
extern IFparm NUMD2mPTable[ ];
|
||||
extern char *NUMD2names[ ];
|
||||
extern int NUMD2pTSize;
|
||||
extern int NUMD2mPTSize;
|
||||
extern int NUMD2nSize;
|
||||
extern int NUMD2iSize;
|
||||
extern int NUMD2mSize;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
**********/
|
||||
|
||||
#ifndef DEV_NUMD2
|
||||
#define DEV_NUMD2
|
||||
|
||||
extern SPICEdev *get_numd2_info(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
noinst_LIBRARIES = libnumos.a
|
||||
|
||||
libnumos_a_SOURCES = \
|
||||
numm.c \
|
||||
nummacld.c \
|
||||
nummask.c \
|
||||
numosdef.h \
|
||||
nummdel.c \
|
||||
nummdest.c \
|
||||
nummdump.c \
|
||||
numosext.h \
|
||||
numosinit.c \
|
||||
numosinit.h \
|
||||
numositf.h \
|
||||
nummload.c \
|
||||
nummmdel.c \
|
||||
nummmpar.c \
|
||||
nummparm.c \
|
||||
nummpzld.c \
|
||||
nummset.c \
|
||||
nummtemp.c \
|
||||
nummtrun.c
|
||||
|
||||
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/src/include
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "devdefs.h"
|
||||
#include "numosdef.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/*
|
||||
* This file defines the 2d Numerical MOSFET data structures that are
|
||||
* available to the next level(s) up the calling hierarchy
|
||||
*/
|
||||
|
||||
IFparm NUMOSpTable[] = { /* parameters */
|
||||
IP("off", NUMOS_OFF, IF_FLAG, "Device initially off"),
|
||||
IP("ic.file", NUMOS_IC_FILE, IF_STRING, "Initial condition file"),
|
||||
IOP("area", NUMOS_AREA, IF_REAL, "Area factor"),
|
||||
IOP("w", NUMOS_WIDTH, IF_REAL, "Width factor"),
|
||||
IOP("l", NUMOS_LENGTH, IF_REAL, "Length factor"),
|
||||
IP("save", NUMOS_PRINT, IF_REAL, "Save solutions"),
|
||||
IP("print", NUMOS_PRINT, IF_REAL, "Print solutions"),
|
||||
OP("g11", NUMOS_G11, IF_REAL, "Conductance"),
|
||||
OP("c11", NUMOS_C11, IF_REAL, "Capacitance"),
|
||||
OP("y11", NUMOS_Y11, IF_COMPLEX, "Admittance"),
|
||||
OP("g12", NUMOS_G12, IF_REAL, "Conductance"),
|
||||
OP("c12", NUMOS_C12, IF_REAL, "Capacitance"),
|
||||
OP("y12", NUMOS_Y12, IF_COMPLEX, "Admittance"),
|
||||
OP("g13", NUMOS_G13, IF_REAL, "Conductance"),
|
||||
OP("c13", NUMOS_C13, IF_REAL, "Capacitance"),
|
||||
OP("y13", NUMOS_Y13, IF_COMPLEX, "Admittance"),
|
||||
OPU("g14", NUMOS_G14, IF_REAL, "Conductance"),
|
||||
OPU("c14", NUMOS_C14, IF_REAL, "Capacitance"),
|
||||
OPU("y14", NUMOS_Y14, IF_COMPLEX, "Admittance"),
|
||||
OP("g21", NUMOS_G21, IF_REAL, "Conductance"),
|
||||
OP("c21", NUMOS_C21, IF_REAL, "Capacitance"),
|
||||
OP("y21", NUMOS_Y21, IF_COMPLEX, "Admittance"),
|
||||
OP("g22", NUMOS_G22, IF_REAL, "Conductance"),
|
||||
OP("c22", NUMOS_C22, IF_REAL, "Capacitance"),
|
||||
OP("y22", NUMOS_Y22, IF_COMPLEX, "Admittance"),
|
||||
OP("g23", NUMOS_G23, IF_REAL, "Conductance"),
|
||||
OP("c23", NUMOS_C23, IF_REAL, "Capacitance"),
|
||||
OP("y23", NUMOS_Y23, IF_COMPLEX, "Admittance"),
|
||||
OPU("g24", NUMOS_G24, IF_REAL, "Conductance"),
|
||||
OPU("c24", NUMOS_C24, IF_REAL, "Capacitance"),
|
||||
OPU("y24", NUMOS_Y24, IF_COMPLEX, "Admittance"),
|
||||
OP("g31", NUMOS_G31, IF_REAL, "Conductance"),
|
||||
OP("c31", NUMOS_C31, IF_REAL, "Capacitance"),
|
||||
OP("y31", NUMOS_Y31, IF_COMPLEX, "Admittance"),
|
||||
OP("g32", NUMOS_G32, IF_REAL, "Conductance"),
|
||||
OP("c32", NUMOS_C32, IF_REAL, "Capacitance"),
|
||||
OP("y32", NUMOS_Y32, IF_COMPLEX, "Admittance"),
|
||||
OP("g33", NUMOS_G33, IF_REAL, "Conductance"),
|
||||
OP("c33", NUMOS_C33, IF_REAL, "Capacitance"),
|
||||
OP("y33", NUMOS_Y33, IF_COMPLEX, "Admittance"),
|
||||
OPU("g34", NUMOS_G34, IF_REAL, "Conductance"),
|
||||
OPU("c34", NUMOS_C34, IF_REAL, "Capacitance"),
|
||||
OPU("y34", NUMOS_Y34, IF_COMPLEX, "Admittance"),
|
||||
OPU("g41", NUMOS_G41, IF_REAL, "Conductance"),
|
||||
OPU("c41", NUMOS_C41, IF_REAL, "Capacitance"),
|
||||
OPU("y41", NUMOS_Y41, IF_COMPLEX, "Admittance"),
|
||||
OPU("g42", NUMOS_G42, IF_REAL, "Conductance"),
|
||||
OPU("c42", NUMOS_C42, IF_REAL, "Capacitance"),
|
||||
OPU("y42", NUMOS_Y42, IF_COMPLEX, "Admittance"),
|
||||
OPU("g43", NUMOS_G43, IF_REAL, "Conductance"),
|
||||
OPU("c43", NUMOS_C43, IF_REAL, "Capacitance"),
|
||||
OPU("y43", NUMOS_Y43, IF_COMPLEX, "Admittance"),
|
||||
OPU("g44", NUMOS_G44, IF_REAL, "Conductance"),
|
||||
OPU("c44", NUMOS_C44, IF_REAL, "Capacitance"),
|
||||
OPU("y44", NUMOS_Y44, IF_COMPLEX, "Admittance"),
|
||||
IOP("temp", NUMOS_TEMP, IF_REAL, "Instance temperature")
|
||||
};
|
||||
|
||||
IFparm NUMOSmPTable[] = { /* model parameters */
|
||||
/* numerical-device models no longer have parameters */
|
||||
/* one is left behind to keep the table from being empty */
|
||||
IP("numos", NUMOS_MOD_NUMOS, IF_FLAG, "Numerical MOSFET"),
|
||||
};
|
||||
|
||||
char *NUMOSnames[] = {
|
||||
"Drain",
|
||||
"Gate",
|
||||
"Source",
|
||||
"Substrate"
|
||||
};
|
||||
|
||||
int NUMOSnSize = NUMELEMS(NUMOSnames);
|
||||
int NUMOSpTSize = NUMELEMS(NUMOSpTable);
|
||||
int NUMOSmPTSize = NUMELEMS(NUMOSmPTable);
|
||||
int NUMOSiSize = sizeof(NUMOSinstance);
|
||||
int NUMOSmSize = sizeof(NUMOSmodel);
|
||||
|
|
@ -0,0 +1,158 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* Function to load the COMPLEX circuit matrix using the small signal
|
||||
* parameters saved during a previous DC operating point analysis.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numosdef.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
#include "complex.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
|
||||
/* External Declarations */
|
||||
extern int TWOacDebug;
|
||||
|
||||
int
|
||||
NUMOSacLoad(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
{
|
||||
register NUMOSmodel *model = (NUMOSmodel *) inModel;
|
||||
register NUMOSinstance *inst;
|
||||
struct mosAdmittances yAc;
|
||||
double startTime;
|
||||
|
||||
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;
|
||||
AcAnalysisMethod = model->NUMOSmethods->METHacAnalysisMethod;
|
||||
MobDeriv = model->NUMOSmethods->METHmobDeriv;
|
||||
TWOacDebug = model->NUMOSoutputs->OUTPacDebug;
|
||||
|
||||
for (inst = model->NUMOSinstances; inst != NULL;
|
||||
inst = inst->NUMOSnextInstance) {
|
||||
if (inst->NUMOSowner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NUMOSglobals));
|
||||
|
||||
model->NUMOSmethods->METHacAnalysisMethod =
|
||||
NUMOSadmittance(inst->NUMOSpDevice,
|
||||
ckt->CKTomega, &yAc);
|
||||
|
||||
*(inst->NUMOSdrainDrainPtr) += yAc.yIdVdb.real;
|
||||
*(inst->NUMOSdrainDrainPtr + 1) += yAc.yIdVdb.imag;
|
||||
*(inst->NUMOSdrainSourcePtr) += yAc.yIdVsb.real;
|
||||
*(inst->NUMOSdrainSourcePtr + 1) += yAc.yIdVsb.imag;
|
||||
*(inst->NUMOSdrainGatePtr) += yAc.yIdVgb.real;
|
||||
*(inst->NUMOSdrainGatePtr + 1) += yAc.yIdVgb.imag;
|
||||
*(inst->NUMOSdrainBulkPtr) -=
|
||||
yAc.yIdVdb.real + yAc.yIdVsb.real + yAc.yIdVgb.real;
|
||||
*(inst->NUMOSdrainBulkPtr + 1) -=
|
||||
yAc.yIdVdb.imag + yAc.yIdVsb.imag + yAc.yIdVgb.imag;
|
||||
|
||||
*(inst->NUMOSsourceDrainPtr) += yAc.yIsVdb.real;
|
||||
*(inst->NUMOSsourceDrainPtr + 1) += yAc.yIsVdb.imag;
|
||||
*(inst->NUMOSsourceSourcePtr) += yAc.yIsVsb.real;
|
||||
*(inst->NUMOSsourceSourcePtr + 1) += yAc.yIsVsb.imag;
|
||||
*(inst->NUMOSsourceGatePtr) += yAc.yIsVgb.real;
|
||||
*(inst->NUMOSsourceGatePtr + 1) += yAc.yIsVgb.imag;
|
||||
*(inst->NUMOSsourceBulkPtr) -=
|
||||
yAc.yIsVdb.real + yAc.yIsVsb.real + yAc.yIsVgb.real;
|
||||
*(inst->NUMOSsourceBulkPtr + 1) -=
|
||||
yAc.yIsVdb.imag + yAc.yIsVsb.imag + yAc.yIsVgb.imag;
|
||||
|
||||
*(inst->NUMOSgateDrainPtr) += yAc.yIgVdb.real;
|
||||
*(inst->NUMOSgateDrainPtr + 1) += yAc.yIgVdb.imag;
|
||||
*(inst->NUMOSgateSourcePtr) += yAc.yIgVsb.real;
|
||||
*(inst->NUMOSgateSourcePtr + 1) += yAc.yIgVsb.imag;
|
||||
*(inst->NUMOSgateGatePtr) += yAc.yIgVgb.real;
|
||||
*(inst->NUMOSgateGatePtr + 1) += yAc.yIgVgb.imag;
|
||||
*(inst->NUMOSgateBulkPtr) -=
|
||||
yAc.yIgVdb.real + yAc.yIgVsb.real + yAc.yIgVgb.real;
|
||||
*(inst->NUMOSgateBulkPtr + 1) -=
|
||||
yAc.yIgVdb.imag + yAc.yIgVsb.imag + yAc.yIgVgb.imag;
|
||||
|
||||
*(inst->NUMOSbulkDrainPtr) -=
|
||||
yAc.yIdVdb.real + yAc.yIsVdb.real + yAc.yIgVdb.real;
|
||||
*(inst->NUMOSbulkDrainPtr + 1) -=
|
||||
yAc.yIdVdb.imag + yAc.yIsVdb.imag + yAc.yIgVdb.imag;
|
||||
*(inst->NUMOSbulkSourcePtr) -=
|
||||
yAc.yIdVsb.real + yAc.yIsVsb.real + yAc.yIgVsb.real;
|
||||
*(inst->NUMOSbulkSourcePtr + 1) -=
|
||||
yAc.yIdVsb.imag + yAc.yIsVsb.imag + yAc.yIgVsb.imag;
|
||||
*(inst->NUMOSbulkGatePtr) -=
|
||||
yAc.yIdVgb.real + yAc.yIsVgb.real + yAc.yIgVgb.real;
|
||||
*(inst->NUMOSbulkGatePtr + 1) -=
|
||||
yAc.yIdVgb.imag + yAc.yIsVgb.imag + yAc.yIgVgb.imag;
|
||||
*(inst->NUMOSbulkBulkPtr) += yAc.yIdVdb.real + yAc.yIdVsb.real +
|
||||
yAc.yIdVgb.real + yAc.yIsVdb.real +
|
||||
yAc.yIsVsb.real + yAc.yIsVgb.real +
|
||||
yAc.yIgVdb.real + yAc.yIgVsb.real +
|
||||
yAc.yIgVgb.real;
|
||||
*(inst->NUMOSbulkBulkPtr + 1) -= yAc.yIdVdb.imag + yAc.yIdVsb.imag +
|
||||
yAc.yIdVgb.imag + yAc.yIsVdb.imag +
|
||||
yAc.yIsVsb.imag + yAc.yIsVgb.imag +
|
||||
yAc.yIgVdb.imag + yAc.yIgVsb.imag +
|
||||
yAc.yIgVgb.imag;
|
||||
if (ckt->CKTomega != 0.0) {
|
||||
inst->NUMOSc11 = yAc.yIdVdb.imag / ckt->CKTomega;
|
||||
inst->NUMOSc12 = yAc.yIdVgb.imag / ckt->CKTomega;
|
||||
inst->NUMOSc13 = yAc.yIdVsb.imag / ckt->CKTomega;
|
||||
inst->NUMOSc21 = yAc.yIgVdb.imag / ckt->CKTomega;
|
||||
inst->NUMOSc22 = yAc.yIgVgb.imag / ckt->CKTomega;
|
||||
inst->NUMOSc23 = yAc.yIgVsb.imag / ckt->CKTomega;
|
||||
inst->NUMOSc31 = yAc.yIsVdb.imag / ckt->CKTomega;
|
||||
inst->NUMOSc32 = yAc.yIsVgb.imag / ckt->CKTomega;
|
||||
inst->NUMOSc33 = yAc.yIsVsb.imag / ckt->CKTomega;
|
||||
} else {
|
||||
inst->NUMOSc11 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NUMOSc12 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NUMOSc13 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NUMOSc21 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NUMOSc22 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NUMOSc23 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NUMOSc31 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NUMOSc32 = 0.0; /* XXX What else can be done?! */
|
||||
inst->NUMOSc33 = 0.0; /* XXX What else can be done?! */
|
||||
}
|
||||
inst->NUMOSy11r = yAc.yIdVdb.real;
|
||||
inst->NUMOSy11i = yAc.yIdVdb.imag;
|
||||
inst->NUMOSy12r = yAc.yIdVgb.real;
|
||||
inst->NUMOSy12i = yAc.yIdVgb.imag;
|
||||
inst->NUMOSy13r = yAc.yIdVsb.real;
|
||||
inst->NUMOSy13i = yAc.yIdVsb.imag;
|
||||
inst->NUMOSy21r = yAc.yIgVdb.real;
|
||||
inst->NUMOSy21i = yAc.yIgVdb.imag;
|
||||
inst->NUMOSy22r = yAc.yIgVgb.real;
|
||||
inst->NUMOSy22i = yAc.yIgVgb.imag;
|
||||
inst->NUMOSy23r = yAc.yIgVsb.real;
|
||||
inst->NUMOSy23i = yAc.yIgVsb.imag;
|
||||
inst->NUMOSy31r = yAc.yIsVdb.real;
|
||||
inst->NUMOSy31i = yAc.yIsVdb.imag;
|
||||
inst->NUMOSy32r = yAc.yIsVgb.real;
|
||||
inst->NUMOSy32i = yAc.yIsVgb.imag;
|
||||
inst->NUMOSy33r = yAc.yIsVsb.real;
|
||||
inst->NUMOSy33i = yAc.yIsVsb.imag;
|
||||
inst->NUMOSsmSigAvail = TRUE;
|
||||
inst->NUMOSpDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,359 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Thomas L. Quarles
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "cktdefs.h"
|
||||
#include "devdefs.h"
|
||||
#include "numosdef.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* Externals Declarations */
|
||||
extern int NUMOSinitSmSig(NUMOSinstance *);
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
NUMOSask(ckt, inInst, which, value, select)
|
||||
CKTcircuit *ckt;
|
||||
GENinstance *inInst;
|
||||
int which;
|
||||
IFvalue *value;
|
||||
IFvalue *select;
|
||||
{
|
||||
NUMOSinstance *inst = (NUMOSinstance *) inInst;
|
||||
switch (which) {
|
||||
case NUMOS_AREA:
|
||||
value->rValue = inst->NUMOSarea;
|
||||
return (OK);
|
||||
case NUMOS_WIDTH:
|
||||
value->rValue = inst->NUMOSwidth;
|
||||
return (OK);
|
||||
case NUMOS_LENGTH:
|
||||
value->rValue = inst->NUMOSlength;
|
||||
return (OK);
|
||||
case NUMOS_TEMP:
|
||||
value->rValue = inst->NUMOStemp - CONSTCtoK;
|
||||
return (OK);
|
||||
case NUMOS_G11:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIdDVdb);
|
||||
return (OK);
|
||||
case NUMOS_G12:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIdDVgb);
|
||||
return (OK);
|
||||
case NUMOS_G13:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIdDVsb);
|
||||
return (OK);
|
||||
case NUMOS_G14:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NUMOSdIdDVdb)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSdIdDVgb)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSdIdDVsb);
|
||||
return (OK);
|
||||
case NUMOS_G21:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIgDVdb);
|
||||
return (OK);
|
||||
case NUMOS_G22:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIgDVgb);
|
||||
return (OK);
|
||||
case NUMOS_G23:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIgDVsb);
|
||||
return (OK);
|
||||
case NUMOS_G24:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NUMOSdIgDVdb)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSdIgDVgb)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSdIgDVsb);
|
||||
return (OK);
|
||||
case NUMOS_G31:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIsDVdb);
|
||||
return (OK);
|
||||
case NUMOS_G32:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIsDVgb);
|
||||
return (OK);
|
||||
case NUMOS_G33:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIsDVsb);
|
||||
return (OK);
|
||||
case NUMOS_G34:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NUMOSdIsDVdb)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSdIsDVgb)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSdIsDVsb);
|
||||
return (OK);
|
||||
case NUMOS_G41:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NUMOSdIdDVdb)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSdIgDVdb)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSdIsDVdb);
|
||||
return (OK);
|
||||
case NUMOS_G42:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NUMOSdIdDVgb)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSdIgDVgb)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSdIsDVgb);
|
||||
return (OK);
|
||||
case NUMOS_G43:
|
||||
value->rValue = -*(ckt->CKTstate0 + inst->NUMOSdIdDVsb)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSdIgDVsb)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSdIsDVsb);
|
||||
return (OK);
|
||||
case NUMOS_G44:
|
||||
value->rValue = *(ckt->CKTstate0 + inst->NUMOSdIdDVdb)
|
||||
+ *(ckt->CKTstate0 + inst->NUMOSdIgDVdb)
|
||||
+ *(ckt->CKTstate0 + inst->NUMOSdIsDVdb)
|
||||
+ *(ckt->CKTstate0 + inst->NUMOSdIdDVgb)
|
||||
+ *(ckt->CKTstate0 + inst->NUMOSdIgDVgb)
|
||||
+ *(ckt->CKTstate0 + inst->NUMOSdIsDVgb)
|
||||
+ *(ckt->CKTstate0 + inst->NUMOSdIdDVsb)
|
||||
+ *(ckt->CKTstate0 + inst->NUMOSdIgDVsb)
|
||||
+ *(ckt->CKTstate0 + inst->NUMOSdIsDVsb);
|
||||
return (OK);
|
||||
case NUMOS_C11:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMOSc11;
|
||||
return (OK);
|
||||
case NUMOS_C12:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMOSc12;
|
||||
return (OK);
|
||||
case NUMOS_C13:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMOSc13;
|
||||
return (OK);
|
||||
case NUMOS_C14:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NUMOSc11 - inst->NUMOSc12 - inst->NUMOSc13;
|
||||
return (OK);
|
||||
case NUMOS_C21:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMOSc21;
|
||||
return (OK);
|
||||
case NUMOS_C22:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMOSc22;
|
||||
return (OK);
|
||||
case NUMOS_C23:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMOSc23;
|
||||
return (OK);
|
||||
case NUMOS_C24:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NUMOSc21 - inst->NUMOSc22 - inst->NUMOSc23;
|
||||
return (OK);
|
||||
case NUMOS_C31:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMOSc31;
|
||||
return (OK);
|
||||
case NUMOS_C32:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMOSc32;
|
||||
return (OK);
|
||||
case NUMOS_C33:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMOSc33;
|
||||
return (OK);
|
||||
case NUMOS_C34:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NUMOSc31 - inst->NUMOSc32 - inst->NUMOSc33;
|
||||
return (OK);
|
||||
case NUMOS_C41:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NUMOSc11 - inst->NUMOSc21 - inst->NUMOSc31;
|
||||
return (OK);
|
||||
case NUMOS_C42:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NUMOSc12 - inst->NUMOSc22 - inst->NUMOSc32;
|
||||
return (OK);
|
||||
case NUMOS_C43:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = -inst->NUMOSc13 - inst->NUMOSc23 - inst->NUMOSc33;
|
||||
return (OK);
|
||||
case NUMOS_C44:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->rValue = inst->NUMOSc11 + inst->NUMOSc12 + inst->NUMOSc13
|
||||
+ inst->NUMOSc21 + inst->NUMOSc22 + inst->NUMOSc23
|
||||
+ inst->NUMOSc31 + inst->NUMOSc32 + inst->NUMOSc33;
|
||||
return (OK);
|
||||
case NUMOS_Y11:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMOSy11r;
|
||||
value->cValue.imag = inst->NUMOSy11i;
|
||||
return (OK);
|
||||
case NUMOS_Y12:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMOSy12r;
|
||||
value->cValue.imag = inst->NUMOSy12i;
|
||||
return (OK);
|
||||
case NUMOS_Y13:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMOSy13r;
|
||||
value->cValue.imag = inst->NUMOSy13i;
|
||||
return (OK);
|
||||
case NUMOS_Y14:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NUMOSy11r - inst->NUMOSy11r - inst->NUMOSy11r;
|
||||
value->cValue.imag = -inst->NUMOSy11i - inst->NUMOSy11i - inst->NUMOSy11i;
|
||||
return (OK);
|
||||
case NUMOS_Y21:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMOSy21r;
|
||||
value->cValue.imag = inst->NUMOSy21i;
|
||||
return (OK);
|
||||
case NUMOS_Y22:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMOSy22r;
|
||||
value->cValue.imag = inst->NUMOSy22i;
|
||||
return (OK);
|
||||
case NUMOS_Y23:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMOSy23r;
|
||||
value->cValue.imag = inst->NUMOSy23i;
|
||||
return (OK);
|
||||
case NUMOS_Y24:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NUMOSy21r - inst->NUMOSy22r - inst->NUMOSy23r;
|
||||
value->cValue.imag = -inst->NUMOSy21i - inst->NUMOSy22i - inst->NUMOSy23i;
|
||||
return (OK);
|
||||
case NUMOS_Y31:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMOSy31r;
|
||||
value->cValue.imag = inst->NUMOSy31i;
|
||||
return (OK);
|
||||
case NUMOS_Y32:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMOSy32r;
|
||||
value->cValue.imag = inst->NUMOSy32i;
|
||||
return (OK);
|
||||
case NUMOS_Y33:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMOSy33r;
|
||||
value->cValue.imag = inst->NUMOSy33i;
|
||||
return (OK);
|
||||
case NUMOS_Y34:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NUMOSy31r - inst->NUMOSy32r - inst->NUMOSy33r;
|
||||
value->cValue.imag = -inst->NUMOSy31i - inst->NUMOSy32i - inst->NUMOSy33i;
|
||||
return (OK);
|
||||
case NUMOS_Y41:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NUMOSy11r - inst->NUMOSy21r - inst->NUMOSy31r;
|
||||
value->cValue.imag = -inst->NUMOSy11i - inst->NUMOSy21i - inst->NUMOSy31i;
|
||||
return (OK);
|
||||
case NUMOS_Y42:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NUMOSy12r - inst->NUMOSy22r - inst->NUMOSy32r;
|
||||
value->cValue.imag = -inst->NUMOSy12i - inst->NUMOSy22i - inst->NUMOSy32i;
|
||||
return (OK);
|
||||
case NUMOS_Y43:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = -inst->NUMOSy13r - inst->NUMOSy23r - inst->NUMOSy33r;
|
||||
value->cValue.imag = -inst->NUMOSy13i - inst->NUMOSy23i - inst->NUMOSy33i;
|
||||
return (OK);
|
||||
case NUMOS_Y44:
|
||||
if (!inst->NUMOSsmSigAvail
|
||||
&& ckt->CKTcurrentAnalysis != DOING_TRAN) {
|
||||
NUMOSinitSmSig(inst);
|
||||
}
|
||||
value->cValue.real = inst->NUMOSy11r + inst->NUMOSy21r + inst->NUMOSy31r
|
||||
+ inst->NUMOSy12r + inst->NUMOSy22r + inst->NUMOSy32r
|
||||
+ inst->NUMOSy13r + inst->NUMOSy23r + inst->NUMOSy33r;
|
||||
value->cValue.imag = inst->NUMOSy11i + inst->NUMOSy21i + inst->NUMOSy31i
|
||||
+ inst->NUMOSy12i + inst->NUMOSy22i + inst->NUMOSy32i
|
||||
+ inst->NUMOSy13i + inst->NUMOSy23i + inst->NUMOSy33i;
|
||||
return (OK);
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine deletes a NUMOS instance from the circuit and frees the
|
||||
* storage it was using.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "numosdef.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NUMOSdelete(inModel, name, kill)
|
||||
GENmodel *inModel;
|
||||
IFuid name;
|
||||
GENinstance **kill;
|
||||
|
||||
{
|
||||
|
||||
NUMOSmodel *model = (NUMOSmodel *) inModel;
|
||||
NUMOSinstance **fast = (NUMOSinstance **) kill;
|
||||
NUMOSinstance **prev = NULL;
|
||||
NUMOSinstance *inst;
|
||||
|
||||
for (; model; model = model->NUMOSnextModel) {
|
||||
prev = &(model->NUMOSinstances);
|
||||
for (inst = *prev; inst; inst = *prev) {
|
||||
if (inst->NUMOSname == name || (fast && inst == *fast)) {
|
||||
*prev = inst->NUMOSnextInstance;
|
||||
FREE(inst);
|
||||
return (OK);
|
||||
}
|
||||
prev = &(inst->NUMOSnextInstance);
|
||||
}
|
||||
}
|
||||
return (E_NODEV);
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine deletes all NUMOSs from the circuit and frees all storage
|
||||
* they were using. The current implementation has memory leaks.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "numosdef.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "suffix.h"
|
||||
|
||||
void
|
||||
NUMOSdestroy(inModel)
|
||||
GENmodel **inModel;
|
||||
|
||||
{
|
||||
|
||||
NUMOSmodel **model = (NUMOSmodel **) inModel;
|
||||
NUMOSmodel *mod, *nextMod;
|
||||
NUMOSinstance *inst, *nextInst;
|
||||
|
||||
for (mod = *model; mod;) {
|
||||
for (inst = mod->NUMOSinstances; inst;) {
|
||||
TWOdestroy(inst->NUMOSpDevice);
|
||||
nextInst = inst->NUMOSnextInstance;
|
||||
FREE(inst);
|
||||
inst = nextInst;
|
||||
}
|
||||
nextMod = mod->NUMOSnextModel;
|
||||
FREE(mod);
|
||||
mod = nextMod;
|
||||
}
|
||||
*model = NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
/**********
|
||||
Copyright 1992 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This is a simple routine to dump the internal device states. It produces
|
||||
* states for .OP, .DC, & .TRAN simulations.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numosdef.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
|
||||
/* Forward Declarations */
|
||||
static void NUMOSputHeader(FILE *, CKTcircuit *, NUMOSinstance *);
|
||||
|
||||
/* State Counter */
|
||||
static int state_numOP = 0;
|
||||
static int state_numDC = 0;
|
||||
static int state_numTR = 0;
|
||||
|
||||
void
|
||||
NUMOSdump(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
{
|
||||
register NUMOSmodel *model = (NUMOSmodel *) inModel;
|
||||
register NUMOSinstance *inst;
|
||||
OUTPcard *output;
|
||||
FILE *fpState;
|
||||
char fileName[BSIZE_SP];
|
||||
char description[BSIZE_SP];
|
||||
char *prefix;
|
||||
int *state_num;
|
||||
int anyOutput = 0;
|
||||
|
||||
if (ckt->CKTmode & MODEDCOP) {
|
||||
prefix = "OP";
|
||||
state_num = &state_numOP;
|
||||
sprintf(description, "...");
|
||||
} else if (ckt->CKTmode & MODEDCTRANCURVE) {
|
||||
prefix = "DC";
|
||||
state_num = &state_numDC;
|
||||
sprintf(description, "sweep = % e", ckt->CKTtime);
|
||||
} else if (ckt->CKTmode & MODETRAN) {
|
||||
prefix = "TR";
|
||||
state_num = &state_numTR;
|
||||
sprintf(description, "time = % e", ckt->CKTtime);
|
||||
} else {
|
||||
/* Not a recognized CKT mode. */
|
||||
return;
|
||||
}
|
||||
|
||||
for (; model != NULL; model = model->NUMOSnextModel) {
|
||||
output = model->NUMOSoutputs;
|
||||
for (inst = model->NUMOSinstances; inst != NULL;
|
||||
inst = inst->NUMOSnextInstance) {
|
||||
if (inst->NUMOSowner != ARCHme) continue;
|
||||
|
||||
if (inst->NUMOSprintGiven) {
|
||||
if ((ckt->CKTmode & MODETRAN) &&
|
||||
((ckt->CKTstat->STATaccepted - 1) % inst->NUMOSprint != 0)) {
|
||||
continue;
|
||||
}
|
||||
anyOutput = 1;
|
||||
sprintf(fileName, "%s%s.%d.%s", output->OUTProotFile, prefix,
|
||||
*state_num, inst->NUMOSname);
|
||||
if (!(fpState = fopen(fileName, "w"))) {
|
||||
perror(fileName);
|
||||
} else {
|
||||
NUMOSputHeader(fpState, ckt, inst);
|
||||
TWOprnSolution(fpState, inst->NUMOSpDevice,
|
||||
model->NUMOSoutputs);
|
||||
fclose(fpState);
|
||||
LOGmakeEntry(fileName, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (anyOutput) {
|
||||
(*state_num)++;
|
||||
}
|
||||
}
|
||||
|
||||
#define NUMOSnumOutputs 10
|
||||
|
||||
static
|
||||
void
|
||||
NUMOSputHeader(file, ckt, inst)
|
||||
FILE *file;
|
||||
CKTcircuit *ckt;
|
||||
NUMOSinstance *inst;
|
||||
{
|
||||
char *reference;
|
||||
double refVal = 0.0;
|
||||
int numVars = NUMOSnumOutputs;
|
||||
|
||||
if (ckt->CKTmode & MODEDCOP) {
|
||||
reference = NULL;
|
||||
} else if (ckt->CKTmode & MODEDCTRANCURVE) {
|
||||
reference = "sweep";
|
||||
refVal = ckt->CKTtime;
|
||||
numVars++;
|
||||
} else if (ckt->CKTmode & MODETRAN) {
|
||||
reference = "time";
|
||||
refVal = ckt->CKTtime;
|
||||
numVars++;
|
||||
} else {
|
||||
reference = NULL;
|
||||
}
|
||||
fprintf(file, "Title: Device %s external state\n", inst->NUMOSname);
|
||||
fprintf(file, "Plotname: Device Operating Point\n");
|
||||
fprintf(file, "Command: deftype v conductance S\n");
|
||||
fprintf(file, "Flags: real\n");
|
||||
fprintf(file, "No. Variables: %d\n", numVars);
|
||||
fprintf(file, "No. Points: 1\n");
|
||||
numVars = 0;
|
||||
fprintf(file, "Variables:\n");
|
||||
if (reference) {
|
||||
fprintf(file, "\t%d %s unknown\n", numVars++, reference);
|
||||
}
|
||||
fprintf(file, "\t%d v14 voltage\n", numVars++);
|
||||
fprintf(file, "\t%d v24 voltage\n", numVars++);
|
||||
fprintf(file, "\t%d v34 voltage\n", numVars++);
|
||||
fprintf(file, "\t%d i1 current\n", numVars++);
|
||||
fprintf(file, "\t%d i2 current\n", numVars++);
|
||||
fprintf(file, "\t%d i3 current\n", numVars++);
|
||||
fprintf(file, "\t%d i4 current\n", numVars++);
|
||||
fprintf(file, "\t%d g11 conductance\n", numVars++);
|
||||
fprintf(file, "\t%d g12 conductance\n", numVars++);
|
||||
fprintf(file, "\t%d g13 conductance\n", numVars++);
|
||||
fprintf(file, "Values:\n0");
|
||||
if (reference) {
|
||||
fprintf(file, "\t% e\n", refVal);
|
||||
}
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSvdb));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSvgb));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSvsb));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSid));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSig));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSis));
|
||||
fprintf(file, "\t% e\n", -*(ckt->CKTstate0 + inst->NUMOSid)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSig)
|
||||
- *(ckt->CKTstate0 + inst->NUMOSis));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSdIdDVdb));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSdIdDVgb));
|
||||
fprintf(file, "\t% e\n", *(ckt->CKTstate0 + inst->NUMOSdIdDVsb));
|
||||
}
|
||||
|
||||
void
|
||||
NUMOSacct(inModel, ckt, file)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
FILE *file;
|
||||
{
|
||||
register NUMOSmodel *model = (NUMOSmodel *) inModel;
|
||||
register NUMOSinstance *inst;
|
||||
OUTPcard *output;
|
||||
|
||||
for (; model != NULL; model = model->NUMOSnextModel) {
|
||||
output = model->NUMOSoutputs;
|
||||
for (inst = model->NUMOSinstances; inst != NULL;
|
||||
inst = inst->NUMOSnextInstance) {
|
||||
if (inst->NUMOSowner != ARCHme) continue;
|
||||
|
||||
if (output->OUTPstats) {
|
||||
TWOmemStats(file, inst->NUMOSpDevice);
|
||||
TWOcpuStats(file, inst->NUMOSpDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,639 @@
|
|||
/**********
|
||||
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);
|
||||
|
||||
int
|
||||
NUMOSload(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;
|
||||
}
|
||||
#endif /* NOBYPASS */
|
||||
/*
|
||||
* limit nonlinear branch voltages
|
||||
*/
|
||||
icheck1 = 1;
|
||||
if (deviceType == OPTN_BIPOLAR) {
|
||||
double vbe, vbe0;
|
||||
double vce, vce0;
|
||||
|
||||
vdb = -inst->NUMOStype * limitJunctionVoltage(-inst->NUMOStype * vdb,
|
||||
-inst->NUMOStype * *(ckt->CKTstate0 + inst->NUMOSvdb), &icheck);
|
||||
vce = vdb - vsb;
|
||||
vce0 = *(ckt->CKTstate0 + inst->NUMOSvdb) -
|
||||
*(ckt->CKTstate0 + inst->NUMOSvsb);
|
||||
vce = inst->NUMOStype * limitVce(inst->NUMOStype * vce,
|
||||
inst->NUMOStype * vce0, &icheck1);
|
||||
if (icheck1 == 1)
|
||||
icheck = 1;
|
||||
vsb = vdb - vce;
|
||||
vbe = vgb - vsb;
|
||||
vbe0 = *(ckt->CKTstate0 + inst->NUMOSvgb) -
|
||||
*(ckt->CKTstate0 + inst->NUMOSvsb);
|
||||
vbe = inst->NUMOStype * limitVbe(inst->NUMOStype * vbe,
|
||||
inst->NUMOStype * vbe0, &icheck1);
|
||||
if (icheck1 == 1)
|
||||
icheck = 1;
|
||||
vgb = vbe + vsb;
|
||||
} else {
|
||||
vdb = -inst->NUMOStype * limitJunctionVoltage(-inst->NUMOStype * vdb,
|
||||
-inst->NUMOStype * *(ckt->CKTstate0 + inst->NUMOSvdb), &icheck);
|
||||
vsb = -inst->NUMOStype * limitJunctionVoltage(-inst->NUMOStype * vsb,
|
||||
-inst->NUMOStype * *(ckt->CKTstate0 + inst->NUMOSvsb), &icheck1);
|
||||
if (icheck1 == 1)
|
||||
icheck = 1;
|
||||
vgb = inst->NUMOStype * limitVgb(inst->NUMOStype * vgb,
|
||||
inst->NUMOStype * *(ckt->CKTstate0 + inst->NUMOSvgb), &icheck1);
|
||||
if (icheck1 == 1)
|
||||
icheck = 1;
|
||||
}
|
||||
delVdb = vdb - *(ckt->CKTstate0 + inst->NUMOSvdb);
|
||||
delVsb = vsb - *(ckt->CKTstate0 + inst->NUMOSvsb);
|
||||
delVgb = vgb - *(ckt->CKTstate0 + inst->NUMOSvgb);
|
||||
NUMOSsetBCs(pDevice, vdb - delVdb, vsb - delVsb, vgb - delVgb);
|
||||
}
|
||||
|
||||
if (doInitSolve) {
|
||||
if (TWOdcDebug) {
|
||||
printVoltages(stdout, model->NUMOSmodName, inst->NUMOSname,
|
||||
deviceType, 3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
startTime2 = SPfrontEnd->IFseconds();
|
||||
TWOequilSolve(pDevice);
|
||||
totalTime2 = SPfrontEnd->IFseconds() - startTime2;
|
||||
pDevice->pStats->totalTime[STAT_SETUP] += totalTime2;
|
||||
pDevice->pStats->totalTime[STAT_DC] -= totalTime2;
|
||||
|
||||
TWObiasSolve(pDevice, MaxIterations, FALSE, NULL);
|
||||
|
||||
*(ckt->CKTstate0 + inst->NUMOSvdb) = 0.0;
|
||||
*(ckt->CKTstate0 + inst->NUMOSvsb) = 0.0;
|
||||
*(ckt->CKTstate0 + inst->NUMOSvgb) = 0.0;
|
||||
|
||||
if (initStateName != NULL) {
|
||||
if (TWOreadState(pDevice, initStateName, 3, &vdb, &vgb, &vsb ) < 0) {
|
||||
fprintf(stderr,
|
||||
"NUMOSload: trouble reading state-file %s\n", initStateName);
|
||||
} else {
|
||||
NUMOSsetBCs(pDevice, vdb, vsb, vgb);
|
||||
delVdb = delVsb = delVgb = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* determine dc current and derivatives using the numerical routines
|
||||
*/
|
||||
if (ckt->CKTmode & (MODEDCOP | MODETRANOP | MODEDCTRANCURVE | MODEINITSMSIG)) {
|
||||
numDevNonCon = 0;
|
||||
inst->NUMOSc11 = inst->NUMOSy11r = inst->NUMOSy11i = 0.0;
|
||||
inst->NUMOSc12 = inst->NUMOSy12r = inst->NUMOSy12i = 0.0;
|
||||
inst->NUMOSc13 = inst->NUMOSy13r = inst->NUMOSy13i = 0.0;
|
||||
inst->NUMOSc21 = inst->NUMOSy21r = inst->NUMOSy21i = 0.0;
|
||||
inst->NUMOSc22 = inst->NUMOSy22r = inst->NUMOSy22i = 0.0;
|
||||
inst->NUMOSc23 = inst->NUMOSy23r = inst->NUMOSy23i = 0.0;
|
||||
inst->NUMOSc31 = inst->NUMOSy31r = inst->NUMOSy31i = 0.0;
|
||||
inst->NUMOSc32 = inst->NUMOSy32r = inst->NUMOSy32i = 0.0;
|
||||
inst->NUMOSc33 = inst->NUMOSy33r = inst->NUMOSy33i = 0.0;
|
||||
inst->NUMOSsmSigAvail = FALSE;
|
||||
devNonCon:
|
||||
NUMOSproject(pDevice, delVdb, delVsb, delVgb);
|
||||
if (TWOdcDebug) {
|
||||
printVoltages(stdout, model->NUMOSmodName, inst->NUMOSname,
|
||||
deviceType, 3, vdb, delVdb, vgb, delVgb, vsb, delVsb);
|
||||
}
|
||||
TWObiasSolve(pDevice, MaxIterations, FALSE, model->NUMOSpInfo);
|
||||
|
||||
devConverged = pDevice->converged;
|
||||
if (devConverged && finite(pDevice->rhsNorm)) {
|
||||
/* compute the currents */
|
||||
NUMOScurrent(pDevice, FALSE, (double *) NULL, &id, &is, &ig);
|
||||
NUMOSconductance(pDevice, FALSE, (double *) NULL, &g);
|
||||
/*
|
||||
* Add gmin to the gate conductance terms since they will be zero.
|
||||
* XXX This messes up the gXY output values, but we choose not to
|
||||
* correct this error, because it shouldn't cause practical problems.
|
||||
*/
|
||||
g.dIgDVdb += ckt->CKTgmin;
|
||||
g.dIgDVsb += ckt->CKTgmin;
|
||||
g.dIgDVgb += ckt->CKTgmin;
|
||||
|
||||
} else {
|
||||
/* reduce the voltage step until converged */
|
||||
/* restore boundary nodes to previous potential */
|
||||
NUMOSsetBCs(pDevice,
|
||||
vdb - delVdb, vsb - delVsb, vgb - delVgb);
|
||||
TWOstoreInitialGuess(pDevice);
|
||||
TWOresetJacobian(pDevice);
|
||||
delVdb *= 0.5;
|
||||
delVsb *= 0.5;
|
||||
delVgb *= 0.5;
|
||||
vdb = delVdb + *(ckt->CKTstate0 + inst->NUMOSvdb);
|
||||
vsb = delVsb + *(ckt->CKTstate0 + inst->NUMOSvsb);
|
||||
vgb = delVgb + *(ckt->CKTstate0 + inst->NUMOSvgb);
|
||||
numDevNonCon++;
|
||||
icheck = 1;
|
||||
if (numDevNonCon > 10) {
|
||||
printVoltages(stderr, model->NUMOSmodName, inst->NUMOSname,
|
||||
deviceType, 3, vdb, delVdb, vgb, delVgb, vsb, delVsb);
|
||||
fprintf(stderr, "*** Non-convergence during load ***\n");
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
return (E_BADMATRIX);
|
||||
} else {
|
||||
goto devNonCon;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((ckt->CKTmode & (MODETRAN | MODEAC)) ||
|
||||
((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) ||
|
||||
(ckt->CKTmode & MODEINITSMSIG)) {
|
||||
/*
|
||||
* store small-signal parameters
|
||||
*/
|
||||
if ((!(ckt->CKTmode & MODETRANOP)) ||
|
||||
(!(ckt->CKTmode & MODEUIC))) {
|
||||
if (ckt->CKTmode & MODEINITSMSIG) {
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
startTime2 = SPfrontEnd->IFseconds();
|
||||
NUMOSinitSmSig(inst);
|
||||
pDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime2;
|
||||
continue;
|
||||
} else {
|
||||
inst->NUMOSsmSigAvail = FALSE;
|
||||
}
|
||||
/*
|
||||
* transient analysis
|
||||
*/
|
||||
if (ckt->CKTmode & MODEINITPRED) {
|
||||
NUMOSsetBCs(pDevice, vdb, vsb, vgb);
|
||||
TWOstoreInitialGuess(pDevice);
|
||||
} else {
|
||||
NUMOSupdate(pDevice, delVdb, delVsb, delVgb, TRUE);
|
||||
}
|
||||
if (TWOtranDebug) {
|
||||
printVoltages(stdout, model->NUMOSmodName, inst->NUMOSname,
|
||||
deviceType, 3, vdb, delVdb, vgb, delVgb, vsb, delVsb);
|
||||
}
|
||||
TWObiasSolve(pDevice, 0, TRUE, model->NUMOSpInfo);
|
||||
if (!finite(pDevice->rhsNorm)) {
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
return (E_BADMATRIX);
|
||||
}
|
||||
devConverged = TWOdeviceConverged(pDevice);
|
||||
pDevice->converged = devConverged;
|
||||
|
||||
/* compute the currents and conductances */
|
||||
NUMOScurrent(pDevice, TRUE, model->NUMOSpInfo->intCoeff,
|
||||
&id, &is, &ig);
|
||||
NUMOSconductance(pDevice, TRUE,
|
||||
model->NUMOSpInfo->intCoeff, &g);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check convergence
|
||||
*/
|
||||
if ((!(ckt->CKTmode & MODEINITFIX)) || (!(inst->NUMOSoff))) {
|
||||
if (icheck == 1 || !devConverged) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
} else {
|
||||
tol = ckt->CKTreltol * MAX(fabs(idhat), fabs(id)) + ckt->CKTabstol;
|
||||
if (fabs(idhat - id) > tol) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
} else {
|
||||
tol = ckt->CKTreltol * MAX(fabs(ishat), fabs(is)) +
|
||||
ckt->CKTabstol;
|
||||
if (fabs(ishat - is) > tol) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
} else {
|
||||
tol = ckt->CKTreltol * MAX(fabs(ighat), fabs(ig)) +
|
||||
ckt->CKTabstol;
|
||||
if (fabs(ighat - ig) > tol) {
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = (GENinstance *) inst;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*(ckt->CKTstate0 + inst->NUMOSvdb) = vdb;
|
||||
*(ckt->CKTstate0 + inst->NUMOSvsb) = vsb;
|
||||
*(ckt->CKTstate0 + inst->NUMOSvgb) = vgb;
|
||||
*(ckt->CKTstate0 + inst->NUMOSid) = id;
|
||||
*(ckt->CKTstate0 + inst->NUMOSis) = is;
|
||||
*(ckt->CKTstate0 + inst->NUMOSig) = ig;
|
||||
*(ckt->CKTstate0 + inst->NUMOSdIdDVdb) = g.dIdDVdb;
|
||||
*(ckt->CKTstate0 + inst->NUMOSdIdDVsb) = g.dIdDVsb;
|
||||
*(ckt->CKTstate0 + inst->NUMOSdIdDVgb) = g.dIdDVgb;
|
||||
*(ckt->CKTstate0 + inst->NUMOSdIsDVdb) = g.dIsDVdb;
|
||||
*(ckt->CKTstate0 + inst->NUMOSdIsDVsb) = g.dIsDVsb;
|
||||
*(ckt->CKTstate0 + inst->NUMOSdIsDVgb) = g.dIsDVgb;
|
||||
*(ckt->CKTstate0 + inst->NUMOSdIgDVdb) = g.dIgDVdb;
|
||||
*(ckt->CKTstate0 + inst->NUMOSdIgDVsb) = g.dIgDVsb;
|
||||
*(ckt->CKTstate0 + inst->NUMOSdIgDVgb) = g.dIgDVgb;
|
||||
|
||||
load:
|
||||
/*
|
||||
* load current excitation vector
|
||||
*/
|
||||
|
||||
ideq = id - g.dIdDVdb * vdb - g.dIdDVsb * vsb - g.dIdDVgb * vgb;
|
||||
iseq = is - g.dIsDVdb * vdb - g.dIsDVsb * vsb - g.dIsDVgb * vgb;
|
||||
igeq = ig - g.dIgDVdb * vdb - g.dIgDVsb * vsb - g.dIgDVgb * vgb;
|
||||
*(ckt->CKTrhs + inst->NUMOSdrainNode) -= ideq;
|
||||
*(ckt->CKTrhs + inst->NUMOSsourceNode) -= iseq;
|
||||
*(ckt->CKTrhs + inst->NUMOSgateNode) -= igeq;
|
||||
*(ckt->CKTrhs + inst->NUMOSbulkNode) += ideq + iseq + igeq;
|
||||
/*
|
||||
* load y matrix
|
||||
*/
|
||||
|
||||
*(inst->NUMOSdrainDrainPtr) += g.dIdDVdb;
|
||||
*(inst->NUMOSdrainSourcePtr) += g.dIdDVsb;
|
||||
*(inst->NUMOSdrainGatePtr) += g.dIdDVgb;
|
||||
*(inst->NUMOSdrainBulkPtr) -= g.dIdDVdb + g.dIdDVsb + g.dIdDVgb;
|
||||
|
||||
*(inst->NUMOSsourceDrainPtr) += g.dIsDVdb;
|
||||
*(inst->NUMOSsourceSourcePtr) += g.dIsDVsb;
|
||||
*(inst->NUMOSsourceGatePtr) += g.dIsDVgb;
|
||||
*(inst->NUMOSsourceBulkPtr) -= g.dIsDVdb + g.dIsDVsb + g.dIsDVgb;
|
||||
|
||||
*(inst->NUMOSgateDrainPtr) += g.dIgDVdb;
|
||||
*(inst->NUMOSgateSourcePtr) += g.dIgDVsb;
|
||||
*(inst->NUMOSgateGatePtr) += g.dIgDVgb;
|
||||
*(inst->NUMOSgateBulkPtr) -= g.dIgDVdb + g.dIgDVsb + g.dIgDVgb;
|
||||
|
||||
*(inst->NUMOSbulkDrainPtr) -= g.dIdDVdb + g.dIsDVdb + g.dIgDVdb;
|
||||
*(inst->NUMOSbulkSourcePtr) -= g.dIdDVsb + g.dIsDVsb + g.dIgDVsb;
|
||||
*(inst->NUMOSbulkGatePtr) -= g.dIdDVgb + g.dIsDVgb + g.dIgDVgb;
|
||||
*(inst->NUMOSbulkBulkPtr) += g.dIdDVdb + g.dIdDVsb + g.dIdDVgb
|
||||
+ g.dIsDVdb + g.dIsDVsb + g.dIsDVgb
|
||||
+ g.dIgDVdb + g.dIgDVsb + g.dIgDVgb;
|
||||
|
||||
totalTime += SPfrontEnd->IFseconds() - startTime;
|
||||
if (ckt->CKTmode & MODETRAN) {
|
||||
pDevice->pStats->totalTime[STAT_TRAN] += totalTime;
|
||||
} else {
|
||||
pDevice->pStats->totalTime[STAT_DC] += totalTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
||||
int
|
||||
NUMOSinitSmSig(inst)
|
||||
NUMOSinstance *inst;
|
||||
{
|
||||
struct mosAdmittances yAc;
|
||||
double omega = inst->NUMOSmodPtr->NUMOSmethods->METHomega;
|
||||
|
||||
AcAnalysisMethod = SOR_ONLY;
|
||||
(void) NUMOSadmittance(inst->NUMOSpDevice, omega, &yAc);
|
||||
inst->NUMOSc11 = yAc.yIdVdb.imag / omega;
|
||||
inst->NUMOSc12 = yAc.yIdVgb.imag / omega;
|
||||
inst->NUMOSc13 = yAc.yIdVsb.imag / omega;
|
||||
inst->NUMOSc21 = yAc.yIgVdb.imag / omega;
|
||||
inst->NUMOSc22 = yAc.yIgVgb.imag / omega;
|
||||
inst->NUMOSc23 = yAc.yIgVsb.imag / omega;
|
||||
inst->NUMOSc31 = yAc.yIsVdb.imag / omega;
|
||||
inst->NUMOSc32 = yAc.yIsVgb.imag / omega;
|
||||
inst->NUMOSc33 = yAc.yIsVsb.imag / omega;
|
||||
inst->NUMOSy11r = yAc.yIdVdb.real;
|
||||
inst->NUMOSy11i = yAc.yIdVdb.imag;
|
||||
inst->NUMOSy12r = yAc.yIdVgb.real;
|
||||
inst->NUMOSy12i = yAc.yIdVgb.imag;
|
||||
inst->NUMOSy13r = yAc.yIdVsb.real;
|
||||
inst->NUMOSy13i = yAc.yIdVsb.imag;
|
||||
inst->NUMOSy21r = yAc.yIgVdb.real;
|
||||
inst->NUMOSy21i = yAc.yIgVdb.imag;
|
||||
inst->NUMOSy22r = yAc.yIgVgb.real;
|
||||
inst->NUMOSy22i = yAc.yIgVgb.imag;
|
||||
inst->NUMOSy23r = yAc.yIgVsb.real;
|
||||
inst->NUMOSy23i = yAc.yIgVsb.imag;
|
||||
inst->NUMOSy31r = yAc.yIsVdb.real;
|
||||
inst->NUMOSy31i = yAc.yIsVdb.imag;
|
||||
inst->NUMOSy32r = yAc.yIsVgb.real;
|
||||
inst->NUMOSy32i = yAc.yIsVgb.imag;
|
||||
inst->NUMOSy33r = yAc.yIsVsb.real;
|
||||
inst->NUMOSy33i = yAc.yIsVsb.imag;
|
||||
inst->NUMOSsmSigAvail = TRUE;
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine deletes a NUMOS model from the circuit and frees the storage
|
||||
* it was using. returns an error if the model has instances
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "numosdef.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NUMOSmDelete(inModel, modname, kill)
|
||||
GENmodel **inModel;
|
||||
IFuid modname;
|
||||
GENmodel *kill;
|
||||
|
||||
{
|
||||
|
||||
NUMOSmodel **model = (NUMOSmodel **) inModel;
|
||||
NUMOSmodel *modfast = (NUMOSmodel *) kill;
|
||||
NUMOSmodel **oldmod;
|
||||
oldmod = model;
|
||||
for (; *model; model = &((*model)->NUMOSnextModel)) {
|
||||
if ((*model)->NUMOSmodName == modname ||
|
||||
(modfast && *model == modfast))
|
||||
goto delgot;
|
||||
oldmod = model;
|
||||
}
|
||||
return (E_NOMOD);
|
||||
|
||||
delgot:
|
||||
if ((*model)->NUMOSinstances)
|
||||
return (E_NOTEMPTY);
|
||||
*oldmod = (*model)->NUMOSnextModel; /* cut deleted device out of list */
|
||||
FREE(*model);
|
||||
return (OK);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine sets model parameters for NUMOSs in the circuit.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "numosdef.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NUMOSmParam(param, value, inModel)
|
||||
int param;
|
||||
IFvalue *value;
|
||||
GENmodel *inModel;
|
||||
{
|
||||
switch (param) {
|
||||
case NUMOS_MOD_NUMOS:
|
||||
/* no action - already know it is a 2d-numerical MOS, but this */
|
||||
/* makes life easier for spice-2 like parsers */
|
||||
break;
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine sets instance parameters for NUMOSs in the circuit.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "const.h"
|
||||
#include "ifsim.h"
|
||||
#include "numosdef.h"
|
||||
#include "sperror.h"
|
||||
#include "suffix.h"
|
||||
|
||||
int
|
||||
NUMOSparam(param, value, inInst, select)
|
||||
int param;
|
||||
IFvalue *value;
|
||||
GENinstance *inInst;
|
||||
IFvalue *select;
|
||||
{
|
||||
register NUMOSinstance *inst = (NUMOSinstance *) inInst;
|
||||
switch (param) {
|
||||
case NUMOS_AREA:
|
||||
inst->NUMOSarea = value->rValue;
|
||||
inst->NUMOSareaGiven = TRUE;
|
||||
break;
|
||||
case NUMOS_WIDTH:
|
||||
inst->NUMOSwidth = value->rValue;
|
||||
inst->NUMOSwidthGiven = TRUE;
|
||||
break;
|
||||
case NUMOS_LENGTH:
|
||||
inst->NUMOSlength = value->rValue;
|
||||
inst->NUMOSlengthGiven = TRUE;
|
||||
break;
|
||||
case NUMOS_OFF:
|
||||
inst->NUMOSoff = TRUE;
|
||||
break;
|
||||
case NUMOS_IC_FILE:
|
||||
inst->NUMOSicFile = value->sValue;
|
||||
inst->NUMOSicFileGiven = TRUE;
|
||||
break;
|
||||
case NUMOS_PRINT:
|
||||
inst->NUMOSprint = value->rValue;
|
||||
inst->NUMOSprintGiven = TRUE;
|
||||
break;
|
||||
case NUMOS_TEMP:
|
||||
inst->NUMOStemp = value->rValue + CONSTCtoK;
|
||||
inst->NUMOStempGiven = TRUE;
|
||||
break;
|
||||
default:
|
||||
return (E_BADPARM);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "complex.h"
|
||||
#include "numosdef.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
/* External Declarations */
|
||||
extern int TWOacDebug;
|
||||
|
||||
|
||||
int
|
||||
NUMOSpzLoad(inModel, ckt, s)
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
SPcomplex *s;
|
||||
|
||||
{
|
||||
register NUMOSmodel *model = (NUMOSmodel *) inModel;
|
||||
register NUMOSinstance *inst;
|
||||
struct mosAdmittances yAc;
|
||||
double startTime;
|
||||
|
||||
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;
|
||||
AcAnalysisMethod = model->NUMOSmethods->METHacAnalysisMethod;
|
||||
MobDeriv = model->NUMOSmethods->METHmobDeriv;
|
||||
TWOacDebug = model->NUMOSoutputs->OUTPacDebug;
|
||||
|
||||
for (inst = model->NUMOSinstances; inst != NULL;
|
||||
inst = inst->NUMOSnextInstance) {
|
||||
if (inst->NUMOSowner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
/* Get Temp.-Dep. Global Parameters */
|
||||
GLOBgetGlobals(&(inst->NUMOSglobals));
|
||||
|
||||
NUMOSys(inst->NUMOSpDevice, s, &yAc);
|
||||
|
||||
*(inst->NUMOSdrainDrainPtr) += yAc.yIdVdb.real;
|
||||
*(inst->NUMOSdrainDrainPtr + 1) += yAc.yIdVdb.imag;
|
||||
*(inst->NUMOSdrainSourcePtr) += yAc.yIdVsb.real;
|
||||
*(inst->NUMOSdrainSourcePtr + 1) += yAc.yIdVsb.imag;
|
||||
*(inst->NUMOSdrainGatePtr) += yAc.yIdVgb.real;
|
||||
*(inst->NUMOSdrainGatePtr + 1) += yAc.yIdVgb.imag;
|
||||
*(inst->NUMOSdrainBulkPtr) -=
|
||||
yAc.yIdVdb.real + yAc.yIdVsb.real + yAc.yIdVgb.real;
|
||||
*(inst->NUMOSdrainBulkPtr + 1) -=
|
||||
yAc.yIdVdb.imag + yAc.yIdVsb.imag + yAc.yIdVgb.imag;
|
||||
|
||||
*(inst->NUMOSsourceDrainPtr) += yAc.yIsVdb.real;
|
||||
*(inst->NUMOSsourceDrainPtr + 1) += yAc.yIsVdb.imag;
|
||||
*(inst->NUMOSsourceSourcePtr) += yAc.yIsVsb.real;
|
||||
*(inst->NUMOSsourceSourcePtr + 1) += yAc.yIsVsb.imag;
|
||||
*(inst->NUMOSsourceGatePtr) += yAc.yIsVgb.real;
|
||||
*(inst->NUMOSsourceGatePtr + 1) += yAc.yIsVgb.imag;
|
||||
*(inst->NUMOSsourceBulkPtr) -=
|
||||
yAc.yIsVdb.real + yAc.yIsVsb.real + yAc.yIsVgb.real;
|
||||
*(inst->NUMOSsourceBulkPtr + 1) -=
|
||||
yAc.yIsVdb.imag + yAc.yIsVsb.imag + yAc.yIsVgb.imag;
|
||||
|
||||
*(inst->NUMOSgateDrainPtr) += yAc.yIgVdb.real;
|
||||
*(inst->NUMOSgateDrainPtr + 1) += yAc.yIgVdb.imag;
|
||||
*(inst->NUMOSgateSourcePtr) += yAc.yIgVsb.real;
|
||||
*(inst->NUMOSgateSourcePtr + 1) += yAc.yIgVsb.imag;
|
||||
*(inst->NUMOSgateGatePtr) += yAc.yIgVgb.real;
|
||||
*(inst->NUMOSgateGatePtr + 1) += yAc.yIgVgb.imag;
|
||||
*(inst->NUMOSgateBulkPtr) -=
|
||||
yAc.yIgVdb.real + yAc.yIgVsb.real + yAc.yIgVgb.real;
|
||||
*(inst->NUMOSgateBulkPtr + 1) -=
|
||||
yAc.yIgVdb.imag + yAc.yIgVsb.imag + yAc.yIgVgb.imag;
|
||||
|
||||
*(inst->NUMOSbulkDrainPtr) -=
|
||||
yAc.yIdVdb.real + yAc.yIsVdb.real + yAc.yIgVdb.real;
|
||||
*(inst->NUMOSbulkDrainPtr + 1) -=
|
||||
yAc.yIdVdb.imag + yAc.yIsVdb.imag + yAc.yIgVdb.imag;
|
||||
*(inst->NUMOSbulkSourcePtr) -=
|
||||
yAc.yIdVsb.real + yAc.yIsVsb.real + yAc.yIgVsb.real;
|
||||
*(inst->NUMOSbulkSourcePtr + 1) -=
|
||||
yAc.yIdVsb.imag + yAc.yIsVsb.imag + yAc.yIgVsb.imag;
|
||||
*(inst->NUMOSbulkGatePtr) -=
|
||||
yAc.yIdVgb.real + yAc.yIsVgb.real + yAc.yIgVgb.real;
|
||||
*(inst->NUMOSbulkGatePtr + 1) -=
|
||||
yAc.yIdVgb.imag + yAc.yIsVgb.imag + yAc.yIgVgb.imag;
|
||||
*(inst->NUMOSbulkBulkPtr) +=
|
||||
yAc.yIdVdb.real + yAc.yIdVsb.real + yAc.yIdVgb.real +
|
||||
yAc.yIsVdb.real + yAc.yIsVsb.real + yAc.yIsVgb.real +
|
||||
yAc.yIgVdb.real + yAc.yIgVsb.real + yAc.yIgVgb.real;
|
||||
*(inst->NUMOSbulkBulkPtr + 1) -=
|
||||
yAc.yIdVdb.imag + yAc.yIdVsb.imag + yAc.yIdVgb.imag +
|
||||
yAc.yIsVdb.imag + yAc.yIsVsb.imag + yAc.yIsVgb.imag +
|
||||
yAc.yIgVdb.imag + yAc.yIgVsb.imag + yAc.yIgVgb.imag;
|
||||
|
||||
inst->NUMOSpDevice->pStats->totalTime[STAT_AC] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "smpdefs.h"
|
||||
#include "numosdef.h"
|
||||
#include "numconst.h"
|
||||
#include "numenum.h"
|
||||
#include "meshext.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "ciderinp.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#define NIL(type) ((type *)0)
|
||||
#define TSCALLOC(var, size, type)\
|
||||
if (size && (!(var =(type *)calloc(1, (unsigned)(size)*sizeof(type))))) {\
|
||||
return(E_NOMEM);\
|
||||
}
|
||||
|
||||
int
|
||||
NUMOSsetup(matrix, inModel, ckt, states)
|
||||
register SMPmatrix *matrix;
|
||||
GENmodel *inModel;
|
||||
CKTcircuit *ckt;
|
||||
int *states;
|
||||
/*
|
||||
* load the structure with those pointers needed later for fast matrix
|
||||
* loading
|
||||
*/
|
||||
{
|
||||
register NUMOSmodel *model = (NUMOSmodel *) inModel;
|
||||
register NUMOSinstance *inst;
|
||||
METHcard *methods;
|
||||
MODLcard *models;
|
||||
OPTNcard *options;
|
||||
OUTPcard *outputs;
|
||||
char *icFileName = NULL;
|
||||
int nameLen;
|
||||
int error, xIndex, yIndex;
|
||||
int xMeshSize, yMeshSize;
|
||||
TWOdevice *pDevice;
|
||||
TWOcoord *xCoordList = NIL(TWOcoord);
|
||||
TWOcoord *yCoordList = NIL(TWOcoord);
|
||||
TWOdomain *domainList = NIL(TWOdomain);
|
||||
TWOelectrode *electrodeList = NIL(TWOelectrode);
|
||||
TWOmaterial *pM, *pMaterial = NIL(TWOmaterial), *materialList = NIL(TWOmaterial);
|
||||
DOPprofile *profileList = NIL(DOPprofile);
|
||||
DOPtable *dopTableList = NIL(DOPtable);
|
||||
double startTime;
|
||||
|
||||
/* loop through all the models */
|
||||
for (; model != NULL; model = model->NUMOSnextModel) {
|
||||
if (!model->NUMOSpInfo) {
|
||||
TSCALLOC(model->NUMOSpInfo, 1, TWOtranInfo);
|
||||
}
|
||||
methods = model->NUMOSmethods;
|
||||
if (!methods) {
|
||||
TSCALLOC(methods, 1, METHcard);
|
||||
model->NUMOSmethods = methods;
|
||||
}
|
||||
models = model->NUMOSmodels;
|
||||
if (!models) {
|
||||
TSCALLOC(models, 1, MODLcard);
|
||||
model->NUMOSmodels = models;
|
||||
}
|
||||
options = model->NUMOSoptions;
|
||||
if (!options) {
|
||||
TSCALLOC(options, 1, OPTNcard);
|
||||
model->NUMOSoptions = options;
|
||||
}
|
||||
outputs = model->NUMOSoutputs;
|
||||
if (!outputs) {
|
||||
TSCALLOC(outputs, 1, OUTPcard);
|
||||
model->NUMOSoutputs = outputs;
|
||||
}
|
||||
if (!methods->METHvoltPredGiven) {
|
||||
methods->METHvoltPred = FALSE;
|
||||
}
|
||||
if (!methods->METHmobDerivGiven) {
|
||||
methods->METHmobDeriv = TRUE;
|
||||
}
|
||||
if (!methods->METHoneCarrierGiven) {
|
||||
methods->METHoneCarrier = FALSE;
|
||||
}
|
||||
if (!methods->METHacAnalysisMethodGiven) {
|
||||
methods->METHacAnalysisMethod = SOR;
|
||||
}
|
||||
if (!methods->METHdabstolGiven) {
|
||||
methods->METHdabstol = DABSTOL2D;
|
||||
}
|
||||
if (!methods->METHdreltolGiven) {
|
||||
methods->METHdreltol = ckt->CKTreltol;
|
||||
}
|
||||
if (!methods->METHitLimGiven) {
|
||||
methods->METHitLim = 50;
|
||||
}
|
||||
if (!methods->METHomegaGiven || methods->METHomega <= 0.0) {
|
||||
methods->METHomega = 2.0 * M_PI /* radians/sec */ ;
|
||||
}
|
||||
if (!options->OPTNdefaGiven || options->OPTNdefa <= 0.0) {
|
||||
options->OPTNdefa = 1.0e4 /* cm^2 */ ;
|
||||
}
|
||||
if (!options->OPTNdeflGiven || options->OPTNdefl <= 0.0) {
|
||||
options->OPTNdefl = 1.0e2 /* cm */ ;
|
||||
}
|
||||
if (!options->OPTNdefwGiven && options->OPTNdefaGiven) {
|
||||
options->OPTNdefw = options->OPTNdefa / options->OPTNdefl;
|
||||
} else if (!options->OPTNdefwGiven || options->OPTNdefw <= 0.0) {
|
||||
options->OPTNdefw = 1.0e2 /* cm */ ;
|
||||
}
|
||||
if (!options->OPTNdeviceTypeGiven) {
|
||||
options->OPTNdeviceType = OPTN_MOSFET;
|
||||
}
|
||||
if (!options->OPTNicFileGiven) {
|
||||
options->OPTNicFile = NULL;
|
||||
options->OPTNunique = FALSE; /* Can't form a unique name. */
|
||||
}
|
||||
if (!options->OPTNuniqueGiven) {
|
||||
options->OPTNunique = FALSE;
|
||||
}
|
||||
OneCarrier = methods->METHoneCarrier;
|
||||
|
||||
/* Set up the rest of the card lists */
|
||||
if ((error = MODLsetup(model->NUMOSmodels)))
|
||||
return (error);
|
||||
BandGapNarrowing = models->MODLbandGapNarrowing;
|
||||
ConcDepLifetime = models->MODLconcDepLifetime;
|
||||
TempDepMobility = models->MODLtempDepMobility;
|
||||
ConcDepMobility = models->MODLconcDepMobility;
|
||||
SurfaceMobility = models->MODLsurfaceMobility;
|
||||
|
||||
if ((error = OUTPsetup(model->NUMOSoutputs)))
|
||||
return (error);
|
||||
if ((error = MATLsetup(model->NUMOSmaterials, &materialList)))
|
||||
return (error);
|
||||
if ((error = MOBsetup(model->NUMOSmobility, materialList)))
|
||||
return (error);
|
||||
if ((error = MESHsetup('x', model->NUMOSxMeshes, &xCoordList, &xMeshSize)))
|
||||
return (error);
|
||||
if ((error = MESHsetup('y', model->NUMOSyMeshes, &yCoordList, &yMeshSize)))
|
||||
return (error);
|
||||
if ((error = DOMNsetup(model->NUMOSdomains, &domainList,
|
||||
xCoordList, yCoordList, materialList)))
|
||||
return (error);
|
||||
if ((error = BDRYsetup(model->NUMOSboundaries,
|
||||
xCoordList, yCoordList, domainList)))
|
||||
return (error);
|
||||
if ((error = ELCTsetup(model->NUMOSelectrodes, &electrodeList,
|
||||
xCoordList, yCoordList)))
|
||||
return (error);
|
||||
/* Make sure electrodes are OK. */
|
||||
checkElectrodes(electrodeList, 4); /* NUMOS has 4 electrodes */
|
||||
|
||||
if ((error = CONTsetup(model->NUMOScontacts, electrodeList)))
|
||||
return (error);
|
||||
if ((error = DOPsetup(model->NUMOSdopings, &profileList,
|
||||
&dopTableList, xCoordList, yCoordList)))
|
||||
return (error);
|
||||
model->NUMOSmatlInfo = materialList;
|
||||
model->NUMOSprofiles = profileList;
|
||||
model->NUMOSdopTables = dopTableList;
|
||||
|
||||
/* loop through all the instances of the model */
|
||||
for (inst = model->NUMOSinstances; inst != NULL;
|
||||
inst = inst->NUMOSnextInstance) {
|
||||
if (inst->NUMOSowner != ARCHme) goto matrixpointers;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
if (!inst->NUMOSprintGiven) {
|
||||
inst->NUMOSprint = 0;
|
||||
} else if (inst->NUMOSprint <= 0) {
|
||||
inst->NUMOSprint = 1;
|
||||
}
|
||||
if (!inst->NUMOSicFileGiven) {
|
||||
if (options->OPTNunique) {
|
||||
nameLen = strlen(options->OPTNicFile) + strlen(inst->NUMOSname) + 1;
|
||||
TSCALLOC(icFileName, nameLen+1, char);
|
||||
sprintf(icFileName, "%s.%s", options->OPTNicFile, inst->NUMOSname);
|
||||
icFileName[nameLen] = '\0';
|
||||
inst->NUMOSicFile = icFileName;
|
||||
} else if (options->OPTNicFile != NULL) {
|
||||
nameLen = strlen(options->OPTNicFile);
|
||||
TSCALLOC(icFileName, nameLen+1, char);
|
||||
icFileName = strcpy(icFileName, options->OPTNicFile);
|
||||
inst->NUMOSicFile = icFileName;
|
||||
} else {
|
||||
inst->NUMOSicFile = NULL;
|
||||
}
|
||||
}
|
||||
inst->NUMOSstate = *states;
|
||||
*states += NUMOSnumStates;
|
||||
|
||||
if (!inst->NUMOSpDevice) {
|
||||
/* Assign the mesh info to each instance. */
|
||||
TSCALLOC(pDevice, 1, TWOdevice);
|
||||
TSCALLOC(pDevice->pStats, 1, TWOstats);
|
||||
pDevice->name = inst->NUMOSname;
|
||||
pDevice->solverType = SLV_NONE;
|
||||
pDevice->numXNodes = xMeshSize;
|
||||
pDevice->numYNodes = yMeshSize;
|
||||
pDevice->xScale = MESHmkArray(xCoordList, xMeshSize);
|
||||
pDevice->yScale = MESHmkArray(yCoordList, yMeshSize);
|
||||
pDevice->abstol = methods->METHdabstol;
|
||||
pDevice->reltol = methods->METHdreltol;
|
||||
TSCALLOC(pDevice->elemArray, pDevice->numXNodes, TWOelem **);
|
||||
for (xIndex = 1; xIndex < pDevice->numXNodes; xIndex++) {
|
||||
TSCALLOC(pDevice->elemArray[xIndex], pDevice->numYNodes, TWOelem *);
|
||||
}
|
||||
|
||||
/* Create a copy of material data that can change with temperature. */
|
||||
pDevice->pMaterials = NIL(TWOmaterial);
|
||||
for (pM = materialList; pM != NIL(TWOmaterial); pM = pM->next) {
|
||||
if (pDevice->pMaterials == NIL(TWOmaterial)) {
|
||||
TSCALLOC(pMaterial, 1, TWOmaterial);
|
||||
pDevice->pMaterials = pMaterial;
|
||||
} else {
|
||||
TSCALLOC(pMaterial->next, 1, TWOmaterial);
|
||||
pMaterial = pMaterial->next;
|
||||
}
|
||||
/* Copy everything, then fix the incorrect pointer. */
|
||||
bcopy((char *) pM, (char *) pMaterial, sizeof(TWOmaterial));
|
||||
pMaterial->next = NIL(TWOmaterial);
|
||||
}
|
||||
|
||||
/* Generate the mesh structure for the device. */
|
||||
TWObuildMesh(pDevice, domainList, electrodeList, pDevice->pMaterials);
|
||||
|
||||
/* Store the device info in the instance. */
|
||||
inst->NUMOSpDevice = pDevice;
|
||||
}
|
||||
/* Now update the state pointers. */
|
||||
TWOgetStatePointers(inst->NUMOSpDevice, states);
|
||||
|
||||
/* Wipe out statistics from previous runs (if any). */
|
||||
bzero((char *) inst->NUMOSpDevice->pStats, sizeof(TWOstats));
|
||||
|
||||
inst->NUMOSpDevice->pStats->totalTime[STAT_SETUP] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
|
||||
/* macro to make elements with built in test for out of memory */
|
||||
#define TSTALLOC(ptr,first,second) \
|
||||
if ((inst->ptr = SMPmakeElt(matrix,inst->first,inst->second))==(double *)NULL){\
|
||||
return(E_NOMEM);\
|
||||
}
|
||||
|
||||
matrixpointers:
|
||||
TSTALLOC(NUMOSdrainDrainPtr, NUMOSdrainNode, NUMOSdrainNode)
|
||||
TSTALLOC(NUMOSdrainSourcePtr, NUMOSdrainNode, NUMOSsourceNode)
|
||||
TSTALLOC(NUMOSdrainGatePtr, NUMOSdrainNode, NUMOSgateNode)
|
||||
TSTALLOC(NUMOSdrainBulkPtr, NUMOSdrainNode, NUMOSbulkNode)
|
||||
TSTALLOC(NUMOSsourceDrainPtr, NUMOSsourceNode, NUMOSdrainNode)
|
||||
TSTALLOC(NUMOSsourceSourcePtr, NUMOSsourceNode, NUMOSsourceNode)
|
||||
TSTALLOC(NUMOSsourceGatePtr, NUMOSsourceNode, NUMOSgateNode)
|
||||
TSTALLOC(NUMOSsourceBulkPtr, NUMOSsourceNode, NUMOSbulkNode)
|
||||
TSTALLOC(NUMOSgateDrainPtr, NUMOSgateNode, NUMOSdrainNode)
|
||||
TSTALLOC(NUMOSgateSourcePtr, NUMOSgateNode, NUMOSsourceNode)
|
||||
TSTALLOC(NUMOSgateGatePtr, NUMOSgateNode, NUMOSgateNode)
|
||||
TSTALLOC(NUMOSgateBulkPtr, NUMOSgateNode, NUMOSbulkNode)
|
||||
TSTALLOC(NUMOSbulkDrainPtr, NUMOSbulkNode, NUMOSdrainNode)
|
||||
TSTALLOC(NUMOSbulkSourcePtr, NUMOSbulkNode, NUMOSsourceNode)
|
||||
TSTALLOC(NUMOSbulkGatePtr, NUMOSbulkNode, NUMOSgateNode)
|
||||
TSTALLOC(NUMOSbulkBulkPtr, NUMOSbulkNode, NUMOSbulkNode)
|
||||
}
|
||||
/* Clean up lists */
|
||||
killCoordInfo(xCoordList);
|
||||
killCoordInfo(yCoordList);
|
||||
killDomainInfo(domainList);
|
||||
killElectrodeInfo(electrodeList);
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
Author: 1991 David A. Gates, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numosdef.h"
|
||||
#include "numenum.h"
|
||||
#include "carddefs.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
#define NIL(type) ((type *)0)
|
||||
|
||||
int
|
||||
NUMOStemp(inModel, ckt)
|
||||
GENmodel *inModel;
|
||||
register CKTcircuit *ckt;
|
||||
/*
|
||||
* perform the temperature update
|
||||
*/
|
||||
{
|
||||
register NUMOSmodel *model = (NUMOSmodel *) inModel;
|
||||
register NUMOSinstance *inst;
|
||||
METHcard *methods;
|
||||
MODLcard *models;
|
||||
OPTNcard *options;
|
||||
OUTPcard *outputs;
|
||||
TWOmaterial *pM, *pMaterial, *pNextMaterial;
|
||||
double startTime;
|
||||
|
||||
|
||||
/* loop through all the models */
|
||||
for (; model != NULL; model = model->NUMOSnextModel) {
|
||||
methods = model->NUMOSmethods;
|
||||
models = model->NUMOSmodels;
|
||||
options = model->NUMOSoptions;
|
||||
outputs = model->NUMOSoutputs;
|
||||
|
||||
if (!options->OPTNtnomGiven) {
|
||||
options->OPTNtnom = ckt->CKTnomTemp;
|
||||
}
|
||||
for (pM = model->NUMOSmatlInfo; pM != NIL(TWOmaterial);
|
||||
pM = pM->next) {
|
||||
pM->tnom = options->OPTNtnom;
|
||||
}
|
||||
BandGapNarrowing = models->MODLbandGapNarrowing;
|
||||
ConcDepLifetime = models->MODLconcDepLifetime;
|
||||
TempDepMobility = models->MODLtempDepMobility;
|
||||
ConcDepMobility = models->MODLconcDepMobility;
|
||||
SurfaceMobility = models->MODLsurfaceMobility;
|
||||
MatchingMobility = models->MODLmatchingMobility;
|
||||
OneCarrier = methods->METHoneCarrier;
|
||||
|
||||
for (inst = model->NUMOSinstances; inst != NULL;
|
||||
inst = inst->NUMOSnextInstance) {
|
||||
if (inst->NUMOSowner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
|
||||
if (!inst->NUMOStempGiven) {
|
||||
inst->NUMOStemp = ckt->CKTtemp;
|
||||
}
|
||||
if (!inst->NUMOSareaGiven || inst->NUMOSarea <= 0.0) {
|
||||
inst->NUMOSarea = 1.0;
|
||||
}
|
||||
if (!inst->NUMOSwidthGiven || inst->NUMOSwidth <= 0.0) {
|
||||
inst->NUMOSwidth = 1.0;
|
||||
}
|
||||
inst->NUMOSpDevice->width =
|
||||
inst->NUMOSarea * inst->NUMOSwidth * options->OPTNdefw;
|
||||
|
||||
/* Compute and save globals for this instance. */
|
||||
GLOBcomputeGlobals(&(inst->NUMOSglobals), inst->NUMOStemp);
|
||||
|
||||
/* Calculate new sets of material parameters. */
|
||||
pM = model->NUMOSmatlInfo;
|
||||
pMaterial = inst->NUMOSpDevice->pMaterials;
|
||||
for (; pM != NULL; pM = pM->next, pMaterial = pMaterial->next) {
|
||||
|
||||
/* Copy everything, then fix the incorrect pointer. */
|
||||
pNextMaterial = pMaterial->next;
|
||||
bcopy((char *) pM, (char *) pMaterial, sizeof(TWOmaterial));
|
||||
pMaterial->next = pNextMaterial;
|
||||
|
||||
/* Now do the temperature dependence. */
|
||||
MATLtempDep(pMaterial, pMaterial->tnom);
|
||||
if (outputs->OUTPmaterial) {
|
||||
printMaterialInfo(pMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign doping to the mesh. */
|
||||
TWOsetDoping(inst->NUMOSpDevice, model->NUMOSprofiles,
|
||||
model->NUMOSdopTables);
|
||||
|
||||
/* Assign physical parameters to the mesh. */
|
||||
TWOsetup(inst->NUMOSpDevice);
|
||||
|
||||
/* Assign boundary condition parameters. */
|
||||
TWOsetBCparams(inst->NUMOSpDevice, model->NUMOSboundaries);
|
||||
|
||||
/* Normalize everything. */
|
||||
TWOnormalize(inst->NUMOSpDevice);
|
||||
|
||||
/* Find the device's type. */
|
||||
if (inst->NUMOSpDevice->pFirstContact->pNodes[0]->netConc < 0.0) {
|
||||
inst->NUMOStype = P_CH;
|
||||
if (OneCarrier) {
|
||||
methods->METHoneCarrier = P_TYPE;
|
||||
}
|
||||
} else {
|
||||
inst->NUMOStype = N_CH;
|
||||
if (OneCarrier) {
|
||||
methods->METHoneCarrier = N_TYPE;
|
||||
}
|
||||
}
|
||||
inst->NUMOSpDevice->pStats->totalTime[STAT_SETUP] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
**********/
|
||||
|
||||
/*
|
||||
* This routine performs truncation error calculations for NUMOSs in the
|
||||
* circuit.
|
||||
*/
|
||||
|
||||
#include "ngspice.h"
|
||||
#include "cktdefs.h"
|
||||
#include "numosdef.h"
|
||||
#include "sperror.h"
|
||||
#include "../../../ciderlib/twod/twoddefs.h"
|
||||
#include "../../../ciderlib/twod/twodext.h"
|
||||
#include "cidersupt.h"
|
||||
#include "suffix.h"
|
||||
|
||||
|
||||
int
|
||||
NUMOStrunc(inModel, ckt, timeStep)
|
||||
GENmodel *inModel;
|
||||
register CKTcircuit *ckt;
|
||||
double *timeStep;
|
||||
{
|
||||
register NUMOSmodel *model = (NUMOSmodel *) inModel;
|
||||
register NUMOSinstance *inst;
|
||||
double deltaNew;
|
||||
double deltaNorm[7];
|
||||
double startTime;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= ckt->CKTmaxOrder; i++) {
|
||||
deltaNorm[i] = ckt->CKTdeltaOld[i] / TNorm;
|
||||
}
|
||||
|
||||
for (; model != NULL; model = model->NUMOSnextModel) {
|
||||
OneCarrier = model->NUMOSmethods->METHoneCarrier;
|
||||
model->NUMOSpInfo->order = ckt->CKTorder;
|
||||
model->NUMOSpInfo->delta = deltaNorm;
|
||||
model->NUMOSpInfo->lteCoeff = computeLTECoeff(model->NUMOSpInfo);
|
||||
for (inst = model->NUMOSinstances; inst != NULL;
|
||||
inst = inst->NUMOSnextInstance) {
|
||||
if (inst->NUMOSowner != ARCHme) continue;
|
||||
|
||||
startTime = SPfrontEnd->IFseconds();
|
||||
deltaNew = TWOtrunc(inst->NUMOSpDevice, model->NUMOSpInfo,
|
||||
ckt->CKTdelta);
|
||||
*timeStep = MIN(*timeStep, deltaNew);
|
||||
inst->NUMOSpDevice->pStats->totalTime[STAT_TRAN] +=
|
||||
SPfrontEnd->IFseconds() - startTime;
|
||||
}
|
||||
}
|
||||
return (OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
Authors: 1987 Karti Mayaram, 1991 David Gates
|
||||
**********/
|
||||
|
||||
#ifndef NUMOS_H
|
||||
#define NUMOS_H "NUMOSdefs.h $Revision$ on $Date$ "
|
||||
|
||||
/* data structures used to describe 2D Numerical MOSFETs */
|
||||
|
||||
/* circuit level includes */
|
||||
#include "ifsim.h"
|
||||
#include "cktdefs.h"
|
||||
#include "gendefs.h"
|
||||
|
||||
/* device level includes */
|
||||
#include "twomesh.h"
|
||||
#include "twodev.h"
|
||||
#include "profile.h"
|
||||
#include "numglobs.h"
|
||||
#include "carddefs.h"
|
||||
|
||||
/* information needed per instance */
|
||||
typedef struct sNUMOSinstance {
|
||||
struct sNUMOSmodel *NUMOSmodPtr; /* back pointer to model */
|
||||
struct sNUMOSinstance *NUMOSnextInstance; /* pointer to next instance
|
||||
* of current model */
|
||||
IFuid NUMOSname; /* pointer to character string naming this
|
||||
* instance */
|
||||
int NUMOSowner; /* number of owner process */
|
||||
int NUMOSstate; /* pointer to start of state vector for
|
||||
* mosfet */
|
||||
|
||||
/* entries in the state vector for mosfet: */
|
||||
#define NUMOSvdb NUMOSstate
|
||||
#define NUMOSvsb NUMOSstate+1
|
||||
#define NUMOSvgb NUMOSstate+2
|
||||
#define NUMOSid NUMOSstate+3
|
||||
#define NUMOSis NUMOSstate+4
|
||||
#define NUMOSig NUMOSstate+5
|
||||
#define NUMOSdIdDVdb NUMOSstate+6
|
||||
#define NUMOSdIdDVsb NUMOSstate+7
|
||||
#define NUMOSdIdDVgb NUMOSstate+8
|
||||
#define NUMOSdIsDVdb NUMOSstate+9
|
||||
#define NUMOSdIsDVsb NUMOSstate+10
|
||||
#define NUMOSdIsDVgb NUMOSstate+11
|
||||
#define NUMOSdIgDVdb NUMOSstate+12
|
||||
#define NUMOSdIgDVsb NUMOSstate+13
|
||||
#define NUMOSdIgDVgb NUMOSstate+14
|
||||
#define NUMOSnumStates 15
|
||||
|
||||
int NUMOSdrainNode; /* number of drain node of MOSFET */
|
||||
int NUMOSgateNode; /* number of gate node of MOSFET */
|
||||
int NUMOSsourceNode; /* number of source node of MOSFET */
|
||||
int NUMOSbulkNode; /* number of bulk node of MOSFET */
|
||||
double NUMOSarea; /* area factor for the mosfet */
|
||||
double NUMOSwidth; /* width factor for the mosfet */
|
||||
double NUMOSlength; /* length factor for the mosfet */
|
||||
TWOdevice *NUMOSpDevice;
|
||||
int NUMOStype;
|
||||
double NUMOStemp; /* Instance Temperature */
|
||||
double NUMOSc11; /* small-signal capacitance */
|
||||
double NUMOSy11r; /* small-signal admittance, real part */
|
||||
double NUMOSy11i; /* small-signal admittance, imag part */
|
||||
double NUMOSc12; /* small-signal capacitance */
|
||||
double NUMOSy12r; /* small-signal admittance, real part */
|
||||
double NUMOSy12i; /* small-signal admittance, imag part */
|
||||
double NUMOSc13; /* small-signal capacitance */
|
||||
double NUMOSy13r; /* small-signal admittance, real part */
|
||||
double NUMOSy13i; /* small-signal admittance, imag part */
|
||||
double NUMOSc21; /* small-signal capacitance */
|
||||
double NUMOSy21r; /* small-signal admittance, real part */
|
||||
double NUMOSy21i; /* small-signal admittance, imag part */
|
||||
double NUMOSc22; /* small-signal capacitance */
|
||||
double NUMOSy22r; /* small-signal admittance, real part */
|
||||
double NUMOSy22i; /* small-signal admittance, imag part */
|
||||
double NUMOSc23; /* small-signal capacitance */
|
||||
double NUMOSy23r; /* small-signal admittance, real part */
|
||||
double NUMOSy23i; /* small-signal admittance, imag part */
|
||||
double NUMOSc31; /* small-signal capacitance */
|
||||
double NUMOSy31r; /* small-signal admittance, real part */
|
||||
double NUMOSy31i; /* small-signal admittance, imag part */
|
||||
double NUMOSc32; /* small-signal capacitance */
|
||||
double NUMOSy32r; /* small-signal admittance, real part */
|
||||
double NUMOSy32i; /* small-signal admittance, imag part */
|
||||
double NUMOSc33; /* small-signal capacitance */
|
||||
double NUMOSy33r; /* small-signal admittance, real part */
|
||||
double NUMOSy33i; /* small-signal admittance, imag part */
|
||||
GLOBvalues NUMOSglobals; /* Temp.-Dep. Global Parameters */
|
||||
int NUMOSprint; /* print timepoints */
|
||||
char *NUMOSicFile; /* Name of initial condition file */
|
||||
double *NUMOSdrainDrainPtr; /* pointer to sparse matrix at (drain,drain) */
|
||||
double *NUMOSdrainSourcePtr; /* pointer to sparse matrix at (drain,source) */
|
||||
double *NUMOSdrainGatePtr; /* pointer to sparse matrix at (drain,gate) */
|
||||
double *NUMOSdrainBulkPtr; /* pointer to sparse matrix at (drain,bulk) */
|
||||
double *NUMOSsourceDrainPtr; /* pointer to sparse matrix at (source,drain) */
|
||||
double *NUMOSsourceSourcePtr; /* pointer to sparse matrix at
|
||||
* (source,source) */
|
||||
double *NUMOSsourceGatePtr; /* pointer to sparse matrix at (source,gate) */
|
||||
double *NUMOSsourceBulkPtr; /* pointer to sparse matrix at (source,bulk) */
|
||||
double *NUMOSgateDrainPtr; /* pointer to sparse matrix at (gate,drain) */
|
||||
double *NUMOSgateSourcePtr; /* pointer to sparse matrix at (gate,source) */
|
||||
double *NUMOSgateGatePtr; /* pointer to sparse matrix at (gate,gate) */
|
||||
double *NUMOSgateBulkPtr; /* pointer to sparse matrix at (gate,bulk) */
|
||||
double *NUMOSbulkDrainPtr; /* pointer to sparse matrix at (bulk,drain) */
|
||||
double *NUMOSbulkSourcePtr; /* pointer to sparse matrix at (bulk,source) */
|
||||
double *NUMOSbulkGatePtr; /* pointer to sparse matrix at (bulk,gate) */
|
||||
double *NUMOSbulkBulkPtr; /* pointer to sparse matrix at (bulk,bulk) */
|
||||
|
||||
int NUMOSoff; /* 'off' flag for mosfet */
|
||||
unsigned NUMOSsmSigAvail:1; /* flag to indicate small-signal done */
|
||||
unsigned NUMOSareaGiven:1; /* flag to indicate area was specified */
|
||||
unsigned NUMOSwidthGiven:1; /* flag to indicate width was specified */
|
||||
unsigned NUMOSlengthGiven:1; /* flag to indicate length was specified */
|
||||
unsigned NUMOSicFileGiven:1; /* flag to indicate init. cond. file given */
|
||||
unsigned NUMOSprintGiven:1; /* flag to indicate print was given */
|
||||
unsigned NUMOStempGiven:1; /* flag to indicate temp was given */
|
||||
} NUMOSinstance;
|
||||
|
||||
/* per model data */
|
||||
typedef struct sNUMOSmodel { /* model structure for a numerical device */
|
||||
int NUMOSmodType; /* type index of this device type */
|
||||
struct sNUMOSmodel *NUMOSnextModel; /* pointer to next model in list */
|
||||
NUMOSinstance *NUMOSinstances;/* pointer to list of instances */
|
||||
IFuid NUMOSmodName; /* pointer to string naming this model */
|
||||
/* Everything below here is numerical-device-specific */
|
||||
MESHcard *NUMOSxMeshes; /* list of xmesh cards */
|
||||
MESHcard *NUMOSyMeshes; /* list of ymesh cards */
|
||||
DOMNcard *NUMOSdomains; /* list of domain cards */
|
||||
BDRYcard *NUMOSboundaries; /* list of boundary cards */
|
||||
DOPcard *NUMOSdopings; /* list of doping cards */
|
||||
ELCTcard *NUMOSelectrodes; /* list of electrode cards */
|
||||
CONTcard *NUMOScontacts; /* list of contact cards */
|
||||
MODLcard *NUMOSmodels; /* list of model cards */
|
||||
MATLcard *NUMOSmaterials; /* list of material cards */
|
||||
MOBcard *NUMOSmobility; /* list of mobility cards */
|
||||
METHcard *NUMOSmethods; /* list of method cards */
|
||||
OPTNcard *NUMOSoptions; /* list of option cards */
|
||||
OUTPcard *NUMOSoutputs; /* list of output cards */
|
||||
TWOtranInfo *NUMOSpInfo; /* transient analysis information */
|
||||
DOPprofile *NUMOSprofiles; /* expanded list of doping profiles */
|
||||
DOPtable *NUMOSdopTables; /* list of tables used by profiles */
|
||||
TWOmaterial *NUMOSmatlInfo; /* list of material info structures */
|
||||
} NUMOSmodel;
|
||||
|
||||
/* type of 2D MOSFET */
|
||||
#define N_CH 1
|
||||
#define P_CH -1
|
||||
|
||||
/* device parameters */
|
||||
#define NUMOS_AREA 1
|
||||
#define NUMOS_WIDTH 2
|
||||
#define NUMOS_LENGTH 3
|
||||
#define NUMOS_OFF 4
|
||||
#define NUMOS_IC_FILE 5
|
||||
#define NUMOS_PRINT 9
|
||||
#define NUMOS_TEMP 10
|
||||
|
||||
#define NUMOS_G11 11
|
||||
#define NUMOS_C11 12
|
||||
#define NUMOS_Y11 13
|
||||
#define NUMOS_G12 14
|
||||
#define NUMOS_C12 15
|
||||
#define NUMOS_Y12 16
|
||||
#define NUMOS_G13 17
|
||||
#define NUMOS_C13 18
|
||||
#define NUMOS_Y13 19
|
||||
#define NUMOS_G14 20
|
||||
#define NUMOS_C14 21
|
||||
#define NUMOS_Y14 22
|
||||
#define NUMOS_G21 23
|
||||
#define NUMOS_C21 24
|
||||
#define NUMOS_Y21 25
|
||||
#define NUMOS_G22 26
|
||||
#define NUMOS_C22 27
|
||||
#define NUMOS_Y22 28
|
||||
#define NUMOS_G23 29
|
||||
#define NUMOS_C23 30
|
||||
#define NUMOS_Y23 31
|
||||
#define NUMOS_G24 32
|
||||
#define NUMOS_C24 33
|
||||
#define NUMOS_Y24 34
|
||||
#define NUMOS_G31 35
|
||||
#define NUMOS_C31 36
|
||||
#define NUMOS_Y31 37
|
||||
#define NUMOS_G32 38
|
||||
#define NUMOS_C32 39
|
||||
#define NUMOS_Y32 40
|
||||
#define NUMOS_G33 41
|
||||
#define NUMOS_C33 42
|
||||
#define NUMOS_Y33 43
|
||||
#define NUMOS_G34 44
|
||||
#define NUMOS_C34 45
|
||||
#define NUMOS_Y34 46
|
||||
#define NUMOS_G41 47
|
||||
#define NUMOS_C41 48
|
||||
#define NUMOS_Y41 49
|
||||
#define NUMOS_G42 50
|
||||
#define NUMOS_C42 51
|
||||
#define NUMOS_Y42 52
|
||||
#define NUMOS_G43 53
|
||||
#define NUMOS_C43 54
|
||||
#define NUMOS_Y43 55
|
||||
#define NUMOS_G44 56
|
||||
#define NUMOS_C44 57
|
||||
#define NUMOS_Y44 58
|
||||
|
||||
/* model parameters */
|
||||
/* NOTE: all true model parameters have been moved to IFcardInfo structures */
|
||||
#define NUMOS_MOD_NUMOS 1
|
||||
|
||||
/* device questions */
|
||||
|
||||
/* model questions */
|
||||
|
||||
#include "numosext.h"
|
||||
|
||||
#endif /* NUMOS_H */
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/**********
|
||||
Copyright 1990 Regents of the University of California. All rights reserved.
|
||||
Author: 1987 Karti Mayaram
|
||||
**********/
|
||||
|
||||
#ifndef NUMOSEXT_H
|
||||
#define NUMOSEXT_H
|
||||
|
||||
|
||||
extern int NUMOSacLoad(GENmodel *, CKTcircuit *);
|
||||
extern int NUMOSask(CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *);
|
||||
extern int NUMOSdelete(GENmodel *, IFuid, GENinstance **);
|
||||
extern void NUMOSdestroy(GENmodel **);
|
||||
extern int NUMOSgetic(GENmodel *, CKTcircuit *);
|
||||
extern int NUMOSload(GENmodel *, CKTcircuit *);
|
||||
extern int NUMOSmDelete(GENmodel **, IFuid, GENmodel *);
|
||||
extern int NUMOSmParam(int, IFvalue *, GENmodel *);
|
||||
extern int NUMOSparam(int, IFvalue *, GENinstance *, IFvalue *);
|
||||
extern int NUMOSpzLoad(GENmodel *, CKTcircuit *, SPcomplex *);
|
||||
extern int NUMOSsetup(SMPmatrix *, GENmodel *, CKTcircuit *, int *);
|
||||
extern int NUMOStemp(GENmodel *, CKTcircuit *);
|
||||
extern int NUMOStrunc(GENmodel *, CKTcircuit *, double *);
|
||||
|
||||
extern void NUMOSdump(GENmodel *, CKTcircuit *);
|
||||
extern void NUMOSacct(GENmodel *, CKTcircuit *, FILE *);
|
||||
|
||||
#endif /* NUMOSEXT_H */
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
#include <config.h>
|
||||
|
||||
#include <devdefs.h>
|
||||
|
||||
#include "numositf.h"
|
||||
#include "numosext.h"
|
||||
#include "numosinit.h"
|
||||
|
||||
|
||||
SPICEdev NUMOSinfo = {
|
||||
{
|
||||
"NUMOS",
|
||||
"2D Numerical MOS Field Effect Transistor model",
|
||||
|
||||
&NUMOSnSize,
|
||||
&NUMOSnSize,
|
||||
NUMOSnames,
|
||||
|
||||
&NUMOSpTSize,
|
||||
NUMOSpTable,
|
||||
|
||||
&NUMOSmPTSize,
|
||||
NUMOSmPTable,
|
||||
|
||||
#ifdef XSPICE
|
||||
/*---- Fixed by SDB 5.2.2003 to enable XSPICE/tclspice integration -----*/
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
|
||||
0, /* This is a SPICE device, it has no MIF info data */
|
||||
NULL, /* This is a SPICE device, it has no MIF info data */
|
||||
/*--------------------------- End of SDB fix -------------------------*/
|
||||
#endif
|
||||
|
||||
DEV_DEFAULT
|
||||
},
|
||||
|
||||
DEVparam : NUMOSparam,
|
||||
DEVmodParam : NUMOSmParam,
|
||||
DEVload : NUMOSload,
|
||||
DEVsetup : NUMOSsetup,
|
||||
DEVunsetup : NULL,
|
||||
DEVpzSetup : NUMOSsetup,
|
||||
DEVtemperature: NUMOStemp,
|
||||
DEVtrunc : NUMOStrunc,
|
||||
DEVfindBranch : NULL,
|
||||
DEVacLoad : NUMOSacLoad,
|
||||
DEVaccept : NULL,
|
||||
DEVdestroy : NUMOSdestroy,
|
||||
DEVmodDelete : NUMOSmDelete,
|
||||
DEVdelete : NUMOSdelete,
|
||||
DEVsetic : NULL,
|
||||
DEVask : NUMOSask,
|
||||
DEVmodAsk : NULL,
|
||||
DEVpzLoad : NUMOSpzLoad,
|
||||
DEVconvTest : NULL,
|
||||
DEVsenSetup : NULL,
|
||||
DEVsenLoad : NULL,
|
||||
DEVsenUpdate : NULL,
|
||||
DEVsenAcLoad : NULL,
|
||||
DEVsenPrint : NULL,
|
||||
DEVsenTrunc : NULL,
|
||||
DEVdisto : NULL,
|
||||
DEVnoise : NULL,
|
||||
DEVdump : NUMOSdump,
|
||||
DEVacct : NUMOSacct,
|
||||
|
||||
DEVinstSize : &NUMOSiSize,
|
||||
DEVmodSize : &NUMOSmSize
|
||||
|
||||
};
|
||||
|
||||
|
||||
SPICEdev *
|
||||
get_numos_info(void)
|
||||
{
|
||||
return &NUMOSinfo;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef _NUMOSINIT_H
|
||||
#define _NUMOSINIT_H
|
||||
|
||||
extern IFparm NUMOSpTable[ ];
|
||||
extern IFparm NUMOSmPTable[ ];
|
||||
extern char *NUMOSnames[ ];
|
||||
extern int NUMOSpTSize;
|
||||
extern int NUMOSmPTSize;
|
||||
extern int NUMOSnSize;
|
||||
extern int NUMOSiSize;
|
||||
extern int NUMOSmSize;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
/**********
|
||||
Copyright 1991 Regents of the University of California. All rights reserved.
|
||||
**********/
|
||||
|
||||
#ifndef DEV_NUMOS
|
||||
#define DEV_NUMOS
|
||||
|
||||
extern SPICEdev *get_numos_info(void);
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue