Cider simulator (numerical devices) Import.

This commit is contained in:
pnenzi 2003-08-11 19:35:20 +00:00
parent f5f8602d3a
commit 89317d34e8
100 changed files with 10551 additions and 0 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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 */
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}
}
}
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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 */
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}
}
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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 */
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}
}
}
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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 */
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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 */
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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

View File

@ -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